plumbbob 0.5.4 → 0.6.1
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 +9 -0
- package/dist/cli-core.js +4 -0
- package/dist/lib/agents.js +498 -0
- package/dist/lib/intent.js +98 -8
- package/dist/lib/settings.js +17 -0
- package/dist/lib/sidecar.js +36 -0
- package/dist/verbs/agent.js +312 -0
- package/dist/verbs/checkpoint.js +2 -1
- package/dist/verbs/doctor.js +96 -3
- package/dist/verbs/status.js +64 -2
- package/node_modules/checkride/CHANGELOG.md +139 -0
- package/node_modules/checkride/LICENSE +21 -0
- package/node_modules/checkride/README.md +179 -0
- package/node_modules/checkride/dist/adapters.d.ts +56 -0
- package/node_modules/checkride/dist/adapters.d.ts.map +1 -0
- package/node_modules/checkride/dist/adapters.js +219 -0
- package/node_modules/checkride/dist/adapters.js.map +1 -0
- package/node_modules/checkride/dist/cli.d.ts +29 -0
- package/node_modules/checkride/dist/cli.d.ts.map +1 -0
- package/node_modules/checkride/dist/cli.js +227 -0
- package/node_modules/checkride/dist/cli.js.map +1 -0
- package/node_modules/checkride/dist/config.d.ts +74 -0
- package/node_modules/checkride/dist/config.d.ts.map +1 -0
- package/node_modules/checkride/dist/config.js +126 -0
- package/node_modules/checkride/dist/config.js.map +1 -0
- package/node_modules/checkride/dist/doctor.d.ts +76 -0
- package/node_modules/checkride/dist/doctor.d.ts.map +1 -0
- package/node_modules/checkride/dist/doctor.js +299 -0
- package/node_modules/checkride/dist/doctor.js.map +1 -0
- package/node_modules/checkride/dist/index.d.ts +18 -0
- package/node_modules/checkride/dist/index.d.ts.map +1 -0
- package/node_modules/checkride/dist/index.js +13 -0
- package/node_modules/checkride/dist/index.js.map +1 -0
- package/node_modules/checkride/dist/init.d.ts +64 -0
- package/node_modules/checkride/dist/init.d.ts.map +1 -0
- package/node_modules/checkride/dist/init.js +489 -0
- package/node_modules/checkride/dist/init.js.map +1 -0
- package/node_modules/checkride/dist/links.d.ts +23 -0
- package/node_modules/checkride/dist/links.d.ts.map +1 -0
- package/node_modules/checkride/dist/links.js +125 -0
- package/node_modules/checkride/dist/links.js.map +1 -0
- package/node_modules/checkride/dist/orchestrator.d.ts +96 -0
- package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -0
- package/node_modules/checkride/dist/orchestrator.js +234 -0
- package/node_modules/checkride/dist/orchestrator.js.map +1 -0
- package/node_modules/checkride/package.json +76 -0
- package/node_modules/checkride/templates/flat/fallow.toml +26 -0
- package/node_modules/checkride/templates/flat/pnpm-workspace.yaml +6 -0
- package/node_modules/checkride/templates/flat/tsconfig.json +9 -0
- package/node_modules/checkride/templates/hybrid/fallow.toml +42 -0
- package/node_modules/checkride/templates/hybrid/pnpm-workspace.yaml +6 -0
- package/node_modules/checkride/templates/hybrid/tsconfig.json +12 -0
- package/node_modules/checkride/templates/monorepo/fallow.toml +44 -0
- package/node_modules/checkride/templates/monorepo/pnpm-workspace.yaml +7 -0
- package/node_modules/checkride/templates/monorepo/tsconfig.json +7 -0
- package/node_modules/checkride/templates/shared/cspell.json +35 -0
- package/node_modules/checkride/templates/shared/gitignore +10 -0
- package/node_modules/checkride/templates/shared/markdownlint-cli2.jsonc +11 -0
- package/node_modules/checkride/templates/shared/npmrc +1 -0
- package/node_modules/checkride/templates/shared/oxlintrc.json +33 -0
- package/node_modules/checkride/templates/shared/rules/no-class.yml +8 -0
- package/node_modules/checkride/templates/shared/rules/no-deep-sibling-import.yml +15 -0
- package/node_modules/checkride/templates/shared/rules/no-default-export.yml +9 -0
- package/node_modules/checkride/templates/shared/rules/require-js-extension.yml +21 -0
- package/node_modules/checkride/templates/shared/sgconfig.yml +2 -0
- package/node_modules/checkride/templates/shared/tsconfig.base.json +28 -0
- package/node_modules/checkride/templates/shared/vitest.config.ts.template +27 -0
- package/package.json +4 -1
- package/skills/pb-build/SKILL.md +42 -7
- package/skills/pb-finish/SKILL.md +1 -1
- package/skills/pb-harvest/SKILL.md +1 -1
- package/skills/pb-park/SKILL.md +1 -1
- package/skills/pb-plan/SKILL.md +25 -4
- package/skills/pb-refine/SKILL.md +1 -1
- package/skills/pb-revert/SKILL.md +1 -1
- package/skills/pb-spike/SKILL.md +1 -1
- package/skills/pb-status/SKILL.md +1 -1
- package/skills/pb-step/SKILL.md +10 -2
- package/skills/pb-verify/SKILL.md +21 -6
package/dist/verbs/status.js
CHANGED
|
@@ -2,8 +2,10 @@
|
|
|
2
2
|
// Read-only, always exits 0. Skills pre-inject this output to gate their own
|
|
3
3
|
// behavior, so the `NO ACTIVE SESSION` sentinel is kept exact.
|
|
4
4
|
import { readFileSync } from 'node:fs';
|
|
5
|
+
import { join } from 'node:path';
|
|
5
6
|
import { findRepoRoot } from "../lib/git.js";
|
|
6
|
-
import {
|
|
7
|
+
import { SLOTS, readHarnessFile, resolveAgent, } from "../lib/agents.js";
|
|
8
|
+
import { buildFolder, buildLogPath, checkpointsPath, hasSession, inSpike, intentPath, listBuilds, resolveBuild, stepPath, } from "../lib/sidecar.js";
|
|
7
9
|
import { formatOrientation, orient } from "../lib/orient.js";
|
|
8
10
|
function readOr(path) {
|
|
9
11
|
try {
|
|
@@ -38,6 +40,66 @@ export function status(cwd, args = []) {
|
|
|
38
40
|
inFlight: /^\d+$/.test(inFlightRaw) ? Number(inFlightRaw) : null,
|
|
39
41
|
spiking: inSpike(root, slug),
|
|
40
42
|
});
|
|
41
|
-
|
|
43
|
+
const lines = [formatOrientation(orientation), ...harnessSection(root, slug)];
|
|
44
|
+
process.stdout.write(`${lines.join('\n')}\n`);
|
|
42
45
|
return 0;
|
|
43
46
|
}
|
|
47
|
+
// The active build's harness bindings (D48): the agents bound to each slot, per
|
|
48
|
+
// `defaults` and per step, with a warning on any bound agent that does not resolve
|
|
49
|
+
// (D54 — a teammate can lack a personal agent and the loop still works). Returns []
|
|
50
|
+
// when the build has no harness.json (a clean no-op) or the file binds nothing, so
|
|
51
|
+
// the dashboard stays uncluttered for builds that use no agents. A broken
|
|
52
|
+
// harness.json surfaces its parse error rather than hiding.
|
|
53
|
+
function harnessSection(root, slug) {
|
|
54
|
+
const parsed = readHarnessFile(join(buildFolder(root, slug), 'harness.json'));
|
|
55
|
+
if (parsed === null)
|
|
56
|
+
return [];
|
|
57
|
+
if (!parsed.ok)
|
|
58
|
+
return ['', `harness bindings: ✗ ${parsed.error}`];
|
|
59
|
+
const harness = parsed.harness;
|
|
60
|
+
const rows = [];
|
|
61
|
+
for (const frag of slotFragments(harness.defaults))
|
|
62
|
+
rows.push(` defaults · ${frag}`);
|
|
63
|
+
for (const [n, binding] of [...harness.steps.entries()].sort((a, b) => a[0] - b[0])) {
|
|
64
|
+
for (const frag of slotFragments(binding.bindings))
|
|
65
|
+
rows.push(` step ${n} · ${frag}`);
|
|
66
|
+
if (binding.note.length > 0)
|
|
67
|
+
rows.push(` step ${n} · note: ${binding.note}`);
|
|
68
|
+
}
|
|
69
|
+
if (rows.length === 0)
|
|
70
|
+
return [];
|
|
71
|
+
return ['', 'harness bindings:', ...rows, ...bindingWarnings(root, harness)];
|
|
72
|
+
}
|
|
73
|
+
// Render a SlotBindings as `slot: name1, name2` fragments, in slot order. A slot
|
|
74
|
+
// bound to no agents (an explicit "override to none") is omitted — there is nothing
|
|
75
|
+
// to run and nothing to name.
|
|
76
|
+
function slotFragments(bindings) {
|
|
77
|
+
const out = [];
|
|
78
|
+
for (const slot of SLOTS) {
|
|
79
|
+
const names = bindings[slot];
|
|
80
|
+
if (names !== undefined && names.length > 0)
|
|
81
|
+
out.push(`${slot}: ${names.join(', ')}`);
|
|
82
|
+
}
|
|
83
|
+
return out;
|
|
84
|
+
}
|
|
85
|
+
// A warning line for every distinct agent bound anywhere in the harness that does
|
|
86
|
+
// not resolve (D54). Deduped and sorted so the report is stable; a name bound in
|
|
87
|
+
// several slots warns once.
|
|
88
|
+
function bindingWarnings(root, harness) {
|
|
89
|
+
const names = new Set();
|
|
90
|
+
for (const slot of SLOTS)
|
|
91
|
+
for (const name of harness.defaults[slot] ?? [])
|
|
92
|
+
names.add(name);
|
|
93
|
+
for (const binding of harness.steps.values()) {
|
|
94
|
+
for (const slot of SLOTS)
|
|
95
|
+
for (const name of binding.bindings[slot] ?? [])
|
|
96
|
+
names.add(name);
|
|
97
|
+
}
|
|
98
|
+
const warnings = [];
|
|
99
|
+
for (const name of [...names].sort()) {
|
|
100
|
+
const res = resolveAgent(root, name);
|
|
101
|
+
if (!res.ok)
|
|
102
|
+
warnings.push(` ⚠ bound agent "${name}" does not resolve — ${res.error}`);
|
|
103
|
+
}
|
|
104
|
+
return warnings;
|
|
105
|
+
}
|
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project
|
|
5
|
+
adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
## [0.1.6] - 2026-06-30
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Custom checks (config entries keyed by a name outside the built-in slot
|
|
12
|
+
catalogue) accept an `order` field: `"order": "first"` runs the check ahead
|
|
13
|
+
of every built-in, `"last"` (the default) keeps it after them. Lets a
|
|
14
|
+
formatter such as `biome format --write` normalize the tree before the
|
|
15
|
+
linters and tests run. Within each group, config key order is preserved.
|
|
16
|
+
|
|
17
|
+
## [0.1.5] - 2026-06-30
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
|
|
21
|
+
- `checkride --help` / `-h` and `checkride --version` / `-V`.
|
|
22
|
+
- Optional per-check timeout, off by default: set a global `timeout` (seconds)
|
|
23
|
+
in `checkride.config.json` or override it per check; `0` exempts a slot. A hung
|
|
24
|
+
check is killed and reported as failed with its elapsed duration.
|
|
25
|
+
|
|
26
|
+
### Changed
|
|
27
|
+
|
|
28
|
+
- Supported Node floor lowered to 22.18 (the minimum required by the cspell and
|
|
29
|
+
oxlint toolchain). `init` and `doctor` reflect it, and CI now runs a Node
|
|
30
|
+
22 + 24 matrix.
|
|
31
|
+
- Unknown commands and bad flags print a concise message plus a `checkride
|
|
32
|
+
--help` pointer; a malformed `checkride.config.json` now reports `invalid
|
|
33
|
+
checkride.config.json: <reason>` instead of a raw parser error.
|
|
34
|
+
- `prepublishOnly` runs the test suite before publishing, not just the build.
|
|
35
|
+
|
|
36
|
+
### Internal
|
|
37
|
+
|
|
38
|
+
- `package.json` gains `repository`, `homepage`, and `bugs` for the npm page.
|
|
39
|
+
- README and cheat sheet document the stderr/stdout stream split; README gains a
|
|
40
|
+
header image.
|
|
41
|
+
|
|
42
|
+
## [0.1.4] - 2026-06-26
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
|
|
46
|
+
- Onboarding and reference documentation under `docs/`: a getting-started guide,
|
|
47
|
+
a command and flag cheat sheet, and a tool-installation reference (system
|
|
48
|
+
prerequisites plus how to install a missing slot tool such as fallow or
|
|
49
|
+
ast-grep). Includes a "Working with agents" section covering how Claude Code
|
|
50
|
+
and other agents adopt the `pnpm check` contract via the AGENTS.md stanza, and
|
|
51
|
+
how to enforce it with a Stop hook without double-running the pipeline.
|
|
52
|
+
|
|
53
|
+
### Internal
|
|
54
|
+
|
|
55
|
+
- Removed the v1 build plan now that it is fully implemented.
|
|
56
|
+
|
|
57
|
+
## [0.1.3] - 2026-06-17
|
|
58
|
+
|
|
59
|
+
### Changed
|
|
60
|
+
|
|
61
|
+
- `checkride doctor` now reports every catalogue slot with its enablement —
|
|
62
|
+
`default`, `opt-in`, `disabled`, or `unavailable` — instead of listing only
|
|
63
|
+
the slots the default run executes. Opt-in slots (mutation, security),
|
|
64
|
+
config-disabled slots, and slots with no detected tool are no longer silently
|
|
65
|
+
omitted; each shows how to enable it. Exit-code behavior is unchanged: only
|
|
66
|
+
default slots are required, so the newly surfaced slots never fail the report.
|
|
67
|
+
|
|
68
|
+
## [0.1.2] - 2026-06-12
|
|
69
|
+
|
|
70
|
+
### Fixed
|
|
71
|
+
|
|
72
|
+
- The CLI now runs when invoked through its installed bin — `pnpm exec
|
|
73
|
+
checkride`, `npx checkride`, and the generated `pnpm check` alias. The 0.1.1
|
|
74
|
+
entrypoint guard compared unresolved paths, so launching via the
|
|
75
|
+
`node_modules/.bin/checkride` symlink (how every consumer runs it) silently
|
|
76
|
+
exited 0 without running any checks.
|
|
77
|
+
|
|
78
|
+
### Internal
|
|
79
|
+
|
|
80
|
+
- Added an end-to-end regression test that invokes the CLI through a bin
|
|
81
|
+
symlink and asserts it behaves identically to a direct invocation.
|
|
82
|
+
- Bumped the CI GitHub Actions to their node24-runtime majors
|
|
83
|
+
(`actions/checkout`, `actions/setup-node`, `pnpm/action-setup`), clearing the
|
|
84
|
+
Node 20 deprecation warning.
|
|
85
|
+
|
|
86
|
+
## [0.1.1] - 2026-06-12
|
|
87
|
+
|
|
88
|
+
### Added
|
|
89
|
+
|
|
90
|
+
- `checkride init` for existing projects gained `--add <slots>`: it scaffolds
|
|
91
|
+
blessed-default configs for the named empty slots (lint, spell, struct, test,
|
|
92
|
+
docs, types, dead) and adopts them in the same run, never clobbering an
|
|
93
|
+
existing config.
|
|
94
|
+
- `checkride init` for existing projects now writes the `check: checkride` alias
|
|
95
|
+
to `package.json` when it is missing — additive, and never overwriting an
|
|
96
|
+
existing `check` script.
|
|
97
|
+
|
|
98
|
+
### Internal
|
|
99
|
+
|
|
100
|
+
- Flattened checkride's own source to named single-file modules with a
|
|
101
|
+
logic-free barrel `index.ts`, relocated unit tests to `src/__tests__/`, and
|
|
102
|
+
added a `no-logic-in-barrel` structural rule. The deep-modules folder pattern
|
|
103
|
+
still ships to consumers unchanged.
|
|
104
|
+
- Added Stryker mutation testing, strengthened weak tests, and gitignored the
|
|
105
|
+
regenerated `stryker.incremental.json` cache.
|
|
106
|
+
- Added a GitHub Actions workflow running `pnpm check` plus the e2e suite.
|
|
107
|
+
- Added a `/version` release skill for cutting tagged releases.
|
|
108
|
+
- Reconciled the module-boundary documentation with the flat source layout.
|
|
109
|
+
|
|
110
|
+
## [0.1.0] - 2026-06-11
|
|
111
|
+
|
|
112
|
+
The first real release. (`0.0.0` was a name-claim placeholder.)
|
|
113
|
+
|
|
114
|
+
### Added
|
|
115
|
+
|
|
116
|
+
- `checkride` run command: the verification pipeline across ten slots (types,
|
|
117
|
+
lint, struct, dead, test, docs, links, spell, plus opt-in mutation and
|
|
118
|
+
security), writing raw per-tool output and an aggregate `.check/summary.json`
|
|
119
|
+
(`schema_version: 1`).
|
|
120
|
+
- Adapter registry with blessed defaults (`tsc`, `oxlint`, `ast-grep`,
|
|
121
|
+
`fallow`, `vitest`, `markdownlint-cli2`, built-in links, `cspell`, `stryker`,
|
|
122
|
+
`pnpm audit`) and wired alternates (`biome`, `eslint`, `knip`, `jest`).
|
|
123
|
+
- Zero-config detection plus `checkride.config.json` for overrides, disabled
|
|
124
|
+
slots, adapter swaps, and custom checks.
|
|
125
|
+
- `checkride init` for new projects (flat / monorepo / hybrid shapes, each green
|
|
126
|
+
out of the box) and existing projects (additive adoption, idempotent AGENTS.md
|
|
127
|
+
stanza, failing slots disabled with a report).
|
|
128
|
+
- `checkride doctor` (read-only environment + tooling verification) and
|
|
129
|
+
`checkride fix` (runs every active adapter's fix command).
|
|
130
|
+
- Flags: `--only`, `--skip`, `--bail`, `--json`, `--changed`, `--all`,
|
|
131
|
+
`--include`.
|
|
132
|
+
|
|
133
|
+
[0.1.6]: https://www.npmjs.com/package/checkride/v/0.1.6
|
|
134
|
+
[0.1.5]: https://www.npmjs.com/package/checkride/v/0.1.5
|
|
135
|
+
[0.1.4]: https://www.npmjs.com/package/checkride/v/0.1.4
|
|
136
|
+
[0.1.3]: https://www.npmjs.com/package/checkride/v/0.1.3
|
|
137
|
+
[0.1.2]: https://www.npmjs.com/package/checkride/v/0.1.2
|
|
138
|
+
[0.1.1]: https://www.npmjs.com/package/checkride/v/0.1.1
|
|
139
|
+
[0.1.0]: https://www.npmjs.com/package/checkride/v/0.1.0
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rob McLarty
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+

|
|
2
|
+
|
|
3
|
+
# checkride
|
|
4
|
+
|
|
5
|
+
**An agent harness for TypeScript repositories**, delivered as one npm package.
|
|
6
|
+
It gives an LLM agent two things it otherwise lacks: a definition of done, and
|
|
7
|
+
lanes to stay inside.
|
|
8
|
+
|
|
9
|
+
## The thesis
|
|
10
|
+
|
|
11
|
+
Agents are good at writing code and bad at knowing when to stop. Checkride fixes
|
|
12
|
+
both halves of that problem.
|
|
13
|
+
|
|
14
|
+
1. **A definition of done.** One command runs the whole verification pipeline —
|
|
15
|
+
types, lint, structure, dead code, tests, docs, links, spelling. **Exit 0
|
|
16
|
+
means the work is complete.** Agents stop guessing; humans stop re-reviewing
|
|
17
|
+
half-finished work.
|
|
18
|
+
2. **Structured boundaries.** A module is an encapsulation boundary with a
|
|
19
|
+
narrow public surface. When one grows internals worth hiding it becomes a
|
|
20
|
+
folder whose only public surface is its `index.ts`, and siblings reach only
|
|
21
|
+
that index — never the internals. Enforced mechanically, boundaries keep
|
|
22
|
+
agents inside lanes and let humans and agents work in parallel with minimal
|
|
23
|
+
merge conflicts.
|
|
24
|
+
|
|
25
|
+
The consumer of the output is an LLM, so checkride never normalizes diagnostics
|
|
26
|
+
into a common format. Each tool writes its own raw JSON to `.check/`; the agent
|
|
27
|
+
reads whatever the tool emits. That deletes the layer that makes every prior
|
|
28
|
+
meta-runner expensive to extend.
|
|
29
|
+
|
|
30
|
+
## Install
|
|
31
|
+
|
|
32
|
+
```bash
|
|
33
|
+
pnpm add -D checkride
|
|
34
|
+
pnpm exec checkride init # set up a project (new or existing, auto-detected)
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
`init` writes a `"check": "checkride"` alias, so daily usage is `pnpm check`
|
|
38
|
+
regardless of the tool's name.
|
|
39
|
+
|
|
40
|
+
## Commands
|
|
41
|
+
|
|
42
|
+
```text
|
|
43
|
+
checkride Run the default checks. Exit 0 pass / 1 fail / 2 error.
|
|
44
|
+
--only <a,b> --skip <a,b> --bail --json --changed --all --include <a,b>
|
|
45
|
+
checkride init Set up a project (new or existing — auto-detected).
|
|
46
|
+
--shape flat|monorepo|hybrid --name <n> --scope <@s> --license <id> --dry-run
|
|
47
|
+
checkride doctor Verify environment + every slot's status (read-only, exit 0/1).
|
|
48
|
+
checkride fix Run every active adapter's fix command (oxlint --fix, ...).
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
During iteration, narrow the loop: `checkride --bail`, `checkride --only
|
|
52
|
+
types,lint`, `checkride --changed`.
|
|
53
|
+
|
|
54
|
+
Output streams: human-readable progress goes to stderr; stdout carries machine
|
|
55
|
+
output only — the summary JSON under `--json`, mirroring `.check/summary.json`.
|
|
56
|
+
So `checkride --json` produces clean JSON on stdout that is safe to pipe, and the
|
|
57
|
+
default run leaves stdout empty.
|
|
58
|
+
|
|
59
|
+
## The pipeline: slots and adapters
|
|
60
|
+
|
|
61
|
+
A **slot** is a role in the pipeline (order matters — cheapest first). An
|
|
62
|
+
**adapter** is a concrete tool that fills a slot. There is one blessed default
|
|
63
|
+
per slot; alternates are wired so checkride can run them, but `init` only
|
|
64
|
+
generates config for the blessed default.
|
|
65
|
+
|
|
66
|
+
| Slot | Role | Blessed default | Alternates |
|
|
67
|
+
| ---------- | -------------------------------------- | ------------------- | ---------------- |
|
|
68
|
+
| `types` | Type checking | `tsc --build` | — |
|
|
69
|
+
| `lint` | Linting | `oxlint` | `biome`, `eslint`|
|
|
70
|
+
| `struct` | Structural rules (deep modules) | `ast-grep` | — |
|
|
71
|
+
| `dead` | Dead code, deps, cycles, boundaries | `fallow` | `knip` |
|
|
72
|
+
| `test` | Tests + coverage | `vitest` | `jest` |
|
|
73
|
+
| `docs` | Markdown lint | `markdownlint-cli2` | — |
|
|
74
|
+
| `links` | Relative markdown links resolve | built-in | — |
|
|
75
|
+
| `spell` | Spelling | `cspell` | — |
|
|
76
|
+
| `mutation` | Mutation testing (opt-in) | `stryker` | — |
|
|
77
|
+
| `security` | Dependency audit (opt-in) | `pnpm audit` | — |
|
|
78
|
+
|
|
79
|
+
Zero-config: for each slot, checkride runs the first adapter whose config file
|
|
80
|
+
exists, and skips slots with no detected tool. The core has **no runtime
|
|
81
|
+
dependency** on any checked tool — it spawns `pnpm exec <tool>`; the project
|
|
82
|
+
owns the pinned tool versions.
|
|
83
|
+
|
|
84
|
+
## The `.check/` contract
|
|
85
|
+
|
|
86
|
+
Every run writes to `.check/`. This is a public API for agents; treat schema
|
|
87
|
+
changes as breaking.
|
|
88
|
+
|
|
89
|
+
- `summary.json` — the aggregate report:
|
|
90
|
+
|
|
91
|
+
```jsonc
|
|
92
|
+
{
|
|
93
|
+
"schema_version": 1,
|
|
94
|
+
"timestamp": "…",
|
|
95
|
+
"ok": true,
|
|
96
|
+
"total_duration_ms": 4200,
|
|
97
|
+
"checks": [
|
|
98
|
+
{ "name": "lint", "adapter": "oxlint", "description": "…",
|
|
99
|
+
"ok": true, "exit_code": 0, "duration_ms": 470, "output_file": "lint.json" }
|
|
100
|
+
]
|
|
101
|
+
}
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
- `<slot>.json` — the raw tool JSON when stdout parses as JSON; otherwise
|
|
105
|
+
`<slot>.stdout.txt` / `<slot>.stderr.txt`. Tools that write their own files
|
|
106
|
+
(vitest `--outputFile`, stryker) keep doing so.
|
|
107
|
+
|
|
108
|
+
To debug a failure: read `summary.json` to find the failing slot, then read that
|
|
109
|
+
slot's raw output for structured diagnostics.
|
|
110
|
+
|
|
111
|
+
## Configuration
|
|
112
|
+
|
|
113
|
+
`checkride.config.json` is optional — add it only to deviate from the defaults:
|
|
114
|
+
|
|
115
|
+
```jsonc
|
|
116
|
+
{
|
|
117
|
+
"timeout": 600, // global per-check timeout in seconds (off by default)
|
|
118
|
+
"checks": {
|
|
119
|
+
"lint": "biome", // pick an alternate adapter
|
|
120
|
+
"spell": false, // disable a slot
|
|
121
|
+
"test": { "use": "vitest", "timeout": 0, "changedArgs": ["--changed", "origin/master"] },
|
|
122
|
+
"format": { // a custom check that runs FIRST, ahead of the built-ins
|
|
123
|
+
"command": "pnpm",
|
|
124
|
+
"args": ["exec", "biome", "format", "--write"],
|
|
125
|
+
"order": "first"
|
|
126
|
+
},
|
|
127
|
+
"licenses": { // a custom check (runs last by default)
|
|
128
|
+
"command": "node",
|
|
129
|
+
"args": ["scripts/check-licenses.mjs"]
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
A custom check (one keyed by a name that isn't a built-in slot) runs *after* the
|
|
136
|
+
built-in catalogue by default. Set `"order": "first"` to run it ahead of every
|
|
137
|
+
built-in check instead — handy for a formatter like `biome format --write` that
|
|
138
|
+
should normalize the tree before the linters and tests look at it. `"order":
|
|
139
|
+
"last"` is the explicit form of the default. Within each group, custom checks
|
|
140
|
+
run in the order they appear in the config.
|
|
141
|
+
|
|
142
|
+
A per-check timeout guards against a hung tool. It is **off by default** — a cap
|
|
143
|
+
short enough to catch a hang on a small repo is short enough to kill a legitimate
|
|
144
|
+
slow run on a large one, and CI job timeouts already bound true hangs. Set a
|
|
145
|
+
global `timeout` (seconds) to opt in, override it per check (`"timeout": <n>`),
|
|
146
|
+
and use `"timeout": 0` to exempt a slot. Leave `dead`, `test`, and `mutation`
|
|
147
|
+
generous or uncapped — they legitimately run long.
|
|
148
|
+
|
|
149
|
+
## Project shapes
|
|
150
|
+
|
|
151
|
+
`init` scaffolds three shapes. They share everything except `tsconfig.json`,
|
|
152
|
+
`fallow.toml`, and `pnpm-workspace.yaml`:
|
|
153
|
+
|
|
154
|
+
- **flat** — a single package using the deep-modules layout under `src/`.
|
|
155
|
+
- **monorepo** — a pnpm workspace of `apps/*` (deployable leaves) and `libs/*`
|
|
156
|
+
(reusable internals); libs may not import from apps.
|
|
157
|
+
- **hybrid** — a root app in `src/` plus internal packages under `packages/*`.
|
|
158
|
+
|
|
159
|
+
Every generated shape is green out of the box — an end-to-end test enforces it.
|
|
160
|
+
|
|
161
|
+
## Conventions
|
|
162
|
+
|
|
163
|
+
Module boundaries, enforced by `ast-grep` and `fallow`:
|
|
164
|
+
|
|
165
|
+
- A module is a unit of encapsulation. A single file is a module; promote it to
|
|
166
|
+
a folder with a barrel `index.ts` when it grows internals worth hiding — a
|
|
167
|
+
one-file folder is just ceremony.
|
|
168
|
+
- A folder module's `index.ts` is its only public surface: it re-exports, it
|
|
169
|
+
holds no logic. Siblings import it via `'../<sibling>/index.js'`, never its
|
|
170
|
+
internals.
|
|
171
|
+
- Named exports only; no classes; `.js` extensions on relative imports
|
|
172
|
+
(NodeNext); tests colocated with the code they cover.
|
|
173
|
+
|
|
174
|
+
See [AGENTS.md](./AGENTS.md) for the contract agents follow, and
|
|
175
|
+
[CHANGELOG.md](./CHANGELOG.md) for release notes.
|
|
176
|
+
|
|
177
|
+
## License
|
|
178
|
+
|
|
179
|
+
[MIT](./LICENSE)
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Adapter registry — pure data.
|
|
3
|
+
*
|
|
4
|
+
* A `Slot` is a role in the pipeline (the catalogue; order matters, cheapest
|
|
5
|
+
* first). An `Adapter` is a concrete tool that can fill a slot. The registry is
|
|
6
|
+
* data only: no logic lives here. Resolution (config vs detection) lives in
|
|
7
|
+
* `../config`, and execution lives in `../orchestrator`.
|
|
8
|
+
*
|
|
9
|
+
* Phase 1 ships the blessed defaults plus the two opt-in slots. Alternates
|
|
10
|
+
* (biome, knip, eslint, jest) land in Phase 2.
|
|
11
|
+
*/
|
|
12
|
+
/** The aggregate-report schema version written to `.check/summary.json`. */
|
|
13
|
+
export declare const SCHEMA_VERSION = 1;
|
|
14
|
+
/** A role in the pipeline. */
|
|
15
|
+
export type Slot = {
|
|
16
|
+
/** Stable slot name, e.g. `'lint'`. Used by `--only`/`--skip` and the report. */
|
|
17
|
+
name: string;
|
|
18
|
+
/** Opt-in slots are excluded from the default run (need `--all`/`--include`). */
|
|
19
|
+
optIn?: boolean;
|
|
20
|
+
};
|
|
21
|
+
/** A concrete tool that can fill a slot. */
|
|
22
|
+
export type Adapter = {
|
|
23
|
+
/** Adapter name, e.g. `'oxlint'`. Recorded as `adapter` in the report. */
|
|
24
|
+
name: string;
|
|
25
|
+
/** The slot this adapter fills, e.g. `'lint'`. */
|
|
26
|
+
slot: string;
|
|
27
|
+
/** Human description for the report (mirrors the interim check catalogue). */
|
|
28
|
+
description: string;
|
|
29
|
+
/** Config files whose presence activates this adapter. `[]` = always available. */
|
|
30
|
+
detect: string[];
|
|
31
|
+
/** Command to spawn (usually `'pnpm'`). Ignored when `builtin` is set. */
|
|
32
|
+
command: string;
|
|
33
|
+
/** Arguments to the command. Ignored when `builtin` is set. */
|
|
34
|
+
args: string[];
|
|
35
|
+
/** `.check/<file>` target when stdout is JSON; `null` if the tool writes its own. */
|
|
36
|
+
outputFile: string | null;
|
|
37
|
+
/** Appended to `args` under `--changed`. */
|
|
38
|
+
changedArgs?: string[];
|
|
39
|
+
/** Used by `checkride fix`. */
|
|
40
|
+
fixArgs?: string[];
|
|
41
|
+
/** Per-check timeout in seconds; `0` disables the cap. Falls back to the config-level `timeout`. */
|
|
42
|
+
timeout?: number;
|
|
43
|
+
/** In-process check id (e.g. `'links'`); when set, the orchestrator runs it directly. */
|
|
44
|
+
builtin?: string;
|
|
45
|
+
/** Pinned versions `init` writes into package.json. */
|
|
46
|
+
devDeps: Record<string, string>;
|
|
47
|
+
};
|
|
48
|
+
/** Pipeline order. Cheapest first so `--bail` fails fast. */
|
|
49
|
+
export declare const SLOTS: readonly Slot[];
|
|
50
|
+
/**
|
|
51
|
+
* Adapter registry. The FIRST adapter for a slot is its blessed default: it
|
|
52
|
+
* wins detection when several tool configs coexist, and is the only one `init`
|
|
53
|
+
* generates config for. Alternates follow so checkride can still *run* them.
|
|
54
|
+
*/
|
|
55
|
+
export declare const ADAPTERS: readonly Adapter[];
|
|
56
|
+
//# sourceMappingURL=adapters.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adapters.d.ts","sourceRoot":"","sources":["../src/adapters.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,4EAA4E;AAC5E,eAAO,MAAM,cAAc,IAAI,CAAC;AAEhC,8BAA8B;AAC9B,MAAM,MAAM,IAAI,GAAG;IACjB,iFAAiF;IACjF,IAAI,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,CAAC;AAEF,4CAA4C;AAC5C,MAAM,MAAM,OAAO,GAAG;IACpB,0EAA0E;IAC1E,IAAI,EAAE,MAAM,CAAC;IACb,kDAAkD;IAClD,IAAI,EAAE,MAAM,CAAC;IACb,8EAA8E;IAC9E,WAAW,EAAE,MAAM,CAAC;IACpB,mFAAmF;IACnF,MAAM,EAAE,MAAM,EAAE,CAAC;IACjB,0EAA0E;IAC1E,OAAO,EAAE,MAAM,CAAC;IAChB,+DAA+D;IAC/D,IAAI,EAAE,MAAM,EAAE,CAAC;IACf,qFAAqF;IACrF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,4CAA4C;IAC5C,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC;IACvB,+BAA+B;IAC/B,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC;IACnB,oGAAoG;IACpG,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,yFAAyF;IACzF,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,uDAAuD;IACvD,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CACjC,CAAC;AAEF,6DAA6D;AAC7D,eAAO,MAAM,KAAK,EAAE,SAAS,IAAI,EAWhC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,QAAQ,EAAE,SAAS,OAAO,EA0LtC,CAAC"}
|