jig-ui 0.21.0 → 0.23.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.
@@ -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`. Run the
9
+ **CLI-backed** — `install`, `update`, `init`, `check`, `explain`, `verdicts`, `gate`, `probe`, `seo`, `ship`. 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
@@ -25,10 +25,14 @@ decide project-wide decisions, and the reason for each once per project
25
25
  spec what exactly is being built: its smallest useful version, at every screen size
26
26
  mockup low-fidelity design of that spec, reviewed before any code
27
27
  make high-fidelity: the actual page or feature, built from the spec & mockup
28
- critique scrutinises what was built against the rules, its spec & mockup
28
+ critique scrutinises what was built against the rules, its spec & mockup;
29
+ now, or later: a page judged as it stands gets the same verdicts
29
30
 
30
31
  tweak a small change the approved mockup does not show: decided if it is a
31
32
  decision, specced, built, and re-judged where it could matter
33
+
34
+ ship everything Jig checks, with nothing optional: critiques every page
35
+ that owes one, and says what Jig does not check
32
36
  ```
33
37
 
34
38
  ## init
@@ -50,10 +54,16 @@ the answer and the CLI is not. So, first:
50
54
  `editorial` for first-visit content, `product` for the signed-in app,
51
55
  `operator` for dense daily tools. State the mapping in one line and let them
52
56
  correct it.
53
- 3. **Write `jig.config.json`** with those surfaces before running anything.
54
- `init` reads an existing config and honours it — writing one mode file per
55
- declared mode — so this is how a decision reaches the tokens.
56
- 4. **Then run the command.**
57
+ 3. **Ask when pages should be critiqued**: after every build, left for
58
+ `{{command_prefix}}ship`, or decided page by page. Page by page is the default
59
+ and writes nothing; each spec then asks. The other two go in as
60
+ `"critique": "each"` or `"critique": "at-ship"`. It is how the owner works,
61
+ so it is asked here, not in `decide`.
62
+ 4. **Write `jig.config.json`** with those surfaces, and the critique answer,
63
+ before running anything. `init` reads an existing config and honours it —
64
+ writing one mode file per declared mode — so this is how a decision reaches
65
+ the tokens.
66
+ 5. **Then run the command.**
57
67
 
58
68
  Where there is genuinely one surface, say so and move on; the point is that the
59
69
  mode was chosen rather than defaulted into.
@@ -289,6 +299,7 @@ the example shows the shape. Say it is an example, not a suggestion.
289
299
  > plan goes straight to sign-up. Nothing on this page may ask for a sales
290
300
  > call."*
291
301
 
302
+
292
303
  **Ask about the phone by name.** What does the reader see first on a phone, and
293
304
  what moves, stacks, or goes behind a control?
294
305
  > *For example: "the plans come first on the phone" — that is the answer this
@@ -297,6 +308,16 @@ what moves, stacks, or goes behind a control?
297
308
  describes the wide screen, the phone composition will be derived from it rather
298
309
  than designed — and a derived phone composition is a squeezed desktop.
299
310
 
311
+ **Last, ask when this page is critiqued: after each build, or left for
312
+ `ship`?** It is the one question about how the owner works rather than what the
313
+ page is, so it comes after all of them. Skip it only where the owner has already
314
+ said, for this page or in asking for the spec. Where the page sets up what later
315
+ pages reuse (a header, a card, a layout), say why now is worth it; otherwise
316
+ offer the project's default from `{{config_file}}`, or "each" where it has none.
317
+ Write the answer as `critique: each` or `critique: at-ship`.
318
+ > *For example: "each: every page has this header, so a finding in it is fixed
319
+ > once, now, not in ten pages later."*
320
+
300
321
  ### 2. Run `L-01`
301
322
 
302
323
  Read `L-01 · Layout method` in `{{rules_path}}/03-patterns.md` and run its five
@@ -348,19 +369,30 @@ sizes: # phone first. Each size is a whole composition, not
348
369
  why: "content is capped at 1200px, so 1600 adds margin and nothing else"
349
370
  switches: none # the recorded switches (--breakpoint-*, T-04) this page crosses, by name; none if it crosses none. Absent, the mockup draws either side of every one
350
371
  states: [default, loading, error, success]
372
+ motion: # every movement the page has, or `none`: what moves, on its trigger; tells what
373
+ - deleted row: rows below slide into the gap, on delete; tells where the list went
351
374
  decisions: [The Engineer Reads First] # every DECISIONS.md entry this screen implements, by name
352
375
  later: [social sign-in, remember this device] # cut from V1, by name — the next specs start here
353
376
  indexable: true # from the mode — editorial yes, product/operator no. Say why when you override it.
354
377
  title: "Pricing — Hoistline" # ≤ 60 characters, the search result's first line
355
378
  description: "Three plans, every price visible. No sales call." # ≤ 155
356
- mockup: pending # `mockup` sets approved or skipped, from the user's own words
379
+ mockup: pending # approved or skipped, quoting the user: approved by `mockup`, skipped by whichever command they said it to
357
380
  mockup_at: # where the approved drawing is: a .jig/mockups path, or a Figma or Stitch link
358
381
  deviations: [] # `make` writes here; `spec` leaves it empty
382
+ critique: each # optional: each, or at-ship; left out, the project's default in {{config_file}}
383
+ # superseded_by: reference.spec.md # only when another spec replaces this one; `ship` then leaves this page to that spec's critique
359
384
  ---
360
385
  ```
361
386
 
362
387
  - **`phone` is written first, and in full.** It is the most common screen, and the
363
388
  one a derived composition fails on worst.
389
+ - **`motion:` lists every movement, and why it moves.** Each names what moves, its
390
+ trigger, and what it tells the reader. The trigger is the user's input, a state
391
+ change, arrival (once per visitor, editorial only, `G-42`) or ambient (editorial
392
+ only, `P-13`). A movement that cannot say what it tells the reader is cut here,
393
+ before it is built. Write it from the composition; it is not a question for the
394
+ owner, who reads it on the sheet beside `states:`. A page with nothing moving
395
+ says `none`.
364
396
  - **`indexable:`, `title:` and `description:` are copy, decided here.** The mode
365
397
  sets the default — `editorial` is first-visit content and is indexable,
366
398
  `product` and `operator` are what somebody reaches after signing in and are
@@ -452,9 +484,93 @@ to the spec, never the spec to the decisions.
452
484
  say in the confirmation message which fields those are, so the user can decide
453
485
  them instead.
454
486
 
487
+ ### 3c. Have it checked by a reader who did not write it
488
+
489
+ Step 3b checks the spec against the decisions. Nothing after it checks the spec
490
+ against the owner's words or against the facts it states: `make` builds a
491
+ confirmed spec as written, and `critique` compares the page to the spec, never
492
+ the spec to what is true. On jig-site a confirmed spec for a docs chapter carried
493
+ seven errors to the built page, among them a procedure Jig does not have and a
494
+ lock written at the wrong moment, and the owner had confirmed it. The writer
495
+ cannot catch these, for the same reason a builder cannot review its own page.
496
+
497
+ **Delegate to a subagent.** Give it the spec, `DECISIONS.md`, the owner's messages
498
+ from this conversation, and read access to the project. Not your reasoning, and
499
+ not your summary of what the owner meant. It writes
500
+ `.jig/specs/<name>.checked.json`:
501
+
502
+ ```json
503
+ {
504
+ "spec": "sha256 of the spec file with its confirmed: line removed",
505
+ "quotes": [
506
+ { "quote": "Only where the steps differ by path", "said": "the owner, this conversation", "holds": true }
507
+ ],
508
+ "facts": [
509
+ { "claim": "the gate records the verdicts when a critique or tweak stops", "source": "templates/COMMAND.md.tmpl:1360", "holds": false, "note": "the spec says only after the findings are fixed" },
510
+ { "claim": "Stitch needs an API key", "source": "https://stitch.withgoogle.com", "holds": "unchecked", "note": "no network access in this session" }
511
+ ],
512
+ "copy": ["Before you start"],
513
+ "conditions": [{ "owner": "three columns from 1280 up", "spec": "desktop: three columns at 1280 and wider" }],
514
+ "open": ["density of the chapter list: unspecified, make chooses"]
515
+ }
516
+ ```
517
+
518
+ - **`quotes`**: every quotation the spec gives as the owner's, and where the owner
519
+ said it. One the owner's words do not hold is removed from the spec or put back
520
+ as they said it.
521
+ - **`facts`**: every statement the spec makes about how something works (the
522
+ product, an API, an existing page, a file, a tool), with the source the reader
523
+ opened: `path` or `path:line` in the project, or a URL. `holds` is `true`,
524
+ `false` or `"unchecked"`, with a `note` for anything but `true`. A fact that
525
+ does not hold is fixed in the spec before anyone is asked; `"unchecked"` says why
526
+ it could not be opened.
527
+ - **`copy`**: the words the spec writes for the page to show as written:
528
+ headings, labels, sentences.
529
+ - **`conditions`**: each condition the owner gave, beside the spec's line for it.
530
+ - **`open`**: every `unspecified` field and every **Unresolved** item the spec
531
+ touches.
532
+
533
+ Fix what it found, then have the spec checked again: the record is of the spec
534
+ you show, and the gate compares its `spec` checksum to the file.
535
+
536
+ **A second check covers what changed, not the whole spec again.** Give the
537
+ reader the earlier record and the spec's diff since it. A quotation or fact whose
538
+ line did not change, and whose source has not changed since (`git diff` on that
539
+ file), carries over as recorded; the reader checks the changed lines, the new
540
+ ones, and any fact whose source moved. It still writes the whole record, with
541
+ the new checksum. On jig-site each re-check opened every source again, about $10
542
+ a round, to confirm facts on lines nobody had touched. **If you cannot
543
+ delegate, write the record yourself, with `"reader": "the writer"` in it, and say
544
+ in the confirmation message that nobody else checked the spec.** That is an
545
+ honest gap the owner can close by reading more closely; a check you ran on your
546
+ own words and reported as independent is not.
547
+
455
548
  ### 4. Get it confirmed
456
549
 
457
- Show the spec and ask the user to confirm it. Then **stop**.
550
+ Show the spec, and with it the sheet the owner checks it by, from
551
+ `<name>.checked.json`:
552
+
553
+ - **Your words:** each quotation given as theirs, and where they said it.
554
+ - **Facts:** each claim and its source, the ones that could not be checked
555
+ first.
556
+ - **Copy the page will show as written.**
557
+ - **What moves:** each line of `motion:`, with its trigger and what it tells
558
+ the reader, or that nothing moves.
559
+ - **Your conditions**, beside the lines that carry them.
560
+ - **Left for you:** the `open` items, which they can decide now.
561
+
562
+ The owner confirms a spec by checking it, and the sheet is what makes that a few
563
+ minutes' work rather than a reread. Ask them to confirm it. Then **stop**.
564
+
565
+ If, in confirming, they also say to skip the mockup, record that too:
566
+ `mockup: skipped — "<their words>"`.
567
+
568
+ **Checking a spec for the owner.** When the owner asks an agent to check a spec
569
+ and confirm it on their behalf, that agent works from the same sheet and confirms
570
+ only what it checked itself: it opens every source marked `"unchecked"` and
571
+ every one it doubts, reads the copy as the person arriving would, and holds each
572
+ condition to the owner's own words. Anything it could not check it names to the
573
+ owner instead of confirming.
458
574
 
459
575
  `confirmed: true` records that **the user said so in their own response**. You
460
576
  may not set it on their behalf, and you may not treat your own summary,
@@ -673,6 +789,27 @@ Then ask **structural** questions, not whether they like it: is the most importa
673
789
  thing the first thing seen at each size? Does anything belong in a different group?
674
790
  Is anything here that V1 does not need?
675
791
 
792
+ **Give them the sheet they check it by.** The drawing is the confirmed spec,
793
+ drawn, so what the owner checks first is that it matches. The gate has checked
794
+ that each region is labelled; whether each is drawn the way the spec says is
795
+ theirs to see. Size by size, set the spec's line beside what the frame shows:
796
+
797
+ - the regions in the spec's order, what comes first, what is grouped, where each
798
+ sits;
799
+ - `nav:` for that size, and the navigation drawn;
800
+ - each state in `states:` that changes the layout, and where it is drawn;
801
+ - anything the spec says a part does that a still drawing cannot show, quoted
802
+ from the spec. Name only what the spec says: a behaviour it does not mention is
803
+ not yours to raise here, and one you add is a spec change;
804
+ - the owner's conditions from the spec, beside the lines that carry them;
805
+ - and what the drawing leaves out on purpose: `later:`, and colour, type and
806
+ spacing, which the tokens settle.
807
+
808
+ **Checking a mockup for the owner.** When the owner asks an agent to check the
809
+ drawing and approve it on their behalf, that agent renders every frame, compares
810
+ each with its line in the spec, and approves only what it checked itself. What
811
+ it could not check, it names to the owner instead of approving.
812
+
676
813
  ### 4. Every change goes into the spec first
677
814
 
678
815
  When the review moves, adds, cuts or regroups anything, **edit the spec**, then
@@ -686,13 +823,20 @@ confirmed again.
686
823
 
687
824
  ### 5. Record the outcome in the user's words
688
825
 
689
- - The user approves → set `mockup: approved` in the spec, and `confirmed: true` if
690
- review changed it. Record where the approved drawing is in `mockup_at:` — the
691
- file path, or the Figma or Stitch link. Only their own response counts; your summary of the drawing,
692
- or no objection, does not.
693
- - The user says to skip it → `mockup: skipped — <their reason>`. For a change small
694
- enough that drawing it costs more than building it, that is a reasonable call; it
695
- is still theirs to make.
826
+ - The user approves → set `mockup: approved — "<their words>"` in the spec,
827
+ quoting the reply that approved it, and `confirmed: true` if review changed it.
828
+ Record where the approved drawing is in `mockup_at:` — the file path, or the
829
+ Figma or Stitch link. Only their own response counts; your summary of the
830
+ drawing, or no objection, does not. **A condition they attach goes into the
831
+ spec first**, in their words, on the lines it governs: on jig-site the owner
832
+ approved with "three columns at 1280 and wider, inside the page margins", the
833
+ condition lived only in the conversation, and `make` moved the switch to 1290.
834
+ - The user says to skip it → `mockup: skipped — "<their words>"`. For a change
835
+ small enough that drawing it costs more than building it, that is a reasonable
836
+ call; it is still theirs to make.
837
+
838
+ With the Stop hook, the gate reads the quotation after `approved` or `skipped` and
839
+ holds it to what the owner said in this session.
696
840
 
697
841
  Then stop. The next step is `{{command_prefix}}make`.
698
842
 
@@ -713,9 +857,12 @@ each finding, run the finish again, and then `critique` runs again. See step 5 o
713
857
  prevent.
714
858
  - `confirmed: false` → the spec exists but nobody has agreed to it. Ask for
715
859
  confirmation and stop.
716
- - `mockup: pending` → the feature has not been looked at. Run
717
- `{{command_prefix}}mockup`, or ask the user whether to skip it. Do not decide to
718
- skip it yourself.
860
+ - `mockup: pending` → nobody has said whether to draw it. Unless the user already
861
+ said to skip it in asking for `make`, ask once: draw it with
862
+ `{{command_prefix}}mockup`, or skip it? If they skip it, write
863
+ `mockup: skipped — "<their words>"` in the spec and build from the spec alone.
864
+ Do not decide to skip it yourself, and do not finish with the spec still
865
+ pending: the gate holds a `make` that does.
719
866
 
720
867
  ### Build
721
868
 
@@ -769,6 +916,10 @@ indexable carries `noindex` instead, from its own metadata rather than from
769
916
  Then the ordinary rules apply: tokens by semantic name, the relevant
770
917
  `03-patterns.md` section for each component, `05-copy.md` for every string.
771
918
 
919
+ **Build the motion `motion:` lists, and no other.** A movement the spec does not
920
+ list is a deviation, recorded below like any other. A spec with no `motion:`
921
+ (one confirmed before it existed) leaves motion to the `G-` rules alone.
922
+
772
923
  ### Record what you changed
773
924
 
774
925
  Building reveals that a spec was wrong somewhere — that is normal and expected.
@@ -820,7 +971,16 @@ and was never looked at on a phone has satisfied a third of its spec. Then run t
820
971
  self-check at the end of `{{rules_path}}/00-anti-patterns.md`.
821
972
 
822
973
  Report the `JIG_CHECK:` line, the table, and any new deviations. Then suggest
823
- `{{command_prefix}}critique`.
974
+ `{{command_prefix}}critique`, now or later: the owner decides when. A page judged
975
+ once, as it stands, gets the verdicts it would have got straight after this build,
976
+ so a critique can wait for a batch of pages, or for `{{command_prefix}}ship`,
977
+ which will not pass until every page is judged. Where the spec says
978
+ `critique: at-ship`, or it is silent and `{{config_file}}` says
979
+ `"critique": "at-ship"`, the owner has already said to wait; do not ask. Where the
980
+ spec says `critique: each`, suggest it now. One
981
+ thing to say when it applies: if this page sets up something later pages will
982
+ reuse (a header, a card, a layout), a finding in it found late is fixed in every
983
+ page built on it, so its critique is worth running now.
824
984
 
825
985
  ## critique
826
986
 
@@ -924,7 +1084,11 @@ owner ruled icon-only, a menu the owner put at every phone width. The verdict
924
1084
  names that decision in `ruling`, exactly as its heading reads, and `verdicts`
925
1085
  refuses a `ruled` with no ruling or with one the file does not hold. A ruled
926
1086
  verdict is reported, and counted apart (`ruled=`); it is not a finding, and it
927
- does not go back to `make`, which could only leave it as it is. On jig-site a
1087
+ does not go back to `make`, which could only leave it as it is. **Put the field
1088
+ in each arm's brief, with its shape:** `{ "id": …, "verdict": "ruled", "ruling":
1089
+ "<the decision's heading>", "reason": … }`. On jig-site an arm wrote four ruled
1090
+ verdicts that named the decision only in `reason`, `verdicts` refused all four,
1091
+ and the parent had to write the field into a file it was not to edit. On jig-site a
928
1092
  header critique counted 15 findings, five of them rulings labelled "owner-ruled"
929
1093
  in prose: every count was inflated, and the real findings were harder to see.
930
1094
  A rule the page breaks with no decision behind it is a `finding`, however sure
@@ -993,11 +1157,21 @@ Each reader arm writes its own file. The arm reports back only that it wrote it.
993
1157
  { "id": "P-14", "verdict": "finding", "reason": "menu button at 360 does not open; aria-expanded never set" },
994
1158
  { "id": "A-60", "verdict": "n/a", "reason": "A-60 is about competing icons; this page has none" },
995
1159
  { "id": "E-51", "verdict": "ruled", "ruling": "The theme toggle is icon-only", "reason": "the toggle shows only a sun or a moon; the owner ruled it icon-only" }
1160
+ ],
1161
+ "differences": [
1162
+ { "what": "the checklist gives nine checks", "where": "src/pages/guide.astro:245", "against": "README.md, 'Before you confirm a spec': ten" }
996
1163
  ]
997
1164
  }
998
1165
  ```
999
1166
 
1000
1167
  `screen.json` carries `rendered` and `artefacts`; `code.json` needs only `verdicts`.
1168
+ **`differences` holds what no rule names:** the page against its spec (step 3),
1169
+ or against a source it quotes or teaches. Each counts as a finding. Never carry
1170
+ one as a verdict under an id you made up: `verdicts` refuses an id the corpus
1171
+ does not hold, and on jig-site both arms of one critique invented one
1172
+ (`page-vs-corpus-1`), which the parent then had to move by hand. `ruled` is for a
1173
+ rule a decision overrides; a decision in `decisions.json` is judged `ok`,
1174
+ `finding` or `n/a`, never ruled.
1001
1175
 
1002
1176
  **And the project's own decisions, one verdict each**, in
1003
1177
  `.jig/critique/<surface>/decisions.json`:
@@ -1144,6 +1318,26 @@ grouped with what, what stacks or moves on the phone. Not the colour, type or
1144
1318
  polish: the mockup is grayscale and low-fidelity on purpose, so its appearance is
1145
1319
  not a target.
1146
1320
 
1321
+ **Motion, against `motion:`.** Each movement on the page is judged against its
1322
+ line: one the spec does not list is a `G-42` finding, and one that tells the
1323
+ reader something other than its line says is a finding under the rule it
1324
+ breaks. With no `motion:` in the spec, the `G-` rules alone judge it.
1325
+
1326
+ **Then the other way: the page against the spec.** Each section, paragraph,
1327
+ control or claim the page carries that no line of the spec asks for is a
1328
+ difference too, however accurate it is. The owner confirmed the spec, not the
1329
+ page; content the spec never held is content they never approved, and every
1330
+ later tweak and critique works from a spec that no longer says what is there.
1331
+ On jig-site a chapter carried an accurate paragraph with no spec line and no
1332
+ deviation, and two critiques in a row saw it and filed nothing, because it broke
1333
+ no rule. Report it among the findings as a difference from the spec, naming the
1334
+ content and where it is: the fix is a tweak that writes it into the spec for the
1335
+ owner to confirm, or removes it.
1336
+
1337
+ **Say in the report what each direction found**, "none" included: a report that
1338
+ does not mention the page-against-spec pass cannot be told apart from one that
1339
+ skipped it.
1340
+
1147
1341
  A difference from either is a finding **unless** `deviations:` already explains it
1148
1342
  — that is what the recorded deviation is for. A difference explained by neither is
1149
1343
  the more serious finding, because it means the spec has quietly stopped describing
@@ -1246,7 +1440,9 @@ because the drawing stays true, and no full critique, because nothing else moved
1246
1440
  a page being made, not changed. Run `{{command_prefix}}spec`, `mockup` and
1247
1441
  `make`.
1248
1442
  - **No critique record for the page yet** (`.jig/critique/<surface>/`) → nothing
1249
- has been judged, so nothing can be re-judged. Run `{{command_prefix}}critique`.
1443
+ has been judged, so nothing can be re-judged. Run `{{command_prefix}}critique`,
1444
+ unless the re-judge is deferred (step 4): then the page's first critique judges
1445
+ it whole.
1250
1446
  - **The change adds, removes, reorders or regroups a region, changes the
1251
1447
  navigation at any size, or would make the drawing wrong** → it is not a tweak.
1252
1448
  Say so and name the route: `spec`, then `mockup`, then `make`. The gate checks
@@ -1272,6 +1468,15 @@ jig-site a tweak shown a picture of a copy button wrote an exception to `E-51`
1272
1468
  gave, which every later critique would have judged the page by. The gate stops a
1273
1469
  tweak whose new `**Why:**` quotes words tweak.json does not hold.
1274
1470
 
1471
+ **A decision you record or amend covers the whole page, not the one place it
1472
+ was raised.** The owner rules on an instance ("keep this apostrophe curly") and
1473
+ the decision states a kind ("every apostrophe, curly"). Before you build, look
1474
+ through the page, and the chrome it shares, for every other instance of that
1475
+ kind, and bring each one in line in the same change; name them in your report.
1476
+ On jig-site a tweak recorded "every apostrophe and quotation mark curly" and
1477
+ fixed the one apostrophe the critique had named; three straight ones and a pair
1478
+ of straight quotation marks on the same page survived to the next critique.
1479
+
1275
1480
  ### 2. Bring the spec in line, if it disagrees
1276
1481
 
1277
1482
  If the spec says something the change contradicts, or the page will no longer
@@ -1313,12 +1518,64 @@ verdict and reason, adding `"tweak": "<at>"`. It changes nothing else. Then run
1313
1518
  The gate holds both ends: it refuses a tweak that changed a verdict it did not
1314
1519
  name, and one that named a verdict it did not re-judge.
1315
1520
 
1521
+ **The re-judge can wait**, when the owner says so. Write their words in
1522
+ tweak.json as `"deferred": "<what they said>"`, or `"deferred": true` where the
1523
+ page's spec says `critique: at-ship` (or, the spec silent, `{{config_file}}`
1524
+ does); keep `ids` named for whoever
1525
+ judges it, and leave the verdicts alone. The page then owes a critique, and
1526
+ `{{command_prefix}}ship` will not pass until one has judged it. Never defer it
1527
+ on your own account: the gate refuses a deferral nobody gave.
1528
+
1316
1529
  ### Finish
1317
1530
 
1318
1531
  Report what changed, in the owner's words; the decision and spec lines you
1319
1532
  touched, if any; each re-judged verdict and what it says now; and the
1320
1533
  `JIG_CHECK` line. A re-judged verdict that is a finding goes to the owner: it is
1321
- fixed by another tweak, or by `make` if it needs more.
1534
+ fixed by another tweak, or by `make` if it needs more. A deferred re-judge is
1535
+ reported as deferred, with the ids it will cover.
1536
+
1537
+ ## ship
1538
+
1539
+ **Get the project ready to ship, by everything Jig checks.** `critique` can wait
1540
+ while pages are built and tweaked; here nothing is optional. `ship` does not
1541
+ deploy anything, and it is not a security review: Jig has no rules for security,
1542
+ performance or what a real screen reader does, and the report says so every time.
1543
+
1544
+ ### 1. Build, then ask the CLI what is owed
1545
+
1546
+ Build the project the way it ships, then run `{{scripts_path}} ship`. It runs
1547
+ `check --all --ci` and `seo`, and reads every confirmed spec's critique: a page
1548
+ is owed a critique when it has none, when its page changed after it was judged,
1549
+ 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. It prints each page's state and
1551
+ a `JIG_SHIP:` line, and exits non-zero until the project is ready. A spec that
1552
+ is not confirmed yet is in progress and not held against the ship. Nor is a spec
1553
+ another has replaced: `superseded_by: <spec>` in its front matter leaves its page
1554
+ to that spec's critique, and `ship` checks the spec it names exists. Write that
1555
+ line, in those words, when a spec is replaced; a marker of your own is not read.
1556
+
1557
+ ### 2. Clear what it names
1558
+
1559
+ - **Mechanical or `seo` errors** → fix them as `make` would, and run `check`
1560
+ again.
1561
+ - **A page owed a critique** → run `critique` on it by its own procedure, in
1562
+ full: three arms, each a reader that has not seen this conversation or the
1563
+ build. The readers are independent here as everywhere; that you are
1564
+ orchestrating does not make you one of them.
1565
+ - **Findings** → put them to the owner. Each is fixed (by `make`, or `tweak` for
1566
+ a small one), or the owner rules on it in their own words and the ruling is
1567
+ recorded (`decide`, or `tweak`'s decision step), after which the verdict is
1568
+ `ruled`. Your view that a finding is minor is not a ruling.
1569
+
1570
+ Then build again and run `{{scripts_path}} ship` again. Repeat until it says
1571
+ `ready=yes`.
1572
+
1573
+ ### Finish
1574
+
1575
+ Report the `JIG_SHIP:` line as printed, each page's state, what was fixed and
1576
+ what the owner ruled, and the line the CLI ends with naming what Jig does not
1577
+ check. With the Stop hook, a `ship` session is held while `jig ship` fails,
1578
+ unless you stop to ask the owner something.
1322
1579
 
1323
1580
  ## probe
1324
1581
 
@@ -1362,6 +1619,13 @@ When a `critique` or `tweak` session stops, the gate records its verdicts in
1362
1619
  if your verdicts are committed it stops you once more to commit the lock on its
1363
1620
  own; the next stop passes.
1364
1621
 
1622
+ **The lock is the gate's to write, never yours.** When the gate is wrong (it
1623
+ 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. On
1625
+ jig-site the gate misread a tweak as no command at all, and the session computed
1626
+ the lock by hand and committed it. The lock was right that time, and a lock an
1627
+ agent can write is still a record of nothing.
1628
+
1365
1629
  It judges the critiques this session touched: any with a file changed since the
1366
1630
  session began, and the current spec's surface when you ran `critique`. Another
1367
1631
  page's older critique does not hold you back. To set a critique aside for good,
@@ -31,13 +31,18 @@ cite the number when you follow or deliberately break one.
31
31
  so ask for the step you need rather than doing it from this summary. Never design the whole product up front. Critique findings go back to
32
32
  `make`, then `critique` again, until clean or accepted by the user — then the
33
33
  next feature.
34
+ **Asked to check or confirm a spec, or a mockup, for the owner?** Work from
35
+ the sheet the command shows with it: `{{command_prefix}}spec`'s from
36
+ `.jig/specs/<name>.checked.json` (its step 4), `{{command_prefix}}mockup`'s
37
+ size by size against the spec (its step 3, rendering every frame). Confirm
38
+ only what you checked yourself, and name to the owner what you could not.
34
39
  **Building a screen rather than a single component?** Read `L-01 · Layout
35
40
  method` in `{{rules_path}}/03-patterns.md` and run its five steps before
36
41
  writing any markup. It is a procedure, not a component, so step 4 never
37
42
  selects it and nothing else will. (`explain L-01` prints it too, but the
38
43
  file is the source — do not skip the step if the command is unavailable.)
39
44
  4. Load the relevant section of `{{rules_path}}/03-patterns.md` for the component you are building.
40
- 5. Load `{{rules_path}}/05-copy.md` whenever you write a label, button, heading, error or empty state.
45
+ 5. Load `{{rules_path}}/05-copy.md` whenever you write a label, button, heading, error or empty state, or prose a page ships (docs, a guide, a blog post).
41
46
  6. Consume tokens by semantic name only. Never write a raw colour or pixel value
42
47
  at a call site, and never resolve a name yourself: if a token you need has no
43
48
  value, that is a finding to report, not a number to supply.
@@ -29,6 +29,11 @@
29
29
  "argumentHint": "[--json]",
30
30
  "status": "available"
31
31
  },
32
+ "ship": {
33
+ "description": "Say whether the project is ready to ship, by everything Jig checks: no mechanical or seo errors, and every confirmed page critiqued as it stands, with nothing the owner has not ruled on. The slash command critiques what is owed first. Security, performance and deployment are not Jig's to check.",
34
+ "argumentHint": "",
35
+ "status": "available"
36
+ },
32
37
  "verdicts": {
33
38
  "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.",
34
39
  "argumentHint": "<surface>",