ctxr-cli 0.1.0

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 (390) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +25 -0
  3. package/dist/adapter.d.ts +18 -0
  4. package/dist/adapter.d.ts.map +1 -0
  5. package/dist/adapter.js +4 -0
  6. package/dist/adapter.js.map +1 -0
  7. package/dist/adapters/builtin/index.d.ts +10 -0
  8. package/dist/adapters/builtin/index.d.ts.map +1 -0
  9. package/dist/adapters/builtin/index.js +11 -0
  10. package/dist/adapters/builtin/index.js.map +1 -0
  11. package/dist/adapters/forge/github.d.ts +9 -0
  12. package/dist/adapters/forge/github.d.ts.map +1 -0
  13. package/dist/adapters/forge/github.js +36 -0
  14. package/dist/adapters/forge/github.js.map +1 -0
  15. package/dist/adapters/forge/types.d.ts +23 -0
  16. package/dist/adapters/forge/types.d.ts.map +1 -0
  17. package/dist/adapters/forge/types.js +2 -0
  18. package/dist/adapters/forge/types.js.map +1 -0
  19. package/dist/adapters/harness/claude-code.d.ts +9 -0
  20. package/dist/adapters/harness/claude-code.d.ts.map +1 -0
  21. package/dist/adapters/harness/claude-code.js +42 -0
  22. package/dist/adapters/harness/claude-code.js.map +1 -0
  23. package/dist/adapters/identity/claude-code.d.ts +11 -0
  24. package/dist/adapters/identity/claude-code.d.ts.map +1 -0
  25. package/dist/adapters/identity/claude-code.js +18 -0
  26. package/dist/adapters/identity/claude-code.js.map +1 -0
  27. package/dist/adapters/registry.d.ts +16 -0
  28. package/dist/adapters/registry.d.ts.map +1 -0
  29. package/dist/adapters/registry.js +29 -0
  30. package/dist/adapters/registry.js.map +1 -0
  31. package/dist/adapters/types.d.ts +65 -0
  32. package/dist/adapters/types.d.ts.map +1 -0
  33. package/dist/adapters/types.js +12 -0
  34. package/dist/adapters/types.js.map +1 -0
  35. package/dist/bin.d.ts +3 -0
  36. package/dist/bin.d.ts.map +1 -0
  37. package/dist/bin.js +6 -0
  38. package/dist/bin.js.map +1 -0
  39. package/dist/commands/adapters-generate.d.ts +23 -0
  40. package/dist/commands/adapters-generate.d.ts.map +1 -0
  41. package/dist/commands/adapters-generate.js +59 -0
  42. package/dist/commands/adapters-generate.js.map +1 -0
  43. package/dist/commands/archive.d.ts +28 -0
  44. package/dist/commands/archive.d.ts.map +1 -0
  45. package/dist/commands/archive.js +66 -0
  46. package/dist/commands/archive.js.map +1 -0
  47. package/dist/commands/catalog-build.d.ts +7 -0
  48. package/dist/commands/catalog-build.d.ts.map +1 -0
  49. package/dist/commands/catalog-build.js +15 -0
  50. package/dist/commands/catalog-build.js.map +1 -0
  51. package/dist/commands/catalog-check.d.ts +22 -0
  52. package/dist/commands/catalog-check.d.ts.map +1 -0
  53. package/dist/commands/catalog-check.js +49 -0
  54. package/dist/commands/catalog-check.js.map +1 -0
  55. package/dist/commands/catalog-show.d.ts +13 -0
  56. package/dist/commands/catalog-show.d.ts.map +1 -0
  57. package/dist/commands/catalog-show.js +19 -0
  58. package/dist/commands/catalog-show.js.map +1 -0
  59. package/dist/commands/check.d.ts +22 -0
  60. package/dist/commands/check.d.ts.map +1 -0
  61. package/dist/commands/check.js +43 -0
  62. package/dist/commands/check.js.map +1 -0
  63. package/dist/commands/doctor.d.ts +27 -0
  64. package/dist/commands/doctor.d.ts.map +1 -0
  65. package/dist/commands/doctor.js +53 -0
  66. package/dist/commands/doctor.js.map +1 -0
  67. package/dist/commands/graph-build.d.ts +24 -0
  68. package/dist/commands/graph-build.d.ts.map +1 -0
  69. package/dist/commands/graph-build.js +36 -0
  70. package/dist/commands/graph-build.js.map +1 -0
  71. package/dist/commands/graph-query.d.ts +41 -0
  72. package/dist/commands/graph-query.d.ts.map +1 -0
  73. package/dist/commands/graph-query.js +63 -0
  74. package/dist/commands/graph-query.js.map +1 -0
  75. package/dist/commands/ingest.d.ts +28 -0
  76. package/dist/commands/ingest.d.ts.map +1 -0
  77. package/dist/commands/ingest.js +60 -0
  78. package/dist/commands/ingest.js.map +1 -0
  79. package/dist/commands/init.d.ts +28 -0
  80. package/dist/commands/init.d.ts.map +1 -0
  81. package/dist/commands/init.js +203 -0
  82. package/dist/commands/init.js.map +1 -0
  83. package/dist/commands/lint.d.ts +30 -0
  84. package/dist/commands/lint.d.ts.map +1 -0
  85. package/dist/commands/lint.js +48 -0
  86. package/dist/commands/lint.js.map +1 -0
  87. package/dist/commands/migrate.d.ts +30 -0
  88. package/dist/commands/migrate.d.ts.map +1 -0
  89. package/dist/commands/migrate.js +56 -0
  90. package/dist/commands/migrate.js.map +1 -0
  91. package/dist/commands/note-resolve.d.ts +14 -0
  92. package/dist/commands/note-resolve.d.ts.map +1 -0
  93. package/dist/commands/note-resolve.js +24 -0
  94. package/dist/commands/note-resolve.js.map +1 -0
  95. package/dist/commands/rollup-gather.d.ts +21 -0
  96. package/dist/commands/rollup-gather.d.ts.map +1 -0
  97. package/dist/commands/rollup-gather.js +40 -0
  98. package/dist/commands/rollup-gather.js.map +1 -0
  99. package/dist/commands/rollup-write.d.ts +25 -0
  100. package/dist/commands/rollup-write.d.ts.map +1 -0
  101. package/dist/commands/rollup-write.js +43 -0
  102. package/dist/commands/rollup-write.js.map +1 -0
  103. package/dist/commands/session-abandon.d.ts +13 -0
  104. package/dist/commands/session-abandon.d.ts.map +1 -0
  105. package/dist/commands/session-abandon.js +22 -0
  106. package/dist/commands/session-abandon.js.map +1 -0
  107. package/dist/commands/session-list.d.ts +14 -0
  108. package/dist/commands/session-list.d.ts.map +1 -0
  109. package/dist/commands/session-list.js +19 -0
  110. package/dist/commands/session-list.js.map +1 -0
  111. package/dist/commands/session-reap.d.ts +22 -0
  112. package/dist/commands/session-reap.d.ts.map +1 -0
  113. package/dist/commands/session-reap.js +47 -0
  114. package/dist/commands/session-reap.js.map +1 -0
  115. package/dist/commands/session-start.d.ts +18 -0
  116. package/dist/commands/session-start.d.ts.map +1 -0
  117. package/dist/commands/session-start.js +36 -0
  118. package/dist/commands/session-start.js.map +1 -0
  119. package/dist/commands/session-submit.d.ts +27 -0
  120. package/dist/commands/session-submit.d.ts.map +1 -0
  121. package/dist/commands/session-submit.js +68 -0
  122. package/dist/commands/session-submit.js.map +1 -0
  123. package/dist/commands/source-check.d.ts +21 -0
  124. package/dist/commands/source-check.d.ts.map +1 -0
  125. package/dist/commands/source-check.js +54 -0
  126. package/dist/commands/source-check.js.map +1 -0
  127. package/dist/commands/source-hash.d.ts +14 -0
  128. package/dist/commands/source-hash.d.ts.map +1 -0
  129. package/dist/commands/source-hash.js +34 -0
  130. package/dist/commands/source-hash.js.map +1 -0
  131. package/dist/commands/update.d.ts +17 -0
  132. package/dist/commands/update.d.ts.map +1 -0
  133. package/dist/commands/update.js +25 -0
  134. package/dist/commands/update.js.map +1 -0
  135. package/dist/commands/verify.d.ts +23 -0
  136. package/dist/commands/verify.d.ts.map +1 -0
  137. package/dist/commands/verify.js +126 -0
  138. package/dist/commands/verify.js.map +1 -0
  139. package/dist/config/defaults.d.ts +69 -0
  140. package/dist/config/defaults.d.ts.map +1 -0
  141. package/dist/config/defaults.js +71 -0
  142. package/dist/config/defaults.js.map +1 -0
  143. package/dist/config/load.d.ts +11 -0
  144. package/dist/config/load.d.ts.map +1 -0
  145. package/dist/config/load.js +49 -0
  146. package/dist/config/load.js.map +1 -0
  147. package/dist/config/render.d.ts +9 -0
  148. package/dist/config/render.d.ts.map +1 -0
  149. package/dist/config/render.js +15 -0
  150. package/dist/config/render.js.map +1 -0
  151. package/dist/config/schema.d.ts +124 -0
  152. package/dist/config/schema.d.ts.map +1 -0
  153. package/dist/config/schema.js +142 -0
  154. package/dist/config/schema.js.map +1 -0
  155. package/dist/core/agents-doc.d.ts +80 -0
  156. package/dist/core/agents-doc.d.ts.map +1 -0
  157. package/dist/core/agents-doc.js +207 -0
  158. package/dist/core/agents-doc.js.map +1 -0
  159. package/dist/core/catalog/build.d.ts +49 -0
  160. package/dist/core/catalog/build.d.ts.map +1 -0
  161. package/dist/core/catalog/build.js +113 -0
  162. package/dist/core/catalog/build.js.map +1 -0
  163. package/dist/core/catalog/model.d.ts +33 -0
  164. package/dist/core/catalog/model.d.ts.map +1 -0
  165. package/dist/core/catalog/model.js +58 -0
  166. package/dist/core/catalog/model.js.map +1 -0
  167. package/dist/core/checks/catalog-checks.d.ts +4 -0
  168. package/dist/core/checks/catalog-checks.d.ts.map +1 -0
  169. package/dist/core/checks/catalog-checks.js +65 -0
  170. package/dist/core/checks/catalog-checks.js.map +1 -0
  171. package/dist/core/checks/identity-checks.d.ts +11 -0
  172. package/dist/core/checks/identity-checks.d.ts.map +1 -0
  173. package/dist/core/checks/identity-checks.js +39 -0
  174. package/dist/core/checks/identity-checks.js.map +1 -0
  175. package/dist/core/checks/integrity-checks.d.ts +23 -0
  176. package/dist/core/checks/integrity-checks.d.ts.map +1 -0
  177. package/dist/core/checks/integrity-checks.js +132 -0
  178. package/dist/core/checks/integrity-checks.js.map +1 -0
  179. package/dist/core/checks/manifest.d.ts +7 -0
  180. package/dist/core/checks/manifest.d.ts.map +1 -0
  181. package/dist/core/checks/manifest.js +20 -0
  182. package/dist/core/checks/manifest.js.map +1 -0
  183. package/dist/core/checks/organize-checks.d.ts +18 -0
  184. package/dist/core/checks/organize-checks.d.ts.map +1 -0
  185. package/dist/core/checks/organize-checks.js +97 -0
  186. package/dist/core/checks/organize-checks.js.map +1 -0
  187. package/dist/core/checks/registry.d.ts +24 -0
  188. package/dist/core/checks/registry.d.ts.map +1 -0
  189. package/dist/core/checks/registry.js +33 -0
  190. package/dist/core/checks/registry.js.map +1 -0
  191. package/dist/core/checks/types.d.ts +72 -0
  192. package/dist/core/checks/types.d.ts.map +1 -0
  193. package/dist/core/checks/types.js +4 -0
  194. package/dist/core/checks/types.js.map +1 -0
  195. package/dist/core/checks/write-lifecycle-checks.d.ts +24 -0
  196. package/dist/core/checks/write-lifecycle-checks.d.ts.map +1 -0
  197. package/dist/core/checks/write-lifecycle-checks.js +205 -0
  198. package/dist/core/checks/write-lifecycle-checks.js.map +1 -0
  199. package/dist/core/command.d.ts +23 -0
  200. package/dist/core/command.d.ts.map +1 -0
  201. package/dist/core/command.js +2 -0
  202. package/dist/core/command.js.map +1 -0
  203. package/dist/core/content/canonicalize.d.ts +14 -0
  204. package/dist/core/content/canonicalize.d.ts.map +1 -0
  205. package/dist/core/content/canonicalize.js +34 -0
  206. package/dist/core/content/canonicalize.js.map +1 -0
  207. package/dist/core/conventions.d.ts +21 -0
  208. package/dist/core/conventions.d.ts.map +1 -0
  209. package/dist/core/conventions.js +73 -0
  210. package/dist/core/conventions.js.map +1 -0
  211. package/dist/core/disclosure/model.d.ts +18 -0
  212. package/dist/core/disclosure/model.d.ts.map +1 -0
  213. package/dist/core/disclosure/model.js +45 -0
  214. package/dist/core/disclosure/model.js.map +1 -0
  215. package/dist/core/env.d.ts +40 -0
  216. package/dist/core/env.d.ts.map +1 -0
  217. package/dist/core/env.js +24 -0
  218. package/dist/core/env.js.map +1 -0
  219. package/dist/core/envelope.d.ts +46 -0
  220. package/dist/core/envelope.d.ts.map +1 -0
  221. package/dist/core/envelope.js +21 -0
  222. package/dist/core/envelope.js.map +1 -0
  223. package/dist/core/errors.d.ts +96 -0
  224. package/dist/core/errors.d.ts.map +1 -0
  225. package/dist/core/errors.js +267 -0
  226. package/dist/core/errors.js.map +1 -0
  227. package/dist/core/exit-codes.d.ts +32 -0
  228. package/dist/core/exit-codes.d.ts.map +1 -0
  229. package/dist/core/exit-codes.js +31 -0
  230. package/dist/core/exit-codes.js.map +1 -0
  231. package/dist/core/fs/atomic.d.ts +10 -0
  232. package/dist/core/fs/atomic.d.ts.map +1 -0
  233. package/dist/core/fs/atomic.js +31 -0
  234. package/dist/core/fs/atomic.js.map +1 -0
  235. package/dist/core/fs/fenced-region.d.ts +47 -0
  236. package/dist/core/fs/fenced-region.d.ts.map +1 -0
  237. package/dist/core/fs/fenced-region.js +122 -0
  238. package/dist/core/fs/fenced-region.js.map +1 -0
  239. package/dist/core/git/exec.d.ts +28 -0
  240. package/dist/core/git/exec.d.ts.map +1 -0
  241. package/dist/core/git/exec.js +21 -0
  242. package/dist/core/git/exec.js.map +1 -0
  243. package/dist/core/git/repo.d.ts +63 -0
  244. package/dist/core/git/repo.d.ts.map +1 -0
  245. package/dist/core/git/repo.js +91 -0
  246. package/dist/core/git/repo.js.map +1 -0
  247. package/dist/core/git/staged.d.ts +10 -0
  248. package/dist/core/git/staged.d.ts.map +1 -0
  249. package/dist/core/git/staged.js +49 -0
  250. package/dist/core/git/staged.js.map +1 -0
  251. package/dist/core/git/worktree.d.ts +29 -0
  252. package/dist/core/git/worktree.d.ts.map +1 -0
  253. package/dist/core/git/worktree.js +61 -0
  254. package/dist/core/git/worktree.js.map +1 -0
  255. package/dist/core/graph/model.d.ts +43 -0
  256. package/dist/core/graph/model.d.ts.map +1 -0
  257. package/dist/core/graph/model.js +60 -0
  258. package/dist/core/graph/model.js.map +1 -0
  259. package/dist/core/graph/persist.d.ts +7 -0
  260. package/dist/core/graph/persist.d.ts.map +1 -0
  261. package/dist/core/graph/persist.js +23 -0
  262. package/dist/core/graph/persist.js.map +1 -0
  263. package/dist/core/graph/query.d.ts +16 -0
  264. package/dist/core/graph/query.d.ts.map +1 -0
  265. package/dist/core/graph/query.js +91 -0
  266. package/dist/core/graph/query.js.map +1 -0
  267. package/dist/core/graph/visibility-filter.d.ts +13 -0
  268. package/dist/core/graph/visibility-filter.d.ts.map +1 -0
  269. package/dist/core/graph/visibility-filter.js +26 -0
  270. package/dist/core/graph/visibility-filter.js.map +1 -0
  271. package/dist/core/hooks.d.ts +34 -0
  272. package/dist/core/hooks.d.ts.map +1 -0
  273. package/dist/core/hooks.js +89 -0
  274. package/dist/core/hooks.js.map +1 -0
  275. package/dist/core/identity.d.ts +14 -0
  276. package/dist/core/identity.d.ts.map +1 -0
  277. package/dist/core/identity.js +36 -0
  278. package/dist/core/identity.js.map +1 -0
  279. package/dist/core/ingest/identity.d.ts +15 -0
  280. package/dist/core/ingest/identity.d.ts.map +1 -0
  281. package/dist/core/ingest/identity.js +17 -0
  282. package/dist/core/ingest/identity.js.map +1 -0
  283. package/dist/core/ingest/model.d.ts +17 -0
  284. package/dist/core/ingest/model.d.ts.map +1 -0
  285. package/dist/core/ingest/model.js +24 -0
  286. package/dist/core/ingest/model.js.map +1 -0
  287. package/dist/core/json-config-merge.d.ts +13 -0
  288. package/dist/core/json-config-merge.d.ts.map +1 -0
  289. package/dist/core/json-config-merge.js +43 -0
  290. package/dist/core/json-config-merge.js.map +1 -0
  291. package/dist/core/markers.d.ts +17 -0
  292. package/dist/core/markers.d.ts.map +1 -0
  293. package/dist/core/markers.js +16 -0
  294. package/dist/core/markers.js.map +1 -0
  295. package/dist/core/migrations/registry.d.ts +6 -0
  296. package/dist/core/migrations/registry.d.ts.map +1 -0
  297. package/dist/core/migrations/registry.js +8 -0
  298. package/dist/core/migrations/registry.js.map +1 -0
  299. package/dist/core/migrations/rename-visibility-field.d.ts +3 -0
  300. package/dist/core/migrations/rename-visibility-field.d.ts.map +1 -0
  301. package/dist/core/migrations/rename-visibility-field.js +62 -0
  302. package/dist/core/migrations/rename-visibility-field.js.map +1 -0
  303. package/dist/core/migrations/types.d.ts +27 -0
  304. package/dist/core/migrations/types.d.ts.map +1 -0
  305. package/dist/core/migrations/types.js +2 -0
  306. package/dist/core/migrations/types.js.map +1 -0
  307. package/dist/core/notes/checks.d.ts +20 -0
  308. package/dist/core/notes/checks.d.ts.map +1 -0
  309. package/dist/core/notes/checks.js +58 -0
  310. package/dist/core/notes/checks.js.map +1 -0
  311. package/dist/core/notes/list.d.ts +26 -0
  312. package/dist/core/notes/list.d.ts.map +1 -0
  313. package/dist/core/notes/list.js +84 -0
  314. package/dist/core/notes/list.js.map +1 -0
  315. package/dist/core/notes/parse.d.ts +12 -0
  316. package/dist/core/notes/parse.d.ts.map +1 -0
  317. package/dist/core/notes/parse.js +36 -0
  318. package/dist/core/notes/parse.js.map +1 -0
  319. package/dist/core/notes/render.d.ts +7 -0
  320. package/dist/core/notes/render.d.ts.map +1 -0
  321. package/dist/core/notes/render.js +13 -0
  322. package/dist/core/notes/render.js.map +1 -0
  323. package/dist/core/notes/visibility.d.ts +26 -0
  324. package/dist/core/notes/visibility.d.ts.map +1 -0
  325. package/dist/core/notes/visibility.js +41 -0
  326. package/dist/core/notes/visibility.js.map +1 -0
  327. package/dist/core/procedures.d.ts +44 -0
  328. package/dist/core/procedures.d.ts.map +1 -0
  329. package/dist/core/procedures.js +154 -0
  330. package/dist/core/procedures.js.map +1 -0
  331. package/dist/core/queue.d.ts +16 -0
  332. package/dist/core/queue.d.ts.map +1 -0
  333. package/dist/core/queue.js +75 -0
  334. package/dist/core/queue.js.map +1 -0
  335. package/dist/core/reconcile.d.ts +18 -0
  336. package/dist/core/reconcile.d.ts.map +1 -0
  337. package/dist/core/reconcile.js +49 -0
  338. package/dist/core/reconcile.js.map +1 -0
  339. package/dist/core/records.d.ts +16 -0
  340. package/dist/core/records.d.ts.map +1 -0
  341. package/dist/core/records.js +36 -0
  342. package/dist/core/records.js.map +1 -0
  343. package/dist/core/reporter.d.ts +20 -0
  344. package/dist/core/reporter.d.ts.map +1 -0
  345. package/dist/core/reporter.js +25 -0
  346. package/dist/core/reporter.js.map +1 -0
  347. package/dist/core/root.d.ts +24 -0
  348. package/dist/core/root.d.ts.map +1 -0
  349. package/dist/core/root.js +51 -0
  350. package/dist/core/root.js.map +1 -0
  351. package/dist/core/security/secrets.d.ts +17 -0
  352. package/dist/core/security/secrets.d.ts.map +1 -0
  353. package/dist/core/security/secrets.js +21 -0
  354. package/dist/core/security/secrets.js.map +1 -0
  355. package/dist/core/session.d.ts +15 -0
  356. package/dist/core/session.d.ts.map +1 -0
  357. package/dist/core/session.js +27 -0
  358. package/dist/core/session.js.map +1 -0
  359. package/dist/core/store.d.ts +15 -0
  360. package/dist/core/store.d.ts.map +1 -0
  361. package/dist/core/store.js +19 -0
  362. package/dist/core/store.js.map +1 -0
  363. package/dist/index.d.ts +13 -0
  364. package/dist/index.d.ts.map +1 -0
  365. package/dist/index.js +7 -0
  366. package/dist/index.js.map +1 -0
  367. package/dist/prompt/inquirer-prompter.d.ts +14 -0
  368. package/dist/prompt/inquirer-prompter.d.ts.map +1 -0
  369. package/dist/prompt/inquirer-prompter.js +27 -0
  370. package/dist/prompt/inquirer-prompter.js.map +1 -0
  371. package/dist/prompt/prompter.d.ts +24 -0
  372. package/dist/prompt/prompter.d.ts.map +1 -0
  373. package/dist/prompt/prompter.js +2 -0
  374. package/dist/prompt/prompter.js.map +1 -0
  375. package/dist/run.d.ts +16 -0
  376. package/dist/run.d.ts.map +1 -0
  377. package/dist/run.js +464 -0
  378. package/dist/run.js.map +1 -0
  379. package/dist/taxonomy/profiles.d.ts +31 -0
  380. package/dist/taxonomy/profiles.d.ts.map +1 -0
  381. package/dist/taxonomy/profiles.js +45 -0
  382. package/dist/taxonomy/profiles.js.map +1 -0
  383. package/dist/version.d.ts +3 -0
  384. package/dist/version.d.ts.map +1 -0
  385. package/dist/version.js +3 -0
  386. package/dist/version.js.map +1 -0
  387. package/package.json +56 -0
  388. package/templates/.gitkeep +0 -0
  389. package/templates/hooks/pre-commit.sh +21 -0
  390. package/templates/hooks/pre-push.sh +24 -0
@@ -0,0 +1,97 @@
1
+ import { checkCatalogCoverage } from '../catalog/build.js';
2
+ import { orphans } from '../graph/query.js';
3
+ import { hasSourceIdentity } from '../ingest/identity.js';
4
+ import { defineCheck } from './types.js';
5
+ const GRAPH_SKIP_REASON = 'graph has not been built yet — run `ctxr graph build`';
6
+ /** context-organize spec: "orphaned notes" — reported by lint, never failed by doctor. */
7
+ export const orphanNotesCheck = defineCheck({
8
+ id: 'organize.orphan_notes',
9
+ title: 'Notes with no links in or out',
10
+ severity: 'observation',
11
+ capability: 'context-organize',
12
+ scopes: ['store'],
13
+ async run(ctx) {
14
+ const graph = await ctx.graph();
15
+ if (!graph)
16
+ return { status: 'skip', skipReason: GRAPH_SKIP_REASON, findings: [] };
17
+ const findings = orphans(graph).map((id) => ({
18
+ code: 'organize.orphan_note',
19
+ severity: 'info',
20
+ message: `"${id}" has no links in or out.`,
21
+ subject: id,
22
+ }));
23
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
24
+ },
25
+ });
26
+ /** context-organize spec: "broken links" — the graph's dangling links (not_found or ambiguous), reported not failed. Shares detection with the doctor-facing invariant checks/integrity-checks.ts:graphDanglingLinksCheck under a different id (task 9.4: two ids, two severity lanes, one condition, never double-counted within a single run). */
27
+ export const brokenLinksCheck = defineCheck({
28
+ id: 'organize.broken_links',
29
+ title: 'Notes with dangling wikilinks',
30
+ severity: 'observation',
31
+ capability: 'context-organize',
32
+ scopes: ['store'],
33
+ async run(ctx) {
34
+ const graph = await ctx.graph();
35
+ if (!graph)
36
+ return { status: 'skip', skipReason: GRAPH_SKIP_REASON, findings: [] };
37
+ const findings = graph.dangling.map((d) => ({
38
+ code: 'organize.broken_link',
39
+ severity: 'info',
40
+ message: `"${d.from}" links to "${d.target}", which is ${d.reason === 'ambiguous' ? 'ambiguous' : 'not found'}.`,
41
+ subject: d.from,
42
+ details: { target: d.target, reason: d.reason },
43
+ }));
44
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
45
+ },
46
+ });
47
+ /** context-ingest / context-organize: material captured but never stamped with source identity. */
48
+ export const uningestedInboxCheck = defineCheck({
49
+ id: 'organize.uningested_inbox_material',
50
+ title: 'Inbox material not yet ingested',
51
+ severity: 'observation',
52
+ capability: 'context-organize',
53
+ scopes: ['store'],
54
+ async run(ctx) {
55
+ const notes = await ctx.notes();
56
+ const prefix = ctx.config.ingest.inbox_path.endsWith('/')
57
+ ? ctx.config.ingest.inbox_path
58
+ : `${ctx.config.ingest.inbox_path}/`;
59
+ const findings = notes
60
+ .filter((note) => note.path.startsWith(prefix) && !hasSourceIdentity(note))
61
+ .map((note) => ({
62
+ code: 'organize.uningested_inbox_material',
63
+ severity: 'info',
64
+ message: `"${note.path}" is in the inbox but has not been ingested.`,
65
+ subject: note.path,
66
+ }));
67
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
68
+ },
69
+ });
70
+ /**
71
+ * context-organize spec: "notes with no catalog entry as covered by
72
+ * context-catalog" — the same underlying condition as `catalogCoverageCheck`
73
+ * (doctor, invariant), surfaced here too as its own observation-severity
74
+ * check id so lint can report it without doctor's invariant double-counting
75
+ * lint's finding or vice versa (same pattern as the fail-closed-visibility
76
+ * pair in Phase 5). Only `missing` is in scope here — `dangling` catalog
77
+ * entries are a stricter integrity concern doctor alone owns.
78
+ */
79
+ export const catalogGapsLintCheck = defineCheck({
80
+ id: 'organize.catalog_gaps',
81
+ title: 'Notes with no catalog entry',
82
+ severity: 'observation',
83
+ capability: 'context-catalog',
84
+ scopes: ['store'],
85
+ async run(ctx) {
86
+ const { missing } = await checkCatalogCoverage({ root: ctx.storeRoot, config: ctx.config });
87
+ const findings = missing.map((notePath) => ({
88
+ code: 'catalog.coverage.missing',
89
+ severity: 'info',
90
+ message: `"${notePath}" is retrievable but has no catalog entry.`,
91
+ subject: notePath,
92
+ }));
93
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
94
+ },
95
+ });
96
+ export const ORGANIZE_CHECKS = [orphanNotesCheck, brokenLinksCheck, uningestedInboxCheck, catalogGapsLintCheck];
97
+ //# sourceMappingURL=organize-checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"organize-checks.js","sourceRoot":"","sources":["../../../src/core/checks/organize-checks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,24 @@
1
+ import type { CheckContext, CheckDefinition, CheckResult, CheckScope, CheckSeverity } from './types.js';
2
+ export interface CheckReport {
3
+ id: string;
4
+ title: string;
5
+ capability: string;
6
+ severity: CheckSeverity;
7
+ result: CheckResult;
8
+ }
9
+ export interface RunSelection {
10
+ scope: CheckScope;
11
+ /** Restrict to these check ids, if given. */
12
+ only?: readonly string[];
13
+ severity?: CheckSeverity;
14
+ }
15
+ /**
16
+ * The dispatch every phase's checks run through, and the one thing that must
17
+ * never change after Phase 0: extending the system means appending an
18
+ * import and an array entry to manifest.ts — a data change, not a change to
19
+ * this function.
20
+ */
21
+ export declare function runChecks(defs: readonly CheckDefinition[], ctx: CheckContext, selection: RunSelection): Promise<CheckReport[]>;
22
+ /** doctor exits non-zero only when a real invariant failed; skips and passes both succeed. */
23
+ export declare function overallStatus(reports: readonly CheckReport[]): 'pass' | 'fail';
24
+ //# sourceMappingURL=registry.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.d.ts","sourceRoot":"","sources":["../../../src/core/checks/registry.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,WAAW,EAAE,UAAU,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAExG,MAAM,WAAW,WAAW;IAC1B,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,aAAa,CAAC;IACxB,MAAM,EAAE,WAAW,CAAC;CACrB;AAED,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,UAAU,CAAC;IAClB,6CAA6C;IAC7C,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IACzB,QAAQ,CAAC,EAAE,aAAa,CAAC;CAC1B;AAED;;;;;GAKG;AACH,wBAAsB,SAAS,CAC7B,IAAI,EAAE,SAAS,eAAe,EAAE,EAChC,GAAG,EAAE,YAAY,EACjB,SAAS,EAAE,YAAY,GACtB,OAAO,CAAC,WAAW,EAAE,CAAC,CAyBxB;AAED,8FAA8F;AAC9F,wBAAgB,aAAa,CAAC,OAAO,EAAE,SAAS,WAAW,EAAE,GAAG,MAAM,GAAG,MAAM,CAE9E"}
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The dispatch every phase's checks run through, and the one thing that must
3
+ * never change after Phase 0: extending the system means appending an
4
+ * import and an array entry to manifest.ts — a data change, not a change to
5
+ * this function.
6
+ */
7
+ export async function runChecks(defs, ctx, selection) {
8
+ const applicable = defs.filter((d) => d.scopes.includes(selection.scope) &&
9
+ (!selection.only || selection.only.includes(d.id)) &&
10
+ (!selection.severity || d.severity === selection.severity));
11
+ const reports = [];
12
+ for (const def of applicable) {
13
+ const gate = def.appliesTo?.(ctx);
14
+ if (gate && !gate.applicable) {
15
+ reports.push({
16
+ id: def.id,
17
+ title: def.title,
18
+ capability: def.capability,
19
+ severity: def.severity,
20
+ result: { status: 'skip', skipReason: gate.reason, findings: [] },
21
+ });
22
+ continue;
23
+ }
24
+ const result = await def.run(ctx);
25
+ reports.push({ id: def.id, title: def.title, capability: def.capability, severity: def.severity, result });
26
+ }
27
+ return reports;
28
+ }
29
+ /** doctor exits non-zero only when a real invariant failed; skips and passes both succeed. */
30
+ export function overallStatus(reports) {
31
+ return reports.some((r) => r.result.status === 'fail') ? 'fail' : 'pass';
32
+ }
33
+ //# sourceMappingURL=registry.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"registry.js","sourceRoot":"","sources":["../../../src/core/checks/registry.ts"],"names":[],"mappings":"AAiBA;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,SAAS,CAC7B,IAAgC,EAChC,GAAiB,EACjB,SAAuB;IAEvB,MAAM,UAAU,GAAG,IAAI,CAAC,MAAM,CAC5B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC;QAClC,CAAC,CAAC,SAAS,CAAC,IAAI,IAAI,SAAS,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAClD,CAAC,CAAC,SAAS,CAAC,QAAQ,IAAI,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,QAAQ,CAAC,CAC7D,CAAC;IAEF,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,GAAG,IAAI,UAAU,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,GAAG,CAAC,SAAS,EAAE,CAAC,GAAG,CAAC,CAAC;QAClC,IAAI,IAAI,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAC7B,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,CAAC,EAAE;gBACV,KAAK,EAAE,GAAG,CAAC,KAAK;gBAChB,UAAU,EAAE,GAAG,CAAC,UAAU;gBAC1B,QAAQ,EAAE,GAAG,CAAC,QAAQ;gBACtB,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,IAAI,CAAC,MAAM,EAAE,QAAQ,EAAE,EAAE,EAAE;aAClE,CAAC,CAAC;YACH,SAAS;QACX,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAClC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,GAAG,CAAC,EAAE,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,EAAE,UAAU,EAAE,GAAG,CAAC,UAAU,EAAE,QAAQ,EAAE,GAAG,CAAC,QAAQ,EAAE,MAAM,EAAE,CAAC,CAAC;IAC7G,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,8FAA8F;AAC9F,MAAM,UAAU,aAAa,CAAC,OAA+B;IAC3D,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC;AAC3E,CAAC"}
@@ -0,0 +1,72 @@
1
+ import type { StoreConfig } from '../../config/schema.js';
2
+ import type { Finding } from '../envelope.js';
3
+ import type { GitRunner } from '../git/exec.js';
4
+ import type { GraphBuildResult } from '../graph/model.js';
5
+ import type { Note } from '../notes/list.js';
6
+ /**
7
+ * `doctor` (invariant checks, fails a run) and `lint` (observation checks,
8
+ * never fails a run — context-organize spec) run off the SAME registry,
9
+ * distinguished only by `severity`. This is what makes Phase 9.4 ("no
10
+ * condition double-counted as both a lint finding and a doctor failure") a
11
+ * type constraint instead of a manual audit six phases later.
12
+ */
13
+ export type CheckSeverity = 'invariant' | 'observation';
14
+ export type CheckStatus = 'pass' | 'fail' | 'skip';
15
+ /**
16
+ * `'staged'` exists from Phase 0 even though nothing uses it yet, because
17
+ * Phase 2.2's pre-commit hook runs `doctor --staged` against a check subset
18
+ * that store-scope checks (like Phase 3's catalog coverage) don't belong in.
19
+ * Omitting this now would mean building a second dispatcher in Phase 2.
20
+ */
21
+ export type CheckScope = 'store' | 'staged';
22
+ export interface CheckResult {
23
+ status: CheckStatus;
24
+ /** Required when status === 'skip'. */
25
+ skipReason?: string;
26
+ findings: Finding[];
27
+ summary?: string;
28
+ }
29
+ /**
30
+ * Memoized accessors shared across every check in one run. Reserved with
31
+ * this shape from Phase 0 so that by Phase 9 — when catalog coverage,
32
+ * dangling-link, identity-collision, fail-closed-visibility, and gloss-rot
33
+ * checks all need the full note set — adding memoization doesn't mean
34
+ * changing `run()`'s signature across six phases of accumulated checks.
35
+ */
36
+ export interface StagedFile {
37
+ path: string;
38
+ status: 'A' | 'M' | 'D' | 'R' | '?';
39
+ addedLines: number | null;
40
+ removedLines: number | null;
41
+ /** Staged (index) content, for non-deleted text files; undefined for deletions or unread files. */
42
+ content?: string;
43
+ }
44
+ export interface CheckContext {
45
+ readonly storeRoot: string;
46
+ readonly config: StoreConfig;
47
+ readonly scope: CheckScope;
48
+ readonly git: GitRunner;
49
+ /** Populated only when scope === 'staged'. */
50
+ readonly staged?: readonly StagedFile[];
51
+ notes(): Promise<readonly Note[]>;
52
+ graph(): Promise<GraphBuildResult | null>;
53
+ catalog(): Promise<unknown>;
54
+ }
55
+ export interface CheckDefinition {
56
+ /** Stable, lowercase-dotted id — part of the --json contract once shipped. */
57
+ id: string;
58
+ title: string;
59
+ severity: CheckSeverity;
60
+ /** Which capability this check verifies, e.g. "context-catalog" — traceability to the spec. */
61
+ capability: string;
62
+ scopes: readonly CheckScope[];
63
+ appliesTo?(ctx: CheckContext): {
64
+ applicable: true;
65
+ } | {
66
+ applicable: false;
67
+ reason: string;
68
+ };
69
+ run(ctx: CheckContext): Promise<CheckResult>;
70
+ }
71
+ export declare function defineCheck(def: CheckDefinition): CheckDefinition;
72
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/core/checks/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC1D,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,gBAAgB,CAAC;AAC9C,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAChD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,mBAAmB,CAAC;AAC1D,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,kBAAkB,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,MAAM,aAAa,GAAG,WAAW,GAAG,aAAa,CAAC;AACxD,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,MAAM,GAAG,MAAM,CAAC;AAEnD;;;;;GAKG;AACH,MAAM,MAAM,UAAU,GAAG,OAAO,GAAG,QAAQ,CAAC;AAE5C,MAAM,WAAW,WAAW;IAC1B,MAAM,EAAE,WAAW,CAAC;IACpB,uCAAuC;IACvC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,MAAM,CAAC;IACb,MAAM,EAAE,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;IACpC,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,mGAAmG;IACnG,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,WAAW,CAAC;IAC7B,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,GAAG,EAAE,SAAS,CAAC;IACxB,8CAA8C;IAC9C,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,UAAU,EAAE,CAAC;IACxC,KAAK,IAAI,OAAO,CAAC,SAAS,IAAI,EAAE,CAAC,CAAC;IAClC,KAAK,IAAI,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IAC1C,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;CAC7B;AAED,MAAM,WAAW,eAAe;IAC9B,8EAA8E;IAC9E,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,aAAa,CAAC;IACxB,+FAA+F;IAC/F,UAAU,EAAE,MAAM,CAAC;IACnB,MAAM,EAAE,SAAS,UAAU,EAAE,CAAC;IAC9B,SAAS,CAAC,CAAC,GAAG,EAAE,YAAY,GAAG;QAAE,UAAU,EAAE,IAAI,CAAA;KAAE,GAAG;QAAE,UAAU,EAAE,KAAK,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAC5F,GAAG,CAAC,GAAG,EAAE,YAAY,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;CAC9C;AAED,wBAAgB,WAAW,CAAC,GAAG,EAAE,eAAe,GAAG,eAAe,CAEjE"}
@@ -0,0 +1,4 @@
1
+ export function defineCheck(def) {
2
+ return def;
3
+ }
4
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/checks/types.ts"],"names":[],"mappings":"AAwEA,MAAM,UAAU,WAAW,CAAC,GAAoB;IAC9C,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,24 @@
1
+ /**
2
+ * write-lifecycle spec: pre-commit's five staged checks. Each is severity:
3
+ * invariant, scoped to 'staged' only — none of them run (or affect anything)
4
+ * during a plain `doctor` (store-scope) invocation.
5
+ */
6
+ export declare const stagedSchemaConformanceCheck: import("./types.js").CheckDefinition;
7
+ export declare const stagedFenceIntegrityCheck: import("./types.js").CheckDefinition;
8
+ export declare const stagedSecretScanCheck: import("./types.js").CheckDefinition;
9
+ /**
10
+ * The concrete, testable interpretation of "path allowlist": a declared
11
+ * derived path must never be committed (context-store spec) — staging one
12
+ * is refused here rather than merely documented as a convention.
13
+ */
14
+ export declare const stagedPathAllowlistCheck: import("./types.js").CheckDefinition;
15
+ export declare const stagedDiffSizeCeilingCheck: import("./types.js").CheckDefinition;
16
+ /**
17
+ * store-scope (not staged): are both hooks present with current content,
18
+ * and is core.hooksPath actually pointed at them? Self-heals by
19
+ * reinstalling on drift — a narrow, documented exception to "doctor only
20
+ * reads" for exactly this git-plumbing self-repair (task 2.4).
21
+ */
22
+ export declare const hooksHealthCheck: import("./types.js").CheckDefinition;
23
+ export declare const WRITE_LIFECYCLE_CHECKS: import("./types.js").CheckDefinition[];
24
+ //# sourceMappingURL=write-lifecycle-checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-lifecycle-checks.d.ts","sourceRoot":"","sources":["../../../src/core/checks/write-lifecycle-checks.ts"],"names":[],"mappings":"AAWA;;;;GAIG;AACH,eAAO,MAAM,4BAA4B,sCAyCvC,CAAC;AAEH,eAAO,MAAM,yBAAyB,sCAsBpC,CAAC;AAEH,eAAO,MAAM,qBAAqB,sCAqBhC,CAAC;AAEH;;;;GAIG;AACH,eAAO,MAAM,wBAAwB,sCAyBnC,CAAC;AAEH,eAAO,MAAM,0BAA0B,sCA2BrC,CAAC;AAEH;;;;;GAKG;AACH,eAAO,MAAM,gBAAgB,sCAiC3B,CAAC;AAEH,eAAO,MAAM,sBAAsB,wCAOlC,CAAC"}
@@ -0,0 +1,205 @@
1
+ import { StoreConfigSchema } from '../../config/schema.js';
2
+ import { parse as parseYaml } from 'yaml';
3
+ import { configureHooksPath, detectStaleHooks, getConfiguredHooksPath, installHooks } from '../hooks.js';
4
+ import { parseNoteText } from '../notes/parse.js';
5
+ import { scanForSecrets } from '../security/secrets.js';
6
+ import { validateFenceIntegrity } from '../fs/fenced-region.js';
7
+ import { defineCheck } from './types.js';
8
+ const CONFIG_FILE_NAME = 'contexture.yaml';
9
+ /**
10
+ * write-lifecycle spec: pre-commit's five staged checks. Each is severity:
11
+ * invariant, scoped to 'staged' only — none of them run (or affect anything)
12
+ * during a plain `doctor` (store-scope) invocation.
13
+ */
14
+ export const stagedSchemaConformanceCheck = defineCheck({
15
+ id: 'staged.schema_conformance',
16
+ title: 'Staged contexture.yaml and note frontmatter parse and validate',
17
+ severity: 'invariant',
18
+ capability: 'write-lifecycle',
19
+ scopes: ['staged'],
20
+ async run(ctx) {
21
+ const findings = [];
22
+ for (const file of ctx.staged ?? []) {
23
+ if (file.status === 'D' || file.content === undefined)
24
+ continue;
25
+ if (file.path === CONFIG_FILE_NAME) {
26
+ const result = StoreConfigSchema.safeParse(parseYaml(file.content));
27
+ if (!result.success) {
28
+ findings.push({
29
+ code: 'staged.schema_conformance.invalid_config',
30
+ severity: 'error',
31
+ message: `Staged "${file.path}" fails schema validation: ${result.error.issues
32
+ .map((i) => `${i.path.join('.') || '(root)'}: ${i.message}`)
33
+ .join('; ')}`,
34
+ subject: file.path,
35
+ });
36
+ }
37
+ continue;
38
+ }
39
+ if (file.path.endsWith('.md')) {
40
+ try {
41
+ parseNoteText(file.content, file.path);
42
+ }
43
+ catch (err) {
44
+ findings.push({
45
+ code: 'staged.schema_conformance.invalid_frontmatter',
46
+ severity: 'error',
47
+ message: err instanceof Error ? err.message : String(err),
48
+ subject: file.path,
49
+ });
50
+ }
51
+ }
52
+ }
53
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
54
+ },
55
+ });
56
+ export const stagedFenceIntegrityCheck = defineCheck({
57
+ id: 'staged.fence_integrity',
58
+ title: 'Staged files have no unpaired or duplicated generated-region markers',
59
+ severity: 'invariant',
60
+ capability: 'write-lifecycle',
61
+ scopes: ['staged'],
62
+ async run(ctx) {
63
+ const findings = [];
64
+ for (const file of ctx.staged ?? []) {
65
+ if (file.status === 'D' || file.content === undefined)
66
+ continue;
67
+ const problems = validateFenceIntegrity(file.content);
68
+ for (const problem of problems) {
69
+ findings.push({
70
+ code: 'staged.fence_integrity.mismatch',
71
+ severity: 'error',
72
+ message: `"${file.path}": ${problem}`,
73
+ subject: file.path,
74
+ });
75
+ }
76
+ }
77
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
78
+ },
79
+ });
80
+ export const stagedSecretScanCheck = defineCheck({
81
+ id: 'staged.secret_scan',
82
+ title: 'Staged content matches no known secret pattern',
83
+ severity: 'invariant',
84
+ capability: 'write-lifecycle',
85
+ scopes: ['staged'],
86
+ async run(ctx) {
87
+ const findings = [];
88
+ for (const file of ctx.staged ?? []) {
89
+ if (file.status === 'D' || file.content === undefined)
90
+ continue;
91
+ for (const match of scanForSecrets(file.content)) {
92
+ findings.push({
93
+ code: 'staged.secret_scan.match',
94
+ severity: 'error',
95
+ message: `"${file.path}:${match.line}" matches the ${match.patternId} secret pattern.`,
96
+ subject: file.path,
97
+ });
98
+ }
99
+ }
100
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
101
+ },
102
+ });
103
+ /**
104
+ * The concrete, testable interpretation of "path allowlist": a declared
105
+ * derived path must never be committed (context-store spec) — staging one
106
+ * is refused here rather than merely documented as a convention.
107
+ */
108
+ export const stagedPathAllowlistCheck = defineCheck({
109
+ id: 'staged.path_allowlist',
110
+ title: 'No staged file is under a declared derived path',
111
+ severity: 'invariant',
112
+ capability: 'write-lifecycle',
113
+ scopes: ['staged'],
114
+ async run(ctx) {
115
+ const findings = [];
116
+ for (const file of ctx.staged ?? []) {
117
+ if (file.status === 'D')
118
+ continue;
119
+ const underDerived = ctx.config.derived.paths.some((derivedPath) => {
120
+ const normalized = derivedPath.endsWith('/') ? derivedPath : `${derivedPath}/`;
121
+ return file.path.startsWith(normalized);
122
+ });
123
+ if (underDerived) {
124
+ findings.push({
125
+ code: 'staged.path_allowlist.derived_path',
126
+ severity: 'error',
127
+ message: `"${file.path}" is under a declared derived path and must never be committed.`,
128
+ subject: file.path,
129
+ });
130
+ }
131
+ }
132
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
133
+ },
134
+ });
135
+ export const stagedDiffSizeCeilingCheck = defineCheck({
136
+ id: 'staged.diff_size_ceiling',
137
+ title: 'Total staged diff size is under the configured ceiling',
138
+ severity: 'invariant',
139
+ capability: 'write-lifecycle',
140
+ scopes: ['staged'],
141
+ async run(ctx) {
142
+ const total = (ctx.staged ?? []).reduce((sum, file) => sum + (file.addedLines ?? 0) + (file.removedLines ?? 0), 0);
143
+ const ceiling = ctx.config.write_lifecycle.diff_size_ceiling_lines;
144
+ if (total > ceiling) {
145
+ return {
146
+ status: 'fail',
147
+ findings: [
148
+ {
149
+ code: 'staged.diff_size_ceiling.exceeded',
150
+ severity: 'error',
151
+ message: `Staged changes total ${total} changed lines, exceeding the configured ceiling of ${ceiling}.`,
152
+ details: { total, ceiling },
153
+ },
154
+ ],
155
+ };
156
+ }
157
+ return { status: 'pass', findings: [] };
158
+ },
159
+ });
160
+ /**
161
+ * store-scope (not staged): are both hooks present with current content,
162
+ * and is core.hooksPath actually pointed at them? Self-heals by
163
+ * reinstalling on drift — a narrow, documented exception to "doctor only
164
+ * reads" for exactly this git-plumbing self-repair (task 2.4).
165
+ */
166
+ export const hooksHealthCheck = defineCheck({
167
+ id: 'git.hooks_health',
168
+ title: 'Version-controlled hooks are installed, current, and wired via core.hooksPath',
169
+ severity: 'invariant',
170
+ capability: 'write-lifecycle',
171
+ scopes: ['store'],
172
+ async run(ctx) {
173
+ const findings = [];
174
+ const defaultBranch = ctx.config.git.default_branch;
175
+ const stale = await detectStaleHooks(ctx.storeRoot, defaultBranch);
176
+ if (stale.length > 0) {
177
+ await installHooks(ctx.storeRoot, defaultBranch);
178
+ findings.push({
179
+ code: 'git.hooks_health.reinstalled',
180
+ severity: 'warning',
181
+ message: `Reinstalled stale hook(s): ${stale.join(', ')}.`,
182
+ details: { stale },
183
+ });
184
+ }
185
+ const hooksPath = await getConfiguredHooksPath(ctx.git, ctx.storeRoot);
186
+ if (hooksPath !== '.githooks') {
187
+ await configureHooksPath(ctx.git, ctx.storeRoot);
188
+ findings.push({
189
+ code: 'git.hooks_health.path_reconfigured',
190
+ severity: 'warning',
191
+ message: `core.hooksPath was "${hooksPath ?? '(unset)'}"; reconfigured to ".githooks".`,
192
+ });
193
+ }
194
+ return { status: findings.length > 0 ? 'fail' : 'pass', findings };
195
+ },
196
+ });
197
+ export const WRITE_LIFECYCLE_CHECKS = [
198
+ stagedSchemaConformanceCheck,
199
+ stagedFenceIntegrityCheck,
200
+ stagedSecretScanCheck,
201
+ stagedPathAllowlistCheck,
202
+ stagedDiffSizeCeilingCheck,
203
+ hooksHealthCheck,
204
+ ];
205
+ //# sourceMappingURL=write-lifecycle-checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"write-lifecycle-checks.js","sourceRoot":"","sources":["../../../src/core/checks/write-lifecycle-checks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,23 @@
1
+ import type { Finding } from './envelope.js';
2
+ import type { ExitCode } from './exit-codes.js';
3
+ /**
4
+ * Declarative, per-command metadata read uniformly by run.ts's dispatcher —
5
+ * `init` is the one command that declares `store: 'absent'`; every other
6
+ * command requires an already-opened store. This is what keeps `init`'s
7
+ * exception to the usual git-check/schema-gate an enumerated, testable fact
8
+ * rather than an `if (commandName === 'init')` special case in the
9
+ * dispatcher.
10
+ */
11
+ export interface CommandRequires {
12
+ store: 'required' | 'absent';
13
+ }
14
+ export interface CommandOutcome<TData> {
15
+ exitCode: ExitCode;
16
+ data: TData | null;
17
+ findings: Finding[];
18
+ /** One-line human-readable summary, used when --json is not passed. */
19
+ humanSummary: string;
20
+ storeRoot: string | null;
21
+ schemaVersion: number | null;
22
+ }
23
+ //# sourceMappingURL=command.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.d.ts","sourceRoot":"","sources":["../../src/core/command.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAC7C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,iBAAiB,CAAC;AAEhD;;;;;;;GAOG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,GAAG,QAAQ,CAAC;CAC9B;AAED,MAAM,WAAW,cAAc,CAAC,KAAK;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC;IACnB,QAAQ,EAAE,OAAO,EAAE,CAAC;IACpB,uEAAuE;IACvE,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,aAAa,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=command.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command.js","sourceRoot":"","sources":["../../src/core/command.ts"],"names":[],"mappings":""}
@@ -0,0 +1,14 @@
1
+ /**
2
+ * context-ingest spec: "Canonicalization is a single shared primitive" that
3
+ * exists in exactly one place — content matching (dedupe, catalog
4
+ * gloss-rot) never inlines or reimplements this. Pipeline: strip a BOM,
5
+ * normalize line endings, rstrip each line, collapse trailing blank lines.
6
+ */
7
+ export declare function canonicalizeText(text: string): string;
8
+ /** Strips frontmatter from raw file text, then canonicalizes the body. */
9
+ export declare function canonicalizeBody(raw: string, notePath?: string): string;
10
+ /** context-ingest spec: a 16-character SHA-256 prefix of the canonicalized body, from raw source text. */
11
+ export declare function contentHash(raw: string, notePath?: string): string;
12
+ /** Same hash, computed from an already-parsed note's body (no frontmatter to strip). */
13
+ export declare function contentHashOfBody(body: string): string;
14
+ //# sourceMappingURL=canonicalize.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize.d.ts","sourceRoot":"","sources":["../../../src/core/content/canonicalize.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQrD;AAED,0EAA0E;AAC1E,wBAAgB,gBAAgB,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAc,GAAG,MAAM,CAG5E;AAMD,0GAA0G;AAC1G,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,QAAQ,SAAc,GAAG,MAAM,CAEvE;AAED,wFAAwF;AACxF,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEtD"}
@@ -0,0 +1,34 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { parseNoteText } from '../notes/parse.js';
3
+ /**
4
+ * context-ingest spec: "Canonicalization is a single shared primitive" that
5
+ * exists in exactly one place — content matching (dedupe, catalog
6
+ * gloss-rot) never inlines or reimplements this. Pipeline: strip a BOM,
7
+ * normalize line endings, rstrip each line, collapse trailing blank lines.
8
+ */
9
+ export function canonicalizeText(text) {
10
+ const withoutBom = text.charCodeAt(0) === 0xfeff ? text.slice(1) : text;
11
+ const normalizedNewlines = withoutBom.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
12
+ const lines = normalizedNewlines.split('\n').map((line) => line.replace(/[ \t]+$/, ''));
13
+ while (lines.length > 0 && lines[lines.length - 1] === '') {
14
+ lines.pop();
15
+ }
16
+ return lines.join('\n');
17
+ }
18
+ /** Strips frontmatter from raw file text, then canonicalizes the body. */
19
+ export function canonicalizeBody(raw, notePath = '(unknown)') {
20
+ const { body } = parseNoteText(raw, notePath);
21
+ return canonicalizeText(body);
22
+ }
23
+ function hashText(text) {
24
+ return createHash('sha256').update(text, 'utf8').digest('hex').slice(0, 16);
25
+ }
26
+ /** context-ingest spec: a 16-character SHA-256 prefix of the canonicalized body, from raw source text. */
27
+ export function contentHash(raw, notePath = '(unknown)') {
28
+ return hashText(canonicalizeBody(raw, notePath));
29
+ }
30
+ /** Same hash, computed from an already-parsed note's body (no frontmatter to strip). */
31
+ export function contentHashOfBody(body) {
32
+ return hashText(canonicalizeText(body));
33
+ }
34
+ //# sourceMappingURL=canonicalize.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonicalize.js","sourceRoot":"","sources":["../../../src/core/content/canonicalize.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAElD;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAAC,IAAY;IAC3C,MAAM,UAAU,GAAG,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC,KAAK,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IACxE,MAAM,kBAAkB,GAAG,UAAU,CAAC,OAAO,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;IAClF,MAAM,KAAK,GAAG,kBAAkB,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC,CAAC;IACxF,OAAO,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC;QAC1D,KAAK,CAAC,GAAG,EAAE,CAAC;IACd,CAAC;IACD,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED,0EAA0E;AAC1E,MAAM,UAAU,gBAAgB,CAAC,GAAW,EAAE,QAAQ,GAAG,WAAW;IAClE,MAAM,EAAE,IAAI,EAAE,GAAG,aAAa,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC;IAC9C,OAAO,gBAAgB,CAAC,IAAI,CAAC,CAAC;AAChC,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED,0GAA0G;AAC1G,MAAM,UAAU,WAAW,CAAC,GAAW,EAAE,QAAQ,GAAG,WAAW;IAC7D,OAAO,QAAQ,CAAC,gBAAgB,CAAC,GAAG,EAAE,QAAQ,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,iBAAiB,CAAC,IAAY;IAC5C,OAAO,QAAQ,CAAC,gBAAgB,CAAC,IAAI,CAAC,CAAC,CAAC;AAC1C,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { StoreConfig } from '../config/schema.js';
2
+ /**
3
+ * harness-portability spec (entry-doc-generation): operator-authored
4
+ * convention documents and (via scanProcedures in procedures.ts) procedure
5
+ * files are indexed from what is actually on disk — adding a file is the
6
+ * entire integration. Metadata extraction order: frontmatter title →
7
+ * first `# ` heading → filename stem; description only from frontmatter.
8
+ */
9
+ export interface ScannedDoc {
10
+ /** Path relative to the store root, forward-slash separated. */
11
+ path: string;
12
+ title: string;
13
+ description: string | null;
14
+ }
15
+ /** The skill-layout filename: `<slug>/SKILL.md` — what harnesses with skill auto-discovery read. */
16
+ export declare const SKILL_FILE_NAME = "SKILL.md";
17
+ export declare function extractDocMetadata(raw: string, relativePath: string): ScannedDoc;
18
+ export declare function scanDocsDir(root: string, dirRelativePath: string): Promise<ScannedDoc[]>;
19
+ /** Every operator convention doc currently at the configured path. */
20
+ export declare function scanConventions(root: string, config: StoreConfig): Promise<ScannedDoc[]>;
21
+ //# sourceMappingURL=conventions.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conventions.d.ts","sourceRoot":"","sources":["../../src/core/conventions.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAGvD;;;;;;GAMG;AACH,MAAM,WAAW,UAAU;IACzB,gEAAgE;IAChE,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAID,oGAAoG;AACpG,eAAO,MAAM,eAAe,aAAa,CAAC;AAE1C,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,GAAG,UAAU,CA2BhF;AAED,wBAAsB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,eAAe,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAgC9F;AAED,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAExF"}