@supersuit/hyperspec 0.8.0 → 0.9.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.
Files changed (36) hide show
  1. package/CHANGELOG.md +57 -0
  2. package/README.md +45 -4
  3. package/SPEC.md +2 -2
  4. package/WRITING.md +334 -16
  5. package/bin/hyperspec.mjs +132 -2
  6. package/examples/writing/course/part-1.md +17 -0
  7. package/examples/writing/course/part-2.md +17 -0
  8. package/examples/writing/course.hyperspec.md +1 -0
  9. package/examples/writing/essay/judge/panel-buyer.packet.json +118 -0
  10. package/examples/writing/essay/judge/panel-expert.packet.json +114 -0
  11. package/examples/writing/essay/judge/panel-novice.packet.json +114 -0
  12. package/examples/writing/essay/judge/panel-skeptic.packet.json +114 -0
  13. package/examples/writing/essay/sample-verdicts/panel-buyer.verdict.json +11 -0
  14. package/examples/writing/essay/sample-verdicts/panel-expert.verdict.json +13 -0
  15. package/examples/writing/essay/sample-verdicts/panel-novice.verdict.json +11 -0
  16. package/examples/writing/essay/sample-verdicts/panel-skeptic.verdict.json +13 -0
  17. package/examples/writing/story/judge/panel-buyer.packet.json +118 -0
  18. package/examples/writing/story/judge/panel-expert.packet.json +114 -0
  19. package/examples/writing/story/judge/panel-novice.packet.json +114 -0
  20. package/examples/writing/story/judge/panel-skeptic.packet.json +114 -0
  21. package/examples/writing/story/sample-verdicts/panel-buyer.verdict.json +13 -0
  22. package/examples/writing/story/sample-verdicts/panel-expert.verdict.json +11 -0
  23. package/examples/writing/story/sample-verdicts/panel-novice.verdict.json +11 -0
  24. package/examples/writing/story/sample-verdicts/panel-skeptic.verdict.json +11 -0
  25. package/package.json +1 -1
  26. package/src/evidence.mjs +74 -0
  27. package/src/judge.mjs +50 -66
  28. package/src/judges/index.mjs +7 -1
  29. package/src/judges/panel.mjs +135 -0
  30. package/src/stations/index.mjs +3 -1
  31. package/src/stations/quotes.mjs +26 -2
  32. package/src/stations/sequence.mjs +113 -0
  33. package/src/stations/triage.mjs +20 -0
  34. package/src/triage.mjs +401 -0
  35. package/src/writing-fields.mjs +48 -1
  36. package/src/writing.mjs +5 -1
package/CHANGELOG.md CHANGED
@@ -1,5 +1,62 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0 (2026-09-29)
4
+
5
+ The pressure test a draft gets before it ships is now part of the run, and so is answering it.
6
+ Several readers reading a draft through their own lenses, and someone deciding what to do about
7
+ each thing they said, was done by hand twice, once for a letter and once for a book outline, and
8
+ both times the review read a stale, truncated copy and none of its readers was the person the
9
+ piece was for. The `panel` judge fixes both by construction, and `hyperspec triage` holds every
10
+ finding, the panel's or an outside review's, to an answer that `check` keeps true against the draft.
11
+
12
+ - The `panel` judgment station, the seventh, run last. One packet per reader,
13
+ `panel-<reader>.packet.json`: the readers the new optional `writing.panel` lists (`id`, `who`,
14
+ `knows`, `lens`), or by default a `skeptic`, a `novice` and an `expert`, and always the audience's
15
+ own reader, added last as `buyer`. It applies when the reader station does (a written audience
16
+ with a rubric). The verdict is `{ good, improve, missing, remove }`, every item `{ evidence, note }`
17
+ under the evidence rule, so a review of any copy but the current draft is refused. The panel
18
+ never fails a draft: improve, missing and remove items are warnings (`judge-panel-improve`,
19
+ `-missing`, `-remove`) and go to the triage file. A panel ledger line carries `reader`, and each
20
+ reader's history is its own. Lint refuses a panel that is not a list of readers, a reader with no
21
+ id, who or lens, an id that is not a slug, used twice or `buyer`, and a hollow `knows`
22
+ (`writing-panel`, `-reader`, `-id`, `-id-duplicate`, `-buyer`, `-who`, `-lens`, `-knows`, test 1).
23
+ - `triage.jsonl`, beside the runs ledger: one finding per line, `{ finding_id, source, reader, kind,
24
+ text, evidence, draft_sha256, disposition, answer }`, each once (the id hashes what it says).
25
+ - The `triage` station, run last in `check`: fails on an unanswered finding
26
+ (`station-triage-untriaged`), a `taken` or `already-true` answer whose evidence is missing or not
27
+ in the draft (`-evidence-missing`, `-evidence-not-found`), a `kept` answer with no reason
28
+ (`-reason-missing`), a disposition outside the four (`-disposition`) or a line that is not a
29
+ finding (`-unreadable`); warns on an `open` finding (`-open`) and on a kept or open answer about a
30
+ passage that has left the draft (`-stale`). With no triage file it skips.
31
+ - `hyperspec triage status` (the counts, the station's rules, and the synthesis: every passage two
32
+ or more readers raised findings about), `triage answer` (refuses with `triage-evidence-missing`,
33
+ `-too-short`, `-not-found` or `triage-reason-missing`, writing nothing), `triage import` (an
34
+ outside review in markdown or plain text as findings: headings name readers, Good, Improve,
35
+ Missing and Remove labels set the kind, praise is counted and not triaged, and a quote the draft
36
+ does not hold warns, `triage-import-quote-not-found`; `triage-import-empty` when there is nothing
37
+ to answer) and `triage reply` (a plain-text reply to the reviewer; it never sends, and exits 1
38
+ while a finding is unanswered).
39
+ - The quotes station reads the new optional `writing.quotes.examples`: `true` reads a quoted span
40
+ whose sentence names no known speaker as an example phrasing, not a quotation; a list exempts
41
+ exactly those phrasings. A quotation that names its speaker is checked either way. Lint refuses
42
+ any other value (`writing-quotes`, `writing-quotes-examples`, test 1).
43
+ - The sequence station gains the quiz rules, on when the new `writing.form.sequence.quiz` names the
44
+ quiz heading: every defined term tested by some question (a simple plural counts), no question
45
+ using a term defined after the unit it is tagged with, every question tagged, every answer one of
46
+ its options (`station-sequence-quiz-missing`, `-untagged`, `-answer`, `-used-before-defined`,
47
+ `-untested`). Promoted from the checker the first book written this way used, with its question
48
+ shape. A hollow `quiz` fails lint (`writing-form-sequence-quiz`, test 1).
49
+ - The evidence rule moved to `src/evidence.mjs`, shared by `judge record` and `triage`; `judge.mjs`
50
+ re-exports what it exported.
51
+ - The worked examples: the essay and the story ship four panel packets each, with a hand-filled
52
+ sample verdict per reader; the course carries a quiz at the end of each part and `quiz: Check
53
+ yourself`.
54
+
55
+ **Behavior change:** `check` runs nine stations, so `--json` and the ledger's `stations` carry
56
+ `triage` (as `skip` for every spec without a triage file). `judge prepare` writes the four panel
57
+ packets for every spec whose audience has a rubric, where 0.8 wrote none; `--only` still limits it.
58
+ No other finding id changed.
59
+
3
60
  ## 0.8.0 (2026-09-29)
4
61
 
5
62
  A work read in order can now be checked as one. Every station so far held ONE piece to its spec; a
package/README.md CHANGED
@@ -31,6 +31,10 @@ improvement ledger. Every test is defined in [SPEC.md](SPEC.md).
31
31
  | `hyperspec check <spec> [--draft <file>] [--only a,b]` | Run a writing spec's deterministic stations against a draft, or, for a sequential work, against its files in reading order. |
32
32
  | `hyperspec judge prepare <spec> --draft <file> --out <dir> [--only a,b] [--force]` | Write one packet per judgment station, for an outside judge to fill. |
33
33
  | `hyperspec judge record <packet> --verdict <file>` | Check a judge's verdict against its packet, derive the station's status, and record it. |
34
+ | `hyperspec triage status <spec> [--draft <file>]` | Count every finding's answer, list the passages two or more readers share, and hold every answer to the draft. |
35
+ | `hyperspec triage answer <spec> <finding> taken\|kept\|already-true\|open [--evidence S] [--reason S] [--draft <file>]` | Answer one finding: evidence from the draft for taken and already-true, a reason for kept. |
36
+ | `hyperspec triage import <spec> <review> [--source S] [--draft <file>]` | Bring an outside review in as findings to answer. |
37
+ | `hyperspec triage reply <spec> [--source S] [--draft <file>]` | Print a plain-text reply to the reviewer from the answers. Never sends anything. |
34
38
  | `hyperspec learn prepare <spec> --first <draft> --approved <draft> --out <dir> [--force]` | Write the edits between a first draft and the approved one, for a judge to classify by spec block. |
35
39
  | `hyperspec learn record <packet> --verdict <file>` | Count the classified edits by block and name one next move. |
36
40
  | `hyperspec recipe check <output-or-recipe>` | Check that a recipe records everything the standard asks for. |
@@ -57,6 +61,12 @@ and 1 when it refused. `judge prepare` and `learn prepare` exit 0 when they wrot
57
61
  with lint's own code when the spec is not ready, and `judge prepare` exits 1 when a station could
58
62
  not build its packet. All four exit 2 on a usage error.
59
63
 
64
+ `hyperspec triage status` exits 0 when every finding is answered and every answer holds against
65
+ the draft, and 1 when not; `triage answer` 0 when it wrote the answer and 1 when it refused it;
66
+ `triage import` 0 when it imported and 1 when the review holds nothing to answer; `triage reply` 0
67
+ when the reply is ready to send and 1 when a finding is still unanswered. All four exit 2 on a
68
+ usage error.
69
+
60
70
  The recipe commands use the same numbers: 0 ok, 1 a check failed or the child regressed, 2
61
71
  usage or unreadable input, 3 pending, when `regenerate` has stages waiting for a runner.
62
72
  `regenerate` also exits 1 when a stage it ran reported a failing verdict, or none. A stage it
@@ -194,13 +204,15 @@ it did in 0.4. The folder shape, every feature, and every finding are in
194
204
 
195
205
  ### Checking a draft
196
206
 
197
- Once a draft exists, `check` holds it to its spec with eight stations, none of which calls a
207
+ Once a draft exists, `check` holds it to its spec with nine stations, none of which calls a
198
208
  model or touches the network: `form` (length and required parts), `terms` (every word in the new
199
209
  optional `writing.audience.terms` is defined where it first appears), `claims` (the claims
200
210
  ledger still matches the draft, and every claim has a source), `quotes` (in nonfiction, every quotation of four
201
- words or more is word for word in a marked quote), `private` (no run of eight words from a
211
+ words or more is word for word in a marked quote; `writing.quotes.examples` marks example
212
+ phrasings such as "write the update for Dana" as examples rather than quotations), `private` (no run of eight words from a
202
213
  private segment), `dna` (the draft's measured style beside its scope's, as warnings), `links`
203
- (well-formed, and relative links resolve) and `sequence` (for a work read in order; see below).
214
+ (well-formed, and relative links resolve), `sequence` (for a work read in order; see below) and
215
+ `triage` (every reader's finding answered, and every answer held to the draft; see below).
204
216
 
205
217
  ```bash
206
218
  npx @supersuit/hyperspec check essay.hyperspec.md --draft essay/draft.md
@@ -219,7 +231,10 @@ it across the whole work: every lesson carries its sections ("After this lesson
219
231
  terms", "Try this" by default), every term is defined in exactly one lesson, no lesson uses a term
220
232
  before the lesson that defines it (code, the part's closing teaser and words the reader already
221
233
  knows are exempt), each lesson defines the terms the outline promises, and a pointer to a later
222
- lesson is a warning. List the work's files and `check` needs no `--draft`:
234
+ lesson is a warning. Name the quiz heading as `quiz:` and every quiz is held to it too: every
235
+ defined term tested by some question, no question using a term from a lesson after the one it is
236
+ tagged with, and every answer one of its question's options. List the work's files and `check`
237
+ needs no `--draft`:
223
238
 
224
239
  ```yaml
225
240
  sequence:
@@ -263,6 +278,32 @@ style rule". It never edits the spec. Both examples ship their packets and hand-
263
278
  verdicts. The packet shapes, every station's rules and findings, and the learn tally are in
264
279
  [WRITING.md](WRITING.md#judging-a-draft).
265
280
 
281
+ ### A reader panel, and answering what it found
282
+
283
+ A draft gets pressure-tested before it ships: several readers read it, each through their own
284
+ lens, and say what works, what to improve, what is missing and what to remove. The `panel` judge
285
+ makes that part of the run. It writes one packet per reader, the ones `writing.panel` lists or by
286
+ default a skeptic, a newcomer and an expert, and always the audience's own reader as `buyer`,
287
+ since a panel that never includes the person the piece is for tests everything but that. Every
288
+ item a reader lists quotes the draft word for word, so a review of a stale copy is refused.
289
+
290
+ Each thing a reader would change becomes a finding in `triage.jsonl`, beside the runs ledger, and
291
+ so does each point of an outside review brought in with `triage import`. Every finding gets one
292
+ answer: `taken` (with the passage of the draft that now does it), `kept` (with the reason),
293
+ `already-true` (with the passage that already did it) or `open` (a decision for you). `check` fails
294
+ while a finding is unanswered or an answer's passage is no longer in the draft, and warns on an
295
+ open one. `triage reply` turns the answers into a plain-text reply to the reviewer, for you to send.
296
+
297
+ ```bash
298
+ npx @supersuit/hyperspec judge record story/judge/panel-skeptic.packet.json --verdict story/sample-verdicts/panel-skeptic.verdict.json
299
+ npx @supersuit/hyperspec triage status story.hyperspec.md --draft story/draft.md
300
+ npx @supersuit/hyperspec triage answer story.hyperspec.md panel-skeptic-aeb09835 open --draft story/draft.md --reason "the author's call"
301
+ npx @supersuit/hyperspec triage reply story.hyperspec.md --draft story/draft.md
302
+ ```
303
+
304
+ The triage file, every answer's rule, how a review is read, and every finding are in
305
+ [WRITING.md](WRITING.md#triage-1).
306
+
266
307
  ## The format
267
308
 
268
309
  A hyperspec is a markdown file with a YAML frontmatter block: `decisions`, `requirements`,
package/SPEC.md CHANGED
@@ -97,7 +97,7 @@ examples:
97
97
  - path: examples/minimal.hyperspec.md
98
98
  why: the smallest spec that passes all nine tests
99
99
  resume:
100
- next_action: collect adopter issues on 0.7, the judge and learn commands included, and cut 0.8 from them
100
+ next_action: collect adopter issues on 0.9, the panel and triage included, and cut 0.10 from them
101
101
  feedback:
102
102
  issues: https://github.com/SupersuitUp/hyperspec/issues
103
103
  fork: MIT; fork it for your own purposes and say so in your SPEC
@@ -109,7 +109,7 @@ improvement:
109
109
 
110
110
  A person writing for another person leaves most of the specification unsaid, because the other person fills the gaps from shared context. An agent has none of that context, so it fills every gap with the average, and the average is what reads as middling. Hyperspecification is writing down the gaps. It is a level of detail that would feel like overkill between two people and is exactly enough for an agent: every decision the agent would otherwise guess is either decided, delegated with the rule for deciding it, or marked open, so the work stops instead of guessing.
111
111
 
112
- **Version 0.8.0** (2026-09-29)
112
+ **Version 0.9.0** (2026-09-29)
113
113
 
114
114
  ## What makes a spec a hyperspec
115
115