@supersuit/hyperspec 0.2.0 → 0.4.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 (43) hide show
  1. package/CHANGELOG.md +119 -0
  2. package/README.md +53 -3
  3. package/SPEC.md +24 -10
  4. package/WRITING.md +597 -0
  5. package/bin/hyperspec.mjs +94 -3
  6. package/examples/minimal.hyperspec.md +2 -2
  7. package/examples/writing/essay/goldens/close.md +2 -0
  8. package/examples/writing/essay/goldens/opening.md +2 -0
  9. package/examples/writing/essay/materials/interview-notes.md +12 -0
  10. package/examples/writing/essay/materials/interview-notes.md.segments.jsonl +10 -0
  11. package/examples/writing/essay/materials/team-survey.md +7 -0
  12. package/examples/writing/essay/materials/team-survey.md.segments.jsonl +6 -0
  13. package/examples/writing/essay/materials/voice-memo.md +18 -0
  14. package/examples/writing/essay/materials/voice-memo.md.segments.jsonl +7 -0
  15. package/examples/writing/essay/runs.jsonl +0 -0
  16. package/examples/writing/essay.hyperspec.md +220 -0
  17. package/examples/writing/story/goldens/dialogue.md +3 -0
  18. package/examples/writing/story/goldens/opening.md +3 -0
  19. package/examples/writing/story/materials/bakery-visit.md +9 -0
  20. package/examples/writing/story/materials/bakery-visit.md.segments.jsonl +13 -0
  21. package/examples/writing/story/materials/notes.md +16 -0
  22. package/examples/writing/story/materials/notes.md.segments.jsonl +7 -0
  23. package/examples/writing/story/materials/scene-list.md +7 -0
  24. package/examples/writing/story/materials/scene-list.md.segments.jsonl +14 -0
  25. package/examples/writing/story/runs.jsonl +0 -0
  26. package/examples/writing/story.hyperspec.md +288 -0
  27. package/examples/writing/style-rules.md +19 -0
  28. package/package.json +4 -2
  29. package/src/blobs.mjs +1 -1
  30. package/src/compare.mjs +6 -6
  31. package/src/fsutil.mjs +1 -1
  32. package/src/labels.mjs +6 -0
  33. package/src/placeholder.mjs +20 -0
  34. package/src/profiles.mjs +50 -0
  35. package/src/reproduce.mjs +5 -5
  36. package/src/rules.mjs +25 -13
  37. package/src/score.mjs +7 -1
  38. package/src/segments.mjs +407 -0
  39. package/src/template.mjs +4 -1
  40. package/src/writing-exports.mjs +6 -0
  41. package/src/writing-fields.mjs +418 -0
  42. package/src/writing-template.mjs +199 -0
  43. package/src/writing.mjs +181 -0
package/CHANGELOG.md CHANGED
@@ -1,5 +1,124 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.4.0 (2026-09-29)
4
+
5
+ Marking materials. Before a writing spec can pass, every material it draws on (a brain dump, a
6
+ transcript, a set of interview notes) is split into segments, and each segment is labeled with
7
+ what a draft may use it as: a claim with its source, the author's own claim, a story with its
8
+ teller, a quote with its speaker, a stance, an open question, an aside, or something private.
9
+ The spine then cites segments rather than whole files, so every claim points at the exact words
10
+ behind it. hyperspec splits and checks; an agent or a person labels. It still calls no model.
11
+
12
+ **Behavior change for 0.3 writing specs:** a writing spec's materials must now be marked. A
13
+ material item with no `segments:` field fails test 1, so a writing spec that passed 0.3.0 fails
14
+ until each of its materials has a segments file, written with `hyperspec segments init` and
15
+ labeled. Specs with no profile are unaffected.
16
+
17
+ - `hyperspec segments init <material> --id <mid> [--out <file>] [--by paragraph|sentence]`
18
+ writes `<material>.segments.jsonl`: a header naming the material, its path and the SHA-256 of
19
+ its bytes, then one line per segment with character offsets, the verbatim text, and the label
20
+ `unlabeled`. Paragraph mode is the default. It refuses to overwrite a file, and exits 2 with a
21
+ plain message on a missing material, a material with nothing in it, an `--out` folder that
22
+ does not exist, or an unknown `--by`.
23
+ - In sentence mode, a new line that opens on a list marker (`-`, `*`, `+`, or a number followed
24
+ by `.` or `)`, then a space) starts a new segment, and a numbered item's own `1.` is not read
25
+ as a sentence ending. A bullet that is entirely a quotation ending in `."` used to run into the
26
+ next bullet; it now stands on its own. Paragraph mode is unchanged.
27
+ - Seven labels, a closed set: `claim` (needs `source`, or `own: true`), `story` (needs
28
+ `teller`), `quote` (needs `speaker`), `stance`, `question`, `aside` and `private`. `unlabeled`
29
+ is never accepted. A placeholder word (`TODO`, `n/a`, `tbd`, `...`, `???` and the rest) counts
30
+ as missing in these fields, in the header, and in segment ids, as it does everywhere else in
31
+ the linter.
32
+ - What `lint` checks on each segments file, under test 1: the file exists and parses, its header
33
+ names the right material, every label is from the set, ids are unique, and segments never
34
+ overlap and cover every character that is not whitespace (the finding quotes the first
35
+ uncovered text and gives its offset), and the material has some text to mark. Under test 4: every segment's text
36
+ matches the material word for word, each label carries the field it needs, and the material
37
+ has not changed since it was marked (its SHA-256 still matches). A changed material fails as
38
+ stale until it is marked again.
39
+ - A spine claim may cite `material#segment`. The segment must exist (test 4), and citing a
40
+ `private` or `question` segment fails test 5. A bare material id still cites the whole
41
+ material; `material#` with nothing after the `#` fails as an unknown segment.
42
+ - Every marking finding id starts `writing-materials-` or `writing-spine-`, and every message
43
+ names the material, and the segment where there is one. Paths in messages read as the spec
44
+ wrote them, never resolved to a folder on your machine, so `--json` output is the same
45
+ everywhere. WRITING.md lists every finding with its test.
46
+ - A new export, `@supersuit/hyperspec/writing`, gives your own tools `MATERIAL_LABELS` and
47
+ `readSegments`, the same parse-and-check lint runs. `readSegments` returns
48
+ `{ header, segments, findings }` and never throws; `displayPath` and `materialDisplayPath` set
49
+ how the files are named in its messages.
50
+ - `hyperspec init --profile writing` names a segments file for its placeholder material, and the
51
+ materials check reads "every segment of every material carries a label from the closed set,
52
+ matches its source verbatim, and the markings are current".
53
+ - Both writing examples ship with every material marked. Between them they use all seven labels,
54
+ and every spine claim cites segments.
55
+ - WRITING.md gains a Marking materials section: the file format with a worked sample, the labels
56
+ and what each needs, coverage, staleness (including a line-ending conversion, which changes the
57
+ hash), citing segments, every finding with its test, and the import. README and SPEC.md point
58
+ at it.
59
+ - The repository's `.gitattributes` keeps example materials and test fixtures LF on every
60
+ checkout, so the hashes their segments files pin still match on a Windows clone.
61
+
62
+ ## 0.3.0 (2026-09-29)
63
+
64
+ The writing profile. A piece of writing can now carry a hyperspec that names everything an
65
+ agent would otherwise fill with the average: what the piece is made from and how far each
66
+ source can be trusted, whose voice it is for this form, audience and purpose, who it speaks as,
67
+ who reads it, the one change it is for, what kind of thing it is, the claims it argues in order,
68
+ where every fact comes from, and in fiction how each character speaks and what they know by
69
+ each scene. `hyperspec lint` checks all of it under the same nine tests, and
70
+ `hyperspec init --profile writing` lays every block out for you to fill in.
71
+
72
+ **Behavior change for existing specs:** a placeholder now counts as missing, everywhere, in
73
+ specs with no profile too. A placeholder is a whole value, trimmed and in any case, of `todo`,
74
+ `tbd`, `fixme`, `xxx`, `placeholder`, `<placeholder>`, `n/a`, a run of dashes, a run of question
75
+ marks, or an ellipsis, optionally followed by a trailing `.`, `:` or `!`. A spec that passed
76
+ 0.2.0 with `source: TODO` or `source: n/a` on a decision now fails that test. Real text that
77
+ starts with one of those, such as `TODO: write the opening`, still counts as present, and so
78
+ does `none`.
79
+
80
+ - `profile: writing` opts a spec in; its blocks live under a top-level `writing:` map:
81
+ `materials`, `dna`, `persona`, `audience`, `goal`, `form`, `spine`, `sources`, and
82
+ `characters`, which is required when `fiction: true`. Every block carries a `check`, a
83
+ `source` and an `author`. The core format still applies in full.
84
+ - No tenth test. Every writing finding reports under one of the nine, with an id starting
85
+ `writing-`, and the score stays out of nine. `lint` prints one more line,
86
+ `writing: <k>/9 blocks complete`, and `--json` carries it as `profile` on each file.
87
+ - A missing block fails test 1 unless a decision with the id `writing-<block>` defers it:
88
+ `open`, which blocks the spec like any open decision, or `delegated` with a `rule`. A
89
+ deferred block does not count as complete.
90
+ - Progress is never stored: a `writing.progress` key fails test 7, because saved progress goes
91
+ stale the first time a session dies mid-arc. Progress is read off the folder instead.
92
+ - Field rules for every block, each under the test it belongs to: closed sets for `fiction`
93
+ (absent means false), `trust`, `reader`, `change.kind`, the shape of `persona.identity` and
94
+ `unsourced_claim`; unique ids for materials, spine claims and characters; a length envelope
95
+ of whole numbers of at least 1 (test 1); five to ten distinct `goal.conditions` naming real
96
+ requirements, each listed once (test 2); spine claims that name real materials (test 4);
97
+ `persona.facts_from: sources` and a non-empty `will_not_say` (test 5); a `why` on every
98
+ golden, material and golden paths that exist, and golden and rejected lines for every
99
+ character with no line in both (test 6). A repeated id counts once toward a minimum. A
100
+ `stance` outside peer, mentor, witness and guide is a warning.
101
+ - A character needs speech rules (what they say and never say), wants, fears, what they hide,
102
+ an arc state, a knowledge timeline, and golden and rejected lines. `relationships` and a
103
+ pointer to a character `entity` file are optional.
104
+ - `hyperspec init <file> --profile writing [--title T] [--form F] [--fiction]` writes a
105
+ skeleton with every required block in schema order, every field a placeholder, and open
106
+ decisions for the four blocks that need your judgment first (dna, persona, audience, goal).
107
+ It fails lint until the placeholders are replaced. `init` exits 2 with a plain message on a
108
+ `--profile` with no value or one it does not know, `--fiction` or `--form` without
109
+ `--profile writing`, `--kind` with it, and a folder that does not exist.
110
+ - `lint` warns under test 7 on a `profile` it does not know, and checks none of its rules. A
111
+ name every object inherits, such as `constructor`, is an unknown profile like any other.
112
+ - WRITING.md documents the profile: the ten components, the schema with every field, the test
113
+ mapping, the closed sets, the seven materials labels and what each may be used as, and
114
+ deferral. It ships in the package.
115
+ - `examples/writing/` ships two complete specs, an essay and a two-character short story, with
116
+ every file they name. Both pass with no findings, and a test keeps them that way.
117
+ - SPEC.md gains a Profiles section and states the placeholder words in its test-to-field map.
118
+ - The illustrative specs and recipe in SPEC.md and `examples/minimal.hyperspec.md` name a
119
+ placeholder author, `example-author`, and a placeholder factory, `my-factory`.
120
+ - Requires `@supersuit/superskill` 0.2.2, whose YAML reader reads an inline map (`scope: { form: essay, purpose: persuade }`), a bare inline map as a list item, and an inline list followed by a comment. On 0.2.1 those came back as text, so a correct spec written in that compact style failed. A test lints the essay example rewritten in that style.
121
+
3
122
  ## 0.2.0 (2026-09-28)
4
123
 
5
124
  Recipes. Every output a factory makes can now carry a recipe beside it: what made it, from
package/README.md CHANGED
@@ -24,13 +24,15 @@ improvement ledger. Every test is defined in [SPEC.md](SPEC.md).
24
24
  |---|---|
25
25
  | `hyperspec lint <file...> [--json]` | Score each hyperspec against the nine tests. |
26
26
  | `hyperspec init <file> [--title T] [--kind K]` | Write a new hyperspec skeleton. Refuses to overwrite an existing file. |
27
+ | `hyperspec init <file> --profile writing [--title T] [--form F] [--fiction]` | Write a writing-spec skeleton, every block shown with placeholders. |
28
+ | `hyperspec segments init <material> --id <mid> [--out F] [--by paragraph\|sentence]` | Split a material into segments to label. Refuses to overwrite an existing file. |
27
29
  | `hyperspec recipe check <output-or-recipe>` | Check that a recipe records everything the standard asks for. |
28
30
  | `hyperspec recipe approve <recipe> --by <slug>` | Record who approved the output. |
29
31
  | `hyperspec reproduce <recipe> [--restore]` | Re-check every hash the recipe recorded. Never runs a model. |
30
32
  | `hyperspec regenerate <recipe> --out <path> --clicker <slug> <one change> [--run cmd]` | Make a child recipe from a parent and one named change, rerunning only the stages it reaches. |
31
33
  | `hyperspec compare <child-recipe> --doctor cmd` | Grade a child and its parent through one doctor against one spec. |
32
34
 
33
- Every command except `init` takes `--json`. `hyperspec --help` prints every flag.
35
+ Every command except `init` and `segments init` takes `--json`. `hyperspec --help` prints every flag.
34
36
 
35
37
  ## Exit codes
36
38
 
@@ -103,11 +105,59 @@ recipe.finish();
103
105
  The schema, the stage key, the runner and doctor contracts, and every exit code are in
104
106
  [SPEC.md](SPEC.md#recipes).
105
107
 
108
+ ## Writing specs
109
+
110
+ A piece of writing gets its own profile. Add `profile: writing` to a hyperspec and it gains nine
111
+ blocks that name what an agent would otherwise fill with the average: the materials it draws on
112
+ and how far each can be trusted, the writer's voice scoped to this form, audience and purpose,
113
+ who the piece speaks as, who reads it and what they already know, the one change the piece is
114
+ for, its form, the claims it argues in order, where every fact comes from, and in fiction every
115
+ character who speaks. Findings still report under the nine tests, and `lint` adds one line:
116
+
117
+ ```
118
+ essay.hyperspec.md: pass (9/9)
119
+ writing: 9/9 blocks complete
120
+ ```
121
+
122
+ Start one with every block laid out and waiting:
123
+
124
+ ```bash
125
+ npx @supersuit/hyperspec init essay.hyperspec.md --profile writing --title "Your title"
126
+ npx @supersuit/hyperspec init story.hyperspec.md --profile writing --form "short story" --fiction
127
+ ```
128
+
129
+ The skeleton fails until every placeholder is real and its four open questions (whose voice,
130
+ who speaks, who reads, what changes) are answered. The blocks, every field, and which test
131
+ each rule reports under are in [WRITING.md](WRITING.md). Two complete specs that pass with
132
+ nothing to warn ship in `examples/writing/`: an essay for new managers, and a short story with
133
+ two characters whose voices a judge can tell apart.
134
+
135
+ ### Marking materials
136
+
137
+ Every material a writing spec draws on is marked before the spec can pass: split into segments,
138
+ and each segment labeled with what it may be used as (claim, story, quote, stance, question,
139
+ aside, private). hyperspec does the splitting and the checking; an agent or a person does the
140
+ labeling.
141
+
142
+ ```bash
143
+ npx @supersuit/hyperspec segments init materials/voice-memo.md --id voice-memo
144
+ npx @supersuit/hyperspec lint essay.hyperspec.md
145
+ ```
146
+
147
+ The first writes `materials/voice-memo.md.segments.jsonl`, every segment `unlabeled`. Name that
148
+ file as `segments:` on the material item, label every segment, and `lint` checks that each label
149
+ is from the set and carries what it needs, that each segment matches the material word for word,
150
+ that the material has not changed since, and that no spine claim cites a private or question
151
+ segment. The file format, the labels, and every finding are in
152
+ [WRITING.md](WRITING.md#marking-materials). A tool of your own can run the same check with
153
+ `import { readSegments } from "@supersuit/hyperspec/writing"`.
154
+
106
155
  ## The format
107
156
 
108
157
  A hyperspec is a markdown file with a YAML frontmatter block: `decisions`, `requirements`,
109
- `rejects`, `examples`, `resume`, `feedback`, and `improvement`. The full field-by-field
110
- standard, including what makes each of the nine tests fail, is in [SPEC.md](SPEC.md).
158
+ `rejects`, `examples`, `resume`, `feedback`, and `improvement`, plus an optional `profile`.
159
+ The full field-by-field standard, including what makes each of the nine tests fail, is in
160
+ [SPEC.md](SPEC.md).
111
161
 
112
162
  ## Install
113
163
 
package/SPEC.md CHANGED
@@ -39,6 +39,12 @@ decisions:
39
39
  source: SPEC.md, section "Recipes"
40
40
  author: agent:claude
41
41
  chosen_by: agent
42
+ - id: profiles
43
+ state: decided
44
+ value: a profile adds rules for one kind of work under the nine tests; it never adds a tenth test, every finding it raises names one of the nine, and the score stays out of nine
45
+ source: WRITING.md, section "The writing profile"
46
+ author: agent:claude
47
+ chosen_by: agent
42
48
  requirements:
43
49
  - id: r1
44
50
  text: lint exits 0 only when all nine tests pass and nothing is open
@@ -91,7 +97,7 @@ examples:
91
97
  - path: examples/minimal.hyperspec.md
92
98
  why: the smallest spec that passes all nine tests
93
99
  resume:
94
- next_action: collect adopter issues on 0.2, recipes included, and cut 0.3 from them
100
+ next_action: collect adopter issues on 0.4, materials marking included, and cut 0.5 from them
95
101
  feedback:
96
102
  issues: https://github.com/SupersuitUp/hyperspec/issues
97
103
  fork: MIT; fork it for your own purposes and say so in your SPEC
@@ -103,7 +109,7 @@ improvement:
103
109
 
104
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.
105
111
 
106
- **Version 0.2.0** (2026-09-28)
112
+ **Version 0.4.0** (2026-09-29)
107
113
 
108
114
  ## What makes a spec a hyperspec
109
115
 
@@ -161,7 +167,7 @@ decisions:
161
167
  state: decided # decided | delegated | open
162
168
  value: the operator, reading on a phone
163
169
  source: interview A2 # where it came from
164
- author: gary-sheng # a person slug, or agent:<model>
170
+ author: example-author # a person slug, or agent:<model>
165
171
  chosen_by: human # human | agent
166
172
  - id: length
167
173
  state: delegated
@@ -182,7 +188,7 @@ requirements:
182
188
  check:
183
189
  rubric: ask the simulated reader to define the term; pass only on a correct definition
184
190
  source: design doc, audience block
185
- author: gary-sheng
191
+ author: example-author
186
192
  rejects:
187
193
  - hype words about AI
188
194
  examples:
@@ -200,7 +206,7 @@ improvement:
200
206
 
201
207
  ## The test-to-field map
202
208
 
203
- Each row lists every condition under which `hyperspec lint` fails that test. A warning never fails a test. A value that is only a YAML comment (`source: # TODO`), or `null`, or `~`, counts as missing. A quoted value that happens to start with `#` (`source: "# literal"`) is real text and counts as present.
209
+ Each row lists every condition under which `hyperspec lint` fails that test. A warning never fails a test. A value that is only a YAML comment (`source: # TODO`), `null`, `~`, or a placeholder counts as missing. A placeholder is a whole value, trimmed and in any case, of `todo`, `tbd`, `fixme`, `xxx`, `placeholder`, `<placeholder>`, `n/a`, a run of dashes, a run of question marks, or an ellipsis, optionally followed by a trailing `.`, `:` or `!`. Real text that starts with one of those (`TODO: write the opening`) counts as present, and so do `none` and a quoted value that happens to start with `#` (`source: "# literal"`).
204
210
 
205
211
  | Test | Fails when |
206
212
  |---|---|
@@ -210,10 +216,12 @@ Each row lists every condition under which `hyperspec lint` fails that test. A w
210
216
  | 4 every field says where it came from and who wrote it | a decision or requirement without `source` or `author`; a decision whose `chosen_by` is not human or agent |
211
217
  | 5 negative space is specified | `rejects` missing or empty; a `rejects` item that is not a plain string |
212
218
  | 6 examples outrank adjectives | `examples` missing or empty; an example without `path` or `why`; a `path` that is not an http(s) URL and does not exist, is a folder, or is the spec itself, read relative to the spec or as an absolute path |
213
- | 7 a stranger can resume it | `resume.next_action` missing; a `next_action` that is only a no-action word (`continue`, `follow up`, `tbd`, `todo`, `keep going`, `pick it back up`, `n/a`, `none`); a `next_action` that says `as discussed` or `as mentioned earlier` or `above`. Those pointers in the body are a warning, and so is a `hyperspec` version this linter does not know |
219
+ | 7 a stranger can resume it | `resume.next_action` missing; a `next_action` that is only a no-action word (`continue`, `follow up`, `tbd`, `todo`, `keep going`, `pick it back up`, `n/a`, `none`); a `next_action` that says `as discussed` or `as mentioned earlier` or `above`. Those pointers in the body are a warning, and so are a `hyperspec` version and a `profile` this linter does not know |
214
220
  | 8 its adopters can push back on it | `feedback.issues` or `feedback.fork` missing |
215
221
  | 9 it improves itself | `improvement.ledger` missing; a ledger path that exists and is not a readable file; if the ledger file exists, a line that is not a JSON object, a `verdict` outside one-shot, improved or not-improved, `improved` without `change`, `not-improved` without `reason`. A declared ledger that does not exist yet is a warning |
216
222
 
223
+ A profile adds its own conditions to these rows. The writing profile's are in [WRITING.md](WRITING.md#the-test-mapping), including the checks on each material's segments file: every material marked, every segment labeled from the closed set and matching its material word for word, the marking current (tests 1 and 4), and no spine claim citing a private or question segment (test 5).
224
+
217
225
  ## Exit codes
218
226
 
219
227
  `hyperspec lint` reports the worst result across every file it is given:
@@ -233,6 +241,12 @@ Every run of a skill that works from a hyperspec writes one line to the ledger n
233
241
 
234
242
  Silence is not a verdict. A run that learned nothing has to say so and why, and a ledger line with none of the three verdicts fails the ninth test.
235
243
 
244
+ ## Profiles
245
+
246
+ A profile adds the rules for one kind of work on top of the nine tests. A spec opts in with a top-level `profile:` naming it. A profile never adds a tenth test: every finding it raises reports under one of the nine, with an id that starts with the profile's name, and the score stays out of nine. `lint` prints one more line for a profiled spec, how many of the profile's blocks are complete. A `profile` this linter does not know is a warning under test 7, and none of its rules are checked.
247
+
248
+ One profile ships: `writing`, for essays, chapters, letters, stories and anything else an agent drafts for a person to read. Its blocks, its fields, which test each rule reports under, `hyperspec init --profile writing`, and marking materials with `hyperspec segments init` are in [WRITING.md](WRITING.md).
249
+
236
250
  ## Recipes
237
251
 
238
252
  A hyperspec says what the work must be. A recipe records what one output was made from, so the output can be checked, made again with one change, and graded against the version before it. hyperspec never calls a model. Every step that needs one is a command the caller supplies: a runner for stages and a doctor for grading.
@@ -246,8 +260,8 @@ A recipe sits beside its output as `<output>.recipe.json`: JSON with a two-space
246
260
  "recipe": "0.1",
247
261
  "created": "2026-09-28T18:00:00.000Z",
248
262
  "output": { "path": "essay.md", "sha256": "<hex>" },
249
- "factory": { "name": "compose-a-piece", "version": "0.3.0" },
250
- "spec": { "path": "essay.hyperspec.md", "sha256": "<hex>", "authors": { "audience": "gary-sheng", "length": "agent:claude" } },
263
+ "factory": { "name": "my-factory", "version": "0.3.0" },
264
+ "spec": { "path": "essay.hyperspec.md", "sha256": "<hex>", "authors": { "audience": "example-author", "length": "agent:claude" } },
251
265
  "inputs": [
252
266
  { "name": "call", "path": "materials/call.md", "sha256": "<hex>", "order": 1 }
253
267
  ],
@@ -261,8 +275,8 @@ A recipe sits beside its output as `<output>.recipe.json`: JSON with a two-space
261
275
  "verdict": { "station": "outline-has-claim-chain", "pass": true, "note": "" }
262
276
  }
263
277
  ],
264
- "clicker": "gary-sheng",
265
- "approver": "gary-sheng",
278
+ "clicker": "example-author",
279
+ "approver": "example-author",
266
280
  "parent": null,
267
281
  "change": null
268
282
  }