plumbbob 0.8.14 → 0.8.18
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/.claude-plugin/plugin.json +1 -1
- package/README.md +6 -0
- package/dist/lib/agents.js +1 -1
- package/dist/lib/check.js +9 -6
- package/dist/verbs/finish.js +4 -2
- package/node_modules/checkride/CHANGELOG.md +234 -0
- package/node_modules/checkride/README.md +134 -31
- package/node_modules/checkride/dist/adapters.d.ts +50 -1
- package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
- package/node_modules/checkride/dist/adapters.js +123 -7
- package/node_modules/checkride/dist/adapters.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/hook.d.ts.map +1 -1
- package/node_modules/checkride/dist/agent-setup/hook.js +15 -1
- package/node_modules/checkride/dist/agent-setup/hook.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/index.d.ts +0 -1
- package/node_modules/checkride/dist/agent-setup/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/agent-setup/index.js.map +1 -1
- package/node_modules/checkride/dist/baseline/fallow.d.ts +64 -0
- package/node_modules/checkride/dist/baseline/fallow.d.ts.map +1 -0
- package/node_modules/checkride/dist/baseline/fallow.js +256 -0
- package/node_modules/checkride/dist/baseline/fallow.js.map +1 -0
- package/node_modules/checkride/dist/baseline/fingerprint.d.ts +4 -6
- package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/fingerprint.js +9 -4
- package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -1
- package/node_modules/checkride/dist/baseline/index.d.ts +4 -5
- package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/index.js +2 -2
- package/node_modules/checkride/dist/baseline/index.js.map +1 -1
- package/node_modules/checkride/dist/{baseline/command.d.ts → baseline-command.d.ts} +11 -9
- package/node_modules/checkride/dist/baseline-command.d.ts.map +1 -0
- package/node_modules/checkride/dist/{baseline/command.js → baseline-command.js} +9 -7
- package/node_modules/checkride/dist/baseline-command.js.map +1 -0
- package/node_modules/checkride/dist/cli.d.ts.map +1 -1
- package/node_modules/checkride/dist/cli.js +95 -8
- package/node_modules/checkride/dist/cli.js.map +1 -1
- package/node_modules/checkride/dist/config.d.ts +37 -12
- package/node_modules/checkride/dist/config.d.ts.map +1 -1
- package/node_modules/checkride/dist/config.js +268 -60
- package/node_modules/checkride/dist/config.js.map +1 -1
- package/node_modules/checkride/dist/digest/digest.d.ts +0 -6
- package/node_modules/checkride/dist/digest/digest.d.ts.map +1 -1
- package/node_modules/checkride/dist/digest/digest.js +3 -3
- package/node_modules/checkride/dist/digest/digest.js.map +1 -1
- package/node_modules/checkride/dist/digest/index.d.ts +1 -2
- package/node_modules/checkride/dist/digest/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/digest/index.js +1 -1
- package/node_modules/checkride/dist/digest/index.js.map +1 -1
- package/node_modules/checkride/dist/doctor.d.ts +14 -1
- package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
- package/node_modules/checkride/dist/doctor.js +124 -55
- package/node_modules/checkride/dist/doctor.js.map +1 -1
- package/node_modules/checkride/dist/init.d.ts +6 -0
- package/node_modules/checkride/dist/init.d.ts.map +1 -1
- package/node_modules/checkride/dist/init.js +347 -121
- package/node_modules/checkride/dist/init.js.map +1 -1
- package/node_modules/checkride/dist/links.d.ts.map +1 -1
- package/node_modules/checkride/dist/links.js +8 -9
- package/node_modules/checkride/dist/links.js.map +1 -1
- package/node_modules/checkride/dist/orchestrator.d.ts +56 -1
- package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
- package/node_modules/checkride/dist/orchestrator.js +506 -138
- package/node_modules/checkride/dist/orchestrator.js.map +1 -1
- package/node_modules/checkride/dist/pack.d.ts +76 -0
- package/node_modules/checkride/dist/pack.d.ts.map +1 -0
- package/node_modules/checkride/dist/pack.js +217 -0
- package/node_modules/checkride/dist/pack.js.map +1 -0
- package/node_modules/checkride/dist/pm/translate.d.ts +18 -10
- package/node_modules/checkride/dist/pm/translate.d.ts.map +1 -1
- package/node_modules/checkride/dist/pm/translate.js +27 -13
- package/node_modules/checkride/dist/pm/translate.js.map +1 -1
- package/node_modules/checkride/dist/smoke.d.ts +86 -0
- package/node_modules/checkride/dist/smoke.d.ts.map +1 -0
- package/node_modules/checkride/dist/smoke.js +346 -0
- package/node_modules/checkride/dist/smoke.js.map +1 -0
- package/node_modules/checkride/dist/snippets.d.ts +215 -0
- package/node_modules/checkride/dist/snippets.d.ts.map +1 -0
- package/node_modules/checkride/dist/snippets.js +360 -0
- package/node_modules/checkride/dist/snippets.js.map +1 -0
- package/node_modules/checkride/package.json +4 -2
- package/node_modules/checkride/schema/checkride.config.schema.json +11 -6
- package/package.json +4 -3
- package/skills/pb-finish/SKILL.md +15 -2
- package/node_modules/checkride/dist/baseline/command.d.ts.map +0 -1
- package/node_modules/checkride/dist/baseline/command.js.map +0 -1
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Built-in `snippets` check.
|
|
3
|
+
*
|
|
4
|
+
* A doc snippet typecheck ported to match fascicle's `check-doc-snippets.mjs`
|
|
5
|
+
* byte-for-byte so the origin repo can adopt the slot verbatim (D11). It pulls
|
|
6
|
+
* fenced ```ts / ```typescript blocks out of `README.md` and the non-recursive
|
|
7
|
+
* `docs/*.md`, and typechecks only the ones explicitly opted in with an HTML
|
|
8
|
+
* comment on the line immediately above the fence:
|
|
9
|
+
*
|
|
10
|
+
* <!-- snippet: check -->
|
|
11
|
+
*
|
|
12
|
+
* Opt-in (rather than checking every fence) keeps the check honest: many doc
|
|
13
|
+
* fences are deliberately partial fragments that assert nothing about the API.
|
|
14
|
+
* A tagged snippet that fails to compile is documentation that lies — this
|
|
15
|
+
* turns that into a build failure. Opting the slot in but tagging *nothing* is
|
|
16
|
+
* a misconfiguration, not a vacuous pass, so zero tagged snippets is a hard
|
|
17
|
+
* error ({@link vacuousOptInError}; fascicle exits 2).
|
|
18
|
+
*
|
|
19
|
+
* The pure machinery — no filesystem, no spawning:
|
|
20
|
+
*
|
|
21
|
+
* - {@link extractSnippets} parses one doc's markdown into its ts/typescript
|
|
22
|
+
* fenced blocks, recording each block's start line and whether it is tagged;
|
|
23
|
+
* - {@link slugForDoc} / {@link snippetFileName} name the emitted scratch file
|
|
24
|
+
* for a block (`<slug>__<n>.ts`);
|
|
25
|
+
* - {@link planSnippets} folds a set of docs into the emission plan (the
|
|
26
|
+
* checked blocks to write, each mapped back to `<doc>:<line>`) plus the
|
|
27
|
+
* checked/skipped counts;
|
|
28
|
+
* - {@link generateSnippetTsconfig} builds the generated tsconfig (extends the
|
|
29
|
+
* repo's own, relaxes the three emit/style flags plus the composite-build
|
|
30
|
+
* fields a `tsc --build` project carries, embeds the caller's mode-specific
|
|
31
|
+
* `paths`).
|
|
32
|
+
*
|
|
33
|
+
* Execution (D12/Q1), consuming the primitives above:
|
|
34
|
+
*
|
|
35
|
+
* - {@link deriveSrcPaths} resolves **src mode**'s `paths` mapping: the repo's
|
|
36
|
+
* own tsconfig `paths` when present, else the `src/index.ts` convention,
|
|
37
|
+
* else null (the caller fails, recommending `snippets-dist`);
|
|
38
|
+
* - {@link checkSnippets} discovers the doc set, plans it, derives the mode's
|
|
39
|
+
* `paths`, emits the scratch files + generated tsconfig under
|
|
40
|
+
* `.check/doc-snippets/`, and typechecks them via a spawned
|
|
41
|
+
* `<pm> exec tsc --noEmit -p`, returning a {@link CheckOutcome} whose
|
|
42
|
+
* failure `stderr` carries tsc's raw output plus the `snippet -> source
|
|
43
|
+
* map:` legend.
|
|
44
|
+
*/
|
|
45
|
+
import { existsSync } from 'node:fs';
|
|
46
|
+
import { mkdir, readFile, readdir, rm, writeFile } from 'node:fs/promises';
|
|
47
|
+
import { join } from 'node:path';
|
|
48
|
+
import { translateExec } from './pm/index.js';
|
|
49
|
+
/**
|
|
50
|
+
* The opt-in marker: an HTML comment `<!-- snippet: check -->` that must sit on
|
|
51
|
+
* the line immediately above a fence for its snippet to be typechecked. Exact
|
|
52
|
+
* fascicle regex (D11).
|
|
53
|
+
*/
|
|
54
|
+
export const CHECK_MARKER_RE = /<!--\s*snippet:\s*check\s*-->/;
|
|
55
|
+
/** An opening fence — `ts` or `typescript` only, nothing else on the line (D11). */
|
|
56
|
+
export const FENCE_OPEN_RE = /^```(ts|typescript)\s*$/;
|
|
57
|
+
/** A closing fence: three backticks alone on the line. */
|
|
58
|
+
export const FENCE_CLOSE_RE = /^```\s*$/;
|
|
59
|
+
/**
|
|
60
|
+
* Select the doc files to check from a `docs/` directory listing (D11): always
|
|
61
|
+
* `README.md`, then every non-recursive `docs/*.md` entry, README first and the
|
|
62
|
+
* `docs/` entries in the order given. Pure — the caller does the (non-recursive)
|
|
63
|
+
* `readdir` and passes its entries; a plain entry list means a nested
|
|
64
|
+
* `docs/sub/x.md` never appears (its listing entry `sub` fails `.md`), matching
|
|
65
|
+
* fascicle's non-recursive `doc_files`.
|
|
66
|
+
*/
|
|
67
|
+
export function selectDocFiles(docsEntries) {
|
|
68
|
+
const files = ['README.md'];
|
|
69
|
+
for (const name of docsEntries) {
|
|
70
|
+
if (name.endsWith('.md'))
|
|
71
|
+
files.push(`docs/${name}`);
|
|
72
|
+
}
|
|
73
|
+
return files;
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Parse a doc's markdown into its `ts`/`typescript` fenced blocks (D11). A block
|
|
77
|
+
* is `checked` when a {@link CHECK_MARKER_RE} marker sits on the line immediately
|
|
78
|
+
* above its opening fence — a marker anywhere else does not count. Untagged
|
|
79
|
+
* blocks are still returned (the caller counts them as skipped). Semantics match
|
|
80
|
+
* fascicle's `extract_blocks` exactly.
|
|
81
|
+
*/
|
|
82
|
+
export function extractSnippets(text) {
|
|
83
|
+
const lines = text.split('\n');
|
|
84
|
+
const blocks = [];
|
|
85
|
+
let i = 0;
|
|
86
|
+
while (i < lines.length) {
|
|
87
|
+
if (FENCE_OPEN_RE.test(lines[i] ?? '')) {
|
|
88
|
+
const startLine = i + 1;
|
|
89
|
+
const checked = i > 0 && CHECK_MARKER_RE.test(lines[i - 1] ?? '');
|
|
90
|
+
const body = [];
|
|
91
|
+
i += 1;
|
|
92
|
+
while (i < lines.length && !FENCE_CLOSE_RE.test(lines[i] ?? '')) {
|
|
93
|
+
body.push(lines[i] ?? '');
|
|
94
|
+
i += 1;
|
|
95
|
+
}
|
|
96
|
+
blocks.push({ code: body.join('\n'), startLine, checked });
|
|
97
|
+
}
|
|
98
|
+
i += 1;
|
|
99
|
+
}
|
|
100
|
+
return blocks;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The scratch-file slug for a doc's repo-relative path: every non-alphanumeric
|
|
104
|
+
* run collapses to a single `_`, with leading/trailing `_` trimmed
|
|
105
|
+
* (`README.md` → `README_md`, `docs/guide.md` → `docs_guide_md`). Exact fascicle
|
|
106
|
+
* algorithm. Distinct docs in the discovered namespace (`README.md` plus the
|
|
107
|
+
* flat `docs/*.md`) map to distinct slugs, so their emitted files never collide.
|
|
108
|
+
*/
|
|
109
|
+
export function slugForDoc(relPath) {
|
|
110
|
+
return relPath.replace(/[^a-zA-Z0-9]+/g, '_').replace(/^_+|_+$/g, '');
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* The scratch-file name for a block: `<slug>__<n>.ts`, where `n` is the block's
|
|
114
|
+
* 1-based position among *all* ts/typescript fences in its doc (checked or not) —
|
|
115
|
+
* so a skipped fence still advances the number, matching fascicle.
|
|
116
|
+
*/
|
|
117
|
+
export function snippetFileName(relPath, blockIndex) {
|
|
118
|
+
return `${slugForDoc(relPath)}__${blockIndex}.ts`;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Fold a set of docs into the emission plan: every checked block becomes a
|
|
122
|
+
* {@link SnippetPlanEntry} (named, mapped back to `<doc>:<line>`), untagged
|
|
123
|
+
* blocks bump `skipped`. The block index for naming counts all fences in a doc,
|
|
124
|
+
* so a checked block keeps its position even after skipped ones (fascicle
|
|
125
|
+
* parity). Pure — the caller reads the docs and writes the files.
|
|
126
|
+
*/
|
|
127
|
+
export function planSnippets(docs) {
|
|
128
|
+
const entries = [];
|
|
129
|
+
let checked = 0;
|
|
130
|
+
let skipped = 0;
|
|
131
|
+
for (const doc of docs) {
|
|
132
|
+
extractSnippets(doc.text).forEach((block, index) => {
|
|
133
|
+
if (!block.checked) {
|
|
134
|
+
skipped += 1;
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
entries.push({
|
|
138
|
+
name: snippetFileName(doc.relPath, index + 1),
|
|
139
|
+
file: doc.relPath,
|
|
140
|
+
line: block.startLine,
|
|
141
|
+
code: block.code,
|
|
142
|
+
});
|
|
143
|
+
checked += 1;
|
|
144
|
+
});
|
|
145
|
+
}
|
|
146
|
+
return { entries, checked, skipped };
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The vacuous-opt-in guard (D11): a plan with no checked snippets is a hard
|
|
150
|
+
* error, not a vacuous green — opting the slot in obligates at least one tagged
|
|
151
|
+
* fence. Returns the error message for step 8 to surface (fascicle exits 2), or
|
|
152
|
+
* null when the plan has something to check.
|
|
153
|
+
*/
|
|
154
|
+
export function vacuousOptInError(plan) {
|
|
155
|
+
if (plan.checked > 0)
|
|
156
|
+
return null;
|
|
157
|
+
return 'no tagged snippets found — refusing to pass vacuously (add a `<!-- snippet: check -->` marker above a ts/typescript fence)';
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Build the generated tsconfig (D11): extend the repo's own config so the
|
|
161
|
+
* snippets inherit its strictness, then relax exactly the three flags that
|
|
162
|
+
* false-positive on illustrative snippets (`verbatimModuleSyntax`,
|
|
163
|
+
* `isolatedModules`, `noPropertyAccessFromIndexSignature`) while keeping the
|
|
164
|
+
* type-correctness flags that catch real API drift. `include` clears the parent's
|
|
165
|
+
* `.check` exclusion so the emitted `./*.ts` are seen; `paths` is the caller's
|
|
166
|
+
* mode-specific module resolution (src vs dist — Q1).
|
|
167
|
+
*
|
|
168
|
+
* A `tsc --build` project (composite, `rootDir`/`outDir` pinned to `src`/`dist`
|
|
169
|
+
* for project-reference emit) fails TS6059 on any *source* file outside its
|
|
170
|
+
* `rootDir` — and the generated snippets live under `.check/doc-snippets/`,
|
|
171
|
+
* while src mode's `paths` mapping pulls in a real source file elsewhere in the
|
|
172
|
+
* repo (dist mode's self-referenced `.d.ts` is exempt: a declaration file isn't
|
|
173
|
+
* subject to the same check). `rootDir: '../..'` re-scopes to `cwd` — the
|
|
174
|
+
* common ancestor of both — so either file satisfies it; `composite`/
|
|
175
|
+
* `declaration`/`declarationMap`/`incremental` are turned off since this is a
|
|
176
|
+
* one-shot typecheck, never a build. All four are no-ops on a plain
|
|
177
|
+
* (non-composite) project's tsconfig, so the override is harmless there too.
|
|
178
|
+
*/
|
|
179
|
+
export function generateSnippetTsconfig(opts) {
|
|
180
|
+
return {
|
|
181
|
+
extends: opts.extendsPath,
|
|
182
|
+
compilerOptions: {
|
|
183
|
+
paths: opts.paths,
|
|
184
|
+
noEmit: true,
|
|
185
|
+
verbatimModuleSyntax: false,
|
|
186
|
+
isolatedModules: false,
|
|
187
|
+
noPropertyAccessFromIndexSignature: false,
|
|
188
|
+
rootDir: '../..',
|
|
189
|
+
composite: false,
|
|
190
|
+
declaration: false,
|
|
191
|
+
declarationMap: false,
|
|
192
|
+
incremental: false,
|
|
193
|
+
},
|
|
194
|
+
include: ['./*.ts'],
|
|
195
|
+
exclude: [],
|
|
196
|
+
};
|
|
197
|
+
}
|
|
198
|
+
/** Where the generated snippet files + tsconfig land, relative to `cwd`. */
|
|
199
|
+
const OUT_DIR_REL = join('.check', 'doc-snippets');
|
|
200
|
+
function isRecord(value) {
|
|
201
|
+
return typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Read the doc set (D11): `README.md` plus non-recursive `docs/*.md`, skipping
|
|
205
|
+
* any that don't exist — a repo with no `docs/` directory (or no `README.md`)
|
|
206
|
+
* still runs on what it has; an empty result is caught by
|
|
207
|
+
* {@link vacuousOptInError}.
|
|
208
|
+
*/
|
|
209
|
+
async function discoverDocs(cwd) {
|
|
210
|
+
let docsEntries = [];
|
|
211
|
+
try {
|
|
212
|
+
docsEntries = await readdir(join(cwd, 'docs'));
|
|
213
|
+
}
|
|
214
|
+
catch {
|
|
215
|
+
// No docs/ directory — README.md alone still gets checked.
|
|
216
|
+
}
|
|
217
|
+
const found = await Promise.all(selectDocFiles(docsEntries).map(async (relPath) => {
|
|
218
|
+
try {
|
|
219
|
+
return { relPath, text: await readFile(join(cwd, relPath), 'utf8') };
|
|
220
|
+
}
|
|
221
|
+
catch {
|
|
222
|
+
return null;
|
|
223
|
+
}
|
|
224
|
+
}));
|
|
225
|
+
return found.filter((d) => d !== null);
|
|
226
|
+
}
|
|
227
|
+
/** The package name from `package.json`, or null on any read/parse failure or a missing `name`. */
|
|
228
|
+
async function readManifestName(cwd) {
|
|
229
|
+
try {
|
|
230
|
+
const parsed = JSON.parse(await readFile(join(cwd, 'package.json'), 'utf8'));
|
|
231
|
+
const name = isRecord(parsed) ? parsed['name'] : undefined;
|
|
232
|
+
return typeof name === 'string' && name ? name : null;
|
|
233
|
+
}
|
|
234
|
+
catch {
|
|
235
|
+
return null;
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* The repo's own `tsconfig.json`'s **own** `compilerOptions.paths` (not resolved
|
|
240
|
+
* through its `extends` chain — a repo that hand-declares self-referencing
|
|
241
|
+
* paths, as fascicle does, puts them directly on the root file), or null when
|
|
242
|
+
* absent, unreadable, or empty.
|
|
243
|
+
*/
|
|
244
|
+
async function readOwnTsconfigPaths(cwd) {
|
|
245
|
+
try {
|
|
246
|
+
const parsed = JSON.parse(await readFile(join(cwd, 'tsconfig.json'), 'utf8'));
|
|
247
|
+
const compilerOptions = isRecord(parsed) ? parsed['compilerOptions'] : undefined;
|
|
248
|
+
const paths = isRecord(compilerOptions) ? compilerOptions['paths'] : undefined;
|
|
249
|
+
if (!isRecord(paths))
|
|
250
|
+
return null;
|
|
251
|
+
const out = {};
|
|
252
|
+
for (const [key, value] of Object.entries(paths)) {
|
|
253
|
+
if (Array.isArray(value) && value.every((v) => typeof v === 'string'))
|
|
254
|
+
out[key] = value;
|
|
255
|
+
}
|
|
256
|
+
return Object.keys(out).length > 0 ? out : null;
|
|
257
|
+
}
|
|
258
|
+
catch {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
/** Rewrite a tsconfig-root-relative target (`./src/x.ts` or `src/x.ts`) to resolve from `.check/doc-snippets/`. */
|
|
263
|
+
function remapRootRelative(target) {
|
|
264
|
+
const stripped = target.startsWith('./') ? target.slice(2) : target;
|
|
265
|
+
return `../../${stripped}`;
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Derive the `paths` mapping **src mode** needs so `import { x } from
|
|
269
|
+
* '<pkg-name>'` resolves against source (Q1): the repo's own tsconfig `paths`
|
|
270
|
+
* when present (remapped two directories deeper, to where the generated
|
|
271
|
+
* tsconfig lives), else the `src/index.ts` convention (`<pkg-name>` maps to its
|
|
272
|
+
* root `src/index.ts`) when the manifest names the package and that file
|
|
273
|
+
* exists, else null — the caller turns a null into a failing outcome that
|
|
274
|
+
* recommends `snippets-dist` (whose dist-mode compilation needs no mapping at
|
|
275
|
+
* all: package self-reference through `exports` resolves the built types).
|
|
276
|
+
*/
|
|
277
|
+
export function deriveSrcPaths(opts) {
|
|
278
|
+
if (opts.tsconfigPaths && Object.keys(opts.tsconfigPaths).length > 0) {
|
|
279
|
+
const remapped = {};
|
|
280
|
+
for (const [key, targets] of Object.entries(opts.tsconfigPaths)) {
|
|
281
|
+
remapped[key] = targets.map(remapRootRelative);
|
|
282
|
+
}
|
|
283
|
+
return remapped;
|
|
284
|
+
}
|
|
285
|
+
if (opts.manifestName !== null && opts.hasSrcIndex) {
|
|
286
|
+
return { [opts.manifestName]: ['../../src/index.ts'] };
|
|
287
|
+
}
|
|
288
|
+
return null;
|
|
289
|
+
}
|
|
290
|
+
function failOutcome(message) {
|
|
291
|
+
return {
|
|
292
|
+
ok: false,
|
|
293
|
+
exit_code: 1,
|
|
294
|
+
stdout: `${JSON.stringify({ ok: false, error: message }, null, 2)}\n`,
|
|
295
|
+
stderr: `check-snippets: ${message}\n`,
|
|
296
|
+
};
|
|
297
|
+
}
|
|
298
|
+
/** Compile the generated tsconfig via `<pm> exec tsc --noEmit -p <path>`, translated per PM. */
|
|
299
|
+
function runTsc(cwd, tsconfigRelPath, pm, spawn, timeoutSec) {
|
|
300
|
+
const { command, args } = translateExec('pnpm', ['exec', 'tsc', '--noEmit', '-p', tsconfigRelPath], pm);
|
|
301
|
+
return spawn(command, args, cwd, timeoutSec);
|
|
302
|
+
}
|
|
303
|
+
/**
|
|
304
|
+
* Run the `snippets` check against `cwd` in `mode` (D12: the `snippets` src
|
|
305
|
+
* adapter passes `'src'`, `snippets-dist` passes `'dist'`). Discovers the doc
|
|
306
|
+
* set, plans the checked snippets ({@link vacuousOptInError} applies first —
|
|
307
|
+
* zero tagged snippets is a hard error before anything is written), derives
|
|
308
|
+
* the mode's `paths` mapping, emits the scratch files plus a generated
|
|
309
|
+
* tsconfig under `.check/doc-snippets/`, and typechecks them through the
|
|
310
|
+
* injected `spawn`. A compile failure's `stderr` carries tsc's raw output plus
|
|
311
|
+
* the `snippet -> source map:` legend mapping each generated file back to
|
|
312
|
+
* `<doc>:<line>` (D11).
|
|
313
|
+
*/
|
|
314
|
+
export async function checkSnippets(opts) {
|
|
315
|
+
const { cwd, mode, pm, spawn, timeoutSec } = opts;
|
|
316
|
+
const plan = planSnippets(await discoverDocs(cwd));
|
|
317
|
+
const vacuous = vacuousOptInError(plan);
|
|
318
|
+
if (vacuous)
|
|
319
|
+
return failOutcome(vacuous);
|
|
320
|
+
let paths = {};
|
|
321
|
+
if (mode === 'src') {
|
|
322
|
+
const [manifestName, tsconfigPaths] = await Promise.all([readManifestName(cwd), readOwnTsconfigPaths(cwd)]);
|
|
323
|
+
const derived = deriveSrcPaths({
|
|
324
|
+
manifestName,
|
|
325
|
+
tsconfigPaths,
|
|
326
|
+
hasSrcIndex: existsSync(join(cwd, 'src', 'index.ts')),
|
|
327
|
+
});
|
|
328
|
+
if (derived === null) {
|
|
329
|
+
return failOutcome("cannot map snippet imports to source: tsconfig.json has no self-referencing 'paths' and there is no " +
|
|
330
|
+
"src/index.ts — add a 'paths' entry for the package name, or opt into the 'snippets-dist' adapter " +
|
|
331
|
+
'instead (dist mode needs no mapping)');
|
|
332
|
+
}
|
|
333
|
+
paths = derived;
|
|
334
|
+
}
|
|
335
|
+
const outDir = join(cwd, OUT_DIR_REL);
|
|
336
|
+
await rm(outDir, { recursive: true, force: true });
|
|
337
|
+
await mkdir(outDir, { recursive: true });
|
|
338
|
+
await Promise.all(plan.entries.map((e) => writeFile(join(outDir, e.name), `${e.code}\n`, 'utf8')));
|
|
339
|
+
const tsconfig = generateSnippetTsconfig({ extendsPath: '../../tsconfig.json', paths });
|
|
340
|
+
await writeFile(join(outDir, 'tsconfig.json'), `${JSON.stringify(tsconfig, null, 2)}\n`, 'utf8');
|
|
341
|
+
const outcome = await runTsc(cwd, join(OUT_DIR_REL, 'tsconfig.json'), pm, spawn, timeoutSec);
|
|
342
|
+
const status = { checked: plan.checked, skipped: plan.skipped, mode };
|
|
343
|
+
if (outcome.ok) {
|
|
344
|
+
return {
|
|
345
|
+
ok: true,
|
|
346
|
+
exit_code: 0,
|
|
347
|
+
stdout: `${JSON.stringify({ ok: true, ...status }, null, 2)}\n`,
|
|
348
|
+
stderr: `check-snippets: ${plan.checked} snippet(s) compile against ${mode} (${plan.skipped} skipped)\n`,
|
|
349
|
+
};
|
|
350
|
+
}
|
|
351
|
+
const legend = plan.entries.map((e) => ` ${e.name} <- ${e.file}:${e.line}`).join('\n');
|
|
352
|
+
const tscOutput = `${outcome.stdout}${outcome.stderr}`.trim();
|
|
353
|
+
return {
|
|
354
|
+
ok: false,
|
|
355
|
+
exit_code: 1,
|
|
356
|
+
stdout: `${JSON.stringify({ ok: false, ...status }, null, 2)}\n`,
|
|
357
|
+
stderr: `check-snippets: snippet(s) failed to compile:\n\n${tscOutput}\n\nsnippet -> source map:\n${legend}\n`,
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
//# sourceMappingURL=snippets.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"snippets.js","sourceRoot":"","sources":["../src/snippets.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "checkride",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"description": "An agent harness for TypeScript repositories: one command that is the definition of done, plus mechanically enforced module boundaries.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Rob McLarty",
|
|
@@ -62,6 +62,7 @@
|
|
|
62
62
|
"prepublishOnly": "tsc --build && vitest run"
|
|
63
63
|
},
|
|
64
64
|
"devDependencies": {
|
|
65
|
+
"@arethetypeswrong/cli": "0.18.4",
|
|
65
66
|
"@ast-grep/cli": "0.42.1",
|
|
66
67
|
"@stryker-mutator/core": "9.6.1",
|
|
67
68
|
"@stryker-mutator/vitest-runner": "9.6.1",
|
|
@@ -69,10 +70,11 @@
|
|
|
69
70
|
"@vitest/coverage-v8": "4.1.5",
|
|
70
71
|
"ajv": "8.20.0",
|
|
71
72
|
"cspell": "10.0.0",
|
|
72
|
-
"fallow": "
|
|
73
|
+
"fallow": "3.5.0",
|
|
73
74
|
"markdownlint-cli2": "0.22.1",
|
|
74
75
|
"oxlint": "1.61.0",
|
|
75
76
|
"oxlint-tsgolint": "0.21.1",
|
|
77
|
+
"publint": "0.3.21",
|
|
76
78
|
"typescript": "6.0.3",
|
|
77
79
|
"vitest": "4.1.5"
|
|
78
80
|
}
|
|
@@ -24,7 +24,7 @@
|
|
|
24
24
|
},
|
|
25
25
|
"checks": {
|
|
26
26
|
"type": "object",
|
|
27
|
-
"description": "Per-slot configuration. A key that matches a catalogue slot (types, format, lint, struct, dead, test, docs, links, spell, mutation, security, publint, attw) configures that slot; any other key is a custom check that runs alongside the catalogue. Naming an opt-in slot (format, mutation, security, publint, attw) here also opts it into the default run.",
|
|
27
|
+
"description": "Per-slot configuration. A key that matches a catalogue slot (types, format, lint, struct, dead, dupes, health, test, docs, links, spell, mutation, security, publint, attw) configures that slot; any other key is a custom check that runs alongside the catalogue. Naming an opt-in slot (format, dupes, health, mutation, security, publint, attw) here also opts it into the default run.",
|
|
28
28
|
"additionalProperties": {
|
|
29
29
|
"$ref": "#/definitions/slotConfig"
|
|
30
30
|
}
|
|
@@ -62,9 +62,17 @@
|
|
|
62
62
|
"outputFile": { "type": ["string", "null"] },
|
|
63
63
|
"changedArgs": { "type": "array", "items": { "type": "string" } },
|
|
64
64
|
"fixArgs": { "type": "array", "items": { "type": "string" } },
|
|
65
|
-
"timeout": { "type": "number", "minimum": 0 }
|
|
65
|
+
"timeout": { "type": "number", "minimum": 0 },
|
|
66
|
+
"order": { "$ref": "#/definitions/order" }
|
|
66
67
|
}
|
|
67
68
|
},
|
|
69
|
+
"order": {
|
|
70
|
+
"description": "Scheduling order. A number places the check on the ascending wave line (equal numbers run together as one wave; decimals sequence steps within a wave); the keywords place it relative to that line — first/last before/after everything, single exclusively on its own, middle/any unordered in the main group.",
|
|
71
|
+
"oneOf": [
|
|
72
|
+
{ "enum": ["first", "last", "middle", "single", "any"] },
|
|
73
|
+
{ "type": "number" }
|
|
74
|
+
]
|
|
75
|
+
},
|
|
68
76
|
"customCheck": {
|
|
69
77
|
"type": "object",
|
|
70
78
|
"description": "A bare command that needs no adapter.",
|
|
@@ -87,10 +95,7 @@
|
|
|
87
95
|
"items": { "type": "string" },
|
|
88
96
|
"description": "Marker files that gate a non-catalogue custom check: it runs only when at least one listed file exists, and is skipped otherwise. Ignored on an entry that fills a catalogue slot."
|
|
89
97
|
},
|
|
90
|
-
"order": {
|
|
91
|
-
"enum": ["first", "last"],
|
|
92
|
-
"description": "Where a non-catalogue custom check runs relative to the catalogue. Default 'last'."
|
|
93
|
-
}
|
|
98
|
+
"order": { "$ref": "#/definitions/order" }
|
|
94
99
|
}
|
|
95
100
|
}
|
|
96
101
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plumbbob",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.18",
|
|
4
4
|
"description": "Attention-first build process: 12 skills + a CLI that keep you the decider — guidance on the work, a latch on the record.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"claude-code",
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
"agent",
|
|
11
11
|
"attention-first"
|
|
12
12
|
],
|
|
13
|
-
"homepage": "https://github.
|
|
13
|
+
"homepage": "https://robmclarty.github.io/plumbbob/",
|
|
14
14
|
"bugs": "https://github.com/robmclarty/plumbbob/issues",
|
|
15
15
|
"repository": {
|
|
16
16
|
"type": "git",
|
|
@@ -46,6 +46,7 @@
|
|
|
46
46
|
},
|
|
47
47
|
"devDependencies": {
|
|
48
48
|
"@ast-grep/cli": "0.43.0",
|
|
49
|
+
"@stryker-mutator/api": "9.6.1",
|
|
49
50
|
"@stryker-mutator/core": "9.6.1",
|
|
50
51
|
"@stryker-mutator/vitest-runner": "9.6.1",
|
|
51
52
|
"@types/node": "24.13.1",
|
|
@@ -58,7 +59,7 @@
|
|
|
58
59
|
"vitest": "4.1.9"
|
|
59
60
|
},
|
|
60
61
|
"dependencies": {
|
|
61
|
-
"checkride": "0.
|
|
62
|
+
"checkride": "0.5.2"
|
|
62
63
|
},
|
|
63
64
|
"bundleDependencies": [
|
|
64
65
|
"checkride"
|
|
@@ -30,11 +30,24 @@ record.
|
|
|
30
30
|
This is the "yeah, I did that" artifact. Write it by default; the human may edit it.
|
|
31
31
|
2. **Finish.** Run `plumbbob finish`, which appends the checkpoint SHAs to the
|
|
32
32
|
report and makes the final commit — subject `chore(<scope>): finish`, its body
|
|
33
|
-
led by a `plumbbob finish` marker plus an optional proportional `--body`
|
|
34
|
-
stdin heredoc) — then
|
|
33
|
+
led by a `plumbbob finish` marker plus an optional proportional `--body` — then
|
|
35
34
|
clears the control state (the in-flight markers, then `STATE` last — one delete
|
|
36
35
|
drops both the session sentinel and the active-build cursor it carries). The
|
|
37
36
|
build folder stays in place, committed, and rides the branch into the PR.
|
|
37
|
+
|
|
38
|
+
`--body` reads the close-out message from **stdin via a single-quoted heredoc
|
|
39
|
+
redirect** — the same form the other verbs use:
|
|
40
|
+
|
|
41
|
+
```
|
|
42
|
+
plumbbob finish --body <<'BODY'
|
|
43
|
+
…proportional close-out prose…
|
|
44
|
+
BODY
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
Redirect the heredoc *into* the command (`--body <<'BODY'`). Do **not** pass it as
|
|
48
|
+
an argument value (`--body "$(cat <<'BODY'…)"`): `--body` ignores an argument and
|
|
49
|
+
reads stdin, so that form leaves stdin open with no EOF and the command hangs. Omit
|
|
50
|
+
`--body` entirely and the commit carries the `plumbbob finish` marker subject only.
|
|
38
51
|
3. **Point at the next goal** — `/pb-plan` to frame the next one.
|
|
39
52
|
|
|
40
53
|
## The hard contracts
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/baseline/command.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACpD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AACpD,OAAO,KAAK,EAAE,WAAW,EAAE,GAAG,EAAc,MAAM,oBAAoB,CAAC;AAEvE,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAG3C,MAAM,MAAM,eAAe,GAAG;IAC5B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,SAAS,IAAI,EAAE,CAAC;IACxB,QAAQ,CAAC,EAAE,SAAS,OAAO,EAAE,CAAC;IAC9B,MAAM,CAAC,EAAE,eAAe,GAAG,IAAI,CAAC;IAChC,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sEAAsE;IACtE,EAAE,CAAC,EAAE,cAAc,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,cAAc,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,QAAQ,CAAA;CAAE,CAAC;AAEnF,gFAAgF;AAChF,wBAAsB,WAAW,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAsCnF"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/baseline/command.ts"],"names":[],"mappings":"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"}
|