plumbbob 0.9.5 → 0.10.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 +89 -87
- package/dist/cli-core.js +18 -8
- package/dist/cli.js +1 -1
- package/dist/lib/agents.js +26 -26
- package/dist/lib/buildlog.js +21 -11
- package/dist/lib/buildlogsync.js +8 -8
- package/dist/lib/check.js +14 -14
- package/dist/lib/commitbody.js +72 -0
- package/dist/lib/commitmsg.js +7 -7
- package/dist/lib/git.js +44 -15
- package/dist/lib/intent.js +20 -19
- package/dist/lib/latch.js +16 -16
- package/dist/lib/orient.js +36 -17
- package/dist/lib/reentry.js +3 -3
- package/dist/lib/settings.js +16 -16
- package/dist/lib/sidecar.js +70 -54
- package/dist/lib/templates.js +1 -1
- package/dist/verbs/abandon.js +122 -0
- package/dist/verbs/agent.js +25 -25
- package/dist/verbs/build.js +9 -9
- package/dist/verbs/check.js +6 -6
- package/dist/verbs/checkpoint.js +48 -47
- package/dist/verbs/doctor.js +35 -29
- package/dist/verbs/finish.js +27 -40
- package/dist/verbs/handoff.js +9 -8
- package/dist/verbs/init.js +9 -9
- package/dist/verbs/park.js +3 -3
- package/dist/verbs/recover.js +12 -12
- package/dist/verbs/revert.js +12 -12
- package/dist/verbs/spike.js +21 -21
- package/dist/verbs/start.js +49 -19
- package/dist/verbs/status.js +8 -8
- package/dist/verbs/turn.js +16 -16
- package/dist/verbs/use.js +4 -4
- package/node_modules/checkride/.claude-plugin/plugin.json +1 -1
- package/node_modules/checkride/CHANGELOG.md +401 -0
- package/node_modules/checkride/README.md +27 -9
- package/node_modules/checkride/dist/adapters.d.ts +12 -4
- package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
- package/node_modules/checkride/dist/adapters.js +21 -1
- package/node_modules/checkride/dist/adapters.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/cursor.d.ts +9 -1
- package/node_modules/checkride/dist/agent-setup/cursor.d.ts.map +1 -1
- package/node_modules/checkride/dist/agent-setup/cursor.js +59 -1
- package/node_modules/checkride/dist/agent-setup/cursor.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/harness.d.ts +1 -1
- package/node_modules/checkride/dist/agent-setup/harness.d.ts.map +1 -1
- package/node_modules/checkride/dist/agent-setup/harness.js +10 -1
- package/node_modules/checkride/dist/agent-setup/harness.js.map +1 -1
- package/node_modules/checkride/dist/agent-setup/scripts.d.ts +23 -0
- package/node_modules/checkride/dist/agent-setup/scripts.d.ts.map +1 -1
- package/node_modules/checkride/dist/agent-setup/scripts.js +387 -82
- package/node_modules/checkride/dist/agent-setup/scripts.js.map +1 -1
- package/node_modules/checkride/dist/baseline/fallow.js +2 -2
- package/node_modules/checkride/dist/baseline/fingerprint.d.ts +14 -5
- package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/fingerprint.js +58 -5
- package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -1
- package/node_modules/checkride/dist/baseline/history.d.ts +98 -0
- package/node_modules/checkride/dist/baseline/history.d.ts.map +1 -0
- package/node_modules/checkride/dist/baseline/history.js +232 -0
- package/node_modules/checkride/dist/baseline/history.js.map +1 -0
- package/node_modules/checkride/dist/baseline/index.d.ts +4 -2
- package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/index.js +2 -1
- package/node_modules/checkride/dist/baseline/index.js.map +1 -1
- package/node_modules/checkride/dist/baseline/store.d.ts +30 -7
- package/node_modules/checkride/dist/baseline/store.d.ts.map +1 -1
- package/node_modules/checkride/dist/baseline/store.js +50 -16
- package/node_modules/checkride/dist/baseline/store.js.map +1 -1
- package/node_modules/checkride/dist/cli.d.ts +5 -1
- package/node_modules/checkride/dist/cli.d.ts.map +1 -1
- package/node_modules/checkride/dist/cli.js +98 -25
- package/node_modules/checkride/dist/cli.js.map +1 -1
- package/node_modules/checkride/dist/config.d.ts +33 -4
- package/node_modules/checkride/dist/config.d.ts.map +1 -1
- package/node_modules/checkride/dist/config.js +21 -6
- package/node_modules/checkride/dist/config.js.map +1 -1
- package/node_modules/checkride/dist/digest/digest.js +1 -1
- package/node_modules/checkride/dist/doctor.d.ts +2 -0
- package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
- package/node_modules/checkride/dist/doctor.js +39 -1
- package/node_modules/checkride/dist/doctor.js.map +1 -1
- package/node_modules/checkride/dist/gate.d.ts +49 -4
- package/node_modules/checkride/dist/gate.d.ts.map +1 -1
- package/node_modules/checkride/dist/gate.js +143 -16
- package/node_modules/checkride/dist/gate.js.map +1 -1
- package/node_modules/checkride/dist/init.d.ts +8 -1
- package/node_modules/checkride/dist/init.d.ts.map +1 -1
- package/node_modules/checkride/dist/init.js +68 -7
- package/node_modules/checkride/dist/init.js.map +1 -1
- package/node_modules/checkride/dist/node-pin.d.ts +1 -1
- package/node_modules/checkride/dist/node-pin.js +1 -1
- package/node_modules/checkride/dist/orchestrator.d.ts +13 -0
- package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
- package/node_modules/checkride/dist/orchestrator.js +118 -13
- package/node_modules/checkride/dist/orchestrator.js.map +1 -1
- package/node_modules/checkride/dist/pm/index.d.ts +1 -0
- package/node_modules/checkride/dist/pm/index.d.ts.map +1 -1
- package/node_modules/checkride/dist/pm/index.js.map +1 -1
- package/node_modules/checkride/dist/pm/launch.d.ts +23 -2
- package/node_modules/checkride/dist/pm/launch.d.ts.map +1 -1
- package/node_modules/checkride/dist/pm/launch.js +16 -0
- package/node_modules/checkride/dist/pm/launch.js.map +1 -1
- package/node_modules/checkride/dist/pm/translate.js +1 -1
- package/node_modules/checkride/dist/pm/translate.js.map +1 -1
- package/node_modules/checkride/dist/qa/mutation.d.ts +4 -4
- package/node_modules/checkride/dist/qa/mutation.js +4 -4
- package/node_modules/checkride/dist/recover.d.ts +48 -0
- package/node_modules/checkride/dist/recover.d.ts.map +1 -0
- package/node_modules/checkride/dist/recover.js +220 -0
- package/node_modules/checkride/dist/recover.js.map +1 -0
- package/node_modules/checkride/dist/smoke.d.ts +1 -1
- package/node_modules/checkride/dist/smoke.js +1 -1
- package/node_modules/checkride/dist/snippets.d.ts +1 -1
- package/node_modules/checkride/package.json +3 -2
- package/node_modules/checkride/schema/checkride.config.schema.json +9 -1
- package/node_modules/checkride/skills/check/SKILL.md +9 -1
- package/node_modules/checkride/templates/shared/styles/Repo/Drift.yml +41 -0
- package/node_modules/checkride/templates/shared/styles/Repo/Latin.yml +14 -0
- package/node_modules/checkride/templates/shared/styles/Repo/LyHyphen.yml +28 -0
- package/node_modules/checkride/templates/shared/styles/Repo/Minted.yml +33 -0
- package/node_modules/checkride/templates/shared/styles/Repo/ThereIs.yml +16 -0
- package/node_modules/checkride/templates/shared/styles/Repo/Weasel.yml +26 -0
- package/node_modules/checkride/templates/shared/vale.ini +34 -0
- package/package.json +13 -11
- package/skills/abandon/SKILL.md +20 -0
- package/skills/build/SKILL.md +69 -64
- package/skills/doctor/SKILL.md +11 -11
- package/skills/finish/SKILL.md +20 -19
- package/skills/harvest/SKILL.md +13 -12
- package/skills/park/SKILL.md +10 -10
- package/skills/plan/SKILL.md +63 -54
- package/skills/recover/SKILL.md +7 -7
- package/skills/refine/SKILL.md +18 -16
- package/skills/revert/SKILL.md +6 -6
- package/skills/spike/SKILL.md +9 -9
- package/skills/status/SKILL.md +5 -5
- package/skills/step/SKILL.md +17 -12
- package/skills/verify/SKILL.md +45 -40
- package/templates/build-log.md +7 -7
- package/templates/intent.md +49 -39
- package/templates/spike-report.md +10 -10
|
@@ -8,6 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export type { PackageManager } from './detect.js';
|
|
10
10
|
export { detectPackageManager } from './detect.js';
|
|
11
|
+
export type { LaunchRefusal } from './launch.js';
|
|
11
12
|
export { launchRefusal, SPAWN_FAILED_MARKER } from './launch.js';
|
|
12
13
|
export { execTool, execUsesGlobalCache, installCommand, isPnPInstall, resolveSlotTool } from './tools.js';
|
|
13
14
|
export { execCommand, isAvailableUnder, runScript, translateExec } from './translate.js';
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1G,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/pm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAEH,YAAY,EAAE,cAAc,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AACnD,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1G,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/pm/index.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AAGH,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,aAAa,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AACjE,OAAO,EAAE,QAAQ,EAAE,mBAAmB,EAAE,cAAc,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,YAAY,CAAC;AAC1G,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,SAAS,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
* that does not describe this run, which is the failure this table exists to
|
|
17
17
|
* prevent.
|
|
18
18
|
*
|
|
19
|
+
* Each refusal also carries {@link RefusalFix}, because "no code change clears
|
|
20
|
+
* it" is true of only *some* of them. That field is what lets the gate block on
|
|
21
|
+
* the ones an agent can fix and stand down on the ones it cannot, instead of
|
|
22
|
+
* blocking on both and looping forever on the second.
|
|
23
|
+
*
|
|
19
24
|
* **Every pattern here must be one a check's own output cannot contain.** A
|
|
20
25
|
* false positive is worse than the bug being fixed: it would tell someone their
|
|
21
26
|
* environment is broken while their code is what failed. The patterns are all
|
|
@@ -27,8 +32,23 @@
|
|
|
27
32
|
/** The sentinel a caller writes when the package-manager binary itself never started. */
|
|
28
33
|
export declare const SPAWN_FAILED_MARKER = "checkride: could not start";
|
|
29
34
|
/**
|
|
30
|
-
*
|
|
31
|
-
*
|
|
35
|
+
* Who can clear a refusal — the one thing a gate has to know before deciding
|
|
36
|
+
* whether blocking on it accomplishes anything.
|
|
37
|
+
*
|
|
38
|
+
* `repo` refusals are cleared by editing the repo: add the missing `check`
|
|
39
|
+
* script, add the missing package.json. An agent holding the edit tools can do
|
|
40
|
+
* that, so a gate that blocks is a gate that works.
|
|
41
|
+
*
|
|
42
|
+
* `environment` refusals cannot be cleared from inside the turn at all — the
|
|
43
|
+
* wrong Node is on `PATH`, corepack will not verify the package manager, the
|
|
44
|
+
* package manager is not installed. Blocking there does not produce a fix; it
|
|
45
|
+
* produces an unbounded retry against an impossible one, because the harness
|
|
46
|
+
* re-prompts the same agent that already has no lever to pull.
|
|
47
|
+
*/
|
|
48
|
+
export type RefusalFix = 'repo' | 'environment';
|
|
49
|
+
/**
|
|
50
|
+
* A refusal checkride recognizes: the marker to look for, the cause in the words
|
|
51
|
+
* a reader needs, and who can clear it.
|
|
32
52
|
*
|
|
33
53
|
* `cause` completes the sentence "the gate could not run — …", so it names what
|
|
34
54
|
* refused and why, never what to do about it; the fix is the caller's to phrase,
|
|
@@ -37,6 +57,7 @@ export declare const SPAWN_FAILED_MARKER = "checkride: could not start";
|
|
|
37
57
|
export type LaunchRefusal = {
|
|
38
58
|
marker: string;
|
|
39
59
|
cause: string;
|
|
60
|
+
fixable: RefusalFix;
|
|
40
61
|
};
|
|
41
62
|
/**
|
|
42
63
|
* Classify `output` — whatever the child printed on either stream — as a launch
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/pm/launch.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"launch.d.ts","sourceRoot":"","sources":["../../src/pm/launch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,yFAAyF;AACzF,eAAO,MAAM,mBAAmB,+BAA+B,CAAC;AAEhE;;;;;;;;;;;;;GAaG;AACH,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,aAAa,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,MAAM,aAAa,GAAG;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,UAAU,CAAA;CAAE,CAAC;AAiEnF;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,MAAM,GAAG,aAAa,GAAG,IAAI,CAElE"}
|
|
@@ -16,6 +16,11 @@
|
|
|
16
16
|
* that does not describe this run, which is the failure this table exists to
|
|
17
17
|
* prevent.
|
|
18
18
|
*
|
|
19
|
+
* Each refusal also carries {@link RefusalFix}, because "no code change clears
|
|
20
|
+
* it" is true of only *some* of them. That field is what lets the gate block on
|
|
21
|
+
* the ones an agent can fix and stand down on the ones it cannot, instead of
|
|
22
|
+
* blocking on both and looping forever on the second.
|
|
23
|
+
*
|
|
19
24
|
* **Every pattern here must be one a check's own output cannot contain.** A
|
|
20
25
|
* false positive is worse than the bug being fixed: it would tell someone their
|
|
21
26
|
* environment is broken while their code is what failed. The patterns are all
|
|
@@ -45,36 +50,47 @@ const REFUSALS = [
|
|
|
45
50
|
{
|
|
46
51
|
marker: 'ERR_PNPM_UNSUPPORTED_ENGINE',
|
|
47
52
|
cause: "the repo's `engines` pin does not match the Node or pnpm running this process, and pnpm refuses to run a script under it",
|
|
53
|
+
fixable: 'environment',
|
|
48
54
|
},
|
|
49
55
|
{
|
|
50
56
|
marker: 'npm error code EBADENGINE',
|
|
51
57
|
cause: "the repo's `engines` pin does not match the Node running this process, and npm is configured `engine-strict`",
|
|
58
|
+
fixable: 'environment',
|
|
52
59
|
},
|
|
53
60
|
{
|
|
54
61
|
marker: 'npm ERR! code EBADENGINE',
|
|
55
62
|
cause: "the repo's `engines` pin does not match the Node running this process, and npm is configured `engine-strict`",
|
|
63
|
+
fixable: 'environment',
|
|
56
64
|
},
|
|
57
65
|
{
|
|
66
|
+
// `repo`, and deliberately: a missing `check` script is one edit away, and it
|
|
67
|
+
// is the one refusal an agent could otherwise *create* to escape the gate.
|
|
68
|
+
// Standing down here would make "delete the check script" a way out.
|
|
58
69
|
marker: 'ERR_PNPM_NO_SCRIPT',
|
|
59
70
|
cause: 'this repo has no `check` script for the gate to run',
|
|
71
|
+
fixable: 'repo',
|
|
60
72
|
},
|
|
61
73
|
{
|
|
62
74
|
marker: 'Missing script:',
|
|
63
75
|
cause: 'this repo has no `check` script for the gate to run',
|
|
76
|
+
fixable: 'repo',
|
|
64
77
|
},
|
|
65
78
|
{
|
|
66
79
|
marker: 'ERR_PNPM_NO_IMPORTER_MANIFEST_FOUND',
|
|
67
80
|
cause: 'there is no package.json here, so the package manager has nothing to run',
|
|
81
|
+
fixable: 'repo',
|
|
68
82
|
},
|
|
69
83
|
{
|
|
70
84
|
// corepack verifying a `packageManager` field against its bundled signing
|
|
71
85
|
// keys. Common after a corepack upgrade, and total: nothing runs.
|
|
72
86
|
marker: 'Cannot find matching keyid',
|
|
73
87
|
cause: 'corepack could not verify the package manager named in `packageManager`, so it never launched',
|
|
88
|
+
fixable: 'environment',
|
|
74
89
|
},
|
|
75
90
|
{
|
|
76
91
|
marker: SPAWN_FAILED_MARKER,
|
|
77
92
|
cause: 'the package-manager binary is not on this process’s PATH',
|
|
93
|
+
fixable: 'environment',
|
|
78
94
|
},
|
|
79
95
|
];
|
|
80
96
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/pm/launch.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"launch.js","sourceRoot":"","sources":["../../src/pm/launch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA8BG;AAEH,yFAAyF;AACzF,MAAM,CAAC,MAAM,mBAAmB,GAAG,4BAA4B,CAAC;AA4BhE;;;;;;;;;;;;;;GAcG;AACH,MAAM,QAAQ,GAA6B;IACzC;QACE,MAAM,EAAE,6BAA6B;QACrC,KAAK,EAAE,0HAA0H;QACjI,OAAO,EAAE,aAAa;KACvB;IACD;QACE,MAAM,EAAE,2BAA2B;QACnC,KAAK,EAAE,8GAA8G;QACrH,OAAO,EAAE,aAAa;KACvB;IACD;QACE,MAAM,EAAE,0BAA0B;QAClC,KAAK,EAAE,8GAA8G;QACrH,OAAO,EAAE,aAAa;KACvB;IACD;QACE,8EAA8E;QAC9E,2EAA2E;QAC3E,qEAAqE;QACrE,MAAM,EAAE,oBAAoB;QAC5B,KAAK,EAAE,qDAAqD;QAC5D,OAAO,EAAE,MAAM;KAChB;IACD;QACE,MAAM,EAAE,iBAAiB;QACzB,KAAK,EAAE,qDAAqD;QAC5D,OAAO,EAAE,MAAM;KAChB;IACD;QACE,MAAM,EAAE,qCAAqC;QAC7C,KAAK,EAAE,0EAA0E;QACjF,OAAO,EAAE,MAAM;KAChB;IACD;QACE,0EAA0E;QAC1E,kEAAkE;QAClE,MAAM,EAAE,4BAA4B;QACpC,KAAK,EAAE,+FAA+F;QACtG,OAAO,EAAE,aAAa;KACvB;IACD;QACE,MAAM,EAAE,mBAAmB;QAC3B,KAAK,EAAE,0DAA0D;QACjE,OAAO,EAAE,aAAa;KACvB;CACF,CAAC;AAEF;;;;;;;;GAQG;AACH,MAAM,UAAU,aAAa,CAAC,MAAc;IAC1C,OAAO,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,IAAI,CAAC;AACjE,CAAC"}
|
|
@@ -51,7 +51,7 @@ export function translateExec(command, args, pm) {
|
|
|
51
51
|
return { command, args: [...args] };
|
|
52
52
|
if (pm === 'pnpm')
|
|
53
53
|
return { command, args: quieted(args) };
|
|
54
|
-
// Drop 'exec'; keep <tool> and its arguments,
|
|
54
|
+
// Drop 'exec'; keep <tool> and its arguments, for example `npx --no-install oxlint --type-aware`.
|
|
55
55
|
if (args[0] === 'exec')
|
|
56
56
|
return { command: EXEC[pm].command, args: [...EXEC[pm].flags, ...args.slice(1)] };
|
|
57
57
|
// `<pm> run <script>` is universal; only the launcher changes.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/pm/translate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;;;;;GAQG;AACH,MAAM,IAAI,GAA2F;IACnG,GAAG,EAAE,EAAE,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC,cAAc,CAAC,EAAE;IAChD,IAAI,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE;IACpC,GAAG,EAAE,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,cAAc,CAAC,EAAE;CAClD,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,eAAe,GAAG,uCAAuC,CAAC;AAEhE;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,aAAa,CAC3B,OAAe,EACf,IAAuB,EACvB,EAAkB;IAElB,IAAI,OAAO,KAAK,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,GAAG,IAAI,CAAC,EAAE,CAAC;IAC5D,IAAI,EAAE,KAAK,MAAM;QAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;IAC3D,
|
|
1
|
+
{"version":3,"file":"translate.js","sourceRoot":"","sources":["../../src/pm/translate.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
* The scores are stryker's own, computed the way stryker computes them, so the
|
|
6
6
|
* numbers here match the ones its reporter printed: `Ignored` (and any error
|
|
7
7
|
* status) leaves the denominator entirely, `Killed` and `Timeout` are detected,
|
|
8
|
-
* `Survived` and `NoCoverage` are not. Inventing a differently
|
|
9
|
-
* than the tool prints is the confidently
|
|
8
|
+
* `Survived` and `NoCoverage` are not. Inventing a differently defined score
|
|
9
|
+
* than the tool prints is the confidently wrong answer this reader exists to
|
|
10
10
|
* prevent, so the arithmetic is pinned to the tool's.
|
|
11
11
|
*
|
|
12
12
|
* **The ranking is the judgment here.** 777 survivors is not a list anyone
|
|
13
13
|
* reads, so files rank by *undetected* count (`Survived` + `NoCoverage`)
|
|
14
14
|
* descending — that is what "where would tests buy the most" means — with the
|
|
15
|
-
* per-file score shown beside it so a small badly
|
|
16
|
-
* next to a large mostly
|
|
15
|
+
* per-file score shown beside it so a small badly tested file is still legible
|
|
16
|
+
* next to a large mostly tested one. Ranking by score alone would put a
|
|
17
17
|
* two-mutant file at the top of a 4453-mutant report; ranking by count alone
|
|
18
18
|
* would say nothing but "the big files are big". Ties break on the worse score,
|
|
19
19
|
* then the path, so the same report always renders the same bytes.
|
|
@@ -5,15 +5,15 @@
|
|
|
5
5
|
* The scores are stryker's own, computed the way stryker computes them, so the
|
|
6
6
|
* numbers here match the ones its reporter printed: `Ignored` (and any error
|
|
7
7
|
* status) leaves the denominator entirely, `Killed` and `Timeout` are detected,
|
|
8
|
-
* `Survived` and `NoCoverage` are not. Inventing a differently
|
|
9
|
-
* than the tool prints is the confidently
|
|
8
|
+
* `Survived` and `NoCoverage` are not. Inventing a differently defined score
|
|
9
|
+
* than the tool prints is the confidently wrong answer this reader exists to
|
|
10
10
|
* prevent, so the arithmetic is pinned to the tool's.
|
|
11
11
|
*
|
|
12
12
|
* **The ranking is the judgment here.** 777 survivors is not a list anyone
|
|
13
13
|
* reads, so files rank by *undetected* count (`Survived` + `NoCoverage`)
|
|
14
14
|
* descending — that is what "where would tests buy the most" means — with the
|
|
15
|
-
* per-file score shown beside it so a small badly
|
|
16
|
-
* next to a large mostly
|
|
15
|
+
* per-file score shown beside it so a small badly tested file is still legible
|
|
16
|
+
* next to a large mostly tested one. Ranking by score alone would put a
|
|
17
17
|
* two-mutant file at the top of a 4453-mutant report; ranking by count alone
|
|
18
18
|
* would say nothing but "the big files are big". Ties break on the worse score,
|
|
19
19
|
* then the path, so the same report always renders the same bytes.
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `checkride recover` — rebuild `checkride.baseline.json` from git history.
|
|
3
|
+
*
|
|
4
|
+
* The incident this exists for: a merge (often an agent resolving a conflict by
|
|
5
|
+
* deleting the "problem" lines) silently drops baseline entries. Missing
|
|
6
|
+
* entries fail closed, so the next run is a wall of red with no explanation and
|
|
7
|
+
* the remedy used to be manual git archaeology. `recover` does the dig: it
|
|
8
|
+
* walks the file's recent commits, dedupes the distinct states, and presents a
|
|
9
|
+
* small candidate set with deltas; `--pick` applies one.
|
|
10
|
+
*
|
|
11
|
+
* Applying writes the file through `writeBaseline` — never `git checkout` — so
|
|
12
|
+
* a restore lands as an ordinary working-tree edit the author reviews and
|
|
13
|
+
* commits. The default write is the UNION of the candidate and the current
|
|
14
|
+
* file: nothing is removed, and a resurrected key that is stale gets pruned by
|
|
15
|
+
* the ratchet on the next full green run. That generosity is also why a bare
|
|
16
|
+
* `checkride baseline` is the wrong remedy here — a re-capture would
|
|
17
|
+
* grandfather genuinely new debt introduced since the damage.
|
|
18
|
+
*
|
|
19
|
+
* Exit codes: 0 listed or applied, 2 usage or environment error — never 1;
|
|
20
|
+
* nothing here is a check failure. Stream discipline: the listing (Markdown or
|
|
21
|
+
* `--json`) is the machine output on stdout; apply confirmations are human
|
|
22
|
+
* prose on stderr.
|
|
23
|
+
*/
|
|
24
|
+
import type { GitRunner } from './baseline/index.js';
|
|
25
|
+
import type { Out } from './orchestrator.js';
|
|
26
|
+
export type RecoverOptions = {
|
|
27
|
+
cwd?: string;
|
|
28
|
+
/** `union`, a listing number, or a sha prefix (≥ 4 hex chars). Absent → list. */
|
|
29
|
+
pick?: string;
|
|
30
|
+
/** Write the picked snapshot verbatim instead of the union with current. */
|
|
31
|
+
exact?: boolean;
|
|
32
|
+
/** Preview what `--pick` would change; write nothing. */
|
|
33
|
+
dryRun?: boolean;
|
|
34
|
+
/** Commits of file history to walk (default {@link DEFAULT_DEPTH}). */
|
|
35
|
+
depth?: number;
|
|
36
|
+
/** Emit the listing / apply result as JSON on stdout. */
|
|
37
|
+
json?: boolean;
|
|
38
|
+
stdout?: Out;
|
|
39
|
+
stderr?: Out;
|
|
40
|
+
/** Injectable for tests. */
|
|
41
|
+
git?: GitRunner;
|
|
42
|
+
};
|
|
43
|
+
export type RecoverResult = {
|
|
44
|
+
ok: boolean;
|
|
45
|
+
exitCode: number;
|
|
46
|
+
};
|
|
47
|
+
export declare function runRecover(options: RecoverOptions): Promise<RecoverResult>;
|
|
48
|
+
//# sourceMappingURL=recover.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recover.d.ts","sourceRoot":"","sources":["../src/recover.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AAEH,OAAO,KAAK,EAAoD,SAAS,EAAe,MAAM,qBAAqB,CAAC;AAcpH,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,mBAAmB,CAAC;AAE7C,MAAM,MAAM,cAAc,GAAG;IAC3B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,iFAAiF;IACjF,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,4EAA4E;IAC5E,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,yDAAyD;IACzD,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,uEAAuE;IACvE,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,yDAAyD;IACzD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,MAAM,CAAC,EAAE,GAAG,CAAC;IACb,4BAA4B;IAC5B,GAAG,CAAC,EAAE,SAAS,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAAE,EAAE,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,CAAC;AAkB9D,wBAAsB,UAAU,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAkBhF"}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `checkride recover` — rebuild `checkride.baseline.json` from git history.
|
|
3
|
+
*
|
|
4
|
+
* The incident this exists for: a merge (often an agent resolving a conflict by
|
|
5
|
+
* deleting the "problem" lines) silently drops baseline entries. Missing
|
|
6
|
+
* entries fail closed, so the next run is a wall of red with no explanation and
|
|
7
|
+
* the remedy used to be manual git archaeology. `recover` does the dig: it
|
|
8
|
+
* walks the file's recent commits, dedupes the distinct states, and presents a
|
|
9
|
+
* small candidate set with deltas; `--pick` applies one.
|
|
10
|
+
*
|
|
11
|
+
* Applying writes the file through `writeBaseline` — never `git checkout` — so
|
|
12
|
+
* a restore lands as an ordinary working-tree edit the author reviews and
|
|
13
|
+
* commits. The default write is the UNION of the candidate and the current
|
|
14
|
+
* file: nothing is removed, and a resurrected key that is stale gets pruned by
|
|
15
|
+
* the ratchet on the next full green run. That generosity is also why a bare
|
|
16
|
+
* `checkride baseline` is the wrong remedy here — a re-capture would
|
|
17
|
+
* grandfather genuinely new debt introduced since the damage.
|
|
18
|
+
*
|
|
19
|
+
* Exit codes: 0 listed or applied, 2 usage or environment error — never 1;
|
|
20
|
+
* nothing here is a check failure. Stream discipline: the listing (Markdown or
|
|
21
|
+
* `--json`) is the machine output on stdout; apply confirmations are human
|
|
22
|
+
* prose on stderr.
|
|
23
|
+
*/
|
|
24
|
+
import { BASELINE_FILE, baselineDirty, baselinesEqual, collectCandidates, countBaselineKeys, DEFAULT_DEPTH, diffBaselines, readBaselineStatus, realGit, unionBaselines, writeBaseline, } from './baseline/index.js';
|
|
25
|
+
const EMPTY_BASELINE = { schema_version: 1, slots: {} };
|
|
26
|
+
/** Keys shown per slot in a `--dry-run` preview before eliding the rest. */
|
|
27
|
+
const PREVIEW_KEYS_PER_SLOT = 20;
|
|
28
|
+
export async function runRecover(options) {
|
|
29
|
+
const cwd = options.cwd ?? process.cwd();
|
|
30
|
+
const stdout = options.stdout ?? process.stdout;
|
|
31
|
+
const stderr = options.stderr ?? process.stderr;
|
|
32
|
+
if (options.exact && options.pick === undefined) {
|
|
33
|
+
throw new Error('recover: --exact requires --pick (it says how to write the picked candidate)');
|
|
34
|
+
}
|
|
35
|
+
const git = options.git ?? realGit(cwd);
|
|
36
|
+
const read = readBaselineStatus(cwd);
|
|
37
|
+
const scan = await collectCandidates(git, read.baseline, options.depth ?? DEFAULT_DEPTH);
|
|
38
|
+
const dirty = await baselineDirty(git);
|
|
39
|
+
const ctx = { cwd, read, scan, dirty, json: options.json ?? false, stdout, stderr };
|
|
40
|
+
if (options.pick === undefined) {
|
|
41
|
+
ctx.stdout.write(ctx.json ? `${JSON.stringify(listingJson(ctx), null, 2)}\n` : renderListing(ctx));
|
|
42
|
+
return { ok: true, exitCode: 0 };
|
|
43
|
+
}
|
|
44
|
+
return apply(ctx, options.pick, options.exact ?? false, options.dryRun ?? false);
|
|
45
|
+
}
|
|
46
|
+
/** Resolve a sha-prefix `--pick` against the listed snapshots. */
|
|
47
|
+
function resolveShaPick(scan, pick) {
|
|
48
|
+
if (!/^[0-9a-f]{4,40}$/i.test(pick)) {
|
|
49
|
+
throw new Error(`recover: --pick expects \`union\`, a listing number, or a sha prefix of at least 4 hex characters, got '${pick}'`);
|
|
50
|
+
}
|
|
51
|
+
const matches = scan.candidates.filter((c) => c.kind === 'snapshot' && c.rev.sha.startsWith(pick.toLowerCase()));
|
|
52
|
+
const first = matches[0];
|
|
53
|
+
if (first && matches.length === 1)
|
|
54
|
+
return first;
|
|
55
|
+
if (matches.length > 1)
|
|
56
|
+
throw new Error(`recover: --pick ${pick} is ambiguous (${matches.length} listed candidates match)`);
|
|
57
|
+
throw new Error(`recover: --pick ${pick} matches none of the listed candidates (run \`checkride recover\` to list them)`);
|
|
58
|
+
}
|
|
59
|
+
/** Resolve `--pick` against the scan: `union`, a 1-based index, or a sha prefix. */
|
|
60
|
+
function resolvePick(scan, pick) {
|
|
61
|
+
if (scan.candidates.length === 0) {
|
|
62
|
+
throw new Error(`recover: no committed history of ${BASELINE_FILE} differs from the current file — nothing to pick`);
|
|
63
|
+
}
|
|
64
|
+
if (pick === 'union') {
|
|
65
|
+
const union = scan.candidates.find((c) => c.kind === 'union');
|
|
66
|
+
if (!union)
|
|
67
|
+
throw new Error('recover: the union of recent history adds nothing to the current baseline');
|
|
68
|
+
return union;
|
|
69
|
+
}
|
|
70
|
+
if (/^\d+$/.test(pick)) {
|
|
71
|
+
const candidate = scan.candidates[Number(pick) - 1];
|
|
72
|
+
if (!candidate)
|
|
73
|
+
throw new Error(`recover: --pick ${pick} is out of range (1..${scan.candidates.length})`);
|
|
74
|
+
return candidate;
|
|
75
|
+
}
|
|
76
|
+
return resolveShaPick(scan, pick);
|
|
77
|
+
}
|
|
78
|
+
/** The human name of a pick, for confirmations: `union of N snapshot(s)` or `snapshot <sha>`. */
|
|
79
|
+
function describe(candidate) {
|
|
80
|
+
return candidate.kind === 'union' ? `union of ${candidate.folded} snapshot(s)` : `snapshot ${candidate.rev.shortSha}`;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Turn `--pick` into an {@link Apply}. The union write is dirty-safe by
|
|
84
|
+
* construction (current keys survive), so only `--exact` — which discards
|
|
85
|
+
* keys, unrecoverable once overwritten — is gated on a clean file.
|
|
86
|
+
*/
|
|
87
|
+
function resolveApply(ctx, pick, exact, dryRun) {
|
|
88
|
+
const candidate = resolvePick(ctx.scan, pick);
|
|
89
|
+
const current = ctx.read.baseline;
|
|
90
|
+
if (exact && ctx.dirty && !dryRun) {
|
|
91
|
+
throw new Error(`recover: ${BASELINE_FILE} has uncommitted changes and --exact would discard them — commit or stash first, or drop --exact (the default union keeps them)`);
|
|
92
|
+
}
|
|
93
|
+
const target = exact ? candidate.baseline : unionBaselines(current === null ? [candidate.baseline] : [current, candidate.baseline]);
|
|
94
|
+
return { candidate, exact, target, delta: diffBaselines(current, target) };
|
|
95
|
+
}
|
|
96
|
+
/** Emit an apply outcome: the machine shape on stdout when `--json`, else nothing. */
|
|
97
|
+
function emitApply(ctx, action, a) {
|
|
98
|
+
if (ctx.json)
|
|
99
|
+
ctx.stdout.write(`${JSON.stringify(applyJson(action, a), null, 2)}\n`);
|
|
100
|
+
return { ok: true, exitCode: 0 };
|
|
101
|
+
}
|
|
102
|
+
async function apply(ctx, pick, exact, dryRun) {
|
|
103
|
+
const a = resolveApply(ctx, pick, exact, dryRun);
|
|
104
|
+
if (dryRun) {
|
|
105
|
+
if (!ctx.json)
|
|
106
|
+
ctx.stdout.write(renderPreview(a));
|
|
107
|
+
return emitApply(ctx, 'dry-run', a);
|
|
108
|
+
}
|
|
109
|
+
if (baselinesEqual(a.target, ctx.read.baseline ?? EMPTY_BASELINE)) {
|
|
110
|
+
writeLine(ctx.stderr, `recover: nothing to write — ${describe(a.candidate)} changes nothing against the current file`);
|
|
111
|
+
return emitApply(ctx, 'noop', a);
|
|
112
|
+
}
|
|
113
|
+
await writeBaseline(ctx.cwd, a.target);
|
|
114
|
+
const dropped = a.delta.absentCount > 0 ? `, −${a.delta.absentCount} dropped (--exact)` : '';
|
|
115
|
+
writeLine(ctx.stderr, `recover: wrote ${BASELINE_FILE} — +${a.delta.restoredCount} key(s) restored${dropped} (${a.exact ? 'exact copy of' : 'union with'} ${describe(a.candidate)}); review with \`git diff\` and commit`);
|
|
116
|
+
return emitApply(ctx, 'written', a);
|
|
117
|
+
}
|
|
118
|
+
function writeLine(out, line) {
|
|
119
|
+
out.write(`${line}\n`);
|
|
120
|
+
}
|
|
121
|
+
/** The `- file:` line — the reader's first question is what state the file is in. */
|
|
122
|
+
function fileLine(read, dirty) {
|
|
123
|
+
if (read.state === 'absent')
|
|
124
|
+
return `- file: \`${BASELINE_FILE}\` — ABSENT`;
|
|
125
|
+
if (read.state === 'unparseable')
|
|
126
|
+
return `- file: \`${BASELINE_FILE}\` — present but unparseable (treated as no baseline)`;
|
|
127
|
+
const baseline = read.baseline ?? EMPTY_BASELINE;
|
|
128
|
+
const keys = countBaselineKeys(baseline);
|
|
129
|
+
const slots = Object.keys(baseline.slots).length;
|
|
130
|
+
return `- file: \`${BASELINE_FILE}\` — present, ${keys} key(s) across ${slots} slot(s)${dirty ? ', with uncommitted changes' : ''}`;
|
|
131
|
+
}
|
|
132
|
+
function candidateRow(candidate, index, current) {
|
|
133
|
+
const delta = diffBaselines(current, candidate.baseline);
|
|
134
|
+
const keys = countBaselineKeys(candidate.baseline);
|
|
135
|
+
const vs = `+${delta.restoredCount} / −${delta.absentCount}`;
|
|
136
|
+
if (candidate.kind === 'union') {
|
|
137
|
+
return `| ${index} | union (${candidate.folded} snapshot(s) + current) | — | — | — | ${keys} | ${vs} |`;
|
|
138
|
+
}
|
|
139
|
+
const { rev } = candidate;
|
|
140
|
+
return `| ${index} | snapshot | ${rev.shortSha} | ${rev.date.slice(0, 10)} | ${rev.author} | ${keys} | ${vs} |`;
|
|
141
|
+
}
|
|
142
|
+
function renderListing(ctx) {
|
|
143
|
+
const { read, scan, dirty } = ctx;
|
|
144
|
+
const lines = ['# checkride recover — baseline candidates from git history', ''];
|
|
145
|
+
lines.push(fileLine(read, dirty));
|
|
146
|
+
const skipped = scan.skipped.length > 0 ? `; skipped ${scan.skipped.length} unreadable snapshot(s): ${scan.skipped.join(', ')}` : '';
|
|
147
|
+
lines.push(`- walked: ${scan.walked} commit(s)${skipped}`);
|
|
148
|
+
if (scan.shallow)
|
|
149
|
+
lines.push('- note: history is shallow (truncated); `git fetch --unshallow` reveals more');
|
|
150
|
+
lines.push('');
|
|
151
|
+
if (scan.walked === 0) {
|
|
152
|
+
lines.push(`No committed history of ${BASELINE_FILE} — nothing to recover.`, '');
|
|
153
|
+
return lines.join('\n');
|
|
154
|
+
}
|
|
155
|
+
if (scan.candidates.length === 0) {
|
|
156
|
+
lines.push('The current file matches every recent committed state — nothing to recover.', '');
|
|
157
|
+
return lines.join('\n');
|
|
158
|
+
}
|
|
159
|
+
lines.push('| # | candidate | commit | date | author | keys | vs current |');
|
|
160
|
+
lines.push('| - | --------- | ------ | ---- | ------ | ---- | ---------- |');
|
|
161
|
+
scan.candidates.forEach((candidate, i) => lines.push(candidateRow(candidate, i + 1, read.baseline)));
|
|
162
|
+
lines.push('', '`vs current` is +keys an apply restores / −keys only `--exact` would drop.', '', 'Apply: `checkride recover --pick <#>` by number, or `--pick <sha>` by commit', '(stable across invocations — prefer it in scripts). Preview with `--dry-run`.', '', 'The default write is the union of the candidate and the current file: nothing', 'is removed, and a stale resurrected key is pruned by the ratchet on the next', 'full green run. `--exact` writes the snapshot verbatim instead.', '');
|
|
163
|
+
return lines.join('\n');
|
|
164
|
+
}
|
|
165
|
+
/** One preview section: a slot's changed keys, elided past the cap. */
|
|
166
|
+
function pushKeySection(lines, slot, keys, verb) {
|
|
167
|
+
lines.push(`## ${slot} — ${keys.length} ${verb}`, '');
|
|
168
|
+
for (const key of keys.slice(0, PREVIEW_KEYS_PER_SLOT))
|
|
169
|
+
lines.push(`- ${key}`);
|
|
170
|
+
if (keys.length > PREVIEW_KEYS_PER_SLOT)
|
|
171
|
+
lines.push(`- … and ${keys.length - PREVIEW_KEYS_PER_SLOT} more`);
|
|
172
|
+
lines.push('');
|
|
173
|
+
}
|
|
174
|
+
/** The `--dry-run` preview: the per-slot keys an apply would restore (and drop, under `--exact`). */
|
|
175
|
+
function renderPreview(a) {
|
|
176
|
+
const lines = [`# checkride recover — dry run: ${describe(a.candidate)}${a.exact ? ' (--exact)' : ''}`, ''];
|
|
177
|
+
lines.push(`Would write ${BASELINE_FILE} with ${countBaselineKeys(a.target)} key(s): +${a.delta.restoredCount} restored, −${a.delta.absentCount} dropped.`, '');
|
|
178
|
+
for (const [slot, keys] of Object.entries(a.delta.restored))
|
|
179
|
+
pushKeySection(lines, slot, keys, 'restored');
|
|
180
|
+
for (const [slot, keys] of Object.entries(a.delta.absent))
|
|
181
|
+
pushKeySection(lines, slot, keys, 'dropped under --exact');
|
|
182
|
+
if (a.delta.restoredCount === 0 && a.delta.absentCount === 0)
|
|
183
|
+
lines.push('No changes against the current file.', '');
|
|
184
|
+
return lines.join('\n');
|
|
185
|
+
}
|
|
186
|
+
/** The machine listing. Documented in help/README; not part of the artifact contract. */
|
|
187
|
+
function listingJson(ctx) {
|
|
188
|
+
const { read, scan, dirty } = ctx;
|
|
189
|
+
return {
|
|
190
|
+
schema_version: 1,
|
|
191
|
+
file: {
|
|
192
|
+
state: read.state,
|
|
193
|
+
keys: read.baseline === null ? 0 : countBaselineKeys(read.baseline),
|
|
194
|
+
dirty,
|
|
195
|
+
},
|
|
196
|
+
walked: scan.walked,
|
|
197
|
+
shallow: scan.shallow,
|
|
198
|
+
skipped: scan.skipped,
|
|
199
|
+
candidates: scan.candidates.map((candidate, i) => {
|
|
200
|
+
const delta = diffBaselines(read.baseline, candidate.baseline);
|
|
201
|
+
const common = { index: i + 1, keys: countBaselineKeys(candidate.baseline), restored: delta.restoredCount, absent: delta.absentCount };
|
|
202
|
+
return candidate.kind === 'union'
|
|
203
|
+
? { kind: 'union', folded: candidate.folded, ...common }
|
|
204
|
+
: { kind: 'snapshot', sha: candidate.rev.sha, short_sha: candidate.rev.shortSha, date: candidate.rev.date, author: candidate.rev.author, subject: candidate.rev.subject, ...common };
|
|
205
|
+
}),
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
function applyJson(action, a) {
|
|
209
|
+
return {
|
|
210
|
+
schema_version: 1,
|
|
211
|
+
action,
|
|
212
|
+
file: BASELINE_FILE,
|
|
213
|
+
pick: a.candidate.kind === 'union' ? 'union' : a.candidate.rev.sha,
|
|
214
|
+
mode: a.exact ? 'exact' : 'union',
|
|
215
|
+
keys: countBaselineKeys(a.target),
|
|
216
|
+
restored: a.delta.restoredCount,
|
|
217
|
+
dropped: a.delta.absentCount,
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
//# sourceMappingURL=recover.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"recover.js","sourceRoot":"","sources":["../src/recover.ts"],"names":[],"mappings":"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"}
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* for every literal subpath:
|
|
10
10
|
*
|
|
11
11
|
* - the built entry `await import()`s without throwing, and (for a dual
|
|
12
|
-
* package,
|
|
12
|
+
* package, that is, a subpath carrying an explicit `require` condition) also
|
|
13
13
|
* `require()`s cleanly — both through package **self-reference**
|
|
14
14
|
* (`import '<pkg>/<subpath>'`), exercising the real `exports`-map resolution
|
|
15
15
|
* a consumer would hit;
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* for every literal subpath:
|
|
10
10
|
*
|
|
11
11
|
* - the built entry `await import()`s without throwing, and (for a dual
|
|
12
|
-
* package,
|
|
12
|
+
* package, that is, a subpath carrying an explicit `require` condition) also
|
|
13
13
|
* `require()`s cleanly — both through package **self-reference**
|
|
14
14
|
* (`import '<pkg>/<subpath>'`), exercising the real `exports`-map resolution
|
|
15
15
|
* a consumer would hit;
|
|
@@ -56,7 +56,7 @@ export declare const FENCE_CLOSE_RE: RegExp;
|
|
|
56
56
|
* One `ts`/`typescript` fenced block extracted from a doc. `code` is the fence
|
|
57
57
|
* body verbatim (no trailing newline — {@link checkSnippets} appends one on write); `startLine`
|
|
58
58
|
* is the 1-based line of the opening fence; `checked` is true when a
|
|
59
|
-
* {@link CHECK_MARKER_RE} marker sits on the immediately
|
|
59
|
+
* {@link CHECK_MARKER_RE} marker sits on the immediately preceding line.
|
|
60
60
|
*/
|
|
61
61
|
export type Snippet = {
|
|
62
62
|
code: string;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "checkride",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.12.2",
|
|
4
4
|
"description": "An agent harness for code repositories: one command that is the definition of done, plus mechanically enforced module boundaries. TypeScript-first, not TypeScript-only.",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"author": "Rob McLarty",
|
|
@@ -70,10 +70,11 @@
|
|
|
70
70
|
"@stryker-mutator/vitest-runner": "9.6.1",
|
|
71
71
|
"@types/node": "22.20.1",
|
|
72
72
|
"@vitest/coverage-v8": "4.1.10",
|
|
73
|
+
"@vvago/vale": "3.17.0",
|
|
73
74
|
"ajv": "8.20.0",
|
|
74
75
|
"cspell": "10.0.1",
|
|
75
76
|
"fallow": "3.9.1",
|
|
76
|
-
"markdownlint-cli2": "0.23.
|
|
77
|
+
"markdownlint-cli2": "0.23.2",
|
|
77
78
|
"oxlint": "1.74.0",
|
|
78
79
|
"oxlint-tsgolint": "0.25.0",
|
|
79
80
|
"publint": "0.3.22",
|
|
@@ -42,12 +42,16 @@
|
|
|
42
42
|
"changed": {
|
|
43
43
|
"type": "boolean",
|
|
44
44
|
"description": "Affected-only mode for the gate, as --changed."
|
|
45
|
+
},
|
|
46
|
+
"preflight": {
|
|
47
|
+
"type": "string",
|
|
48
|
+
"description": "Repo-relative path to a script the generated stop-hook gate runs before checkride — the one supported seam for wrapping the gate, and the only one that survives a refresh (agent-setup rewrites the generated script and re-points the harness config, but re-reads this file). Exit 0 runs the gate; exit 2 blocks the turn; any other exit stands the gate down. Either non-zero branch uses the script's stdout as the message and never runs checkride."
|
|
45
49
|
}
|
|
46
50
|
}
|
|
47
51
|
},
|
|
48
52
|
"checks": {
|
|
49
53
|
"type": "object",
|
|
50
|
-
"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 — set optIn:true on the entry to configure it without opting in (run it only with --all/--include).",
|
|
54
|
+
"description": "Per-slot configuration. A key that matches a catalogue slot (types, format, lint, struct, dead, dupes, health, test, docs, links, spell, prose, mutation, security, build, publint, attw, pack, smoke, snippets) configures that slot; any other key is a custom check that runs alongside the catalogue. Naming an opt-in slot (format, dupes, health, prose, mutation, security, build, publint, attw, pack, smoke, snippets) here also opts it into the default run — set optIn:true on the entry to configure it without opting in (run it only with --all/--include).",
|
|
51
55
|
"additionalProperties": {
|
|
52
56
|
"$ref": "#/definitions/slotConfig"
|
|
53
57
|
}
|
|
@@ -112,6 +116,10 @@
|
|
|
112
116
|
"profile": {
|
|
113
117
|
"type": "string",
|
|
114
118
|
"description": "attw slot only: append --profile <name> (e.g. esm-only) to the attw invocation — a shortcut for retyping the full args."
|
|
119
|
+
},
|
|
120
|
+
"exemplars": {
|
|
121
|
+
"type": "string",
|
|
122
|
+
"description": "prose slot only: repo-relative directory of hand-written voice exemplars. The check fails when the directory is missing or empty, and agent-setup adds an AGENTS.md stanza section telling writing sessions to read and imitate the exemplars (never edit them)."
|
|
115
123
|
}
|
|
116
124
|
}
|
|
117
125
|
},
|
|
@@ -254,4 +254,12 @@ fine when the lanes are genuinely independent; five means you re-ranked nothing.
|
|
|
254
254
|
then exactly one file. If you find yourself opening a second artifact before
|
|
255
255
|
naming a cause, that is exploration, not triage.
|
|
256
256
|
- **It does not touch the baseline.** `checkride baseline` hides findings
|
|
257
|
-
permanently; that is the human's call, never a triage step.
|
|
257
|
+
permanently; that is the human's call, never a triage step. One exception in
|
|
258
|
+
what you *propose*: when the run's stderr carries a
|
|
259
|
+
`hint: N of M new finding(s) were grandfathered until <sha>` line — or a
|
|
260
|
+
`baseline: … present but unparseable` warning — the wall of red is a
|
|
261
|
+
clobbered baseline, not new debt. The remedy to name is `checkride recover`
|
|
262
|
+
(restores the dropped entries from git history, additively), never
|
|
263
|
+
`checkride baseline`, whose re-capture would grandfather genuinely-new
|
|
264
|
+
findings along with the lost ones. Proposing it is still the deliverable;
|
|
265
|
+
running it is still the human's call.
|