paperlint 10.1.1 → 10.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 (72) hide show
  1. package/README.md +2 -0
  2. package/dist/adapters/study-registry/index.d.ts +357 -0
  3. package/dist/adapters/study-registry/index.d.ts.map +1 -0
  4. package/dist/adapters/study-registry/index.js +221 -0
  5. package/dist/adapters/study-registry/index.js.map +1 -0
  6. package/dist/cli.d.ts.map +1 -1
  7. package/dist/cli.js +42 -2
  8. package/dist/cli.js.map +1 -1
  9. package/dist/domain/repro-layout.d.ts +12 -4
  10. package/dist/domain/repro-layout.d.ts.map +1 -1
  11. package/dist/domain/repro-layout.js +49 -18
  12. package/dist/domain/repro-layout.js.map +1 -1
  13. package/dist/domain/scaffold-layout.d.ts +4 -3
  14. package/dist/domain/scaffold-layout.d.ts.map +1 -1
  15. package/dist/domain/scaffold-layout.js +7 -4
  16. package/dist/domain/scaffold-layout.js.map +1 -1
  17. package/dist/domain/study-registry.d.ts +372 -0
  18. package/dist/domain/study-registry.d.ts.map +1 -0
  19. package/dist/domain/study-registry.js +593 -0
  20. package/dist/domain/study-registry.js.map +1 -0
  21. package/dist/ports/study-registry-codec.d.ts +15 -0
  22. package/dist/ports/study-registry-codec.d.ts.map +1 -0
  23. package/dist/ports/study-registry-codec.js +2 -0
  24. package/dist/ports/study-registry-codec.js.map +1 -0
  25. package/dist/repro-layout-rule.d.ts.map +1 -1
  26. package/dist/repro-layout-rule.js +4 -3
  27. package/dist/repro-layout-rule.js.map +1 -1
  28. package/dist/studies.d.ts +27 -0
  29. package/dist/studies.d.ts.map +1 -0
  30. package/dist/studies.js +163 -0
  31. package/dist/studies.js.map +1 -0
  32. package/dist/study-registry-rule.d.ts +24 -0
  33. package/dist/study-registry-rule.d.ts.map +1 -0
  34. package/dist/study-registry-rule.js +145 -0
  35. package/dist/study-registry-rule.js.map +1 -0
  36. package/docs/design/study-registry.md +246 -0
  37. package/docs/layout.md +51 -46
  38. package/docs/rules/paper/allowed-files-only.md +3 -2
  39. package/docs/rules/repro/allowed-files-only.md +40 -30
  40. package/docs/rules/repro/study-plan-name.md +70 -0
  41. package/docs/rules/repro/study-registered.md +320 -0
  42. package/docs/rules/study/declare-sample.md +1 -1
  43. package/docs/rules.md +53 -51
  44. package/package.json +1 -1
  45. package/skills/build-benchmark/SKILL.md +39 -8
  46. package/skills/build-benchmark/SKILL.md.spec.ts +38 -7
  47. package/skills/build-label-page/SKILL.md +14 -9
  48. package/skills/build-label-page/SKILL.md.spec.ts +13 -8
  49. package/skills/paper-pipeline/references/artifact-checklist.md +2 -1
  50. package/skills/paper-pipeline/references/pipeline-status-template.md +5 -3
  51. package/skills/run-agent-grid/SKILL.md +13 -1
  52. package/skills/run-agent-grid/SKILL.md.spec.ts +12 -0
  53. package/src/adapters/study-registry/index.test.ts +484 -0
  54. package/src/adapters/study-registry/index.ts +328 -0
  55. package/src/cli.ts +53 -2
  56. package/src/domain/paper-layout.test.ts +1 -1
  57. package/src/domain/repro-layout.test.ts +18 -9
  58. package/src/domain/repro-layout.ts +58 -18
  59. package/src/domain/scaffold-layout.ts +7 -4
  60. package/src/domain/study-measurements.test.ts +629 -0
  61. package/src/domain/study-registry.test.ts +666 -0
  62. package/src/domain/study-registry.ts +1044 -0
  63. package/src/folder-layout-hook.test.ts +10 -0
  64. package/src/new-paper.test.ts +29 -2
  65. package/src/ports/study-registry-codec.ts +15 -0
  66. package/src/repro-layout-rule.ts +4 -3
  67. package/src/rule-cases.test.ts +68 -0
  68. package/src/studies-cli.test.ts +113 -0
  69. package/src/studies.test.ts +359 -0
  70. package/src/studies.ts +268 -0
  71. package/src/study-registry-rule.test.ts +456 -0
  72. package/src/study-registry-rule.ts +239 -0
@@ -0,0 +1,15 @@
1
+ /**
2
+ * How a `repro/studies.json`, and a study's `plan.json`, become values: its text parsed once, where it enters, against the schema
3
+ * of `StudyRegistry` (`src/domain/study-registry.ts`). The one implementation is
4
+ * `src/adapters/study-registry/` (zod); `src/cli.ts` wires it.
5
+ */
6
+ import type { ParsedPlan, ParsedRegistry } from "../domain/study-registry.ts";
7
+ export interface StudyRegistryCodec {
8
+ /** A `studies.json`'s text: the registry, or the one reason it is not one of this schema. */
9
+ readonly parse: (text: string) => ParsedRegistry;
10
+ /** A study's `plan.json` text, strict: ready, a draft naming its empty texts, or why it is no plan. */
11
+ readonly parsePlan: (text: string) => ParsedPlan;
12
+ /** A plan still named `prereg.json`, loose: the same three outcomes. */
13
+ readonly parseLegacyPlan: (text: string) => ParsedPlan;
14
+ }
15
+ //# sourceMappingURL=study-registry-codec.d.ts.map
@@ -0,0 +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,EAAE,UAAU,EAAE,cAAc,EAAE,MAAM,6BAA6B,CAAC;AAE9E,MAAM,WAAW,kBAAkB;IACjC,6FAA6F;IAC7F,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,cAAc,CAAC;IACjD,uGAAuG;IACvG,QAAQ,CAAC,SAAS,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,CAAC;IACjD,wEAAwE;IACxE,QAAQ,CAAC,eAAe,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,UAAU,CAAC;CACxD"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=study-registry-codec.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"study-registry-codec.js","sourceRoot":"","sources":["../../src/ports/study-registry-codec.ts"],"names":[],"mappings":""}
@@ -1 +1 @@
1
- {"version":3,"file":"repro-layout-rule.d.ts","sourceRoot":"","sources":["../src/repro-layout-rule.ts"],"names":[],"mappings":"AA2BA,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAkB5D;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,KAAK,MAAM,EACX,SAAS,SAAS,WAAW,EAAE,EAC/B,OAAO,KAAK,KACX,SAAS,MAAM,EAC6C,CAAC;AAEhE,kGAAkG;AAClG,eAAO,MAAM,cAAc,GACzB,KAAK,MAAM,EACX,MAAM,gBAAgB,KACrB,SAAS,WAAW,EAMlB,CAAC;AAgBN,mDAAmD;AACnD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,gBAAgB,GACrB,QAAQ,CAAC,MAAM,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,CAAC,CAwB1D;AAED,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAC7C,MAAM,CAAC,0BAA0B,EAAE,OAAO,CAAC,CACF,CAAC"}
1
+ {"version":3,"file":"repro-layout-rule.d.ts","sourceRoot":"","sources":["../src/repro-layout-rule.ts"],"names":[],"mappings":"AA4BA,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAChC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAkB5D;;;GAGG;AACH,eAAO,MAAM,UAAU,GACrB,KAAK,MAAM,EACX,SAAS,SAAS,WAAW,EAAE,EAC/B,OAAO,KAAK,KACX,SAAS,MAAM,EAC6C,CAAC;AAEhE,kGAAkG;AAClG,eAAO,MAAM,cAAc,GACzB,KAAK,MAAM,EACX,MAAM,gBAAgB,KACrB,SAAS,WAAW,EAMlB,CAAC;AAgBN,mDAAmD;AACnD,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,gBAAgB,GACrB,QAAQ,CAAC,MAAM,CAAC,oBAAoB,EAAE,gBAAgB,CAAC,CAAC,CAwB1D;AAED,+FAA+F;AAC/F,eAAO,MAAM,wBAAwB,EAAE,QAAQ,CAC7C,MAAM,CAAC,0BAA0B,EAAE,OAAO,CAAC,CACF,CAAC"}
@@ -1,6 +1,7 @@
1
1
  /**
2
- * `repro/allowed-files-only` — the top of a paper's `repro/` holds an index, the shared `tools/` and
3
- * `data/`, and one dated folder per study, each with a `README.md`.
2
+ * `repro/allowed-files-only` — the top of a paper's `repro/` holds an index, the study registry, the
3
+ * shared `tools/` and `data/`, and one folder per study, each with a `README.md`. Whether each study
4
+ * folder has its row in the registry is `repro/study-registered`'s (src/study-registry-rule.ts).
4
5
  *
5
6
  * What may stand there, and why, is `src/domain/repro-layout.ts` and docs/rules/repro/allowed-files-only.md.
6
7
  * This file lists the folder and reports.
@@ -42,7 +43,7 @@ export const reproEntriesOf = (dir, deps) => [...deps.listDir(callerPath(join(di
42
43
  const META = {
43
44
  type: "suggestion",
44
45
  docs: {
45
- description: "the top of a paper's repro/ holds README.md, .gitignore, tools/, data/ and one <slug>-YYYY-MM-DD folder per study, each with a README.md",
46
+ description: "the top of a paper's repro/ holds README.md, studies.json, .gitignore, tools/, data/ and one <id>-<slug> (or <slug>-YYYY-MM-DD) folder per study, each with a README.md",
46
47
  url: rulePageUrl("repro/allowed-files-only"),
47
48
  },
48
49
  schema: [],
@@ -1 +1 @@
1
- {"version":3,"file":"repro-layout-rule.js","sourceRoot":"","sources":["../src/repro-layout-rule.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AACH,OAAO,EAAE,QAAQ,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACpD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EACL,MAAM,EACN,SAAS,EACT,UAAU,EACV,YAAY,GAEb,MAAM,0BAA0B,CAAC;AAQlC,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,MAAM,WAAW,GAAG,oBAAoB,CAAC;AAEzC,kFAAkF;AAClF,MAAM,UAAU,GAAG,CACjB,GAAW,EACX,OAA+B,EAC/B,KAAY,EACW,EAAE,CACzB,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAClB,GAAG,CAAC;IACJ,SAAS,EACP,CAAC,CAAC,IAAI,KAAK,KAAK;QAChB,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC;CACjE,CAAC,CAAC,CAAC;AAEN;;;GAGG;AACH,MAAM,CAAC,MAAM,UAAU,GAAG,CACxB,GAAW,EACX,OAA+B,EAC/B,KAAY,EACO,EAAE,CACrB,UAAU,CAAC,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,YAAY,CAAC,CAAC;AAEhE,kGAAkG;AAClG,MAAM,CAAC,MAAM,cAAc,GAAG,CAC5B,GAAW,EACX,IAAsB,EACE,EAAE,CAC1B,CAAC,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;IACxE,IAAI;IACJ,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,GAAG,EAAE,SAAS,EAAE,IAAI,CAAC,CAAC,CAAC;QAC7D,CAAC,CAAC,MAAM;QACR,CAAC,CAAC,KAAK;CACV,CAAC,CAAC,CAAC;AAEN,MAAM,IAAI,GAA6B;IACrC,IAAI,EAAE,YAAY;IAClB,IAAI,EAAE;QACJ,WAAW,EACT,0IAA0I;QAC5I,GAAG,EAAE,WAAW,CAAC,0BAA0B,CAAC;KAC7C;IACD,MAAM,EAAE,EAAE;IACV,QAAQ,EAAE;QACR,6FAA6F;QAC7F,SAAS,EAAE,UAAU;KACtB;CACF,CAAC;AAEF,mDAAmD;AACnD,MAAM,UAAU,gBAAgB,CAC9B,IAAsB;IAEtB,OAAO;QACL,oBAAoB,EAAE;YACpB,IAAI,EAAE,IAAI;YACV,MAAM,CAAC,OAA0B;gBAC/B,IAAI,QAAQ,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,WAAW;oBAAE,OAAO,EAAE,CAAC;gBAC1D,OAAO;oBACL,IAAI;wBACF,MAAM,GAAG,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;wBACtC,MAAM,EAAE,GAAG,OAAO,CAAC,UAAU,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;wBACjD,UAAU,CAAC,GAAG,EAAE,cAAc,CAAC,GAAG,EAAE,IAAI,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,CAC5D,CAAC,IAAI,EAAE,EAAE;4BACP,OAAO,CAAC,MAAM,CAAC;gCACb,GAAG,EAAE,EAAE,KAAK,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE;gCAC3B,SAAS,EAAE,WAAW;gCACtB,IAAI,EAAE,EAAE,IAAI,EAAE;6BACf,CAAC,CAAC;wBACL,CAAC,CACF,CAAC;oBACJ,CAAC;iBACF,CAAC;YACJ,CAAC;SACF;KACF,CAAC;AACJ,CAAC;AAED,+FAA+F;AAC/F,MAAM,CAAC,MAAM,wBAAwB,GAEjC,EAAE,0BAA0B,EAAE,OAAO,EAAE,CAAC"}
1
+ {"version":3,"file":"repro-layout-rule.js","sourceRoot":"","sources":["../src/repro-layout-rule.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,27 @@
1
+ import type { Files } from "./ports/files.ts";
2
+ import type { StudyRegistryCodec } from "./ports/study-registry-codec.ts";
3
+ import type { ListDir } from "./ports/talk-media.ts";
4
+ /** What one `studies` run was asked, after the command line. */
5
+ export interface StudiesArgs {
6
+ readonly sub: string | undefined;
7
+ readonly paperDir: string | undefined;
8
+ /** `new`'s title; for `index`, an argument too many. */
9
+ readonly title: string | undefined;
10
+ /** Positional arguments past the title: refused. */
11
+ readonly extra: readonly string[];
12
+ /** `--kind <kind>`; null: the default. */
13
+ readonly kind: string | null;
14
+ }
15
+ export interface StudiesDeps {
16
+ readonly files: Files;
17
+ readonly listDir: ListDir;
18
+ readonly codec: StudyRegistryCodec;
19
+ readonly cwd: string;
20
+ /** Today, `YYYY-MM-DD`: the root reads the clock. */
21
+ readonly today: string;
22
+ readonly log: (line: string) => void;
23
+ readonly err: (line: string) => void;
24
+ }
25
+ /** The run: 0 done, 1 refused by the paper's state, 2 refused by the command line. */
26
+ export declare function runStudies(a: StudiesArgs, deps: StudiesDeps): number;
27
+ //# sourceMappingURL=studies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studies.d.ts","sourceRoot":"","sources":["../src/studies.ts"],"names":[],"mappings":"AAoCA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAGrD,gEAAgE;AAChE,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,MAAM,GAAG,SAAS,CAAC;IACtC,wDAAwD;IACxD,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAC;IACnC,oDAAoD;IACpD,QAAQ,CAAC,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC,0CAA0C;IAC1C,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,KAAK,EAAE,KAAK,CAAC;IACtB,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAC;IAC1B,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;IACrB,qDAAqD;IACrD,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;IACrC,QAAQ,CAAC,GAAG,EAAE,CAAC,IAAI,EAAE,MAAM,KAAK,IAAI,CAAC;CACtC;AA6LD,sFAAsF;AACtF,wBAAgB,UAAU,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,EAAE,WAAW,GAAG,MAAM,CAepE"}
@@ -0,0 +1,163 @@
1
+ /**
2
+ * `paperlint studies new|index <paper-dir>` — the two commands that write a paper's study registry,
3
+ * `repro/studies.json`, and its index in `repro/README.md` (docs/design/study-registry.md).
4
+ *
5
+ * new <paper-dir> "<title>" [--kind <kind>]
6
+ * the next id; `repro/<id>-<slug>/README.md` with the id and title in its frontmatter, and
7
+ * `plan.json`, the plan's template; the row, `status: designing`, today's date, its `plan`;
8
+ * the index regenerated
9
+ * index <paper-dir>
10
+ * the index block of `repro/README.md`, regenerated from the registry
11
+ *
12
+ * Nothing else changes a row: a study's status, result and `in_paper` are edited in `studies.json`, and
13
+ * `repro/study-registered` checks them. The prefix is the paper's own choice, so a paper without a
14
+ * registry is refused with the file to write rather than given a guessed one.
15
+ */
16
+ import { join, relative, resolve } from "node:path";
17
+ import { callerPath } from "./caller-path.js";
18
+ import { README, REPRO_DIR } from "./domain/repro-layout.js";
19
+ import { DEFAULT_KIND, PLAN_FILE, STUDIES_FILE, STUDY_KINDS, addStudy, indexInSync, isStudyKind, planTemplate, planText, registryText, studyReadme, withIndex, } from "./domain/study-registry.js";
20
+ import { registryOf } from "./study-registry-rule.js";
21
+ const NEW_USAGE = 'npx paperlint studies new <paper-dir> "<title>" [--kind <kind>]';
22
+ const INDEX_USAGE = "npx paperlint studies index <paper-dir>";
23
+ const SUBS = `new or index — ${NEW_USAGE} · ${INDEX_USAGE}`;
24
+ const STATUS_FILE = "PIPELINE-STATUS.md";
25
+ const refuse = (code, line) => ({ code, line });
26
+ /** The paper folder's registry, or the refusal naming why there is none to write to. */
27
+ function registryIn(p, deps) {
28
+ const r = registryOf(p.dir, deps);
29
+ const file = `${p.shown}/${REPRO_DIR}/${STUDIES_FILE}`;
30
+ switch (r.kind) {
31
+ case "absent":
32
+ return refuse(1, `${file} does not exist. Its prefix is the paper's own choice — a capital letter, then capitals or digits, one per paper (P1) — so write the file, then run this again:\n\n{ "prefix": "P1", "studies": [] }`);
33
+ case "unreadable":
34
+ return refuse(1, `${file} is not a study registry: ${r.why}`);
35
+ case "read":
36
+ return r.registry;
37
+ }
38
+ }
39
+ const isRefusal = (v) => typeof v === "object" && v !== null && "code" in v && "line" in v;
40
+ const text = (s) => new TextEncoder().encode(s);
41
+ /** The README's text; null when there is none. */
42
+ const readmeOf = (dir, files) => {
43
+ const b = files.readBytes(callerPath(join(dir, REPRO_DIR, README)));
44
+ return b === null ? null : new TextDecoder().decode(b);
45
+ };
46
+ const studiesCount = (r) => `${String(r.studies.length)} ${r.studies.length === 1 ? "study" : "studies"}`;
47
+ /**
48
+ * Write the index of `r` into the README; whether it wrote. A block already in sync is left as it
49
+ * is, so the padding a formatter gave the table is never undone.
50
+ */
51
+ function writeIndex(dir, r, files) {
52
+ const before = readmeOf(dir, files);
53
+ if (indexInSync(before, r))
54
+ return false;
55
+ files.writeAtomic(callerPath(join(dir, REPRO_DIR, README)), text(withIndex(before, r)));
56
+ return true;
57
+ }
58
+ /** The refusal when something that is not a file sits where `repro/README.md` goes; null when none. */
59
+ function readmeBlocked(p, deps) {
60
+ const listed = deps.listDir(callerPath(join(p.dir, REPRO_DIR)));
61
+ const path = callerPath(join(p.dir, REPRO_DIR, README));
62
+ return listed.includes(README) && !deps.files.isFile(path)
63
+ ? refuse(1, `${p.shown}/${REPRO_DIR}/${README} is not a file, so the index cannot be written there. Move it, then run this again.`)
64
+ : null;
65
+ }
66
+ /** `studies index`: the README's block regenerated from the registry. */
67
+ function runIndex(p, a, deps) {
68
+ const [surplus] = [...(a.title === undefined ? [] : [a.title]), ...a.extra];
69
+ if (surplus !== undefined)
70
+ return refuse(2, `studies index takes only the paper's folder — \`${surplus}\` is one argument too many`);
71
+ const r = registryIn(p, deps);
72
+ if (isRefusal(r))
73
+ return r;
74
+ const blocked = readmeBlocked(p, deps);
75
+ if (blocked !== null)
76
+ return blocked;
77
+ const readme = `${p.shown}/${REPRO_DIR}/${README}`;
78
+ return [
79
+ writeIndex(p.dir, r, deps.files)
80
+ ? `wrote the index of ${studiesCount(r)} in ${readme}`
81
+ : `the index in ${readme} is in sync with ${studiesCount(r)}`,
82
+ ];
83
+ }
84
+ /** `new`'s title and kind from the command line, or the refusal. */
85
+ function newArgs(a) {
86
+ if (a.title === undefined)
87
+ return refuse(2, `studies new needs the study's title: ${NEW_USAGE}`);
88
+ const [surplus] = a.extra;
89
+ if (surplus !== undefined)
90
+ return refuse(2, `studies new takes the paper's folder and one title — \`${surplus}\` is one argument too many (quote a title of several words)`);
91
+ const kind = a.kind ?? DEFAULT_KIND;
92
+ return isStudyKind(kind)
93
+ ? { title: a.title, kind }
94
+ : refuse(2, `--kind ${kind} is not a kind of study: one of ${STUDY_KINDS.join(", ")}`);
95
+ }
96
+ /** Write a new study's README.md and plan.json, the registry, and the index; the lines that say so. */
97
+ function writeStudy(p, added, files) {
98
+ const { study, registry } = added;
99
+ const at = (...names) => callerPath(join(p.dir, REPRO_DIR, ...names));
100
+ files.writeAtomic(at(study.folder, README), text(studyReadme(study)));
101
+ files.writeAtomic(at(study.folder, PLAN_FILE), text(planText(planTemplate())));
102
+ files.writeAtomic(at(STUDIES_FILE), text(registryText(registry)));
103
+ writeIndex(p.dir, registry, files);
104
+ const repro = `${p.shown}/${REPRO_DIR}`;
105
+ return [
106
+ `created ${repro}/${study.folder}/${README}`,
107
+ `created ${repro}/${study.folder}/${PLAN_FILE}, the study's plan: its fields are there to fill in before the first run`,
108
+ `added ${study.id} to ${repro}/${STUDIES_FILE}: kind ${study.kind}, status ${study.status}, ${study.date}`,
109
+ `wrote the index of ${studiesCount(registry)} in ${repro}/${README}`,
110
+ `Next: write the study's one-sentence question in its row (\`question\`) and in its README.md. When it ends, set \`status\`, \`result\`, \`result_file\` and \`in_paper\` in its row, then run \`npx paperlint studies index ${p.shown}\`.`,
111
+ ];
112
+ }
113
+ /** `studies new`: the folder, its README.md, the row, the index. */
114
+ function runNew(p, a, deps) {
115
+ const args = newArgs(a);
116
+ if (isRefusal(args))
117
+ return args;
118
+ const r = registryIn(p, deps);
119
+ if (isRefusal(r))
120
+ return r;
121
+ const blocked = readmeBlocked(p, deps);
122
+ if (blocked !== null)
123
+ return blocked;
124
+ const added = addStudy(r, { ...args, date: deps.today });
125
+ if (!added.ok)
126
+ return refuse(2, added.why);
127
+ const folder = added.study.folder;
128
+ return deps.listDir(callerPath(join(p.dir, REPRO_DIR))).includes(folder)
129
+ ? refuse(1, `${p.shown}/${REPRO_DIR}/${folder}/ already exists; it is never overwritten. Register it by hand, or remove it and run this again.`)
130
+ : writeStudy(p, added, deps.files);
131
+ }
132
+ /** The paper folder the command line names, or the refusal. */
133
+ function paperOf(a, deps) {
134
+ if (a.sub === undefined)
135
+ return refuse(2, `studies needs a subcommand: ${SUBS}`);
136
+ if (a.sub !== "new" && a.sub !== "index")
137
+ return refuse(2, `unknown subcommand \`studies ${a.sub}\`: ${SUBS}`);
138
+ if (a.paperDir === undefined)
139
+ return refuse(2, `studies ${a.sub} needs the paper's folder: ${a.sub === "new" ? NEW_USAGE : INDEX_USAGE}`);
140
+ const dir = resolve(deps.cwd, a.paperDir);
141
+ const shown = relative(deps.cwd, dir) || ".";
142
+ return deps.files.isFile(callerPath(join(dir, STATUS_FILE)))
143
+ ? { dir, shown }
144
+ : refuse(2, `${shown} is not a paper folder: it has no ${STATUS_FILE}`);
145
+ }
146
+ /** The run: 0 done, 1 refused by the paper's state, 2 refused by the command line. */
147
+ export function runStudies(a, deps) {
148
+ const p = paperOf(a, deps);
149
+ const out = isRefusal(p)
150
+ ? p
151
+ : a.sub === "new"
152
+ ? runNew(p, a, deps)
153
+ : runIndex(p, a, deps);
154
+ if (isRefusal(out)) {
155
+ deps.err(out.line);
156
+ return out.code;
157
+ }
158
+ out.forEach((line) => {
159
+ deps.log(line);
160
+ });
161
+ return 0;
162
+ }
163
+ //# sourceMappingURL=studies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"studies.js","sourceRoot":"","sources":["../src/studies.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import { type RegistryState, type StudyFinding } from "./domain/study-registry.ts";
2
+ import type { FolderLayoutDeps } from "./folder-layout-rule.ts";
3
+ import type { FolderRuleModule } from "./folder-venue-rule.ts";
4
+ import type { StudyRegistryCodec } from "./ports/study-registry-codec.ts";
5
+ /** What the rule reads with: the disk, its listings, and the registry's parser. */
6
+ export interface StudyRegistryDeps extends FolderLayoutDeps {
7
+ readonly codec: StudyRegistryCodec;
8
+ }
9
+ /** The registry of the paper folder `dir`: absent, unreadable with why, or read. */
10
+ export declare function registryOf(dir: string, deps: Pick<StudyRegistryDeps, "files" | "codec">): RegistryState;
11
+ /** Every finding of the paper folder `dir`'s study registry — THE function behind both rules. */
12
+ export declare function studyFindings(dir: string, deps: StudyRegistryDeps): readonly StudyFinding[];
13
+ /**
14
+ * The two rules, reading the folder through `deps`: `study-registered`, the registry's errors, and
15
+ * `study-plan-name`, a warning for a plan still named `prereg.json` — read as the plan, so a paper
16
+ * that wrote one before `plan.json` existed is not broken, and told the name to move to.
17
+ */
18
+ export declare function studyRegistryRules(deps: StudyRegistryDeps): Readonly<Record<"study-registered" | "study-plan-name", FolderRuleModule>>;
19
+ /** The levels they are on at in paperlint's own config, for every paper's `PIPELINE-STATUS.md`. */
20
+ export declare const STUDY_REGISTRY_RULE_LEVELS: Readonly<{
21
+ "repro/study-registered": "error";
22
+ "repro/study-plan-name": "warn";
23
+ }>;
24
+ //# sourceMappingURL=study-registry-rule.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"study-registry-rule.d.ts","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"AA2BA,OAAO,EAQL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,4BAA4B,CAAC;AACpC,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAChE,OAAO,KAAK,EAEV,gBAAgB,EACjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,iCAAiC,CAAC;AAM1E,mFAAmF;AACnF,MAAM,WAAW,iBAAkB,SAAQ,gBAAgB;IACzD,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;CACpC;AAQD,oFAAoF;AACpF,wBAAgB,UAAU,CACxB,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,IAAI,CAAC,iBAAiB,EAAE,OAAO,GAAG,OAAO,CAAC,GAC/C,aAAa,CAOf;AAwDD,iGAAiG;AACjG,wBAAgB,aAAa,CAC3B,GAAG,EAAE,MAAM,EACX,IAAI,EAAE,iBAAiB,GACtB,SAAS,YAAY,EAAE,CASzB;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"}
@@ -0,0 +1,145 @@
1
+ /**
2
+ * `repro/study-registered` — every study folder at the top of a paper's `repro/` has exactly one row in
3
+ * `repro/studies.json`, every row names a folder that exists, a row's measurement and plan hold
4
+ * together, and the index in `repro/README.md` is the one the registry generates. Beside it,
5
+ * `repro/study-plan-name`, a warning: a plan still named `prereg.json`.
6
+ *
7
+ * What is judged, and why, is `src/domain/study-registry.ts` and docs/rules/repro/study-registered.md.
8
+ * This file lists `repro/`, reads the registry, the README, the result files and the plans, and reports.
9
+ *
10
+ * ── WHY A RULE OF ITS OWN, NOT MORE OF `repro/allowed-files-only` ─────────────────────
11
+ * `repro/allowed-files-only` judges what may stand at the top of `repro/`, by name, and accepts the
12
+ * dated `<slug>-YYYY-MM-DD` folders of a paper that predates the registry. This rule judges the
13
+ * registry against the folders. A paper that keeps its dated folders turns this one off and keeps
14
+ * its layout judged.
15
+ *
16
+ * ── WHICH FILE IT REPORTS ON ─────────────────────────────────────────────────────
17
+ * `PIPELINE-STATUS.md`, first line, like the layout rules: every paper has it, and ESLint lints no
18
+ * file in `repro/`.
19
+ */
20
+ import { basename, dirname, join, posix } from "node:path";
21
+ import { callerPath } from "./caller-path.js";
22
+ import { README, REPRO_BYPRODUCTS, REPRO_DIR, REPRO_DIRS, } from "./domain/repro-layout.js";
23
+ import { LEGACY_PLAN_FILE, PLAN_NAME_PROBLEMS, STUDIES_FILE, judgeStudies, planKeys, studyMessage, } from "./domain/study-registry.js";
24
+ import { reproEntriesOf } from "./repro-layout-rule.js";
25
+ import { rulePageUrl } from "./venue-rules.js";
26
+ const STATUS_FILE = "PIPELINE-STATUS.md";
27
+ /** The text of the file at `p`; null when there is none, or a directory sits there. */
28
+ const textAt = (files, p) => {
29
+ const b = files.isFile(callerPath(p)) ? files.readBytes(callerPath(p)) : null;
30
+ return b === null ? null : new TextDecoder().decode(b);
31
+ };
32
+ /** The registry of the paper folder `dir`: absent, unreadable with why, or read. */
33
+ export function registryOf(dir, deps) {
34
+ const text = textAt(deps.files, join(dir, REPRO_DIR, STUDIES_FILE));
35
+ if (text === null)
36
+ return { kind: "absent" };
37
+ const parsed = deps.codec.parse(text);
38
+ return parsed.ok
39
+ ? { kind: "read", registry: parsed.registry }
40
+ : { kind: "unreadable", why: parsed.why };
41
+ }
42
+ /** The study folders at the top of `<dir>/repro/`: every folder but the shared ones and the byproducts. */
43
+ const studyFolders = (dir, deps) => reproEntriesOf(dir, deps)
44
+ .filter((e) => e.kind === "dir" &&
45
+ !REPRO_DIRS.includes(e.name) &&
46
+ !REPRO_BYPRODUCTS.includes(e.name))
47
+ .map((e) => e.name);
48
+ /** Each `<folder>/<result_file>` of `r` that is a file. */
49
+ const existingResults = (dir, r, files) => new Set((r.kind === "read" ? r.registry.studies : [])
50
+ .flatMap((s) => s.result_file === undefined ? [] : [`${s.folder}/${s.result_file}`])
51
+ // A NUL is no path the disk can hold, and probing one throws: such a row reads as missing.
52
+ .filter((p) => !p.includes("\0") &&
53
+ files.isFile(callerPath(join(dir, REPRO_DIR, p)))));
54
+ /**
55
+ * The plan each row of `r` names, read and parsed, by `<folder>/<plan>`; a plan not there is left out.
56
+ * A plan still named `prereg.json` is parsed by the loose schema of its old name.
57
+ */
58
+ const plansOf = (dir, r, deps) => new Map((r.kind === "read" ? planKeys(r.registry) : [])
59
+ // A NUL is no path the disk can hold, and probing one throws: such a plan reads as missing.
60
+ .filter((key) => !key.includes("\0"))
61
+ .flatMap((key) => {
62
+ const text = textAt(deps.files, join(dir, REPRO_DIR, key));
63
+ if (text === null)
64
+ return [];
65
+ const parse = posix.basename(key) === LEGACY_PLAN_FILE
66
+ ? deps.codec.parseLegacyPlan
67
+ : deps.codec.parsePlan;
68
+ return [[key, parse(text)]];
69
+ }));
70
+ /** Every finding of the paper folder `dir`'s study registry — THE function behind both rules. */
71
+ export function studyFindings(dir, deps) {
72
+ const registry = registryOf(dir, deps);
73
+ return judgeStudies({
74
+ folders: studyFolders(dir, deps),
75
+ registry,
76
+ readme: textAt(deps.files, join(dir, REPRO_DIR, README)),
77
+ existingResults: existingResults(dir, registry, deps.files),
78
+ plans: plansOf(dir, registry, deps),
79
+ });
80
+ }
81
+ /** The problems `repro/study-registered` reports, each its own message id; the text is `studyMessage`. */
82
+ const PROBLEMS = [
83
+ "no-registry",
84
+ "unreadable",
85
+ "unregistered",
86
+ "no-folder",
87
+ "two-rows",
88
+ "bad-id",
89
+ "duplicate-id",
90
+ "folder-name",
91
+ "long-title",
92
+ "no-result",
93
+ "result-file",
94
+ "no-successor",
95
+ "stale-index",
96
+ "unknown-measurement",
97
+ "empty-measurement",
98
+ "unknown-requirement",
99
+ "headline-approval",
100
+ "bad-plan",
101
+ "author-check",
102
+ ];
103
+ /** A rule's meta: its page, and a message id per problem, the whole text being `studyMessage`. */
104
+ const metaOf = (name, description, problems) => ({
105
+ type: "suggestion",
106
+ docs: { description, url: rulePageUrl(name) },
107
+ schema: [],
108
+ messages: Object.fromEntries(problems.map((p) => [p, "{{text}}"])),
109
+ });
110
+ /** A rule that reports the findings of `problems`, reading the folder through `deps`. */
111
+ const ruleOf = (meta, problems, deps) => ({
112
+ meta,
113
+ create(context) {
114
+ if (basename(context.filename) !== STATUS_FILE)
115
+ return {};
116
+ return {
117
+ root() {
118
+ const at = context.sourceCode.getLocFromIndex(0);
119
+ studyFindings(dirname(context.filename), deps)
120
+ .filter((f) => problems.includes(f.problem))
121
+ .forEach((f) => {
122
+ context.report({
123
+ loc: { start: at, end: at },
124
+ messageId: f.problem,
125
+ data: { text: studyMessage(f) },
126
+ });
127
+ });
128
+ },
129
+ };
130
+ },
131
+ });
132
+ /**
133
+ * The two rules, reading the folder through `deps`: `study-registered`, the registry's errors, and
134
+ * `study-plan-name`, a warning for a plan still named `prereg.json` — read as the plan, so a paper
135
+ * that wrote one before `plan.json` existed is not broken, and told the name to move to.
136
+ */
137
+ export function studyRegistryRules(deps) {
138
+ return {
139
+ "study-registered": ruleOf(metaOf("repro/study-registered", "every study folder at the top of a paper's repro/ has exactly one row in repro/studies.json, every row names a folder that exists, its measurement and its plan hold together, and repro/README.md's index is the one the registry generates", PROBLEMS), PROBLEMS, deps),
140
+ "study-plan-name": ruleOf(metaOf("repro/study-plan-name", "a study's plan is named plan.json, not prereg.json", PLAN_NAME_PROBLEMS), PLAN_NAME_PROBLEMS, deps),
141
+ };
142
+ }
143
+ /** The levels they are on at in paperlint's own config, for every paper's `PIPELINE-STATUS.md`. */
144
+ export const STUDY_REGISTRY_RULE_LEVELS = { "repro/study-registered": "error", "repro/study-plan-name": "warn" };
145
+ //# sourceMappingURL=study-registry-rule.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"study-registry-rule.js","sourceRoot":"","sources":["../src/study-registry-rule.ts"],"names":[],"mappings":"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"}