jig-ui 0.22.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.
@@ -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 write the spec and present it
265
- for approval on your first response — a spec synthesised from a one-line prompt
266
- and handed over for a yes is the failure this command exists to prevent, and it
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.
@@ -369,6 +377,8 @@ sizes: # phone first. Each size is a whole composition, not
369
377
  why: "content is capped at 1200px, so 1600 adds margin and nothing else"
370
378
  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
371
379
  states: [default, loading, error, success]
380
+ motion: # every movement the page has, or `none`: what moves, on its trigger; tells what
381
+ - deleted row: rows below slide into the gap, on delete; tells where the list went
372
382
  decisions: [The Engineer Reads First] # every DECISIONS.md entry this screen implements, by name
373
383
  later: [social sign-in, remember this device] # cut from V1, by name — the next specs start here
374
384
  indexable: true # from the mode — editorial yes, product/operator no. Say why when you override it.
@@ -378,11 +388,23 @@ mockup: pending # approved or skipped, quoting the user: approved by
378
388
  mockup_at: # where the approved drawing is: a .jig/mockups path, or a Figma or Stitch link
379
389
  deviations: [] # `make` writes here; `spec` leaves it empty
380
390
  critique: each # optional: each, or at-ship; left out, the project's default in {{config_file}}
391
+ # superseded_by: reference.spec.md # only when another spec replaces this one; `ship` then leaves this page to that spec's critique
381
392
  ---
382
393
  ```
383
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.
384
399
  - **`phone` is written first, and in full.** It is the most common screen, and the
385
400
  one a derived composition fails on worst.
401
+ - **`motion:` lists every movement, and why it moves.** Each names what moves, its
402
+ trigger, and what it tells the reader. The trigger is the user's input, a state
403
+ change, arrival (once per visitor, editorial only, `G-42`) or ambient (editorial
404
+ only, `P-13`). A movement that cannot say what it tells the reader is cut here,
405
+ before it is built. Write it from the composition; it is not a question for the
406
+ owner, who reads it on the sheet beside `states:`. A page with nothing moving
407
+ says `none`.
386
408
  - **`indexable:`, `title:` and `description:` are copy, decided here.** The mode
387
409
  sets the default — `editorial` is first-visit content and is indexable,
388
410
  `product` and `operator` are what somebody reaches after signing in and are
@@ -479,10 +501,9 @@ to the spec, never the spec to the decisions.
479
501
  Step 3b checks the spec against the decisions. Nothing after it checks the spec
480
502
  against the owner's words or against the facts it states: `make` builds a
481
503
  confirmed spec as written, and `critique` compares the page to the spec, never
482
- the spec to what is true. On jig-site a confirmed spec for a docs chapter carried
483
- seven errors to the built page, among them a procedure Jig does not have and a
484
- lock written at the wrong moment, and the owner had confirmed it. The writer
485
- 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.
486
507
 
487
508
  **Delegate to a subagent.** Give it the spec, `DECISIONS.md`, the owner's messages
488
509
  from this conversation, and read access to the project. Not your reasoning, and
@@ -491,7 +512,7 @@ not your summary of what the owner meant. It writes
491
512
 
492
513
  ```json
493
514
  {
494
- "spec": "sha256 of the spec file with its confirmed: line removed",
515
+ "spec": "`{{scripts_path}} checksum <name>` prints it: the spec with its confirmed: and mockup: lines emptied",
495
516
  "quotes": [
496
517
  { "quote": "Only where the steps differ by path", "said": "the owner, this conversation", "holds": true }
497
518
  ],
@@ -521,7 +542,15 @@ not your summary of what the owner meant. It writes
521
542
  touches.
522
543
 
523
544
  Fix what it found, then have the spec checked again: the record is of the spec
524
- you show, and the gate compares its `spec` checksum to the file. **If you cannot
545
+ you show, and the gate compares its `spec` checksum to the file.
546
+
547
+ **A second check covers what changed, not the whole spec again.** Give the
548
+ reader the earlier record and the spec's diff since it. A quotation or fact whose
549
+ line did not change, and whose source has not changed since (`git diff` on that
550
+ file), carries over as recorded; the reader checks the changed lines, the new
551
+ ones, and any fact whose source moved. It still writes the whole record, with
552
+ the new checksum. Opening every source again on each round costs the most on
553
+ exactly the lines nobody touched. **If you cannot
525
554
  delegate, write the record yourself, with `"reader": "the writer"` in it, and say
526
555
  in the confirmation message that nobody else checked the spec.** That is an
527
556
  honest gap the owner can close by reading more closely; a check you ran on your
@@ -536,6 +565,8 @@ Show the spec, and with it the sheet the owner checks it by, from
536
565
  - **Facts:** each claim and its source, the ones that could not be checked
537
566
  first.
538
567
  - **Copy the page will show as written.**
568
+ - **What moves:** each line of `motion:`, with its trigger and what it tells
569
+ the reader, or that nothing moves.
539
570
  - **Your conditions**, beside the lines that carry them.
540
571
  - **Left for you:** the `open` items, which they can decide now.
541
572
 
@@ -564,9 +595,9 @@ they confirm.
564
595
  renames a region at any size, the approved drawing no longer shows the page: set
565
596
  `mockup: pending`, and `{{command_prefix}}mockup` redraws it for the owner. The gate
566
597
  checks it for a drawing in frames: while `mockup: approved`, each region the spec lists must be labelled in
567
- its size's frame of the drawing at `mockup_at:`. On jig-site the header spec went
568
- through five confirmed rounds after its drawing was approved, and still said
569
- `approved` over a drawing of none of them.
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.
570
601
 
571
602
  ## mockup
572
603
 
@@ -808,9 +839,9 @@ confirmed again.
808
839
  Record where the approved drawing is in `mockup_at:` — the file path, or the
809
840
  Figma or Stitch link. Only their own response counts; your summary of the
810
841
  drawing, or no objection, does not. **A condition they attach goes into the
811
- spec first**, in their words, on the lines it governs: on jig-site the owner
812
- approved with "three columns at 1280 and wider, inside the page margins", the
813
- condition lived only in the conversation, and `make` moved the switch to 1290.
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.
814
845
  - The user says to skip it → `mockup: skipped — "<their words>"`. For a change
815
846
  small enough that drawing it costs more than building it, that is a reasonable
816
847
  call; it is still theirs to make.
@@ -867,10 +898,9 @@ and `make` is where decisions are carried out, not taken. When the build shows a
867
898
  decision is wrong, missing or in conflict with the spec, stop and say so: the owner
868
899
  changes it through `{{command_prefix}}decide`, or `{{command_prefix}}tweak` for a
869
900
  small change to a built page. A note that a decision has been carried out belongs in
870
- the spec, under `deviations:` or its as-built notes, not in the decision. On jig-site
871
- one make round added a decision and another rewrote one to match the tokens it had
872
- just switched to; the next critique judged the page against text the build had
873
- 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`.
874
904
 
875
905
  Build V1 only. Nothing in `later:`, however little extra it looks.
876
906
 
@@ -896,6 +926,10 @@ indexable carries `noindex` instead, from its own metadata rather than from
896
926
  Then the ordinary rules apply: tokens by semantic name, the relevant
897
927
  `03-patterns.md` section for each component, `05-copy.md` for every string.
898
928
 
929
+ **Build the motion `motion:` lists, and no other.** A movement the spec does not
930
+ list is a deviation, recorded below like any other. A spec with no `motion:`
931
+ (one confirmed before it existed) leaves motion to the `G-` rules alone.
932
+
899
933
  ### Record what you changed
900
934
 
901
935
  Building reveals that a spec was wrong somewhere — that is normal and expected.
@@ -1060,9 +1094,12 @@ owner ruled icon-only, a menu the owner put at every phone width. The verdict
1060
1094
  names that decision in `ruling`, exactly as its heading reads, and `verdicts`
1061
1095
  refuses a `ruled` with no ruling or with one the file does not hold. A ruled
1062
1096
  verdict is reported, and counted apart (`ruled=`); it is not a finding, and it
1063
- does not go back to `make`, which could only leave it as it is. On jig-site a
1064
- header critique counted 15 findings, five of them rulings labelled "owner-ruled"
1065
- in prose: every count was inflated, and the real findings were harder to see.
1097
+ does not go back to `make`, which could only leave it as it is. **Put the field
1098
+ in each arm's brief, with its shape:** `{ "id": …, "verdict": "ruled", "ruling":
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.
1066
1103
  A rule the page breaks with no decision behind it is a `finding`, however sure
1067
1104
  you are the owner would agree.
1068
1105
 
@@ -1129,11 +1166,27 @@ Each reader arm writes its own file. The arm reports back only that it wrote it.
1129
1166
  { "id": "P-14", "verdict": "finding", "reason": "menu button at 360 does not open; aria-expanded never set" },
1130
1167
  { "id": "A-60", "verdict": "n/a", "reason": "A-60 is about competing icons; this page has none" },
1131
1168
  { "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" }
1169
+ ],
1170
+ "differences": [
1171
+ { "what": "the checklist gives nine checks", "where": "src/pages/guide.astro:245", "against": "README.md, 'Before you confirm a spec': ten" }
1132
1172
  ]
1133
1173
  }
1134
1174
  ```
1135
1175
 
1136
1176
  `screen.json` carries `rendered` and `artefacts`; `code.json` needs only `verdicts`.
1177
+ **`differences` holds what no rule names:** the page against its spec (step 3),
1178
+ or against a source it quotes or teaches. Each counts as a finding. Never carry
1179
+ one as a verdict under an id you made up: `verdicts` refuses an id the corpus
1180
+ does not hold (`page-vs-corpus-1`), and the parent is left to move it by hand. `ruled` is for a
1181
+ rule a decision overrides; a decision in `decisions.json` is judged `ok`,
1182
+ `finding` or `n/a`, never ruled.
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.
1137
1190
 
1138
1191
  **And the project's own decisions, one verdict each**, in
1139
1192
  `.jig/critique/<surface>/decisions.json`:
@@ -1280,6 +1333,25 @@ grouped with what, what stacks or moves on the phone. Not the colour, type or
1280
1333
  polish: the mockup is grayscale and low-fidelity on purpose, so its appearance is
1281
1334
  not a target.
1282
1335
 
1336
+ **Motion, against `motion:`.** Each movement on the page is judged against its
1337
+ line: one the spec does not list is a `G-42` finding, and one that tells the
1338
+ reader something other than its line says is a finding under the rule it
1339
+ breaks. With no `motion:` in the spec, the `G-` rules alone judge it.
1340
+
1341
+ **Then the other way: the page against the spec.** Each section, paragraph,
1342
+ control or claim the page carries that no line of the spec asks for is a
1343
+ difference too, however accurate it is. The owner confirmed the spec, not the
1344
+ page; content the spec never held is content they never approved, and every
1345
+ later tweak and critique works from a spec that no longer says what is there.
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
1348
+ content and where it is: the fix is a tweak that writes it into the spec for the
1349
+ owner to confirm, or removes it.
1350
+
1351
+ **Say in the report what each direction found**, "none" included: a report that
1352
+ does not mention the page-against-spec pass cannot be told apart from one that
1353
+ skipped it.
1354
+
1283
1355
  A difference from either is a finding **unless** `deviations:` already explains it
1284
1356
  — that is what the recorded deviation is for. A difference explained by neither is
1285
1357
  the more serious finding, because it means the spec has quietly stopped describing
@@ -1404,12 +1476,21 @@ its own line, `B-106`), there is nothing to decide; do not invent a decision.
1404
1476
 
1405
1477
  The owner's words are the ones tweak.json records as `change`. A `**Why:**` you
1406
1478
  add quotes them, in quotation marks, and nothing else; what you read into them,
1407
- or into a screenshot the owner pointed at, goes under `**Why (inferred):**`. On
1408
- jig-site a tweak shown a picture of a copy button wrote an exception to `E-51`
1409
- "given directly by the owner … by reference rather than words": a ruling nobody
1410
- gave, which every later critique would have judged the page by. The gate stops a
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
1411
1483
  tweak whose new `**Why:**` quotes words tweak.json does not hold.
1412
1484
 
1485
+ **A decision you record or amend covers the whole page, not the one place it
1486
+ was raised.** The owner rules on an instance ("keep this apostrophe curly") and
1487
+ the decision states a kind ("every apostrophe, curly"). Before you build, look
1488
+ through the page, and the chrome it shares, for every other instance of that
1489
+ kind, and bring each one in line in the same change; name them in your report.
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.
1493
+
1413
1494
  ### 2. Bring the spec in line, if it disagrees
1414
1495
 
1415
1496
  If the spec says something the change contradicts, or the page will no longer
@@ -1480,9 +1561,14 @@ Build the project the way it ships, then run `{{scripts_path}} ship`. It runs
1480
1561
  `check --all --ci` and `seo`, and reads every confirmed spec's critique: a page
1481
1562
  is owed a critique when it has none, when its page changed after it was judged,
1482
1563
  when a tweak deferred its re-judge, when its verdicts are incomplete, or when a
1483
- finding stands that the owner has not ruled on. It prints each page's state and
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
1484
1567
  a `JIG_SHIP:` line, and exits non-zero until the project is ready. A spec that
1485
- is not confirmed yet is in progress and not held against the ship.
1568
+ is not confirmed yet is in progress and not held against the ship. Nor is a spec
1569
+ another has replaced: `superseded_by: <spec>` in its front matter leaves its page
1570
+ to that spec's critique, and `ship` checks the spec it names exists. Write that
1571
+ line, in those words, when a spec is replaced; a marker of your own is not read.
1486
1572
 
1487
1573
  ### 2. Clear what it names
1488
1574
 
@@ -1547,14 +1633,15 @@ review, never by the builder editing the last one.
1547
1633
  When a `critique` or `tweak` session stops, the gate records its verdicts in
1548
1634
  `.jig/critique/<surface>/verdicts.lock`. That happens after you have committed, so
1549
1635
  if your verdicts are committed it stops you once more to commit the lock on its
1550
- 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.
1551
1639
 
1552
1640
  **The lock is the gate's to write, never yours.** When the gate is wrong (it
1553
1641
  misreads the session, or asks for something the procedure does not), say what it
1554
- got wrong, leave the lock as it is, and report the work as held by the gate. On
1555
- jig-site the gate misread a tweak as no command at all, and the session computed
1556
- the lock by hand and committed it. The lock was right that time, and a lock an
1557
- 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.
1558
1645
 
1559
1646
  It judges the critiques this session touched: any with a file changed since the
1560
1647
  session began, and the current spec's surface when you ran `critique`. Another
@@ -1575,6 +1662,14 @@ It exists because every "run check" and "run verdicts" step in these procedures
1575
1662
  skipped in a live run, and pages that did not render their styles were reported
1576
1663
  clean.
1577
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
+
1578
1673
  ## verdicts
1579
1674
 
1580
1675
  Run `{{scripts_path}} verdicts <surface>`, passing the argument through, and report its
@@ -1782,9 +1877,9 @@ weighs it as the team's and applies the rule where the team never would.
1782
1877
 
1783
1878
  What you add to explain a reason, work out from it, or carry over from what the
1784
1879
  owner said elsewhere goes in its own paragraph, `**Why (inferred):**`, which says it
1785
- is yours. On jig-site, reasons read "given directly by the owner", followed by
1786
- sentences the agent had written; a later agent could not tell which half to weigh
1787
- as the team's. The gate checks each decision this session wrote or changed: its
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
1788
1883
  `Why` is quoted, `not given`, or labelled inferred.
1789
1884
 
1790
1885
  **Record what is still open in its own section, at the end:**
@@ -36,13 +36,25 @@ 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
42
54
  selects it and nothing else will. (`explain L-01` prints it too, but the
43
55
  file is the source — do not skip the step if the command is unavailable.)
44
56
  4. Load the relevant section of `{{rules_path}}/03-patterns.md` for the component you are building.
45
- 5. Load `{{rules_path}}/05-copy.md` whenever you write a label, button, heading, error or empty state.
57
+ 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).
46
58
  6. Consume tokens by semantic name only. Never write a raw colour or pixel value
47
59
  at a call site, and never resolve a name yourself: if a token you need has no
48
60
  value, that is a finding to report, not a number to supply.
@@ -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>",