paperlint 10.3.0 → 10.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.github/workflows/ci.yml +15 -4
- package/README.md +1 -0
- package/dist/adapters/git/index.d.ts +10 -0
- package/dist/adapters/git/index.d.ts.map +1 -0
- package/dist/adapters/git/index.js +151 -0
- package/dist/adapters/git/index.js.map +1 -0
- package/dist/adapters/memory/index.d.ts +6 -0
- package/dist/adapters/memory/index.d.ts.map +1 -1
- package/dist/adapters/memory/index.js +8 -0
- package/dist/adapters/memory/index.js.map +1 -1
- package/dist/adapters/node/index.d.ts +1 -0
- package/dist/adapters/node/index.d.ts.map +1 -1
- package/dist/adapters/node/index.js +1 -0
- package/dist/adapters/node/index.js.map +1 -1
- package/dist/adapters/node/list-entries.io.d.ts +3 -0
- package/dist/adapters/node/list-entries.io.d.ts.map +1 -0
- package/dist/adapters/node/list-entries.io.js +24 -0
- package/dist/adapters/node/list-entries.io.js.map +1 -0
- package/dist/adapters/study-registry/index.d.ts +70 -10
- package/dist/adapters/study-registry/index.d.ts.map +1 -1
- package/dist/adapters/study-registry/index.js +84 -10
- package/dist/adapters/study-registry/index.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +33 -3
- package/dist/cli.js.map +1 -1
- package/dist/domain/decide-first.d.ts +100 -0
- package/dist/domain/decide-first.d.ts.map +1 -0
- package/dist/domain/decide-first.js +102 -0
- package/dist/domain/decide-first.js.map +1 -0
- package/dist/domain/index-columns.d.ts +45 -0
- package/dist/domain/index-columns.d.ts.map +1 -0
- package/dist/domain/index-columns.js +62 -0
- package/dist/domain/index-columns.js.map +1 -0
- package/dist/domain/study-mode.d.ts +37 -0
- package/dist/domain/study-mode.d.ts.map +1 -0
- package/dist/domain/study-mode.js +45 -0
- package/dist/domain/study-mode.js.map +1 -0
- package/dist/domain/study-registry.d.ts +57 -10
- package/dist/domain/study-registry.d.ts.map +1 -1
- package/dist/domain/study-registry.js +106 -30
- package/dist/domain/study-registry.js.map +1 -1
- package/dist/outputs-before-decision-rule.d.ts +17 -0
- package/dist/outputs-before-decision-rule.d.ts.map +1 -0
- package/dist/outputs-before-decision-rule.js +90 -0
- package/dist/outputs-before-decision-rule.js.map +1 -0
- package/dist/ports/git-history.d.ts +44 -0
- package/dist/ports/git-history.d.ts.map +1 -0
- package/dist/ports/git-history.js +2 -0
- package/dist/ports/git-history.js.map +1 -0
- package/dist/ports/list-entries.d.ts +17 -0
- package/dist/ports/list-entries.d.ts.map +1 -0
- package/dist/ports/list-entries.js +2 -0
- package/dist/ports/list-entries.js.map +1 -0
- package/dist/ports/study-registry-codec.d.ts +6 -3
- package/dist/ports/study-registry-codec.d.ts.map +1 -1
- package/dist/studies.d.ts +4 -0
- package/dist/studies.d.ts.map +1 -1
- package/dist/studies.js +50 -22
- package/dist/studies.js.map +1 -1
- package/dist/study-gate.d.ts +14 -0
- package/dist/study-gate.d.ts.map +1 -0
- package/dist/study-gate.js +95 -0
- package/dist/study-gate.js.map +1 -0
- package/dist/study-index-input.d.ts +5 -0
- package/dist/study-index-input.d.ts.map +1 -0
- package/dist/study-index-input.js +13 -0
- package/dist/study-index-input.js.map +1 -0
- package/dist/study-modes.d.ts +45 -0
- package/dist/study-modes.d.ts.map +1 -0
- package/dist/study-modes.js +70 -0
- package/dist/study-modes.js.map +1 -0
- package/dist/study-registry-rule.d.ts +17 -1
- package/dist/study-registry-rule.d.ts.map +1 -1
- package/dist/study-registry-rule.js +34 -13
- package/dist/study-registry-rule.js.map +1 -1
- package/dist/study-run.d.ts +19 -0
- package/dist/study-run.d.ts.map +1 -0
- package/dist/study-run.js +9 -0
- package/dist/study-run.js.map +1 -0
- package/docs/design/study-modes.md +247 -0
- package/docs/design/study-registry.md +6 -0
- package/docs/e2e.md +8 -4
- package/docs/layout.md +22 -19
- package/docs/rules/repro/outputs-before-decision.md +119 -0
- package/docs/rules/repro/study-registered.md +47 -14
- package/docs/rules.md +54 -53
- package/docs/testing.md +1 -0
- package/package.json +2 -1
- package/scripts/check.ts +6 -0
- package/skills/camera-ready/SKILL.md +6 -1
- package/skills/camera-ready/SKILL.md.spec.ts +5 -0
- package/skills/draft-paper/SKILL.md +11 -3
- package/skills/draft-paper/SKILL.md.spec.ts +10 -2
- package/skills/harden-paper/SKILL.md +12 -2
- package/skills/harden-paper/SKILL.md.spec.ts +11 -1
- package/skills/osf-artifact-upload/SKILL.md +7 -1
- package/skills/osf-artifact-upload/SKILL.md.spec.ts +6 -0
- package/skills/pc-panel-review/SKILL.md +10 -3
- package/skills/pc-panel-review/SKILL.md.spec.ts +9 -2
- package/skills/tighten-paper/SKILL.md +5 -1
- package/skills/tighten-paper/SKILL.md.spec.ts +4 -0
- package/src/adapters/git/history.test.ts +121 -0
- package/src/adapters/git/index.test.ts +268 -0
- package/src/adapters/git/index.ts +227 -0
- package/src/adapters/memory/index.test.ts +15 -1
- package/src/adapters/memory/index.ts +13 -0
- package/src/adapters/node/index.ts +1 -0
- package/src/adapters/node/list-entries.io.ts +26 -0
- package/src/adapters/node/list-entries.test.ts +43 -0
- package/src/adapters/study-registry/index.test.ts +12 -9
- package/src/adapters/study-registry/index.ts +130 -24
- package/src/adapters/study-registry/mode.test.ts +162 -0
- package/src/cli.ts +47 -3
- package/src/domain/decide-first.test.ts +258 -0
- package/src/domain/decide-first.ts +243 -0
- package/src/domain/index-columns.test.ts +216 -0
- package/src/domain/index-columns.ts +105 -0
- package/src/domain/study-measurements.test.ts +9 -5
- package/src/domain/study-mode.test.ts +55 -0
- package/src/domain/study-mode.ts +78 -0
- package/src/domain/study-registry.test.ts +38 -31
- package/src/domain/study-registry.ts +170 -31
- package/src/new-paper.test.ts +5 -1
- package/src/outputs-before-decision-rule.test.ts +206 -0
- package/src/outputs-before-decision-rule.ts +124 -0
- package/src/ports/git-history.ts +44 -0
- package/src/ports/list-entries.ts +18 -0
- package/src/ports/study-registry-codec.ts +10 -3
- package/src/rule-cases.test.ts +78 -3
- package/src/studies-index-modes.test.ts +129 -0
- package/src/studies.test.ts +35 -11
- package/src/studies.ts +88 -27
- package/src/study-gate.test.ts +316 -0
- package/src/study-gate.ts +161 -0
- package/src/study-index-input.ts +23 -0
- package/src/study-modes.ts +120 -0
- package/src/study-registry-rule.test.ts +198 -11
- package/src/study-registry-rule.ts +51 -14
- package/src/study-run.ts +21 -0
|
@@ -29,8 +29,9 @@ import {
|
|
|
29
29
|
LEGACY_PLAN_FILE,
|
|
30
30
|
PLAN_NAME_PROBLEMS,
|
|
31
31
|
STUDIES_FILE,
|
|
32
|
+
isFolderName,
|
|
32
33
|
judgeStudies,
|
|
33
|
-
|
|
34
|
+
planRefs,
|
|
34
35
|
studyMessage,
|
|
35
36
|
type PlanState,
|
|
36
37
|
type RegistryState,
|
|
@@ -42,6 +43,7 @@ import type {
|
|
|
42
43
|
FolderRuleModule,
|
|
43
44
|
} from "./folder-venue-rule.ts";
|
|
44
45
|
import type { Files } from "./ports/files.ts";
|
|
46
|
+
import type { ListEntries } from "./ports/list-entries.ts";
|
|
45
47
|
import type { StudyRegistryCodec } from "./ports/study-registry-codec.ts";
|
|
46
48
|
import { reproEntriesOf } from "./repro-layout-rule.ts";
|
|
47
49
|
import { rulePageUrl } from "./venue-rules.ts";
|
|
@@ -51,10 +53,36 @@ const STATUS_FILE = "PIPELINE-STATUS.md";
|
|
|
51
53
|
/** What the rule reads with: the disk, its listings, and the registry's parser. */
|
|
52
54
|
export interface StudyRegistryDeps extends FolderLayoutDeps {
|
|
53
55
|
readonly codec: StudyRegistryCodec;
|
|
56
|
+
/** `repro/`'s entries, links not followed: a study folder that is a link is never read through. */
|
|
57
|
+
readonly entries: ListEntries;
|
|
54
58
|
}
|
|
55
59
|
|
|
60
|
+
/** The names at the top of `<dir>/repro/` that are symbolic links. */
|
|
61
|
+
const linksIn = (
|
|
62
|
+
dir: string,
|
|
63
|
+
deps: Pick<StudyRegistryDeps, "entries">,
|
|
64
|
+
): ReadonlySet<string> =>
|
|
65
|
+
new Set(
|
|
66
|
+
deps
|
|
67
|
+
.entries(callerPath(join(dir, REPRO_DIR)))
|
|
68
|
+
.filter((e) => e.kind === "symlink")
|
|
69
|
+
.map((e) => e.name),
|
|
70
|
+
);
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* The test every reader of a study's folder passes a row through: its folder is one folder name
|
|
74
|
+
* inside `repro/` (`isFolderName`) and not a symbolic link, which would lead the reads anywhere.
|
|
75
|
+
*/
|
|
76
|
+
export const readableFolders = (
|
|
77
|
+
dir: string,
|
|
78
|
+
deps: Pick<StudyRegistryDeps, "entries">,
|
|
79
|
+
): ((folder: string) => boolean) => {
|
|
80
|
+
const links = linksIn(dir, deps);
|
|
81
|
+
return (folder) => isFolderName(folder) && !links.has(folder);
|
|
82
|
+
};
|
|
83
|
+
|
|
56
84
|
/** The text of the file at `p`; null when there is none, or a directory sits there. */
|
|
57
|
-
const textAt = (files: Files, p: string): string | null => {
|
|
85
|
+
export const textAt = (files: Files, p: string): string | null => {
|
|
58
86
|
const b = files.isFile(callerPath(p)) ? files.readBytes(callerPath(p)) : null;
|
|
59
87
|
return b === null ? null : new TextDecoder().decode(b);
|
|
60
88
|
};
|
|
@@ -88,9 +116,12 @@ const existingResults = (
|
|
|
88
116
|
dir: string,
|
|
89
117
|
r: RegistryState,
|
|
90
118
|
files: Files,
|
|
119
|
+
readable: (folder: string) => boolean,
|
|
91
120
|
): ReadonlySet<string> =>
|
|
92
121
|
new Set(
|
|
93
122
|
(r.kind === "read" ? r.registry.studies : [])
|
|
123
|
+
// A row whose folder is not one inside `repro/`, or is a link, is never read through.
|
|
124
|
+
.filter((s) => readable(s.folder))
|
|
94
125
|
.flatMap((s) =>
|
|
95
126
|
s.result_file === undefined ? [] : [`${s.folder}/${s.result_file}`],
|
|
96
127
|
)
|
|
@@ -106,23 +137,28 @@ const existingResults = (
|
|
|
106
137
|
* The plan each row of `r` names, read and parsed, by `<folder>/<plan>`; a plan not there is left out.
|
|
107
138
|
* A plan still named `prereg.json` is parsed by the loose schema of its old name.
|
|
108
139
|
*/
|
|
109
|
-
const plansOf = (
|
|
140
|
+
export const plansOf = (
|
|
110
141
|
dir: string,
|
|
111
142
|
r: RegistryState,
|
|
112
143
|
deps: Pick<StudyRegistryDeps, "files" | "codec">,
|
|
144
|
+
readable: (folder: string) => boolean,
|
|
113
145
|
): ReadonlyMap<string, PlanState> =>
|
|
114
146
|
new Map(
|
|
115
|
-
(r.kind === "read" ?
|
|
116
|
-
// A NUL is no path the disk can hold, and probing one throws: such a plan reads as missing.
|
|
117
|
-
|
|
118
|
-
.
|
|
147
|
+
(r.kind === "read" ? planRefs(r.registry) : [])
|
|
148
|
+
// A NUL is no path the disk can hold, and probing one throws: such a plan reads as missing. A
|
|
149
|
+
// folder that is a link is never read through.
|
|
150
|
+
.filter(({ key, folder }) => !key.includes("\0") && readable(folder))
|
|
151
|
+
.flatMap(({ key, kind }): readonly (readonly [string, PlanState])[] => {
|
|
119
152
|
const text = textAt(deps.files, join(dir, REPRO_DIR, key));
|
|
120
153
|
if (text === null) return [];
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
154
|
+
return [
|
|
155
|
+
[
|
|
156
|
+
key,
|
|
157
|
+
posix.basename(key) === LEGACY_PLAN_FILE
|
|
158
|
+
? deps.codec.parseLegacyPlan(text)
|
|
159
|
+
: deps.codec.parsePlan(text, kind),
|
|
160
|
+
],
|
|
161
|
+
];
|
|
126
162
|
}),
|
|
127
163
|
);
|
|
128
164
|
|
|
@@ -131,13 +167,14 @@ export function studyFindings(
|
|
|
131
167
|
dir: string,
|
|
132
168
|
deps: StudyRegistryDeps,
|
|
133
169
|
): readonly StudyFinding[] {
|
|
170
|
+
const readable = readableFolders(dir, deps);
|
|
134
171
|
const registry = registryOf(dir, deps);
|
|
135
172
|
return judgeStudies({
|
|
136
173
|
folders: studyFolders(dir, deps),
|
|
137
174
|
registry,
|
|
138
175
|
readme: textAt(deps.files, join(dir, REPRO_DIR, README)),
|
|
139
|
-
existingResults: existingResults(dir, registry, deps.files),
|
|
140
|
-
plans: plansOf(dir, registry, deps),
|
|
176
|
+
existingResults: existingResults(dir, registry, deps.files, readable),
|
|
177
|
+
plans: plansOf(dir, registry, deps, readable),
|
|
141
178
|
});
|
|
142
179
|
}
|
|
143
180
|
|
package/src/study-run.ts
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
/** What a `paperlint studies` command on one study comes to: the lines it prints, or its refusal. */
|
|
2
|
+
|
|
3
|
+
/** A refusal: the exit code, and the line that explains it. */
|
|
4
|
+
export interface StudyRefusal {
|
|
5
|
+
readonly code: 1 | 2;
|
|
6
|
+
readonly line: string;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/** What a run came to: the lines it printed, or the refusal. */
|
|
10
|
+
export type StudyRun =
|
|
11
|
+
| { readonly ok: true; readonly lines: readonly string[] }
|
|
12
|
+
| { readonly ok: false; readonly refusal: StudyRefusal };
|
|
13
|
+
|
|
14
|
+
/** A refusal for the paper's state: exit 1. */
|
|
15
|
+
export const refusal = (line: string): StudyRefusal => ({ code: 1, line });
|
|
16
|
+
|
|
17
|
+
/** The run that is `r`. */
|
|
18
|
+
export const refused = (r: StudyRefusal): StudyRun => ({
|
|
19
|
+
ok: false,
|
|
20
|
+
refusal: r,
|
|
21
|
+
});
|