plumbbob 0.9.2 → 0.9.5

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.
Files changed (279) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +15 -13
  3. package/dist/cli-core.js +298 -24
  4. package/dist/lib/check.js +46 -13
  5. package/dist/lib/intent.js +1 -1
  6. package/dist/lib/latch.js +3 -3
  7. package/dist/lib/reentry.js +70 -0
  8. package/dist/verbs/agent.js +5 -4
  9. package/dist/verbs/check.js +6 -2
  10. package/dist/verbs/doctor.js +4 -4
  11. package/dist/verbs/finish.js +1 -1
  12. package/dist/verbs/recover.js +297 -0
  13. package/dist/verbs/revert.js +2 -2
  14. package/dist/verbs/spike.js +8 -2
  15. package/hooks/post-edit.sh +4 -4
  16. package/hooks/pre-bash-commit.sh +3 -3
  17. package/node_modules/checkride/.claude-plugin/plugin.json +11 -0
  18. package/node_modules/checkride/CHANGELOG.md +1003 -0
  19. package/node_modules/checkride/LICENSE +201 -21
  20. package/node_modules/checkride/README.md +171 -30
  21. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts +15 -0
  22. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts.map +1 -0
  23. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js +17 -0
  24. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js.map +1 -0
  25. package/node_modules/checkride/dist/adapters.d.ts +18 -6
  26. package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
  27. package/node_modules/checkride/dist/adapters.js +42 -23
  28. package/node_modules/checkride/dist/adapters.js.map +1 -1
  29. package/node_modules/checkride/dist/agent-setup/claude.d.ts +88 -0
  30. package/node_modules/checkride/dist/agent-setup/claude.d.ts.map +1 -0
  31. package/node_modules/checkride/dist/agent-setup/claude.js +305 -0
  32. package/node_modules/checkride/dist/agent-setup/claude.js.map +1 -0
  33. package/node_modules/checkride/dist/agent-setup/command.d.ts +43 -0
  34. package/node_modules/checkride/dist/agent-setup/command.d.ts.map +1 -0
  35. package/node_modules/checkride/dist/agent-setup/command.js +77 -0
  36. package/node_modules/checkride/dist/agent-setup/command.js.map +1 -0
  37. package/node_modules/checkride/dist/agent-setup/cursor.d.ts +61 -0
  38. package/node_modules/checkride/dist/agent-setup/cursor.d.ts.map +1 -0
  39. package/node_modules/checkride/dist/agent-setup/cursor.js +189 -0
  40. package/node_modules/checkride/dist/agent-setup/cursor.js.map +1 -0
  41. package/node_modules/checkride/dist/agent-setup/files.d.ts +50 -0
  42. package/node_modules/checkride/dist/agent-setup/files.d.ts.map +1 -0
  43. package/node_modules/checkride/dist/agent-setup/files.js +80 -0
  44. package/node_modules/checkride/dist/agent-setup/files.js.map +1 -0
  45. package/node_modules/checkride/dist/agent-setup/harness.d.ts +101 -0
  46. package/node_modules/checkride/dist/agent-setup/harness.d.ts.map +1 -0
  47. package/node_modules/checkride/dist/agent-setup/harness.js +84 -0
  48. package/node_modules/checkride/dist/agent-setup/harness.js.map +1 -0
  49. package/node_modules/checkride/dist/agent-setup/hook.d.ts +45 -52
  50. package/node_modules/checkride/dist/agent-setup/hook.d.ts.map +1 -1
  51. package/node_modules/checkride/dist/agent-setup/hook.js +64 -95
  52. package/node_modules/checkride/dist/agent-setup/hook.js.map +1 -1
  53. package/node_modules/checkride/dist/agent-setup/index.d.ts +10 -4
  54. package/node_modules/checkride/dist/agent-setup/index.d.ts.map +1 -1
  55. package/node_modules/checkride/dist/agent-setup/index.js +9 -4
  56. package/node_modules/checkride/dist/agent-setup/index.js.map +1 -1
  57. package/node_modules/checkride/dist/agent-setup/scripts.d.ts +58 -0
  58. package/node_modules/checkride/dist/agent-setup/scripts.d.ts.map +1 -0
  59. package/node_modules/checkride/dist/agent-setup/scripts.js +299 -0
  60. package/node_modules/checkride/dist/agent-setup/scripts.js.map +1 -0
  61. package/node_modules/checkride/dist/agent-setup/skills.d.ts +31 -0
  62. package/node_modules/checkride/dist/agent-setup/skills.d.ts.map +1 -0
  63. package/node_modules/checkride/dist/agent-setup/skills.js +56 -0
  64. package/node_modules/checkride/dist/agent-setup/skills.js.map +1 -0
  65. package/node_modules/checkride/dist/artifacts/configured.d.ts +30 -0
  66. package/node_modules/checkride/dist/artifacts/configured.d.ts.map +1 -0
  67. package/node_modules/checkride/dist/artifacts/configured.js +45 -0
  68. package/node_modules/checkride/dist/artifacts/configured.js.map +1 -0
  69. package/node_modules/checkride/dist/artifacts/format.d.ts +33 -0
  70. package/node_modules/checkride/dist/artifacts/format.d.ts.map +1 -0
  71. package/node_modules/checkride/dist/artifacts/format.js +56 -0
  72. package/node_modules/checkride/dist/artifacts/format.js.map +1 -0
  73. package/node_modules/checkride/dist/artifacts/freshness.d.ts +32 -0
  74. package/node_modules/checkride/dist/artifacts/freshness.d.ts.map +1 -0
  75. package/node_modules/checkride/dist/artifacts/freshness.js +37 -0
  76. package/node_modules/checkride/dist/artifacts/freshness.js.map +1 -0
  77. package/node_modules/checkride/dist/artifacts/index.d.ts +22 -0
  78. package/node_modules/checkride/dist/artifacts/index.d.ts.map +1 -0
  79. package/node_modules/checkride/dist/artifacts/index.js +19 -0
  80. package/node_modules/checkride/dist/artifacts/index.js.map +1 -0
  81. package/node_modules/checkride/dist/artifacts/json.d.ts +31 -0
  82. package/node_modules/checkride/dist/artifacts/json.d.ts.map +1 -0
  83. package/node_modules/checkride/dist/artifacts/json.js +47 -0
  84. package/node_modules/checkride/dist/artifacts/json.js.map +1 -0
  85. package/node_modules/checkride/dist/artifacts/raw.d.ts +60 -0
  86. package/node_modules/checkride/dist/artifacts/raw.d.ts.map +1 -0
  87. package/node_modules/checkride/dist/artifacts/raw.js +91 -0
  88. package/node_modules/checkride/dist/artifacts/raw.js.map +1 -0
  89. package/node_modules/checkride/dist/artifacts/summary.d.ts +69 -0
  90. package/node_modules/checkride/dist/artifacts/summary.d.ts.map +1 -0
  91. package/node_modules/checkride/dist/artifacts/summary.js +108 -0
  92. package/node_modules/checkride/dist/artifacts/summary.js.map +1 -0
  93. package/node_modules/checkride/dist/atomic.d.ts +16 -1
  94. package/node_modules/checkride/dist/atomic.d.ts.map +1 -1
  95. package/node_modules/checkride/dist/atomic.js +25 -3
  96. package/node_modules/checkride/dist/atomic.js.map +1 -1
  97. package/node_modules/checkride/dist/baseline/fallow.d.ts +9 -5
  98. package/node_modules/checkride/dist/baseline/fallow.d.ts.map +1 -1
  99. package/node_modules/checkride/dist/baseline/fallow.js +161 -58
  100. package/node_modules/checkride/dist/baseline/fallow.js.map +1 -1
  101. package/node_modules/checkride/dist/baseline/fingerprint.d.ts +7 -7
  102. package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -1
  103. package/node_modules/checkride/dist/baseline/fingerprint.js +16 -19
  104. package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -1
  105. package/node_modules/checkride/dist/baseline/index.d.ts +4 -4
  106. package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -1
  107. package/node_modules/checkride/dist/baseline/index.js +4 -4
  108. package/node_modules/checkride/dist/baseline/index.js.map +1 -1
  109. package/node_modules/checkride/dist/baseline/store.d.ts +12 -4
  110. package/node_modules/checkride/dist/baseline/store.d.ts.map +1 -1
  111. package/node_modules/checkride/dist/baseline/store.js +16 -9
  112. package/node_modules/checkride/dist/baseline/store.js.map +1 -1
  113. package/node_modules/checkride/dist/baseline-command.d.ts +5 -5
  114. package/node_modules/checkride/dist/baseline-command.js +7 -7
  115. package/node_modules/checkride/dist/baseline-command.js.map +1 -1
  116. package/node_modules/checkride/dist/cli.d.ts +17 -4
  117. package/node_modules/checkride/dist/cli.d.ts.map +1 -1
  118. package/node_modules/checkride/dist/cli.js +259 -18
  119. package/node_modules/checkride/dist/cli.js.map +1 -1
  120. package/node_modules/checkride/dist/config.d.ts +84 -8
  121. package/node_modules/checkride/dist/config.d.ts.map +1 -1
  122. package/node_modules/checkride/dist/config.js +122 -18
  123. package/node_modules/checkride/dist/config.js.map +1 -1
  124. package/node_modules/checkride/dist/digest/digest.d.ts +5 -5
  125. package/node_modules/checkride/dist/digest/digest.js +5 -5
  126. package/node_modules/checkride/dist/digest/index.d.ts +2 -2
  127. package/node_modules/checkride/dist/digest/index.js +2 -2
  128. package/node_modules/checkride/dist/doctor.d.ts +25 -6
  129. package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
  130. package/node_modules/checkride/dist/doctor.js +193 -27
  131. package/node_modules/checkride/dist/doctor.js.map +1 -1
  132. package/node_modules/checkride/dist/gate.d.ts +135 -0
  133. package/node_modules/checkride/dist/gate.d.ts.map +1 -0
  134. package/node_modules/checkride/dist/gate.js +490 -0
  135. package/node_modules/checkride/dist/gate.js.map +1 -0
  136. package/node_modules/checkride/dist/init.d.ts +72 -12
  137. package/node_modules/checkride/dist/init.d.ts.map +1 -1
  138. package/node_modules/checkride/dist/init.js +324 -81
  139. package/node_modules/checkride/dist/init.js.map +1 -1
  140. package/node_modules/checkride/dist/json.d.ts +21 -0
  141. package/node_modules/checkride/dist/json.d.ts.map +1 -0
  142. package/node_modules/checkride/dist/json.js +21 -0
  143. package/node_modules/checkride/dist/json.js.map +1 -0
  144. package/node_modules/checkride/dist/links.d.ts +31 -5
  145. package/node_modules/checkride/dist/links.d.ts.map +1 -1
  146. package/node_modules/checkride/dist/links.js +141 -32
  147. package/node_modules/checkride/dist/links.js.map +1 -1
  148. package/node_modules/checkride/dist/node-pin.d.ts +129 -0
  149. package/node_modules/checkride/dist/node-pin.d.ts.map +1 -0
  150. package/node_modules/checkride/dist/node-pin.js +211 -0
  151. package/node_modules/checkride/dist/node-pin.js.map +1 -0
  152. package/node_modules/checkride/dist/orchestrator.d.ts +40 -10
  153. package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
  154. package/node_modules/checkride/dist/orchestrator.js +196 -102
  155. package/node_modules/checkride/dist/orchestrator.js.map +1 -1
  156. package/node_modules/checkride/dist/pack.d.ts +8 -9
  157. package/node_modules/checkride/dist/pack.d.ts.map +1 -1
  158. package/node_modules/checkride/dist/pack.js +53 -17
  159. package/node_modules/checkride/dist/pack.js.map +1 -1
  160. package/node_modules/checkride/dist/pm/detect.d.ts +6 -1
  161. package/node_modules/checkride/dist/pm/detect.d.ts.map +1 -1
  162. package/node_modules/checkride/dist/pm/detect.js +6 -1
  163. package/node_modules/checkride/dist/pm/detect.js.map +1 -1
  164. package/node_modules/checkride/dist/pm/index.d.ts +6 -2
  165. package/node_modules/checkride/dist/pm/index.d.ts.map +1 -1
  166. package/node_modules/checkride/dist/pm/index.js +6 -2
  167. package/node_modules/checkride/dist/pm/index.js.map +1 -1
  168. package/node_modules/checkride/dist/pm/launch.d.ts +51 -0
  169. package/node_modules/checkride/dist/pm/launch.d.ts.map +1 -0
  170. package/node_modules/checkride/dist/pm/launch.js +92 -0
  171. package/node_modules/checkride/dist/pm/launch.js.map +1 -0
  172. package/node_modules/checkride/dist/pm/tools.d.ts +73 -0
  173. package/node_modules/checkride/dist/pm/tools.d.ts.map +1 -0
  174. package/node_modules/checkride/dist/pm/tools.js +124 -0
  175. package/node_modules/checkride/dist/pm/tools.js.map +1 -0
  176. package/node_modules/checkride/dist/pm/translate.d.ts +35 -9
  177. package/node_modules/checkride/dist/pm/translate.d.ts.map +1 -1
  178. package/node_modules/checkride/dist/pm/translate.js +78 -18
  179. package/node_modules/checkride/dist/pm/translate.js.map +1 -1
  180. package/node_modules/checkride/dist/proc.d.ts +30 -0
  181. package/node_modules/checkride/dist/proc.d.ts.map +1 -0
  182. package/node_modules/checkride/dist/proc.js +42 -0
  183. package/node_modules/checkride/dist/proc.js.map +1 -0
  184. package/node_modules/checkride/dist/qa/cli.d.ts +20 -0
  185. package/node_modules/checkride/dist/qa/cli.d.ts.map +1 -0
  186. package/node_modules/checkride/dist/qa/cli.js +24 -0
  187. package/node_modules/checkride/dist/qa/cli.js.map +1 -0
  188. package/node_modules/checkride/dist/qa/dead.d.ts +39 -0
  189. package/node_modules/checkride/dist/qa/dead.d.ts.map +1 -0
  190. package/node_modules/checkride/dist/qa/dead.js +88 -0
  191. package/node_modules/checkride/dist/qa/dead.js.map +1 -0
  192. package/node_modules/checkride/dist/qa/dupes.d.ts +45 -0
  193. package/node_modules/checkride/dist/qa/dupes.d.ts.map +1 -0
  194. package/node_modules/checkride/dist/qa/dupes.js +62 -0
  195. package/node_modules/checkride/dist/qa/dupes.js.map +1 -0
  196. package/node_modules/checkride/dist/qa/health.d.ts +85 -0
  197. package/node_modules/checkride/dist/qa/health.d.ts.map +1 -0
  198. package/node_modules/checkride/dist/qa/health.js +109 -0
  199. package/node_modules/checkride/dist/qa/health.js.map +1 -0
  200. package/node_modules/checkride/dist/qa/index.d.ts +23 -0
  201. package/node_modules/checkride/dist/qa/index.d.ts.map +1 -0
  202. package/node_modules/checkride/dist/qa/index.js +22 -0
  203. package/node_modules/checkride/dist/qa/index.js.map +1 -0
  204. package/node_modules/checkride/dist/qa/mutation.d.ts +80 -0
  205. package/node_modules/checkride/dist/qa/mutation.d.ts.map +1 -0
  206. package/node_modules/checkride/dist/qa/mutation.js +195 -0
  207. package/node_modules/checkride/dist/qa/mutation.js.map +1 -0
  208. package/node_modules/checkride/dist/qa/qa.d.ts +71 -0
  209. package/node_modules/checkride/dist/qa/qa.d.ts.map +1 -0
  210. package/node_modules/checkride/dist/qa/qa.js +158 -0
  211. package/node_modules/checkride/dist/qa/qa.js.map +1 -0
  212. package/node_modules/checkride/dist/qa/read.d.ts +40 -0
  213. package/node_modules/checkride/dist/qa/read.d.ts.map +1 -0
  214. package/node_modules/checkride/dist/qa/read.js +47 -0
  215. package/node_modules/checkride/dist/qa/read.js.map +1 -0
  216. package/node_modules/checkride/dist/qa/render.d.ts +26 -0
  217. package/node_modules/checkride/dist/qa/render.d.ts.map +1 -0
  218. package/node_modules/checkride/dist/qa/render.js +310 -0
  219. package/node_modules/checkride/dist/qa/render.js.map +1 -0
  220. package/node_modules/checkride/dist/security.d.ts +45 -0
  221. package/node_modules/checkride/dist/security.d.ts.map +1 -0
  222. package/node_modules/checkride/dist/security.js +86 -0
  223. package/node_modules/checkride/dist/security.js.map +1 -0
  224. package/node_modules/checkride/dist/smoke.d.ts +5 -5
  225. package/node_modules/checkride/dist/smoke.js +5 -5
  226. package/node_modules/checkride/dist/snippets.d.ts +26 -29
  227. package/node_modules/checkride/dist/snippets.d.ts.map +1 -1
  228. package/node_modules/checkride/dist/snippets.js +26 -30
  229. package/node_modules/checkride/dist/snippets.js.map +1 -1
  230. package/node_modules/checkride/dist/tool-json.d.ts +33 -0
  231. package/node_modules/checkride/dist/tool-json.d.ts.map +1 -0
  232. package/node_modules/checkride/dist/tool-json.js +58 -0
  233. package/node_modules/checkride/dist/tool-json.js.map +1 -0
  234. package/node_modules/checkride/dist/triage/cli.d.ts +21 -0
  235. package/node_modules/checkride/dist/triage/cli.d.ts.map +1 -0
  236. package/node_modules/checkride/dist/triage/cli.js +26 -0
  237. package/node_modules/checkride/dist/triage/cli.js.map +1 -0
  238. package/node_modules/checkride/dist/triage/doctor-fold.d.ts +51 -0
  239. package/node_modules/checkride/dist/triage/doctor-fold.d.ts.map +1 -0
  240. package/node_modules/checkride/dist/triage/doctor-fold.js +88 -0
  241. package/node_modules/checkride/dist/triage/doctor-fold.js.map +1 -0
  242. package/node_modules/checkride/dist/triage/env.d.ts +54 -0
  243. package/node_modules/checkride/dist/triage/env.d.ts.map +1 -0
  244. package/node_modules/checkride/dist/triage/env.js +81 -0
  245. package/node_modules/checkride/dist/triage/env.js.map +1 -0
  246. package/node_modules/checkride/dist/triage/gate.d.ts +61 -0
  247. package/node_modules/checkride/dist/triage/gate.d.ts.map +1 -0
  248. package/node_modules/checkride/dist/triage/gate.js +121 -0
  249. package/node_modules/checkride/dist/triage/gate.js.map +1 -0
  250. package/node_modules/checkride/dist/triage/index.d.ts +22 -0
  251. package/node_modules/checkride/dist/triage/index.d.ts.map +1 -0
  252. package/node_modules/checkride/dist/triage/index.js +20 -0
  253. package/node_modules/checkride/dist/triage/index.js.map +1 -0
  254. package/node_modules/checkride/dist/triage/render.d.ts +19 -0
  255. package/node_modules/checkride/dist/triage/render.d.ts.map +1 -0
  256. package/node_modules/checkride/dist/triage/render.js +419 -0
  257. package/node_modules/checkride/dist/triage/render.js.map +1 -0
  258. package/node_modules/checkride/dist/triage/triage.d.ts +83 -0
  259. package/node_modules/checkride/dist/triage/triage.d.ts.map +1 -0
  260. package/node_modules/checkride/dist/triage/triage.js +131 -0
  261. package/node_modules/checkride/dist/triage/triage.js.map +1 -0
  262. package/node_modules/checkride/package.json +17 -15
  263. package/node_modules/checkride/schema/checkride.config.schema.json +62 -5
  264. package/node_modules/checkride/schema/checkride.summary.schema.json +1 -1
  265. package/node_modules/checkride/skills/check/SKILL.md +257 -0
  266. package/node_modules/checkride/skills/qa/SKILL.md +231 -0
  267. package/node_modules/checkride/templates/shared/cspell.json +1 -0
  268. package/node_modules/checkride/templates/shared/oxlintrc.json +1 -1
  269. package/package.json +2 -2
  270. package/skills/build/SKILL.md +23 -19
  271. package/skills/finish/SKILL.md +3 -1
  272. package/skills/harvest/SKILL.md +2 -1
  273. package/skills/plan/SKILL.md +8 -7
  274. package/skills/recover/SKILL.md +28 -0
  275. package/skills/refine/SKILL.md +5 -4
  276. package/skills/spike/SKILL.md +1 -1
  277. package/skills/step/SKILL.md +4 -4
  278. package/skills/verify/SKILL.md +19 -14
  279. package/templates/intent.md +8 -7
@@ -0,0 +1,88 @@
1
+ /**
2
+ * Folding `checkride doctor` into the broken-harness branch.
3
+ *
4
+ * Exit 2 means the harness broke or was misused, and every check result from
5
+ * that run is untrustworthy. "Broken harness" on its own costs a round-trip:
6
+ * the agent has to go ask what broke. `doctor` already answers that — it is
7
+ * read-only, runs no checks, and splits 0/1 the same way — so triage runs it at
8
+ * the one moment it is the right answer and arrives with the diagnosis attached.
9
+ *
10
+ * It is spawned as `node <repo's checkride>/dist/cli.js doctor --json`, not
11
+ * through the package manager: `<pm> exec` can print its own noise onto stdout,
12
+ * and the JSON report is the thing being parsed. It is also deliberately the
13
+ * *repo's* installed checkride rather than the one this reader ships inside —
14
+ * diagnosing an environment with a different version's doctor is how a reader
15
+ * reports a problem the repo does not have.
16
+ */
17
+ import { existsSync, readFileSync } from 'node:fs';
18
+ import { join } from 'node:path';
19
+ import { asStringOrNull, isRecord, parseJson } from '../artifacts/index.js';
20
+ /** A doctor probe is a read; it should never be the thing that hangs a triage. */
21
+ const DOCTOR_TIMEOUT_MS = 120_000;
22
+ /** Read a package.json `name` field, or `null` when it cannot be read. */
23
+ function packageName(cwd) {
24
+ try {
25
+ const pkg = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf8'));
26
+ return pkg.name ?? null;
27
+ }
28
+ catch {
29
+ return null;
30
+ }
31
+ }
32
+ /**
33
+ * The checkride CLI this repo would run: its installed copy, or its own build
34
+ * when `cwd` *is* the checkride package (the dogfooding case). Never some other
35
+ * repo's `dist/cli.js` — the package name has to say so.
36
+ */
37
+ export function resolveCheckrideCli(cwd) {
38
+ const installed = join(cwd, 'node_modules', 'checkride', 'dist', 'cli.js');
39
+ if (existsSync(installed))
40
+ return installed;
41
+ const own = join(cwd, 'dist', 'cli.js');
42
+ if (packageName(cwd) === 'checkride' && existsSync(own))
43
+ return own;
44
+ return null;
45
+ }
46
+ /** Narrow one `checks[]` row to a finding, or `null` when it is not a problem. */
47
+ function toFinding(value) {
48
+ if (!isRecord(value))
49
+ return null;
50
+ if (value['required'] !== true || value['status'] === 'ok')
51
+ return null;
52
+ return {
53
+ name: asStringOrNull(value['name']) ?? 'unnamed check',
54
+ status: asStringOrNull(value['status']) ?? 'unknown',
55
+ found: asStringOrNull(value['found']),
56
+ expected: asStringOrNull(value['expected']),
57
+ hint: asStringOrNull(value['hint']),
58
+ };
59
+ }
60
+ /** Pull the required-and-not-ok rows out of a `doctor --json` report. */
61
+ function readFindings(stdout) {
62
+ const report = parseJson(stdout);
63
+ if (!isRecord(report))
64
+ return null;
65
+ const checks = report['checks'];
66
+ if (!Array.isArray(checks))
67
+ return null;
68
+ return checks.map(toFinding).filter((f) => f !== null);
69
+ }
70
+ /**
71
+ * Run the repo's `checkride doctor --json` and extract what is broken. Never
72
+ * throws; an absent or unparseable doctor is reported as such so the report can
73
+ * say "the harness broke and I could not ask why" instead of inventing a cause.
74
+ */
75
+ export async function foldDoctor(cwd, env) {
76
+ const cli = resolveCheckrideCli(cwd);
77
+ if (cli === null) {
78
+ return { state: 'unavailable', reason: 'checkride is not installed in this repo (no node_modules/checkride)' };
79
+ }
80
+ const outcome = await env.spawn(process.execPath, [cli, 'doctor', '--json'], { cwd, timeoutMs: DOCTOR_TIMEOUT_MS });
81
+ if (outcome.error !== null)
82
+ return { state: 'unreadable', reason: `could not run doctor: ${outcome.error}` };
83
+ const findings = readFindings(outcome.stdout);
84
+ if (findings === null)
85
+ return { state: 'unreadable', reason: 'doctor --json did not produce a readable report' };
86
+ return { state: 'ran', ok: outcome.code === 0, exitCode: outcome.code, findings };
87
+ }
88
+ //# sourceMappingURL=doctor-fold.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-fold.js","sourceRoot":"","sources":["../../src/triage/doctor-fold.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,54 @@
1
+ /**
2
+ * The triage reader's process surface: spawning, and the clock.
3
+ *
4
+ * Both are injectable because the reader's hardest guarantees are about
5
+ * *failure* — it must survive a red gate, a broken harness, a missing binary
6
+ * and a hung run without dying itself, and none of those are reachable from a
7
+ * test that has to spawn a real toolchain to get there.
8
+ *
9
+ * {@link spawnCapture} never rejects. A reader that throws on a red gate would
10
+ * fail exactly when it is needed, so a spawn failure is a *value* — an outcome
11
+ * with `error` set — not an exception.
12
+ */
13
+ /**
14
+ * A finished (or failed) child process. `code` is `null` when the process died
15
+ * by signal or never started; `error` is set only in the latter case.
16
+ */
17
+ export type SpawnOutcome = {
18
+ code: number | null;
19
+ signal: string | null;
20
+ stdout: string;
21
+ stderr: string;
22
+ /** The spawn error message when the process could not start at all. */
23
+ error: string | null;
24
+ };
25
+ /** Run a command and capture it. The one process touch the reader makes. */
26
+ export type Spawner = (command: string, args: readonly string[], opts: {
27
+ cwd: string;
28
+ timeoutMs: number;
29
+ }) => Promise<SpawnOutcome>;
30
+ /** Everything the reader needs from the outside world. */
31
+ export type TriageEnv = {
32
+ spawn: Spawner;
33
+ now: () => number;
34
+ /** Budget for the gate run. A hung check must not hang the agent waiting on it. */
35
+ timeoutMs: number;
36
+ };
37
+ /**
38
+ * Spawn `command`, capture both streams, and resolve however it ends. Never rejects.
39
+ *
40
+ * `detached`, so the child leads its own process group and the timeout can
41
+ * reap the whole tree. The gate is `<pm> run check`, which means the process
42
+ * actually doing the work is a *grandchild* — a bare `proc.kill()` signals the
43
+ * package-manager wrapper and leaves the checks themselves running, which both
44
+ * defeats the budget and can hold this promise open forever, since `close`
45
+ * waits on every inherited pipe. `killGroupEscalating` signals the group and
46
+ * insists with SIGKILL after the grace (see `../proc.ts`).
47
+ */
48
+ export declare function spawnCapture(command: string, args: readonly string[], opts: {
49
+ cwd: string;
50
+ timeoutMs: number;
51
+ }): Promise<SpawnOutcome>;
52
+ /** The real process surface. */
53
+ export declare const realEnv: TriageEnv;
54
+ //# sourceMappingURL=env.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.d.ts","sourceRoot":"","sources":["../../src/triage/env.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAMH;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,uEAAuE;IACvE,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CACtB,CAAC;AAEF,4EAA4E;AAC5E,MAAM,MAAM,OAAO,GAAG,CACpB,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,KACrC,OAAO,CAAC,YAAY,CAAC,CAAC;AAE3B,0DAA0D;AAC1D,MAAM,MAAM,SAAS,GAAG;IACtB,KAAK,EAAE,OAAO,CAAC;IACf,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,mFAAmF;IACnF,SAAS,EAAE,MAAM,CAAC;CACnB,CAAC;AAoBF;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAC1B,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,MAAM,CAAA;CAAE,GACvC,OAAO,CAAC,YAAY,CAAC,CA+BvB;AAED,gCAAgC;AAChC,eAAO,MAAM,OAAO,EAAE,SAIrB,CAAC"}
@@ -0,0 +1,81 @@
1
+ /**
2
+ * The triage reader's process surface: spawning, and the clock.
3
+ *
4
+ * Both are injectable because the reader's hardest guarantees are about
5
+ * *failure* — it must survive a red gate, a broken harness, a missing binary
6
+ * and a hung run without dying itself, and none of those are reachable from a
7
+ * test that has to spawn a real toolchain to get there.
8
+ *
9
+ * {@link spawnCapture} never rejects. A reader that throws on a red gate would
10
+ * fail exactly when it is needed, so a spawn failure is a *value* — an outcome
11
+ * with `error` set — not an exception.
12
+ */
13
+ import { spawn } from 'node:child_process';
14
+ import { killGroupEscalating } from '../proc.js';
15
+ /**
16
+ * A full gate can legitimately take minutes (mutation testing, a cold build),
17
+ * so the ceiling is generous: it exists to break a hang, not to police a slow
18
+ * repo. checkride's own per-check timeouts fire long before this does.
19
+ */
20
+ const DEFAULT_GATE_TIMEOUT_MS = 20 * 60 * 1000;
21
+ /**
22
+ * Keep the tail of each stream. The reader only ever renders an excerpt, and a
23
+ * runaway tool must not be able to exhaust memory before the run even ends.
24
+ */
25
+ const MAX_CAPTURE_CHARS = 256 * 1024;
26
+ function appendCapped(buffer, chunk) {
27
+ const next = buffer + chunk;
28
+ return next.length > MAX_CAPTURE_CHARS ? next.slice(next.length - MAX_CAPTURE_CHARS) : next;
29
+ }
30
+ /**
31
+ * Spawn `command`, capture both streams, and resolve however it ends. Never rejects.
32
+ *
33
+ * `detached`, so the child leads its own process group and the timeout can
34
+ * reap the whole tree. The gate is `<pm> run check`, which means the process
35
+ * actually doing the work is a *grandchild* — a bare `proc.kill()` signals the
36
+ * package-manager wrapper and leaves the checks themselves running, which both
37
+ * defeats the budget and can hold this promise open forever, since `close`
38
+ * waits on every inherited pipe. `killGroupEscalating` signals the group and
39
+ * insists with SIGKILL after the grace (see `../proc.ts`).
40
+ */
41
+ export function spawnCapture(command, args, opts) {
42
+ return new Promise((resolve) => {
43
+ const proc = spawn(command, [...args], {
44
+ cwd: opts.cwd,
45
+ detached: true,
46
+ stdio: ['ignore', 'pipe', 'pipe'],
47
+ env: { ...process.env, FORCE_COLOR: '0', NO_COLOR: '1' },
48
+ });
49
+ let stdout = '';
50
+ let stderr = '';
51
+ let settled = false;
52
+ let escalation = null;
53
+ const timer = setTimeout(() => { escalation = killGroupEscalating(proc.pid); }, opts.timeoutMs);
54
+ const settle = (outcome) => {
55
+ if (settled)
56
+ return;
57
+ settled = true;
58
+ clearTimeout(timer);
59
+ // A pending SIGKILL timer would hold the event loop open past the run.
60
+ if (escalation !== null)
61
+ clearTimeout(escalation);
62
+ resolve(outcome);
63
+ };
64
+ // Decoded string streams: the internal StringDecoder holds a partial
65
+ // multibyte sequence until its continuation bytes arrive, so `+=` never
66
+ // concatenates half a character.
67
+ proc.stdout.setEncoding('utf8');
68
+ proc.stderr.setEncoding('utf8');
69
+ proc.stdout.on('data', (chunk) => { stdout = appendCapped(stdout, chunk); });
70
+ proc.stderr.on('data', (chunk) => { stderr = appendCapped(stderr, chunk); });
71
+ proc.on('error', (err) => { settle({ code: null, signal: null, stdout, stderr, error: err.message }); });
72
+ proc.on('close', (code, signal) => { settle({ code, signal, stdout, stderr, error: null }); });
73
+ });
74
+ }
75
+ /** The real process surface. */
76
+ export const realEnv = {
77
+ spawn: spawnCapture,
78
+ now: () => Date.now(),
79
+ timeoutMs: DEFAULT_GATE_TIMEOUT_MS,
80
+ };
81
+ //# sourceMappingURL=env.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env.js","sourceRoot":"","sources":["../../src/triage/env.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,61 @@
1
+ /**
2
+ * Running the gate — the preflight every triage begins with.
3
+ *
4
+ * The reader runs the repo's *own* `check` script rather than `checkride`
5
+ * directly, because that script is the repo's definition of done and may carry
6
+ * deliberate `--only` / `--skip` / `--changed` that a direct invocation would
7
+ * bypass. It also means a pre-existing `summary.json` is never mistaken for
8
+ * evidence: every run overwrites it, so `ok: true` on disk can mean "three of
9
+ * seventeen slots passed fourteen minutes ago".
10
+ *
11
+ * checkride promises the 0/1/2 exit split, so the verdict branches on that
12
+ * before anything is read. Anything outside it — 127, a signal death, a wrapper
13
+ * command that failed before checkride ran — is `off-contract`, reported as
14
+ * itself rather than folded into one of the three.
15
+ *
16
+ * One exit *inside* the split still is not checkride's: a package manager that
17
+ * refuses to start the script — an `engines.node` pin the running Node does not
18
+ * satisfy, most often — exits 1, exactly as a red pipeline does. Left
19
+ * unclassified, the reader an agent is sent to by a red gate would confirm the
20
+ * red and point at slots that never ran. See `../pm/launch.ts`.
21
+ */
22
+ import type { PackageManager } from '../pm/index.js';
23
+ import type { TriageEnv } from './env.js';
24
+ /** How the gate ended, in the reader's vocabulary. */
25
+ export type GateVerdict = 'green' | 'red' | 'could-not-start' | 'harness-broken' | 'off-contract' | 'not-run';
26
+ /** The gate run: what was executed, how it ended, and what it printed. */
27
+ export type GateOutcome = {
28
+ verdict: GateVerdict;
29
+ /** The repo's `scripts.check`, verbatim — the definition of done. */
30
+ script: string | null;
31
+ /** The command line as run, for the report to quote. */
32
+ command: string;
33
+ pm: PackageManager;
34
+ exitCode: number | null;
35
+ signal: string | null;
36
+ startedMs: number;
37
+ durationMs: number;
38
+ stdout: string;
39
+ stderr: string;
40
+ spawnError: string | null;
41
+ /** Why the package manager never started the script, on the `could-not-start` verdict. */
42
+ refusal: string | null;
43
+ /** Selection flags found in the script text: it narrows the run on purpose. */
44
+ narrowingFlags: string[];
45
+ };
46
+ /**
47
+ * Run `<pm> run check` in `cwd` and classify the result. Never throws: a repo
48
+ * with no `check` script, a missing package manager and a gate that fails are
49
+ * all outcomes, because each is something the report has to say.
50
+ */
51
+ export declare function runGate(cwd: string, env: TriageEnv): Promise<GateOutcome>;
52
+ /**
53
+ * Whether this ending means the harness itself is suspect, not the code.
54
+ *
55
+ * `could-not-start` belongs here for the strongest version of that reason:
56
+ * nothing ran at all, so the environment is the entire finding and the slot
57
+ * table is not evidence of anything. It is also what folds `doctor` into the
58
+ * report, which is where the reader will find the Node the hook got.
59
+ */
60
+ export declare function isHarnessProblem(verdict: GateVerdict): boolean;
61
+ //# sourceMappingURL=gate.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.d.ts","sourceRoot":"","sources":["../../src/triage/gate.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AAMH,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAErD,OAAO,KAAK,EAAgB,SAAS,EAAE,MAAM,UAAU,CAAC;AAExD,sDAAsD;AACtD,MAAM,MAAM,WAAW,GAAG,OAAO,GAAG,KAAK,GAAG,iBAAiB,GAAG,gBAAgB,GAAG,cAAc,GAAG,SAAS,CAAC;AAE9G,0EAA0E;AAC1E,MAAM,MAAM,WAAW,GAAG;IACxB,OAAO,EAAE,WAAW,CAAC;IACrB,qEAAqE;IACrE,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,EAAE,EAAE,cAAc,CAAC;IACnB,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IACtB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,0FAA0F;IAC1F,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,+EAA+E;IAC/E,cAAc,EAAE,MAAM,EAAE,CAAC;CAC1B,CAAC;AA0DF;;;;GAIG;AACH,wBAAsB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CA0B/E;AAED;;;;;;;GAOG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,GAAG,OAAO,CAE9D"}
@@ -0,0 +1,121 @@
1
+ /**
2
+ * Running the gate — the preflight every triage begins with.
3
+ *
4
+ * The reader runs the repo's *own* `check` script rather than `checkride`
5
+ * directly, because that script is the repo's definition of done and may carry
6
+ * deliberate `--only` / `--skip` / `--changed` that a direct invocation would
7
+ * bypass. It also means a pre-existing `summary.json` is never mistaken for
8
+ * evidence: every run overwrites it, so `ok: true` on disk can mean "three of
9
+ * seventeen slots passed fourteen minutes ago".
10
+ *
11
+ * checkride promises the 0/1/2 exit split, so the verdict branches on that
12
+ * before anything is read. Anything outside it — 127, a signal death, a wrapper
13
+ * command that failed before checkride ran — is `off-contract`, reported as
14
+ * itself rather than folded into one of the three.
15
+ *
16
+ * One exit *inside* the split still is not checkride's: a package manager that
17
+ * refuses to start the script — an `engines.node` pin the running Node does not
18
+ * satisfy, most often — exits 1, exactly as a red pipeline does. Left
19
+ * unclassified, the reader an agent is sent to by a red gate would confirm the
20
+ * red and point at slots that never ran. See `../pm/launch.ts`.
21
+ */
22
+ import { readFileSync } from 'node:fs';
23
+ import { join } from 'node:path';
24
+ import { readSummary } from '../artifacts/index.js';
25
+ import { detectPackageManager, launchRefusal } from '../pm/index.js';
26
+ /** Script name every checkride repo exposes; `checkride init` writes it. */
27
+ const CHECK_SCRIPT = 'check';
28
+ /**
29
+ * Flags that make a green run cover less than the repo configures. Detected
30
+ * textually in the script, which is exact and needs no knowledge of the
31
+ * installed checkride's catalogue.
32
+ */
33
+ const NARROWING_FLAGS = ['--only', '--skip', '--changed'];
34
+ /** checkride's promised exit split. Everything else is off-contract. */
35
+ const VERDICT_BY_CODE = { 0: 'green', 1: 'red', 2: 'harness-broken' };
36
+ /** Read `scripts.check` from `cwd`'s package.json, or `null` when there is none. */
37
+ function readCheckScript(cwd) {
38
+ try {
39
+ const pkg = JSON.parse(readFileSync(join(cwd, 'package.json'), 'utf8'));
40
+ return pkg.scripts?.[CHECK_SCRIPT] ?? null;
41
+ }
42
+ catch {
43
+ return null;
44
+ }
45
+ }
46
+ /**
47
+ * Tolerance for a summary written moments before the gate's own clock reading —
48
+ * mirrors `MTIME_TOLERANCE_MS` in `./triage.ts`, where the same comparison
49
+ * decides whether the summary belongs to this run.
50
+ */
51
+ const MTIME_TOLERANCE_MS = 1000;
52
+ /**
53
+ * Did this run write a summary? Proof that the pipeline started, whatever its
54
+ * output happens to contain — the guard that keeps a check which merely
55
+ * *printed* a package-manager error code from being read as a refusal to launch.
56
+ */
57
+ async function wroteSummary(cwd, startedMs) {
58
+ const read = await readSummary(cwd);
59
+ return read.state === 'ok' && read.mtimeMs >= startedMs - MTIME_TOLERANCE_MS;
60
+ }
61
+ /**
62
+ * Classify an exit-1 gate: a red pipeline, or a package manager that never
63
+ * started one. Only exit 1 is examined — 0 and 2 are checkride's own answers and
64
+ * mean the pipeline ran, and everything else is already `off-contract`.
65
+ */
66
+ async function refusalFor(outcome, cwd, startedMs) {
67
+ if (outcome.code !== 1 || (await wroteSummary(cwd, startedMs)))
68
+ return null;
69
+ return launchRefusal(`${outcome.stdout}${outcome.stderr}`)?.cause ?? null;
70
+ }
71
+ function verdictFor(outcome, refusal) {
72
+ if (outcome.error !== null || outcome.code === null)
73
+ return 'off-contract';
74
+ if (refusal !== null)
75
+ return 'could-not-start';
76
+ return VERDICT_BY_CODE[outcome.code] ?? 'off-contract';
77
+ }
78
+ /**
79
+ * Run `<pm> run check` in `cwd` and classify the result. Never throws: a repo
80
+ * with no `check` script, a missing package manager and a gate that fails are
81
+ * all outcomes, because each is something the report has to say.
82
+ */
83
+ export async function runGate(cwd, env) {
84
+ const pm = detectPackageManager({ cwd });
85
+ const script = readCheckScript(cwd);
86
+ const base = {
87
+ script,
88
+ command: `${pm} run ${CHECK_SCRIPT}`,
89
+ pm,
90
+ startedMs: env.now(),
91
+ narrowingFlags: NARROWING_FLAGS.filter((flag) => script?.includes(flag) ?? false),
92
+ };
93
+ if (script === null) {
94
+ return { ...base, verdict: 'not-run', exitCode: null, signal: null, durationMs: 0, stdout: '', stderr: '', spawnError: null, refusal: null };
95
+ }
96
+ const outcome = await env.spawn(pm, ['run', CHECK_SCRIPT], { cwd, timeoutMs: env.timeoutMs });
97
+ const refusal = await refusalFor(outcome, cwd, base.startedMs);
98
+ return {
99
+ ...base,
100
+ verdict: verdictFor(outcome, refusal),
101
+ exitCode: outcome.code,
102
+ signal: outcome.signal,
103
+ durationMs: env.now() - base.startedMs,
104
+ stdout: outcome.stdout,
105
+ stderr: outcome.stderr,
106
+ spawnError: outcome.error,
107
+ refusal,
108
+ };
109
+ }
110
+ /**
111
+ * Whether this ending means the harness itself is suspect, not the code.
112
+ *
113
+ * `could-not-start` belongs here for the strongest version of that reason:
114
+ * nothing ran at all, so the environment is the entire finding and the slot
115
+ * table is not evidence of anything. It is also what folds `doctor` into the
116
+ * report, which is where the reader will find the Node the hook got.
117
+ */
118
+ export function isHarnessProblem(verdict) {
119
+ return verdict === 'harness-broken' || verdict === 'off-contract' || verdict === 'could-not-start';
120
+ }
121
+ //# sourceMappingURL=gate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"gate.js","sourceRoot":"","sources":["../../src/triage/gate.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Triage module — the bundled plugin's preflight reader.
3
+ *
4
+ * Runs the repo's own `check` script, branches on checkride's promised 0/1/2
5
+ * exit split, then reads `.check/` as an index: the summary's provenance and
6
+ * schema, one row per slot with its raw output located and sized, and the traps
7
+ * the five-line prose procedure never mentions (vacuous green, narrow green,
8
+ * `baselined`, `skipped`, `exit_code: -1`, a stale artifact). It defines no new
9
+ * contract surface and runs nothing checkride does not already run.
10
+ *
11
+ * `./cli.ts` is the executable form (`node dist/triage/cli.js`); this barrel is
12
+ * the module's programmatic surface, and files inside the module import each
13
+ * other directly rather than through it.
14
+ */
15
+ export type { SpawnOutcome, TriageEnv } from './env.js';
16
+ export { realEnv } from './env.js';
17
+ export { isHarnessProblem } from './gate.js';
18
+ export { resolveCheckrideCli } from './doctor-fold.js';
19
+ export { renderTriage } from './render.js';
20
+ export { triage } from './triage.js';
21
+ export type { TriageReport } from './triage.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/triage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,YAAY,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Triage module — the bundled plugin's preflight reader.
3
+ *
4
+ * Runs the repo's own `check` script, branches on checkride's promised 0/1/2
5
+ * exit split, then reads `.check/` as an index: the summary's provenance and
6
+ * schema, one row per slot with its raw output located and sized, and the traps
7
+ * the five-line prose procedure never mentions (vacuous green, narrow green,
8
+ * `baselined`, `skipped`, `exit_code: -1`, a stale artifact). It defines no new
9
+ * contract surface and runs nothing checkride does not already run.
10
+ *
11
+ * `./cli.ts` is the executable form (`node dist/triage/cli.js`); this barrel is
12
+ * the module's programmatic surface, and files inside the module import each
13
+ * other directly rather than through it.
14
+ */
15
+ export { realEnv } from './env.js';
16
+ export { isHarnessProblem } from './gate.js';
17
+ export { resolveCheckrideCli } from './doctor-fold.js';
18
+ export { renderTriage } from './render.js';
19
+ export { triage } from './triage.js';
20
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/triage/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAGH,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AAEnC,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAE7C,OAAO,EAAE,mBAAmB,EAAE,MAAM,kBAAkB,CAAC;AAEvD,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE3C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Rendering a {@link TriageReport} as Markdown — what the skill actually reads.
3
+ *
4
+ * The output is an *index with a verdict*, never an excerpt of tool output. It
5
+ * opens with provenance (what ran, how it ended, whether the summary on disk
6
+ * belongs to that run, and what it covered) because every wrong triage answer
7
+ * this reader exists to prevent comes from skipping straight to the findings.
8
+ * Slot rows carry sizes and paths; the bytes stay on disk. The only raw text
9
+ * that ever appears is a capped tail of the gate's own output, and only on the
10
+ * two branches where no slot can explain the failure: the harness broke, or the
11
+ * gate went red before checkride ran at all.
12
+ *
13
+ * Sections that have nothing to say render empty and drop out, so a clean run
14
+ * is short and a pathological one is still bounded.
15
+ */
16
+ import type { TriageReport } from './triage.js';
17
+ /** Render the whole report. Deterministic: same report in, same bytes out. */
18
+ export declare function renderTriage(report: TriageReport): string;
19
+ //# sourceMappingURL=render.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../../src/triage/render.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAMH,OAAO,KAAK,EAAW,YAAY,EAAE,MAAM,aAAa,CAAC;AA2bzD,8EAA8E;AAC9E,wBAAgB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,MAAM,CAKzD"}