paperlint 13.1.0 → 13.3.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 (141) hide show
  1. package/.github/workflows/ci.yml +10 -0
  2. package/CLAUDE.md +9 -1
  3. package/dist/adapters/git/index.d.ts.map +1 -1
  4. package/dist/adapters/git/index.js +13 -0
  5. package/dist/adapters/git/index.js.map +1 -1
  6. package/dist/adapters/study-registry/index.d.ts +142 -1
  7. package/dist/adapters/study-registry/index.d.ts.map +1 -1
  8. package/dist/adapters/study-registry/index.js +160 -1
  9. package/dist/adapters/study-registry/index.js.map +1 -1
  10. package/dist/cli.d.ts.map +1 -1
  11. package/dist/cli.js +3 -0
  12. package/dist/cli.js.map +1 -1
  13. package/dist/doctor.d.ts.map +1 -1
  14. package/dist/doctor.js +2 -2
  15. package/dist/doctor.js.map +1 -1
  16. package/dist/domain/decide-first.d.ts +43 -0
  17. package/dist/domain/decide-first.d.ts.map +1 -1
  18. package/dist/domain/decide-first.js +45 -2
  19. package/dist/domain/decide-first.js.map +1 -1
  20. package/dist/domain/study-gates.d.ts +96 -0
  21. package/dist/domain/study-gates.d.ts.map +1 -0
  22. package/dist/domain/study-gates.js +56 -0
  23. package/dist/domain/study-gates.js.map +1 -0
  24. package/dist/domain/study-mode.d.ts +6 -0
  25. package/dist/domain/study-mode.d.ts.map +1 -1
  26. package/dist/domain/study-mode.js.map +1 -1
  27. package/dist/domain/study-registry.d.ts +24 -4
  28. package/dist/domain/study-registry.d.ts.map +1 -1
  29. package/dist/domain/study-registry.js +39 -2
  30. package/dist/domain/study-registry.js.map +1 -1
  31. package/dist/domain/study-result.d.ts +151 -0
  32. package/dist/domain/study-result.d.ts.map +1 -0
  33. package/dist/domain/study-result.js +175 -0
  34. package/dist/domain/study-result.js.map +1 -0
  35. package/dist/outputs-before-decision-rule.d.ts.map +1 -1
  36. package/dist/outputs-before-decision-rule.js +37 -3
  37. package/dist/outputs-before-decision-rule.js.map +1 -1
  38. package/dist/ports/git-history.d.ts +12 -0
  39. package/dist/ports/git-history.d.ts.map +1 -1
  40. package/dist/ports/study-registry-codec.d.ts +3 -0
  41. package/dist/ports/study-registry-codec.d.ts.map +1 -1
  42. package/dist/skills/assess-novelty/scripts/candidate_page.d.ts +1 -0
  43. package/dist/skills/assess-novelty/scripts/novelty_reader_brief.d.ts +25 -0
  44. package/dist/skills/build-label-page/scripts/label-page-cli.d.ts +6 -0
  45. package/dist/skills/build-label-page/scripts/label-page-commands.d.ts +14 -0
  46. package/dist/skills/build-label-page/scripts/label-page-core.d.ts +149 -0
  47. package/dist/skills/build-label-page/scripts/label-page-html.d.ts +5 -0
  48. package/dist/skills/build-label-page/scripts/label-page.d.ts +2 -0
  49. package/dist/study-modes.d.ts +3 -0
  50. package/dist/study-modes.d.ts.map +1 -1
  51. package/dist/study-modes.js +8 -1
  52. package/dist/study-modes.js.map +1 -1
  53. package/dist/study-registry-rule.d.ts.map +1 -1
  54. package/dist/study-registry-rule.js +1 -0
  55. package/dist/study-registry-rule.js.map +1 -1
  56. package/dist/study-result-rule.d.ts +12 -0
  57. package/dist/study-result-rule.d.ts.map +1 -0
  58. package/dist/study-result-rule.js +87 -0
  59. package/dist/study-result-rule.js.map +1 -0
  60. package/docs/design/study-gates.md +208 -0
  61. package/docs/rules/repro/outputs-before-decision.md +8 -0
  62. package/docs/rules/repro/study-registered.md +38 -15
  63. package/docs/rules/repro/study-result.md +100 -0
  64. package/docs/rules.md +1 -0
  65. package/docs/toolchain.md +1 -1
  66. package/eslint.config.mjs +52 -0
  67. package/package.json +3 -1
  68. package/presets/agentverify.md +15 -4
  69. package/schemas/plan.v2.schema.json +341 -0
  70. package/skills/assess-novelty/scripts/candidate_page.css +31 -0
  71. package/skills/assess-novelty/scripts/candidate_page.html +934 -0
  72. package/skills/assess-novelty/scripts/candidate_page.js +165 -0
  73. package/skills/assess-novelty/scripts/candidate_page.test.ts +401 -0
  74. package/skills/assess-novelty/scripts/candidate_page.ts +194 -0
  75. package/skills/assess-novelty/scripts/check_novelty.py +230 -0
  76. package/skills/assess-novelty/scripts/check_novelty.test.ts +490 -0
  77. package/skills/assess-novelty/scripts/check_novelty_coverage.test.ts +176 -0
  78. package/skills/assess-novelty/scripts/crop_quote.py +104 -0
  79. package/skills/assess-novelty/scripts/crop_quote.test.ts +130 -0
  80. package/skills/assess-novelty/scripts/fixtures/crop-quote/make_sample.py +42 -0
  81. package/skills/assess-novelty/scripts/fixtures/crop-quote/sample.pdf +106 -0
  82. package/skills/assess-novelty/scripts/fixtures/novelty/CLAIMS.md +11 -0
  83. package/skills/assess-novelty/scripts/fixtures/novelty/paper.tex +10 -0
  84. package/skills/assess-novelty/scripts/fixtures/novelty/siblings/2026-10-27-novelty-refutation.md +8 -0
  85. package/skills/assess-novelty/scripts/fixtures/novelty/siblings/data/doe-preprint.txt +63 -0
  86. package/skills/assess-novelty/scripts/fixtures/novelty/siblings/novelty.json +54 -0
  87. package/skills/assess-novelty/scripts/novelty_candidates.py +136 -0
  88. package/skills/assess-novelty/scripts/novelty_candidates.test.ts +222 -0
  89. package/skills/assess-novelty/scripts/novelty_cells.py +88 -0
  90. package/skills/assess-novelty/scripts/novelty_cells.test.ts +159 -0
  91. package/skills/assess-novelty/scripts/novelty_coverage.py +55 -0
  92. package/skills/assess-novelty/scripts/novelty_reader_brief.js +165 -0
  93. package/skills/assess-novelty/scripts/novelty_reader_brief.test.ts +251 -0
  94. package/skills/assess-novelty/scripts/novelty_reader_brief.ts +215 -0
  95. package/skills/assess-novelty/scripts/quote_match.py +34 -0
  96. package/skills/assess-novelty/scripts/script_edges.test.ts +174 -0
  97. package/skills/build-label-page/SKILL.md +85 -54
  98. package/skills/build-label-page/SKILL.md.spec.ts +85 -53
  99. package/skills/build-label-page/build-label-page.test.ts +10 -941
  100. package/skills/build-label-page/references/checklist.md +45 -3
  101. package/skills/build-label-page/references/closed-choice-generator.md +88 -0
  102. package/skills/build-label-page/scripts/label-page-cli.js +72 -0
  103. package/skills/build-label-page/scripts/label-page-cli.ts +85 -0
  104. package/skills/build-label-page/scripts/label-page-commands.js +14 -0
  105. package/skills/build-label-page/scripts/label-page-commands.ts +14 -0
  106. package/skills/build-label-page/scripts/label-page-core.js +850 -0
  107. package/skills/build-label-page/scripts/label-page-core.test.ts +1164 -0
  108. package/skills/build-label-page/scripts/label-page-core.ts +1210 -0
  109. package/skills/build-label-page/scripts/label-page-html.js +33 -0
  110. package/skills/build-label-page/scripts/label-page-html.test.ts +413 -0
  111. package/skills/build-label-page/scripts/label-page-html.ts +43 -0
  112. package/skills/build-label-page/scripts/label-page.js +70 -0
  113. package/skills/build-label-page/scripts/label-page.test.ts +71 -0
  114. package/skills/build-label-page/scripts/label-page.ts +71 -0
  115. package/skills/build-label-page/scripts/page-template.html +513 -0
  116. package/src/adapters/git/index.test.ts +33 -0
  117. package/src/adapters/git/index.ts +19 -0
  118. package/src/adapters/study-registry/gates.test.ts +181 -0
  119. package/src/adapters/study-registry/index.ts +219 -1
  120. package/src/adapters/study-registry/mode.test.ts +6 -0
  121. package/src/cli.ts +3 -0
  122. package/src/doctor.ts +4 -2
  123. package/src/domain/decide-first.test.ts +131 -0
  124. package/src/domain/decide-first.ts +92 -2
  125. package/src/domain/study-gates.ts +125 -0
  126. package/src/domain/study-measurements.test.ts +71 -0
  127. package/src/domain/study-mode.ts +6 -0
  128. package/src/domain/study-registry.ts +64 -2
  129. package/src/domain/study-result.test.ts +300 -0
  130. package/src/domain/study-result.ts +358 -0
  131. package/src/outputs-before-decision-rule.test.ts +115 -2
  132. package/src/outputs-before-decision-rule.ts +50 -2
  133. package/src/ports/git-history.ts +12 -0
  134. package/src/ports/study-registry-codec.ts +3 -0
  135. package/src/rule-cases.test.ts +74 -0
  136. package/src/studies.test.ts +3 -0
  137. package/src/study-modes.ts +10 -1
  138. package/src/study-registry-rule.ts +1 -0
  139. package/src/study-result-rule.test.ts +281 -0
  140. package/src/study-result-rule.ts +123 -0
  141. package/skills/build-label-page/references/example-generator.py +0 -803
@@ -0,0 +1,149 @@
1
+ export declare class Refusal extends Error {
2
+ readonly exitCode: number;
3
+ constructor(exitCode: number, message: string);
4
+ }
5
+ export declare const fail: (message: string) => never;
6
+ /** The lines printed since the last call, each ending in a newline. */
7
+ export declare const takePrinted: () => string;
8
+ export declare const say: (line: string) => void;
9
+ type Json = null | boolean | number | string | readonly Json[] | {
10
+ readonly [key: string]: Json;
11
+ };
12
+ type JsonObject = {
13
+ readonly [key: string]: Json;
14
+ };
15
+ type SchemaNode = {
16
+ kind: "string";
17
+ required: boolean;
18
+ pattern?: string;
19
+ } | {
20
+ kind: "integer";
21
+ required: boolean;
22
+ } | {
23
+ kind: "array";
24
+ required: boolean;
25
+ min: number;
26
+ items: SchemaNode;
27
+ } | {
28
+ kind: "map";
29
+ required: boolean;
30
+ min: number;
31
+ key_pattern: string;
32
+ values: SchemaNode;
33
+ } | {
34
+ kind: "object";
35
+ required: boolean;
36
+ closed: boolean;
37
+ fields: Readonly<Record<string, SchemaNode>>;
38
+ };
39
+ export declare const CONFIG_SCHEMA: SchemaNode;
40
+ interface Option {
41
+ readonly value: string;
42
+ readonly label: string;
43
+ readonly example: string;
44
+ readonly icon?: string;
45
+ readonly ask_why?: string;
46
+ }
47
+ interface Question {
48
+ readonly id: string;
49
+ readonly text: string;
50
+ readonly short?: string;
51
+ readonly options: readonly Option[];
52
+ }
53
+ type Item = Readonly<Record<string, string>> & {
54
+ readonly source_id: string;
55
+ readonly group: string;
56
+ };
57
+ interface Practice {
58
+ readonly title?: string;
59
+ readonly body: string;
60
+ readonly code?: string;
61
+ readonly context?: string;
62
+ readonly expected: Readonly<Record<string, string>>;
63
+ readonly why: string;
64
+ }
65
+ interface Config {
66
+ readonly study: string;
67
+ readonly title: string;
68
+ readonly intro?: string;
69
+ readonly seed: number;
70
+ readonly groups: Readonly<Record<string, string>>;
71
+ readonly labeller_knows?: readonly string[];
72
+ readonly familiarity_question?: string;
73
+ readonly questions: readonly Question[];
74
+ readonly practice: readonly Practice[];
75
+ readonly practice_round?: number;
76
+ readonly items: readonly Item[];
77
+ }
78
+ interface KeyEntry {
79
+ readonly source_id: string;
80
+ readonly group: string;
81
+ readonly on_page: boolean;
82
+ }
83
+ /** Only what the labeller can answer goes on the page, and only that gets an id, in id order. */
84
+ declare function itemsOnPage(cfg: Config, keyPath: string): {
85
+ items: Item[];
86
+ ids: ReadonlyMap<string, string>;
87
+ entries: Readonly<Record<string, KeyEntry>>;
88
+ idOf: (i: Item) => string;
89
+ };
90
+ /** What a page shows: the questions, the practice and the items, blind, with their neutral ids. */
91
+ declare function payloadOf(cfg: Config, page: ReturnType<typeof itemsOnPage>): {
92
+ title: string;
93
+ intro: string;
94
+ groups: {
95
+ id: string;
96
+ label: string;
97
+ }[];
98
+ familiarity_question: string;
99
+ familiarity: {
100
+ value: string;
101
+ label: string;
102
+ }[];
103
+ allowed: JsonObject;
104
+ questions: readonly Question[];
105
+ practice: {
106
+ round: number;
107
+ items: readonly (Practice & {
108
+ readonly id: string;
109
+ })[];
110
+ };
111
+ items: {
112
+ id: string;
113
+ }[];
114
+ };
115
+ export type Payload = ReturnType<typeof payloadOf>;
116
+ /**
117
+ * Everything a build does but lay out the page: reads and checks items.json (the schema, the
118
+ * cross-field checks, the leak guard), gives the items their ids, writes key.json beside the page and
119
+ * returns what the page shows. A page written by hand can take its blindness and its key from here.
120
+ */
121
+ export declare function prepareBuild(configPath: string, outDir: string): {
122
+ payload: {
123
+ title: string;
124
+ intro: string;
125
+ groups: {
126
+ id: string;
127
+ label: string;
128
+ }[];
129
+ familiarity_question: string;
130
+ familiarity: {
131
+ value: string;
132
+ label: string;
133
+ }[];
134
+ allowed: JsonObject;
135
+ questions: readonly Question[];
136
+ practice: {
137
+ round: number;
138
+ items: readonly (Practice & {
139
+ readonly id: string;
140
+ })[];
141
+ };
142
+ items: {
143
+ id: string;
144
+ }[];
145
+ };
146
+ dropped: number;
147
+ };
148
+ export declare function exportLabels(dumpPath: string, keyPath: string, outDir: string, day: string): void;
149
+ export {};
@@ -0,0 +1,5 @@
1
+ import { type Payload } from "./label-page-core.ts";
2
+ /** The page: the template with its title and its data. */
3
+ export declare function pageHtml(payload: Payload): string;
4
+ /** items.json → out/page.html and out/key.json. */
5
+ export declare function build(configPath: string, outDir: string): void;
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};
@@ -1,4 +1,5 @@
1
1
  import type { NotAFile } from "./domain/decide-first.ts";
2
+ import { type PlanGates } from "./domain/study-gates.ts";
2
3
  import type { StudyMode } from "./domain/study-mode.ts";
3
4
  import { type PlanTextField, type RegistryState, type Study } from "./domain/study-registry.ts";
4
5
  import type { StudyRegistryCodec } from "./ports/study-registry-codec.ts";
@@ -30,6 +31,8 @@ export interface ModeStudy {
30
31
  readonly plan: string;
31
32
  readonly mode: StudyMode;
32
33
  readonly empty: readonly PlanTextField[];
34
+ /** A plan v2's gates as HEAD holds them; null for a plan v1. */
35
+ readonly gates: PlanGates | null;
33
36
  }
34
37
  /** What reading the plan of one row gave: its mode study, nothing, or a link on the way to it. */
35
38
  export type ModeRead = {
@@ -1 +1 @@
1
- {"version":3,"file":"study-modes.d.ts","sourceRoot":"","sources":["../src/study-modes.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,KAAK,EACX,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,6FAA6F;AAC7F,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,WAAW,EACnB,MAAM,MAAM,KACX,aAQF,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;CAC1C;AAED,kGAAkG;AAClG,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACxB,GAAG,KAAK,EACR,QAAQ,WAAW,EACnB,OAAO,kBAAkB,KACxB,QAcF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACtB,GAAG,aAAa,EAChB,QAAQ,WAAW,EACnB,OAAO,kBAAkB,KACxB,SAAS,SAAS,EAMlB,CAAC"}
1
+ {"version":3,"file":"study-modes.d.ts","sourceRoot":"","sources":["../src/study-modes.ts"],"names":[],"mappings":"AAQA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,0BAA0B,CAAC;AACzD,OAAO,EAAW,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AAClE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AACxD,OAAO,EAEL,KAAK,aAAa,EAClB,KAAK,aAAa,EAClB,KAAK,KAAK,EACX,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAE3D,6FAA6F;AAC7F,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,IAAI,EAAE,IAAI,CAAA;CAAE,GACvB;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GACxD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;;GAKG;AACH,eAAO,MAAM,aAAa,GACxB,QAAQ,WAAW,EACnB,MAAM,MAAM,KACX,aAQF,CAAC;AAEF;;;;GAIG;AACH,MAAM,WAAW,SAAS;IACxB,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IACzB,QAAQ,CAAC,KAAK,EAAE,SAAS,aAAa,EAAE,CAAC;IACzC,gEAAgE;IAChE,QAAQ,CAAC,KAAK,EAAE,SAAS,GAAG,IAAI,CAAC;CAClC;AAED,kGAAkG;AAClG,MAAM,MAAM,QAAQ,GAChB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,CAAA;CAAE,GACpD;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GACzB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD;;;;GAIG;AACH,eAAO,MAAM,aAAa,GACxB,GAAG,KAAK,EACR,QAAQ,WAAW,EACnB,OAAO,kBAAkB,KACxB,QAoBF,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,WAAW,GACtB,GAAG,aAAa,EAChB,QAAQ,WAAW,EACnB,OAAO,kBAAkB,KACxB,SAAS,SAAS,EAMlB,CAAC"}
@@ -6,6 +6,7 @@
6
6
  */
7
7
  import { posix } from "node:path";
8
8
  import { filter, map, pipe } from "remeda";
9
+ import { gatesOf } from "./domain/study-gates.js";
9
10
  import { studiesOf, } from "./domain/study-registry.js";
10
11
  /**
11
12
  * What the decision file `file` (relative to the paper) is, read through `folder` without following
@@ -45,7 +46,13 @@ export const readModeStudy = (s, folder, codec) => {
45
46
  const empty = parsed.kind === "draft" ? parsed.empty : [];
46
47
  return {
47
48
  kind: "mode",
48
- study: { row: s, plan, mode: parsed.plan.mode, empty },
49
+ study: {
50
+ row: s,
51
+ plan,
52
+ mode: parsed.plan.mode,
53
+ empty,
54
+ gates: gatesOf(parsed.plan),
55
+ },
49
56
  };
50
57
  };
51
58
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"study-modes.js","sourceRoot":"","sources":["../src/study-modes.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,EAAE,KAAK,EAAE,MAAM,WAAW,CAAC;AAClC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI,EAAE,MAAM,QAAQ,CAAC;AAG3C,OAAO,EACL,SAAS,GAIV,MAAM,4BAA4B,CAAC;AAUpC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,MAAmB,EACnB,IAAY,EACG,EAAE;IACjB,MAAM,EAAE,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;IAChC,IAAI,EAAE,CAAC,IAAI,KAAK,KAAK;QAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,WAAW,EAAE,CAAC;IACxE,IAAI,EAAE,CAAC,IAAI,KAAK,OAAO;QAAE,OAAO,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,cAAc,EAAE,CAAC;IAC7E,IAAI,EAAE,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IAChD,OAAO,EAAE,CAAC,IAAI,KAAK,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC;QACtC,CAAC,CAAC,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,eAAe,EAAE;QAC/C,CAAC,CAAC,EAAE,CAAC;AACT,CAAC,CAAC;AAoBF;;;;GAIG;AACH,MAAM,CAAC,MAAM,aAAa,GAAG,CAC3B,CAAQ,EACR,MAAmB,EACnB,KAAyB,EACf,EAAE;IACZ,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC;IACpB,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAChD,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;IACzC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACxC,IAAI,IAAI,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IACpD,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAClD,IAAI,MAAM,CAAC,IAAI,KAAK,YAAY,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS;QAChE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,CAAC;IAC1B,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IAC1D,OAAO;QACL,IAAI,EAAE,MAAM;QACZ,KAAK,EAAE,EAAE,GAAG,EAAE,CAAC,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;KACvD,CAAC;AACJ,CAAC,CAAC;AAEF;;;;GAIG;AACH,MAAM,CAAC,MAAM,WAAW,GAAG,CACzB,CAAgB,EAChB,MAAmB,EACnB,KAAyB,EACH,EAAE,CACxB,IAAI,CACF,SAAS,CAAC,CAAC,CAAC,EACZ,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,aAAa,CAAC,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,CAAC,EAC3C,MAAM,CAAC,MAAM,CAAC,EACd,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CACpB,CAAC;AAEJ,wCAAwC;AACxC,MAAM,MAAM,GAAG,CAAC,CAAW,EAA4C,EAAE,CACvE,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC"}
1
+ {"version":3,"file":"study-modes.js","sourceRoot":"","sources":["../src/study-modes.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"study-registry-rule.d.ts","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"AA4BA,OAAO,EASL,KAAK,SAAS,EACd,KAAK,aAAa,EAElB,KAAK,YAAY,EAGlB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAM3D,mFAAmF;AACnF,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,mGAAmG;IACnG,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B;AAED,uFAAuF;AACvF,eAAO,MAAM,MAAM,GAAI,OAAO,KAAK,EAAE,GAAG,MAAM,KAAG,MAAM,GAAG,IAGzD,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,OAAO,CAAC,GAC/C,aAAa,CAOf;AAoCD;;;GAGG;AACH,eAAO,MAAM,OAAO,GAClB,GAAG,aAAa,EAChB,QAAQ,WAAW,EACnB,OAAO,kBAAkB,KACxB,WAAW,CAAC,MAAM,EAAE,SAAS,CAQ7B,CAAC;AAqBJ,iGAAiG;AACjG,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,iBAAiB,GACtB,SAAS,YAAY,EAAE,CAUzB;AA+DD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,iBAAiB,GACtB,QAAQ,CAAC,MAAM,CAAC,kBAAkB,GAAG,iBAAiB,EAAE,gBAAgB,CAAC,CAAC,CAqB5E;AAED,mGAAmG;AACnG,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC;IAChD,wBAAwB,EAAE,OAAO,CAAC;IAClC,uBAAuB,EAAE,MAAM,CAAC;CACjC,CAA0E,CAAC"}
1
+ {"version":3,"file":"study-registry-rule.d.ts","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"AA4BA,OAAO,EASL,KAAK,SAAS,EACd,KAAK,aAAa,EAElB,KAAK,YAAY,EAGlB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAE1E,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAM3D,mFAAmF;AACnF,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,mGAAmG;IACnG,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;CAC/B;AAED,uFAAuF;AACvF,eAAO,MAAM,MAAM,GAAI,OAAO,KAAK,EAAE,GAAG,MAAM,KAAG,MAAM,GAAG,IAGzD,CAAC;AAEF,oFAAoF;AACpF,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,OAAO,CAAC,GAC/C,aAAa,CAOf;AAoCD;;;GAGG;AACH,eAAO,MAAM,OAAO,GAClB,GAAG,aAAa,EAChB,QAAQ,WAAW,EACnB,OAAO,kBAAkB,KACxB,WAAW,CAAC,MAAM,EAAE,SAAS,CAQ7B,CAAC;AAqBJ,iGAAiG;AACjG,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,iBAAiB,GACtB,SAAS,YAAY,EAAE,CAUzB;AAgED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAChC,IAAI,EAAE,iBAAiB,GACtB,QAAQ,CAAC,MAAM,CAAC,kBAAkB,GAAG,iBAAiB,EAAE,gBAAgB,CAAC,CAAC,CAqB5E;AAED,mGAAmG;AACnG,eAAO,MAAM,0BAA0B,EAAE,QAAQ,CAAC;IAChD,wBAAwB,EAAE,OAAO,CAAC;IAClC,uBAAuB,EAAE,MAAM,CAAC;CACjC,CAA0E,CAAC"}
@@ -110,6 +110,7 @@ const PROBLEMS = [
110
110
  "unknown-requirement",
111
111
  "headline-approval",
112
112
  "bad-plan",
113
+ "plan-version",
113
114
  "author-check",
114
115
  ];
115
116
  /** A rule's meta: its page, and a message id per problem, the whole text being `studyMessage`. */
@@ -1 +1 @@
1
- {"version":3,"file":"study-registry-rule.js","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"study-registry-rule.js","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import { type ResultStudy } from "./domain/study-result.ts";
2
+ import type { FolderRuleModule } from "./folder-venue-rule.ts";
3
+ import type { StudyDeps } from "./ports/study-deps.ts";
4
+ /** Every done study of a ready plan v2 in the paper folder `paper`. */
5
+ export declare const resultStudies: (paper: string, deps: StudyDeps) => readonly ResultStudy[];
6
+ /** The rule, reading the folder through `deps`. */
7
+ export declare const studyResultRules: (deps: StudyDeps) => Readonly<Record<"study-result", FolderRuleModule>>;
8
+ /** Its level in paperlint's own config: an error. */
9
+ export declare const RESULT_RULE_LEVELS: Readonly<{
10
+ "repro/study-result": "error";
11
+ }>;
12
+ //# sourceMappingURL=study-result-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"study-result-rule.d.ts","sourceRoot":"","sources":["../src/study-result-rule.ts"],"names":[],"mappings":"AAcA,OAAO,EAML,KAAK,WAAW,EACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AA0CvD,uEAAuE;AACvE,eAAO,MAAM,aAAa,GACxB,OAAO,MAAM,EACb,MAAM,SAAS,KACd,SAAS,WAAW,EAOtB,CAAC;AAqBF,mDAAmD;AACnD,eAAO,MAAM,gBAAgB,GAC3B,MAAM,SAAS,KACd,QAAQ,CAAC,MAAM,CAAC,cAAc,EAAE,gBAAgB,CAAC,CAclD,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,kBAAkB,EAAE,QAAQ,CAAC;IAAE,oBAAoB,EAAE,OAAO,CAAA;CAAE,CAE1E,CAAC"}
@@ -0,0 +1,87 @@
1
+ /**
2
+ * `repro/study-result` — a `done` study whose plan is v2 shows, in its `result.json`, what its plan
3
+ * fixed before the run: the number its claim stands or falls by, each labelling step's kappa, its
4
+ * self-test, its funnel and its extractor's recall audit. What is judged, and why, is `src/domain/study-result.ts` and
5
+ * docs/rules/repro/study-result.md; this file finds those studies, reads their result through the
6
+ * study folder's reader (no link followed), and reports.
7
+ *
8
+ * A plan that does not parse, is a draft, or is v1 is `repro/study-registered`'s to report; here it
9
+ * asks nothing. Reported on `PIPELINE-STATUS.md`, first line, like the other `repro/` rules.
10
+ */
11
+ import { basename, dirname, posix } from "node:path";
12
+ import { filter, map, pipe } from "remeda";
13
+ import { RESULT_FILE } from "./domain/study-gates.js";
14
+ import { studiesOf } from "./domain/study-registry.js";
15
+ import { RESULT_PROBLEMS, gatesOf, judgeResult, resultMessage, } from "./domain/study-result.js";
16
+ import { studyFolder } from "./study-folder.js";
17
+ import { registryOf } from "./study-registry-rule.js";
18
+ import { rulePageUrl } from "./venue-rules.js";
19
+ const STATUS_FILE = "PIPELINE-STATUS.md";
20
+ const NAME = "repro/study-result";
21
+ /** What the folder holds of a study's `result.json`, beside its plan (`plan`, relative to the folder). */
22
+ const resultState = (folder, of, plan, codec) => {
23
+ const read = folder.read(of, posix.join(posix.dirname(plan), RESULT_FILE));
24
+ return read.kind === "text" ? codec.parseResult(read.text) : read;
25
+ };
26
+ /** The row `s` as a study to judge: `done`, its plan ready, every gate decided; else null. */
27
+ const resultStudy = (s, folder, codec) => {
28
+ if (s.status !== "done" || s.plan === undefined)
29
+ return null;
30
+ const read = folder.read(s.folder, s.plan);
31
+ if (read.kind !== "text")
32
+ return null;
33
+ const parsed = codec.parsePlan(read.text, s.kind);
34
+ const gates = parsed.kind === "ready" ? gatesOf(parsed.plan) : null;
35
+ return gates === null
36
+ ? null
37
+ : {
38
+ id: s.id,
39
+ folder: s.folder,
40
+ ...gates,
41
+ state: resultState(folder, s.folder, s.plan, codec),
42
+ };
43
+ };
44
+ /** Every done study of a ready plan v2 in the paper folder `paper`. */
45
+ export const resultStudies = (paper, deps) => {
46
+ const folder = studyFolder(paper, deps);
47
+ return pipe(studiesOf(registryOf(paper, deps)), map((s) => resultStudy(s, folder, deps.codec)), filter((s) => s !== null));
48
+ };
49
+ /** On `PIPELINE-STATUS.md`, every finding of every such study of its paper, at its first line. */
50
+ const reportOn = (context, deps) => {
51
+ if (basename(context.filename) !== STATUS_FILE)
52
+ return {};
53
+ return {
54
+ root() {
55
+ const at = context.sourceCode.getLocFromIndex(0);
56
+ resultStudies(dirname(context.filename), deps)
57
+ .flatMap(judgeResult)
58
+ .forEach((f) => {
59
+ context.report({
60
+ loc: { start: at, end: at },
61
+ messageId: f.problem,
62
+ data: { text: resultMessage(f) },
63
+ });
64
+ });
65
+ },
66
+ };
67
+ };
68
+ /** The rule, reading the folder through `deps`. */
69
+ export const studyResultRules = (deps) => ({
70
+ "study-result": {
71
+ meta: {
72
+ type: "suggestion",
73
+ docs: {
74
+ description: "a done study whose plan is v2 shows in its result.json what its plan fixed before the run: the number its claim stands or falls by, each labelling step's kappa, its self-test, its funnel and its extractor's recall audit",
75
+ url: rulePageUrl(NAME),
76
+ },
77
+ schema: [],
78
+ messages: Object.fromEntries(RESULT_PROBLEMS.map((p) => [p, "{{text}}"])),
79
+ },
80
+ create: (context) => reportOn(context, deps),
81
+ },
82
+ });
83
+ /** Its level in paperlint's own config: an error. */
84
+ export const RESULT_RULE_LEVELS = {
85
+ "repro/study-result": "error",
86
+ };
87
+ //# sourceMappingURL=study-result-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"study-result-rule.js","sourceRoot":"","sources":["../src/study-result-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,208 @@
1
+ # The gates of a plan v2
2
+
3
+ Issue [#332](https://github.com/zernie/paperlint/issues/332). A measurement study's `plan.json` says,
4
+ before the run, what makes its number worth believing; after the run its `result.json` shows it.
5
+ Two rules hold it: [`repro/study-registered`](../rules/repro/study-registered.md) reads the plan,
6
+ [`repro/study-result`](../rules/repro/study-result.md) reads the result. The code is
7
+ `src/domain/study-gates.ts`, `src/domain/study-result.ts` and the parser in
8
+ `src/adapters/study-registry/`.
9
+
10
+ ## Where it came from
11
+
12
+ A consumer paper's main measurement drew rules out of repositories, ran several executed "readings" of
13
+ each rule, and counted how often the readings disagreed. Refuting its design by hand found two holes:
14
+
15
+ - **It could not lose.** A reading that flagged nothing made every other reading "disagree", so the
16
+ number came out in the design's favour whatever the rules said.
17
+ - **Readings were not tied to the rule's text.** For "max line length 100", readings of 79, 88, 100
18
+ and 120 counted as interpretations, though three of them contradict the text. The number measured
19
+ how varied configurations are, not how vague the rule is.
20
+
21
+ The neighbours of that paper that hold up report four checks this design lacked: two raters with an
22
+ agreement statistic (Cohen's kappa 0.86 and 0.89 in two of them), errors planted to see that the
23
+ checker catches them, every dropped unit counted, and an audit of the extractor — one neighbour read
24
+ 50 files in full and reports that its extraction caught 66.3% of the eligible rules. A preregistration template —
25
+ AsPredicted's eight questions — asks "Specify exactly which analyses you will conduct to examine the
26
+ main question/hypothesis"; the plan had no field for what decides the question.
27
+
28
+ ## Versions
29
+
30
+ A plan says it is v2 with `"$schema": "https://unpkg.com/paperlint/schemas/plan.v2.schema.json"`.
31
+
32
+ | plan | judged |
33
+ | ----------------- | ------------------------------------------------------------------------- |
34
+ | no `$schema` (v1) | as before; it may carry none of the gates |
35
+ | v2 | every gate present: `null` (not decided: a draft), `"none"`, or its value |
36
+
37
+ A measurement registered on or after **2026-10-31** must have a plan v2 (`plan-version`), so dropping
38
+ the marker is no way around the gates. A measurement registered earlier keeps its plan v1; nothing it
39
+ had turns red. `paperlint studies new` writes a measurement's plan as v2. A later field is a v3, the
40
+ same way: v2 plans keep passing.
41
+
42
+ **There is no optional gate.** A gate left out of a plan v2 makes the file "not a study plan". The one
43
+ way to say "not this study" is the literal `"none"`, written where the reader of the diff sees it.
44
+
45
+ ## The five gates
46
+
47
+ ### `mode.we_lose_if` — the claim can lose
48
+
49
+ ```json
50
+ "mode": {
51
+ "kind": "decide_before_run",
52
+ "outputs": ["result.json"],
53
+ "decision": { "file": "repro/P1-S07-readings/decision.md", "note": "…" },
54
+ "we_lose_if": { "result": "share_upper95", "below": 0.20 }
55
+ }
56
+ ```
57
+
58
+ `result` names a number the study writes in `result.json`; `below` **or** `above` (exactly one) is
59
+ the threshold. It lives only in a decide-first mode: an `exploratory` study has no claim to lose, and
60
+ its mode cannot hold one. The name is the study's own: `share_upper95` in one study, `fix_rate` in
61
+ another.
62
+
63
+ - **Checked:** present, its shape; after the run, the number is there, and when it crosses the
64
+ threshold `result.json` says `"claim": "lost"` (`claim-lost`), never of a claim that holds
65
+ (`claim-holds`).
66
+ - **Not checked:** that the number named is the right one to decide the question — the author's
67
+ check.
68
+
69
+ **Frozen at the first output.** All five gates are held by git's history
70
+ ([`repro/outputs-before-decision`](../rules/repro/outputs-before-decision.md)): the plan as it stood
71
+ at the commit of the study's first output (the first that came after its decision) must declare each
72
+ gate exactly as HEAD's plan does. A gate edited since is `gates-changed`: a threshold moved after the
73
+ result was seen can only follow the result. A plan that was not in history yet at that commit, or was
74
+ a v1 or unreadable there, is `gates-not-fixed`. Edits to other parts of the plan (its question, its
75
+ source) are not reported.
76
+
77
+ ### `second_check` — two raters on each labelling step
78
+
79
+ ```json
80
+ "second_check": [
81
+ { "step": "lint-checkable", "min_kappa": 0.60 },
82
+ { "step": "admissible", "min_kappa": 0.60 }
83
+ ]
84
+ ```
85
+
86
+ One entry per step on which a model or a person labels units, with the least Cohen's kappa
87
+ (agreement between two raters beyond chance) the two raters must reach. The threshold is fixed
88
+ before labelling, so a kappa of 0.4 cannot be called good enough after it is seen. Landis and Koch's
89
+ bands (0.61–0.80 "substantial") are a common reference, and an opinion, not evidence: the study
90
+ chooses its own and says why in its design. `"none"` when nothing is labelled.
91
+
92
+ In the consumer paper the second hole above is closed here: whether a reading fits the rule's text
93
+ is the `admissible` labelling step.
94
+
95
+ - **Checked:** each step's kappa is in `result.json`'s `kappa` and at least its `min_kappa`.
96
+ - **Not checked:** who the raters were, how the subset was drawn — that stays in the design. A
97
+ `"none"` on a study that does label is caught only by the author's check.
98
+
99
+ ### `self_test` — the checker is run on known answers first
100
+
101
+ ```json
102
+ "self_test": { "made_by": "scripts/extract.selftest.mjs" }
103
+ "self_test": { "must_catch": "self-test/bad.js", "must_pass": "self-test/good.js" }
104
+ ```
105
+
106
+ When the study runs a check (a linter rule, a script, a classifier) its zero means nothing until the
107
+ check has caught an input it must catch and passed one it must pass. Either a script makes and runs
108
+ such pairs (`made_by`), or the plan names one pair; the inputs are of whatever type the check reads.
109
+ Paths are inside the study's folder. `"none"` when the study runs no check.
110
+
111
+ - **Checked:** the paths stay in the folder; after the run, `result.json`'s
112
+ `"self_test": { "passed": n, "failed": n }` is there and `failed` is 0.
113
+
114
+ ### `funnel` — every drop counted
115
+
116
+ ```json
117
+ "funnel": ["no linter rule", "< 2 admissible readings", "no files in scope", "clone failed"]
118
+ ```
119
+
120
+ The reasons a drawn unit may be dropped, each once, fixed before the draw — a study cannot invent a
121
+ reason for a unit it would rather not count. Like a trial's flow diagram, which "displays the
122
+ progress of all participants through the trial" (CONSORT). `"none"` when no unit is dropped.
123
+
124
+ - **Checked:** `result.json`'s `funnel` holds a count for every reason (0 when none).
125
+
126
+ ### `recall_audit` — how much the extractor misses
127
+
128
+ ```json
129
+ "recall_audit": { "n_files": 50, "min_recall": 0.6 }
130
+ ```
131
+
132
+ A study that draws units out of artefacts (rules out of instruction files, functions out of code)
133
+ counts only what its extractor found. A person reads `n_files` files of a seeded sample in full and
134
+ marks every unit there; the recall is the share of those units the extractor found too. Without it, a
135
+ reviewer's "how many did your parser miss?" has no number. `"none"` when nothing is extracted (the
136
+ units are given, or a person draws them by hand).
137
+
138
+ ```
139
+ STAGE WHO WRITES WHICH RULE RED WHEN
140
+ ───────────── ───────────────────────── ────────────────────────── ──────────────────────────────
141
+ 1 plan the author (+ agent): repro/study-registered key missing (schema error);
142
+ (before "recall_audit": null while the study runs
143
+ the run) {n_files, min_recall} repro/outputs-before- changed after the first output
144
+ decision (gates-changed)
145
+ 2 run the study's script: — —
146
+ extracts units
147
+ 3 audit a PERSON reads n_files — —
148
+ sampled files in full,
149
+ marks every unit (a
150
+ build-label-page page)
151
+ 4 result the study's script: repro/study-result counts missing (no-recall-audit);
152
+ (after "recall_audit": (when the study is done) files < n_files (recall-sample);
153
+ the run) {files, units_in_files, extracted / units_in_files
154
+ extracted} < min_recall (recall);
155
+ extracted > units_in_files
156
+ (result unreadable)
157
+ FIRES: in the editor on save · npx paperlint lint · the paper's CI
158
+ CANNOT SEE: whether the person really read the files in full, or counted right;
159
+ whether the sample was drawn as the design says
160
+ ```
161
+
162
+ `result.json` carries the counts, not a share: the files are checked against the plan, and the
163
+ recall is computed by the rule (`extracted / units_in_files`), so a share rounded in the study's
164
+ favour cannot pass.
165
+
166
+ - **Checked:** the counts are there; at least `n_files` files; the recall at least `min_recall`.
167
+ - **Not checked:** the reading itself — the labels of the audit are data the study exports and
168
+ commits, like any other labels.
169
+
170
+ ## `result.json`
171
+
172
+ The study's own script writes it beside the plan; the rule only reads it.
173
+
174
+ ```json
175
+ {
176
+ "share_upper95": 0.31,
177
+ "kappa": { "lint-checkable": 0.71, "admissible": 0.64 },
178
+ "self_test": { "passed": 212, "failed": 0 },
179
+ "funnel": {
180
+ "no linter rule": 400,
181
+ "< 2 admissible readings": 37,
182
+ "no files in scope": 5,
183
+ "clone failed": 3
184
+ },
185
+ "recall_audit": { "files": 50, "units_in_files": 95, "extracted": 63 }
186
+ }
187
+ ```
188
+
189
+ Its own numbers go at the top under any name. `kappa`, `self_test`, `funnel`, `recall_audit` and
190
+ `claim` have the shapes above. It is judged once the study is `done`.
191
+
192
+ ## What a machine never sees
193
+
194
+ A `"none"` that is false, a threshold chosen to be easy, a `result` that names the wrong number. These
195
+ are read by the author when they approve the plan (`author_check`) — which is why the gates are few,
196
+ named in plain words, and visible in the diff.
197
+
198
+ ## Rejected
199
+
200
+ - **Optional gates, "when they apply".** An author who forgets one would read as an author who did
201
+ not need it. Every gate is present and says `"none"` out loud.
202
+ - **A "kind of measurement" field choosing which gates apply.** One more field that can be wrong;
203
+ `"none"` per gate says the same thing where it is checked.
204
+ - **Free-text gates** (`why`, `raters`, the subset's share and seed). No check reads them; they stay
205
+ in the study's design.
206
+ - **A gate per study design** (admissibility of executed versions, a replication frame, one unit per
207
+ cluster). Specific to one paper so far; a paper keeps such keys in the plan's `extra` until two
208
+ papers have needed them unchanged.
@@ -42,6 +42,12 @@ A study decided before its run — its plan's `mode` is `decide_before_run`, the
42
42
  - **`shallow`** — the clone is shallow, so every file's first commit is the clone's: no order can be
43
43
  read, and the rule says so instead of judging.
44
44
  - **`no-history`** — git could not answer (not installed, not a repository).
45
+ - **`gates-changed`** — the plan is a plan v2 ([`docs/design/study-gates.md`](../../design/study-gates.md)),
46
+ and one of its gates (`mode.we_lose_if`, `second_check`, `self_test`, `funnel`, `recall_audit`) differs from what
47
+ the plan declared at the commit of the study's first output after its decision: a threshold moved
48
+ after a result exists. One finding per changed gate, with its value then and now.
49
+ - **`gates-not-fixed`** — the plan v2 was not in history at that commit, or was a plan v1 or no
50
+ readable plan there: its gates were not fixed before the run.
45
51
 
46
52
  The study's own files — `plan.json`, `README.md` and the decision file — are never outputs. A symbolic
47
53
  link in the study's folder is one entry, as git stores it, and is never followed: a link to the folder
@@ -93,6 +99,8 @@ No rule options. The study declares its mode in its plan.
93
99
  - What the decision says. The gate is that it is committed, not its content.
94
100
  - **A decision amended after the outputs**: the order is between FIRST commits. A later edit of the
95
101
  decision file is visible in its history (`git log -- <file>`) but not reported.
102
+ - A plan v1, or a plan v2's parts other than its four gates: the question, the source and the note
103
+ may be reworded after the outputs. Only the gates are frozen.
96
104
  - That nobody ran the study before the decision and kept the outputs out of git. History records
97
105
  what was committed; a run on a machine that never committed it leaves no trace.
98
106
  - A study whose row names a folder that is not one inside `repro/` (`../x`), or a folder that is a