jig-ui 0.23.0 → 0.24.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 +101 -0
- package/README.md +98 -52
- package/dist/index.js +882 -523
- package/package.json +3 -2
- package/templates/COMMAND.md.tmpl +73 -48
- package/templates/SKILL.md.tmpl +12 -0
- package/templates/command-metadata.json +5 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "jig-ui",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.24.0",
|
|
4
4
|
"description": "A design system for coding agents. 159 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",
|
|
@@ -22,7 +22,7 @@
|
|
|
22
22
|
"CHANGELOG.md"
|
|
23
23
|
],
|
|
24
24
|
"engines": {
|
|
25
|
-
"node": ">=
|
|
25
|
+
"node": ">=22"
|
|
26
26
|
},
|
|
27
27
|
"scripts": {
|
|
28
28
|
"build": "tsup",
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/node": "^22.0.0",
|
|
39
39
|
"tsup": "^8.3.0",
|
|
40
|
+
"tsx": "^4.23.15",
|
|
40
41
|
"typescript": "^5.6.0",
|
|
41
42
|
"vitest": "^2.1.0"
|
|
42
43
|
},
|
|
@@ -6,7 +6,7 @@ these, say so, list them, and stop.
|
|
|
6
6
|
|
|
7
7
|
There are two kinds of subcommand, and they are not run the same way.
|
|
8
8
|
|
|
9
|
-
**CLI-backed** — `install`, `update`, `init`, `check`, `explain`, `verdicts`, `gate`, `probe`, `seo`, `ship`. Run the
|
|
9
|
+
**CLI-backed** — `install`, `update`, `init`, `check`, `explain`, `verdicts`, `gate`, `probe`, `seo`, `ship`, `checksum`. Run the
|
|
10
10
|
matching command with `{{scripts_path}}`, passing the flags through unchanged,
|
|
11
11
|
then do the work below for that subcommand. Read the command's full output —
|
|
12
12
|
findings are ordered by severity, not position, so `head`, `tail`, `grep` and
|
|
@@ -261,10 +261,12 @@ The commands after this run unchanged.
|
|
|
261
261
|
### 1. Ask, two or three questions at a time
|
|
262
262
|
|
|
263
263
|
**This is a required interaction, not a suggestion.** Ask two or three questions,
|
|
264
|
-
then **wait**. Do not send a questionnaire. Do not
|
|
265
|
-
for approval on your first response — a spec synthesised from a one-line
|
|
266
|
-
and handed over for a yes is the failure this command exists to prevent,
|
|
267
|
-
looks exactly like the command working.
|
|
264
|
+
then **wait**. Do not send a questionnaire. Do not hand the owner a finished
|
|
265
|
+
spec for approval on your first response — a spec synthesised from a one-line
|
|
266
|
+
prompt and handed over for a yes is the failure this command exists to prevent,
|
|
267
|
+
and it looks exactly like the command working. (This is about what you ask the
|
|
268
|
+
owner, not where you write: when you do write the spec, it goes in
|
|
269
|
+
`.jig/specs/`, step 3.)
|
|
268
270
|
|
|
269
271
|
Ask about **structure**, not appearance. Colour, type scale and density were
|
|
270
272
|
settled at `init` and live in `{{config_file}}` and the token layer; re-deciding
|
|
@@ -327,6 +329,11 @@ hierarchy plainly enough that the squint question can be answered against it.
|
|
|
327
329
|
|
|
328
330
|
### 3. Write it down — one composition per screen size
|
|
329
331
|
|
|
332
|
+
**Write it at `.jig/specs/<name>.spec.md` from the first draft**, with
|
|
333
|
+
`confirmed: false`, never in a scratchpad or a temporary file. Every check the
|
|
334
|
+
owner relies on reads that file, the check in 3c and the gate among them; a
|
|
335
|
+
draft kept elsewhere is checked by nothing, and reaches the owner unchecked.
|
|
336
|
+
|
|
330
337
|
`.jig/specs/<surface-slug>.spec.md`. Frontmatter carries what can be compared to
|
|
331
338
|
a built page; prose carries the reasoning that no check can read.
|
|
332
339
|
|
|
@@ -340,6 +347,7 @@ phone as a squeezed desktop.
|
|
|
340
347
|
---
|
|
341
348
|
feature: sign in to an existing account # the task, not the screen
|
|
342
349
|
surface: login page
|
|
350
|
+
route: /login/ # optional: where the page is served, when the surface's name does not say
|
|
343
351
|
mode: product # from {{config_file}} — state it, never leave it implied
|
|
344
352
|
confirmed: false # only the user sets this to true; see below
|
|
345
353
|
sizes: # phone first. Each size is a whole composition, not a diff.
|
|
@@ -384,6 +392,10 @@ critique: each # optional: each, or at-ship; left out, the project's
|
|
|
384
392
|
---
|
|
385
393
|
```
|
|
386
394
|
|
|
395
|
+
- **Only these fields.** The front matter holds the fields above and nothing
|
|
396
|
+
else; the gate refuses one it does not read, since nothing would check what it
|
|
397
|
+
says. Everything else a spec has to say (where its words come from, a round's
|
|
398
|
+
history, a note for `make`) goes in the prose below it.
|
|
387
399
|
- **`phone` is written first, and in full.** It is the most common screen, and the
|
|
388
400
|
one a derived composition fails on worst.
|
|
389
401
|
- **`motion:` lists every movement, and why it moves.** Each names what moves, its
|
|
@@ -489,10 +501,9 @@ to the spec, never the spec to the decisions.
|
|
|
489
501
|
Step 3b checks the spec against the decisions. Nothing after it checks the spec
|
|
490
502
|
against the owner's words or against the facts it states: `make` builds a
|
|
491
503
|
confirmed spec as written, and `critique` compares the page to the spec, never
|
|
492
|
-
the spec to what is true.
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
cannot catch these, for the same reason a builder cannot review its own page.
|
|
504
|
+
the spec to what is true. An error a confirmed spec carries (a feature the
|
|
505
|
+
product does not have, a step in the wrong order) is built into the page, and the
|
|
506
|
+
owner confirmed it without knowing. The writer cannot catch these, for the same reason a builder cannot review its own page.
|
|
496
507
|
|
|
497
508
|
**Delegate to a subagent.** Give it the spec, `DECISIONS.md`, the owner's messages
|
|
498
509
|
from this conversation, and read access to the project. Not your reasoning, and
|
|
@@ -501,7 +512,7 @@ not your summary of what the owner meant. It writes
|
|
|
501
512
|
|
|
502
513
|
```json
|
|
503
514
|
{
|
|
504
|
-
"spec": "
|
|
515
|
+
"spec": "`{{scripts_path}} checksum <name>` prints it: the spec with its confirmed: and mockup: lines emptied",
|
|
505
516
|
"quotes": [
|
|
506
517
|
{ "quote": "Only where the steps differ by path", "said": "the owner, this conversation", "holds": true }
|
|
507
518
|
],
|
|
@@ -538,8 +549,8 @@ reader the earlier record and the spec's diff since it. A quotation or fact whos
|
|
|
538
549
|
line did not change, and whose source has not changed since (`git diff` on that
|
|
539
550
|
file), carries over as recorded; the reader checks the changed lines, the new
|
|
540
551
|
ones, and any fact whose source moved. It still writes the whole record, with
|
|
541
|
-
the new checksum.
|
|
542
|
-
|
|
552
|
+
the new checksum. Opening every source again on each round costs the most on
|
|
553
|
+
exactly the lines nobody touched. **If you cannot
|
|
543
554
|
delegate, write the record yourself, with `"reader": "the writer"` in it, and say
|
|
544
555
|
in the confirmation message that nobody else checked the spec.** That is an
|
|
545
556
|
honest gap the owner can close by reading more closely; a check you ran on your
|
|
@@ -584,9 +595,9 @@ they confirm.
|
|
|
584
595
|
renames a region at any size, the approved drawing no longer shows the page: set
|
|
585
596
|
`mockup: pending`, and `{{command_prefix}}mockup` redraws it for the owner. The gate
|
|
586
597
|
checks it for a drawing in frames: while `mockup: approved`, each region the spec lists must be labelled in
|
|
587
|
-
its size's frame of the drawing at `mockup_at:`.
|
|
588
|
-
|
|
589
|
-
|
|
598
|
+
its size's frame of the drawing at `mockup_at:`. Otherwise a spec can go through
|
|
599
|
+
several confirmed rounds after its drawing was approved and still say `approved`
|
|
600
|
+
over a drawing of none of them.
|
|
590
601
|
|
|
591
602
|
## mockup
|
|
592
603
|
|
|
@@ -828,9 +839,9 @@ confirmed again.
|
|
|
828
839
|
Record where the approved drawing is in `mockup_at:` — the file path, or the
|
|
829
840
|
Figma or Stitch link. Only their own response counts; your summary of the
|
|
830
841
|
drawing, or no objection, does not. **A condition they attach goes into the
|
|
831
|
-
spec first**, in their words, on the lines it governs
|
|
832
|
-
|
|
833
|
-
|
|
842
|
+
spec first**, in their words, on the lines it governs. An approval "with three
|
|
843
|
+
columns at 1280 and wider" whose condition lives only in the conversation is
|
|
844
|
+
not what `make` builds: it reads the spec, and may put the switch anywhere.
|
|
834
845
|
- The user says to skip it → `mockup: skipped — "<their words>"`. For a change
|
|
835
846
|
small enough that drawing it costs more than building it, that is a reasonable
|
|
836
847
|
call; it is still theirs to make.
|
|
@@ -887,10 +898,9 @@ and `make` is where decisions are carried out, not taken. When the build shows a
|
|
|
887
898
|
decision is wrong, missing or in conflict with the spec, stop and say so: the owner
|
|
888
899
|
changes it through `{{command_prefix}}decide`, or `{{command_prefix}}tweak` for a
|
|
889
900
|
small change to a built page. A note that a decision has been carried out belongs in
|
|
890
|
-
the spec, under `deviations:` or its as-built notes, not in the decision.
|
|
891
|
-
|
|
892
|
-
|
|
893
|
-
written. The gate stops a `make` session that changed `DECISIONS.md`.
|
|
901
|
+
the spec, under `deviations:` or its as-built notes, not in the decision. A build
|
|
902
|
+
that adds a decision, or rewrites one to match what it just built, leaves the next
|
|
903
|
+
critique judging the page against text the build wrote. The gate stops a `make` session that changed `DECISIONS.md`.
|
|
894
904
|
|
|
895
905
|
Build V1 only. Nothing in `later:`, however little extra it looks.
|
|
896
906
|
|
|
@@ -1086,11 +1096,10 @@ refuses a `ruled` with no ruling or with one the file does not hold. A ruled
|
|
|
1086
1096
|
verdict is reported, and counted apart (`ruled=`); it is not a finding, and it
|
|
1087
1097
|
does not go back to `make`, which could only leave it as it is. **Put the field
|
|
1088
1098
|
in each arm's brief, with its shape:** `{ "id": …, "verdict": "ruled", "ruling":
|
|
1089
|
-
"<the decision's heading>", "reason": … }`.
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1093
|
-
in prose: every count was inflated, and the real findings were harder to see.
|
|
1099
|
+
"<the decision's heading>", "reason": … }`. An arm that names the decision only
|
|
1100
|
+
in `reason` has every ruled verdict refused by `verdicts`, and the parent is left
|
|
1101
|
+
to write the field into a file it is not to edit. Rulings counted as findings
|
|
1102
|
+
inflate every count, and the real findings are harder to see.
|
|
1094
1103
|
A rule the page breaks with no decision behind it is a `finding`, however sure
|
|
1095
1104
|
you are the owner would agree.
|
|
1096
1105
|
|
|
@@ -1168,11 +1177,17 @@ Each reader arm writes its own file. The arm reports back only that it wrote it.
|
|
|
1168
1177
|
**`differences` holds what no rule names:** the page against its spec (step 3),
|
|
1169
1178
|
or against a source it quotes or teaches. Each counts as a finding. Never carry
|
|
1170
1179
|
one as a verdict under an id you made up: `verdicts` refuses an id the corpus
|
|
1171
|
-
does not hold, and
|
|
1172
|
-
(`page-vs-corpus-1`), which the parent then had to move by hand. `ruled` is for a
|
|
1180
|
+
does not hold (`page-vs-corpus-1`), and the parent is left to move it by hand. `ruled` is for a
|
|
1173
1181
|
rule a decision overrides; a decision in `decisions.json` is judged `ok`,
|
|
1174
1182
|
`finding` or `n/a`, never ruled.
|
|
1175
1183
|
|
|
1184
|
+
**One problem, one entry.** A difference goes under `differences` only when no
|
|
1185
|
+
rule and no decision holds it. A stale figure is `I-148`'s finding; a page
|
|
1186
|
+
paraphrasing a source the owner decided it quotes is that decision's. File it
|
|
1187
|
+
there and nowhere else, and let the two arms' entries agree rather than repeat.
|
|
1188
|
+
One stale number filed as a rule's finding, a decision's, and a difference in
|
|
1189
|
+
each arm is four findings for one problem, and every count built on them is wrong.
|
|
1190
|
+
|
|
1176
1191
|
**And the project's own decisions, one verdict each**, in
|
|
1177
1192
|
`.jig/critique/<surface>/decisions.json`:
|
|
1178
1193
|
|
|
@@ -1328,9 +1343,8 @@ control or claim the page carries that no line of the spec asks for is a
|
|
|
1328
1343
|
difference too, however accurate it is. The owner confirmed the spec, not the
|
|
1329
1344
|
page; content the spec never held is content they never approved, and every
|
|
1330
1345
|
later tweak and critique works from a spec that no longer says what is there.
|
|
1331
|
-
|
|
1332
|
-
|
|
1333
|
-
no rule. Report it among the findings as a difference from the spec, naming the
|
|
1346
|
+
An accurate paragraph with no spec line and no deviation breaks no rule, so a
|
|
1347
|
+
critique that reads only the spec against the page sees it and files nothing. Report it among the findings as a difference from the spec, naming the
|
|
1334
1348
|
content and where it is: the fix is a tweak that writes it into the spec for the
|
|
1335
1349
|
owner to confirm, or removes it.
|
|
1336
1350
|
|
|
@@ -1462,10 +1476,10 @@ its own line, `B-106`), there is nothing to decide; do not invent a decision.
|
|
|
1462
1476
|
|
|
1463
1477
|
The owner's words are the ones tweak.json records as `change`. A `**Why:**` you
|
|
1464
1478
|
add quotes them, in quotation marks, and nothing else; what you read into them,
|
|
1465
|
-
or into a screenshot the owner pointed at, goes under `**Why (inferred):**`.
|
|
1466
|
-
|
|
1467
|
-
|
|
1468
|
-
|
|
1479
|
+
or into a screenshot the owner pointed at, goes under `**Why (inferred):**`. A
|
|
1480
|
+
tweak shown a picture that writes an exception "given directly by the owner … by
|
|
1481
|
+
reference rather than words" records a ruling nobody gave, and every later
|
|
1482
|
+
critique judges the page by it. The gate stops a
|
|
1469
1483
|
tweak whose new `**Why:**` quotes words tweak.json does not hold.
|
|
1470
1484
|
|
|
1471
1485
|
**A decision you record or amend covers the whole page, not the one place it
|
|
@@ -1473,9 +1487,9 @@ was raised.** The owner rules on an instance ("keep this apostrophe curly") and
|
|
|
1473
1487
|
the decision states a kind ("every apostrophe, curly"). Before you build, look
|
|
1474
1488
|
through the page, and the chrome it shares, for every other instance of that
|
|
1475
1489
|
kind, and bring each one in line in the same change; name them in your report.
|
|
1476
|
-
|
|
1477
|
-
|
|
1478
|
-
|
|
1490
|
+
A tweak that records "every apostrophe and quotation mark curly" and fixes only
|
|
1491
|
+
the one the critique named leaves the rest of the page's straight marks for the
|
|
1492
|
+
next critique to find.
|
|
1479
1493
|
|
|
1480
1494
|
### 2. Bring the spec in line, if it disagrees
|
|
1481
1495
|
|
|
@@ -1547,7 +1561,9 @@ Build the project the way it ships, then run `{{scripts_path}} ship`. It runs
|
|
|
1547
1561
|
`check --all --ci` and `seo`, and reads every confirmed spec's critique: a page
|
|
1548
1562
|
is owed a critique when it has none, when its page changed after it was judged,
|
|
1549
1563
|
when a tweak deferred its re-judge, when its verdicts are incomplete, or when a
|
|
1550
|
-
finding stands that the owner has not ruled on.
|
|
1564
|
+
finding stands that the owner has not ruled on. A page that is as judged but
|
|
1565
|
+
whose stylesheets or scripts changed is owed only a re-probe
|
|
1566
|
+
(`{{scripts_path}} verdicts <page> --reprobe`), not a critique. It prints each page's state and
|
|
1551
1567
|
a `JIG_SHIP:` line, and exits non-zero until the project is ready. A spec that
|
|
1552
1568
|
is not confirmed yet is in progress and not held against the ship. Nor is a spec
|
|
1553
1569
|
another has replaced: `superseded_by: <spec>` in its front matter leaves its page
|
|
@@ -1617,14 +1633,15 @@ review, never by the builder editing the last one.
|
|
|
1617
1633
|
When a `critique` or `tweak` session stops, the gate records its verdicts in
|
|
1618
1634
|
`.jig/critique/<surface>/verdicts.lock`. That happens after you have committed, so
|
|
1619
1635
|
if your verdicts are committed it stops you once more to commit the lock on its
|
|
1620
|
-
own; the next stop passes.
|
|
1636
|
+
own; the next stop passes. The same goes for a page's probe files: when the page
|
|
1637
|
+
changed since they were taken, the gate renders it again as you stop, and if
|
|
1638
|
+
your work is committed it stops you once to commit them on their own.
|
|
1621
1639
|
|
|
1622
1640
|
**The lock is the gate's to write, never yours.** When the gate is wrong (it
|
|
1623
1641
|
misreads the session, or asks for something the procedure does not), say what it
|
|
1624
|
-
got wrong, leave the lock as it is, and report the work as held by the gate.
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
agent can write is still a record of nothing.
|
|
1642
|
+
got wrong, leave the lock as it is, and report the work as held by the gate. A
|
|
1643
|
+
lock computed by hand may even be right, and a lock an agent can write is still a
|
|
1644
|
+
record of nothing.
|
|
1628
1645
|
|
|
1629
1646
|
It judges the critiques this session touched: any with a file changed since the
|
|
1630
1647
|
session began, and the current spec's surface when you ran `critique`. Another
|
|
@@ -1645,6 +1662,14 @@ It exists because every "run check" and "run verdicts" step in these procedures
|
|
|
1645
1662
|
skipped in a live run, and pages that did not render their styles were reported
|
|
1646
1663
|
clean.
|
|
1647
1664
|
|
|
1665
|
+
## checksum
|
|
1666
|
+
|
|
1667
|
+
Run `{{scripts_path}} checksum <spec>`, passing the argument through, and report the
|
|
1668
|
+
value it prints. It is the `spec` field of `.jig/specs/<name>.checked.json`: the
|
|
1669
|
+
spec's checksum with its `confirmed:` and `mockup:` lines emptied, which the owner's
|
|
1670
|
+
answer sets after the check. Never compute it yourself: a hand-computed value is
|
|
1671
|
+
easily wrong, and a wrong one reads as a spec that changed after its check.
|
|
1672
|
+
|
|
1648
1673
|
## verdicts
|
|
1649
1674
|
|
|
1650
1675
|
Run `{{scripts_path}} verdicts <surface>`, passing the argument through, and report its
|
|
@@ -1852,9 +1877,9 @@ weighs it as the team's and applies the rule where the team never would.
|
|
|
1852
1877
|
|
|
1853
1878
|
What you add to explain a reason, work out from it, or carry over from what the
|
|
1854
1879
|
owner said elsewhere goes in its own paragraph, `**Why (inferred):**`, which says it
|
|
1855
|
-
is yours.
|
|
1856
|
-
|
|
1857
|
-
|
|
1880
|
+
is yours. A reason that reads "given directly by the owner" and goes on in the
|
|
1881
|
+
agent's own sentences leaves a later agent unable to tell which half to weigh as
|
|
1882
|
+
the team's. The gate checks each decision this session wrote or changed: its
|
|
1858
1883
|
`Why` is quoted, `not given`, or labelled inferred.
|
|
1859
1884
|
|
|
1860
1885
|
**Record what is still open in its own section, at the end:**
|
package/templates/SKILL.md.tmpl
CHANGED
|
@@ -36,6 +36,18 @@ cite the number when you follow or deliberately break one.
|
|
|
36
36
|
`.jig/specs/<name>.checked.json` (its step 4), `{{command_prefix}}mockup`'s
|
|
37
37
|
size by size against the spec (its step 3, rendering every frame). Confirm
|
|
38
38
|
only what you checked yourself, and name to the owner what you could not.
|
|
39
|
+
**Recording the owner's word?** A spec confirmed, a drawing approved or
|
|
40
|
+
skipped, a re-judge left for later, a tweak's change, a decision's reason:
|
|
41
|
+
each is the owner's words, quoted as they said them, and words that say that
|
|
42
|
+
thing. A remark about the layout is not a skip of the mockup; a yes to one
|
|
43
|
+
question is not a yes to the spec. When they have not said it, ask. What you
|
|
44
|
+
read into their words goes under a label that says it is yours
|
|
45
|
+
(`**Why (inferred):**`), never inside their quotation marks.
|
|
46
|
+
**Recording something Jig has no field for?** Write it in prose, below a
|
|
47
|
+
spec's front matter or in the report. Never invent a front-matter key, a
|
|
48
|
+
verdict id or a JSON field for it: nothing reads an invented one, so what it
|
|
49
|
+
says is lost to every check. If it keeps recurring, tell the owner, since
|
|
50
|
+
Jig may be missing a field.
|
|
39
51
|
**Building a screen rather than a single component?** Read `L-01 · Layout
|
|
40
52
|
method` in `{{rules_path}}/03-patterns.md` and run its five steps before
|
|
41
53
|
writing any markup. It is a procedure, not a component, so step 4 never
|
|
@@ -34,6 +34,11 @@
|
|
|
34
34
|
"argumentHint": "",
|
|
35
35
|
"status": "available"
|
|
36
36
|
},
|
|
37
|
+
"checksum": {
|
|
38
|
+
"description": "Print a spec's checksum: the value its `.checked.json` records as `spec`, so a spec's reader never computes it by hand.",
|
|
39
|
+
"argumentHint": "<spec>",
|
|
40
|
+
"status": "available"
|
|
41
|
+
},
|
|
37
42
|
"verdicts": {
|
|
38
43
|
"description": "Verify a critique's verdict files: every rule in each pass judged once, no id that does not exist, no rule in the wrong arm, rendered only with a screenshot. Computes the counts the critique reports, so the agent never writes them.",
|
|
39
44
|
"argumentHint": "<surface>",
|