jig-ui 0.7.1 → 0.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +822 -0
- package/README.md +107 -23
- package/dist/index.js +300 -15
- package/package.json +3 -2
- package/rules/00-anti-patterns.md +24 -14
- package/rules/01-modes.md +0 -14
- package/rules/02-tokens.md +80 -5
- package/rules/03-patterns.md +0 -14
- package/rules/04-principles.md +0 -14
- package/rules/05-copy.md +0 -10
- package/rules.index.json +12 -9
- package/templates/SKILL.md.tmpl +24 -1
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,822 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.8.1
|
|
4
|
+
|
|
5
|
+
Both fixes here are the same shape: 0.8.0 corrected the instance it was looking
|
|
6
|
+
at and left the class alone, and in each case the commit message claimed a
|
|
7
|
+
verification that had only checked the file it had just edited. Both were found
|
|
8
|
+
by inspecting the published tarball rather than the working tree.
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- **Four rule files still shipped author notes.** 0.7.x removed the section
|
|
13
|
+
headed "Notes for the author (not for the agent)" from `00-anti-patterns.md`
|
|
14
|
+
after an agent read it as "license to go tighter than the shared default" and
|
|
15
|
+
halved the radius scale on that authority. `01-modes.md`, `03-patterns.md`,
|
|
16
|
+
`04-principles.md` and `05-copy.md` carried a section under the same heading
|
|
17
|
+
and kept shipping it to every agent that installed Jig.
|
|
18
|
+
|
|
19
|
+
`01-modes.md` was the worst of them: it told the reader to **"Change them in
|
|
20
|
+
`tokens/mode.*.css`"** and closed with **"it is your call"** — an invitation
|
|
21
|
+
to edit the token layer, which is the one thing Jig's architecture reserves
|
|
22
|
+
for a human. `03-patterns.md` described navigation and cards as "deliberately
|
|
23
|
+
absent… add them once you have built enough". `05-copy.md` pointed at
|
|
24
|
+
`03-brand.md`, which does not exist. The content moves to
|
|
25
|
+
`docs/house-positions.md` unchanged; only its audience changes.
|
|
26
|
+
|
|
27
|
+
- **`02-tokens.md` contradicted its own Tailwind fix 352 lines earlier.** The
|
|
28
|
+
compatibility table near the top still read *"Tailwind v4 | Wrap in
|
|
29
|
+
`@theme { }`"* — the exact instruction the section below it retracts with
|
|
30
|
+
*"Earlier versions of this file told you to, and Tailwind rejects it
|
|
31
|
+
outright."* The table is the part an agent reads first, so the correction
|
|
32
|
+
shipped underneath the error it corrected. A second, softer restatement
|
|
33
|
+
("the same file can be wrapped in `@theme`") is gone too. `@theme` now first
|
|
34
|
+
appears in the section that explains it correctly.
|
|
35
|
+
|
|
36
|
+
- **`jig explain` rendered a dangling `---` in 14 of the 15 pattern and mode
|
|
37
|
+
specs.** `parse.ts` has always dropped bare separator lines; `specs.ts` is a
|
|
38
|
+
separate code path and never did, so every `P-` and `M-` spec that is
|
|
39
|
+
followed by a separator in the source carried it into the rendered body,
|
|
40
|
+
between the last paragraph and the footer. Spotted on `P-12`, but it was
|
|
41
|
+
never about `P-12`. Table separators (`| --- |`) are untouched.
|
|
42
|
+
|
|
43
|
+
- **`jig init`'s refusal without a terminal offered a way out that does not
|
|
44
|
+
work.** The message ended *"(To choose the mode without a terminal, write
|
|
45
|
+
jig.config.json first — init honours it.)"* The guard runs before any config
|
|
46
|
+
is read, so a config alone still exits 1. The sentence was true about mode
|
|
47
|
+
selection and false in a paragraph about not having a terminal, so it read as
|
|
48
|
+
a third alternative when it is a modifier on the first — a cold agent
|
|
49
|
+
followed it literally, hit the identical error, and allocated a
|
|
50
|
+
pseudo-terminal with Python's `pty` to get past it. It now says a config does
|
|
51
|
+
not replace `--yes`, and what the two do together. Nothing covered this path;
|
|
52
|
+
three tests now do.
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
|
|
56
|
+
- **`check-tokens` rule 13 — no shipped rule file addresses the author.** The
|
|
57
|
+
guard that should have existed for the 0.7.x fix. It reads `rules/` from disk
|
|
58
|
+
rather than a hardcoded list, so a rule file added later cannot escape it the
|
|
59
|
+
way those four did, and it checks the second-person tells ("your taste", "it
|
|
60
|
+
is your call", "my inclination is") as well as the heading, because a rename
|
|
61
|
+
would otherwise defeat it. Each tell is verified to fire on reintroduction.
|
|
62
|
+
|
|
63
|
+
## 0.8.0
|
|
64
|
+
|
|
65
|
+
Everything here was found by handing Jig to agents that had never seen it and
|
|
66
|
+
asking them to build something real — its own documentation site. None of it
|
|
67
|
+
was found by the test suite, which passed throughout.
|
|
68
|
+
|
|
69
|
+
Minor rather than patch: `explain` prints lines it did not print before, and
|
|
70
|
+
`init` can write a file it did not write before.
|
|
71
|
+
|
|
72
|
+
### Fixed
|
|
73
|
+
|
|
74
|
+
- **`jig explain` discarded most of the reasoning in the rules.** The parser
|
|
75
|
+
kept the first `❌` and the first `✅` and threw away everything else. **41 of
|
|
76
|
+
104 rules carry prose outside that pair — 103 lines.** `A-04` explains why
|
|
77
|
+
shadow-only definition cannot hold 3:1; `C-22` loses sixteen lines; `C-49`
|
|
78
|
+
leads with a three-row table distinguishing when a link needs colour, when it
|
|
79
|
+
needs an underline, and when neither is required — and its pair alone says
|
|
80
|
+
"keep the underline". All of it shipped in the tarball, installed into every
|
|
81
|
+
skill directory, and was unreachable through the command built to read it.
|
|
82
|
+
|
|
83
|
+
- **`02-tokens.md` documented a Tailwind arrangement that fails.** It told every
|
|
84
|
+
reader to write `@theme { @import "./jig/theme.css"; }` and claimed it yields
|
|
85
|
+
`bg-surface`, `rounded-surface`, `p-card` and `text-body` as utilities.
|
|
86
|
+
Tailwind 4 rejects it: *"@theme blocks must only contain custom properties or
|
|
87
|
+
@keyframes."* The tokens cannot move into `@theme` regardless — it requires
|
|
88
|
+
them top-level and unnested, while they live in `:root` and are redeclared
|
|
89
|
+
under `[data-theme="dark"]` and a `prefers-color-scheme` query, which is what
|
|
90
|
+
makes dark mode work. The flat import is what works, and is what `init`
|
|
91
|
+
already wired without being told.
|
|
92
|
+
|
|
93
|
+
- **`02-tokens.md` named a token location the tool had stopped using.** It said
|
|
94
|
+
tokens live at `.jig/tokens/`, that this was "the only location, in every
|
|
95
|
+
scope and every project", and that "nothing relocates them" — while `init`
|
|
96
|
+
printed `Token layer: src/styles/jig/` in the same run. `check-tokens` rule 4
|
|
97
|
+
hardcoded the same path in a comment anticipating and forbidding this exact
|
|
98
|
+
change, so the guard held the claim in place and would have failed the build
|
|
99
|
+
on anyone correcting it. Shipped in 0.7.1.
|
|
100
|
+
|
|
101
|
+
- **A section headed "Notes for the author (not for the agent)" shipped to every
|
|
102
|
+
agent.** The heading was a label, not a mechanism: the file is in the tarball
|
|
103
|
+
and installs into every skill directory. A probe read it, quoted the
|
|
104
|
+
`A-07`/`A-08` line back as "the author's own notes… license to go tighter than
|
|
105
|
+
the shared default", and halved the radius scale on that authority. Moved to
|
|
106
|
+
`docs/house-positions.md`.
|
|
107
|
+
|
|
108
|
+
- **The published package shipped no changelog**, despite the repo holding 32KB
|
|
109
|
+
of one. Staging and `files` now change together, which the tarball guard
|
|
110
|
+
already enforced.
|
|
111
|
+
|
|
112
|
+
- **`A-01` had no stated scope for "then ask".** Two agents given the same brief
|
|
113
|
+
split on it — one shipped the unbranded default and deferred, the other
|
|
114
|
+
proposed a hue and argued the proposal *was* the ask — both citing the same
|
|
115
|
+
conflict-resolution clause. The rule now says a proposal is a question with a
|
|
116
|
+
suggested answer, not a decision.
|
|
117
|
+
|
|
118
|
+
- **`B-11` capped line length and stated no floor**, so a column could be halved
|
|
119
|
+
indefinitely and still pass. Measured on the documentation site: two
|
|
120
|
+
side-by-side panels rendering prose at 41 characters, in a mode whose
|
|
121
|
+
`--measure-prose` selects 68. The 40–80 band existed in `02-tokens.md` but not
|
|
122
|
+
in the file an agent reads for a line-length decision.
|
|
123
|
+
|
|
124
|
+
### Added
|
|
125
|
+
|
|
126
|
+
- **Three detectors for the anti-slop rules, and a self-check that names them.**
|
|
127
|
+
Section A is Jig's answer to "what is AI slop" — fourteen rules for the
|
|
128
|
+
defaults a model reaches for when nothing was specified. **Three had
|
|
129
|
+
detectors.** The other eleven were enforced by one self-check question —
|
|
130
|
+
*"would this look different from a generic template?"* — which an agent that
|
|
131
|
+
has just produced a generic template answers yes to, and whose `A-01 → A-10`
|
|
132
|
+
range silently excluded `A-58`, `A-59`, `A-60` and `A-67`.
|
|
133
|
+
|
|
134
|
+
Jig's own documentation site shipped `<span aria-hidden="true">❌</span> Don't`
|
|
135
|
+
in the chrome of all 104 rule pages with `check --all` reporting nothing.
|
|
136
|
+
|
|
137
|
+
`A-05` (emoji as iconography) and `A-10` (placeholder content) were never
|
|
138
|
+
judgment calls — an emoji in a text node is a regex, and so is "lorem ipsum".
|
|
139
|
+
`A-09` (marketing voice) is the first **mode-gated** detector: it fires in
|
|
140
|
+
`product` and `operator`, stays silent in `editorial` where that register
|
|
141
|
+
belongs, and stays silent when no mode is declared rather than guessing.
|
|
142
|
+
|
|
143
|
+
The remaining eight stay judgment. Detecting "a container around every group"
|
|
144
|
+
needs to know what an element is and how heavy it looks, and six noisy checks
|
|
145
|
+
that fire on correct code is how a linter gets switched off. What reaches them
|
|
146
|
+
is the self-check, rewritten to name each tell the way every other item does.
|
|
147
|
+
|
|
148
|
+
- **`check` reports what it examined.** `0 errors · 104 rules, 0 fired` was
|
|
149
|
+
byte-identical whether forty components were examined and found clean or
|
|
150
|
+
nothing was examined at all. It now reads `· 26 files, 4 with styles`, the
|
|
151
|
+
`JIG_CHECK:` record carries `files=` and `styled=`, and a run where nothing
|
|
152
|
+
carried a style region says **"Nothing inspected."** rather than "No
|
|
153
|
+
findings." Both counts, because `.ts` and `.tsx` are style-bearing by
|
|
154
|
+
extension and the file count includes parsers and configs that can never
|
|
155
|
+
produce a finding.
|
|
156
|
+
|
|
157
|
+
Worth knowing: `check` defaults to changed files, so on a clean tree it scans
|
|
158
|
+
almost nothing. That was always true and always looked like a pass.
|
|
159
|
+
|
|
160
|
+
- **`init` offers a Tailwind v4 alias block.** The flat import gives you tokens,
|
|
161
|
+
not utility classes — Tailwind only generates those for names declared in
|
|
162
|
+
`@theme`. `init` can now generate that block, and **asks first**: it changes
|
|
163
|
+
how every component in a project is written, both styles are correct, and
|
|
164
|
+
silence is no. Under `--yes` it declines and says how to get it.
|
|
165
|
+
|
|
166
|
+
Only the 18 Tailwind namespaces are aliased. `--size-*`, `--measure-*`,
|
|
167
|
+
`--focus-ring-*`, `--border-width-*` and `--opacity-*` have none, and aliasing
|
|
168
|
+
one emits a declaration that generates nothing. 189 declared names filter to
|
|
169
|
+
87 — and the filter also excludes every primitive `02-tokens.md` says never to
|
|
170
|
+
consume directly.
|
|
171
|
+
|
|
172
|
+
The generated file explains why `--radius-surface: var(--radius-surface)`
|
|
173
|
+
appears beside Jig's own declaration in the compiled CSS: Tailwind's lands in
|
|
174
|
+
`@layer theme`, Jig's is unlayered, and unlayered beats layered regardless of
|
|
175
|
+
source order. Without that note, someone finds it and "fixes" it.
|
|
176
|
+
|
|
177
|
+
- **The skill treats Tailwind setup as an ask.** Finding Tailwind in a project
|
|
178
|
+
is not permission to change how every component in it is written. The agent
|
|
179
|
+
reports what it found, shows both arrangements, and waits — and is told never
|
|
180
|
+
to write `@import "tailwindcss"` into a project that does not already have it.
|
|
181
|
+
|
|
182
|
+
- **A guard that staged assets stay out of git.** Adding `CHANGELOG.md` to the
|
|
183
|
+
prepack staging list committed a build artifact, because
|
|
184
|
+
`packages/cli/.gitignore` is a hand-maintained list that nothing forced into
|
|
185
|
+
step. On its first run the new guard caught a second, pre-existing hole:
|
|
186
|
+
`references` had been staged and unignored since it was added, saved only by
|
|
187
|
+
the directory not existing yet.
|
|
188
|
+
|
|
189
|
+
### Corrected
|
|
190
|
+
|
|
191
|
+
- **0.7.0's notes said the non-TTY refusal "names the three ways out".** It
|
|
192
|
+
names three; two work. The guard runs before any config is read, so
|
|
193
|
+
`jig.config.json` alone still exits 1 — it selects the mode once you are past
|
|
194
|
+
the guard, it does not get you past it. The message is unchanged here and
|
|
195
|
+
recorded in `docs/known-follow-ups.md`, because the right wording depends on
|
|
196
|
+
whether the guard should consult the config first, which is a behaviour
|
|
197
|
+
question rather than a copy one.
|
|
198
|
+
|
|
199
|
+
## 0.7.1
|
|
200
|
+
|
|
201
|
+
A rule file that contradicted the tool, and the guard that kept it that way.
|
|
202
|
+
|
|
203
|
+
Patch: the shipped rules change, but no command writes anything different.
|
|
204
|
+
|
|
205
|
+
### Fixed
|
|
206
|
+
|
|
207
|
+
- **`02-tokens.md` named a token location that 0.7.0 stopped using.** It said
|
|
208
|
+
tokens live at `.jig/tokens/`, that this was "the only location, in every
|
|
209
|
+
scope and every project", and that "nothing relocates them". Since 0.7.0 the
|
|
210
|
+
layer follows the project: `init` puts it beside the stylesheet it wires and
|
|
211
|
+
prints the path it chose. So a single `init` run told you `Token layer:
|
|
212
|
+
src/styles/jig/` while the rule file an agent is explicitly told to load
|
|
213
|
+
before writing token code insisted that directory could not exist.
|
|
214
|
+
|
|
215
|
+
The file also disagreed with itself — four absolute examples, and one
|
|
216
|
+
relative one added when the Tailwind section was written.
|
|
217
|
+
|
|
218
|
+
It now describes the real behaviour, says pre-0.7.0 projects keep their
|
|
219
|
+
layout, and points at the `theme.css` barrel so relocating the layer costs
|
|
220
|
+
one line instead of every stylesheet.
|
|
221
|
+
|
|
222
|
+
- **`check-tokens` rule 4 was holding the claim in place.** It hardcoded the
|
|
223
|
+
same path, in a comment that anticipated and forbade this exact change:
|
|
224
|
+
"nothing — including a future `init` — relocates them". It was checking the
|
|
225
|
+
documentation against itself rather than against the CLI, so it could not
|
|
226
|
+
see the drift and would have failed the build on anyone correcting it.
|
|
227
|
+
|
|
228
|
+
It now asserts what stays true as the layer moves: token imports shown in
|
|
229
|
+
the rules must be relative. Mutation-tested in both directions.
|
|
230
|
+
|
|
231
|
+
### Corrected
|
|
232
|
+
|
|
233
|
+
- **0.7.0's notes said the non-TTY refusal "names the three ways out:
|
|
234
|
+
`--yes`, a real terminal, or writing `jig.config.json` first."** The third
|
|
235
|
+
is not a way out on its own. The guard runs before any config is read, so a
|
|
236
|
+
config alone changes nothing — it selects the *mode* once you are past the
|
|
237
|
+
guard. `jig.config.json` plus `--yes` works; `jig.config.json` alone exits 1
|
|
238
|
+
with the same message that suggested it.
|
|
239
|
+
|
|
240
|
+
The message itself is unchanged in this release and still reads as though
|
|
241
|
+
the config were a third alternative. It is recorded in
|
|
242
|
+
`docs/known-follow-ups.md` rather than reworded here, because the wording
|
|
243
|
+
that is actually right depends on whether the guard should consult the
|
|
244
|
+
config first — a behaviour question, not a copy question.
|
|
245
|
+
|
|
246
|
+
### How these were found
|
|
247
|
+
|
|
248
|
+
Not by the test suite, which passes 631 tests either way. By handing the rules
|
|
249
|
+
to agents that had never seen this repository and asking them to build
|
|
250
|
+
something real. Everyone who could have caught the token-location defect
|
|
251
|
+
already knew where the tokens were.
|
|
252
|
+
|
|
253
|
+
## 0.7.0
|
|
254
|
+
|
|
255
|
+
A silent no-op, fixed, plus the missing half of 0.6.0's token-layer move.
|
|
256
|
+
|
|
257
|
+
Minor rather than patch, and the call is arguable. The non-TTY fix is a
|
|
258
|
+
correction; the relocation offer is new behaviour that can move files, though
|
|
259
|
+
only interactively and only with consent. Taking the higher of the two is the
|
|
260
|
+
reading that does not understate the change, and anyone who might be prompted
|
|
261
|
+
to move their token layer should read these notes.
|
|
262
|
+
|
|
263
|
+
### Fixed
|
|
264
|
+
|
|
265
|
+
- **`jig init` without `--yes` exited 0 having written nothing when stdin was
|
|
266
|
+
not a terminal.** It printed the first prompt, read EOF, and stopped. Every CI
|
|
267
|
+
step, every piped invocation, and every agent shelling out without a TTY got a
|
|
268
|
+
silent no-op — and exit 0 having done nothing is the worst outcome available,
|
|
269
|
+
because the caller cannot tell it from success and then acts on a token layer
|
|
270
|
+
that was never created. Confirmed identical in 0.5.0, so this predates the
|
|
271
|
+
prompts added since. It now fails where the cause is still visible and names
|
|
272
|
+
the three ways out: `--yes`, a real terminal, or writing `jig.config.json`
|
|
273
|
+
first.
|
|
274
|
+
|
|
275
|
+
### Added
|
|
276
|
+
|
|
277
|
+
- **`init` offers to move a legacy `.jig/tokens/` layout** to the location your
|
|
278
|
+
project's own structure suggests. 0.6.0 deliberately left an upgraded project
|
|
279
|
+
where it was — a silent relocation could break an import you wrote that `init`
|
|
280
|
+
knows nothing about — but that meant the improvement only ever reached new
|
|
281
|
+
projects, and the way out was one line of output that is easy to miss.
|
|
282
|
+
|
|
283
|
+
Interactively it asks; under `--yes` it declines and says how. Moving is all
|
|
284
|
+
four halves or none: write at the new location, remove the old copies, strip
|
|
285
|
+
the stale import before wiring the new one, and update `jig.config.json` so
|
|
286
|
+
the next run does not go back for them. A file you have edited is never
|
|
287
|
+
removed — it is named and left for you to clear.
|
|
288
|
+
|
|
289
|
+
```text
|
|
290
|
+
BEFORE @import "../../.jig/tokens/brand.acme.css";
|
|
291
|
+
@import "../../.jig/tokens/mode.product.css";
|
|
292
|
+
AFTER @import "./jig/theme.css";
|
|
293
|
+
```
|
|
294
|
+
|
|
295
|
+
## 0.6.0
|
|
296
|
+
|
|
297
|
+
The token layer stops hiding in a dotfolder, and `check` starts reading it back.
|
|
298
|
+
|
|
299
|
+
Both came from the same question: who should write the tokens. The answer turned
|
|
300
|
+
out to depend on something that did not exist — **nothing validated the token
|
|
301
|
+
layer's own declarations.** `init` checked a brand colour once, at write time,
|
|
302
|
+
and no command ever looked again. A generated file edited afterwards, by a person
|
|
303
|
+
or an agent, went unexamined: `--color-text-weak` dropped to 22% opacity and
|
|
304
|
+
`check` reported "No findings". With that closed, where the files live and who
|
|
305
|
+
writes them become ordinary decisions rather than load-bearing ones.
|
|
306
|
+
|
|
307
|
+
**Upgrading:** run `npx jig-ui@latest update`, then `npx jig-ui@latest init`.
|
|
308
|
+
Existing installs keep their `.jig/tokens/` layout — nothing moves unless you
|
|
309
|
+
move it, because relocating files could break an import you wrote yourself.
|
|
310
|
+
|
|
311
|
+
### Added
|
|
312
|
+
|
|
313
|
+
- **`check` validates the token layer** (`check/token-audit.ts`). Text roles to
|
|
314
|
+
4.5:1, interface strokes to 3:1, **in both themes**, plus `--text-prose` at
|
|
315
|
+
18px and `--size-touch-target` at 48px. Alpha foregrounds are composited over
|
|
316
|
+
each surface first — Jig's foregrounds are alpha by design, so a ratio before
|
|
317
|
+
compositing means nothing. Only floors, never density: `--size-control` at 28px
|
|
318
|
+
is a deliberate `operator` choice, and reporting it would teach you to ignore
|
|
319
|
+
the ones that matter.
|
|
320
|
+
- **`H-47` enforces the half of itself it only stated.** Its correction always
|
|
321
|
+
read "consume the semantic role, not the primitive"; the detector caught raw
|
|
322
|
+
hex and raw px and nothing else. `color: var(--brand-l)` was silent — and it is
|
|
323
|
+
the worse case, because it looks exactly like correct token usage while reading
|
|
324
|
+
a bare number and bypassing every theme override.
|
|
325
|
+
- **`exempt` in `jig.config.json`.** Some surfaces render outside the cascade: an
|
|
326
|
+
OG card in an SVG `foreignObject` carries no stylesheet, a PDF renderer never
|
|
327
|
+
sees CSS. Those files were in permanent violation, which is an adoption blocker
|
|
328
|
+
— a check that cannot pass is a check people switch off.
|
|
329
|
+
|
|
330
|
+
Nothing is exempt by default and no filename is baked in; this list is the only
|
|
331
|
+
source. Every run reports the **pattern** and what it excused, because an
|
|
332
|
+
over-broad glob does not fail — `check` simply gets quieter, and quieter looks
|
|
333
|
+
like progress:
|
|
334
|
+
|
|
335
|
+
```text
|
|
336
|
+
5 file(s) exempt via jig.config.json and not scanned:
|
|
337
|
+
src/*-card.css (5 files — likely too broad, review it)
|
|
338
|
+
src/nope.css (matches nothing — check the path)
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
Prefer an exact path. An exemption is a claim about one file's rendering
|
|
342
|
+
context, and that is usually literally true of one file. `src/cv/pdf/**` is a
|
|
343
|
+
fact about a tree; `**/*-card.tsx` is a naming coincidence that would also
|
|
344
|
+
excuse every real card component in the project.
|
|
345
|
+
- **One import per surface, through a barrel.** `jig/theme.css` imports the brand
|
|
346
|
+
file and one mode file; your stylesheet imports that single line and then never
|
|
347
|
+
changes again. Switching mode rewrites Jig's file, not yours.
|
|
348
|
+
|
|
349
|
+
### Changed
|
|
350
|
+
|
|
351
|
+
- **The token layer follows your project's layout.** `.jig/tokens/` was right
|
|
352
|
+
everywhere by being right nowhere — a tool dotdir holding product source,
|
|
353
|
+
reached from a Rails stylesheet by `@import "../../../.jig/tokens/…"`. The
|
|
354
|
+
default is now a `jig/` directory beside the stylesheet being wired, so the
|
|
355
|
+
import is `./jig/theme.css` in every ecosystem. `jig.config.json`'s `brand`
|
|
356
|
+
now decides placement, not just wiring — it previously honoured the path only
|
|
357
|
+
when the file already existed, which is the one case where it does not matter.
|
|
358
|
+
- **The mode is chosen before `init` runs.** It is the most consequential thing
|
|
359
|
+
`init` writes and the thing it is worst at choosing: `--yes` took `'/' → product`
|
|
360
|
+
without reading the project, and that config then outranks every agent's later
|
|
361
|
+
inference. The command file now tells the agent to ask what the product is, map
|
|
362
|
+
each surface, write the config, and only then run. `init` also reports the
|
|
363
|
+
surfaces it **used** rather than the ones it defaulted to — with a config
|
|
364
|
+
present it had been announcing a default it was about to ignore.
|
|
365
|
+
- A barrel holds exactly one mode, never a merge. Importing all three into one
|
|
366
|
+
document leaves only the last; verified in a browser, it yields `operator`
|
|
367
|
+
throughout. `01-modes.md` already said why that is not a loss: density switches
|
|
368
|
+
at the route boundary, never inside one view.
|
|
369
|
+
|
|
370
|
+
### Fixed
|
|
371
|
+
|
|
372
|
+
- `--text-prose`, `--size-touch-target` and every semantic colour are now held to
|
|
373
|
+
their floors after `init` as well as during it.
|
|
374
|
+
- **`H-47`'s built-in token-layer skip was over-broad.** It matched
|
|
375
|
+
`(brand|mode).*.css` with the directory optional, so a project's own
|
|
376
|
+
`src/legacy/brand.colors.css` was silently exempt from the primitive check
|
|
377
|
+
wherever it sat. Scoped to the token layer's directory now — Jig owns `jig/`
|
|
378
|
+
outright, and a filename that merely looks like one of ours is a coincidence.
|
|
379
|
+
- The token audit follows the token layer instead of reading a fixed directory.
|
|
380
|
+
It was written when `.jig/tokens/` was the only possible answer, so moving the
|
|
381
|
+
layer made it find nothing and report nothing — caught in a pre-release smoke
|
|
382
|
+
test, where a brand file edited to 22% opacity passed cleanly. A check that
|
|
383
|
+
goes quiet when its subject moves is worse than one that was never written,
|
|
384
|
+
because the silence reads as a pass.
|
|
385
|
+
- Tailwind v4 does not scan workspace packages — documented, with the `@source`
|
|
386
|
+
directive it needs. Nothing errors when this bites: the class lands on the
|
|
387
|
+
element, no rule exists to match it, and the style simply does not apply.
|
|
388
|
+
|
|
389
|
+
## 0.5.0
|
|
390
|
+
|
|
391
|
+
Four things shipped in 0.4.0 were broken in ways that reported success. `/jig
|
|
392
|
+
update` refreshed to the version already installed and said "Updated Jig →
|
|
393
|
+
0.4.0". Dark mode could not be reached by choosing it. `check` skipped nearly
|
|
394
|
+
every colour in a project that had not run `init`. And the reconciliation of
|
|
395
|
+
every numeric default against an external reference is finished — 0 rows open —
|
|
396
|
+
which is where most of the rest of this release came from.
|
|
397
|
+
|
|
398
|
+
**If you are on 0.4.0, run `npx jig-ui@latest update` from a terminal.** The
|
|
399
|
+
`/jig update` fix cannot deliver itself: your command file is the broken one, so
|
|
400
|
+
the slash command will keep reporting a successful no-op until the CLI replaces
|
|
401
|
+
it. Once, from the terminal, and the slash command works from then on.
|
|
402
|
+
|
|
403
|
+
### Fixed
|
|
404
|
+
|
|
405
|
+
- **`/jig update` could never upgrade anyone.** Every subcommand is invoked at
|
|
406
|
+
the installed pin so the CLI and the vendored rules agree; `update` is the one
|
|
407
|
+
exception, because its job is to move that pin. The skill file knew that and
|
|
408
|
+
the slash command did not, so it ran `npx jig-ui@<installed> update` — a no-op
|
|
409
|
+
that reports success, which is worse than an error.
|
|
410
|
+
- **Dark mode was unreachable by explicit choice.** `brand.default.css` had one
|
|
411
|
+
dark block, inside `@media (prefers-color-scheme: dark)`. A selector inside a
|
|
412
|
+
media query cannot match when the query is false, so `data-theme="dark"` on a
|
|
413
|
+
light-mode system produced no dark tokens at all. A second, unmediated block
|
|
414
|
+
now carries the same declarations, and a check keeps the two identical.
|
|
415
|
+
- **`check` did not resolve the project's own tokens.** The token map held only
|
|
416
|
+
Jig's vendored `.jig/tokens/*.css`, so any `var(--your-token)` was
|
|
417
|
+
unresolvable and skipped. On a project that had never run `jig init`,
|
|
418
|
+
`contrast-floor` and `violet-band-hue` evaluated very nearly nothing. A name
|
|
419
|
+
declared in two places with different values is still skipped — which value a
|
|
420
|
+
browser uses depends on import order, and a wrong guess reports a finding
|
|
421
|
+
against a value the page never renders.
|
|
422
|
+
- **`operator` prose text was 16px** against the 18px floor `B-75` states and
|
|
423
|
+
`02-tokens.md` repeats. It is the mode most likely to be read for hours.
|
|
424
|
+
- **Rules cited tokens that do not exist** — the `--color-danger` family,
|
|
425
|
+
`--color-surface`, `--leading-heading`, `--leading-display`,
|
|
426
|
+
`--font-weight-body`, `--spacing-unit`. An agent following those wrote a
|
|
427
|
+
`var()` resolving to nothing, with no error anywhere.
|
|
428
|
+
- **`C-19` named the same token twice**, once "for large text only".
|
|
429
|
+
`--color-text-weak` clears 4.5:1 at any size, and there is no lighter grey.
|
|
430
|
+
- **The error message in `P-03` moved above the input**, where autofill menus
|
|
431
|
+
and on-screen keyboards do not cover it.
|
|
432
|
+
- **CSS nesting and line endings.** `install` and `update` had three near-copies
|
|
433
|
+
of one write helper and one had lost its line-ending handling, so `update`
|
|
434
|
+
flattened a CRLF token file to LF while leaving the rule files beside it
|
|
435
|
+
alone. All three now share `install/writer.ts`, and writes are atomic.
|
|
436
|
+
|
|
437
|
+
### Added
|
|
438
|
+
|
|
439
|
+
- **`P-13 · Ambient motion`** — a third category of motion the system lacked.
|
|
440
|
+
Interaction and transition motion are milliseconds; ambient motion is slow,
|
|
441
|
+
looping and decorative, and must never be noticed. `G-44` forbade all of it by
|
|
442
|
+
stating a 300ms ceiling it had never scoped, so an agent asked for a slow
|
|
443
|
+
decorative loop would have refused, citing a rule about something else.
|
|
444
|
+
- **`--duration-ambient-fast/base/slow`** (3s / 4.7s / 7.1s), `editorial` only.
|
|
445
|
+
The values are mutually prime in tenths of a second so layered loops do not
|
|
446
|
+
re-align into one visible pulse.
|
|
447
|
+
- **Fluid headings.** `--text-h1` and `--text-h2` are `clamp()` in `editorial`
|
|
448
|
+
and `product`, reaching their minimum at a 360px viewport and their maximum at
|
|
449
|
+
1024px. Every term is `rem`-based: a `px` or bare-`vw` bound ignores a
|
|
450
|
+
reader's font-size preference, which is a WCAG 1.4.4 failure.
|
|
451
|
+
- **`explain` finds rules you cannot name.** A word searches every title and
|
|
452
|
+
body; one match prints in full. `--list` prints every id, or one section's.
|
|
453
|
+
- **Easing direction** — `--ease-out` on entry, `--ease-in-out` on exit, never
|
|
454
|
+
linear for anything that moves. Both tokens shipped with no rule for choosing.
|
|
455
|
+
|
|
456
|
+
### Changed
|
|
457
|
+
|
|
458
|
+
- **`--text-h1` resolves to 32px on a phone**, not 48px. This is the change most
|
|
459
|
+
likely to be visible in an existing project, and it is the point: at a fixed
|
|
460
|
+
48px, a 45-character headline set as four lines and 211px of headline on a
|
|
461
|
+
360px screen.
|
|
462
|
+
- **Line heights are documented per mode.** They always were per mode; the docs
|
|
463
|
+
quoted one mode's values as though they were everyone's, and were wrong for
|
|
464
|
+
two modes out of three.
|
|
465
|
+
- **The README covers installing and using Jig, and nothing else.** How to
|
|
466
|
+
change a rule and how to test that a rule earns its context cost moved to
|
|
467
|
+
`AGENTS.md`, where an agent working on this repository will read them.
|
|
468
|
+
|
|
469
|
+
### Reconciliation
|
|
470
|
+
|
|
471
|
+
`RECONCILE.md` is at **0 open rows**. Every numeric default is either adopted
|
|
472
|
+
from the reference or deliberately kept with its argument stated in one line.
|
|
473
|
+
The motion rows are the exception worth knowing: that reference has no motion
|
|
474
|
+
chapter, so those values were settled against separate sources, and where no
|
|
475
|
+
source gave a number they are kept as ours on stated reasoning rather than
|
|
476
|
+
adopted.
|
|
477
|
+
|
|
478
|
+
`check-tokens` grew from 5 rules to 12, each mutation-tested. Two of the new
|
|
479
|
+
ones exist because a guard had been passing vacuously: rule 6's regex was
|
|
480
|
+
line-anchored and so covered 103 of 133 tokens while claiming to cover all of
|
|
481
|
+
them, and nothing at all checked that a token cited in the rules exists.
|
|
482
|
+
|
|
483
|
+
## 0.4.0
|
|
484
|
+
|
|
485
|
+
Jig stops copying itself into your project. It is a skill an agent reads, and
|
|
486
|
+
0.3.0 wrote 220KB across 17 files into every consuming repo to deliver it —
|
|
487
|
+
roughly 200KB of that Jig's own property, read by an agent that already had it
|
|
488
|
+
from the skill install. A single-mode project now gets **three** files, all of
|
|
489
|
+
them its own.
|
|
490
|
+
|
|
491
|
+
### Changed
|
|
492
|
+
|
|
493
|
+
- **`install` writes one place: the harness's skill directory.** `SKILL.md`, the
|
|
494
|
+
rules, `rules.index.json` and attribution live beside each other at
|
|
495
|
+
`<harness>/skills/jig/`, project or global. Nothing lands in `.jig/` any more.
|
|
496
|
+
|
|
497
|
+
The rules are not a build input — nothing compiles them, and the agent reading
|
|
498
|
+
them already has them. The genuine exception is CSS: a stylesheet `@import` is
|
|
499
|
+
an edge in a build graph and must resolve inside the project, on every machine
|
|
500
|
+
that builds it. That is the one category `init` still copies.
|
|
501
|
+
|
|
502
|
+
- **`.jig/` holds only what belongs to the project** — the brand file, the mode
|
|
503
|
+
files for the modes actually declared (not all three), and `state.json`.
|
|
504
|
+
|
|
505
|
+
- **A project install refuses when a global one exists.** Two `jig` skills
|
|
506
|
+
registered with the same harness, whose rule paths point at different places,
|
|
507
|
+
is exactly the incoherence this layout exists to prevent.
|
|
508
|
+
|
|
509
|
+
- **Every harness comes from one table.** Five adapters — Claude Code, Cursor,
|
|
510
|
+
opencode, Gemini CLI, and a generic `.agents/skills` — share the
|
|
511
|
+
`<harness>/skills/<name>/` convention, so adding one is a row rather than a
|
|
512
|
+
file. Codex keeps a bespoke implementation because `AGENTS.md` genuinely is a
|
|
513
|
+
different mechanism.
|
|
514
|
+
|
|
515
|
+
### Fixed
|
|
516
|
+
|
|
517
|
+
- **The skill told agents `check` was planned.** It shipped in 0.3.0. A baseline
|
|
518
|
+
run reported "the CLI is ahead of the doc" and worked by hand rather than
|
|
519
|
+
running it. The guard that should have caught this compared the metadata
|
|
520
|
+
against a hand-maintained list, so when `check` landed and neither was
|
|
521
|
+
updated, the two agreed and the test stayed green. The list is now read out of
|
|
522
|
+
the CLI source, and agreement is asserted in both directions.
|
|
523
|
+
|
|
524
|
+
- **The skill sent agents to an unpinned CLI.** `npx jig-ui` resolves to whatever
|
|
525
|
+
is latest on npm, which need not be the version that wrote the bundle. Two
|
|
526
|
+
baselines hit this and fell back to working by hand. The skill now names the
|
|
527
|
+
version that built it, and `jig update` moves both together.
|
|
528
|
+
|
|
529
|
+
- **`JIG_CHECK:` named two different records.** The CLI emitted `version=
|
|
530
|
+
mechanical= judgment=`; the skill told the agent to emit `version= mode=
|
|
531
|
+
self_check=` — disjoint fields under one label. There is now one field set,
|
|
532
|
+
`version mode mechanical judgment`, asserted against both sources. An emitter
|
|
533
|
+
that cannot determine a field says so in the value rather than dropping it.
|
|
534
|
+
|
|
535
|
+
- **Every vendored file cited a licence path that no longer exists.** The header
|
|
536
|
+
hardcoded `.jig/LICENSE`, true only while install vendored into `.jig/`. In
|
|
537
|
+
the new layout the one line whose job is directing a reader to the licence
|
|
538
|
+
directed them nowhere. It is now computed from the file's depth in the bundle.
|
|
539
|
+
|
|
540
|
+
- **`update` refreshed only one harness.** A project can hold several installs,
|
|
541
|
+
each with its own manifest; the rest stayed pinned at their install version
|
|
542
|
+
with nothing said about them. It now refreshes every one and reports each.
|
|
543
|
+
|
|
544
|
+
- **`update` wrote files before checking the path.** `assertSafeRelPath` covered
|
|
545
|
+
adapter-rendered files but not `referenceDir`, which the harness table derives
|
|
546
|
+
just as directly. The shipped table is asserted at module load, so a bad entry
|
|
547
|
+
fails at import rather than at whichever command writes first.
|
|
548
|
+
|
|
549
|
+
- **A project-scope Codex install wrote Jig's rules into your project's
|
|
550
|
+
`.jig/`.** Codex has no skill-directory convention, so its bundle went to a
|
|
551
|
+
bare `.jig` — the one directory this release reserves for the project's own
|
|
552
|
+
material. Install plus `init` left 13 files there, Jig's rules and manifest
|
|
553
|
+
interleaved with your tokens and state, and the harness that most needed the
|
|
554
|
+
0.4.0 separation was the only one that did not get it.
|
|
555
|
+
|
|
556
|
+
Two concrete harms beyond the untidiness: `init`'s legacy scanner looks in
|
|
557
|
+
`.jig/` for exactly those artifacts and offers to remove them, so it could
|
|
558
|
+
offer to delete a live install; and one directory holding two manifests is
|
|
559
|
+
what let a stale `.jig/manifest.json` hijack `update` in the first place.
|
|
560
|
+
|
|
561
|
+
Codex now uses `.codex/.jig/` at both scopes, mirroring the path its global
|
|
562
|
+
install already used. Verified against the real Codex CLI: it reads
|
|
563
|
+
`AGENTS.md`, resolves every rule path under the new location, and picks up the
|
|
564
|
+
declared mode. Upgrading leaves the old bundle in place — nothing is deleted —
|
|
565
|
+
and `update` now names it rather than reporting a bare "Jig is not installed"
|
|
566
|
+
to someone looking straight at the files.
|
|
567
|
+
|
|
568
|
+
- **`update` could never move an install forward.** Pinning the CLI fixed version
|
|
569
|
+
skew, but applied to every command it trapped the install: `npx jig-ui@0.4.0
|
|
570
|
+
update` refreshes to 0.4.0, reports success, and changes nothing. `update` is
|
|
571
|
+
the one command whose job is moving the pin, so it is the one that does not
|
|
572
|
+
carry it — the skill renders `npx jig-ui@latest update`.
|
|
573
|
+
|
|
574
|
+
- **`init --yes` chose a mode silently.** It takes `'/' → product` without
|
|
575
|
+
inferring anything, and `01-modes.md` rule 1 makes the config authoritative
|
|
576
|
+
over an agent's own inference — so the default is not a neutral placeholder,
|
|
577
|
+
it binds every agent that reads the project afterwards. Two baseline runs on
|
|
578
|
+
an `ops-console` project read every signal as `operator`, found `product`, and
|
|
579
|
+
correctly deferred to it; one noted the density difference is expensive to
|
|
580
|
+
reverse. The brand colour already stated its default and why. The mode now
|
|
581
|
+
does too, and says where to change it.
|
|
582
|
+
|
|
583
|
+
- **A source build could stamp a pin to a version that was never published**,
|
|
584
|
+
silently, until an agent tried to run it. `install` and `update` now say so
|
|
585
|
+
when the running CLI is not an npm-installed package.
|
|
586
|
+
|
|
587
|
+
- **Concurrent runs lost each other's manifest entries.** Two runs against one
|
|
588
|
+
install — two agents, or a script running `jig init` across a monorepo against
|
|
589
|
+
a shared global install — both read the manifest and both wrote it, and the
|
|
590
|
+
last writer's copy dropped the other's records of "Jig owns this file".
|
|
591
|
+
Losing one makes a later `update` treat that file as the user's and stop
|
|
592
|
+
refreshing it: the safe direction, but silent.
|
|
593
|
+
|
|
594
|
+
Fixed without a lock. The `files` map is additive and per-file — a run only
|
|
595
|
+
records entries for files it actually wrote — so merging against whatever is
|
|
596
|
+
on disk at write time is correct, and needs none of the stale-lock recovery a
|
|
597
|
+
mutex would after a process is killed mid-run. Writes are atomic
|
|
598
|
+
(temp + rename), and verified-and-retried to close the window between the read
|
|
599
|
+
and the rename. Ten parallel processes writing fifty entries now keep all
|
|
600
|
+
fifty; without the merge, one survives.
|
|
601
|
+
|
|
602
|
+
- **An asset could be staged at prepack and left out of the tarball** — correct
|
|
603
|
+
code reading an asset that never shipped. Both lists must now agree, verified
|
|
604
|
+
against the real `npm pack` output.
|
|
605
|
+
|
|
606
|
+
- **A legacy `.jig/manifest.json` hijacked `update`** and resurrected the whole
|
|
607
|
+
vendored layout.
|
|
608
|
+
|
|
609
|
+
- **Agents invented token values when `init` had not been run.** A baseline run
|
|
610
|
+
with the skill installed but the project not initialised authored its own
|
|
611
|
+
`:root` block — "control height (32), row height (48), duration (120ms) and
|
|
612
|
+
the near-black brand default are my resolved values, not the system's" — and
|
|
613
|
+
wrote it into the project's stylesheet. Step 5 said "consume tokens by
|
|
614
|
+
semantic name only", and it complied to the letter by inventing the
|
|
615
|
+
definitions behind the names.
|
|
616
|
+
|
|
617
|
+
`SKILL.md` now opens with the precondition: no `jig.config.json` means no
|
|
618
|
+
token layer, so run `init` and stop, and do not author a `:root` block of your
|
|
619
|
+
own. Step 5 gained the counter — a token with no value is a finding to report,
|
|
620
|
+
not a number to supply. Re-run on the same fixture, the agent invented
|
|
621
|
+
nothing, and reported a real gap in the token contract instead.
|
|
622
|
+
|
|
623
|
+
### Added
|
|
624
|
+
|
|
625
|
+
- **`/jig` slash commands.** `install` writes a command file for every harness
|
|
626
|
+
that has a slash-command mechanism, so `/jig init`, `/jig check --all` and
|
|
627
|
+
`/jig update` work without leaving the session. One file named `jig`
|
|
628
|
+
dispatching on its arguments, which is what gives `/jig init` with a space
|
|
629
|
+
rather than a separate `/jig-init` per subcommand.
|
|
630
|
+
|
|
631
|
+
The command is not a thin wrapper: `/jig check` runs the CLI for the seven
|
|
632
|
+
mechanical rules, then applies the 97 judgment rules to the same files and
|
|
633
|
+
merges both halves into one report keyed by rule id — the half a CLI cannot
|
|
634
|
+
do, which is the reason the command exists at all.
|
|
635
|
+
|
|
636
|
+
Claude Code, Cursor, opencode and Gemini CLI (which gets its own TOML shape).
|
|
637
|
+
Not Codex: its custom prompts are not expanded by `codex exec` — probed
|
|
638
|
+
directly — so a file there could sit and never fire. Only subcommands the CLI
|
|
639
|
+
actually registers are offered, since a slash command that errors out is worse
|
|
640
|
+
than one that does not exist.
|
|
641
|
+
|
|
642
|
+
- **`check` reads CSS wherever it lives.** It read `.css`/`.scss`/`.less` only,
|
|
643
|
+
which for most projects meant it examined almost nothing — and said nothing
|
|
644
|
+
about that. A Tailwind v4 fixture with `bg-[#6D28D9] p-[13px] rounded-[12px]
|
|
645
|
+
text-[22px] h-[32px]` reported "No findings · 0 errors · mechanical=pass:0". A
|
|
646
|
+
clean bill of health for a project where every value bypassed the token layer.
|
|
647
|
+
|
|
648
|
+
Now covered: `<style>` blocks (HTML, Astro, Vue, Svelte, PHP, ERB, Twig,
|
|
649
|
+
Handlebars, MDX, ASP and ASP.NET, Razor, JSP, Phoenix, EJS, Nunjucks, Liquid,
|
|
650
|
+
Jinja, Velocity, FreeMarker), the indentation-delimited templates (Pug's
|
|
651
|
+
`style.`, Haml's `:css`, Slim's `css:`, each with its own attribute syntax),
|
|
652
|
+
`style="…"` and `style={{ }}`, CSS-in-JS tagged templates
|
|
653
|
+
(`styled.button`, `styled(Link)`, `css`, `createGlobalStyle`, `keyframes`),
|
|
654
|
+
Tailwind arbitrary values, and Tailwind default-palette contrast pairs.
|
|
655
|
+
`@theme` counts as the token layer, so a v4 project that has adopted Jig is
|
|
656
|
+
recognised as having done so.
|
|
657
|
+
|
|
658
|
+
The mechanism is extraction rather than a detector per language: everything
|
|
659
|
+
that is not CSS is blanked, preserving character positions, and the existing
|
|
660
|
+
detectors run unchanged — so a finding in a `.vue` file still points at the
|
|
661
|
+
right line, and all seven rules gained host-language support at once.
|
|
662
|
+
|
|
663
|
+
Two deliberate limits. A bare `p-4` is not a finding: it resolves through a
|
|
664
|
+
scale, and flagging it would mean flagging correct Tailwind. A colour outside
|
|
665
|
+
the default palette is not resolved rather than guessed at.
|
|
666
|
+
|
|
667
|
+
- **Reference files ship beside the skill.** `references/**` in the package
|
|
668
|
+
installs into the bundle with its subdirectory shape preserved, refreshed by
|
|
669
|
+
`update` under the same rule as the rules: replace when untouched, skip when
|
|
670
|
+
you have edited it. Adding one is a file drop, no code change.
|
|
671
|
+
|
|
672
|
+
**No reference ships in 0.4.0.** Four were planned — a procedure for `init`,
|
|
673
|
+
for `check`, for building a component, and one for resolving apparent rule
|
|
674
|
+
conflicts. Each was tested first by running an agent on the task with no
|
|
675
|
+
guidance, and in every case the agent already did the right thing: it inferred
|
|
676
|
+
the mode with signals stated, kept a 32px control inside a 48px target rather
|
|
677
|
+
than reading the two as contradictory, surfaced the brand question instead of
|
|
678
|
+
guessing, and handled loading, error and never-checked states unprompted.
|
|
679
|
+
`04-principles.md`'s tiebreakers were doing the work the references were meant
|
|
680
|
+
to do. Writing them anyway would have added words the rules already carry.
|
|
681
|
+
|
|
682
|
+
### Migration
|
|
683
|
+
|
|
684
|
+
`install` no longer writes rule files into `.jig/`, so a pre-0.4.0 project has
|
|
685
|
+
rules in two places. The old copies are yours to remove; nothing deletes them
|
|
686
|
+
for you, because you may have edited one and that edit is yours to keep. Run
|
|
687
|
+
`jig install --agent <name>` to place the new bundle, then delete `.jig/rules/`
|
|
688
|
+
and `.jig/rules.index.json` once you have checked them for your own changes.
|
|
689
|
+
|
|
690
|
+
## 0.3.0
|
|
691
|
+
|
|
692
|
+
Two new commands. `install` and `update` put the system in place; these two make
|
|
693
|
+
it do something.
|
|
694
|
+
|
|
695
|
+
### Added
|
|
696
|
+
|
|
697
|
+
- **`jig check`** — verifies a consumer's code against the rules. Seven
|
|
698
|
+
detectors, exactly the ones `rules.index.json` already named: `gradient-text`
|
|
699
|
+
(A-02), `backdrop-blur` (A-04), `pure-black-white` (C-18), `contrast-floor`
|
|
700
|
+
(C-19), `focus-removed` (E-29), `hardcoded-value` (H-47), and
|
|
701
|
+
`violet-band-hue` (A-01, hybrid — it asks rather than fails). With `--all`,
|
|
702
|
+
`--ci` (mechanical bucket only, no model, deterministic) and `--json`.
|
|
703
|
+
|
|
704
|
+
H-47 runs only on files that reference a Jig token or import a vendored token
|
|
705
|
+
file. "Hard-coded *past* the token layer" means nothing for a file that never
|
|
706
|
+
adopted it, and without that scope it produced 13 of 13 findings on a 20-line
|
|
707
|
+
stylesheet. A project where nothing participates is told how to start.
|
|
708
|
+
|
|
709
|
+
- **`jig init`** — sets a project up to use the system. Detects the CSS system,
|
|
710
|
+
derives a brand colour from existing code rather than interviewing cold,
|
|
711
|
+
validates it against the contract `brand.default.css` already states, writes
|
|
712
|
+
the brand file and `jig.config.json`, wires the imports, and runs `check` for
|
|
713
|
+
a baseline.
|
|
714
|
+
|
|
715
|
+
This is also what makes global installs coherent. The brand file and config
|
|
716
|
+
always live in the project, and for a global install the one selected mode
|
|
717
|
+
file is copied into the project's `.jig/tokens/` so the import is
|
|
718
|
+
project-relative. A `$HOME`-relative CSS import resolves only on the machine
|
|
719
|
+
that generated it; a stylesheet is committed and must build everywhere.
|
|
720
|
+
|
|
721
|
+
- `oklch()` is parsed. Tailwind v4 and shadcn emit it by default, so skipping it
|
|
722
|
+
meant `init` derived nothing on a large share of new projects and `C-19`
|
|
723
|
+
computed no contrast against Jig's own `--color-bg-base`.
|
|
724
|
+
|
|
725
|
+
### Fixed
|
|
726
|
+
|
|
727
|
+
- **CSS nesting hid the parent's declarations.** A block containing braces was
|
|
728
|
+
discarded whole, so in `.card { color: red; .h { … } }` the `color: red`
|
|
729
|
+
belonged to no block and was invisible to every detector. On a Sass codebase
|
|
730
|
+
that was most declarations, reported as a clean result.
|
|
731
|
+
|
|
732
|
+
- Comments produced findings, and a commented-out `:focus-visible` silenced
|
|
733
|
+
E-29 for a whole file — a dead detector reporting success.
|
|
734
|
+
|
|
735
|
+
- `var(--x, fallback)` was resolved to the fallback and reported as fact.
|
|
736
|
+
|
|
737
|
+
- The large-text contrast exemption was inert because only `px` font-sizes were
|
|
738
|
+
recognised, so `2rem` at 3.54:1 was flagged as failing a 4.5:1 floor that did
|
|
739
|
+
not apply to it.
|
|
740
|
+
|
|
741
|
+
|
|
742
|
+
## 0.2.1
|
|
743
|
+
|
|
744
|
+
### Fixed
|
|
745
|
+
|
|
746
|
+
- **`--color-text-warning` and `--color-text-success` failed their contrast
|
|
747
|
+
floors.** Warning was 3.64:1 and success 4.48:1 against the surfaces they can
|
|
748
|
+
land on, where text requires 4.5:1 and strokes 3:1. The source is explicit:
|
|
749
|
+
system colours used for text need 4.5:1; used for interface elements and
|
|
750
|
+
icons, 3:1. `RECONCILE.md` also lists the contrast floors as the one category
|
|
751
|
+
not up for reconciliation, and `C-19` is a rule about this exact failure — so
|
|
752
|
+
the system was breaking its own hardest rule, in a shipped default that every
|
|
753
|
+
consumer inherits unless they override it.
|
|
754
|
+
|
|
755
|
+
Warning lightness 36% → 29%, success 26% → 23%. Hue and saturation unchanged,
|
|
756
|
+
so both are the same colour, darker. All four semantic colours now clear both
|
|
757
|
+
floors against `bg-base`, `bg-raised`, and `fill` on either.
|
|
758
|
+
|
|
759
|
+
- The system colours now state what a replacement must satisfy. The brand colour
|
|
760
|
+
already carried that contract; these did not, so a user bringing their own
|
|
761
|
+
error or warning colour — the intended workflow — had no floor to hit.
|
|
762
|
+
|
|
763
|
+
### Added
|
|
764
|
+
|
|
765
|
+
- `scripts/check-tokens.mjs` gains two rules, both mutation-tested. Rule 5
|
|
766
|
+
computes contrast from the token values and fails the build; this is the only
|
|
767
|
+
defect class here that arithmetic can catch, and it shipped twice because
|
|
768
|
+
nobody was doing the arithmetic. Rule 6 fails the build when a token is
|
|
769
|
+
defined but never rendered by the preview.
|
|
770
|
+
|
|
771
|
+
- `packages/preview` — a rendering harness. Every prior check verified the
|
|
772
|
+
system by arithmetic or grep; nothing had looked at it. Plain HTML and CSS,
|
|
773
|
+
no build, not published. It found two gaps on its first run: there is no
|
|
774
|
+
border-width token and no focus-ring geometry tokens.
|
|
775
|
+
|
|
776
|
+
## 0.2.0
|
|
777
|
+
|
|
778
|
+
The first release that actually works end to end. `0.1.0` shipped rules that
|
|
779
|
+
cited tokens it never installed, and a token name that did not exist.
|
|
780
|
+
|
|
781
|
+
### Fixed
|
|
782
|
+
|
|
783
|
+
- **`--color-brand` was cited nine times and defined nowhere**, including
|
|
784
|
+
`03-patterns.md`'s primary-button spec. An agent following that rule wrote
|
|
785
|
+
`background: var(--color-brand)` and got an unset custom property.
|
|
786
|
+
- **The design tokens were never installed.** The rules cite tokens 22 times
|
|
787
|
+
and `02-tokens.md` instructs the reader to import them, but `install` only
|
|
788
|
+
wrote the rule markdown. The CSS was in the published tarball the whole time
|
|
789
|
+
and never copied out.
|
|
790
|
+
- **Rule `C-49` had no correction and `I-80` had no anti-pattern**, in a file
|
|
791
|
+
whose own contract states every rule pairs both. The totals hid it — the two
|
|
792
|
+
defects cancelled at 103/103.
|
|
793
|
+
- **Ten values in the mode profile tables contradicted the tokens**, including
|
|
794
|
+
editorial body size, section rhythm, card padding, and a heading step that
|
|
795
|
+
did not exist.
|
|
796
|
+
- **`A-07`'s correction had silently inverted from true to false.** A mechanical
|
|
797
|
+
rename of `--radius-base` to `--radius-sm` turned a correct statement about
|
|
798
|
+
radius derivation into an incorrect one, with nothing to catch it.
|
|
799
|
+
- **`A-07`'s prohibition used a `16px+` threshold** that flagged `--radius-md`,
|
|
800
|
+
the value the rule exists to sanction.
|
|
801
|
+
- **`C-68` depended on a radius token it never named.** "A badge is more rounded
|
|
802
|
+
than a button" now cites `--radius-full`.
|
|
803
|
+
|
|
804
|
+
### Changed
|
|
805
|
+
|
|
806
|
+
- Tokens vendor to **`.jig/tokens/`** on install, in every scope. That is the
|
|
807
|
+
only location; `update` refreshes them there and nothing relocates them.
|
|
808
|
+
- Editing a vendored token file is expected: `install` and `update` both leave
|
|
809
|
+
files you have changed alone and report them skipped.
|
|
810
|
+
- The mode profile tables cite token names instead of literals; the comparison
|
|
811
|
+
table is ordinal. A number in prose is a call site.
|
|
812
|
+
- The semantic colours are defined once each as `--<name>-h/s/l`. Every variation
|
|
813
|
+
previously repeated the same literal four to five times, so changing a colour
|
|
814
|
+
meant editing every copy or the variations desynchronised.
|
|
815
|
+
|
|
816
|
+
### Added
|
|
817
|
+
|
|
818
|
+
- `scripts/check-tokens.mjs`, run by `npm test`. Four rules, each mutation-tested
|
|
819
|
+
against the drift it guards: the type table must match its tokens by name, no
|
|
820
|
+
unanchored literal in a prose table, no chosen colour literal repeated in a
|
|
821
|
+
token file, and every token import must use the canonical path.
|
|
822
|
+
|