paperlint 9.0.1 → 10.0.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 (150) hide show
  1. package/README.md +68 -128
  2. package/dist/build.d.ts +1 -1
  3. package/dist/build.js +1 -1
  4. package/dist/cli.d.ts +5 -1
  5. package/dist/cli.d.ts.map +1 -1
  6. package/dist/cli.js +52 -6
  7. package/dist/cli.js.map +1 -1
  8. package/dist/domain/layout-tree.d.ts +19 -0
  9. package/dist/domain/layout-tree.d.ts.map +1 -0
  10. package/dist/domain/layout-tree.js +32 -0
  11. package/dist/domain/layout-tree.js.map +1 -0
  12. package/dist/domain/lookup-cache.d.ts +2 -2
  13. package/dist/domain/lookup-cache.js +2 -2
  14. package/dist/domain/paper-layout.d.ts +81 -0
  15. package/dist/domain/paper-layout.d.ts.map +1 -0
  16. package/dist/domain/paper-layout.js +259 -0
  17. package/dist/domain/paper-layout.js.map +1 -0
  18. package/dist/domain/repro-layout.d.ts +80 -0
  19. package/dist/domain/repro-layout.d.ts.map +1 -0
  20. package/dist/domain/repro-layout.js +247 -0
  21. package/dist/domain/repro-layout.js.map +1 -0
  22. package/dist/domain/scaffold-layout.d.ts +28 -0
  23. package/dist/domain/scaffold-layout.d.ts.map +1 -0
  24. package/dist/domain/scaffold-layout.js +81 -0
  25. package/dist/domain/scaffold-layout.js.map +1 -0
  26. package/dist/eslint-rules/prereg-coverage.d.ts +98 -0
  27. package/dist/eslint-rules/prereg-coverage.d.ts.map +1 -0
  28. package/dist/eslint-rules/prereg-coverage.js +274 -0
  29. package/dist/eslint-rules/prereg-coverage.js.map +1 -0
  30. package/dist/folder-layout-hook.d.ts +21 -0
  31. package/dist/folder-layout-hook.d.ts.map +1 -0
  32. package/dist/folder-layout-hook.js +117 -0
  33. package/dist/folder-layout-hook.js.map +1 -0
  34. package/dist/folder-layout-rule.d.ts +22 -0
  35. package/dist/folder-layout-rule.d.ts.map +1 -0
  36. package/dist/folder-layout-rule.js +107 -0
  37. package/dist/folder-layout-rule.js.map +1 -0
  38. package/dist/init.js +1 -1
  39. package/dist/init.js.map +1 -1
  40. package/dist/new-paper.d.ts +4 -1
  41. package/dist/new-paper.d.ts.map +1 -1
  42. package/dist/new-paper.js +40 -6
  43. package/dist/new-paper.js.map +1 -1
  44. package/dist/references.d.ts +1 -1
  45. package/dist/references.d.ts.map +1 -1
  46. package/dist/references.js +2 -2
  47. package/dist/references.js.map +1 -1
  48. package/dist/repro-layout-rule.d.ts +16 -0
  49. package/dist/repro-layout-rule.d.ts.map +1 -0
  50. package/dist/repro-layout-rule.js +81 -0
  51. package/dist/repro-layout-rule.js.map +1 -0
  52. package/docs/ci.md +60 -0
  53. package/docs/configuration.md +2 -0
  54. package/docs/e2e.md +2 -2
  55. package/docs/install.md +20 -16
  56. package/docs/layout.md +154 -0
  57. package/docs/optional-rules.md +5 -4
  58. package/docs/references.md +5 -2
  59. package/docs/rules/paper/allowed-files-only.md +192 -0
  60. package/docs/rules/repro/allowed-files-only.md +128 -0
  61. package/docs/rules/study/declare-sample.md +146 -0
  62. package/docs/rules.md +53 -50
  63. package/docs/skills.md +6 -3
  64. package/docs/venues.md +94 -0
  65. package/eslint-rules/prereg-coverage.test.ts +448 -0
  66. package/eslint-rules/prereg-coverage.ts +419 -0
  67. package/lib/skill-trigger-cases.harness.mjs +51 -5
  68. package/lib/skill-trigger-cases.mjs +53 -15
  69. package/package.json +1 -1
  70. package/plugin/hooks/hooks.json +9 -0
  71. package/skills/analyze-sibling-paper/SKILL.md +2 -2
  72. package/skills/analyze-sibling-paper/SKILL.md.spec.ts +1 -1
  73. package/skills/build-benchmark/SKILL.md +14 -1
  74. package/skills/build-benchmark/SKILL.md.spec.ts +13 -0
  75. package/skills/build-label-page/SKILL.md +118 -0
  76. package/skills/build-label-page/SKILL.md.spec.ts +129 -0
  77. package/skills/build-label-page/build-label-page.eval.mjs +15 -0
  78. package/skills/build-label-page/build-label-page.test.ts +959 -0
  79. package/skills/build-label-page/references/checklist.md +148 -0
  80. package/skills/build-label-page/references/example-generator.py +803 -0
  81. package/skills/find-venue/SKILL.md +5 -3
  82. package/skills/find-venue/SKILL.md.spec.ts +4 -2
  83. package/skills/grade-paper-writing/SKILL.md +7 -7
  84. package/skills/grade-paper-writing/SKILL.md.spec.ts +6 -6
  85. package/skills/map-prior-work/SKILL.md +2 -2
  86. package/skills/map-prior-work/SKILL.md.spec.ts +1 -1
  87. package/skills/paper-pipeline/SKILL.md +8 -6
  88. package/skills/paper-pipeline/SKILL.md.spec.ts +7 -5
  89. package/skills/paper-pipeline/grade-paper-writing-ablation.eval.mjs +19 -9
  90. package/skills/paper-pipeline/references/acceptance-gate.md +19 -19
  91. package/skills/paper-pipeline/references/artifact-checklist.md +5 -0
  92. package/skills/paper-pipeline/references/pipeline-status-template.md +30 -1
  93. package/skills/paper-pipeline/repro/2026-08-07-fork-check.log +1 -1
  94. package/skills/paper-pipeline/repro/2026-08-07-fork-check2.log +1 -1
  95. package/skills/paper-pipeline/repro/2026-08-07-language-eval-pilot.log +1 -1
  96. package/skills/paper-pipeline/repro/2026-08-07-language-eval-raw.log +1 -1
  97. package/skills/paper-pipeline/repro/2026-08-08-framing-vs-vocabulary-oracle.log +48 -48
  98. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-A6-oracle.log +8 -8
  99. package/skills/paper-pipeline/repro/2026-08-08-grade-paper-writing-ablation-oracle.log +48 -48
  100. package/skills/paper-pipeline/repro/2026-08-08-parent-replication-gpw.log +2 -2
  101. package/skills/paper-pipeline/repro/2026-08-08-parent-replication.mjs +3 -3
  102. package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-ablation-preflight-after.log +81 -0
  103. package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-ablation-preflight-before.log +81 -0
  104. package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-ablation-setupdiff.log +59 -0
  105. package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-trigger.jsonl +1 -0
  106. package/skills/paper-pipeline/repro/2026-10-13-grade-paper-writing-trigger.log +22 -0
  107. package/skills/paper-pipeline/repro/README.md +4 -0
  108. package/skills/paper-pipeline/scripts/extract-ref-facts.harness.mjs +2 -2
  109. package/skills/paper-pipeline/scripts/extract-ref-facts.mjs +2 -2
  110. package/skills/paper-pipeline/scripts/extract-ref-facts.test.mjs +4 -2
  111. package/skills/paper-pipeline/scripts/generated-code.harness.mjs +7 -2
  112. package/skills/paper-pipeline/scripts/generated-code.mjs +8 -4
  113. package/skills/paper-pipeline/scripts/generated-code.test.ts +15 -1
  114. package/skills/paper-status/SKILL.md +2 -2
  115. package/skills/paper-status/SKILL.md.spec.ts +1 -1
  116. package/skills/study-accepted-papers/SKILL.md +163 -161
  117. package/skills/study-accepted-papers/SKILL.md.spec.ts +167 -165
  118. package/skills/study-accepted-papers/references/base-rates.md +69 -0
  119. package/skills/study-accepted-papers/references/mechanisms.md +181 -0
  120. package/skills/verify-citations/SKILL.md +2 -2
  121. package/skills/verify-citations/SKILL.md.spec.ts +1 -1
  122. package/src/build.ts +1 -1
  123. package/src/cli.harness.mjs +42 -0
  124. package/src/cli.test.ts +90 -6
  125. package/src/cli.ts +78 -5
  126. package/src/domain/layout-tree.test.ts +32 -0
  127. package/src/domain/layout-tree.ts +47 -0
  128. package/src/domain/lookup-cache.ts +2 -2
  129. package/src/domain/paper-layout.test.ts +264 -0
  130. package/src/domain/paper-layout.ts +336 -0
  131. package/src/domain/repro-layout.test.ts +222 -0
  132. package/src/domain/repro-layout.ts +311 -0
  133. package/src/domain/scaffold-layout.ts +104 -0
  134. package/src/folder-layout-hook.test.ts +214 -0
  135. package/src/folder-layout-hook.ts +141 -0
  136. package/src/folder-layout-rule.test.ts +235 -0
  137. package/src/folder-layout-rule.ts +151 -0
  138. package/src/hooks-settings.harness.ts +9 -8
  139. package/src/init.ts +1 -1
  140. package/src/layout-docs.test.ts +52 -0
  141. package/src/new-paper.harness.mjs +23 -1
  142. package/src/new-paper.test.ts +299 -6
  143. package/src/new-paper.ts +51 -5
  144. package/src/paper-files.test.ts +9 -6
  145. package/src/references.test.ts +5 -5
  146. package/src/references.ts +2 -2
  147. package/src/repro-layout-rule.test.ts +114 -0
  148. package/src/repro-layout-rule.ts +121 -0
  149. package/src/rule-cases.test.ts +98 -0
  150. package/templates/paper/PIPELINE-STATUS.md +41 -7
@@ -5,7 +5,7 @@ context: fork
5
5
  allowed-tools: [Read, Write, Edit, Grep, Glob, Bash, Agent]
6
6
  ---
7
7
 
8
- <!-- vigiles:sha256:0b91129ca6a6b2a3 compiled from skills/build-benchmark/SKILL.md.spec.ts -->
8
+ <!-- vigiles:sha256:5eb2ba9561e082d9 compiled from skills/build-benchmark/SKILL.md.spec.ts -->
9
9
 
10
10
  # build-benchmark — the study + the artifact reviewers can run
11
11
 
@@ -51,6 +51,17 @@ is the *inverse* of the flaw:
51
51
 
52
52
  Write the design as the answer to "what would make the critiqued pitfall impossible here?"
53
53
 
54
+ **Declare the population, the screens and the coverage before freezing the sample.** Each screen
55
+ between the population and the sample (fits one excerpt, one classifier lane, a model-picked item)
56
+ changes what the sample can say, not only its size; screens that are reasonable one by one can leave a
57
+ sample nobody meets in practice. So, before the draw is frozen, the study's `prereg.json` says what
58
+ the claim is about, what each screen removed per stratum and what share the sample can represent; then
59
+ show the author the drawn **units** (the rules or cases, not the items made from them) and ask: *is
60
+ this what you meet in practice?* The fields are the experimental rule
61
+ `study/declare-sample` (`docs/rules/study/declare-sample.md`), off by default: do this step either way,
62
+ and turn the check on with `"rules": { "study/declare-sample": "error" }` in the paper's `paperlint.json`
63
+ for `paperlint lint` to fail until they are there.
64
+
54
65
  ## 2. Honest statistics — the part reviewers attack first
55
66
 
56
67
  - **Paired where the design is paired; Welch where variances differ.** Use a **paired-t** when the same
@@ -156,6 +167,8 @@ Before submitting, verify the artifact you built with the reviewer-side reproduc
156
167
  - **argument-arc (frame mode)** — 🔴 **hard input.** Owns row `frame`, the stated claim. No `frame`, no study.
157
168
  - **research-ideate** (upstream) — supplies the contribution and the pitfall to invert; this skill turns
158
169
  it into evidence.
170
+ - **build-label-page** — when the study needs a person to label items (gold labels, a blind review of
171
+ outputs): it builds the page, publishes it and exports the answers into the study's `data/`.
159
172
  - **draft-paper** — the study's stats, bound, and artifact-number table feed Methods/Results/Availability.
160
173
  - **pc-panel-review** — its artifact-runner reviewer `cd`s in and re-executes every harness; build so
161
174
  that pass is deterministic.
@@ -57,6 +57,17 @@ is the *inverse* of the flaw:
57
57
 
58
58
  Write the design as the answer to "what would make the critiqued pitfall impossible here?"
59
59
 
60
+ **Declare the population, the screens and the coverage before freezing the sample.** Each screen
61
+ between the population and the sample (fits one excerpt, one classifier lane, a model-picked item)
62
+ changes what the sample can say, not only its size; screens that are reasonable one by one can leave a
63
+ sample nobody meets in practice. So, before the draw is frozen, the study's \`prereg.json\` says what
64
+ the claim is about, what each screen removed per stratum and what share the sample can represent; then
65
+ show the author the drawn **units** (the rules or cases, not the items made from them) and ask: *is
66
+ this what you meet in practice?* The fields are the experimental rule
67
+ \`study/declare-sample\` (\`docs/rules/study/declare-sample.md\`), off by default: do this step either way,
68
+ and turn the check on with \`"rules": { "study/declare-sample": "error" }\` in the paper's \`paperlint.json\`
69
+ for \`paperlint lint\` to fail until they are there.
70
+
60
71
  ## 2. Honest statistics — the part reviewers attack first
61
72
 
62
73
  - **Paired where the design is paired; Welch where variances differ.** Use a **paired-t** when the same
@@ -162,6 +173,8 @@ Before submitting, verify the artifact you built with the reviewer-side reproduc
162
173
  - **argument-arc (frame mode)** — 🔴 **hard input.** Owns row \`frame\`, the stated claim. No \`frame\`, no study.
163
174
  - **research-ideate** (upstream) — supplies the contribution and the pitfall to invert; this skill turns
164
175
  it into evidence.
176
+ - **build-label-page** — when the study needs a person to label items (gold labels, a blind review of
177
+ outputs): it builds the page, publishes it and exports the answers into the study's \`data/\`.
165
178
  - **draft-paper** — the study's stats, bound, and artifact-number table feed Methods/Results/Availability.
166
179
  - **pc-panel-review** — its artifact-runner reviewer \`cd\`s in and re-executes every harness; build so
167
180
  that pass is deterministic.
@@ -0,0 +1,118 @@
1
+ ---
2
+ name: build-label-page
3
+ description: Build a phone labelling page published as a claude.ai Artifact with a shared answer store, and export the answers into the paper's study folder. Use when a study needs a person to label items (gold labels, a blind review of model outputs, "is this a real boundary case"), or on "a page to label these", "a gold-labelling page", "a blind review page". Carries the seven rules that keep such a page honest. Composes with build-benchmark and draft-paper.
4
+ allowed-tools: [Read, Write, Edit, Grep, Glob, Bash, Artifact, ArtifactData]
5
+ ---
6
+
7
+ <!-- vigiles:sha256:894d8a2df3f5c319 compiled from skills/build-label-page/SKILL.md.spec.ts -->
8
+
9
+ # build-label-page — a page the person labels on a phone, and the labels back in the repo
10
+
11
+ When a study needs a person to decide something about each of many items, a chat thread is the wrong
12
+ tool: it loses answers, shows the model's own output next to the question and gives no count of what
13
+ is left. Build a page instead. The agent generates it from the items, publishes it as an Artifact with
14
+ a shared answer store (the `db` capability), the person answers on a phone, and the agent exports the
15
+ answers into the study's `data/` folder. The labels are data the paper's numbers trace to, so they are
16
+ committed, not left in the store.
17
+
18
+ **Not for** an LLM judge (no person answers), a questionnaire about the person, or a form that collects
19
+ anything but labels.
20
+
21
+ ## The seven rules
22
+
23
+ The full text, each with its reason and its check, is
24
+ [`references/checklist.md`](references/checklist.md). Read it before building. In one line each:
25
+
26
+ 1. **Test it in the claude.ai phone viewer before sending the link.** The viewer can size the frame to
27
+ the page, so the page cannot scroll itself and a fixed toast may be off-screen. A plain browser
28
+ passing proves nothing about this.
29
+ 2. **Navigation never relies on in-page scrolling or toasts.** "Next unanswered" is a filter: it hides
30
+ every finished item and group, and a note at the top lists what is left and what each still needs.
31
+ 3. **An item is done only when every question on it is answered.** The card names the missing
32
+ question; the progress counter counts complete items only.
33
+ 4. **Blind.** Neutral ids (`G001`…), order shuffled with a fixed seed, no model answers, verdicts or
34
+ source labels on the page. The generator refuses to build when an item carries a field outside an
35
+ allow-list; new question wording is added to the allow-list on purpose.
36
+ 5. **Ask only what the labeller can answer.** Only the languages and tools they know; one "how well do
37
+ you know it" question per group, used later as an analysis filter; "clear-cut or real boundary"
38
+ is the labeller's judgement, not the designer's.
39
+ 6. **Export into the repository right away**, one JSON per page into the study's `data/` with the
40
+ export date, commit it, and record answers given in chat with `source: "chat"`. If the page fails,
41
+ take the last answers in chat; patch the page blind at most once.
42
+ 7. **Save on click**, no submit button; "Saved <time>" on every card; survive a reload; render
43
+ readable, with a banner, when the store is unavailable.
44
+
45
+ ## Procedure
46
+
47
+ 1. **Decide the labelling.** What exactly does the labeller decide per item (the questions, each with
48
+ a closed set of answers)? Which groups (languages, tools) does the labeller know? How many items
49
+ fit the time they have on a phone? Who is the labeller: a page with a store opens only for people
50
+ with access to the artifact, so the labeller is the owner or has been shared as a Contributor.
51
+ If the study design is not written yet, `build-benchmark` comes first.
52
+ If the items come from a drawn sample, the study's `prereg.json` declares the population, the
53
+ screens and the coverage before the sample is frozen (the experimental rule `study/declare-sample` checks it, off by default), and the
54
+ author has been shown the drawn **units** (the rules or cases, not the items) with "is this what
55
+ you meet in practice?". The labelling page is not that check: items made from easy units each look
56
+ fine on their own.
57
+ 2. **Copy the generator into the study and write the items.** The study folder is
58
+ `<paper-dir>/repro/<slug>-YYYY-MM-DD/` (`gold-labels-2026-10-12`; `repro/allowed-files-only` wants the
59
+ date, a `README.md` in it saying what the study asks, and a line in `repro/README.md`; where this
60
+ sits in stage 3, and what checks each place: `docs/layout.md` in the paperlint package).
61
+ `items.json` follows the header of the generator. Source ids in `items.json` are the study's own;
62
+ the page never shows them.
63
+
64
+ ```bash
65
+ cp ${CLAUDE_SKILL_DIR}/references/example-generator.py <study-dir>/make_label_page.py
66
+ ```
67
+
68
+ The generator is a template: change the questions and keep the guards (allow-list, neutral ids,
69
+ store-unavailable banner, filter instead of scrolling). Do not loosen the allow-list to make a
70
+ build pass; take the field out of the item.
71
+ 3. **Build and read it as the labeller.** From the study folder (`<study-dir>`):
72
+
73
+ ```bash
74
+ python3 make_label_page.py build items.json label-page
75
+ ```
76
+
77
+ This writes `label-page/page.html` and `label-page/key.json` (the only link from `G001` to the
78
+ source id; it never goes on the page). Rebuilding with the same seed keeps every id, and a new item
79
+ gets the next one. Read the page text once as a person who knows nothing about the source: if
80
+ anything on it tells the answer, take it out of the item.
81
+ 4. **Publish.** Load `artifact-design` and `artifact-capabilities`, then publish `page.html` with
82
+ `capabilities: {db: {}}`. Use a title of two to four words. Do not ask the page for `user` or
83
+ anything else it does not use.
84
+ 5. **Test in the viewer (rule 1)** and list the store once with `ArtifactData` (`list` of
85
+ `answers`) to confirm the test answer arrived. `ArtifactData` can be a deferred tool: load it with
86
+ `ToolSearch` first. Then delete the test answer's document, or tell the person which one it is
87
+ and keep it out of the export.
88
+ 6. **Send the link** with one line on how it works: tap an answer, it saves; "Next unanswered" shows
89
+ what is left. Say what you tested and what you could not.
90
+ 7. **Export when the person is done, or stops** (rule 6). Save the store's two collections, `answers`
91
+ and `groups`, as `dump.json` in the shape the generator's header gives (answers given in chat go
92
+ in with `"source": "chat"`), then:
93
+
94
+ ```bash
95
+ python3 make_label_page.py export dump.json label-page/key.json data
96
+ ```
97
+
98
+ It writes `data/<study>-labels-<date>.json` and prints every incomplete item, every answer or
99
+ familiarity value that is not one of the offered options (not counted, same rule as on the page;
100
+ correct it in the dump and export again) and every group with no familiarity answer. Commit the file in the same pass, and add the line "labels →
101
+ `data/<study>-labels-<date>.json`" to the paper's `NOTES.md` for the numbers that use them.
102
+
103
+ ## When the page misbehaves
104
+
105
+ Look at what the store holds (`ArtifactData` `list`) before changing anything: the page may be fine
106
+ and the person may have opened it without access. One fix to the page is allowed. If it fails again,
107
+ ask for the remaining answers in chat, write them into the dump with `"source": "chat"`, and export.
108
+ Do not iterate on a page you cannot see.
109
+
110
+ ## Compose with
111
+
112
+ - **build-benchmark** — owns the study design and the inter-rater rule: agreement with the person who
113
+ wrote the codebook measures trainability, not reliability, so the labeller for gold labels is
114
+ someone who did not write the scheme.
115
+ - **draft-paper** — the exported labels, the familiarity filter and the complete-item count feed the
116
+ Methods and the threats.
117
+ - **submit-paper** — a published artifact page is not anonymous. Do not link it from an anonymized
118
+ submission; the exported JSON is what goes into the reproduction artifact.
@@ -0,0 +1,129 @@
1
+ // Compiled to SKILL.md by `vigiles compile`. Edit THIS file, never the markdown.
2
+ import { experimental_skill } from "vigiles/spec";
3
+
4
+ export default experimental_skill({
5
+ name: "build-label-page",
6
+ description:
7
+ 'Build a phone labelling page published as a claude.ai Artifact with a shared answer store, and export the answers into the paper\'s study folder. Use when a study needs a person to label items (gold labels, a blind review of model outputs, "is this a real boundary case"), or on "a page to label these", "a gold-labelling page", "a blind review page". Carries the seven rules that keep such a page honest. Composes with build-benchmark and draft-paper.',
8
+ tools: [
9
+ "Read",
10
+ "Write",
11
+ "Edit",
12
+ "Grep",
13
+ "Glob",
14
+ "Bash",
15
+ "Artifact",
16
+ "ArtifactData",
17
+ ],
18
+ body: `
19
+ # build-label-page — a page the person labels on a phone, and the labels back in the repo
20
+
21
+ When a study needs a person to decide something about each of many items, a chat thread is the wrong
22
+ tool: it loses answers, shows the model's own output next to the question and gives no count of what
23
+ is left. Build a page instead. The agent generates it from the items, publishes it as an Artifact with
24
+ a shared answer store (the \`db\` capability), the person answers on a phone, and the agent exports the
25
+ answers into the study's \`data/\` folder. The labels are data the paper's numbers trace to, so they are
26
+ committed, not left in the store.
27
+
28
+ **Not for** an LLM judge (no person answers), a questionnaire about the person, or a form that collects
29
+ anything but labels.
30
+
31
+ ## The seven rules
32
+
33
+ The full text, each with its reason and its check, is
34
+ [\`references/checklist.md\`](references/checklist.md). Read it before building. In one line each:
35
+
36
+ 1. **Test it in the claude.ai phone viewer before sending the link.** The viewer can size the frame to
37
+ the page, so the page cannot scroll itself and a fixed toast may be off-screen. A plain browser
38
+ passing proves nothing about this.
39
+ 2. **Navigation never relies on in-page scrolling or toasts.** "Next unanswered" is a filter: it hides
40
+ every finished item and group, and a note at the top lists what is left and what each still needs.
41
+ 3. **An item is done only when every question on it is answered.** The card names the missing
42
+ question; the progress counter counts complete items only.
43
+ 4. **Blind.** Neutral ids (\`G001\`…), order shuffled with a fixed seed, no model answers, verdicts or
44
+ source labels on the page. The generator refuses to build when an item carries a field outside an
45
+ allow-list; new question wording is added to the allow-list on purpose.
46
+ 5. **Ask only what the labeller can answer.** Only the languages and tools they know; one "how well do
47
+ you know it" question per group, used later as an analysis filter; "clear-cut or real boundary"
48
+ is the labeller's judgement, not the designer's.
49
+ 6. **Export into the repository right away**, one JSON per page into the study's \`data/\` with the
50
+ export date, commit it, and record answers given in chat with \`source: "chat"\`. If the page fails,
51
+ take the last answers in chat; patch the page blind at most once.
52
+ 7. **Save on click**, no submit button; "Saved <time>" on every card; survive a reload; render
53
+ readable, with a banner, when the store is unavailable.
54
+
55
+ ## Procedure
56
+
57
+ 1. **Decide the labelling.** What exactly does the labeller decide per item (the questions, each with
58
+ a closed set of answers)? Which groups (languages, tools) does the labeller know? How many items
59
+ fit the time they have on a phone? Who is the labeller: a page with a store opens only for people
60
+ with access to the artifact, so the labeller is the owner or has been shared as a Contributor.
61
+ If the study design is not written yet, \`build-benchmark\` comes first.
62
+ If the items come from a drawn sample, the study's \`prereg.json\` declares the population, the
63
+ screens and the coverage before the sample is frozen (the experimental rule \`study/declare-sample\` checks it, off by default), and the
64
+ author has been shown the drawn **units** (the rules or cases, not the items) with "is this what
65
+ you meet in practice?". The labelling page is not that check: items made from easy units each look
66
+ fine on their own.
67
+ 2. **Copy the generator into the study and write the items.** The study folder is
68
+ \`<paper-dir>/repro/<slug>-YYYY-MM-DD/\` (\`gold-labels-2026-10-12\`; \`repro/allowed-files-only\` wants the
69
+ date, a \`README.md\` in it saying what the study asks, and a line in \`repro/README.md\`; where this
70
+ sits in stage 3, and what checks each place: \`docs/layout.md\` in the paperlint package).
71
+ \`items.json\` follows the header of the generator. Source ids in \`items.json\` are the study's own;
72
+ the page never shows them.
73
+
74
+ \`\`\`bash
75
+ cp \${CLAUDE_SKILL_DIR}/references/example-generator.py <study-dir>/make_label_page.py
76
+ \`\`\`
77
+
78
+ The generator is a template: change the questions and keep the guards (allow-list, neutral ids,
79
+ store-unavailable banner, filter instead of scrolling). Do not loosen the allow-list to make a
80
+ build pass; take the field out of the item.
81
+ 3. **Build and read it as the labeller.** From the study folder (\`<study-dir>\`):
82
+
83
+ \`\`\`bash
84
+ python3 make_label_page.py build items.json label-page
85
+ \`\`\`
86
+
87
+ This writes \`label-page/page.html\` and \`label-page/key.json\` (the only link from \`G001\` to the
88
+ source id; it never goes on the page). Rebuilding with the same seed keeps every id, and a new item
89
+ gets the next one. Read the page text once as a person who knows nothing about the source: if
90
+ anything on it tells the answer, take it out of the item.
91
+ 4. **Publish.** Load \`artifact-design\` and \`artifact-capabilities\`, then publish \`page.html\` with
92
+ \`capabilities: {db: {}}\`. Use a title of two to four words. Do not ask the page for \`user\` or
93
+ anything else it does not use.
94
+ 5. **Test in the viewer (rule 1)** and list the store once with \`ArtifactData\` (\`list\` of
95
+ \`answers\`) to confirm the test answer arrived. \`ArtifactData\` can be a deferred tool: load it with
96
+ \`ToolSearch\` first. Then delete the test answer's document, or tell the person which one it is
97
+ and keep it out of the export.
98
+ 6. **Send the link** with one line on how it works: tap an answer, it saves; "Next unanswered" shows
99
+ what is left. Say what you tested and what you could not.
100
+ 7. **Export when the person is done, or stops** (rule 6). Save the store's two collections, \`answers\`
101
+ and \`groups\`, as \`dump.json\` in the shape the generator's header gives (answers given in chat go
102
+ in with \`"source": "chat"\`), then:
103
+
104
+ \`\`\`bash
105
+ python3 make_label_page.py export dump.json label-page/key.json data
106
+ \`\`\`
107
+
108
+ It writes \`data/<study>-labels-<date>.json\` and prints every incomplete item, every answer or
109
+ familiarity value that is not one of the offered options (not counted, same rule as on the page;
110
+ correct it in the dump and export again) and every group with no familiarity answer. Commit the file in the same pass, and add the line "labels →
111
+ \`data/<study>-labels-<date>.json\`" to the paper's \`NOTES.md\` for the numbers that use them.
112
+
113
+ ## When the page misbehaves
114
+
115
+ Look at what the store holds (\`ArtifactData\` \`list\`) before changing anything: the page may be fine
116
+ and the person may have opened it without access. One fix to the page is allowed. If it fails again,
117
+ ask for the remaining answers in chat, write them into the dump with \`"source": "chat"\`, and export.
118
+ Do not iterate on a page you cannot see.
119
+
120
+ ## Compose with
121
+
122
+ - **build-benchmark** — owns the study design and the inter-rater rule: agreement with the person who
123
+ wrote the codebook measures trainability, not reliability, so the labeller for gold labels is
124
+ someone who did not write the scheme.
125
+ - **draft-paper** — the exported labels, the familiarity filter and the complete-item count feed the
126
+ Methods and the threats.
127
+ - **submit-paper** — a published artifact page is not anonymous. Do not link it from an anonymized
128
+ submission; the exported JSON is what goes into the reproduction artifact.`,
129
+ });
@@ -0,0 +1,15 @@
1
+ /**
2
+ * build-label-page — the PAID tier: does this skill's description actually fire?
3
+ *
4
+ * The prompts live in `lib/skill-trigger-cases.mjs` beside every other skill's, so collisions with
5
+ * `build-benchmark` and `draft-paper` are visible in one table. Measures recall on its own
6
+ * territory and precision against those siblings, against the real harness.
7
+ *
8
+ * ⚠️ NEVER RUN. Written 2026-10-12 with the skill; its rate is UNKNOWN, not assumed good.
9
+ *
10
+ * Costs money; not CI.
11
+ * node skills/build-label-page/build-label-page.eval.mjs [trials]
12
+ */
13
+ import { runSkillTriggerEval } from "../../lib/skill-eval-kit.mjs";
14
+
15
+ await runSkillTriggerEval("build-label-page");