jig-ui 0.18.1 → 0.18.3

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,6 +1,41 @@
1
1
  # Changelog
2
2
 
3
- ## 0.18.1
3
+ ## 0.18.3 (2026-09-25)
4
+
5
+ Recording a decision no longer undoes the critiques written before it, and an
6
+ older probe file says it is older rather than forged.
7
+
8
+ ### Fixed
9
+
10
+ - **A decision recorded after a critique no longer undoes it.** On jig-site one
11
+ `/jig decide` session added eight decisions; every finished critique turned
12
+ "incomplete", and the gate stopped an unrelated spec session over records that
13
+ could not have judged them. `jig verdicts` now asks git: a decision whose
14
+ heading was added in a commit the critique's `decisions.json` commit does not
15
+ contain, or not committed yet, is left for the next critique and listed as
16
+ such. Without git, or while `decisions.json` has uncommitted changes (a
17
+ critique in progress), every decision is still required.
18
+ - **An older probe file is called older, not forged.** After a release changed
19
+ the probe's version, the old files read "not output of `jig probe` … do not
20
+ write it by hand", and an agent stopped work believing they were fabricated.
21
+ They now say which version took them and to record them again.
22
+
23
+ ## 0.18.2 (2026-09-25)
24
+
25
+ Every release in this changelog now carries its date and a one-line summary,
26
+ for jig-site's Versions page.
27
+
28
+ ### Changed
29
+
30
+ - **Every release heading carries its date**, as `## 0.18.1 (2026-09-25)`,
31
+ backfilled from the tags. The npm package has no git history, so the
32
+ CHANGELOG is where a release's date travels with it; jig-site's Versions page
33
+ lists each release by date. A test keeps every released heading dated.
34
+ - **Every release opens with a one-line summary.** Five had none (0.17.1,
35
+ 0.16.1, 0.15.1, 0.12.0, 0.2.1) and now do, written from their own entries.
36
+ The Versions page shows the line under each release; a test keeps it there.
37
+
38
+ ## 0.18.1 (2026-09-25)
4
39
 
5
40
  Two fixes found by jig-site's fourth round: the probe misread a `<details>`
6
41
  menu, and `A-05` missed an arrow that renders as an emoji.
@@ -35,7 +70,7 @@ menu, and `A-05` missed an arrow that renders as an emoji.
35
70
  content of an element, or a pseudo-element's `content`) without U+FE0E. The
36
71
  same arrow in a sentence still does not.
37
72
 
38
- ## 0.18.0
73
+ ## 0.18.0 (2026-09-25)
39
74
 
40
75
  A page's frame gets tokens, a project gets a place to record where its layout
41
76
  switches, and keyboard access a rule requires fits every script budget. All of
@@ -71,7 +106,7 @@ it found building jig-site's header and Reference with the full loop.
71
106
  one pixel before and at each `--breakpoint-*` the project declares, and the
72
107
  gate's refresh keeps those probes current too.
73
108
 
74
- ## 0.17.3
109
+ ## 0.17.3 (2026-09-25)
75
110
 
76
111
  Three defects found building jig-site's header with the full loop.
77
112
 
@@ -100,7 +135,7 @@ Three defects found building jig-site's header with the full loop.
100
135
  said so; only `jig init --yes` refreshed them. `update` now refreshes each
101
136
  untouched copy wherever `init` recorded writing it.
102
137
 
103
- ## 0.17.2
138
+ ## 0.17.2 (2026-09-24)
104
139
 
105
140
  Four defects found by building one page with the full loop.
106
141
 
@@ -128,7 +163,9 @@ Four defects found by building one page with the full loop.
128
163
  stated as measured, the two outliers are trimmed, and a test renders all 286
129
164
  figures in Chrome and fails any wider or taller.
130
165
 
131
- ## 0.17.1
166
+ ## 0.17.1 (2026-09-24)
167
+
168
+ The gate judges only the critiques a session touched.
132
169
 
133
170
  ### Fixed
134
171
 
@@ -141,7 +178,7 @@ Four defects found by building one page with the full loop.
141
178
  starts with `_` is set aside and never judged. With no transcript, as when
142
179
  the gate is run by hand, it checks every critique as before.
143
180
 
144
- ## 0.17.0
181
+ ## 0.17.0 (2026-09-24)
145
182
 
146
183
  Thirteen more tells of a generated page, ten of them caught by `check`, and a
147
184
  picture for every rule. Also carries the probe and verdict fixes tagged as 0.16.2,
@@ -188,7 +225,10 @@ which was not published to npm.
188
225
  any count, `I-81` the page's headline, and `I-89` button labels as well as
189
226
  links.
190
227
 
191
- ## 0.16.1
228
+ ## 0.16.1 (2026-09-19)
229
+
230
+ Jig's own headings drop the em dash, a quotation keeps its own punctuation,
231
+ and a spec's `indexable:` is `true` or `false`.
192
232
 
193
233
  ### Fixed
194
234
 
@@ -206,7 +246,7 @@ which was not published to npm.
206
246
  reported as contradicting J-123. Anything else is now a spec-shape problem,
207
247
  and an error in `verdicts` that names the field.
208
248
 
209
- ## 0.16.0
249
+ ## 0.16.0 (2026-09-19)
210
250
 
211
251
  With more than one mode, every barrel names its mode, and none sits in the
212
252
  global stylesheet.
@@ -226,7 +266,9 @@ global stylesheet.
226
266
  An edited one is left, with a note on where its edits belong. `check` names a
227
267
  `theme.css` left beside two modes.
228
268
 
229
- ## 0.15.1
269
+ ## 0.15.1 (2026-09-19)
270
+
271
+ The gate hears a question anywhere in the message, not only on its last line.
230
272
 
231
273
  ### Fixed
232
274
 
@@ -237,7 +279,7 @@ global stylesheet.
237
279
  live `/jig decide` three times. Any sentence ending in `?` now counts; a `?`
238
280
  in a URL or a code span does not.
239
281
 
240
- ## 0.15.0
282
+ ## 0.15.0 (2026-09-19)
241
283
 
242
284
  The gate holds an agent on warnings, waits while it asks the owner a question,
243
285
  and reaches projects where the skill is installed globally.
@@ -279,7 +321,7 @@ and reaches projects where the skill is installed globally.
279
321
  - **`jig seo` says an endpoint is not a page**, so `pages=` can be checked
280
322
  against a site's route files.
281
323
 
282
- ## 0.14.1
324
+ ## 0.14.1 (2026-09-19)
283
325
 
284
326
  `jig seo` cites only what a rule says.
285
327
 
@@ -304,7 +346,7 @@ and reaches projects where the skill is installed globally.
304
346
  as `/pages/admin`, so a `noindex` Astro or Next page listed in the sitemap
305
347
  went unreported.
306
348
 
307
- ## 0.14.0
349
+ ## 0.14.0 (2026-09-18)
308
350
 
309
351
  What a stranger meets before the page, what the page must not hand them, and a
310
352
  project that states its own direction.
@@ -367,7 +409,7 @@ project that states its own direction.
367
409
  already have. Redesigning an existing page is its own path, and `spec` asks
368
410
  different questions when the page exists.
369
411
 
370
- ## 0.13.0
412
+ ## 0.13.0 (2026-09-18)
371
413
 
372
414
  Meaning before presentation, and one fewer step anyone can skip.
373
415
 
@@ -409,7 +451,9 @@ Meaning before presentation, and one fewer step anyone can skip.
409
451
  `.github`.** Jig's own vendored rules are not the project's interface.
410
452
  - **Probe files are version 3.** Older ones no longer validate.
411
453
 
412
- ## 0.12.0
454
+ ## 0.12.0 (2026-09-18)
455
+
456
+ One new rule: no em dashes in interface text (`I-118`), with a detector.
413
457
 
414
458
  ### Added
415
459
 
@@ -422,7 +466,7 @@ Meaning before presentation, and one fewer step anyone can skip.
422
466
  styles, comments, class names and documentation are not interface text.
423
467
  The en dash keeps its one job, a range read as "to" (`2-10 seats`).
424
468
 
425
- ## 0.11.1
469
+ ## 0.11.1 (2026-09-18)
426
470
 
427
471
  Two holes in the gate, both found by running the loop twice on 0.11.0 —
428
472
  once on Haiku, once on Sonnet.
@@ -441,7 +485,7 @@ once on Haiku, once on Sonnet.
441
485
  at a width where the links fit. A false positive is how a gate gets
442
486
  ignored.
443
487
 
444
- ## 0.11.0
488
+ ## 0.11.0 (2026-09-18)
445
489
 
446
490
  One release, one lesson: a measurement an agent can type is not a
447
491
  measurement. Everything here came from two live runs at the capability
@@ -470,7 +514,7 @@ floor the day 0.10.0 shipped.
470
514
  critique verdicts. Both are warned about separately, each with what
471
515
  ignoring it costs. Since 0.7.0 both had said `.jig/` holds the tokens.
472
516
 
473
- ## 0.10.0
517
+ ## 0.10.0 (2026-09-18)
474
518
 
475
519
  Mobile-first, and a design loop that a weak model cannot skip. Everything here
476
520
  was measured on live runs at the capability floor (Haiku), and most of it exists
@@ -536,7 +580,7 @@ because an instruction the agent could choose to ignore was ignored.
536
580
  - **`init --yes` says what it did not decide** — no surface mapping, and
537
581
  re-running `init` after you declare one.
538
582
 
539
- ## 0.9.0
583
+ ## 0.9.0 (2026-09-13)
540
584
 
541
585
  One new rule and one amended correction, both from the same afternoon of
542
586
  dogfooding and both about the same blind spot: H-47's correction always pointed
@@ -581,7 +625,7 @@ at a token, so an agent reading it literally always produced one.
581
625
  it.
582
626
 
583
627
 
584
- ## 0.8.2
628
+ ## 0.8.2 (2026-09-12)
585
629
 
586
630
  Every fix here was found by a consumer using Jig rather than by Jig checking
587
631
  itself: the documentation site was upgraded to 0.8.1 and then styled in
@@ -660,7 +704,7 @@ disagreeing without either knowing the other existed.
660
704
  guard built on it. Caught by its own canary the moment an option wrapped.
661
705
 
662
706
 
663
- ## 0.8.1
707
+ ## 0.8.1 (2026-09-12)
664
708
 
665
709
  Both fixes here are the same shape: 0.8.0 corrected the instance it was looking
666
710
  at and left the class alone, and in each case the commit message claimed a
@@ -720,7 +764,7 @@ by inspecting the published tarball rather than the working tree.
720
764
  is your call", "my inclination is") as well as the heading, because a rename
721
765
  would otherwise defeat it. Each tell is verified to fire on reintroduction.
722
766
 
723
- ## 0.8.0
767
+ ## 0.8.0 (2026-09-11)
724
768
 
725
769
  Everything here was found by handing Jig to agents that had never seen it and
726
770
  asking them to build something real — its own documentation site. None of it
@@ -856,7 +900,7 @@ Minor rather than patch: `explain` prints lines it did not print before, and
856
900
  whether the guard should consult the config first, which is a behaviour
857
901
  question rather than a copy one.
858
902
 
859
- ## 0.7.1
903
+ ## 0.7.1 (2026-09-11)
860
904
 
861
905
  A rule file that contradicted the tool, and the guard that kept it that way.
862
906
 
@@ -910,7 +954,7 @@ to agents that had never seen this repository and asking them to build
910
954
  something real. Everyone who could have caught the token-location defect
911
955
  already knew where the tokens were.
912
956
 
913
- ## 0.7.0
957
+ ## 0.7.0 (2026-09-11)
914
958
 
915
959
  A silent no-op, fixed, plus the missing half of 0.6.0's token-layer move.
916
960
 
@@ -952,7 +996,7 @@ to move their token layer should read these notes.
952
996
  AFTER @import "./jig/theme.css";
953
997
  ```
954
998
 
955
- ## 0.6.0
999
+ ## 0.6.0 (2026-09-11)
956
1000
 
957
1001
  The token layer stops hiding in a dotfolder, and `check` starts reading it back.
958
1002
 
@@ -1046,7 +1090,7 @@ move it, because relocating files could break an import you wrote yourself.
1046
1090
  directive it needs. Nothing errors when this bites: the class lands on the
1047
1091
  element, no rule exists to match it, and the style simply does not apply.
1048
1092
 
1049
- ## 0.5.0
1093
+ ## 0.5.0 (2026-09-10)
1050
1094
 
1051
1095
  Four things shipped in 0.4.0 were broken in ways that reported success. `/jig
1052
1096
  update` refreshed to the version already installed and said "Updated Jig →
@@ -1140,7 +1184,7 @@ ones exist because a guard had been passing vacuously: rule 6's regex was
1140
1184
  line-anchored and so covered 103 of 133 tokens while claiming to cover all of
1141
1185
  them, and nothing at all checked that a token cited in the rules exists.
1142
1186
 
1143
- ## 0.4.0
1187
+ ## 0.4.0 (2026-09-04)
1144
1188
 
1145
1189
  Jig stops copying itself into your project. It is a skill an agent reads, and
1146
1190
  0.3.0 wrote 220KB across 17 files into every consuming repo to deliver it —
@@ -1347,7 +1391,7 @@ for you, because you may have edited one and that edit is yours to keep. Run
1347
1391
  `jig install --agent <name>` to place the new bundle, then delete `.jig/rules/`
1348
1392
  and `.jig/rules.index.json` once you have checked them for your own changes.
1349
1393
 
1350
- ## 0.3.0
1394
+ ## 0.3.0 (2026-09-03)
1351
1395
 
1352
1396
  Two new commands. `install` and `update` put the system in place; these two make
1353
1397
  it do something.
@@ -1399,7 +1443,10 @@ it do something.
1399
1443
  not apply to it.
1400
1444
 
1401
1445
 
1402
- ## 0.2.1
1446
+ ## 0.2.1 (2026-09-01)
1447
+
1448
+ Two shipped colours failed Jig's own contrast floors. They are darker now,
1449
+ and the build does the contrast arithmetic.
1403
1450
 
1404
1451
  ### Fixed
1405
1452
 
@@ -1433,7 +1480,7 @@ it do something.
1433
1480
  no build, not published. It found two gaps on its first run: there is no
1434
1481
  border-width token and no focus-ring geometry tokens.
1435
1482
 
1436
- ## 0.2.0
1483
+ ## 0.2.0 (2026-09-01)
1437
1484
 
1438
1485
  The first release that actually works end to end. `0.1.0` shipped rules that
1439
1486
  cited tokens it never installed, and a token name that did not exist.
package/dist/index.js CHANGED
@@ -5673,8 +5673,9 @@ Could not write to ${wireTarget}: ${err.message}`);
5673
5673
  }
5674
5674
 
5675
5675
  // src/commands/verdicts.ts
5676
+ import { execFileSync as execFileSync3 } from "child_process";
5676
5677
  import { existsSync as existsSync23, readFileSync as readFileSync30 } from "fs";
5677
- import { join as join37, resolve as resolve5 } from "path";
5678
+ import { join as join37, relative as relative4, resolve as resolve5 } from "path";
5678
5679
 
5679
5680
  // src/rules/citations.ts
5680
5681
  import { join as join29 } from "path";
@@ -6258,6 +6259,10 @@ function readProbes(projectRoot, dir, errors) {
6258
6259
  for (const f of readdirSync13(dir).filter((n) => /^probe-\d+\.json$/.test(n)).sort()) {
6259
6260
  try {
6260
6261
  const p = JSON.parse(readFileSync27(join34(dir, f), "utf8"));
6262
+ if (typeof p.jigProbe === "number" && p.jigProbe < PROBE_VERSION && typeof p.width === "number") {
6263
+ errors.push(`${f} was taken by an older \`jig probe\` (version ${p.jigProbe}; this Jig reads version ${PROBE_VERSION}). Record it again with \`jig probe --run\`.`);
6264
+ continue;
6265
+ }
6261
6266
  if (p.jigProbe !== PROBE_VERSION || typeof p.width !== "number") {
6262
6267
  errors.push(`${f} is not output of \`jig probe\` (version ${PROBE_VERSION}). Re-run the probe; do not write it by hand.`);
6263
6268
  continue;
@@ -6366,21 +6371,24 @@ function decisionsFile(projectRoot) {
6366
6371
  return void 0;
6367
6372
  }
6368
6373
  function decisionNames(projectRoot) {
6374
+ return [...decisionHeadings(projectRoot).keys()];
6375
+ }
6376
+ function decisionHeadings(projectRoot) {
6377
+ const headings = /* @__PURE__ */ new Map();
6369
6378
  const path = decisionsFile(projectRoot);
6370
- if (!path) return [];
6379
+ if (!path) return headings;
6371
6380
  let body;
6372
6381
  try {
6373
6382
  body = readFileSync28(join35(projectRoot, path), "utf8");
6374
6383
  } catch {
6375
- return [];
6384
+ return headings;
6376
6385
  }
6377
- const names = [];
6378
6386
  for (const match of body.matchAll(HEADING3)) {
6379
6387
  const name = match[2].replace(/[`*]/g, "").trim();
6380
6388
  if (!name || NOT_A_DECISION.test(name)) continue;
6381
- if (!names.includes(name)) names.push(name);
6389
+ if (!headings.has(name)) headings.set(name, match[0].trim());
6382
6390
  }
6383
- return names;
6391
+ return headings;
6384
6392
  }
6385
6393
 
6386
6394
  // src/check/spec-shape.ts
@@ -6583,11 +6591,41 @@ function checkDecisions(projectRoot, dir, errors) {
6583
6591
  else if (ABSENCE.test(reason)) errors.push(`decisions.json: "${match}" \u2014 "${reason}" says the decision was not read.`);
6584
6592
  if (v.verdict === "finding") findings++;
6585
6593
  }
6586
- const missing = required.filter((r) => !seen.has(r));
6594
+ const unjudged = required.filter((r) => !seen.has(r));
6595
+ const since = decisionsSince(projectRoot, dir, unjudged);
6596
+ const missing = unjudged.filter((r) => !since.includes(r));
6597
+ const total = required.length - since.length;
6587
6598
  if (missing.length) {
6588
- errors.push(`decisions.json: ${missing.length} of ${required.length} decisions have no verdict: ${missing.join(", ")}.`);
6599
+ errors.push(`decisions.json: ${missing.length} of ${total} decisions have no verdict: ${missing.join(", ")}.`);
6600
+ }
6601
+ return { state: missing.length ? "incomplete" : "ran", judged: total - missing.length, total, findings, ...since.length ? { since } : {} };
6602
+ }
6603
+ function decisionsSince(projectRoot, dir, unjudged) {
6604
+ if (unjudged.length === 0) return [];
6605
+ const path = decisionsFile(projectRoot);
6606
+ if (!path) return [];
6607
+ const git = (args) => execFileSync3("git", args, { cwd: projectRoot, encoding: "utf8", stdio: ["ignore", "pipe", "ignore"] }).trim();
6608
+ try {
6609
+ const verdictFile = relative4(projectRoot, join37(dir, "decisions.json"));
6610
+ if (git(["status", "--porcelain", "--", verdictFile])) return [];
6611
+ const judgedIn = git(["log", "-1", "--format=%H", "--", verdictFile]);
6612
+ if (!judgedIn) return [];
6613
+ const headings = decisionHeadings(projectRoot);
6614
+ return unjudged.filter((name) => {
6615
+ const line = headings.get(name);
6616
+ if (!line) return false;
6617
+ const addedIn = git(["log", "--format=%H", "-S", line, "--", path]).split("\n").filter(Boolean).pop();
6618
+ if (!addedIn) return true;
6619
+ try {
6620
+ git(["merge-base", "--is-ancestor", addedIn, judgedIn]);
6621
+ return false;
6622
+ } catch {
6623
+ return true;
6624
+ }
6625
+ });
6626
+ } catch {
6627
+ return [];
6589
6628
  }
6590
- return { state: missing.length ? "incomplete" : "ran", judged: required.length - missing.length, total: required.length, findings };
6591
6629
  }
6592
6630
  function verifyVerdicts(opts) {
6593
6631
  const root = opts.packageRoot ?? assetRoot();
@@ -7120,6 +7158,8 @@ program.command("verdicts").description("Verify a critique's verdict files and c
7120
7158
  const result = verifyVerdicts({ projectRoot, surface });
7121
7159
  for (const error of result.errors) console.error(` \u2717 ${error}`);
7122
7160
  if (result.ok) console.log(` Every rule in both passes has a verdict.`);
7161
+ const since = result.decisions.since ?? [];
7162
+ if (since.length) console.log(` ${since.length} decision(s) recorded after this critique, for the next one to judge: ${since.join(", ")}.`);
7123
7163
  console.log(` ${result.line}`);
7124
7164
  process.exit(result.ok ? 0 : 1);
7125
7165
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "jig-ui",
3
- "version": "0.18.1",
3
+ "version": "0.18.3",
4
4
  "description": "A design system for coding agents. 143 numbered UI rules, brand x mode design tokens, and an installer for Claude Code, Codex, Cursor and opencode.",
5
5
  "license": "Apache-2.0",
6
6
  "type": "module",