@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.
- package/CHANGELOG.md +57 -0
- package/README.md +45 -4
- package/SPEC.md +2 -2
- package/WRITING.md +334 -16
- package/bin/hyperspec.mjs +132 -2
- package/examples/writing/course/part-1.md +17 -0
- package/examples/writing/course/part-2.md +17 -0
- package/examples/writing/course.hyperspec.md +1 -0
- package/examples/writing/essay/judge/panel-buyer.packet.json +118 -0
- package/examples/writing/essay/judge/panel-expert.packet.json +114 -0
- package/examples/writing/essay/judge/panel-novice.packet.json +114 -0
- package/examples/writing/essay/judge/panel-skeptic.packet.json +114 -0
- package/examples/writing/essay/sample-verdicts/panel-buyer.verdict.json +11 -0
- package/examples/writing/essay/sample-verdicts/panel-expert.verdict.json +13 -0
- package/examples/writing/essay/sample-verdicts/panel-novice.verdict.json +11 -0
- package/examples/writing/essay/sample-verdicts/panel-skeptic.verdict.json +13 -0
- package/examples/writing/story/judge/panel-buyer.packet.json +118 -0
- package/examples/writing/story/judge/panel-expert.packet.json +114 -0
- package/examples/writing/story/judge/panel-novice.packet.json +114 -0
- package/examples/writing/story/judge/panel-skeptic.packet.json +114 -0
- package/examples/writing/story/sample-verdicts/panel-buyer.verdict.json +13 -0
- package/examples/writing/story/sample-verdicts/panel-expert.verdict.json +11 -0
- package/examples/writing/story/sample-verdicts/panel-novice.verdict.json +11 -0
- package/examples/writing/story/sample-verdicts/panel-skeptic.verdict.json +11 -0
- package/package.json +1 -1
- package/src/evidence.mjs +74 -0
- package/src/judge.mjs +50 -66
- package/src/judges/index.mjs +7 -1
- package/src/judges/panel.mjs +135 -0
- package/src/stations/index.mjs +3 -1
- package/src/stations/quotes.mjs +26 -2
- package/src/stations/sequence.mjs +113 -0
- package/src/stations/triage.mjs +20 -0
- package/src/triage.mjs +401 -0
- package/src/writing-fields.mjs +48 -1
- 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
|
|
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
|
|
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)
|
|
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.
|
|
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.
|
|
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.
|
|
112
|
+
**Version 0.9.0** (2026-09-29)
|
|
113
113
|
|
|
114
114
|
## What makes a spec a hyperspec
|
|
115
115
|
|