wingfoil 0.2.2 → 0.3.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 (454) hide show
  1. package/README.md +83 -43
  2. package/dist/agent/discovery.d.ts +72 -0
  3. package/dist/agent/discovery.d.ts.map +1 -0
  4. package/dist/agent/discovery.js +210 -0
  5. package/dist/agent/discovery.js.map +1 -0
  6. package/dist/agent/execute.d.ts +206 -0
  7. package/dist/agent/execute.d.ts.map +1 -0
  8. package/dist/agent/execute.js +581 -0
  9. package/dist/agent/execute.js.map +1 -0
  10. package/dist/agent/index.d.ts +23 -0
  11. package/dist/agent/index.d.ts.map +1 -0
  12. package/dist/agent/index.js +85 -0
  13. package/dist/agent/index.js.map +1 -0
  14. package/dist/agent/launch.d.ts +133 -0
  15. package/dist/agent/launch.d.ts.map +1 -0
  16. package/dist/agent/launch.js +380 -0
  17. package/dist/agent/launch.js.map +1 -0
  18. package/dist/agent/manifest.d.ts +30 -0
  19. package/dist/agent/manifest.d.ts.map +1 -0
  20. package/dist/agent/manifest.js +93 -0
  21. package/dist/agent/manifest.js.map +1 -0
  22. package/dist/agent/placeholders.d.ts +49 -0
  23. package/dist/agent/placeholders.d.ts.map +1 -0
  24. package/dist/agent/placeholders.js +177 -0
  25. package/dist/agent/placeholders.js.map +1 -0
  26. package/dist/agent/run-log.d.ts +254 -0
  27. package/dist/agent/run-log.d.ts.map +1 -0
  28. package/dist/agent/run-log.js +612 -0
  29. package/dist/agent/run-log.js.map +1 -0
  30. package/dist/agent/schema.d.ts +100 -0
  31. package/dist/agent/schema.d.ts.map +1 -0
  32. package/dist/agent/schema.js +89 -0
  33. package/dist/agent/schema.js.map +1 -0
  34. package/dist/agent/step.d.ts +41 -0
  35. package/dist/agent/step.d.ts.map +1 -0
  36. package/dist/agent/step.js +95 -0
  37. package/dist/agent/step.js.map +1 -0
  38. package/dist/build-info.json +4 -0
  39. package/dist/cli/error.d.ts +11 -2
  40. package/dist/cli/error.d.ts.map +1 -1
  41. package/dist/cli/error.js +27 -6
  42. package/dist/cli/error.js.map +1 -1
  43. package/dist/cli/exit.d.ts +33 -3
  44. package/dist/cli/exit.d.ts.map +1 -1
  45. package/dist/cli/exit.js +54 -3
  46. package/dist/cli/exit.js.map +1 -1
  47. package/dist/cli/index.d.ts +1 -1
  48. package/dist/cli/index.d.ts.map +1 -1
  49. package/dist/cli/index.js +2 -1
  50. package/dist/cli/index.js.map +1 -1
  51. package/dist/cli/init-command.d.ts.map +1 -1
  52. package/dist/cli/init-command.js +4 -2
  53. package/dist/cli/init-command.js.map +1 -1
  54. package/dist/cli/mcp-command.d.ts +13 -4
  55. package/dist/cli/mcp-command.d.ts.map +1 -1
  56. package/dist/cli/mcp-command.js +25 -8
  57. package/dist/cli/mcp-command.js.map +1 -1
  58. package/dist/cli/output.d.ts +12 -4
  59. package/dist/cli/output.d.ts.map +1 -1
  60. package/dist/cli/output.js +15 -4
  61. package/dist/cli/output.js.map +1 -1
  62. package/dist/cli/program.d.ts +1 -1
  63. package/dist/cli/program.d.ts.map +1 -1
  64. package/dist/cli/program.js +162 -40
  65. package/dist/cli/program.js.map +1 -1
  66. package/dist/cli/registrar.d.ts +1 -1
  67. package/dist/cli/registrar.d.ts.map +1 -1
  68. package/dist/cli/registrar.js +67 -6
  69. package/dist/cli/registrar.js.map +1 -1
  70. package/dist/cli/suggest.d.ts +20 -0
  71. package/dist/cli/suggest.d.ts.map +1 -0
  72. package/dist/cli/suggest.js +49 -0
  73. package/dist/cli/suggest.js.map +1 -0
  74. package/dist/cli/warning.d.ts +26 -0
  75. package/dist/cli/warning.d.ts.map +1 -0
  76. package/dist/cli/warning.js +66 -0
  77. package/dist/cli/warning.js.map +1 -0
  78. package/dist/cli.js +11 -2
  79. package/dist/cli.js.map +1 -1
  80. package/dist/core/agent-execute.d.ts +44 -0
  81. package/dist/core/agent-execute.d.ts.map +1 -0
  82. package/dist/core/agent-execute.js +71 -0
  83. package/dist/core/agent-execute.js.map +1 -0
  84. package/dist/core/agent-list.d.ts +95 -0
  85. package/dist/core/agent-list.d.ts.map +1 -0
  86. package/dist/core/agent-list.js +207 -0
  87. package/dist/core/agent-list.js.map +1 -0
  88. package/dist/core/agent-show.d.ts +44 -0
  89. package/dist/core/agent-show.d.ts.map +1 -0
  90. package/dist/core/agent-show.js +188 -0
  91. package/dist/core/agent-show.js.map +1 -0
  92. package/dist/core/approval-authority.d.ts +17 -14
  93. package/dist/core/approval-authority.d.ts.map +1 -1
  94. package/dist/core/approval-authority.js +9 -9
  95. package/dist/core/approval-authority.js.map +1 -1
  96. package/dist/core/builtin-asset.d.ts +18 -15
  97. package/dist/core/builtin-asset.d.ts.map +1 -1
  98. package/dist/core/builtin-asset.js +17 -14
  99. package/dist/core/builtin-asset.js.map +1 -1
  100. package/dist/core/builtin-integrity.d.ts +12 -2
  101. package/dist/core/builtin-integrity.d.ts.map +1 -1
  102. package/dist/core/builtin-integrity.js +85 -9
  103. package/dist/core/builtin-integrity.js.map +1 -1
  104. package/dist/core/confinement.d.ts +3 -1
  105. package/dist/core/confinement.d.ts.map +1 -1
  106. package/dist/core/confinement.js +7 -4
  107. package/dist/core/confinement.js.map +1 -1
  108. package/dist/core/context.d.ts +150 -98
  109. package/dist/core/context.d.ts.map +1 -1
  110. package/dist/core/context.js +602 -66
  111. package/dist/core/context.js.map +1 -1
  112. package/dist/core/directive-assign.d.ts +33 -7
  113. package/dist/core/directive-assign.d.ts.map +1 -1
  114. package/dist/core/directive-assign.js +67 -27
  115. package/dist/core/directive-assign.js.map +1 -1
  116. package/dist/core/directive-scope.d.ts +36 -0
  117. package/dist/core/directive-scope.d.ts.map +1 -0
  118. package/dist/core/directive-scope.js +34 -0
  119. package/dist/core/directive-scope.js.map +1 -0
  120. package/dist/core/directives-list.d.ts +13 -3
  121. package/dist/core/directives-list.d.ts.map +1 -1
  122. package/dist/core/directives-list.js +18 -6
  123. package/dist/core/directives-list.js.map +1 -1
  124. package/dist/core/dry-run.d.ts +33 -0
  125. package/dist/core/dry-run.d.ts.map +1 -0
  126. package/dist/core/dry-run.js +45 -0
  127. package/dist/core/dry-run.js.map +1 -0
  128. package/dist/core/element-ref.d.ts +23 -0
  129. package/dist/core/element-ref.d.ts.map +1 -0
  130. package/dist/core/element-ref.js +24 -0
  131. package/dist/core/element-ref.js.map +1 -0
  132. package/dist/core/error-details.d.ts +20 -0
  133. package/dist/core/error-details.d.ts.map +1 -0
  134. package/dist/core/error-details.js +65 -0
  135. package/dist/core/error-details.js.map +1 -0
  136. package/dist/core/exit-code.d.ts.map +1 -1
  137. package/dist/core/exit-code.js +6 -7
  138. package/dist/core/exit-code.js.map +1 -1
  139. package/dist/core/git-identity.d.ts +46 -11
  140. package/dist/core/git-identity.d.ts.map +1 -1
  141. package/dist/core/git-identity.js +140 -27
  142. package/dist/core/git-identity.js.map +1 -1
  143. package/dist/core/index.d.ts +184 -10
  144. package/dist/core/index.d.ts.map +1 -1
  145. package/dist/core/index.js +1045 -185
  146. package/dist/core/index.js.map +1 -1
  147. package/dist/core/init.d.ts +45 -5
  148. package/dist/core/init.d.ts.map +1 -1
  149. package/dist/core/init.js +134 -24
  150. package/dist/core/init.js.map +1 -1
  151. package/dist/core/loaders.d.ts +170 -14
  152. package/dist/core/loaders.d.ts.map +1 -1
  153. package/dist/core/loaders.js +570 -89
  154. package/dist/core/loaders.js.map +1 -1
  155. package/dist/core/memory-add-link.d.ts +28 -0
  156. package/dist/core/memory-add-link.d.ts.map +1 -0
  157. package/dist/core/memory-add-link.js +67 -0
  158. package/dist/core/memory-add-link.js.map +1 -0
  159. package/dist/core/memory-add-type.d.ts +25 -1
  160. package/dist/core/memory-add-type.d.ts.map +1 -1
  161. package/dist/core/memory-add-type.js +59 -1
  162. package/dist/core/memory-add-type.js.map +1 -1
  163. package/dist/core/memory-amend.d.ts +80 -0
  164. package/dist/core/memory-amend.d.ts.map +1 -0
  165. package/dist/core/memory-amend.js +160 -0
  166. package/dist/core/memory-amend.js.map +1 -0
  167. package/dist/core/memory-supersede.d.ts +28 -0
  168. package/dist/core/memory-supersede.d.ts.map +1 -0
  169. package/dist/core/memory-supersede.js +79 -0
  170. package/dist/core/memory-supersede.js.map +1 -0
  171. package/dist/core/memory-transition.d.ts +190 -30
  172. package/dist/core/memory-transition.d.ts.map +1 -1
  173. package/dist/core/memory-transition.js +480 -59
  174. package/dist/core/memory-transition.js.map +1 -1
  175. package/dist/core/registry.d.ts +82 -10
  176. package/dist/core/registry.d.ts.map +1 -1
  177. package/dist/core/registry.js +50 -0
  178. package/dist/core/registry.js.map +1 -1
  179. package/dist/core/relevance.d.ts +74 -12
  180. package/dist/core/relevance.d.ts.map +1 -1
  181. package/dist/core/relevance.js +45 -27
  182. package/dist/core/relevance.js.map +1 -1
  183. package/dist/core/require-reason.d.ts.map +1 -1
  184. package/dist/core/require-reason.js +6 -5
  185. package/dist/core/require-reason.js.map +1 -1
  186. package/dist/core/required-fields.d.ts +28 -0
  187. package/dist/core/required-fields.d.ts.map +1 -0
  188. package/dist/core/required-fields.js +60 -0
  189. package/dist/core/required-fields.js.map +1 -0
  190. package/dist/core/revision.d.ts +82 -0
  191. package/dist/core/revision.d.ts.map +1 -0
  192. package/dist/core/revision.js +144 -0
  193. package/dist/core/revision.js.map +1 -0
  194. package/dist/core/types.d.ts +28 -2
  195. package/dist/core/types.d.ts.map +1 -1
  196. package/dist/core/types.js +12 -3
  197. package/dist/core/types.js.map +1 -1
  198. package/dist/core/workflow-core-checks.d.ts +34 -0
  199. package/dist/core/workflow-core-checks.d.ts.map +1 -0
  200. package/dist/core/workflow-core-checks.js +403 -0
  201. package/dist/core/workflow-core-checks.js.map +1 -0
  202. package/dist/core/workflow-create-remove.d.ts +65 -0
  203. package/dist/core/workflow-create-remove.d.ts.map +1 -0
  204. package/dist/core/workflow-create-remove.js +277 -0
  205. package/dist/core/workflow-create-remove.js.map +1 -0
  206. package/dist/core/workflow-deduction.d.ts +48 -0
  207. package/dist/core/workflow-deduction.d.ts.map +1 -0
  208. package/dist/core/workflow-deduction.js +523 -0
  209. package/dist/core/workflow-deduction.js.map +1 -0
  210. package/dist/core/workflow-diagnostics.d.ts +83 -0
  211. package/dist/core/workflow-diagnostics.d.ts.map +1 -0
  212. package/dist/core/workflow-diagnostics.js +375 -0
  213. package/dist/core/workflow-diagnostics.js.map +1 -0
  214. package/dist/core/workflow-exit-state.d.ts +125 -0
  215. package/dist/core/workflow-exit-state.d.ts.map +1 -0
  216. package/dist/core/workflow-exit-state.js +243 -0
  217. package/dist/core/workflow-exit-state.js.map +1 -0
  218. package/dist/core/workflow-finalize.d.ts +37 -0
  219. package/dist/core/workflow-finalize.d.ts.map +1 -0
  220. package/dist/core/workflow-finalize.js +153 -0
  221. package/dist/core/workflow-finalize.js.map +1 -0
  222. package/dist/core/workflow-list-show.d.ts +176 -0
  223. package/dist/core/workflow-list-show.d.ts.map +1 -0
  224. package/dist/core/workflow-list-show.js +268 -0
  225. package/dist/core/workflow-list-show.js.map +1 -0
  226. package/dist/core/workflow-next.d.ts +268 -0
  227. package/dist/core/workflow-next.d.ts.map +1 -0
  228. package/dist/core/workflow-next.js +503 -0
  229. package/dist/core/workflow-next.js.map +1 -0
  230. package/dist/core/workflow-registry.d.ts +52 -0
  231. package/dist/core/workflow-registry.d.ts.map +1 -0
  232. package/dist/core/workflow-registry.js +158 -0
  233. package/dist/core/workflow-registry.js.map +1 -0
  234. package/dist/core/workflow-start-end.d.ts +71 -0
  235. package/dist/core/workflow-start-end.d.ts.map +1 -0
  236. package/dist/core/workflow-start-end.js +298 -0
  237. package/dist/core/workflow-start-end.js.map +1 -0
  238. package/dist/core/workflow-status.d.ts +83 -0
  239. package/dist/core/workflow-status.d.ts.map +1 -0
  240. package/dist/core/workflow-status.js +125 -0
  241. package/dist/core/workflow-status.js.map +1 -0
  242. package/dist/core/write-guard.d.ts +51 -8
  243. package/dist/core/write-guard.d.ts.map +1 -1
  244. package/dist/core/write-guard.js +139 -9
  245. package/dist/core/write-guard.js.map +1 -1
  246. package/dist/directives/index.d.ts +3 -2
  247. package/dist/directives/index.d.ts.map +1 -1
  248. package/dist/directives/index.js +5 -3
  249. package/dist/directives/index.js.map +1 -1
  250. package/dist/directives/schema.d.ts +34 -29
  251. package/dist/directives/schema.d.ts.map +1 -1
  252. package/dist/directives/schema.js +35 -29
  253. package/dist/directives/schema.js.map +1 -1
  254. package/dist/directives/version.d.ts +28 -0
  255. package/dist/directives/version.d.ts.map +1 -0
  256. package/dist/directives/version.js +51 -0
  257. package/dist/directives/version.js.map +1 -0
  258. package/dist/dna/edit.d.ts +7 -6
  259. package/dist/dna/edit.d.ts.map +1 -1
  260. package/dist/dna/edit.js +96 -41
  261. package/dist/dna/edit.js.map +1 -1
  262. package/dist/dna/mutate.js +18 -3
  263. package/dist/dna/mutate.js.map +1 -1
  264. package/dist/dna/path.d.ts +2 -2
  265. package/dist/dna/roles.d.ts +1 -1
  266. package/dist/dna/schema.d.ts +61 -3
  267. package/dist/dna/schema.d.ts.map +1 -1
  268. package/dist/dna/schema.js +121 -6
  269. package/dist/dna/schema.js.map +1 -1
  270. package/dist/mcp/dna-resource.d.ts.map +1 -1
  271. package/dist/mcp/dna-resource.js +4 -4
  272. package/dist/mcp/dna-resource.js.map +1 -1
  273. package/dist/mcp/index.d.ts +8 -4
  274. package/dist/mcp/index.d.ts.map +1 -1
  275. package/dist/mcp/index.js +13 -2
  276. package/dist/mcp/index.js.map +1 -1
  277. package/dist/mcp/memory-resource.d.ts.map +1 -1
  278. package/dist/mcp/memory-resource.js +30 -19
  279. package/dist/mcp/memory-resource.js.map +1 -1
  280. package/dist/mcp/prompt.d.ts +61 -24
  281. package/dist/mcp/prompt.d.ts.map +1 -1
  282. package/dist/mcp/prompt.js +176 -47
  283. package/dist/mcp/prompt.js.map +1 -1
  284. package/dist/mcp/read-only.d.ts +39 -0
  285. package/dist/mcp/read-only.d.ts.map +1 -1
  286. package/dist/mcp/read-only.js +61 -0
  287. package/dist/mcp/read-only.js.map +1 -1
  288. package/dist/mcp/registrar.d.ts +10 -0
  289. package/dist/mcp/registrar.d.ts.map +1 -1
  290. package/dist/mcp/registrar.js +48 -12
  291. package/dist/mcp/registrar.js.map +1 -1
  292. package/dist/mcp/server.d.ts +21 -14
  293. package/dist/mcp/server.d.ts.map +1 -1
  294. package/dist/mcp/server.js +41 -15
  295. package/dist/mcp/server.js.map +1 -1
  296. package/dist/mcp/session-resource.d.ts +13 -0
  297. package/dist/mcp/session-resource.d.ts.map +1 -0
  298. package/dist/mcp/session-resource.js +65 -0
  299. package/dist/mcp/session-resource.js.map +1 -0
  300. package/dist/mcp/workflow-resource.d.ts +18 -0
  301. package/dist/mcp/workflow-resource.d.ts.map +1 -1
  302. package/dist/mcp/workflow-resource.js +37 -8
  303. package/dist/mcp/workflow-resource.js.map +1 -1
  304. package/dist/memory/add.d.ts +110 -24
  305. package/dist/memory/add.d.ts.map +1 -1
  306. package/dist/memory/add.js +251 -64
  307. package/dist/memory/add.js.map +1 -1
  308. package/dist/memory/audit.d.ts +152 -39
  309. package/dist/memory/audit.d.ts.map +1 -1
  310. package/dist/memory/audit.js +257 -103
  311. package/dist/memory/audit.js.map +1 -1
  312. package/dist/memory/commit-message.d.ts +60 -38
  313. package/dist/memory/commit-message.d.ts.map +1 -1
  314. package/dist/memory/commit-message.js +167 -21
  315. package/dist/memory/commit-message.js.map +1 -1
  316. package/dist/memory/entry.d.ts.map +1 -1
  317. package/dist/memory/entry.js +1 -2
  318. package/dist/memory/entry.js.map +1 -1
  319. package/dist/memory/frontmatter-edit.d.ts +16 -4
  320. package/dist/memory/frontmatter-edit.d.ts.map +1 -1
  321. package/dist/memory/frontmatter-edit.js +13 -1
  322. package/dist/memory/frontmatter-edit.js.map +1 -1
  323. package/dist/memory/git-log.d.ts +18 -6
  324. package/dist/memory/git-log.d.ts.map +1 -1
  325. package/dist/memory/git-log.js +40 -13
  326. package/dist/memory/git-log.js.map +1 -1
  327. package/dist/memory/history.d.ts +73 -12
  328. package/dist/memory/history.d.ts.map +1 -1
  329. package/dist/memory/history.js +128 -44
  330. package/dist/memory/history.js.map +1 -1
  331. package/dist/memory/index.d.ts +13 -11
  332. package/dist/memory/index.d.ts.map +1 -1
  333. package/dist/memory/index.js +34 -3
  334. package/dist/memory/index.js.map +1 -1
  335. package/dist/memory/query.d.ts +161 -19
  336. package/dist/memory/query.d.ts.map +1 -1
  337. package/dist/memory/query.js +435 -55
  338. package/dist/memory/query.js.map +1 -1
  339. package/dist/memory/schema.d.ts +52 -3
  340. package/dist/memory/schema.d.ts.map +1 -1
  341. package/dist/memory/schema.js +132 -8
  342. package/dist/memory/schema.js.map +1 -1
  343. package/dist/memory/state-machine.d.ts +65 -10
  344. package/dist/memory/state-machine.d.ts.map +1 -1
  345. package/dist/memory/state-machine.js +134 -46
  346. package/dist/memory/state-machine.js.map +1 -1
  347. package/dist/memory/submit.d.ts +52 -3
  348. package/dist/memory/submit.d.ts.map +1 -1
  349. package/dist/memory/submit.js +118 -11
  350. package/dist/memory/submit.js.map +1 -1
  351. package/dist/storage/build-stamp.d.ts +18 -0
  352. package/dist/storage/build-stamp.d.ts.map +1 -0
  353. package/dist/storage/build-stamp.js +68 -0
  354. package/dist/storage/build-stamp.js.map +1 -0
  355. package/dist/storage/builtin-adapters.d.ts +32 -0
  356. package/dist/storage/builtin-adapters.d.ts.map +1 -0
  357. package/dist/storage/builtin-adapters.js +100 -0
  358. package/dist/storage/builtin-adapters.js.map +1 -0
  359. package/dist/storage/builtin-directives.d.ts +0 -29
  360. package/dist/storage/builtin-directives.d.ts.map +1 -1
  361. package/dist/storage/builtin-directives.js +9 -4
  362. package/dist/storage/builtin-directives.js.map +1 -1
  363. package/dist/storage/commit.d.ts +310 -3
  364. package/dist/storage/commit.d.ts.map +1 -1
  365. package/dist/storage/commit.js +807 -33
  366. package/dist/storage/commit.js.map +1 -1
  367. package/dist/storage/document.d.ts +6 -0
  368. package/dist/storage/document.d.ts.map +1 -1
  369. package/dist/storage/document.js +10 -1
  370. package/dist/storage/document.js.map +1 -1
  371. package/dist/storage/dry-run.d.ts +65 -0
  372. package/dist/storage/dry-run.d.ts.map +1 -0
  373. package/dist/storage/dry-run.js +150 -0
  374. package/dist/storage/dry-run.js.map +1 -0
  375. package/dist/storage/errors.d.ts +26 -0
  376. package/dist/storage/errors.d.ts.map +1 -1
  377. package/dist/storage/errors.js +27 -1
  378. package/dist/storage/errors.js.map +1 -1
  379. package/dist/storage/frontmatter.d.ts +1 -1
  380. package/dist/storage/frontmatter.js +1 -1
  381. package/dist/storage/git-read.d.ts +64 -0
  382. package/dist/storage/git-read.d.ts.map +1 -0
  383. package/dist/storage/git-read.js +107 -0
  384. package/dist/storage/git-read.js.map +1 -0
  385. package/dist/storage/index.d.ts +13 -5
  386. package/dist/storage/index.d.ts.map +1 -1
  387. package/dist/storage/index.js +39 -2
  388. package/dist/storage/index.js.map +1 -1
  389. package/dist/storage/layout.d.ts +2 -2
  390. package/dist/storage/layout.d.ts.map +1 -1
  391. package/dist/storage/layout.js +2 -7
  392. package/dist/storage/layout.js.map +1 -1
  393. package/dist/storage/memory-path.d.ts +18 -5
  394. package/dist/storage/memory-path.d.ts.map +1 -1
  395. package/dist/storage/memory-path.js +41 -5
  396. package/dist/storage/memory-path.js.map +1 -1
  397. package/dist/storage/snapshot.js +1 -1
  398. package/dist/storage/templates.d.ts +33 -6
  399. package/dist/storage/templates.d.ts.map +1 -1
  400. package/dist/storage/templates.js +170 -16
  401. package/dist/storage/templates.js.map +1 -1
  402. package/dist/validation/config-version.d.ts +19 -0
  403. package/dist/validation/config-version.d.ts.map +1 -0
  404. package/dist/validation/config-version.js +53 -0
  405. package/dist/validation/config-version.js.map +1 -0
  406. package/dist/validation/diagnostic.d.ts +40 -0
  407. package/dist/validation/diagnostic.d.ts.map +1 -0
  408. package/dist/validation/diagnostic.js +41 -0
  409. package/dist/validation/diagnostic.js.map +1 -0
  410. package/dist/validation/format.d.ts +74 -0
  411. package/dist/validation/format.d.ts.map +1 -0
  412. package/dist/validation/format.js +104 -0
  413. package/dist/validation/format.js.map +1 -0
  414. package/dist/validation/id.d.ts +14 -0
  415. package/dist/validation/id.d.ts.map +1 -1
  416. package/dist/validation/id.js +35 -11
  417. package/dist/validation/id.js.map +1 -1
  418. package/dist/validation/identity.d.ts +40 -0
  419. package/dist/validation/identity.d.ts.map +1 -0
  420. package/dist/validation/identity.js +78 -0
  421. package/dist/validation/identity.js.map +1 -0
  422. package/dist/validation/index.d.ts +9 -3
  423. package/dist/validation/index.d.ts.map +1 -1
  424. package/dist/validation/index.js +30 -1
  425. package/dist/validation/index.js.map +1 -1
  426. package/dist/validation/secret-scan.d.ts +3 -2
  427. package/dist/validation/secret-scan.d.ts.map +1 -1
  428. package/dist/validation/secret-scan.js +32 -11
  429. package/dist/validation/secret-scan.js.map +1 -1
  430. package/dist/validation/warning.d.ts +30 -16
  431. package/dist/validation/warning.d.ts.map +1 -1
  432. package/dist/validation/warning.js +74 -7
  433. package/dist/validation/warning.js.map +1 -1
  434. package/dist/workflow/bindings.d.ts +152 -0
  435. package/dist/workflow/bindings.d.ts.map +1 -0
  436. package/dist/workflow/bindings.js +249 -0
  437. package/dist/workflow/bindings.js.map +1 -0
  438. package/dist/workflow/create.d.ts +13 -0
  439. package/dist/workflow/create.d.ts.map +1 -0
  440. package/dist/workflow/create.js +41 -0
  441. package/dist/workflow/create.js.map +1 -0
  442. package/dist/workflow/deduce.d.ts +400 -0
  443. package/dist/workflow/deduce.d.ts.map +1 -0
  444. package/dist/workflow/deduce.js +1109 -0
  445. package/dist/workflow/deduce.js.map +1 -0
  446. package/dist/workflow/manifest-edit.d.ts +19 -0
  447. package/dist/workflow/manifest-edit.d.ts.map +1 -0
  448. package/dist/workflow/manifest-edit.js +124 -0
  449. package/dist/workflow/manifest-edit.js.map +1 -0
  450. package/dist/workflow/schema.d.ts +158 -19
  451. package/dist/workflow/schema.d.ts.map +1 -1
  452. package/dist/workflow/schema.js +163 -15
  453. package/dist/workflow/schema.js.map +1 -1
  454. package/package.json +18 -8
@@ -1,14 +1,24 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.E_EMPTY_SEARCH_QUERY = void 0;
3
+ exports.E_EMPTY_SEARCH_QUERY = exports.W_MEMORY_UNREADABLE = void 0;
4
4
  exports.computeMemoryContentRoots = computeMemoryContentRoots;
5
+ exports.memoryUnreadableDiagnostic = memoryUnreadableDiagnostic;
6
+ exports.firstLineOf = firstLineOf;
5
7
  exports.listMemoryDocumentPaths = listMemoryDocumentPaths;
6
8
  exports.loadMemoryDocumentSummary = loadMemoryDocumentSummary;
9
+ exports.loadMemoryDocuments = loadMemoryDocuments;
10
+ exports.listMemoryDocumentPathsAtRev = listMemoryDocumentPathsAtRev;
11
+ exports.loadMemoryDocumentsAtRev = loadMemoryDocumentsAtRev;
12
+ exports.loadMemoryDocumentsAtCommit = loadMemoryDocumentsAtCommit;
13
+ exports.loadMemoryDocumentSummaryAtRev = loadMemoryDocumentSummaryAtRev;
7
14
  exports.findMemoryDocumentById = findMemoryDocumentById;
15
+ exports.findMemoryDocumentByIdAtRev = findMemoryDocumentByIdAtRev;
8
16
  exports.listMemoryDocumentsByType = listMemoryDocumentsByType;
9
17
  exports.findMemoryDocumentByTypeAndId = findMemoryDocumentByTypeAndId;
18
+ exports.findMemoryDocumentByTypeAndIdAtRev = findMemoryDocumentByTypeAndIdAtRev;
10
19
  exports.validateSearchQuery = validateSearchQuery;
11
20
  exports.searchMemoryDocuments = searchMemoryDocuments;
21
+ exports.loadTypeDocumentCopiesAtRevs = loadTypeDocumentCopiesAtRevs;
12
22
  /**
13
23
  * Memory query primitives (task-008-dna-memory-query-latency, REQ-PERF-02; match/rank algorithm and
14
24
  * empty-query validation hardened by task-023-implement-keyword-search, P1.12) — the performance-
@@ -53,12 +63,34 @@ exports.searchMemoryDocuments = searchMemoryDocuments;
53
63
  * `draft` is deliberately NOT excluded here: spec-012 §6 excludes drafts from an assembled agent
54
64
  * *context*, but REQ-STATE-06 scopes default-search exclusion to archived content only, so a draft
55
65
  * document a user is actively working on stays findable. The two filters are different sets on purpose.
66
+ *
67
+ * **Fail closed on archived elements (task-171, `dl-038` option 1).** {@link listMemoryDocumentsByType}
68
+ * and {@link findMemoryDocumentByTypeAndId} (and its `…AtRev` sibling) exclude archived documents by
69
+ * default too, so a consumer that forgets to filter does not reach them; the one that must —
70
+ * `wingfoil://memory/{type}/{id}` — passes `includeArchived: true`. {@link findMemoryDocumentById}
71
+ * stays neutral: `memory history` and the transition verbs act on archived elements.
72
+ *
73
+ * **Tolerant reads (task-171, `bug-031`, `spec-017` §1.4).** A scan never throws on a document it
74
+ * cannot read. A document whose frontmatter does not parse, and a symbolic link (never followed and
75
+ * never parsed, by either baseline, `bug-189`), are left out and reported to the caller's
76
+ * {@link MemoryScanOptions.onDiagnostic} as {@link W_MEMORY_UNREADABLE}, in path order. Only the
77
+ * single-file read {@link loadMemoryDocumentSummary} still throws: its caller named that file.
78
+ *
79
+ * **The `format` key (task-257, `bug-241`, `dl-149`).** An element keeps the `format` of the template
80
+ * it was copied from and reads with that counter, `MEMORY_TEMPLATE_FORMAT`; absent reads as `1`. An
81
+ * element written in a newer format is not read by today's rules: a collection scan leaves it out and
82
+ * reports it as {@link W_MEMORY_UNREADABLE}, naming the file and the "upgrade WingFoil" refusal; a
83
+ * single-file read, and a lookup by id that reaches the element it names, throw that refusal
84
+ * (`ValidationError`, `E_INVALID_FORMAT`, exit `1`); a lookup reports one it passes on its way.
56
85
  */
57
86
  const fs_1 = require("fs");
58
87
  const path_1 = require("path");
59
88
  const validation_1 = require("../validation");
60
89
  const state_machine_1 = require("./state-machine");
61
90
  const storage_1 = require("../storage");
91
+ // The module, not the `../core` barrel: `src/core` imports this module, and `./revision` depends on
92
+ // `../storage` alone, so nothing here closes a load-time cycle.
93
+ const revision_1 = require("../core/revision");
62
94
  /**
63
95
  * The static (placeholder-free) directory prefix of a `memory.yaml` type `path` pattern — e.g.
64
96
  * `"docs/04_memory/design/adrs/{id}.md"` -> `"docs/04_memory/design/adrs"`. A pattern whose first
@@ -88,8 +120,43 @@ function computeMemoryContentRoots(memoryYaml) {
88
120
  const all = [...dirs].sort();
89
121
  return all.filter((dir) => !all.some((other) => other !== dir && dir.startsWith(`${other}/`)));
90
122
  }
91
- /** Recursively list every `.md` file under `root/dir`, as root-relative POSIX paths, sorted. */
92
- function listMarkdownFilesUnder(root, dir) {
123
+ /** `W_MEMORY_UNREADABLE` (`spec-017` §1.4, §2): a Memory file a scan left out because it cannot read it. */
124
+ exports.W_MEMORY_UNREADABLE = 'W_MEMORY_UNREADABLE';
125
+ /** The reason {@link W_MEMORY_UNREADABLE} gives for a symbolic link (task-171, `bug-189`). */
126
+ const SYMLINK_REASON = 'a symbolic link is not read as a Memory document';
127
+ /**
128
+ * The one builder of a {@link W_MEMORY_UNREADABLE} diagnostic, shared by the scan here and by
129
+ * `spec-017`'s deduction: `spec-003`'s shape, `file` repository-relative, `path` `''` (the whole file),
130
+ * and `spec-017` §1.4's message `unreadable frontmatter in <file>: <reason>`.
131
+ */
132
+ function memoryUnreadableDiagnostic(file, reason) {
133
+ return { code: exports.W_MEMORY_UNREADABLE, severity: 'warning', file, path: '', message: `unreadable frontmatter in ${file}: ${reason}` };
134
+ }
135
+ /** The first line of a parse error: js-yaml appends a multi-line excerpt a one-line warning cannot carry. */
136
+ function firstLineOf(message) {
137
+ return message.split('\n')[0].trim();
138
+ }
139
+ /**
140
+ * Code-unit order of two strings, as `Array.prototype.sort()` orders them by default, written without
141
+ * a branch: `1`, `0` or `-1`.
142
+ */
143
+ function compareText(a, b) {
144
+ return Number(a > b) - Number(a < b);
145
+ }
146
+ /** Ascending by path. */
147
+ function byPath(a, b) {
148
+ return compareText(a.path, b.path);
149
+ }
150
+ /**
151
+ * Recursively list every `.md` entry under `root/dir`, as root-relative POSIX paths, sorted.
152
+ *
153
+ * One rule with the read at a commit (task-171, `bug-189`): a symbolic link is never followed — a
154
+ * `.md` link is listed as a link, so the caller can report it, and a link to a directory is not
155
+ * entered — and a directory holding `.git` (a nested repository, which a commit records as a gitlink
156
+ * at most) is not entered. With `followSymlinks` the walk is the pre-task-171 one, for
157
+ * {@link MemoryIdLookupOptions.followSymlinks}'s explain-only use.
158
+ */
159
+ function listMarkdownFilesUnder(root, dir, followSymlinks) {
93
160
  const absoluteDir = (0, path_1.join)(root, dir);
94
161
  if (!(0, fs_1.existsSync)(absoluteDir) || !(0, fs_1.statSync)(absoluteDir).isDirectory())
95
162
  return [];
@@ -98,47 +165,275 @@ function listMarkdownFilesUnder(root, dir) {
98
165
  for (const entry of (0, fs_1.readdirSync)(current).sort()) {
99
166
  const full = (0, path_1.join)(current, entry);
100
167
  const relative = `${relativePrefix}/${entry}`;
101
- if ((0, fs_1.statSync)(full).isDirectory()) {
168
+ const own = (0, fs_1.lstatSync)(full);
169
+ if (own.isSymbolicLink() && !followSymlinks) {
170
+ if (entry.endsWith('.md'))
171
+ out.push({ path: relative, symlink: true });
172
+ continue;
173
+ }
174
+ // Following (explain-only): a dangling link names nothing to read, so it is passed over.
175
+ if (own.isSymbolicLink() && !(0, fs_1.existsSync)(full))
176
+ continue;
177
+ const stats = own.isSymbolicLink() ? (0, fs_1.statSync)(full) : own;
178
+ if (stats.isDirectory()) {
179
+ if (!followSymlinks && (0, fs_1.existsSync)((0, path_1.join)(full, '.git')))
180
+ continue;
102
181
  walk(full, relative);
103
182
  }
104
183
  else if (entry.endsWith('.md')) {
105
- out.push(relative);
184
+ out.push({ path: relative, symlink: false });
106
185
  }
107
186
  }
108
187
  };
109
188
  walk(absoluteDir, dir);
110
189
  return out;
111
190
  }
191
+ /** Every `.md` entry under the scan roots of `memoryYaml`, sorted, links marked (see {@link listMarkdownFilesUnder}). */
192
+ function scanWorkingTree(root, memoryYaml, followSymlinks = false) {
193
+ const out = new Map();
194
+ for (const dir of computeMemoryContentRoots(memoryYaml)) {
195
+ for (const file of listMarkdownFilesUnder(root, dir, followSymlinks))
196
+ out.set(file.path, file);
197
+ }
198
+ return [...out.values()].sort(byPath);
199
+ }
112
200
  /**
113
201
  * List every Memory document under `root`, as root-relative POSIX paths, sorted lexicographically
114
202
  * (REQ-SYS-07 — deterministic, no unordered iteration). Scans only the directories
115
- * {@link computeMemoryContentRoots} derives from `memoryYaml`, never the whole project tree.
203
+ * {@link computeMemoryContentRoots} derives from `memoryYaml`, never the whole project tree. A
204
+ * symbolic link is not a document and is not listed (task-171, `bug-189`), the same as
205
+ * {@link listMemoryDocumentPathsAtRev} at a commit.
116
206
  */
117
207
  function listMemoryDocumentPaths(root, memoryYaml) {
118
- const out = new Set();
119
- for (const dir of computeMemoryContentRoots(memoryYaml)) {
120
- for (const path of listMarkdownFilesUnder(root, dir))
121
- out.add(path);
122
- }
123
- return [...out].sort();
208
+ return scanWorkingTree(root, memoryYaml)
209
+ .filter((file) => !file.symlink)
210
+ .map((file) => file.path);
124
211
  }
125
212
  /**
126
213
  * Read one Memory document and split it into its parsed frontmatter and body text, without running
127
214
  * it through any type's Zod schema — `memory search`/`history` must handle documents of every type
128
215
  * and any (even structurally imperfect) state, so this is a read, never a validation.
216
+ *
217
+ * This single-file read **throws** `ValidationError` (`E_YAML_PARSE_ERROR`) when the frontmatter does
218
+ * not parse: its caller named the file. The scans built on it are what is tolerant (task-171,
219
+ * `bug-031`): each one leaves such a document out and reports it as {@link W_MEMORY_UNREADABLE} to its
220
+ * {@link MemoryScanOptions.onDiagnostic}, so one malformed document never fails a query about another.
129
221
  */
130
222
  function loadMemoryDocumentSummary(root, relativePath) {
131
223
  const absolute = (0, path_1.join)(root, relativePath);
132
- const raw = (0, storage_1.readDocument)(absolute);
224
+ return refuseNewerElement(parseMemoryDocument((0, storage_1.readDocument)(absolute), relativePath, absolute));
225
+ }
226
+ /**
227
+ * A Memory document's bytes split into parsed frontmatter and body — the one parse both baselines use
228
+ * ({@link loadMemoryDocumentSummary} for the working tree, {@link loadMemoryDocumentsAtRev} and its
229
+ * siblings for a commit), so they cannot drift on what a document *is*. `label` is what a parse error
230
+ * names: the absolute path, or `<rev>:<path>`.
231
+ */
232
+ function parseMemoryDocument(raw, relativePath, label) {
133
233
  const { frontmatter: frontmatterText, body } = (0, storage_1.splitFrontmatter)(raw);
134
234
  let frontmatter = {};
135
235
  if (frontmatterText) {
136
- const parsed = (0, validation_1.parseYaml)(frontmatterText, absolute);
236
+ const parsed = (0, validation_1.parseYaml)(frontmatterText, label);
137
237
  if (parsed !== null && typeof parsed === 'object')
138
238
  frontmatter = parsed;
139
239
  }
140
240
  return { path: relativePath, frontmatter, body };
141
241
  }
242
+ /**
243
+ * The `format` check of an element (`dl-149`, task-257, `bug-241`): `E_INVALID_FORMAT` on `format`
244
+ * when the document's frontmatter declares a format newer than this build reads, else `null`. An
245
+ * element is its template's copy (`spec-001`: the scaffold is copied verbatim, `format` line included),
246
+ * and keeps the format its template carries (approver ruling at the W2 B2 gate, task-251 decision 4),
247
+ * so it reads with the template's counter, `MEMORY_TEMPLATE_FORMAT`. An absent `format` reads as `1`.
248
+ * The issue names the repository-relative path, whichever baseline was read, as a scan diagnostic does.
249
+ *
250
+ * Only a newer format is checked here. The element read is loose by design (no type's schema runs on
251
+ * it, see {@link loadMemoryDocumentSummary}), so a `format` that is not a positive integer is left to
252
+ * the rules that validate an element's frontmatter, as every other field is.
253
+ */
254
+ function newerElementFormat(summary) {
255
+ return (0, validation_1.newerFormatIssue)(summary.frontmatter, validation_1.MEMORY_TEMPLATE_FORMAT, summary.path);
256
+ }
257
+ /**
258
+ * `summary`, or the `dl-149` refusal of it as a `ValidationError` at exit `1` when it is written in a
259
+ * newer format: a read whose caller named this document — a single-file read, or a lookup that reached
260
+ * the element it looks for — refuses it, where a scan reports it ({@link readableDocuments}).
261
+ */
262
+ function refuseNewerElement(summary) {
263
+ const newer = newerElementFormat(summary);
264
+ if (newer !== null)
265
+ throw new validation_1.ValidationError([newer], validation_1.EXIT_VALIDATION);
266
+ return summary;
267
+ }
268
+ /** The {@link W_MEMORY_UNREADABLE} report of a document written in a newer format: the file and the `dl-149` refusal. */
269
+ function newerFormatDiagnostic(newer) {
270
+ return memoryUnreadableDiagnostic(newer.file, `${newer.code}: ${newer.message}`);
271
+ }
272
+ /**
273
+ * {@link parseMemoryDocument} for a scan: the document with its format check, or `undefined` after
274
+ * reporting it as {@link W_MEMORY_UNREADABLE} when its frontmatter does not parse. The diagnostic names
275
+ * the repository-relative path, whichever baseline was read.
276
+ */
277
+ function parseScanned(raw, relativePath, label, options) {
278
+ let summary;
279
+ try {
280
+ summary = parseMemoryDocument(raw, relativePath, label);
281
+ }
282
+ catch (error) {
283
+ // `parseYaml` is the only thing in the parse that throws, and it throws only
284
+ // `ValidationError.yamlParse`, whose one issue carries the parser's message.
285
+ const parseError = error.issues[0];
286
+ options.onDiagnostic?.(memoryUnreadableDiagnostic(relativePath, firstLineOf(parseError.message)));
287
+ return undefined;
288
+ }
289
+ return { summary, newer: newerElementFormat(summary) };
290
+ }
291
+ /**
292
+ * The documents of a scan a **collection** reader may use: one written in a newer format is left out
293
+ * and reported as {@link W_MEMORY_UNREADABLE}, naming the file and the `dl-149` refusal (task-257,
294
+ * `bug-241`), so it is neither read by today's rules nor dropped silently.
295
+ */
296
+ function* readableDocuments(documents, options) {
297
+ for (const { summary, newer } of documents) {
298
+ if (newer !== null) {
299
+ options.onDiagnostic?.(newerFormatDiagnostic(newer));
300
+ continue;
301
+ }
302
+ yield summary;
303
+ }
304
+ }
305
+ /**
306
+ * The first document of a scan whose frontmatter `matches`, for a **lookup**: the caller named that
307
+ * element, so one written in a newer format is refused (`ValidationError`, `E_INVALID_FORMAT`, exit
308
+ * `1`), as a single-file read refuses it; a newer-format document the lookup passes on its way is
309
+ * reported, as a collection scan reports it (task-257, `bug-241`).
310
+ */
311
+ function findFirst(documents, matches, options) {
312
+ for (const { summary, newer } of documents) {
313
+ if (matches(summary.frontmatter))
314
+ return refuseNewerElement(summary);
315
+ if (newer !== null)
316
+ options.onDiagnostic?.(newerFormatDiagnostic(newer));
317
+ }
318
+ return undefined;
319
+ }
320
+ /**
321
+ * The working-tree scan every tolerant reader is built on: each document under the scan roots, parsed,
322
+ * lazily and in path order, so a lookup can stop at its match. A link and an unparsable document are
323
+ * reported and skipped.
324
+ */
325
+ function* scanWorkingTreeDocuments(root, memoryYaml, options) {
326
+ for (const file of scanWorkingTree(root, memoryYaml, options.followSymlinks === true)) {
327
+ if (file.symlink) {
328
+ options.onDiagnostic?.(memoryUnreadableDiagnostic(file.path, SYMLINK_REASON));
329
+ continue;
330
+ }
331
+ const absolute = (0, path_1.join)(root, file.path);
332
+ const summary = parseScanned((0, storage_1.readDocument)(absolute), file.path, absolute, options);
333
+ if (summary !== undefined)
334
+ yield summary;
335
+ }
336
+ }
337
+ /**
338
+ * Every Memory document **in the working tree** under `root`, parsed — {@link loadMemoryDocumentsAtRev}
339
+ * for the live files, in {@link listMemoryDocumentPaths}'s sorted order. Archived documents are
340
+ * included: the caller decides what to drop. A document whose frontmatter does not parse, and a
341
+ * symbolic link, are left out and reported to `options.onDiagnostic` as {@link W_MEMORY_UNREADABLE}
342
+ * (task-171, task-253 / `bug-230`), so one malformed document never fails a read of the others.
343
+ */
344
+ function loadMemoryDocuments(root, memoryYaml, options = {}) {
345
+ return [...readableDocuments(scanWorkingTreeDocuments(root, memoryYaml, options), options)];
346
+ }
347
+ // --- The same scan at a revision (task-137) -----------------------------------------------------
348
+ //
349
+ // `spec-012` §2 pins an agent context to `stateRef`, a commit sha, and `spec-017` §1.1/§1.3 deduce
350
+ // workflow state from every Memory document "enumerated from `HEAD`'s tree in sorted path order". The
351
+ // readers below are the working-tree scan above, read at one commit instead: the same scan roots
352
+ // ({@link computeMemoryContentRoots}), the same `.md` filter, the same sort, the same parse, the same
353
+ // tolerance and the same rule for links (task-171). Each resolves `rev` once (`resolveRevision`) and
354
+ // reads every byte at that sha; an unknown or malformed rev throws `RevisionError` rather than
355
+ // answering with an empty scan. Pass the `memoryYaml` loaded at the same rev (`loadMemoryYamlAtRev`),
356
+ // and a resolved sha when several calls must see one commit.
357
+ /** Every `.md` blob under the scan roots at `sha`, sorted, links marked (git mode `120000`). */
358
+ function scanCommit(root, sha, memoryYaml) {
359
+ const out = new Map();
360
+ for (const dir of computeMemoryContentRoots(memoryYaml)) {
361
+ for (const entry of (0, revision_1.listBlobEntriesAtCommit)(root, sha, dir))
362
+ if (entry.path.endsWith('.md'))
363
+ out.set(entry.path, entry);
364
+ }
365
+ return [...out.values()].sort(byPath);
366
+ }
367
+ /**
368
+ * Every Memory document **commit `rev` holds**, as root-relative POSIX paths sorted the way
369
+ * {@link listMemoryDocumentPaths} sorts the working tree's (REQ-SYS-07). A document added after `rev`,
370
+ * or present only in the working tree, is not listed; nor is a symbolic link (task-171, `bug-189`).
371
+ *
372
+ * @throws `RevisionError` when `rev` is malformed or names no commit.
373
+ */
374
+ function listMemoryDocumentPathsAtRev(root, rev, memoryYaml) {
375
+ return scanCommit(root, (0, revision_1.resolveRevision)(root, rev), memoryYaml)
376
+ .filter((file) => !file.symlink)
377
+ .map((file) => file.path);
378
+ }
379
+ /**
380
+ * Read `files` at `sha` in one batch and parse them **lazily**, in path order; a path the commit does
381
+ * holds every one of them (they were listed at it); a link or an unparsable document is reported and
382
+ * skipped (task-171). Lazy
383
+ * so that a lookup can stop at its match, as the working-tree lookup does.
384
+ */
385
+ function* parseMemoryDocumentsAtSha(root, sha, rev, files, options) {
386
+ const raws = (0, storage_1.readPathsAtRev)(root, sha, files.filter((file) => !file.symlink).map((file) => file.path));
387
+ let next = 0;
388
+ for (const file of files) {
389
+ if (file.symlink) {
390
+ options.onDiagnostic?.(memoryUnreadableDiagnostic(file.path, SYMLINK_REASON));
391
+ continue;
392
+ }
393
+ // Every path here was listed as a blob of this very commit, so the commit holds it and the batch
394
+ // answers its bytes, never `null`.
395
+ const raw = raws[next++];
396
+ const summary = parseScanned(raw, file.path, `${rev}:${file.path}`, options);
397
+ if (summary !== undefined)
398
+ yield summary;
399
+ }
400
+ }
401
+ /**
402
+ * Every Memory document **commit `rev` holds**, parsed — the paths of
403
+ * {@link listMemoryDocumentPathsAtRev}, in its order, each read in one batch (`storage.readPathsAtRev`)
404
+ * and split as {@link loadMemoryDocumentSummary} splits a working-tree file. This is the snapshot a
405
+ * reader pinned to one commit builds from (`spec-012` §6 relevance, `spec-017` §4 deduction). A
406
+ * document whose frontmatter does not parse, and a link, are left out and reported (task-171).
407
+ *
408
+ * @throws `RevisionError` when `rev` is malformed or names no commit.
409
+ */
410
+ function loadMemoryDocumentsAtRev(root, rev, memoryYaml, options = {}) {
411
+ const sha = (0, revision_1.resolveRevision)(root, rev);
412
+ return [...readableDocuments(parseMemoryDocumentsAtSha(root, sha, rev, scanCommit(root, sha, memoryYaml), options), options)];
413
+ }
414
+ /**
415
+ * {@link loadMemoryDocumentsAtRev} for a `sha` already resolved to a commit (`resolveRevision`,
416
+ * `src/core/revision.ts`): the same scan and parse, without resolving the revision again. A reader that
417
+ * resolves its commit once and reads several pillars at it (the workflow deduction's snapshot, task-283,
418
+ * `bug-309`) uses this, so one call spends one `git rev-parse`, not one per loader.
419
+ *
420
+ * @param sha - The full sha of a commit, as `resolveRevision` returned it; labels name it.
421
+ */
422
+ function loadMemoryDocumentsAtCommit(root, sha, memoryYaml, options) {
423
+ return [...readableDocuments(parseMemoryDocumentsAtSha(root, sha, sha, scanCommit(root, sha, memoryYaml), options), options)];
424
+ }
425
+ /**
426
+ * One Memory document **as commit `rev` holds it** — {@link loadMemoryDocumentSummary} at a commit.
427
+ * `null` when that commit does not hold `relativePath` as a file. Like its working-tree counterpart,
428
+ * this single-file read throws when the frontmatter does not parse.
429
+ *
430
+ * @throws `RevisionError` when `rev` is malformed or names no commit; `ValidationError` when the
431
+ * frontmatter does not parse.
432
+ */
433
+ function loadMemoryDocumentSummaryAtRev(root, rev, relativePath) {
434
+ const raw = (0, storage_1.readPathsAtRev)(root, (0, revision_1.resolveRevision)(root, rev), [relativePath])[0];
435
+ return raw === null ? null : refuseNewerElement(parseMemoryDocument(raw, relativePath, `${rev}:${relativePath}`));
436
+ }
142
437
  function asStringArray(value) {
143
438
  return Array.isArray(value) ? value.filter((entry) => typeof entry === 'string') : [];
144
439
  }
@@ -153,25 +448,40 @@ function asString(value) {
153
448
  * (single document) — there is no bare, single-segment `wingfoil://memory/{id}` form there, and this
154
449
  * `{id}` segment would collide with spec-004's `{type}` segment. task-011-mcp-resources-read-only has
155
450
  * since replaced the `wingfoil://memory/{id}` *Resource* this primitive originally backed with the
156
- * conformant `wingfoil://memory/{type}/{id}` form (see {@link findMemoryDocumentByTypeAndId}) — this
157
- * bare-id primitive itself is left in place (still covered by its own `test/memory/query.test.ts`
158
- * unit tests and REQ-PERF-04's ported benchmark) as a generic, type-agnostic lookup; nothing in
159
- * `src/mcp` calls it anymore.
451
+ * conformant `wingfoil://memory/{type}/{id}` form (see {@link findMemoryDocumentByTypeAndId}). This
452
+ * bare-id primitive is what `memory history` resolves its `<id>` with, and what the transition verbs
453
+ * use to explain a refusal; it is neutral about archived documents, since both act on them.
160
454
  *
161
- * A linear scan over every document {@link listMemoryDocumentPaths} returns, in its
162
- * already-deterministic sorted order, stopping at the first document whose frontmatter `id` matches
455
+ * A linear scan, in sorted path order, stopping at the first document whose frontmatter `id` matches
163
456
  * *exactly* (never a substring — that remains `searchMemoryDocuments`'/task-021's keyword-search
164
- * surface, not this primitive's). Returns `undefined` — never throws — when no document matches;
165
- * turning that into a protocol-level "resource not found" failure is the MCP Resource adapter's job
166
- * (spec-004 §2.2's general unresolvable-URI contract), not this primitive's.
457
+ * surface, not this primitive's). Returns `undefined` — never throws — when no document matches; a
458
+ * document it cannot read on the way is reported to `options.onDiagnostic` and skipped (task-171).
167
459
  */
168
- function findMemoryDocumentById(root, memoryYaml, id) {
169
- for (const path of listMemoryDocumentPaths(root, memoryYaml)) {
170
- const summary = loadMemoryDocumentSummary(root, path);
171
- if (asString(summary.frontmatter.id) === id)
172
- return summary;
173
- }
174
- return undefined;
460
+ function findMemoryDocumentById(root, memoryYaml, id, options = {}) {
461
+ return findFirst(scanWorkingTreeDocuments(root, memoryYaml, options), (frontmatter) => asString(frontmatter.id) === id, options);
462
+ }
463
+ /**
464
+ * {@link findMemoryDocumentById} **at commit `rev`** (task-247, `bug-187`): the first document, in
465
+ * the sorted path order of {@link listMemoryDocumentPathsAtRev}, whose own frontmatter `id` matches
466
+ * exactly, with its frontmatter and body as `rev` holds them; `undefined` when that commit holds none.
467
+ * A document present only in the working tree, or added after `rev`, is never returned. This is the
468
+ * lookup the Memory transition verbs decide from (`spec-006-core-domain-api` §6 item 1). A document it
469
+ * cannot read on the way is reported to `options.onDiagnostic` and skipped (task-171).
470
+ *
471
+ * @throws `RevisionError` when `rev` is malformed or names no commit.
472
+ */
473
+ function findMemoryDocumentByIdAtRev(root, rev, memoryYaml, id, options = {}) {
474
+ const sha = (0, revision_1.resolveRevision)(root, rev);
475
+ const documents = parseMemoryDocumentsAtSha(root, sha, rev, scanCommit(root, sha, memoryYaml), options);
476
+ return findFirst(documents, (frontmatter) => asString(frontmatter.id) === id, options);
477
+ }
478
+ /** The match of the (`type`, `id`) lookups: both are the document's own frontmatter values. */
479
+ function isTypeAndId(type, id) {
480
+ return (frontmatter) => asString(frontmatter.type) === type && asString(frontmatter.id) === id;
481
+ }
482
+ /** Whether a document is kept under the archived default of {@link MemoryTypeScanOptions}. */
483
+ function keptByArchivedDefault(frontmatter, options) {
484
+ return options.includeArchived === true || !(0, state_machine_1.isArchivedStatus)(asString(frontmatter.status));
175
485
  }
176
486
  /**
177
487
  * List every Memory document whose frontmatter `type:` field equals `type` (a `memory.yaml` `types:`
@@ -184,13 +494,17 @@ function findMemoryDocumentById(root, memoryYaml, id) {
184
494
  * `release`/`release-line` both resolve to `docs/04_memory/planning`; `task`'s own pattern collapses
185
495
  * all the way to `docs/04_memory` itself — see {@link computeMemoryContentRoots}'s doc comment), so a
186
496
  * directory-only filter would wrongly fold sibling types' documents into this type's collection.
497
+ *
498
+ * Archived documents are left out unless `options.includeArchived` (task-171, `dl-038` option 1), and
499
+ * a document the scan cannot read is reported to `options.onDiagnostic` and skipped.
187
500
  */
188
- function listMemoryDocumentsByType(root, memoryYaml, type) {
501
+ function listMemoryDocumentsByType(root, memoryYaml, type, options = {}) {
189
502
  const out = [];
190
- for (const path of listMemoryDocumentPaths(root, memoryYaml)) {
191
- const { frontmatter } = loadMemoryDocumentSummary(root, path);
503
+ for (const { path, frontmatter } of readableDocuments(scanWorkingTreeDocuments(root, memoryYaml, options), options)) {
192
504
  if (asString(frontmatter.type) !== type)
193
505
  continue;
506
+ if (!keptByArchivedDefault(frontmatter, options))
507
+ continue;
194
508
  out.push({
195
509
  path,
196
510
  id: asString(frontmatter.id),
@@ -199,11 +513,9 @@ function listMemoryDocumentsByType(root, memoryYaml, type) {
199
513
  tags: asStringArray(frontmatter.tags),
200
514
  });
201
515
  }
202
- return out.sort((a, b) => {
203
- const keyA = a.id ?? a.path;
204
- const keyB = b.id ?? b.path;
205
- return keyA < keyB ? -1 : keyA > keyB ? 1 : 0;
206
- });
516
+ // By `id`, a document with none by its path, then by path: a total order even when two files carry
517
+ // one `id` (REQ-SYS-07).
518
+ return out.sort((a, b) => compareText(a.id ?? a.path, b.id ?? b.path) || compareText(a.path, b.path));
207
519
  }
208
520
  /**
209
521
  * Resolve a single Memory document by (`type`, `id`) — spec-004 §2.1's `wingfoil://memory/{type}/{id}`
@@ -214,14 +526,25 @@ function listMemoryDocumentsByType(root, memoryYaml, type) {
214
526
  * because that type's path pattern happens to also resolve under the same directory. Returns
215
527
  * `undefined` — never throws — when nothing matches; surfacing that as a protocol-level "resource not
216
528
  * found" failure is the MCP Resource adapter's job (spec-004 §2.2), not this primitive's.
529
+ *
530
+ * An archived document matches only with `options.includeArchived` (task-171, `dl-038` option 1); the
531
+ * single-document Resource passes it, since REQ-STATE-06 keeps archived content retrievable.
217
532
  */
218
- function findMemoryDocumentByTypeAndId(root, memoryYaml, type, id) {
219
- for (const path of listMemoryDocumentPaths(root, memoryYaml)) {
220
- const summary = loadMemoryDocumentSummary(root, path);
221
- if (asString(summary.frontmatter.type) === type && asString(summary.frontmatter.id) === id)
222
- return summary;
223
- }
224
- return undefined;
533
+ function findMemoryDocumentByTypeAndId(root, memoryYaml, type, id, options = {}) {
534
+ const found = findFirst(scanWorkingTreeDocuments(root, memoryYaml, options), isTypeAndId(type, id), options);
535
+ return found !== undefined && keptByArchivedDefault(found.frontmatter, options) ? found : undefined;
536
+ }
537
+ /**
538
+ * {@link findMemoryDocumentByTypeAndId} **at commit `rev`**: the document whose own frontmatter `type`
539
+ * and `id` match, with its frontmatter and body as `rev` holds them; `undefined` when that commit holds
540
+ * none, or holds it archived without `options.includeArchived`.
541
+ *
542
+ * @throws `RevisionError` when `rev` is malformed or names no commit.
543
+ */
544
+ function findMemoryDocumentByTypeAndIdAtRev(root, rev, memoryYaml, type, id, options = {}) {
545
+ const sha = (0, revision_1.resolveRevision)(root, rev);
546
+ const found = findFirst(parseMemoryDocumentsAtSha(root, sha, rev, scanCommit(root, sha, memoryYaml), options), isTypeAndId(type, id), options);
547
+ return found !== undefined && keptByArchivedDefault(found.frontmatter, options) ? found : undefined;
225
548
  }
226
549
  /** `E_EMPTY_SEARCH_QUERY` field-level code (spec-009-validation-strategy §3) for a rejected empty
227
550
  * or whitespace-only `wingfoil memory search` query. */
@@ -256,8 +579,13 @@ function validateSearchQuery(query) {
256
579
  * concern, task-021's, not this primitive's).
257
580
  *
258
581
  * Ordering is a total, deterministic order (REQ-SYS-07): metadata matches before body-only matches,
259
- * then by `id` (falling back to `path` when a document has no `id`) ascending — so calling this
260
- * twice against unchanged state always returns the exact same array.
582
+ * then by `id`, then by `path` (two files may carry one `id`) ascending — so calling this twice
583
+ * against unchanged state always returns the exact same array.
584
+ *
585
+ * **Only elements, never a throw (task-171).** A match has an `id` and a `type` (`bug-164`); a file
586
+ * with neither is left out without a report. A document whose frontmatter does not parse, or a
587
+ * symbolic link, is left out and reported to `options.onDiagnostic` as {@link W_MEMORY_UNREADABLE}
588
+ * (`bug-031`), so one malformed file never fails a search.
261
589
  *
262
590
  * **REQ-STATE-06:** a document whose frontmatter `status` is archived — `deprecated` or `superseded`
263
591
  * (`isArchivedStatus`, `dl-028`) — is excluded by default, so it never appears in these "default
@@ -270,8 +598,13 @@ function validateSearchQuery(query) {
270
598
  function searchMemoryDocuments(root, memoryYaml, query, options = {}) {
271
599
  const needle = query.trim().toLowerCase();
272
600
  const matches = [];
273
- for (const path of listMemoryDocumentPaths(root, memoryYaml)) {
274
- const { frontmatter, body } = loadMemoryDocumentSummary(root, path);
601
+ for (const { path, frontmatter, body } of readableDocuments(scanWorkingTreeDocuments(root, memoryYaml, options), options)) {
602
+ // Only an element is a match (task-171, `bug-164`): a file with no `id` or no `type` — a plan
603
+ // `dl-019` grandfathered without frontmatter — is left out, silently: it is not unreadable.
604
+ const id = asString(frontmatter.id);
605
+ const type = asString(frontmatter.type);
606
+ if (id === undefined || type === undefined)
607
+ continue;
275
608
  const status = asString(frontmatter.status);
276
609
  if (!options.includeArchived && (0, state_machine_1.isArchivedStatus)(status))
277
610
  continue;
@@ -279,14 +612,12 @@ function searchMemoryDocuments(root, memoryYaml, query, options = {}) {
279
612
  if (options.tag && !tags.includes(options.tag))
280
613
  continue;
281
614
  const title = asString(frontmatter.title);
282
- const id = asString(frontmatter.id);
283
- const type = asString(frontmatter.type);
284
615
  let metadataMatch = false;
285
616
  let bodyMatch = false;
286
617
  if (needle.length > 0) {
287
618
  metadataMatch =
288
619
  (title !== undefined && title.toLowerCase().includes(needle)) ||
289
- (id !== undefined && id.toLowerCase().includes(needle)) ||
620
+ id.toLowerCase().includes(needle) ||
290
621
  tags.some((tag) => tag.toLowerCase().includes(needle));
291
622
  bodyMatch = body.toLowerCase().includes(needle);
292
623
  if (!metadataMatch && !bodyMatch)
@@ -299,9 +630,58 @@ function searchMemoryDocuments(root, memoryYaml, query, options = {}) {
299
630
  const scoreB = b.metadataMatch ? 1 : 0;
300
631
  if (scoreA !== scoreB)
301
632
  return scoreB - scoreA;
302
- const keyA = a.id ?? a.path;
303
- const keyB = b.id ?? b.path;
304
- return keyA < keyB ? -1 : keyA > keyB ? 1 : 0;
633
+ return compareText(a.id, b.id) || compareText(a.path, b.path);
634
+ });
635
+ }
636
+ /**
637
+ * The documents of type `type` each of `revs` holds, one sorted list per revision, in input order —
638
+ * the read the WIP-limit count across refs takes (`requireWipSlot`, `dl-156` Q1 (a), task-274).
639
+ *
640
+ * Narrow and batched, unlike one {@link loadMemoryDocumentsAtRev} per revision (which parses every
641
+ * document of every type at each commit): only the type's own static directory is listed, every
642
+ * revision's listing in one batched walk (`listBlobsAtRevs`), every distinct blob read in one batch and
643
+ * parsed **once** however many revisions hold it. A document counts when its own frontmatter `type` is
644
+ * `type`, as in every Memory scan. A link, an unparsable document and one written in a newer format are
645
+ * left out and reported through `options.onDiagnostic` as {@link W_MEMORY_UNREADABLE} (task-171,
646
+ * task-257), once per blob.
647
+ *
648
+ * @throws `StorageError` `E_GIT_READ_FAILED` when a revision names no commit or a batch read fails.
649
+ */
650
+ function loadTypeDocumentCopiesAtRevs(root, revs, memoryYaml, type, options = {}) {
651
+ const typeEntry = memoryYaml.types[type];
652
+ const directory = typeEntry === undefined ? '' : staticDirPrefix(typeEntry.path);
653
+ const listings = (0, storage_1.listBlobsAtRevs)(root, revs, directory).map((blobs) => blobs.filter((blob) => blob.path.endsWith('.md')));
654
+ const reported = new Set();
655
+ const contents = (0, storage_1.readBlobs)(root, listings.flatMap((blobs) => blobs.filter((blob) => !blob.symlink).map((blob) => blob.oid)));
656
+ const parsed = new Map();
657
+ const frontmatterOf = (path, oid) => {
658
+ if (parsed.has(oid))
659
+ return parsed.get(oid);
660
+ const scanned = parseScanned(contents.get(oid), path, `${oid}:${path}`, options);
661
+ let frontmatter = null;
662
+ if (scanned !== undefined) {
663
+ if (scanned.newer !== null)
664
+ options.onDiagnostic?.(newerFormatDiagnostic(scanned.newer));
665
+ else
666
+ frontmatter = scanned.summary.frontmatter;
667
+ }
668
+ parsed.set(oid, frontmatter);
669
+ return frontmatter;
670
+ };
671
+ return listings.map((blobs) => {
672
+ const copies = [];
673
+ for (const blob of blobs) {
674
+ if (blob.symlink) {
675
+ if (!reported.has(blob.path))
676
+ options.onDiagnostic?.(memoryUnreadableDiagnostic(blob.path, SYMLINK_REASON));
677
+ reported.add(blob.path);
678
+ continue;
679
+ }
680
+ const frontmatter = frontmatterOf(blob.path, blob.oid);
681
+ if (frontmatter !== null && frontmatter.type === type)
682
+ copies.push({ path: blob.path, oid: blob.oid, frontmatter });
683
+ }
684
+ return copies;
305
685
  });
306
686
  }
307
687
  //# sourceMappingURL=query.js.map