plumbbob 0.8.13 → 0.8.17
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/dist/lib/agents.js +1 -1
- package/dist/lib/check.js +9 -6
- package/dist/lib/intent.js +20 -0
- package/dist/lib/orient.js +4 -3
- package/dist/verbs/checkpoint.js +30 -11
- package/dist/verbs/finish.js +24 -8
- 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 +3 -2
- package/skills/pb-build/SKILL.md +7 -0
- package/skills/pb-park/SKILL.md +3 -2
- package/skills/pb-plan/SKILL.md +30 -9
- package/skills/pb-refine/SKILL.md +21 -6
- package/skills/pb-step/SKILL.md +10 -5
- package/skills/pb-verify/SKILL.md +12 -1
- package/templates/intent.md +55 -11
- package/node_modules/checkride/dist/baseline/command.d.ts.map +0 -1
- package/node_modules/checkride/dist/baseline/command.js.map +0 -1
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "plumbbob",
|
|
3
3
|
"displayName": "PlumbBob",
|
|
4
|
-
"version": "0.8.
|
|
4
|
+
"version": "0.8.17",
|
|
5
5
|
"description": "Attention-first build process — driver skills + a CLI that keep you the decider: guidance on the work, a latch on the record.",
|
|
6
6
|
"author": { "name": "Rob McLarty", "email": "hello@robmclarty.com", "url": "https://robmclarty.com" },
|
|
7
7
|
"homepage": "https://github.com/robmclarty/plumbbob#readme",
|
package/dist/lib/agents.js
CHANGED
|
@@ -327,7 +327,7 @@ function skipWarnings(heading, skipped) {
|
|
|
327
327
|
// is the author's error and is refused loud. Slot *contents* stay lenient (D61): a
|
|
328
328
|
// slot value may be one name or a list, and blanks/non-strings drop rather than
|
|
329
329
|
// refuse, because bindings feed a spawn, not a git-gating parse.
|
|
330
|
-
|
|
330
|
+
function parseHarness(raw) {
|
|
331
331
|
if (!isObject(raw)) {
|
|
332
332
|
return { ok: false, error: 'harness.json must be a JSON object.' };
|
|
333
333
|
}
|
package/dist/lib/check.js
CHANGED
|
@@ -31,12 +31,15 @@ export async function detectGate(root) {
|
|
|
31
31
|
}
|
|
32
32
|
}
|
|
33
33
|
// Checkride's always-on repo checks: the adapters its doctor reports even for
|
|
34
|
-
// an EMPTY directory
|
|
35
|
-
// publint/attw package-shape probes
|
|
36
|
-
//
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
|
|
34
|
+
// an EMPTY directory — the built-in `links` slot, the pnpm-audit security
|
|
35
|
+
// scan, the publint/attw package-shape probes, and (checkride 0.5.0's
|
|
36
|
+
// publish bundle) the built-in pack/smoke/snippets slots, which resolve on any
|
|
37
|
+
// package with no tool config of their own. They exercise the repo's plumbing
|
|
38
|
+
// or its shipped artifact, not its code — a gate made only of these green-lights
|
|
39
|
+
// every checkpoint while the human believes their work is being checked. Coupled
|
|
40
|
+
// to checkride's built-in set by construction; the check.test.ts and
|
|
41
|
+
// doctor.test.ts probes pin the coupling.
|
|
42
|
+
const ALWAYS_ON_ADAPTERS = ['links', 'pnpm-audit', 'publint', 'attw', 'pack', 'smoke', 'snippets'];
|
|
40
43
|
// The detection rule, shared by `start`'s probe and doctor's callout: some tool
|
|
41
44
|
// slot beyond the always-on family has an adapter — i.e. checkride can see the
|
|
42
45
|
// CODE (a tsconfig, a test runner, a linter…), not just the repo.
|
package/dist/lib/intent.js
CHANGED
|
@@ -149,6 +149,26 @@ export function parseBuildTitle(content) {
|
|
|
149
149
|
}
|
|
150
150
|
return '';
|
|
151
151
|
}
|
|
152
|
+
const SCOPE_HEADER = /^\*\*Scope:\*\*\s*(.*)$/;
|
|
153
|
+
const SCOPE_PLACEHOLDER = /^<.*>$/;
|
|
154
|
+
// The build's default Conventional-Commit scope (D4): the `**Scope:**` header
|
|
155
|
+
// field authored once at plan time, its value read verbatim off the line with any
|
|
156
|
+
// trailing `<!-- ... -->` guidance note stripped. An unfilled placeholder — an
|
|
157
|
+
// empty value or an angle-bracket placeholder like `<feature>` — parses as absent
|
|
158
|
+
// (D7), so a freshly scaffolded, not-yet-edited build falls through to the next
|
|
159
|
+
// scope rung (the build slug) rather than landing commits scoped `(<feature>)`.
|
|
160
|
+
// null when the header is absent entirely — the pre-D4 shape (C2 back-compat).
|
|
161
|
+
export function parseBuildScope(content) {
|
|
162
|
+
for (const line of content.split('\n')) {
|
|
163
|
+
const m = SCOPE_HEADER.exec(line.trim());
|
|
164
|
+
if (m === null) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const value = (m[1] ?? '').split('<!--')[0]?.trim() ?? '';
|
|
168
|
+
return value === '' || SCOPE_PLACEHOLDER.test(value) ? null : value;
|
|
169
|
+
}
|
|
170
|
+
return null;
|
|
171
|
+
}
|
|
152
172
|
export function scrapeBullets(content, heading) {
|
|
153
173
|
const lines = content.split('\n');
|
|
154
174
|
const start = lines.findIndex((l) => l.trim() === heading);
|
package/dist/lib/orient.js
CHANGED
|
@@ -73,10 +73,11 @@ export function markStepDone(intent, n) {
|
|
|
73
73
|
})
|
|
74
74
|
.join('\n');
|
|
75
75
|
}
|
|
76
|
-
// Open questions still open: `- Q\d+:`
|
|
76
|
+
// Open questions still open: `- Q\d+:` openers that do not say "resolved". The
|
|
77
|
+
// opener may carry a slug-at-birth gloss — `- Q2 (some-slug): ...` (D3) — which
|
|
78
|
+
// the count reads through; sub-lines (`*plain:*`/`*lean:*`) never match.
|
|
77
79
|
export function parseOpenQuestions(intent) {
|
|
78
|
-
return sectionLines(intent, '## Open questions').filter((l) => /^- Q\d
|
|
79
|
-
.length;
|
|
80
|
+
return sectionLines(intent, '## Open questions').filter((l) => /^- Q\d+(?: \([^)]+\))?:/.test(l.trim()) && !/resolved/i.test(l)).length;
|
|
80
81
|
}
|
|
81
82
|
// Open parked items: `- [ ]` lines under `## Park list` (the `park` verb's format).
|
|
82
83
|
// A harvested item is flipped to `- [x]` by `/pb-harvest` and no longer counts; the
|
package/dist/verbs/checkpoint.js
CHANGED
|
@@ -13,7 +13,7 @@ import { activeBuild, buildFolder, buildLogPath, buildScope, bumpStepStat, check
|
|
|
13
13
|
import { runCheck } from "../lib/check.js";
|
|
14
14
|
import { checkLatch } from "../lib/latch.js";
|
|
15
15
|
import { markStepDone, parseSteps } from "../lib/orient.js";
|
|
16
|
-
import { parseStepSeam, scopeDrift } from "../lib/intent.js";
|
|
16
|
+
import { parseBuildScope, parseStepSeam, scopeDrift } from "../lib/intent.js";
|
|
17
17
|
import { conventionalSubject, subjectFromTitle, withMarker } from "../lib/commitmsg.js";
|
|
18
18
|
import { appendToSection, checkpointLogLine } from "../lib/buildlog.js";
|
|
19
19
|
import { AT_BOUNDARY, syncBuildLogState } from "../lib/buildlogsync.js";
|
|
@@ -101,11 +101,12 @@ function checkpointPlan(root, args) {
|
|
|
101
101
|
process.stdout.write(`plumbbob: plan committed — ${sha.slice(0, 9)}. Baseline → plan → steps.\n`);
|
|
102
102
|
return 0;
|
|
103
103
|
}
|
|
104
|
-
// The plan commit's CLI-owned subject (D68): `chore(<scope>): plan`, the scope
|
|
105
|
-
//
|
|
106
|
-
// `plumbbob plan` identifier rides the body marker, not the
|
|
104
|
+
// The plan commit's CLI-owned subject (D68): `chore(<scope>): plan`, the scope
|
|
105
|
+
// resolved through the build-default fallback chain (a bare `chore: plan` when
|
|
106
|
+
// none resolves). The `plumbbob plan` identifier rides the body marker, not the
|
|
107
|
+
// subject.
|
|
107
108
|
function planSubject(root) {
|
|
108
|
-
return conventionalSubject({ type: 'chore', scope:
|
|
109
|
+
return conventionalSubject({ type: 'chore', scope: buildDefaultScope(root), description: 'plan' });
|
|
109
110
|
}
|
|
110
111
|
// Step resolution (D3): explicit arg > in-flight STEP file > first undone step in
|
|
111
112
|
// intent.md. Returns null when none can be determined. A `-m` value is a message,
|
|
@@ -210,18 +211,36 @@ function statsSuffix(root, step) {
|
|
|
210
211
|
return parts.length > 0 ? parts.join(', ') : null;
|
|
211
212
|
}
|
|
212
213
|
// The CLI-owned, deterministic commit subject (D68): a Conventional `type(scope):
|
|
213
|
-
// description`. The
|
|
214
|
-
//
|
|
215
|
-
//
|
|
216
|
-
//
|
|
217
|
-
//
|
|
214
|
+
// description`. The type and wording come from the step's title — an author-written
|
|
215
|
+
// prefix (`fix(parser): …`) is honoured verbatim, a bare title defaults to `feat`.
|
|
216
|
+
// The scope falls back through the chain (D3): the title's own `(scope)` wins
|
|
217
|
+
// (handled inside `subjectFromTitle`), else `buildDefaultScope`. A titleless step
|
|
218
|
+
// falls back to `chore(<scope>): checkpoint`. The `plumbbob`/`step N` identifiers
|
|
219
|
+
// ride the body marker, not the subject; a `-m` override or `--body` prose is a
|
|
220
|
+
// separate concern.
|
|
218
221
|
function subjectForStep(root, step) {
|
|
219
|
-
const scope =
|
|
222
|
+
const scope = buildDefaultScope(root);
|
|
220
223
|
const title = titleForStep(root, step);
|
|
221
224
|
return title !== null && title.trim().length > 0
|
|
222
225
|
? subjectFromTitle(title, 'feat', scope)
|
|
223
226
|
: conventionalSubject({ type: 'chore', scope, description: 'checkpoint' });
|
|
224
227
|
}
|
|
228
|
+
// The build-default Conventional scope (D3/D4): the `**Scope:**` header field in
|
|
229
|
+
// intent.md when authored and filled, else the build slug (D68's original rung,
|
|
230
|
+
// now the penultimate one), else null — a bare subject (C2 back-compat: a build
|
|
231
|
+
// with neither field behaves exactly as before D4).
|
|
232
|
+
function buildDefaultScope(root) {
|
|
233
|
+
try {
|
|
234
|
+
const fromHeader = parseBuildScope(readFileSync(intentPath(root), 'utf8'));
|
|
235
|
+
if (fromHeader !== null) {
|
|
236
|
+
return fromHeader;
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
catch {
|
|
240
|
+
// no intent.md yet — fall through to the slug rung.
|
|
241
|
+
}
|
|
242
|
+
return buildScope(activeBuild(root));
|
|
243
|
+
}
|
|
225
244
|
function titleForStep(root, step) {
|
|
226
245
|
try {
|
|
227
246
|
return parseSteps(readFileSync(intentPath(root), 'utf8')).find((s) => s.n === step)?.title ?? null;
|
package/dist/verbs/finish.js
CHANGED
|
@@ -9,8 +9,9 @@
|
|
|
9
9
|
import { appendFileSync, existsSync, readFileSync, rmSync } from 'node:fs';
|
|
10
10
|
import { join } from 'node:path';
|
|
11
11
|
import { commit, findRepoRoot, isDirty, stageAll } from "../lib/git.js";
|
|
12
|
-
import { buildScope, checkpointsPath, clearTick, hasSession, readStats, reportPath, resolveBuild, seamPath, setGrant, sidecarDir, spikePath, stepPath, } from "../lib/sidecar.js";
|
|
12
|
+
import { buildScope, checkpointsPath, clearTick, hasSession, intentPath, readStats, reportPath, resolveBuild, seamPath, setGrant, sidecarDir, spikePath, stepPath, } from "../lib/sidecar.js";
|
|
13
13
|
import { conventionalSubject, withMarker } from "../lib/commitmsg.js";
|
|
14
|
+
import { parseBuildScope } from "../lib/intent.js";
|
|
14
15
|
export function finish(cwd, args = []) {
|
|
15
16
|
const root = findRepoRoot(cwd);
|
|
16
17
|
if (root === null || !hasSession(root)) {
|
|
@@ -34,7 +35,7 @@ export function finish(cwd, args = []) {
|
|
|
34
35
|
if (isDirty(root)) {
|
|
35
36
|
stageAll(root);
|
|
36
37
|
}
|
|
37
|
-
const sha = commit(root, subject(slug), withMarker('plumbbob finish', bodyArg(args) ?? undefined));
|
|
38
|
+
const sha = commit(root, subject(root, slug), withMarker('plumbbob finish', bodyArg(args) ?? undefined));
|
|
38
39
|
// Clear the control state: the in-flight markers first, then the session sentinel
|
|
39
40
|
// last (so "no session" flips exactly at the end). Deleting STATE also drops the
|
|
40
41
|
// cursor (D28) — cursor and session share the one file now, so a single delete does
|
|
@@ -54,12 +55,27 @@ export function finish(cwd, args = []) {
|
|
|
54
55
|
'Run `/pb-plan` (or `plumbbob start "<title>"`) to frame the next goal.\n');
|
|
55
56
|
return 0;
|
|
56
57
|
}
|
|
57
|
-
// The CLI-owned final-commit subject (D68): `chore(<scope>): finish`, the scope
|
|
58
|
-
//
|
|
59
|
-
//
|
|
60
|
-
// The `plumbbob finish` identifier rides the body marker, not the
|
|
61
|
-
|
|
62
|
-
|
|
58
|
+
// The CLI-owned final-commit subject (D68): `chore(<scope>): finish`, the scope
|
|
59
|
+
// resolved through the same build-default fallback chain as plan/step subjects
|
|
60
|
+
// (D3/D4): the `**Scope:**` header field, else the build slug, else bare (e.g.
|
|
61
|
+
// `--local`). The `plumbbob finish` identifier rides the body marker, not the
|
|
62
|
+
// subject.
|
|
63
|
+
function subject(root, slug) {
|
|
64
|
+
return conventionalSubject({ type: 'chore', scope: buildDefaultScope(root, slug), description: 'finish' });
|
|
65
|
+
}
|
|
66
|
+
// See checkpoint.ts's twin of this helper (same fallback, this verb's own `slug`
|
|
67
|
+
// resolution instead of the active-build cursor).
|
|
68
|
+
function buildDefaultScope(root, slug) {
|
|
69
|
+
try {
|
|
70
|
+
const fromHeader = parseBuildScope(readFileSync(intentPath(root, slug), 'utf8'));
|
|
71
|
+
if (fromHeader !== null) {
|
|
72
|
+
return fromHeader;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
catch {
|
|
76
|
+
// no intent.md — fall through to the slug rung.
|
|
77
|
+
}
|
|
78
|
+
return buildScope(slug);
|
|
63
79
|
}
|
|
64
80
|
// `--body` reads the final-commit body from stdin (the single-quoted heredoc of
|
|
65
81
|
// D34), so the pb-finish skill can compose a proportional close-out message. Returns
|
|
@@ -4,8 +4,235 @@ All notable changes to this project are documented here. The format is based on
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
5
|
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## [0.5.2] - 2026-07-19
|
|
8
|
+
|
|
9
|
+
### Internal
|
|
10
|
+
|
|
11
|
+
- Split the release workflow into a gated `publish.yaml` (npm publish with
|
|
12
|
+
provenance, now paused behind a required-reviewer approval on the
|
|
13
|
+
`npm-publish` GitHub Environment) and a separate `release.yaml` (GitHub
|
|
14
|
+
Release from the CHANGELOG), matching the fascicle/plumbbob pattern so the
|
|
15
|
+
npm publish credential and the release-authoring permission never share a
|
|
16
|
+
job.
|
|
17
|
+
|
|
18
|
+
## [0.5.1] - 2026-07-19
|
|
19
|
+
|
|
20
|
+
### Added
|
|
21
|
+
|
|
22
|
+
- **A GitHub Pages marketing site** under `site/` — a homepage pitching the
|
|
23
|
+
elevator case for checkride, a docs hub aggregating the existing
|
|
24
|
+
`docs/*.md` guides into a concise sidebar reference, and a full
|
|
25
|
+
CLI/config/programmatic API reference — plus the GitHub Actions workflow
|
|
26
|
+
that deploys it.
|
|
27
|
+
- `docs/why.md` — the case for adopting checkride: what it's selling, the ROI
|
|
28
|
+
against ad-hoc scripts and task runners, and straight answers to the
|
|
29
|
+
objections that come up in an adoption conversation.
|
|
30
|
+
|
|
31
|
+
## [0.5.0] - 2026-07-19
|
|
32
|
+
|
|
33
|
+
### Contract
|
|
34
|
+
|
|
35
|
+
- **The `order` field is now a first-class, promised scheduling surface.** A
|
|
36
|
+
config entry's `order` accepts a **number** — a wave, where distinct wave
|
|
37
|
+
numbers run in ascending order with a barrier between them, checks sharing a
|
|
38
|
+
number run concurrently, and decimals sequence steps within a wave (`1` before
|
|
39
|
+
`1.1`) — or one of `first`, `last`, `middle`, `single`, `any`. It is honored
|
|
40
|
+
on every object-form entry: a slot's `{ use, order }` and a custom check
|
|
41
|
+
alike. `first`/`last` keep their exact historical meaning, pinned by a
|
|
42
|
+
backward-compat contract test. See `docs/contract.md` §"Check ordering and
|
|
43
|
+
concurrency".
|
|
44
|
+
- **Two deliberate default-placement changes**, both noted in `docs/contract.md`:
|
|
45
|
+
a config-only custom check with **no** `order` now defaults to `any` (the main
|
|
46
|
+
group) instead of the old implicit `last` — set `"order": "last"` to restore
|
|
47
|
+
the previous placement — and a catalogue-filling custom entry's `order`, which
|
|
48
|
+
earlier releases documented as ignored, is now **honored**. A sequential
|
|
49
|
+
default run is unaffected in verdicts and summary order; the difference is
|
|
50
|
+
visible only under concurrency or beside a numbered wave.
|
|
51
|
+
- **New `--concurrency <n>` flag.** Sets the size of the pool that runs a wave's
|
|
52
|
+
checks concurrently (`1` = sequential; the default is a conservative cap
|
|
53
|
+
derived from the CPU count). `--bail` overrides it: the run goes fully
|
|
54
|
+
sequential and a one-line stderr note reports that `--concurrency` was ignored
|
|
55
|
+
(the combination is safe, just slower — not a usage error). Additive to the
|
|
56
|
+
flag contract and contract-tested.
|
|
57
|
+
- **`total_duration_ms` is now the run's wall-clock duration.** Under
|
|
58
|
+
concurrency the summary's total is measured wall-to-wall rather than summed
|
|
59
|
+
across checks; the two are identical for any sequential run (including
|
|
60
|
+
`--bail`). The `checks` array stays in deterministic group order — the run's
|
|
61
|
+
scheduling sequence, never completion order. `schema_version` is unchanged.
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- **A publish-ready bundle of four opt-in slots** that take the definition of
|
|
66
|
+
done past static publishing lint (`publint`, `attw`) and out to the shipped
|
|
67
|
+
artifact. Each is a built-in or runs the consumer's own `build`/`tsc`, so
|
|
68
|
+
enabling them adds **zero devDependencies**:
|
|
69
|
+
- **`build`** (wave 10) runs the consumer's `build` script, so the artifact
|
|
70
|
+
checks below inspect fresh output rather than a stale `dist/`. An opted-in
|
|
71
|
+
`build` on a repo with no build script stands down as a skip, never a red
|
|
72
|
+
check.
|
|
73
|
+
- **`pack`** (wave 20) packs the tarball with a dry-run and fails if a required
|
|
74
|
+
file (a resolved `exports`/`main`/`types`/`bin` target, or `README`) is
|
|
75
|
+
missing or a forbidden one (`src/`, tests, `.ts` sources — the
|
|
76
|
+
`dist/**/*.d.ts` declarations excepted) is shipped. npm/pnpm only; yarn/bun
|
|
77
|
+
report **unavailable** until a per-manager adapter lands, like `security`.
|
|
78
|
+
- **`smoke`** (wave 20) imports every `exports` entry of the built package
|
|
79
|
+
through its own resolution map and asserts each declared value export is live
|
|
80
|
+
at runtime — a liveness check, not a type check.
|
|
81
|
+
- **`snippets`** (wave 20 / `any`) type-checks the fenced code blocks tagged
|
|
82
|
+
`<!-- snippet: check -->` in `README.md` and `docs/*.md`. The default
|
|
83
|
+
`snippets` adapter checks against source; a second `snippets-dist` adapter
|
|
84
|
+
checks against the built `.d.ts`. A slot opted in with zero tagged fences is
|
|
85
|
+
a hard error.
|
|
86
|
+
|
|
87
|
+
All four are opt-in (`--all`, `--include`, or config), so a default run is
|
|
88
|
+
byte-for-byte unchanged. They **order themselves**: `build` at wave 10 precedes
|
|
89
|
+
`pack`/`smoke`/`snippets`/`publint`/`attw` at wave 20, so `checkride --all`
|
|
90
|
+
builds before it inspects the artifact with no ordering config. `checkride
|
|
91
|
+
init` on a library can scaffold the bundle.
|
|
92
|
+
|
|
93
|
+
### Changed
|
|
94
|
+
|
|
95
|
+
- **A dependency can now activate a slot, not just its config file.** Adapters
|
|
96
|
+
whose tool runs correctly with zero config — `oxlint` (lint), `knip` (dead),
|
|
97
|
+
`vitest` (test), `cspell` (spell), and `prettier` (the opt-in format slot) —
|
|
98
|
+
now also activate when the package appears in `dependencies`/`devDependencies`,
|
|
99
|
+
as a backup to the detect-file signal. A repo that installed one of these but
|
|
100
|
+
never wrote its config file gains that check on upgrade; `doctor` names which
|
|
101
|
+
signal matched. This widens the default run for those slots and is a
|
|
102
|
+
deliberate, noted behavior change.
|
|
103
|
+
- **Checks now run concurrently within a wave by default.** The orchestrator
|
|
104
|
+
schedules the wave sequence — `first`s, the numeric line ascending (equal
|
|
105
|
+
values through a bounded pool, a barrier between distinct values), `single`s
|
|
106
|
+
exclusively, then `last`s — instead of strictly one-at-a-time cheapest-first.
|
|
107
|
+
`--bail` keeps the sequential fail-fast path. The catalogue ships ordered so
|
|
108
|
+
existing default runs produce the same verdicts and the same summary order as
|
|
109
|
+
before, only faster; `mutation` runs as a `single` (exclusive) because Stryker
|
|
110
|
+
saturates every core and races the real test run's cache.
|
|
111
|
+
- **`mutation` now ships uncapped (`timeout: 0`) by default.** A real Stryker run
|
|
112
|
+
legitimately outlives the 600s per-check cap; because `mutation` is opt-in and
|
|
113
|
+
never part of the definition-of-done gate the cap protects, its adapter runs to
|
|
114
|
+
completion instead of tripping a timeout under `checkride --all`. Every other
|
|
115
|
+
slot keeps the safe-by-default cap; override per check or globally with
|
|
116
|
+
`timeout`.
|
|
117
|
+
|
|
118
|
+
## [0.4.3] - 2026-07-18
|
|
119
|
+
|
|
120
|
+
### Internal
|
|
121
|
+
|
|
122
|
+
- Refactored for maintainability: decomposed high-complexity functions across
|
|
123
|
+
the orchestrator, `init`, `doctor`, `config`, and the baseline code into small
|
|
124
|
+
single-purpose helpers, extracted shared option/stanza helpers, and broke
|
|
125
|
+
internal import cycles. No change to runtime behavior or the public API.
|
|
126
|
+
- Zeroed the project's grandfathered debt: cleared the `lint`, `dead`, `dupes`,
|
|
127
|
+
and `health` baselines and removed checkride's own `checkride.baseline.json`,
|
|
128
|
+
so the repo passes a full `pnpm check` with no suppressions.
|
|
129
|
+
- The repo's own default `pnpm check` now also runs the `dupes` and `health`
|
|
130
|
+
slots. Mutation stays opt-in (`pnpm mutation`): a cold full pass has no warm
|
|
131
|
+
incremental cache in CI and would time out the gate.
|
|
132
|
+
|
|
133
|
+
## [0.4.2] - 2026-07-18
|
|
134
|
+
|
|
135
|
+
### Fixed
|
|
136
|
+
|
|
137
|
+
- **The `dead` (fallow) slot now actually gates.** checkride ran fallow in JSON
|
|
138
|
+
mode, which exits `0` even with findings, so the slot reported ✔ while fallow
|
|
139
|
+
had real issues. checkride now reads fallow's JSON report and derives the
|
|
140
|
+
verdict from the issue count instead of the (unreliable) exit code — so the
|
|
141
|
+
slot fails `pnpm check` on new findings and passes only when clean or fully
|
|
142
|
+
baselined. An **unrecognized fallow report fails loudly** (explicit
|
|
143
|
+
"unsupported schema_version" / "unrecognized kind") rather than passing
|
|
144
|
+
silently.
|
|
145
|
+
- **fallow ≥ 3.5 support.** The dead-code parser reads fallow's current
|
|
146
|
+
`schema_version` 7 JSON (2.x emitted schema 4 with an incompatible layout).
|
|
147
|
+
The pinned devDependency moves from `fallow@2.48.0` to `fallow@3.5.0`.
|
|
148
|
+
|
|
149
|
+
### Added
|
|
150
|
+
|
|
151
|
+
- **`checkride baseline` now grandfathers fallow findings.** A fingerprint
|
|
152
|
+
extractor keys each fallow finding by kind + file + symbol, so fallow slots
|
|
153
|
+
participate in `checkride.baseline.json` like `lint`/`struct`/`spell` (and
|
|
154
|
+
ratchet the same way). Repos that prefer fallow's native `--save-baseline`
|
|
155
|
+
suppression can still use it — see `docs/tools.md`.
|
|
156
|
+
- **New opt-in `dupes` and `health` slots.** fallow's duplication and
|
|
157
|
+
complexity analyses are now first-class checks (`--include dupes,health` or
|
|
158
|
+
`"dupes": "fallow"` in config), each with gating and baselines. They stay
|
|
159
|
+
opt-in so adopting checkride never fails a repo on duplication/complexity it
|
|
160
|
+
never signed up for.
|
|
161
|
+
|
|
162
|
+
## [0.4.1] - 2026-07-11
|
|
163
|
+
|
|
164
|
+
### Internal
|
|
165
|
+
|
|
166
|
+
- Docs refresh: updated the reported mutation score to 69% and bumped the README `$schema` example to v0.4.0.
|
|
167
|
+
|
|
168
|
+
## [0.4.0] - 2026-07-11
|
|
169
|
+
|
|
170
|
+
### Contract
|
|
171
|
+
|
|
172
|
+
- **An unknown slot name is now a usage error.** An unrecognized slot in
|
|
173
|
+
`--only`, `--skip`, or `--include` (e.g. `checkride --only lints`) exits **2**,
|
|
174
|
+
naming the bad slot and the valid set (catalogue slots plus config
|
|
175
|
+
custom-check names). It previously matched nothing and exited **0** — a typo
|
|
176
|
+
could silently disable the gate, the worst vacuous green in a definition-of-done
|
|
177
|
+
check. See `docs/contract.md` §CLI.
|
|
178
|
+
|
|
179
|
+
### Added
|
|
180
|
+
|
|
181
|
+
- New-project `checkride init` refuses to overwrite existing files, listing
|
|
182
|
+
every collision, and writes nothing; `--force` overrides. Existing-project
|
|
183
|
+
mode (additive-only) is unchanged.
|
|
184
|
+
- Per-command `--help` (`checkride init --help`, etc.); new-project `init` ends
|
|
185
|
+
by printing the next command to run; `checkride baseline` now rejects stray
|
|
186
|
+
flags instead of ignoring them.
|
|
187
|
+
|
|
188
|
+
### Changed
|
|
189
|
+
|
|
190
|
+
- `checkride init` scaffolds an exact checkride version (no caret), and the
|
|
191
|
+
README install uses `pnpm add -D -E checkride`, matching the pre-1.0
|
|
192
|
+
exact-pin policy consumers are told to follow.
|
|
193
|
+
- Malformed consumer JSON (`.claude/settings.json`, a project `package.json`)
|
|
194
|
+
now produces an error naming the offending file instead of a bare stack trace.
|
|
195
|
+
|
|
196
|
+
### Fixed
|
|
197
|
+
|
|
198
|
+
- **Interrupts no longer orphan checks.** Ctrl-C (SIGINT) or SIGTERM on a
|
|
199
|
+
running `checkride` is forwarded to every in-flight check and group-kills its
|
|
200
|
+
whole process tree before exit, then re-raises so the shell still sees the
|
|
201
|
+
conventional signal exit (130/143). Since checks run in detached process
|
|
202
|
+
groups (for the timeout kill), a plain interrupt previously left them running.
|
|
203
|
+
- `doctor` distinguishes a version probe that **timed out** from one that
|
|
204
|
+
**could not be parsed** (30s probe), so a slow `pnpm --version` is no longer
|
|
205
|
+
misdiagnosed.
|
|
206
|
+
- `checkride init --baseline --dry-run` no longer writes a real
|
|
207
|
+
`checkride.baseline.json` — a dry run now truly writes nothing.
|
|
208
|
+
- A timed-out check's whole process group is killed (wrapper-spawned
|
|
209
|
+
grandchildren included), and output is captured with a UTF-8 decoder so a
|
|
210
|
+
multibyte character split across read chunks survives intact.
|
|
211
|
+
- `checkride fix` runs under the detected package manager (e.g. `npx` under
|
|
212
|
+
npm), matching the run path instead of assuming pnpm.
|
|
213
|
+
- A slot's stale `.check/` artifacts are cleared before it re-runs, so a leaner
|
|
214
|
+
or empty run can't leave the previous run's output behind as authoritative.
|
|
215
|
+
|
|
216
|
+
### Internal
|
|
217
|
+
|
|
218
|
+
- Docs pass: README restructure linking all six `docs/` files and splitting the
|
|
219
|
+
existing-repo vs new-project install paths, getting-started/tools sync,
|
|
220
|
+
reconciliation of the "locked by `test/contract/`" claim with real tests, and
|
|
221
|
+
a batch of drift corrections.
|
|
222
|
+
- Release automation: tag↔version guard on release, CI concurrency group,
|
|
223
|
+
security-only Dependabot; `publint` and `attw` added as dev checks and
|
|
224
|
+
dogfooded; explicit test timeouts for slow-spawn machines; npm publishing
|
|
225
|
+
switched to Trusted Publishing (OIDC).
|
|
226
|
+
|
|
7
227
|
## [0.3.0] - 2026-07-10
|
|
8
228
|
|
|
229
|
+
### Contract
|
|
230
|
+
|
|
231
|
+
- Three additions to the promised surfaces, each recorded in `docs/contract.md`
|
|
232
|
+
and locked by `test/contract/`: the `summary.json` `checks_run` field, the
|
|
233
|
+
`--strict` flag, and the `DEFAULT_TIMEOUT_SECONDS` export. (Heading added
|
|
234
|
+
retroactively — the full entries are under **Added** below.)
|
|
235
|
+
|
|
9
236
|
### Added
|
|
10
237
|
|
|
11
238
|
- **Vacuous-green signal.** `summary.json` gains a top-level `checks_run` count
|
|
@@ -238,6 +465,13 @@ The first real release. (`0.0.0` was a name-claim placeholder.)
|
|
|
238
465
|
- Flags: `--only`, `--skip`, `--bail`, `--json`, `--changed`, `--all`,
|
|
239
466
|
`--include`.
|
|
240
467
|
|
|
468
|
+
[0.5.2]: https://www.npmjs.com/package/checkride/v/0.5.2
|
|
469
|
+
[0.5.1]: https://www.npmjs.com/package/checkride/v/0.5.1
|
|
470
|
+
[0.5.0]: https://www.npmjs.com/package/checkride/v/0.5.0
|
|
471
|
+
[0.4.3]: https://www.npmjs.com/package/checkride/v/0.4.3
|
|
472
|
+
[0.4.2]: https://www.npmjs.com/package/checkride/v/0.4.2
|
|
473
|
+
[0.4.1]: https://www.npmjs.com/package/checkride/v/0.4.1
|
|
474
|
+
[0.4.0]: https://www.npmjs.com/package/checkride/v/0.4.0
|
|
241
475
|
[0.3.0]: https://www.npmjs.com/package/checkride/v/0.3.0
|
|
242
476
|
[0.2.1]: https://www.npmjs.com/package/checkride/v/0.2.1
|
|
243
477
|
[0.2.0]: https://www.npmjs.com/package/checkride/v/0.2.0
|