plumbbob 0.9.3 → 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 (278) hide show
  1. package/.claude-plugin/plugin.json +1 -1
  2. package/README.md +15 -13
  3. package/dist/cli-core.js +19 -2
  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 +2 -2
  9. package/dist/verbs/doctor.js +4 -4
  10. package/dist/verbs/finish.js +1 -1
  11. package/dist/verbs/recover.js +297 -0
  12. package/dist/verbs/revert.js +2 -2
  13. package/dist/verbs/spike.js +8 -2
  14. package/hooks/post-edit.sh +4 -4
  15. package/hooks/pre-bash-commit.sh +3 -3
  16. package/node_modules/checkride/.claude-plugin/plugin.json +11 -0
  17. package/node_modules/checkride/CHANGELOG.md +1003 -0
  18. package/node_modules/checkride/LICENSE +201 -21
  19. package/node_modules/checkride/README.md +171 -30
  20. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts +15 -0
  21. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.d.ts.map +1 -0
  22. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js +17 -0
  23. package/node_modules/checkride/dist/__tests__/fixtures/released-stanzas.js.map +1 -0
  24. package/node_modules/checkride/dist/adapters.d.ts +18 -6
  25. package/node_modules/checkride/dist/adapters.d.ts.map +1 -1
  26. package/node_modules/checkride/dist/adapters.js +42 -23
  27. package/node_modules/checkride/dist/adapters.js.map +1 -1
  28. package/node_modules/checkride/dist/agent-setup/claude.d.ts +88 -0
  29. package/node_modules/checkride/dist/agent-setup/claude.d.ts.map +1 -0
  30. package/node_modules/checkride/dist/agent-setup/claude.js +305 -0
  31. package/node_modules/checkride/dist/agent-setup/claude.js.map +1 -0
  32. package/node_modules/checkride/dist/agent-setup/command.d.ts +43 -0
  33. package/node_modules/checkride/dist/agent-setup/command.d.ts.map +1 -0
  34. package/node_modules/checkride/dist/agent-setup/command.js +77 -0
  35. package/node_modules/checkride/dist/agent-setup/command.js.map +1 -0
  36. package/node_modules/checkride/dist/agent-setup/cursor.d.ts +61 -0
  37. package/node_modules/checkride/dist/agent-setup/cursor.d.ts.map +1 -0
  38. package/node_modules/checkride/dist/agent-setup/cursor.js +189 -0
  39. package/node_modules/checkride/dist/agent-setup/cursor.js.map +1 -0
  40. package/node_modules/checkride/dist/agent-setup/files.d.ts +50 -0
  41. package/node_modules/checkride/dist/agent-setup/files.d.ts.map +1 -0
  42. package/node_modules/checkride/dist/agent-setup/files.js +80 -0
  43. package/node_modules/checkride/dist/agent-setup/files.js.map +1 -0
  44. package/node_modules/checkride/dist/agent-setup/harness.d.ts +101 -0
  45. package/node_modules/checkride/dist/agent-setup/harness.d.ts.map +1 -0
  46. package/node_modules/checkride/dist/agent-setup/harness.js +84 -0
  47. package/node_modules/checkride/dist/agent-setup/harness.js.map +1 -0
  48. package/node_modules/checkride/dist/agent-setup/hook.d.ts +45 -52
  49. package/node_modules/checkride/dist/agent-setup/hook.d.ts.map +1 -1
  50. package/node_modules/checkride/dist/agent-setup/hook.js +64 -95
  51. package/node_modules/checkride/dist/agent-setup/hook.js.map +1 -1
  52. package/node_modules/checkride/dist/agent-setup/index.d.ts +10 -4
  53. package/node_modules/checkride/dist/agent-setup/index.d.ts.map +1 -1
  54. package/node_modules/checkride/dist/agent-setup/index.js +9 -4
  55. package/node_modules/checkride/dist/agent-setup/index.js.map +1 -1
  56. package/node_modules/checkride/dist/agent-setup/scripts.d.ts +58 -0
  57. package/node_modules/checkride/dist/agent-setup/scripts.d.ts.map +1 -0
  58. package/node_modules/checkride/dist/agent-setup/scripts.js +299 -0
  59. package/node_modules/checkride/dist/agent-setup/scripts.js.map +1 -0
  60. package/node_modules/checkride/dist/agent-setup/skills.d.ts +31 -0
  61. package/node_modules/checkride/dist/agent-setup/skills.d.ts.map +1 -0
  62. package/node_modules/checkride/dist/agent-setup/skills.js +56 -0
  63. package/node_modules/checkride/dist/agent-setup/skills.js.map +1 -0
  64. package/node_modules/checkride/dist/artifacts/configured.d.ts +30 -0
  65. package/node_modules/checkride/dist/artifacts/configured.d.ts.map +1 -0
  66. package/node_modules/checkride/dist/artifacts/configured.js +45 -0
  67. package/node_modules/checkride/dist/artifacts/configured.js.map +1 -0
  68. package/node_modules/checkride/dist/artifacts/format.d.ts +33 -0
  69. package/node_modules/checkride/dist/artifacts/format.d.ts.map +1 -0
  70. package/node_modules/checkride/dist/artifacts/format.js +56 -0
  71. package/node_modules/checkride/dist/artifacts/format.js.map +1 -0
  72. package/node_modules/checkride/dist/artifacts/freshness.d.ts +32 -0
  73. package/node_modules/checkride/dist/artifacts/freshness.d.ts.map +1 -0
  74. package/node_modules/checkride/dist/artifacts/freshness.js +37 -0
  75. package/node_modules/checkride/dist/artifacts/freshness.js.map +1 -0
  76. package/node_modules/checkride/dist/artifacts/index.d.ts +22 -0
  77. package/node_modules/checkride/dist/artifacts/index.d.ts.map +1 -0
  78. package/node_modules/checkride/dist/artifacts/index.js +19 -0
  79. package/node_modules/checkride/dist/artifacts/index.js.map +1 -0
  80. package/node_modules/checkride/dist/artifacts/json.d.ts +31 -0
  81. package/node_modules/checkride/dist/artifacts/json.d.ts.map +1 -0
  82. package/node_modules/checkride/dist/artifacts/json.js +47 -0
  83. package/node_modules/checkride/dist/artifacts/json.js.map +1 -0
  84. package/node_modules/checkride/dist/artifacts/raw.d.ts +60 -0
  85. package/node_modules/checkride/dist/artifacts/raw.d.ts.map +1 -0
  86. package/node_modules/checkride/dist/artifacts/raw.js +91 -0
  87. package/node_modules/checkride/dist/artifacts/raw.js.map +1 -0
  88. package/node_modules/checkride/dist/artifacts/summary.d.ts +69 -0
  89. package/node_modules/checkride/dist/artifacts/summary.d.ts.map +1 -0
  90. package/node_modules/checkride/dist/artifacts/summary.js +108 -0
  91. package/node_modules/checkride/dist/artifacts/summary.js.map +1 -0
  92. package/node_modules/checkride/dist/atomic.d.ts +16 -1
  93. package/node_modules/checkride/dist/atomic.d.ts.map +1 -1
  94. package/node_modules/checkride/dist/atomic.js +25 -3
  95. package/node_modules/checkride/dist/atomic.js.map +1 -1
  96. package/node_modules/checkride/dist/baseline/fallow.d.ts +9 -5
  97. package/node_modules/checkride/dist/baseline/fallow.d.ts.map +1 -1
  98. package/node_modules/checkride/dist/baseline/fallow.js +161 -58
  99. package/node_modules/checkride/dist/baseline/fallow.js.map +1 -1
  100. package/node_modules/checkride/dist/baseline/fingerprint.d.ts +7 -7
  101. package/node_modules/checkride/dist/baseline/fingerprint.d.ts.map +1 -1
  102. package/node_modules/checkride/dist/baseline/fingerprint.js +16 -19
  103. package/node_modules/checkride/dist/baseline/fingerprint.js.map +1 -1
  104. package/node_modules/checkride/dist/baseline/index.d.ts +4 -4
  105. package/node_modules/checkride/dist/baseline/index.d.ts.map +1 -1
  106. package/node_modules/checkride/dist/baseline/index.js +4 -4
  107. package/node_modules/checkride/dist/baseline/index.js.map +1 -1
  108. package/node_modules/checkride/dist/baseline/store.d.ts +12 -4
  109. package/node_modules/checkride/dist/baseline/store.d.ts.map +1 -1
  110. package/node_modules/checkride/dist/baseline/store.js +16 -9
  111. package/node_modules/checkride/dist/baseline/store.js.map +1 -1
  112. package/node_modules/checkride/dist/baseline-command.d.ts +5 -5
  113. package/node_modules/checkride/dist/baseline-command.js +7 -7
  114. package/node_modules/checkride/dist/baseline-command.js.map +1 -1
  115. package/node_modules/checkride/dist/cli.d.ts +17 -4
  116. package/node_modules/checkride/dist/cli.d.ts.map +1 -1
  117. package/node_modules/checkride/dist/cli.js +259 -18
  118. package/node_modules/checkride/dist/cli.js.map +1 -1
  119. package/node_modules/checkride/dist/config.d.ts +84 -8
  120. package/node_modules/checkride/dist/config.d.ts.map +1 -1
  121. package/node_modules/checkride/dist/config.js +122 -18
  122. package/node_modules/checkride/dist/config.js.map +1 -1
  123. package/node_modules/checkride/dist/digest/digest.d.ts +5 -5
  124. package/node_modules/checkride/dist/digest/digest.js +5 -5
  125. package/node_modules/checkride/dist/digest/index.d.ts +2 -2
  126. package/node_modules/checkride/dist/digest/index.js +2 -2
  127. package/node_modules/checkride/dist/doctor.d.ts +25 -6
  128. package/node_modules/checkride/dist/doctor.d.ts.map +1 -1
  129. package/node_modules/checkride/dist/doctor.js +193 -27
  130. package/node_modules/checkride/dist/doctor.js.map +1 -1
  131. package/node_modules/checkride/dist/gate.d.ts +135 -0
  132. package/node_modules/checkride/dist/gate.d.ts.map +1 -0
  133. package/node_modules/checkride/dist/gate.js +490 -0
  134. package/node_modules/checkride/dist/gate.js.map +1 -0
  135. package/node_modules/checkride/dist/init.d.ts +72 -12
  136. package/node_modules/checkride/dist/init.d.ts.map +1 -1
  137. package/node_modules/checkride/dist/init.js +324 -81
  138. package/node_modules/checkride/dist/init.js.map +1 -1
  139. package/node_modules/checkride/dist/json.d.ts +21 -0
  140. package/node_modules/checkride/dist/json.d.ts.map +1 -0
  141. package/node_modules/checkride/dist/json.js +21 -0
  142. package/node_modules/checkride/dist/json.js.map +1 -0
  143. package/node_modules/checkride/dist/links.d.ts +31 -5
  144. package/node_modules/checkride/dist/links.d.ts.map +1 -1
  145. package/node_modules/checkride/dist/links.js +141 -32
  146. package/node_modules/checkride/dist/links.js.map +1 -1
  147. package/node_modules/checkride/dist/node-pin.d.ts +129 -0
  148. package/node_modules/checkride/dist/node-pin.d.ts.map +1 -0
  149. package/node_modules/checkride/dist/node-pin.js +211 -0
  150. package/node_modules/checkride/dist/node-pin.js.map +1 -0
  151. package/node_modules/checkride/dist/orchestrator.d.ts +40 -10
  152. package/node_modules/checkride/dist/orchestrator.d.ts.map +1 -1
  153. package/node_modules/checkride/dist/orchestrator.js +196 -102
  154. package/node_modules/checkride/dist/orchestrator.js.map +1 -1
  155. package/node_modules/checkride/dist/pack.d.ts +8 -9
  156. package/node_modules/checkride/dist/pack.d.ts.map +1 -1
  157. package/node_modules/checkride/dist/pack.js +53 -17
  158. package/node_modules/checkride/dist/pack.js.map +1 -1
  159. package/node_modules/checkride/dist/pm/detect.d.ts +6 -1
  160. package/node_modules/checkride/dist/pm/detect.d.ts.map +1 -1
  161. package/node_modules/checkride/dist/pm/detect.js +6 -1
  162. package/node_modules/checkride/dist/pm/detect.js.map +1 -1
  163. package/node_modules/checkride/dist/pm/index.d.ts +6 -2
  164. package/node_modules/checkride/dist/pm/index.d.ts.map +1 -1
  165. package/node_modules/checkride/dist/pm/index.js +6 -2
  166. package/node_modules/checkride/dist/pm/index.js.map +1 -1
  167. package/node_modules/checkride/dist/pm/launch.d.ts +51 -0
  168. package/node_modules/checkride/dist/pm/launch.d.ts.map +1 -0
  169. package/node_modules/checkride/dist/pm/launch.js +92 -0
  170. package/node_modules/checkride/dist/pm/launch.js.map +1 -0
  171. package/node_modules/checkride/dist/pm/tools.d.ts +73 -0
  172. package/node_modules/checkride/dist/pm/tools.d.ts.map +1 -0
  173. package/node_modules/checkride/dist/pm/tools.js +124 -0
  174. package/node_modules/checkride/dist/pm/tools.js.map +1 -0
  175. package/node_modules/checkride/dist/pm/translate.d.ts +35 -9
  176. package/node_modules/checkride/dist/pm/translate.d.ts.map +1 -1
  177. package/node_modules/checkride/dist/pm/translate.js +78 -18
  178. package/node_modules/checkride/dist/pm/translate.js.map +1 -1
  179. package/node_modules/checkride/dist/proc.d.ts +30 -0
  180. package/node_modules/checkride/dist/proc.d.ts.map +1 -0
  181. package/node_modules/checkride/dist/proc.js +42 -0
  182. package/node_modules/checkride/dist/proc.js.map +1 -0
  183. package/node_modules/checkride/dist/qa/cli.d.ts +20 -0
  184. package/node_modules/checkride/dist/qa/cli.d.ts.map +1 -0
  185. package/node_modules/checkride/dist/qa/cli.js +24 -0
  186. package/node_modules/checkride/dist/qa/cli.js.map +1 -0
  187. package/node_modules/checkride/dist/qa/dead.d.ts +39 -0
  188. package/node_modules/checkride/dist/qa/dead.d.ts.map +1 -0
  189. package/node_modules/checkride/dist/qa/dead.js +88 -0
  190. package/node_modules/checkride/dist/qa/dead.js.map +1 -0
  191. package/node_modules/checkride/dist/qa/dupes.d.ts +45 -0
  192. package/node_modules/checkride/dist/qa/dupes.d.ts.map +1 -0
  193. package/node_modules/checkride/dist/qa/dupes.js +62 -0
  194. package/node_modules/checkride/dist/qa/dupes.js.map +1 -0
  195. package/node_modules/checkride/dist/qa/health.d.ts +85 -0
  196. package/node_modules/checkride/dist/qa/health.d.ts.map +1 -0
  197. package/node_modules/checkride/dist/qa/health.js +109 -0
  198. package/node_modules/checkride/dist/qa/health.js.map +1 -0
  199. package/node_modules/checkride/dist/qa/index.d.ts +23 -0
  200. package/node_modules/checkride/dist/qa/index.d.ts.map +1 -0
  201. package/node_modules/checkride/dist/qa/index.js +22 -0
  202. package/node_modules/checkride/dist/qa/index.js.map +1 -0
  203. package/node_modules/checkride/dist/qa/mutation.d.ts +80 -0
  204. package/node_modules/checkride/dist/qa/mutation.d.ts.map +1 -0
  205. package/node_modules/checkride/dist/qa/mutation.js +195 -0
  206. package/node_modules/checkride/dist/qa/mutation.js.map +1 -0
  207. package/node_modules/checkride/dist/qa/qa.d.ts +71 -0
  208. package/node_modules/checkride/dist/qa/qa.d.ts.map +1 -0
  209. package/node_modules/checkride/dist/qa/qa.js +158 -0
  210. package/node_modules/checkride/dist/qa/qa.js.map +1 -0
  211. package/node_modules/checkride/dist/qa/read.d.ts +40 -0
  212. package/node_modules/checkride/dist/qa/read.d.ts.map +1 -0
  213. package/node_modules/checkride/dist/qa/read.js +47 -0
  214. package/node_modules/checkride/dist/qa/read.js.map +1 -0
  215. package/node_modules/checkride/dist/qa/render.d.ts +26 -0
  216. package/node_modules/checkride/dist/qa/render.d.ts.map +1 -0
  217. package/node_modules/checkride/dist/qa/render.js +310 -0
  218. package/node_modules/checkride/dist/qa/render.js.map +1 -0
  219. package/node_modules/checkride/dist/security.d.ts +45 -0
  220. package/node_modules/checkride/dist/security.d.ts.map +1 -0
  221. package/node_modules/checkride/dist/security.js +86 -0
  222. package/node_modules/checkride/dist/security.js.map +1 -0
  223. package/node_modules/checkride/dist/smoke.d.ts +5 -5
  224. package/node_modules/checkride/dist/smoke.js +5 -5
  225. package/node_modules/checkride/dist/snippets.d.ts +26 -29
  226. package/node_modules/checkride/dist/snippets.d.ts.map +1 -1
  227. package/node_modules/checkride/dist/snippets.js +26 -30
  228. package/node_modules/checkride/dist/snippets.js.map +1 -1
  229. package/node_modules/checkride/dist/tool-json.d.ts +33 -0
  230. package/node_modules/checkride/dist/tool-json.d.ts.map +1 -0
  231. package/node_modules/checkride/dist/tool-json.js +58 -0
  232. package/node_modules/checkride/dist/tool-json.js.map +1 -0
  233. package/node_modules/checkride/dist/triage/cli.d.ts +21 -0
  234. package/node_modules/checkride/dist/triage/cli.d.ts.map +1 -0
  235. package/node_modules/checkride/dist/triage/cli.js +26 -0
  236. package/node_modules/checkride/dist/triage/cli.js.map +1 -0
  237. package/node_modules/checkride/dist/triage/doctor-fold.d.ts +51 -0
  238. package/node_modules/checkride/dist/triage/doctor-fold.d.ts.map +1 -0
  239. package/node_modules/checkride/dist/triage/doctor-fold.js +88 -0
  240. package/node_modules/checkride/dist/triage/doctor-fold.js.map +1 -0
  241. package/node_modules/checkride/dist/triage/env.d.ts +54 -0
  242. package/node_modules/checkride/dist/triage/env.d.ts.map +1 -0
  243. package/node_modules/checkride/dist/triage/env.js +81 -0
  244. package/node_modules/checkride/dist/triage/env.js.map +1 -0
  245. package/node_modules/checkride/dist/triage/gate.d.ts +61 -0
  246. package/node_modules/checkride/dist/triage/gate.d.ts.map +1 -0
  247. package/node_modules/checkride/dist/triage/gate.js +121 -0
  248. package/node_modules/checkride/dist/triage/gate.js.map +1 -0
  249. package/node_modules/checkride/dist/triage/index.d.ts +22 -0
  250. package/node_modules/checkride/dist/triage/index.d.ts.map +1 -0
  251. package/node_modules/checkride/dist/triage/index.js +20 -0
  252. package/node_modules/checkride/dist/triage/index.js.map +1 -0
  253. package/node_modules/checkride/dist/triage/render.d.ts +19 -0
  254. package/node_modules/checkride/dist/triage/render.d.ts.map +1 -0
  255. package/node_modules/checkride/dist/triage/render.js +419 -0
  256. package/node_modules/checkride/dist/triage/render.js.map +1 -0
  257. package/node_modules/checkride/dist/triage/triage.d.ts +83 -0
  258. package/node_modules/checkride/dist/triage/triage.d.ts.map +1 -0
  259. package/node_modules/checkride/dist/triage/triage.js +131 -0
  260. package/node_modules/checkride/dist/triage/triage.js.map +1 -0
  261. package/node_modules/checkride/package.json +17 -15
  262. package/node_modules/checkride/schema/checkride.config.schema.json +62 -5
  263. package/node_modules/checkride/schema/checkride.summary.schema.json +1 -1
  264. package/node_modules/checkride/skills/check/SKILL.md +257 -0
  265. package/node_modules/checkride/skills/qa/SKILL.md +231 -0
  266. package/node_modules/checkride/templates/shared/cspell.json +1 -0
  267. package/node_modules/checkride/templates/shared/oxlintrc.json +1 -1
  268. package/package.json +2 -2
  269. package/skills/build/SKILL.md +23 -19
  270. package/skills/finish/SKILL.md +3 -1
  271. package/skills/harvest/SKILL.md +2 -1
  272. package/skills/plan/SKILL.md +8 -7
  273. package/skills/recover/SKILL.md +28 -0
  274. package/skills/refine/SKILL.md +5 -4
  275. package/skills/spike/SKILL.md +1 -1
  276. package/skills/step/SKILL.md +4 -4
  277. package/skills/verify/SKILL.md +19 -14
  278. package/templates/intent.md +8 -7
@@ -0,0 +1,37 @@
1
+ /**
2
+ * The freshness window — which `.check/` files belong to the run that wrote the
3
+ * summary sitting beside them.
4
+ *
5
+ * The window is `[timestamp - total_duration_ms, ∞)`: the run's *start*, not
6
+ * its end, because `timestamp` is stamped once every check has finished (see
7
+ * `buildSummary` in `../orchestrator.ts`) and every artifact the run just wrote
8
+ * is therefore older than it. Anything outside the window is labelled with its
9
+ * age, never silently dropped.
10
+ *
11
+ * Why a window at all, and why this derivation is contract-legal:
12
+ * `docs/plugin.md` §How the readers decide an artifact is stale.
13
+ *
14
+ * The `../artifacts` barrel is this module's only public surface.
15
+ */
16
+ const FRESH = { state: 'fresh', ageMs: null };
17
+ const UNKNOWN = { state: 'unknown', ageMs: null };
18
+ /**
19
+ * Epoch milliseconds at which the run began, or `null` when `timestamp` is not
20
+ * a parseable date. Callers treat `null` as "cannot judge freshness" rather
21
+ * than guessing in either direction.
22
+ */
23
+ export function runWindowStart(summary) {
24
+ const stamped = Date.parse(summary.timestamp);
25
+ if (Number.isNaN(stamped))
26
+ return null;
27
+ return stamped - summary.total_duration_ms;
28
+ }
29
+ /** Classify one artifact's mtime against the window from {@link runWindowStart}. */
30
+ export function classifyFreshness(mtimeMs, windowStart) {
31
+ if (windowStart === null)
32
+ return UNKNOWN;
33
+ if (mtimeMs >= windowStart)
34
+ return FRESH;
35
+ return { state: 'stale', ageMs: windowStart - mtimeMs };
36
+ }
37
+ //# sourceMappingURL=freshness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"freshness.js","sourceRoot":"","sources":["../../src/artifacts/freshness.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAYH,MAAM,KAAK,GAAc,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACzD,MAAM,OAAO,GAAc,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AAE7D;;;;GAIG;AACH,MAAM,UAAU,cAAc,CAAC,OAAgB;IAC7C,MAAM,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,SAAS,CAAC,CAAC;IAC9C,IAAI,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,OAAO,GAAG,OAAO,CAAC,iBAAiB,CAAC;AAC7C,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,iBAAiB,CAAC,OAAe,EAAE,WAA0B;IAC3E,IAAI,WAAW,KAAK,IAAI;QAAE,OAAO,OAAO,CAAC;IACzC,IAAI,OAAO,IAAI,WAAW;QAAE,OAAO,KAAK,CAAC;IACzC,OAAO,EAAE,KAAK,EAAE,OAAO,EAAE,KAAK,EAAE,WAAW,GAAG,OAAO,EAAE,CAAC;AAC1D,CAAC"}
@@ -0,0 +1,22 @@
1
+ /**
2
+ * Artifacts module — the shared, bounded read of what a checkride run left in
3
+ * `.check/`. Parse the summary and pin its schema, judge each file against the
4
+ * run's freshness window, resolve a slot's raw output by the documented
5
+ * convention, and size what was found without opening it.
6
+ *
7
+ * Both bundled-plugin readers (`../triage` and `../qa`) consume the
8
+ * contract only through here — one copy of the summary parse,
9
+ * one freshness rule, one raw-output lookup. This barrel is the module's only
10
+ * public surface: siblings import from `../artifacts/index.js`, never from a
11
+ * file inside it.
12
+ */
13
+ export { configuredSlots } from './configured.js';
14
+ export { formatBytes, formatDuration, tail } from './format.js';
15
+ export { classifyFreshness, runWindowStart } from './freshness.js';
16
+ export type { Freshness } from './freshness.js';
17
+ export { asNumberOrNull, asRecord, asRecordArray, asStringOrNull, isRecord, parseJson } from './json.js';
18
+ export { listArtifacts, resolveRawOutput, statArtifact } from './raw.js';
19
+ export type { ArtifactFile, RawOutput } from './raw.js';
20
+ export { CHECK_DIR, parseSummary, readSummary, SUPPORTED_SCHEMA_VERSION } from './summary.js';
21
+ export type { SummaryRead } from './summary.js';
22
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/artifacts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACnE,YAAY,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAEhD,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEzG,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AACzE,YAAY,EAAE,YAAY,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAExD,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC;AAC9F,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,19 @@
1
+ /**
2
+ * Artifacts module — the shared, bounded read of what a checkride run left in
3
+ * `.check/`. Parse the summary and pin its schema, judge each file against the
4
+ * run's freshness window, resolve a slot's raw output by the documented
5
+ * convention, and size what was found without opening it.
6
+ *
7
+ * Both bundled-plugin readers (`../triage` and `../qa`) consume the
8
+ * contract only through here — one copy of the summary parse,
9
+ * one freshness rule, one raw-output lookup. This barrel is the module's only
10
+ * public surface: siblings import from `../artifacts/index.js`, never from a
11
+ * file inside it.
12
+ */
13
+ export { configuredSlots } from './configured.js';
14
+ export { formatBytes, formatDuration, tail } from './format.js';
15
+ export { classifyFreshness, runWindowStart } from './freshness.js';
16
+ export { asNumberOrNull, asRecord, asRecordArray, asStringOrNull, isRecord, parseJson } from './json.js';
17
+ export { listArtifacts, resolveRawOutput, statArtifact } from './raw.js';
18
+ export { CHECK_DIR, parseSummary, readSummary, SUPPORTED_SCHEMA_VERSION } from './summary.js';
19
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/artifacts/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAElD,OAAO,EAAE,WAAW,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAEhE,OAAO,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGnE,OAAO,EAAE,cAAc,EAAE,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AAEzG,OAAO,EAAE,aAAa,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,UAAU,CAAC;AAGzE,OAAO,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,wBAAwB,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Defensive JSON narrowing for artifact reads.
3
+ *
4
+ * Both readers parse files a *different* checkride version may have written, so
5
+ * every field access goes through a guard rather than a cast: a reader that
6
+ * crashes on an unexpected shape is worse than one that says what it could not
7
+ * read. These are the smallest primitives that make a `JSON.parse` result
8
+ * usable without `any` and without asserting a type onto unvalidated bytes.
9
+ *
10
+ * The `../artifacts` barrel is this module's only public surface.
11
+ */
12
+ import { isRecord } from '../json.js';
13
+ import type { JsonRecord } from '../json.js';
14
+ export { isRecord };
15
+ export type { JsonRecord };
16
+ /** A string field, or `null` for every other type — including a missing key. */
17
+ export declare function asStringOrNull(value: unknown): string | null;
18
+ /** A number field, or `null` for every other type — including a missing key. */
19
+ export declare function asNumberOrNull(value: unknown): number | null;
20
+ /**
21
+ * A nested object, or an empty one when the key is missing or holds something
22
+ * else. Reading a handful of fields off a block that may not exist is the
23
+ * common shape in these artifacts, and `{}` makes every such read a `null`
24
+ * rather than a branch at each call site.
25
+ */
26
+ export declare function asRecord(value: unknown): JsonRecord;
27
+ /** The object entries of an array field; `[]` when it is not an array at all. */
28
+ export declare function asRecordArray(value: unknown): JsonRecord[];
29
+ /** Parse JSON without throwing: the parsed value, or `null` when it is not JSON. */
30
+ export declare function parseJson(raw: string): unknown;
31
+ //# sourceMappingURL=json.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.d.ts","sourceRoot":"","sources":["../../src/artifacts/json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AACtC,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAK7C,OAAO,EAAE,QAAQ,EAAE,CAAC;AACpB,YAAY,EAAE,UAAU,EAAE,CAAC;AAE3B,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAE5D;AAED,gFAAgF;AAChF,wBAAgB,cAAc,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAE5D;AAED;;;;;GAKG;AACH,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,CAEnD;AAED,iFAAiF;AACjF,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,UAAU,EAAE,CAE1D;AAED,oFAAoF;AACpF,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAM9C"}
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Defensive JSON narrowing for artifact reads.
3
+ *
4
+ * Both readers parse files a *different* checkride version may have written, so
5
+ * every field access goes through a guard rather than a cast: a reader that
6
+ * crashes on an unexpected shape is worse than one that says what it could not
7
+ * read. These are the smallest primitives that make a `JSON.parse` result
8
+ * usable without `any` and without asserting a type onto unvalidated bytes.
9
+ *
10
+ * The `../artifacts` barrel is this module's only public surface.
11
+ */
12
+ import { isRecord } from '../json.js';
13
+ // `isRecord`/`JsonRecord` are the package-wide primitives (`../json.ts`);
14
+ // re-exported here so the artifacts barrel keeps its existing surface and the
15
+ // readers' import sites are unchanged.
16
+ export { isRecord };
17
+ /** A string field, or `null` for every other type — including a missing key. */
18
+ export function asStringOrNull(value) {
19
+ return typeof value === 'string' ? value : null;
20
+ }
21
+ /** A number field, or `null` for every other type — including a missing key. */
22
+ export function asNumberOrNull(value) {
23
+ return typeof value === 'number' ? value : null;
24
+ }
25
+ /**
26
+ * A nested object, or an empty one when the key is missing or holds something
27
+ * else. Reading a handful of fields off a block that may not exist is the
28
+ * common shape in these artifacts, and `{}` makes every such read a `null`
29
+ * rather than a branch at each call site.
30
+ */
31
+ export function asRecord(value) {
32
+ return isRecord(value) ? value : {};
33
+ }
34
+ /** The object entries of an array field; `[]` when it is not an array at all. */
35
+ export function asRecordArray(value) {
36
+ return Array.isArray(value) ? value.filter(isRecord) : [];
37
+ }
38
+ /** Parse JSON without throwing: the parsed value, or `null` when it is not JSON. */
39
+ export function parseJson(raw) {
40
+ try {
41
+ return JSON.parse(raw);
42
+ }
43
+ catch {
44
+ return null;
45
+ }
46
+ }
47
+ //# sourceMappingURL=json.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"json.js","sourceRoot":"","sources":["../../src/artifacts/json.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,YAAY,CAAC;AAGtC,0EAA0E;AAC1E,8EAA8E;AAC9E,uCAAuC;AACvC,OAAO,EAAE,QAAQ,EAAE,CAAC;AAGpB,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED,gFAAgF;AAChF,MAAM,UAAU,cAAc,CAAC,KAAc;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC;AAClD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,QAAQ,CAAC,KAAc;IACrC,OAAO,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;AACtC,CAAC;AAED,iFAAiF;AACjF,MAAM,UAAU,aAAa,CAAC,KAAc;IAC1C,OAAO,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC5D,CAAC;AAED,oFAAoF;AACpF,MAAM,UAAU,SAAS,CAAC,GAAW;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;IACzB,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Locating a slot's raw output — the bytes the summary indexes but usually does
3
+ * not name.
4
+ *
5
+ * `output_file` is populated only when a tool emits JSON on stdout, so most
6
+ * slots carry `null` there while their real output sits in `.check/` under the
7
+ * documented convention (`<slot>.json`, else `<slot>.stdout.txt` /
8
+ * `<slot>.stderr.txt`). On a full run of this repo, 8 of 17 checks name no file
9
+ * — `test` among them, the slot most likely to need triage. A reader that
10
+ * reported "no output" for those would be wrong about the one thing it exists
11
+ * to get right, so it owns the convention as a fallback.
12
+ *
13
+ * Everything found is measured, never opened: the readers report *sizes* and
14
+ * point at the file. `mutation.json` in this repo is 2.3 MB; `test.json` is
15
+ * 650 KB beside a 5 KB `test.stdout.txt` saying the same thing, which is why a
16
+ * smaller text sibling wins over a large JSON one.
17
+ *
18
+ * The `../artifacts` barrel is this module's only public surface.
19
+ */
20
+ import type { Freshness } from './freshness.js';
21
+ /** One measured `.check/` file. Size and standing only — never contents. */
22
+ export type ArtifactFile = {
23
+ /** Name within `.check/`, as an agent would type it: `lint.json`. */
24
+ file: string;
25
+ /** Absolute path, for a caller that does choose to open it. */
26
+ path: string;
27
+ bytes: number;
28
+ mtimeMs: number;
29
+ freshness: Freshness;
30
+ };
31
+ /**
32
+ * A slot's raw output: the file worth reading first, plus every other candidate
33
+ * found — so a caller can say what else is there instead of implying the chosen
34
+ * one is all of it.
35
+ */
36
+ export type RawOutput = {
37
+ chosen: ArtifactFile;
38
+ candidates: ArtifactFile[];
39
+ };
40
+ /** Measure one `.check/` file, or `null` when it does not exist. */
41
+ export declare function statArtifact(checkDir: string, file: string, windowStart: number | null): Promise<ArtifactFile | null>;
42
+ /**
43
+ * Measure every file directly in `checkDir`, name-ordered so the render is
44
+ * byte-stable. Subdirectories and anything that vanishes mid-read drop out;
45
+ * an absent directory is `[]`, because "there is nothing there" is an answer.
46
+ *
47
+ * This is the fallback index. Normally the summary names what to look at and
48
+ * {@link resolveRawOutput} locates it, but when the summary cannot be parsed
49
+ * the directory itself is the only inventory that exists — and a reader that
50
+ * gave up there would leave an agent to run `ls` by hand, which is the
51
+ * unbounded read this module exists to prevent.
52
+ */
53
+ export declare function listArtifacts(checkDir: string, windowStart: number | null): Promise<ArtifactFile[]>;
54
+ /**
55
+ * Resolve a slot's raw output under `checkDir`, freshness-gating whatever it
56
+ * finds — a stale candidate is labelled, not dropped. `null` only when the slot
57
+ * genuinely wrote nothing.
58
+ */
59
+ export declare function resolveRawOutput(checkDir: string, slot: string, outputFile: string | null, windowStart: number | null): Promise<RawOutput | null>;
60
+ //# sourceMappingURL=raw.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw.d.ts","sourceRoot":"","sources":["../../src/artifacts/raw.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAGhD,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG;IACzB,qEAAqE;IACrE,IAAI,EAAE,MAAM,CAAC;IACb,+DAA+D;IAC/D,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,SAAS,CAAC;CACtB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,SAAS,GAAG;IAAE,MAAM,EAAE,YAAY,CAAC;IAAC,UAAU,EAAE,YAAY,EAAE,CAAA;CAAE,CAAC;AAE7E,oEAAoE;AACpE,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CAS9B;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAWzG;AAwBD;;;;GAIG;AACH,wBAAsB,gBAAgB,CACpC,QAAQ,EAAE,MAAM,EAChB,IAAI,EAAE,MAAM,EACZ,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,WAAW,EAAE,MAAM,GAAG,IAAI,GACzB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAO3B"}
@@ -0,0 +1,91 @@
1
+ /**
2
+ * Locating a slot's raw output — the bytes the summary indexes but usually does
3
+ * not name.
4
+ *
5
+ * `output_file` is populated only when a tool emits JSON on stdout, so most
6
+ * slots carry `null` there while their real output sits in `.check/` under the
7
+ * documented convention (`<slot>.json`, else `<slot>.stdout.txt` /
8
+ * `<slot>.stderr.txt`). On a full run of this repo, 8 of 17 checks name no file
9
+ * — `test` among them, the slot most likely to need triage. A reader that
10
+ * reported "no output" for those would be wrong about the one thing it exists
11
+ * to get right, so it owns the convention as a fallback.
12
+ *
13
+ * Everything found is measured, never opened: the readers report *sizes* and
14
+ * point at the file. `mutation.json` in this repo is 2.3 MB; `test.json` is
15
+ * 650 KB beside a 5 KB `test.stdout.txt` saying the same thing, which is why a
16
+ * smaller text sibling wins over a large JSON one.
17
+ *
18
+ * The `../artifacts` barrel is this module's only public surface.
19
+ */
20
+ import { readdir, stat } from 'node:fs/promises';
21
+ import { join } from 'node:path';
22
+ import { classifyFreshness } from './freshness.js';
23
+ /** Measure one `.check/` file, or `null` when it does not exist. */
24
+ export async function statArtifact(checkDir, file, windowStart) {
25
+ const path = join(checkDir, file);
26
+ try {
27
+ const stats = await stat(path);
28
+ if (!stats.isFile())
29
+ return null;
30
+ return { file, path, bytes: stats.size, mtimeMs: stats.mtimeMs, freshness: classifyFreshness(stats.mtimeMs, windowStart) };
31
+ }
32
+ catch {
33
+ return null;
34
+ }
35
+ }
36
+ /**
37
+ * Measure every file directly in `checkDir`, name-ordered so the render is
38
+ * byte-stable. Subdirectories and anything that vanishes mid-read drop out;
39
+ * an absent directory is `[]`, because "there is nothing there" is an answer.
40
+ *
41
+ * This is the fallback index. Normally the summary names what to look at and
42
+ * {@link resolveRawOutput} locates it, but when the summary cannot be parsed
43
+ * the directory itself is the only inventory that exists — and a reader that
44
+ * gave up there would leave an agent to run `ls` by hand, which is the
45
+ * unbounded read this module exists to prevent.
46
+ */
47
+ export async function listArtifacts(checkDir, windowStart) {
48
+ let names;
49
+ try {
50
+ names = await readdir(checkDir);
51
+ }
52
+ catch {
53
+ return [];
54
+ }
55
+ const found = await Promise.all(names.toSorted().map((name) => statArtifact(checkDir, name, windowStart)));
56
+ return found.filter((file) => file !== null);
57
+ }
58
+ /**
59
+ * The convention, in priority order: what the summary named, then the JSON file,
60
+ * then the captured streams. Deduped, because `output_file` is usually
61
+ * `<slot>.json` when it is set at all.
62
+ */
63
+ function candidateNames(slot, outputFile) {
64
+ const names = [outputFile, `${slot}.json`, `${slot}.stdout.txt`, `${slot}.stderr.txt`];
65
+ return [...new Set(names.filter((name) => name !== null))];
66
+ }
67
+ /**
68
+ * Pick what to read first. The convention order wins, except that a *smaller*
69
+ * text sibling beats a large JSON file: `test.stdout.txt` (5 KB) carries the
70
+ * same failure `test.json` (650 KB) does, and a reader that sends an agent to
71
+ * the big one has spent the context it was built to save. A text file that is
72
+ * already first stays first — stdout is the diagnostics, stderr the leftovers.
73
+ */
74
+ function chooseRaw(first, rest) {
75
+ if (first.file.endsWith('.txt'))
76
+ return first;
77
+ return rest.find((c) => c.file.endsWith('.txt') && c.bytes < first.bytes) ?? first;
78
+ }
79
+ /**
80
+ * Resolve a slot's raw output under `checkDir`, freshness-gating whatever it
81
+ * finds — a stale candidate is labelled, not dropped. `null` only when the slot
82
+ * genuinely wrote nothing.
83
+ */
84
+ export async function resolveRawOutput(checkDir, slot, outputFile, windowStart) {
85
+ const found = await Promise.all(candidateNames(slot, outputFile).map((name) => statArtifact(checkDir, name, windowStart)));
86
+ const [first, ...rest] = found.filter((c) => c !== null);
87
+ if (first === undefined)
88
+ return null;
89
+ return { chosen: chooseRaw(first, rest), candidates: [first, ...rest] };
90
+ }
91
+ //# sourceMappingURL=raw.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"raw.js","sourceRoot":"","sources":["../../src/artifacts/raw.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAEH,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AACjD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAGjC,OAAO,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAoBnD,oEAAoE;AACpE,MAAM,CAAC,KAAK,UAAU,YAAY,CAChC,QAAgB,EAChB,IAAY,EACZ,WAA0B;IAE1B,MAAM,IAAI,GAAG,IAAI,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IAClC,IAAI,CAAC;QACH,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;YAAE,OAAO,IAAI,CAAC;QACjC,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,SAAS,EAAE,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC,EAAE,CAAC;IAC7H,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,QAAgB,EAAE,WAA0B;IAC9E,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,QAAQ,CAAC,CAAC;IAClC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,KAAK,CAAC,QAAQ,EAAE,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAC1E,CAAC;IACF,OAAO,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAwB,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AACrE,CAAC;AAED;;;;GAIG;AACH,SAAS,cAAc,CAAC,IAAY,EAAE,UAAyB;IAC7D,MAAM,KAAK,GAAG,CAAC,UAAU,EAAE,GAAG,IAAI,OAAO,EAAE,GAAG,IAAI,aAAa,EAAE,GAAG,IAAI,aAAa,CAAC,CAAC;IACvF,OAAO,CAAC,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAkB,EAAE,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC;AAC7E,CAAC;AAED;;;;;;GAMG;AACH,SAAS,SAAS,CAAC,KAAmB,EAAE,IAA6B;IACnE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC;QAAE,OAAO,KAAK,CAAC;IAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC;AACrF,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,QAAgB,EAChB,IAAY,EACZ,UAAyB,EACzB,WAA0B;IAE1B,MAAM,KAAK,GAAG,MAAM,OAAO,CAAC,GAAG,CAC7B,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,IAAI,EAAE,WAAW,CAAC,CAAC,CAC1F,CAAC;IACF,MAAM,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAqB,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC;IAC5E,IAAI,KAAK,KAAK,SAAS;QAAE,OAAO,IAAI,CAAC;IACrC,OAAO,EAAE,MAAM,EAAE,SAAS,CAAC,KAAK,EAAE,IAAI,CAAC,EAAE,UAAU,EAAE,CAAC,KAAK,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;AAC1E,CAAC"}
@@ -0,0 +1,69 @@
1
+ /**
2
+ * The `.check/summary.json` read — the one place either reader parses it.
3
+ *
4
+ * The summary is checkride's promised index: `schema_version`-ed, additive-only,
5
+ * deterministically ordered and crash-consistent. This module turns it into a
6
+ * five-state result rather than a value-or-throw, because every failure mode is
7
+ * something a reader has to *report* — a missing summary means the gate never
8
+ * wrote one, and a `schema_version` this reader does not understand means stop,
9
+ * not guess.
10
+ *
11
+ * `foreign` and `schema-mismatch` are deliberately separate states even though
12
+ * both end in "this reader cannot use the file". An absent `schema_version` is
13
+ * evidence the file was not written by checkride at all — a repo whose gate is
14
+ * a homegrown script that happens to write `.check/` — and the honest report
15
+ * there is "your gate is not checkride", not "STOP, version boundary". A
16
+ * `schema_version` of 2 is the opposite case: checkride wrote it, and a newer
17
+ * one, so guessing across the boundary is what has to stop.
18
+ *
19
+ * Validation here is deliberately structural, not schematic: the full JSON
20
+ * Schema lives in `schema/checkride.summary.schema.json` and is the engine's
21
+ * job. All this needs is enough narrowing that the fields the readers touch are
22
+ * the types they claim to be, with no cast onto unvalidated bytes.
23
+ *
24
+ * The `../artifacts` barrel is this module's only public surface.
25
+ */
26
+ import type { Summary } from '../orchestrator.js';
27
+ /** The gitignored directory every run writes its artifacts into. */
28
+ export declare const CHECK_DIR = ".check";
29
+ /**
30
+ * The only `schema_version` these readers understand.
31
+ *
32
+ * Deliberately a literal, not the engine's `SCHEMA_VERSION` import: the
33
+ * additive-only guarantee holds *within* a version and promises nothing across
34
+ * one, so a bump has to stop the reader loudly rather than be silently
35
+ * followed. `artifacts.test.ts` asserts this equals the engine's constant, so a
36
+ * future bump turns a test red — a deliberate update, never a quiet change of
37
+ * behavior.
38
+ */
39
+ export declare const SUPPORTED_SCHEMA_VERSION = 1;
40
+ /** The outcome of reading `.check/summary.json`. Every state is reportable. */
41
+ export type SummaryRead = {
42
+ state: 'ok';
43
+ path: string;
44
+ mtimeMs: number;
45
+ summary: Summary;
46
+ }
47
+ /** A JSON object with no `schema_version` at all — not checkride's file. */
48
+ | {
49
+ state: 'foreign';
50
+ path: string;
51
+ mtimeMs: number;
52
+ } | {
53
+ state: 'schema-mismatch';
54
+ path: string;
55
+ mtimeMs: number;
56
+ found: unknown;
57
+ } | {
58
+ state: 'unreadable';
59
+ path: string;
60
+ detail: string;
61
+ } | {
62
+ state: 'missing';
63
+ path: string;
64
+ };
65
+ /** Classify already-read bytes. Split out so tests can drive every state. */
66
+ export declare function parseSummary(raw: string, path: string, mtimeMs: number): SummaryRead;
67
+ /** Read and classify `<cwd>/.check/summary.json`. Never throws. */
68
+ export declare function readSummary(cwd: string): Promise<SummaryRead>;
69
+ //# sourceMappingURL=summary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.d.ts","sourceRoot":"","sources":["../../src/artifacts/summary.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAKH,OAAO,KAAK,EAAE,OAAO,EAAgB,MAAM,oBAAoB,CAAC;AAIhE,oEAAoE;AACpE,eAAO,MAAM,SAAS,WAAW,CAAC;AAKlC;;;;;;;;;GASG;AACH,eAAO,MAAM,wBAAwB,IAAI,CAAC;AAE1C,+EAA+E;AAC/E,MAAM,MAAM,WAAW,GACnB;IAAE,KAAK,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AAClE,4EAA4E;GAC1E;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,GACnD;IAAE,KAAK,EAAE,iBAAiB,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GAC3E;IAAE,KAAK,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,GACrD;IAAE,KAAK,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AA8CvC,6EAA6E;AAC7E,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,WAAW,CAcpF;AAED,mEAAmE;AACnE,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAQnE"}
@@ -0,0 +1,108 @@
1
+ /**
2
+ * The `.check/summary.json` read — the one place either reader parses it.
3
+ *
4
+ * The summary is checkride's promised index: `schema_version`-ed, additive-only,
5
+ * deterministically ordered and crash-consistent. This module turns it into a
6
+ * five-state result rather than a value-or-throw, because every failure mode is
7
+ * something a reader has to *report* — a missing summary means the gate never
8
+ * wrote one, and a `schema_version` this reader does not understand means stop,
9
+ * not guess.
10
+ *
11
+ * `foreign` and `schema-mismatch` are deliberately separate states even though
12
+ * both end in "this reader cannot use the file". An absent `schema_version` is
13
+ * evidence the file was not written by checkride at all — a repo whose gate is
14
+ * a homegrown script that happens to write `.check/` — and the honest report
15
+ * there is "your gate is not checkride", not "STOP, version boundary". A
16
+ * `schema_version` of 2 is the opposite case: checkride wrote it, and a newer
17
+ * one, so guessing across the boundary is what has to stop.
18
+ *
19
+ * Validation here is deliberately structural, not schematic: the full JSON
20
+ * Schema lives in `schema/checkride.summary.schema.json` and is the engine's
21
+ * job. All this needs is enough narrowing that the fields the readers touch are
22
+ * the types they claim to be, with no cast onto unvalidated bytes.
23
+ *
24
+ * The `../artifacts` barrel is this module's only public surface.
25
+ */
26
+ import { readFile, stat } from 'node:fs/promises';
27
+ import { join } from 'node:path';
28
+ import { isRecord, parseJson } from './json.js';
29
+ /** The gitignored directory every run writes its artifacts into. */
30
+ export const CHECK_DIR = '.check';
31
+ /** The aggregate report, beside the raw artifacts under {@link CHECK_DIR}. */
32
+ const SUMMARY_FILE = 'summary.json';
33
+ /**
34
+ * The only `schema_version` these readers understand.
35
+ *
36
+ * Deliberately a literal, not the engine's `SCHEMA_VERSION` import: the
37
+ * additive-only guarantee holds *within* a version and promises nothing across
38
+ * one, so a bump has to stop the reader loudly rather than be silently
39
+ * followed. `artifacts.test.ts` asserts this equals the engine's constant, so a
40
+ * future bump turns a test red — a deliberate update, never a quiet change of
41
+ * behavior.
42
+ */
43
+ export const SUPPORTED_SCHEMA_VERSION = 1;
44
+ /**
45
+ * Name, adapter and description are present and the right type. Bracket access
46
+ * throughout: these are unvalidated bytes, and reading them as a dynamic record
47
+ * is what they are.
48
+ */
49
+ function hasCheckIdentity(value) {
50
+ return (typeof value['name'] === 'string' &&
51
+ typeof value['description'] === 'string' &&
52
+ (typeof value['adapter'] === 'string' || value['adapter'] === null));
53
+ }
54
+ /** The result fields the readers render are present and the right type. */
55
+ function hasCheckOutcome(value) {
56
+ return (typeof value['ok'] === 'boolean' &&
57
+ typeof value['duration_ms'] === 'number' &&
58
+ (typeof value['exit_code'] === 'number' || value['exit_code'] === null) &&
59
+ (typeof value['output_file'] === 'string' || value['output_file'] === null));
60
+ }
61
+ /**
62
+ * One `checks[]` entry. The optional additive fields (`skipped`, `reason`,
63
+ * `baselined`) are read through `??` at the point of use, so they need no guard.
64
+ */
65
+ function isCheck(value) {
66
+ return isRecord(value) && hasCheckIdentity(value) && hasCheckOutcome(value);
67
+ }
68
+ /** Every required top-level field, and a well-formed `checks[]`. */
69
+ function isSummary(value) {
70
+ const checks = value['checks'];
71
+ return (typeof value['timestamp'] === 'string' &&
72
+ typeof value['ok'] === 'boolean' &&
73
+ typeof value['checks_run'] === 'number' &&
74
+ typeof value['total_duration_ms'] === 'number' &&
75
+ Array.isArray(checks) &&
76
+ checks.every(isCheck));
77
+ }
78
+ /** Classify already-read bytes. Split out so tests can drive every state. */
79
+ export function parseSummary(raw, path, mtimeMs) {
80
+ const value = parseJson(raw);
81
+ if (!isRecord(value))
82
+ return { state: 'unreadable', path, detail: 'not a JSON object' };
83
+ // Provenance first, then version: a summary this reader cannot read is a
84
+ // whose-file-is-this problem or a version problem, not a shape problem, even
85
+ // when its other fields also fail to narrow. Key presence rather than value,
86
+ // so an explicit `"schema_version": null` stays a mismatch — a malformed
87
+ // checkride summary — instead of being read as a stranger's file.
88
+ if (!('schema_version' in value))
89
+ return { state: 'foreign', path, mtimeMs };
90
+ if (value['schema_version'] !== SUPPORTED_SCHEMA_VERSION) {
91
+ return { state: 'schema-mismatch', path, mtimeMs, found: value['schema_version'] };
92
+ }
93
+ if (!isSummary(value))
94
+ return { state: 'unreadable', path, detail: 'missing or mistyped required field(s)' };
95
+ return { state: 'ok', path, mtimeMs, summary: value };
96
+ }
97
+ /** Read and classify `<cwd>/.check/summary.json`. Never throws. */
98
+ export async function readSummary(cwd) {
99
+ const path = join(cwd, CHECK_DIR, SUMMARY_FILE);
100
+ try {
101
+ const [stats, raw] = await Promise.all([stat(path), readFile(path, 'utf8')]);
102
+ return parseSummary(raw, path, stats.mtimeMs);
103
+ }
104
+ catch {
105
+ return { state: 'missing', path };
106
+ }
107
+ }
108
+ //# sourceMappingURL=summary.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"summary.js","sourceRoot":"","sources":["../../src/artifacts/summary.ts"],"names":[],"mappings":"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"}
@@ -8,6 +8,21 @@
8
8
  * version or the new complete version — `rename(2)` is atomic within a
9
9
  * directory — never torn.
10
10
  */
11
- /** Write `data` to `path` atomically: temp sibling first, then rename over. */
11
+ /**
12
+ * Write `data` to `path` atomically: temp sibling, flushed to disk, then
13
+ * renamed over.
14
+ *
15
+ * The `fsync` before the rename is what makes the promise above true rather
16
+ * than nearly true. `rename(2)` is atomic for the *name*, but a write that is
17
+ * still sitting in the page cache when the machine loses power can leave the
18
+ * renamed inode holding nothing — the reader then finds a file that exists and
19
+ * is empty, which is the torn read this exists to prevent, just relocated.
20
+ *
21
+ * The containing directory is deliberately not synced. Without that, the
22
+ * rename itself may not survive a crash — but the reader then sees the
23
+ * *previous complete version*, which is exactly what is promised. Paying a
24
+ * second fsync per artifact to also guarantee which of the two you get is not
25
+ * worth it for a report that the next run rewrites anyway.
26
+ */
12
27
  export declare function writeFileAtomic(path: string, data: string): Promise<void>;
13
28
  //# sourceMappingURL=atomic.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"atomic.d.ts","sourceRoot":"","sources":["../src/atomic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,+EAA+E;AAC/E,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAS/E"}
1
+ {"version":3,"file":"atomic.d.ts","sourceRoot":"","sources":["../src/atomic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAe/E"}
@@ -8,12 +8,34 @@
8
8
  * version or the new complete version — `rename(2)` is atomic within a
9
9
  * directory — never torn.
10
10
  */
11
- import { rename, rm, writeFile } from 'node:fs/promises';
12
- /** Write `data` to `path` atomically: temp sibling first, then rename over. */
11
+ import { open, rename, rm } from 'node:fs/promises';
12
+ /**
13
+ * Write `data` to `path` atomically: temp sibling, flushed to disk, then
14
+ * renamed over.
15
+ *
16
+ * The `fsync` before the rename is what makes the promise above true rather
17
+ * than nearly true. `rename(2)` is atomic for the *name*, but a write that is
18
+ * still sitting in the page cache when the machine loses power can leave the
19
+ * renamed inode holding nothing — the reader then finds a file that exists and
20
+ * is empty, which is the torn read this exists to prevent, just relocated.
21
+ *
22
+ * The containing directory is deliberately not synced. Without that, the
23
+ * rename itself may not survive a crash — but the reader then sees the
24
+ * *previous complete version*, which is exactly what is promised. Paying a
25
+ * second fsync per artifact to also guarantee which of the two you get is not
26
+ * worth it for a report that the next run rewrites anyway.
27
+ */
13
28
  export async function writeFileAtomic(path, data) {
14
29
  const tmp = `${path}.${process.pid}.tmp`;
15
30
  try {
16
- await writeFile(tmp, data);
31
+ const handle = await open(tmp, 'w');
32
+ try {
33
+ await handle.writeFile(data);
34
+ await handle.sync();
35
+ }
36
+ finally {
37
+ await handle.close();
38
+ }
17
39
  await rename(tmp, path);
18
40
  }
19
41
  catch (err) {
@@ -1 +1 @@
1
- {"version":3,"file":"atomic.js","sourceRoot":"","sources":["../src/atomic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,MAAM,EAAE,EAAE,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAEzD,+EAA+E;AAC/E,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY;IAC9D,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QAC3B,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"atomic.js","sourceRoot":"","sources":["../src/atomic.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAEH,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEpD;;;;;;;;;;;;;;;GAeG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAY,EAAE,IAAY;IAC9D,MAAM,GAAG,GAAG,GAAG,IAAI,IAAI,OAAO,CAAC,GAAG,MAAM,CAAC;IACzC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;QACpC,IAAI,CAAC;YACH,MAAM,MAAM,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;YAC7B,MAAM,MAAM,CAAC,IAAI,EAAE,CAAC;QACtB,CAAC;gBAAS,CAAC;YACT,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QACvB,CAAC;QACD,MAAM,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;IAC1B,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC/B,MAAM,GAAG,CAAC;IACZ,CAAC;AACH,CAAC"}