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,151 @@
1
+ /**
2
+ * WHAT A STUDY'S RUN SHOWED, AGAINST WHAT ITS PLAN V2 FIXED — `repro/study-result`
3
+ * (docs/rules/repro/study-result.md, src/domain/study-gates.ts).
4
+ *
5
+ * A study whose plan is v2 writes its numbers to `result.json` beside the plan; the study's own
6
+ * script produces the facts, this module judges them. For a study that is `done`:
7
+ *
8
+ * we_lose_if the number it names is in the file; when it crosses the threshold the file says
9
+ * `"claim": "lost"` — a loss is written where the paper reads its numbers, never
10
+ * left for a reader to work out — and it never says so of a claim that holds.
11
+ * second_check each step's kappa is in `kappa`, and at least its `min_kappa`.
12
+ * self_test `self_test` holds `passed` and `failed`, and `failed` is 0.
13
+ * funnel `funnel` counts every declared reason.
14
+ * recall_audit `recall_audit` gives the files a person read in full, the units found there, and
15
+ * how many of them the extractor found; at least `n_files` files, and a recall
16
+ * (extracted / units) of at least `min_recall`. The counts, not a recall the study
17
+ * computed: the files are checked against the plan, and the share is computed here.
18
+ *
19
+ * A gate that is `"none"` asks nothing of the file. Pure.
20
+ */
21
+ import { type Funnel, type RecallAudit, type SecondCheck, type SelfTest, type WeLoseIf } from "./study-gates.ts";
22
+ import type { StudyPlan } from "./study-registry.ts";
23
+ /** The value a study's result says its claim has, when its number crossed `we_lose_if`. */
24
+ export declare const CLAIM_LOST = "lost";
25
+ /** What a person found reading the audited files in full, and how many of those units the extractor found. */
26
+ export interface RecallCounts {
27
+ readonly files: number;
28
+ readonly units_in_files: number;
29
+ readonly extracted: number;
30
+ }
31
+ /** A study's `result.json`: its own numbers by name, and the five parts the gates read. */
32
+ export interface StudyResult {
33
+ readonly claim?: typeof CLAIM_LOST | undefined;
34
+ readonly kappa?: Readonly<Record<string, number>> | undefined;
35
+ readonly self_test?: {
36
+ readonly passed: number;
37
+ readonly failed: number;
38
+ } | undefined;
39
+ readonly funnel?: Readonly<Record<string, number>> | undefined;
40
+ readonly recall_audit?: RecallCounts | undefined;
41
+ readonly [key: string]: unknown;
42
+ }
43
+ /** A `result.json`'s text, parsed: the result, or why it is none. */
44
+ export type ParsedResult = {
45
+ readonly kind: "read";
46
+ readonly result: StudyResult;
47
+ } | {
48
+ readonly kind: "unreadable";
49
+ readonly why: string;
50
+ };
51
+ /** What the study's folder holds of `result.json`. */
52
+ export type ResultState = {
53
+ readonly kind: "absent";
54
+ } | {
55
+ readonly kind: "linked";
56
+ readonly link: string;
57
+ } | ParsedResult;
58
+ /** A done study of a ready plan v2: its gates, and what its folder holds of its result. */
59
+ export interface ResultStudy {
60
+ readonly id: string;
61
+ readonly folder: string;
62
+ /** null: an exploratory study, which has no claim to lose. */
63
+ readonly we_lose_if: WeLoseIf | null;
64
+ readonly second_check: SecondCheck;
65
+ readonly self_test: SelfTest;
66
+ readonly funnel: Funnel;
67
+ readonly recall_audit: RecallAudit;
68
+ readonly state: ResultState;
69
+ }
70
+ /** The gates a ready plan v2 declares, as the judge reads them. */
71
+ export type Gates = Pick<ResultStudy, "we_lose_if" | "second_check" | "self_test" | "funnel" | "recall_audit">;
72
+ /**
73
+ * The gates of plan `p`, when every one is decided; null for a plan v1 or a draft. An exploratory
74
+ * plan, or one whose mode carries no `we_lose_if`, has no claim to lose.
75
+ */
76
+ export declare const gatesOf: (p: StudyPlan) => Gates | null;
77
+ /** One defect of a study's result. */
78
+ export type ResultFinding = {
79
+ readonly problem: "no-result-file";
80
+ readonly id: string;
81
+ } | {
82
+ readonly problem: "result-linked";
83
+ readonly id: string;
84
+ readonly link: string;
85
+ } | {
86
+ readonly problem: "result-unreadable";
87
+ readonly id: string;
88
+ readonly why: string;
89
+ } | {
90
+ readonly problem: "no-number";
91
+ readonly id: string;
92
+ readonly key: string;
93
+ } | {
94
+ readonly problem: "claim-lost";
95
+ readonly id: string;
96
+ readonly key: string;
97
+ readonly value: number;
98
+ readonly threshold: string;
99
+ } | {
100
+ readonly problem: "claim-holds";
101
+ readonly id: string;
102
+ readonly key: string;
103
+ readonly value: number;
104
+ readonly threshold: string;
105
+ } | {
106
+ readonly problem: "kappa";
107
+ readonly id: string;
108
+ readonly step: string;
109
+ readonly min: number;
110
+ readonly got: number | null;
111
+ } | {
112
+ readonly problem: "self-test";
113
+ readonly id: string;
114
+ readonly failed: number | null;
115
+ }
116
+ /** The self-test ran no case: it says nothing about the check. */
117
+ | {
118
+ readonly problem: "self-test-empty";
119
+ readonly id: string;
120
+ } | {
121
+ readonly problem: "funnel";
122
+ readonly id: string;
123
+ readonly missing: readonly string[];
124
+ } | {
125
+ readonly problem: "no-recall-audit";
126
+ readonly id: string;
127
+ } | {
128
+ readonly problem: "recall-sample";
129
+ readonly id: string;
130
+ readonly files: number;
131
+ readonly min_files: number;
132
+ } | {
133
+ readonly problem: "recall";
134
+ readonly id: string;
135
+ readonly extracted: number;
136
+ readonly units: number;
137
+ readonly min: number;
138
+ };
139
+ /** Every defect of one study's result, in the order of its gates. */
140
+ export declare const judgeResult: (s: ResultStudy) => readonly ResultFinding[];
141
+ /** Each finding by its problem. */
142
+ type FindingOf = {
143
+ readonly [F in ResultFinding as F["problem"]]: F;
144
+ };
145
+ type Problem = keyof FindingOf;
146
+ /** The one text a finding is reported with. */
147
+ export declare const resultMessage: (f: ResultFinding) => string;
148
+ /** Every problem the rule reports, each its own message id. */
149
+ export declare const RESULT_PROBLEMS: readonly Problem[];
150
+ export {};
151
+ //# sourceMappingURL=study-result.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"study-result.d.ts","sourceRoot":"","sources":["../../src/domain/study-result.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;GAmBG;AACH,OAAO,EAIL,KAAK,MAAM,EACX,KAAK,WAAW,EAEhB,KAAK,WAAW,EAChB,KAAK,QAAQ,EACb,KAAK,QAAQ,EACd,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,qBAAqB,CAAC;AAErD,2FAA2F;AAC3F,eAAO,MAAM,UAAU,SAAS,CAAC;AAEjC,8GAA8G;AAC9G,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,cAAc,EAAE,MAAM,CAAC;IAChC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B;AAED,2FAA2F;AAC3F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,CAAC,EAAE,OAAO,UAAU,GAAG,SAAS,CAAC;IAC/C,QAAQ,CAAC,KAAK,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IAC9D,QAAQ,CAAC,SAAS,CAAC,EACjB;QAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;QAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;KAAE,GAAG,SAAS,CAAC;IACnE,QAAQ,CAAC,MAAM,CAAC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,SAAS,CAAC;IAC/D,QAAQ,CAAC,YAAY,CAAC,EAAE,YAAY,GAAG,SAAS,CAAC;IACjD,QAAQ,EAAE,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACjC;AAED,qEAAqE;AACrE,MAAM,MAAM,YAAY,GACpB;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAA;CAAE,GACvD;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAE1D,sDAAsD;AACtD,MAAM,MAAM,WAAW,GACnB;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAClD,YAAY,CAAC;AAEjB,2FAA2F;AAC3F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,8DAA8D;IAC9D,QAAQ,CAAC,UAAU,EAAE,QAAQ,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,QAAQ,CAAC;IAC7B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,YAAY,EAAE,WAAW,CAAC;IACnC,QAAQ,CAAC,KAAK,EAAE,WAAW,CAAC;CAC7B;AAED,mEAAmE;AACnE,MAAM,MAAM,KAAK,GAAG,IAAI,CACtB,WAAW,EACX,YAAY,GAAG,cAAc,GAAG,WAAW,GAAG,QAAQ,GAAG,cAAc,CACxE,CAAC;AAMF;;;GAGG;AACH,eAAO,MAAM,OAAO,GAAI,GAAG,SAAS,KAAG,KAAK,GAAG,IAiB9C,CAAC;AAEF,sCAAsC;AACtC,MAAM,MAAM,aAAa,GACrB;IAAE,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC3D;IACE,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB,GACD;IACE,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAC;IACtC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,GACD;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC5E;IACE,QAAQ,CAAC,OAAO,EAAE,YAAY,CAAC;IAC/B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,GACD;IACE,QAAQ,CAAC,OAAO,EAAE,aAAa,CAAC;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,GACD;IACE,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B,GACD;IACE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;CAChC;AACH,kEAAkE;GAChE;IAAE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC5D;IACE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;CACrC,GACD;IAAE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAA;CAAE,GAC5D;IACE,QAAQ,CAAC,OAAO,EAAE,eAAe,CAAC;IAClC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;CAC5B,GACD;IACE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAC3B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;CACtB,CAAC;AAoGN,qEAAqE;AACrE,eAAO,MAAM,WAAW,GAAI,GAAG,WAAW,KAAG,SAAS,aAAa,EAoBlE,CAAC;AAKF,mCAAmC;AACnC,KAAK,SAAS,GAAG;IAAE,QAAQ,EAAE,CAAC,IAAI,aAAa,IAAI,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC;CAAE,CAAC;AACtE,KAAK,OAAO,GAAG,MAAM,SAAS,CAAC;AAuC/B,+CAA+C;AAC/C,eAAO,MAAM,aAAa,GAAI,GAAG,aAAa,KAAG,MAC6D,CAAC;AAE/G,+DAA+D;AAC/D,eAAO,MAAM,eAAe,EAAE,SAAS,OAAO,EAc7C,CAAC"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * WHAT A STUDY'S RUN SHOWED, AGAINST WHAT ITS PLAN V2 FIXED — `repro/study-result`
3
+ * (docs/rules/repro/study-result.md, src/domain/study-gates.ts).
4
+ *
5
+ * A study whose plan is v2 writes its numbers to `result.json` beside the plan; the study's own
6
+ * script produces the facts, this module judges them. For a study that is `done`:
7
+ *
8
+ * we_lose_if the number it names is in the file; when it crosses the threshold the file says
9
+ * `"claim": "lost"` — a loss is written where the paper reads its numbers, never
10
+ * left for a reader to work out — and it never says so of a claim that holds.
11
+ * second_check each step's kappa is in `kappa`, and at least its `min_kappa`.
12
+ * self_test `self_test` holds `passed` and `failed`, and `failed` is 0.
13
+ * funnel `funnel` counts every declared reason.
14
+ * recall_audit `recall_audit` gives the files a person read in full, the units found there, and
15
+ * how many of them the extractor found; at least `n_files` files, and a recall
16
+ * (extracted / units) of at least `min_recall`. The counts, not a recall the study
17
+ * computed: the files are checked against the plan, and the share is computed here.
18
+ *
19
+ * A gate that is `"none"` asks nothing of the file. Pure.
20
+ */
21
+ import { loses, thresholdText, RESULT_FILE, } from "./study-gates.js";
22
+ /** The value a study's result says its claim has, when its number crossed `we_lose_if`. */
23
+ export const CLAIM_LOST = "lost";
24
+ /** Whether a gate is decided: neither absent (a plan v1) nor null (not decided yet). */
25
+ const decided = (g) => g !== null && g !== undefined;
26
+ /**
27
+ * The gates of plan `p`, when every one is decided; null for a plan v1 or a draft. An exploratory
28
+ * plan, or one whose mode carries no `we_lose_if`, has no claim to lose.
29
+ */
30
+ export const gatesOf = (p) => {
31
+ const { second_check, self_test, funnel, recall_audit, mode } = p;
32
+ if (!decided(second_check) ||
33
+ !decided(self_test) ||
34
+ !decided(funnel) ||
35
+ !decided(recall_audit))
36
+ return null;
37
+ const w = mode?.kind === "decide_before_run" ? mode.we_lose_if : null;
38
+ return {
39
+ we_lose_if: decided(w) ? w : null,
40
+ second_check,
41
+ self_test,
42
+ funnel,
43
+ recall_audit,
44
+ };
45
+ };
46
+ /** What `we_lose_if` asks of `r`: the number, and a loss said in so many words. */
47
+ const claimFindings = (id, w, r) => {
48
+ const value = r[w.result];
49
+ if (typeof value !== "number")
50
+ return [{ problem: "no-number", id, key: w.result }];
51
+ const lost = loses(w, value);
52
+ const said = r.claim === CLAIM_LOST;
53
+ if (lost === said)
54
+ return [];
55
+ const at = { id, key: w.result, value, threshold: thresholdText(w) };
56
+ return [
57
+ lost ? { problem: "claim-lost", ...at } : { problem: "claim-holds", ...at },
58
+ ];
59
+ };
60
+ /** What `second_check` asks of `r`: each step's kappa, at least its least. */
61
+ const kappaFindings = (id, c, r) => c === "none"
62
+ ? []
63
+ : c.flatMap((s) => {
64
+ const got = r.kappa?.[s.step] ?? null;
65
+ return got !== null && got >= s.min_kappa
66
+ ? []
67
+ : [{ problem: "kappa", id, step: s.step, min: s.min_kappa, got }];
68
+ });
69
+ /** What `self_test` asks of `r`: its counts, none failed. */
70
+ const selfTestFindings = (id, t, r) => {
71
+ if (t === "none")
72
+ return [];
73
+ const run = r.self_test;
74
+ if (run === undefined)
75
+ return [{ problem: "self-test", id, failed: null }];
76
+ if (run.failed !== 0)
77
+ return [{ problem: "self-test", id, failed: run.failed }];
78
+ return run.passed > 0 ? [] : [{ problem: "self-test-empty", id }];
79
+ };
80
+ /** What `funnel` asks of `r`: a count for every reason. */
81
+ const funnelFindings = (id, f, r) => {
82
+ if (f === "none")
83
+ return [];
84
+ const missing = f.filter((reason) => r.funnel?.[reason] === undefined);
85
+ return missing.length === 0 ? [] : [{ problem: "funnel", id, missing }];
86
+ };
87
+ /** The audit's file count against the plan's: too few files is a finding. */
88
+ const sampleFindings = (id, a, c) => c.files < a.n_files
89
+ ? [{ problem: "recall-sample", id, files: c.files, min_files: a.n_files }]
90
+ : [];
91
+ /** The recall the counts give, against the plan's least. */
92
+ const shareFindings = (id, a, c) => c.extracted / c.units_in_files < a.min_recall
93
+ ? [
94
+ {
95
+ problem: "recall",
96
+ id,
97
+ extracted: c.extracted,
98
+ units: c.units_in_files,
99
+ min: a.min_recall,
100
+ },
101
+ ]
102
+ : [];
103
+ /** What `recall_audit` asks of `r`: the counts, on enough files, with a recall at least its least. */
104
+ const recallFindings = (id, a, r) => {
105
+ if (a === "none")
106
+ return [];
107
+ const c = r.recall_audit;
108
+ if (c === undefined)
109
+ return [{ problem: "no-recall-audit", id }];
110
+ return [...sampleFindings(id, a, c), ...shareFindings(id, a, c)];
111
+ };
112
+ /** Every defect of one study's result, in the order of its gates. */
113
+ export const judgeResult = (s) => {
114
+ const st = s.state;
115
+ switch (st.kind) {
116
+ case "absent":
117
+ return [{ problem: "no-result-file", id: s.id }];
118
+ case "linked":
119
+ return [{ problem: "result-linked", id: s.id, link: st.link }];
120
+ case "unreadable":
121
+ return [{ problem: "result-unreadable", id: s.id, why: st.why }];
122
+ case "read":
123
+ return [
124
+ ...(s.we_lose_if === null
125
+ ? []
126
+ : claimFindings(s.id, s.we_lose_if, st.result)),
127
+ ...kappaFindings(s.id, s.second_check, st.result),
128
+ ...selfTestFindings(s.id, s.self_test, st.result),
129
+ ...funnelFindings(s.id, s.funnel, st.result),
130
+ ...recallFindings(s.id, s.recall_audit, st.result),
131
+ ];
132
+ }
133
+ };
134
+ const RULE = "repro/study-result";
135
+ const tick = (s) => `\`${s}\``;
136
+ /** The text of each finding: what is wrong, and what to do. */
137
+ const HEADS = {
138
+ "no-result-file": (f) => `${tick(f.id)} is \`done\` and its plan is v2, but its folder has no ${tick(RESULT_FILE)}. What to do: have the study's script write its numbers there — the one its \`we_lose_if\` names, \`kappa\`, \`self_test\` and \`funnel\` as its plan declares them.`,
139
+ "result-linked": (f) => `The ${tick(RESULT_FILE)} of ${tick(f.id)} passes through the symbolic link ${tick(f.link)}; nothing is read through a link. What to do: write the file itself in the study's folder.`,
140
+ "result-unreadable": (f) => `The ${tick(RESULT_FILE)} of ${tick(f.id)} is not a study result: ${f.why}. What to do: give it the shape on the rule's page.`,
141
+ "no-number": (f) => `The ${tick(RESULT_FILE)} of ${tick(f.id)} has no number ${tick(f.key)}, the one its plan's \`we_lose_if\` names. What to do: write it there, or correct \`we_lose_if.result\` — before the run, never after.`,
142
+ "claim-lost": (f) => `${tick(f.id)}'s claim LOST: its ${tick(f.key)} is ${String(f.value)}, ${f.threshold}, the threshold its plan fixed before the run. What to do: report the loss in the paper, and say so in ${tick(RESULT_FILE)} with \`"claim": "${CLAIM_LOST}"\`; the threshold is not moved after the run.`,
143
+ "claim-holds": (f) => `The ${tick(RESULT_FILE)} of ${tick(f.id)} says \`"claim": "${CLAIM_LOST}"\`, but its ${tick(f.key)} is ${String(f.value)}, not ${f.threshold}: by its plan the claim holds. What to do: remove \`claim\`, or correct the number.`,
144
+ kappa: (f) => f.got === null
145
+ ? `The ${tick(RESULT_FILE)} of ${tick(f.id)} has no kappa for the step ${tick(f.step)} its plan's \`second_check\` declares. What to do: write it in \`kappa.${f.step}\`.`
146
+ : `${tick(f.id)}: the two raters of the step ${tick(f.step)} agree with kappa ${String(f.got)}, below the ${String(f.min)} its plan fixed before labelling. What to do: the labels of that step do not carry a number — revise the codebook and label again, or report the step as unreliable; the threshold is not lowered after the fact.`,
147
+ "self-test": (f) => f.failed === null
148
+ ? `The ${tick(RESULT_FILE)} of ${tick(f.id)} has no \`self_test\` counts, and its plan declares a self-test. What to do: write \`"self_test": { "passed": n, "failed": n }\` from the run on the known answers.`
149
+ : `${tick(f.id)}: ${String(f.failed)} self-test case(s) failed — a check that misses a known answer counts nothing. What to do: fix the check or leave it out of the count, and run the self-test again.`,
150
+ "self-test-empty": (f) => `${tick(f.id)}: its self-test ran no case (0 passed, 0 failed) — a check never tried on a known answer is not tested. What to do: make the self-test find and run its known inputs, and write the counts of that run.`,
151
+ funnel: (f) => `The ${tick(RESULT_FILE)} of ${tick(f.id)} counts no drop for ${f.missing.map(tick).join(", ")}, declared in its plan's \`funnel\`. What to do: write each in \`funnel\`, 0 when none was dropped for it.`,
152
+ "no-recall-audit": (f) => `The ${tick(RESULT_FILE)} of ${tick(f.id)} has no \`recall_audit\` counts, and its plan declares a recall audit. What to do: have a person read the sampled files in full and write \`"recall_audit": { "files": n, "units_in_files": n, "extracted": n }\`.`,
153
+ "recall-sample": (f) => `${tick(f.id)}: its recall audit read ${String(f.files)} file(s) in full, fewer than the ${String(f.min_files)} its plan fixed. What to do: audit the remaining files of the sample before the recall is reported.`,
154
+ recall: (f) => `${tick(f.id)}: the extractor found ${String(f.extracted)} of the ${String(f.units)} units a person found reading the audited files in full, a recall of ${(f.extracted / f.units).toFixed(3)}, below the ${String(f.min)} its plan fixed before the run — the extractor misses too much. What to do: report the recall as a limit of the number, or fix the extractor and audit again; the bar is not lowered after the fact.`,
155
+ };
156
+ const headOf = (p, f) => HEADS[p](f);
157
+ /** The one text a finding is reported with. */
158
+ export const resultMessage = (f) => `${headOf(f.problem, f)}\nRule ${RULE}: https://github.com/zernie/paperlint/blob/main/docs/rules/${RULE}.md`;
159
+ /** Every problem the rule reports, each its own message id. */
160
+ export const RESULT_PROBLEMS = [
161
+ "no-result-file",
162
+ "result-linked",
163
+ "result-unreadable",
164
+ "no-number",
165
+ "claim-lost",
166
+ "claim-holds",
167
+ "kappa",
168
+ "self-test",
169
+ "self-test-empty",
170
+ "funnel",
171
+ "no-recall-audit",
172
+ "recall-sample",
173
+ "recall",
174
+ ];
175
+ //# sourceMappingURL=study-result.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"study-result.js","sourceRoot":"","sources":["../../src/domain/study-result.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"outputs-before-decision-rule.d.ts","sourceRoot":"","sources":["../src/outputs-before-decision-rule.ts"],"names":[],"mappings":"AAmBA,OAAO,EAGL,KAAK,gBAAgB,EAEtB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOvD,iEAAiE;AACjE,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;CACxB;AAED,mGAAmG;AACnG,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,EACb,MAAM,SAAS,KACd,SAAS,gBAAgB,EAsB3B,CAAC;AAwCF,2DAA2D;AAC3D,eAAO,MAAM,0BAA0B,GACrC,MAAM,SAAS,KACd,QAAQ,CAAC,MAAM,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAc7D,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC;IACvC,+BAA+B,EAAE,OAAO,CAAC;CAC1C,CAAgD,CAAC"}
1
+ {"version":3,"file":"outputs-before-decision-rule.d.ts","sourceRoot":"","sources":["../src/outputs-before-decision-rule.ts"],"names":[],"mappings":"AAmBA,OAAO,EAIL,KAAK,gBAAgB,EAItB,MAAM,0BAA0B,CAAC;AAKlC,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,uBAAuB,CAAC;AAOvD,iEAAiE;AACjE,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,QAAQ,CAAC,GAAG,EAAE,QAAQ,CAAC;CACxB;AAED,mGAAmG;AACnG,eAAO,MAAM,kBAAkB,GAC7B,OAAO,MAAM,EACb,MAAM,SAAS,KACd,SAAS,gBAAgB,EA0B3B,CAAC;AA+EF,2DAA2D;AAC3D,eAAO,MAAM,0BAA0B,GACrC,MAAM,SAAS,KACd,QAAQ,CAAC,MAAM,CAAC,yBAAyB,EAAE,gBAAgB,CAAC,CAc7D,CAAC;AAEH,qDAAqD;AACrD,eAAO,MAAM,iBAAiB,EAAE,QAAQ,CAAC;IACvC,+BAA+B,EAAE,OAAO,CAAC;CAC1C,CAAgD,CAAC"}
@@ -17,7 +17,8 @@ import { basename, dirname, join } from "node:path";
17
17
  import { filter, map, pipe } from "remeda";
18
18
  import { callerPath } from "./caller-path.js";
19
19
  import { decisionEntry, modeStudies } from "./study-modes.js";
20
- import { judgeOrder, orderMessage, } from "./domain/decide-first.js";
20
+ import { firstOutputAfter, judgeOrder, orderMessage, } from "./domain/decide-first.js";
21
+ import { gatesOf } from "./domain/study-gates.js";
21
22
  import { REPRO_DIR } from "./domain/repro-layout.js";
22
23
  import { studyFolder } from "./study-folder.js";
23
24
  import { registryOf } from "./study-registry-rule.js";
@@ -26,11 +27,11 @@ const STATUS_FILE = "PIPELINE-STATUS.md";
26
27
  /** Every decide-first study of the paper folder `paper`, with its tree and its history's order. */
27
28
  export const decideFirstStudies = (paper, deps) => {
28
29
  const reader = studyFolder(paper, deps);
29
- return pipe(modeStudies(registryOf(paper, deps), reader, deps.codec), filter(isDecidedAndReady), map(({ row, plan, mode }) => {
30
+ return pipe(modeStudies(registryOf(paper, deps), reader, deps.codec), filter(isDecidedAndReady), map(({ row, plan, mode, gates }) => {
30
31
  const folder = join(paper, REPRO_DIR, row.folder);
31
32
  const decision = join(paper, mode.decision.file);
32
33
  const on = decisionEntry(reader, mode.decision.file);
33
- return {
34
+ const study = {
34
35
  id: row.id,
35
36
  folder: row.folder,
36
37
  plan,
@@ -40,8 +41,39 @@ export const decideFirstStudies = (paper, deps) => {
40
41
  ? deps.git.order(callerPath(folder), callerPath(decision))
41
42
  : on,
42
43
  };
44
+ return {
45
+ ...study,
46
+ gates: gateHistory(study, { now: gates, kind: row.kind, folder }, deps),
47
+ };
43
48
  }));
44
49
  };
50
+ /**
51
+ * The gates of a plan v2 now, and the plan at the study's first output after its decision: none for
52
+ * a plan v1, a history not read, or a study with no such output yet.
53
+ */
54
+ const gateHistory = (s, from, deps) => {
55
+ if (from.now === null || s.facts.kind !== "read")
56
+ return undefined;
57
+ const output = firstOutputAfter(s, s.facts.files);
58
+ if (output === null)
59
+ return undefined;
60
+ const at = deps.git.fileAt(callerPath(from.folder), output.commit, s.plan);
61
+ return { now: from.now, output, then: planThen(at, from.kind, deps) };
62
+ };
63
+ /** What the plan held at that commit, by gates. */
64
+ const planThen = (at, kind, deps) => {
65
+ if (at.kind === "unknown")
66
+ return at;
67
+ if (at.kind === "absent")
68
+ return { kind: "no-gates", why: "absent" };
69
+ const parsed = deps.codec.parsePlan(at.text, kind);
70
+ if (parsed.kind === "unreadable")
71
+ return { kind: "no-gates", why: "unreadable" };
72
+ const gates = gatesOf(parsed.plan);
73
+ return gates === null
74
+ ? { kind: "no-gates", why: "v1" }
75
+ : { kind: "gates", gates };
76
+ };
45
77
  /** Only a ready plan decides: a draft may name no outputs, or an empty decision file. */
46
78
  const isDecidedAndReady = (s) => s.mode.kind === "decide_before_run" && s.empty.length === 0;
47
79
  const PROBLEMS = [
@@ -53,6 +85,8 @@ const PROBLEMS = [
53
85
  "shallow",
54
86
  "undecided-output",
55
87
  "output-before-decision",
88
+ "gates-changed",
89
+ "gates-not-fixed",
56
90
  ];
57
91
  const NAME = "repro/outputs-before-decision";
58
92
  /** On `PIPELINE-STATUS.md`, every finding of every decide-first study of its paper, at its first line. */
@@ -1 +1 @@
1
- {"version":3,"file":"outputs-before-decision-rule.js","sourceRoot":"","sources":["../src/outputs-before-decision-rule.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"outputs-before-decision-rule.js","sourceRoot":"","sources":["../src/outputs-before-decision-rule.ts"],"names":[],"mappings":"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"}
@@ -37,8 +37,20 @@ export interface GitHistory {
37
37
  /** `file` (absolute, in the repository that holds `paper`), asked from the paper's folder. */
38
38
  readonly committed: (paper: AbsolutePath, file: AbsolutePath) => Committed;
39
39
  }
40
+ /** A file as it stood at a commit: its text, not there, or why git could not say. */
41
+ export type FileAt = {
42
+ readonly kind: "text";
43
+ readonly text: string;
44
+ } | {
45
+ readonly kind: "absent";
46
+ } | {
47
+ readonly kind: "unknown";
48
+ readonly why: string;
49
+ };
40
50
  export interface GitOrder {
41
51
  /** The order of `decision`'s first commit against every file's under `studyDir` (a folder that exists). */
42
52
  readonly order: (studyDir: AbsolutePath, decision: AbsolutePath) => OrderFacts;
53
+ /** `path` (relative to `studyDir`) as it stood at `commit`: what a plan's gates were at the first output. */
54
+ readonly fileAt: (studyDir: AbsolutePath, commit: string, path: string) => FileAt;
43
55
  }
44
56
  //# sourceMappingURL=git-history.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-history.d.ts","sourceRoot":"","sources":["../../src/ports/git-history.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,YAAY,EACV,QAAQ,EACR,WAAW,EACX,KAAK,EACL,UAAU,GACX,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,SAAS;AACnB,0EAA0E;AACxE;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAE;AACpC,iGAAiG;GAC/F;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACvD,oGAAoG;GAClG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACvD,uFAAuF;GACrF;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AACH,6DAA6D;GAC3D;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,WAAW,UAAU;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,KAAK,SAAS,CAAC;CAC5E;AAED,MAAM,WAAW,QAAQ;IACvB,2GAA2G;IAC3G,QAAQ,CAAC,KAAK,EAAE,CACd,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,YAAY,KACnB,UAAU,CAAC;CACjB"}
1
+ {"version":3,"file":"git-history.d.ts","sourceRoot":"","sources":["../../src/ports/git-history.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAC;AAEvD,YAAY,EACV,QAAQ,EACR,WAAW,EACX,KAAK,EACL,UAAU,GACX,MAAM,2BAA2B,CAAC;AAEnC,MAAM,MAAM,SAAS;AACnB,0EAA0E;AACxE;IAAE,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAA;CAAE;AACpC,iGAAiG;GAC/F;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACvD,oGAAoG;GAClG;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE;AACvD,uFAAuF;GACrF;IACE,QAAQ,CAAC,IAAI,EAAE,WAAW,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AACH,6DAA6D;GAC3D;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,WAAW,UAAU;IACzB,8FAA8F;IAC9F,QAAQ,CAAC,SAAS,EAAE,CAAC,KAAK,EAAE,YAAY,EAAE,IAAI,EAAE,YAAY,KAAK,SAAS,CAAC;CAC5E;AAED,qFAAqF;AACrF,MAAM,MAAM,MAAM,GACd;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,GAChD;IAAE,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAA;CAAE,GAC3B;IAAE,QAAQ,CAAC,IAAI,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC;AAEvD,MAAM,WAAW,QAAQ;IACvB,2GAA2G;IAC3G,QAAQ,CAAC,KAAK,EAAE,CACd,QAAQ,EAAE,YAAY,EACtB,QAAQ,EAAE,YAAY,KACnB,UAAU,CAAC;IAChB,6GAA6G;IAC7G,QAAQ,CAAC,MAAM,EAAE,CACf,QAAQ,EAAE,YAAY,EACtB,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,KACT,MAAM,CAAC;CACb"}
@@ -4,6 +4,7 @@
4
4
  * `src/adapters/study-registry/` (zod); `src/cli.ts` wires it.
5
5
  */
6
6
  import type { ParsedPlan, ParsedRegistry, StudyKind } from "../domain/study-registry.ts";
7
+ import type { ParsedResult } from "../domain/study-result.ts";
7
8
  export interface StudyRegistryCodec {
8
9
  /** A `studies.json`'s text: the registry, or the one reason it is not one of this schema. */
9
10
  readonly parse: (text: string) => ParsedRegistry;
@@ -14,5 +15,7 @@ export interface StudyRegistryCodec {
14
15
  readonly parsePlan: (text: string, kind: StudyKind) => ParsedPlan;
15
16
  /** A plan still named `prereg.json`, loose: the same three outcomes. */
16
17
  readonly parseLegacyPlan: (text: string) => ParsedPlan;
18
+ /** A study's `result.json`: its numbers, or why it is none (src/domain/study-result.ts). */
19
+ readonly parseResult: (text: string) => ParsedResult;
17
20
  }
18
21
  //# sourceMappingURL=study-registry-codec.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"study-registry-codec.d.ts","sourceRoot":"","sources":["../../src/ports/study-registry-codec.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,SAAS,EACV,MAAM,6BAA6B,CAAC;AAErC,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC;IACjD;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,UAAU,CAAC;IAClE,wEAAwE;IACxE,QAAQ,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,CAAC;CACxD"}
1
+ {"version":3,"file":"study-registry-codec.d.ts","sourceRoot":"","sources":["../../src/ports/study-registry-codec.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,EACV,UAAU,EACV,cAAc,EACd,SAAS,EACV,MAAM,6BAA6B,CAAC;AACrC,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC;IACjD;;;OAGG;IACH,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,SAAS,KAAK,UAAU,CAAC;IAClE,wEAAwE;IACxE,QAAQ,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,CAAC;IACvD,4FAA4F;IAC5F,QAAQ,CAAC,WAAW,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,YAAY,CAAC;CACtD"}
@@ -0,0 +1,25 @@
1
+ #!/usr/bin/env node
2
+ type Neighbour = {
3
+ id: string;
4
+ text: string;
5
+ url?: string;
6
+ title?: string;
7
+ };
8
+ type Claim = {
9
+ id: string;
10
+ sentence: string;
11
+ pieces: Record<string, string>;
12
+ };
13
+ /** Lines exactly as Read and the coverage checker number them (novelty_coverage.py: removesuffix("\n").split("\n")). */
14
+ export declare const lineCount: (text: string) => number;
15
+ /** Share of non-blank lines with a 6+ space gap: two page columns glued into one line by `pdftotext -layout`. */
16
+ export declare const glue: (text: string) => number;
17
+ /**
18
+ * The fewest chunks of at most CHUNK lines, spread evenly: 401 lines are [1, 201] [202, 401], not [1, 400] [401, 401].
19
+ * A stub last chunk (a lone page break or page number) holds no 8-word quote, so a complete read could not be proved.
20
+ */
21
+ export declare const chunks: (n: number) => [number, number][];
22
+ export declare const claimsText: (claims: Claim[]) => string;
23
+ /** The brief, pure. `lines` = the saved text's line count; `repair` = the checker's errors for this neighbour. */
24
+ export declare const readerBrief: (paper: string, n: Neighbour, claims: Claim[], lines: number, repair?: string[]) => string;
25
+ export {};
@@ -0,0 +1,6 @@
1
+ /** One command line: what it printed to stdout and to stderr, and its exit code. */
2
+ export declare function cli(argv: readonly string[]): {
3
+ readonly status: number;
4
+ readonly stdout: string;
5
+ readonly stderr: string;
6
+ };
@@ -0,0 +1,14 @@
1
+ /**
2
+ * The subcommands of `label-page`, by name. One table, read twice: the dispatcher in `label-page.ts`
3
+ * compares against these, and `SKILL.md.spec.ts` interpolates them into every command it instructs
4
+ * (a name that is not here is a type error there). So the skill cannot instruct a subcommand the
5
+ * script does not have.
6
+ *
7
+ * A module of its own, with no side effects: the spec imports it at compile time, and importing
8
+ * `label-page.ts` itself would run the command line.
9
+ */
10
+ export declare const COMMANDS: {
11
+ readonly build: "build";
12
+ readonly export: "export";
13
+ readonly schema: "schema";
14
+ };