wingfoil 0.2.1 → 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 (452) hide show
  1. package/README.md +88 -42
  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 +2 -2
  48. package/dist/cli/index.d.ts.map +1 -1
  49. package/dist/cli/index.js +3 -2
  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 +6 -3
  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 +270 -60
  65. package/dist/cli/program.js.map +1 -1
  66. package/dist/cli/registrar.d.ts +16 -7
  67. package/dist/cli/registrar.d.ts.map +1 -1
  68. package/dist/cli/registrar.js +71 -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.js +6 -6
  137. package/dist/core/git-identity.d.ts +46 -11
  138. package/dist/core/git-identity.d.ts.map +1 -1
  139. package/dist/core/git-identity.js +140 -27
  140. package/dist/core/git-identity.js.map +1 -1
  141. package/dist/core/index.d.ts +189 -14
  142. package/dist/core/index.d.ts.map +1 -1
  143. package/dist/core/index.js +1241 -238
  144. package/dist/core/index.js.map +1 -1
  145. package/dist/core/init.d.ts +50 -8
  146. package/dist/core/init.d.ts.map +1 -1
  147. package/dist/core/init.js +139 -27
  148. package/dist/core/init.js.map +1 -1
  149. package/dist/core/loaders.d.ts +170 -14
  150. package/dist/core/loaders.d.ts.map +1 -1
  151. package/dist/core/loaders.js +570 -89
  152. package/dist/core/loaders.js.map +1 -1
  153. package/dist/core/memory-add-link.d.ts +28 -0
  154. package/dist/core/memory-add-link.d.ts.map +1 -0
  155. package/dist/core/memory-add-link.js +67 -0
  156. package/dist/core/memory-add-link.js.map +1 -0
  157. package/dist/core/memory-add-type.d.ts +25 -1
  158. package/dist/core/memory-add-type.d.ts.map +1 -1
  159. package/dist/core/memory-add-type.js +59 -1
  160. package/dist/core/memory-add-type.js.map +1 -1
  161. package/dist/core/memory-amend.d.ts +80 -0
  162. package/dist/core/memory-amend.d.ts.map +1 -0
  163. package/dist/core/memory-amend.js +160 -0
  164. package/dist/core/memory-amend.js.map +1 -0
  165. package/dist/core/memory-supersede.d.ts +28 -0
  166. package/dist/core/memory-supersede.d.ts.map +1 -0
  167. package/dist/core/memory-supersede.js +79 -0
  168. package/dist/core/memory-supersede.js.map +1 -0
  169. package/dist/core/memory-transition.d.ts +190 -30
  170. package/dist/core/memory-transition.d.ts.map +1 -1
  171. package/dist/core/memory-transition.js +480 -59
  172. package/dist/core/memory-transition.js.map +1 -1
  173. package/dist/core/registry.d.ts +147 -23
  174. package/dist/core/registry.d.ts.map +1 -1
  175. package/dist/core/registry.js +50 -0
  176. package/dist/core/registry.js.map +1 -1
  177. package/dist/core/relevance.d.ts +74 -12
  178. package/dist/core/relevance.d.ts.map +1 -1
  179. package/dist/core/relevance.js +45 -27
  180. package/dist/core/relevance.js.map +1 -1
  181. package/dist/core/require-reason.d.ts.map +1 -1
  182. package/dist/core/require-reason.js +6 -5
  183. package/dist/core/require-reason.js.map +1 -1
  184. package/dist/core/required-fields.d.ts +28 -0
  185. package/dist/core/required-fields.d.ts.map +1 -0
  186. package/dist/core/required-fields.js +60 -0
  187. package/dist/core/required-fields.js.map +1 -0
  188. package/dist/core/revision.d.ts +82 -0
  189. package/dist/core/revision.d.ts.map +1 -0
  190. package/dist/core/revision.js +144 -0
  191. package/dist/core/revision.js.map +1 -0
  192. package/dist/core/types.d.ts +28 -2
  193. package/dist/core/types.d.ts.map +1 -1
  194. package/dist/core/types.js +12 -3
  195. package/dist/core/types.js.map +1 -1
  196. package/dist/core/workflow-core-checks.d.ts +34 -0
  197. package/dist/core/workflow-core-checks.d.ts.map +1 -0
  198. package/dist/core/workflow-core-checks.js +403 -0
  199. package/dist/core/workflow-core-checks.js.map +1 -0
  200. package/dist/core/workflow-create-remove.d.ts +65 -0
  201. package/dist/core/workflow-create-remove.d.ts.map +1 -0
  202. package/dist/core/workflow-create-remove.js +277 -0
  203. package/dist/core/workflow-create-remove.js.map +1 -0
  204. package/dist/core/workflow-deduction.d.ts +48 -0
  205. package/dist/core/workflow-deduction.d.ts.map +1 -0
  206. package/dist/core/workflow-deduction.js +523 -0
  207. package/dist/core/workflow-deduction.js.map +1 -0
  208. package/dist/core/workflow-diagnostics.d.ts +83 -0
  209. package/dist/core/workflow-diagnostics.d.ts.map +1 -0
  210. package/dist/core/workflow-diagnostics.js +375 -0
  211. package/dist/core/workflow-diagnostics.js.map +1 -0
  212. package/dist/core/workflow-exit-state.d.ts +125 -0
  213. package/dist/core/workflow-exit-state.d.ts.map +1 -0
  214. package/dist/core/workflow-exit-state.js +243 -0
  215. package/dist/core/workflow-exit-state.js.map +1 -0
  216. package/dist/core/workflow-finalize.d.ts +37 -0
  217. package/dist/core/workflow-finalize.d.ts.map +1 -0
  218. package/dist/core/workflow-finalize.js +153 -0
  219. package/dist/core/workflow-finalize.js.map +1 -0
  220. package/dist/core/workflow-list-show.d.ts +176 -0
  221. package/dist/core/workflow-list-show.d.ts.map +1 -0
  222. package/dist/core/workflow-list-show.js +268 -0
  223. package/dist/core/workflow-list-show.js.map +1 -0
  224. package/dist/core/workflow-next.d.ts +268 -0
  225. package/dist/core/workflow-next.d.ts.map +1 -0
  226. package/dist/core/workflow-next.js +503 -0
  227. package/dist/core/workflow-next.js.map +1 -0
  228. package/dist/core/workflow-registry.d.ts +52 -0
  229. package/dist/core/workflow-registry.d.ts.map +1 -0
  230. package/dist/core/workflow-registry.js +158 -0
  231. package/dist/core/workflow-registry.js.map +1 -0
  232. package/dist/core/workflow-start-end.d.ts +71 -0
  233. package/dist/core/workflow-start-end.d.ts.map +1 -0
  234. package/dist/core/workflow-start-end.js +298 -0
  235. package/dist/core/workflow-start-end.js.map +1 -0
  236. package/dist/core/workflow-status.d.ts +83 -0
  237. package/dist/core/workflow-status.d.ts.map +1 -0
  238. package/dist/core/workflow-status.js +125 -0
  239. package/dist/core/workflow-status.js.map +1 -0
  240. package/dist/core/write-guard.d.ts +51 -8
  241. package/dist/core/write-guard.d.ts.map +1 -1
  242. package/dist/core/write-guard.js +139 -9
  243. package/dist/core/write-guard.js.map +1 -1
  244. package/dist/directives/index.d.ts +3 -2
  245. package/dist/directives/index.d.ts.map +1 -1
  246. package/dist/directives/index.js +5 -3
  247. package/dist/directives/index.js.map +1 -1
  248. package/dist/directives/schema.d.ts +35 -30
  249. package/dist/directives/schema.d.ts.map +1 -1
  250. package/dist/directives/schema.js +36 -30
  251. package/dist/directives/schema.js.map +1 -1
  252. package/dist/directives/version.d.ts +28 -0
  253. package/dist/directives/version.d.ts.map +1 -0
  254. package/dist/directives/version.js +51 -0
  255. package/dist/directives/version.js.map +1 -0
  256. package/dist/dna/edit.d.ts +7 -6
  257. package/dist/dna/edit.d.ts.map +1 -1
  258. package/dist/dna/edit.js +96 -41
  259. package/dist/dna/edit.js.map +1 -1
  260. package/dist/dna/mutate.js +18 -3
  261. package/dist/dna/mutate.js.map +1 -1
  262. package/dist/dna/path.d.ts +2 -2
  263. package/dist/dna/roles.d.ts +1 -1
  264. package/dist/dna/schema.d.ts +61 -3
  265. package/dist/dna/schema.d.ts.map +1 -1
  266. package/dist/dna/schema.js +121 -6
  267. package/dist/dna/schema.js.map +1 -1
  268. package/dist/mcp/dna-resource.d.ts.map +1 -1
  269. package/dist/mcp/dna-resource.js +4 -4
  270. package/dist/mcp/dna-resource.js.map +1 -1
  271. package/dist/mcp/index.d.ts +9 -5
  272. package/dist/mcp/index.d.ts.map +1 -1
  273. package/dist/mcp/index.js +13 -2
  274. package/dist/mcp/index.js.map +1 -1
  275. package/dist/mcp/memory-resource.d.ts.map +1 -1
  276. package/dist/mcp/memory-resource.js +30 -19
  277. package/dist/mcp/memory-resource.js.map +1 -1
  278. package/dist/mcp/prompt.d.ts +61 -24
  279. package/dist/mcp/prompt.d.ts.map +1 -1
  280. package/dist/mcp/prompt.js +176 -47
  281. package/dist/mcp/prompt.js.map +1 -1
  282. package/dist/mcp/read-only.d.ts +39 -0
  283. package/dist/mcp/read-only.d.ts.map +1 -1
  284. package/dist/mcp/read-only.js +61 -0
  285. package/dist/mcp/read-only.js.map +1 -1
  286. package/dist/mcp/registrar.d.ts +10 -0
  287. package/dist/mcp/registrar.d.ts.map +1 -1
  288. package/dist/mcp/registrar.js +48 -12
  289. package/dist/mcp/registrar.js.map +1 -1
  290. package/dist/mcp/server.d.ts +21 -14
  291. package/dist/mcp/server.d.ts.map +1 -1
  292. package/dist/mcp/server.js +41 -15
  293. package/dist/mcp/server.js.map +1 -1
  294. package/dist/mcp/session-resource.d.ts +13 -0
  295. package/dist/mcp/session-resource.d.ts.map +1 -0
  296. package/dist/mcp/session-resource.js +65 -0
  297. package/dist/mcp/session-resource.js.map +1 -0
  298. package/dist/mcp/workflow-resource.d.ts +18 -0
  299. package/dist/mcp/workflow-resource.d.ts.map +1 -1
  300. package/dist/mcp/workflow-resource.js +37 -8
  301. package/dist/mcp/workflow-resource.js.map +1 -1
  302. package/dist/memory/add.d.ts +160 -17
  303. package/dist/memory/add.d.ts.map +1 -1
  304. package/dist/memory/add.js +361 -51
  305. package/dist/memory/add.js.map +1 -1
  306. package/dist/memory/audit.d.ts +165 -32
  307. package/dist/memory/audit.d.ts.map +1 -1
  308. package/dist/memory/audit.js +267 -97
  309. package/dist/memory/audit.js.map +1 -1
  310. package/dist/memory/commit-message.d.ts +60 -38
  311. package/dist/memory/commit-message.d.ts.map +1 -1
  312. package/dist/memory/commit-message.js +167 -21
  313. package/dist/memory/commit-message.js.map +1 -1
  314. package/dist/memory/entry.d.ts.map +1 -1
  315. package/dist/memory/entry.js +1 -2
  316. package/dist/memory/entry.js.map +1 -1
  317. package/dist/memory/frontmatter-edit.d.ts +16 -4
  318. package/dist/memory/frontmatter-edit.d.ts.map +1 -1
  319. package/dist/memory/frontmatter-edit.js +13 -1
  320. package/dist/memory/frontmatter-edit.js.map +1 -1
  321. package/dist/memory/git-log.d.ts +18 -6
  322. package/dist/memory/git-log.d.ts.map +1 -1
  323. package/dist/memory/git-log.js +40 -13
  324. package/dist/memory/git-log.js.map +1 -1
  325. package/dist/memory/history.d.ts +74 -13
  326. package/dist/memory/history.d.ts.map +1 -1
  327. package/dist/memory/history.js +129 -45
  328. package/dist/memory/history.js.map +1 -1
  329. package/dist/memory/index.d.ts +13 -11
  330. package/dist/memory/index.d.ts.map +1 -1
  331. package/dist/memory/index.js +38 -3
  332. package/dist/memory/index.js.map +1 -1
  333. package/dist/memory/query.d.ts +161 -19
  334. package/dist/memory/query.d.ts.map +1 -1
  335. package/dist/memory/query.js +435 -55
  336. package/dist/memory/query.js.map +1 -1
  337. package/dist/memory/schema.d.ts +52 -3
  338. package/dist/memory/schema.d.ts.map +1 -1
  339. package/dist/memory/schema.js +132 -8
  340. package/dist/memory/schema.js.map +1 -1
  341. package/dist/memory/state-machine.d.ts +65 -10
  342. package/dist/memory/state-machine.d.ts.map +1 -1
  343. package/dist/memory/state-machine.js +136 -48
  344. package/dist/memory/state-machine.js.map +1 -1
  345. package/dist/memory/submit.d.ts +52 -3
  346. package/dist/memory/submit.d.ts.map +1 -1
  347. package/dist/memory/submit.js +118 -11
  348. package/dist/memory/submit.js.map +1 -1
  349. package/dist/storage/build-stamp.d.ts +18 -0
  350. package/dist/storage/build-stamp.d.ts.map +1 -0
  351. package/dist/storage/build-stamp.js +68 -0
  352. package/dist/storage/build-stamp.js.map +1 -0
  353. package/dist/storage/builtin-adapters.d.ts +32 -0
  354. package/dist/storage/builtin-adapters.d.ts.map +1 -0
  355. package/dist/storage/builtin-adapters.js +100 -0
  356. package/dist/storage/builtin-adapters.js.map +1 -0
  357. package/dist/storage/builtin-directives.d.ts +0 -29
  358. package/dist/storage/builtin-directives.d.ts.map +1 -1
  359. package/dist/storage/builtin-directives.js +9 -4
  360. package/dist/storage/builtin-directives.js.map +1 -1
  361. package/dist/storage/commit.d.ts +310 -3
  362. package/dist/storage/commit.d.ts.map +1 -1
  363. package/dist/storage/commit.js +807 -33
  364. package/dist/storage/commit.js.map +1 -1
  365. package/dist/storage/document.d.ts +6 -0
  366. package/dist/storage/document.d.ts.map +1 -1
  367. package/dist/storage/document.js +10 -1
  368. package/dist/storage/document.js.map +1 -1
  369. package/dist/storage/dry-run.d.ts +65 -0
  370. package/dist/storage/dry-run.d.ts.map +1 -0
  371. package/dist/storage/dry-run.js +150 -0
  372. package/dist/storage/dry-run.js.map +1 -0
  373. package/dist/storage/errors.d.ts +26 -0
  374. package/dist/storage/errors.d.ts.map +1 -1
  375. package/dist/storage/errors.js +27 -1
  376. package/dist/storage/errors.js.map +1 -1
  377. package/dist/storage/frontmatter.d.ts +1 -1
  378. package/dist/storage/frontmatter.js +1 -1
  379. package/dist/storage/git-read.d.ts +64 -0
  380. package/dist/storage/git-read.d.ts.map +1 -0
  381. package/dist/storage/git-read.js +107 -0
  382. package/dist/storage/git-read.js.map +1 -0
  383. package/dist/storage/index.d.ts +13 -5
  384. package/dist/storage/index.d.ts.map +1 -1
  385. package/dist/storage/index.js +39 -2
  386. package/dist/storage/index.js.map +1 -1
  387. package/dist/storage/layout.d.ts +2 -2
  388. package/dist/storage/layout.d.ts.map +1 -1
  389. package/dist/storage/layout.js +2 -7
  390. package/dist/storage/layout.js.map +1 -1
  391. package/dist/storage/memory-path.d.ts +18 -5
  392. package/dist/storage/memory-path.d.ts.map +1 -1
  393. package/dist/storage/memory-path.js +41 -5
  394. package/dist/storage/memory-path.js.map +1 -1
  395. package/dist/storage/snapshot.js +1 -1
  396. package/dist/storage/templates.d.ts +33 -6
  397. package/dist/storage/templates.d.ts.map +1 -1
  398. package/dist/storage/templates.js +182 -17
  399. package/dist/storage/templates.js.map +1 -1
  400. package/dist/validation/config-version.d.ts +19 -0
  401. package/dist/validation/config-version.d.ts.map +1 -0
  402. package/dist/validation/config-version.js +53 -0
  403. package/dist/validation/config-version.js.map +1 -0
  404. package/dist/validation/diagnostic.d.ts +40 -0
  405. package/dist/validation/diagnostic.d.ts.map +1 -0
  406. package/dist/validation/diagnostic.js +41 -0
  407. package/dist/validation/diagnostic.js.map +1 -0
  408. package/dist/validation/format.d.ts +74 -0
  409. package/dist/validation/format.d.ts.map +1 -0
  410. package/dist/validation/format.js +104 -0
  411. package/dist/validation/format.js.map +1 -0
  412. package/dist/validation/id.d.ts +40 -0
  413. package/dist/validation/id.d.ts.map +1 -1
  414. package/dist/validation/id.js +99 -12
  415. package/dist/validation/id.js.map +1 -1
  416. package/dist/validation/identity.d.ts +40 -0
  417. package/dist/validation/identity.d.ts.map +1 -0
  418. package/dist/validation/identity.js +78 -0
  419. package/dist/validation/identity.js.map +1 -0
  420. package/dist/validation/index.d.ts +9 -3
  421. package/dist/validation/index.d.ts.map +1 -1
  422. package/dist/validation/index.js +33 -1
  423. package/dist/validation/index.js.map +1 -1
  424. package/dist/validation/secret-scan.d.ts +10 -7
  425. package/dist/validation/secret-scan.d.ts.map +1 -1
  426. package/dist/validation/secret-scan.js +39 -16
  427. package/dist/validation/secret-scan.js.map +1 -1
  428. package/dist/validation/warning.d.ts +30 -16
  429. package/dist/validation/warning.d.ts.map +1 -1
  430. package/dist/validation/warning.js +74 -7
  431. package/dist/validation/warning.js.map +1 -1
  432. package/dist/workflow/bindings.d.ts +152 -0
  433. package/dist/workflow/bindings.d.ts.map +1 -0
  434. package/dist/workflow/bindings.js +249 -0
  435. package/dist/workflow/bindings.js.map +1 -0
  436. package/dist/workflow/create.d.ts +13 -0
  437. package/dist/workflow/create.d.ts.map +1 -0
  438. package/dist/workflow/create.js +41 -0
  439. package/dist/workflow/create.js.map +1 -0
  440. package/dist/workflow/deduce.d.ts +400 -0
  441. package/dist/workflow/deduce.d.ts.map +1 -0
  442. package/dist/workflow/deduce.js +1109 -0
  443. package/dist/workflow/deduce.js.map +1 -0
  444. package/dist/workflow/manifest-edit.d.ts +19 -0
  445. package/dist/workflow/manifest-edit.d.ts.map +1 -0
  446. package/dist/workflow/manifest-edit.js +124 -0
  447. package/dist/workflow/manifest-edit.js.map +1 -0
  448. package/dist/workflow/schema.d.ts +158 -19
  449. package/dist/workflow/schema.d.ts.map +1 -1
  450. package/dist/workflow/schema.js +190 -16
  451. package/dist/workflow/schema.js.map +1 -1
  452. package/package.json +37 -13
@@ -1,35 +1,71 @@
1
1
  "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
2
35
  Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.WrittenTimestamp = exports.CONTEXT_PAYLOAD_FORMAT = void 0;
3
37
  exports.selectDirectivesById = selectDirectivesById;
4
38
  exports.resolveRoleDirectives = resolveRoleDirectives;
39
+ exports.validateExecutionContext = validateExecutionContext;
40
+ exports.serializeExecutionContext = serializeExecutionContext;
5
41
  exports.assembleExecutionContext = assembleExecutionContext;
6
42
  /**
7
- * Agent execution context assembly (task-037-role-task-scoped-context, REQ-STATE-05) — the
8
- * `directive-loader` + a minimal `context-builder` slice of
9
- * `spec-012-context-loader-relevance-filtering` (§1 "placement & responsibilities", §5 "Directive
10
- * resolution"). Satisfies REQ-STATE-05's Fit Criterion, verbatim: "The assembled context object
11
- * exposes separate `dna`, `memory`, `directives` sections; it contains 100% of the role's assigned
12
- * directives and 0 directives of other roles."
43
+ * The `spec-012-context-loader-relevance-filtering` context builder: the `directive-loader`
44
+ * ({@link resolveRoleDirectives}, §5), the `dna-loader` (§4), the call into the `relevance-filter`
45
+ * (`./relevance.ts`, §6), the validator (P5.4.4 sc. 3) and the canonical serializer (§7), behind one
46
+ * public entry, {@link assembleExecutionContext} (task-176; task-037 built the directive half,
47
+ * REQ-STATE-05).
13
48
  *
14
- * **Archived elements are excluded** (REQ-STATE-06, the `{deprecated, superseded}` set ratified by
15
- * `dl-028-archived-states-excluded-from-context`): {@link assembleExecutionContext} drops a resolved
16
- * element whose `status` is archived, through the shared `isArchivedStatus` primitive rather than any
17
- * local notion of "archived". This closed `bug-010-deprecated-reaches-agent-context` — which this
18
- * header previously recorded as an open gap — together with the `wingfoil://memory/{type}` collection
19
- * Resource, the other surface that bug covered (`task-069-fix-archived-excluded-from-agent-context`).
49
+ * Every read is pinned to `spec-012` §2's `stateRef`: the entry resolves it once to a commit sha
50
+ * (`resolveRevision`) and reads every pillar and every Memory document at that sha through task-137's
51
+ * `…AtRev` readers. The working tree is never read, so the same `(role, element, stateRef, limits)`
52
+ * yields the same bytes (§8, REQ-SYS-07).
20
53
  *
21
- * Still deliberately NOT the full spec-012 pipeline: no `ContextRequest`/`stateRef` pinning, no tiered
22
- * (T1–T4) Memory relevance ranking, no bounding caps, and no canonical byte-for-byte Markdown
23
- * serialization (§7). Those are split across sibling Wave-1 v0.2 tasks
24
- * (task-035-bounded-context-relevance REQ-PERF-05, task-038-deprecated-excluded-from-context
25
- * REQ-STATE-06) and v0.3 (`REQ-SYS-07`, `REQ-PERF-01`, `REQ-STATE-09`, the real `agent execute`
26
- * CLI/MCP surface) — see this task's Execution Notes for the full scope decision. This module wraps
27
- * only existing, already-shipped primitives: `loadDirectives`/`loadRolesYaml` (`./loaders`),
28
- * `findMemoryDocumentByTypeAndId` and `isArchivedStatus` (`../memory`, task-011/task-035) — no
29
- * scan/parse logic and no second status predicate is reimplemented here.
54
+ * **Archived elements never reach a context** (REQ-STATE-06, the `{deprecated, superseded}` set
55
+ * ratified by `dl-028-archived-states-excluded-from-context`): an archived subject element is refused,
56
+ * and archived candidates are dropped by the relevance filter — both through the shared
57
+ * `isArchivedStatus`.
30
58
  */
59
+ const jsYaml = __importStar(require("js-yaml"));
60
+ const js_yaml_1 = require("js-yaml");
31
61
  const memory_1 = require("../memory");
62
+ const storage_1 = require("../storage");
63
+ const validation_1 = require("../validation");
32
64
  const builtin_asset_1 = require("./builtin-asset");
65
+ const loaders_1 = require("./loaders");
66
+ const relevance_1 = require("./relevance");
67
+ const revision_1 = require("./revision");
68
+ const types_1 = require("./types");
33
69
  /** `assignments` is a plain object parsed from YAML, so a role named `toString`, `constructor`,
34
70
  * `valueOf`, `hasOwnProperty` or `__proto__` would otherwise resolve to an inherited
35
71
  * `Object.prototype` member instead of `undefined`. Read own properties only. */
@@ -138,55 +174,555 @@ function resolveRoleDirectives(directiveFiles, rolesYaml, role) {
138
174
  return { directives: [...selection.byId.values()], warnings };
139
175
  }
140
176
  /**
141
- * Assemble a role- and task-scoped {@link ExecutionContext} (REQ-STATE-05) from already-loaded pillar
142
- * config. Given the same inputs and unchanged on-disk Memory content, the output is deep-equal across
143
- * calls: the function itself introduces no wall-clock, randomness, or unordered iteration
144
- * (REQ-SYS-07's discipline, applied to this narrower slice per REQ-STATE-05's own rationale "crisp,
145
- * low-noise context; determinism"), and `directives` is totally ordered by
146
- * {@link resolveRoleDirectives}.
177
+ * The sections {@link validateExecutionContext} checks, in §7 order, with the shape each must have.
178
+ * The name is the {@link ExecutionContext} property, so the refusal names what to address.
179
+ */
180
+ const REQUIRED_SECTIONS = [
181
+ ['element', (value) => isRecord(value)],
182
+ ['dna', (value) => isRecord(value) && Array.isArray(value.modules)],
183
+ ['directives', (value) => Array.isArray(value)],
184
+ ['memory', (value) => Array.isArray(value)],
185
+ ];
186
+ function isRecord(value) {
187
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
188
+ }
189
+ function missingSection(name) {
190
+ return `invalid execution context: missing '${name}' section`;
191
+ }
192
+ /**
193
+ * Validate an assembled context before anything uses it (P5.4.4 sc. 3). The first section that is
194
+ * absent, or not of its section's shape, refuses the context with `VALIDATION` and the scenario's
195
+ * message, verbatim: `invalid execution context: missing '<section>' section`. Sections are checked in
196
+ * §7 order — `element`, `dna`, `directives`, `memory` — so the refusal is deterministic.
197
+ */
198
+ function validateExecutionContext(candidate) {
199
+ const value = isRecord(candidate) ? candidate : {};
200
+ for (const [name, hasShape] of REQUIRED_SECTIONS) {
201
+ if (!hasShape(value[name]))
202
+ return (0, types_1.coreErr)({ code: 'VALIDATION', message: missingSection(name) });
203
+ }
204
+ return (0, types_1.coreOk)(candidate);
205
+ }
206
+ /**
207
+ * The payload's format version (`dl-150` option B, the `dl-149` format key): the first field of the
208
+ * header comment. A change to the bytes §7 pins is a new format.
209
+ */
210
+ exports.CONTEXT_PAYLOAD_FORMAT = 1;
211
+ /**
212
+ * A YAML timestamp scalar exactly as its document wrote it (`bug-232`, review F1 of task-255): the
213
+ * frontmatter the payload carries holds one of these where js-yaml's default schema would hold a
214
+ * `Date`, so `2026-10-05`, `2026-10-05T00:00:00Z` and `2026-10-05 10:00:00 +02:00` are re-emitted
215
+ * unchanged rather than normalized to an instant.
216
+ */
217
+ class WrittenTimestamp {
218
+ text;
219
+ constructor(
220
+ /** The scalar's text, as written. */
221
+ text) {
222
+ this.text = text;
223
+ }
224
+ /** The text as written, so `JSON.stringify` of a context renders the timestamp as the document did. */
225
+ toJSON() {
226
+ return this.text;
227
+ }
228
+ }
229
+ exports.WrittenTimestamp = WrittenTimestamp;
230
+ // js-yaml 4 exports its built-in types as `types`; `@types/js-yaml` does not declare that export.
231
+ const types = jsYaml.types;
232
+ /** js-yaml's timestamp tag and resolution, constructing a {@link WrittenTimestamp} instead of a `Date`. */
233
+ const WRITTEN_TIMESTAMP_TYPE = new js_yaml_1.Type('tag:yaml.org,2002:timestamp', {
234
+ kind: 'scalar',
235
+ resolve: (data) => types.timestamp.resolve(data),
236
+ construct: (data) => new WrittenTimestamp(data),
237
+ instanceOf: WrittenTimestamp,
238
+ represent: (value) => value.text,
239
+ });
240
+ /**
241
+ * The schema the payload's frontmatter is read and dumped with: js-yaml's default schema (same implicit
242
+ * and explicit types, so it accepts what the scan accepted) with {@link WRITTEN_TIMESTAMP_TYPE} in place
243
+ * of the timestamp type. A timestamp is written back as written; a quoted date is a string that a reader
244
+ * could take for a timestamp, so the dump keeps it quoted.
245
+ */
246
+ const PAYLOAD_YAML_SCHEMA = js_yaml_1.CORE_SCHEMA.extend({
247
+ implicit: [WRITTEN_TIMESTAMP_TYPE, types.merge],
248
+ explicit: [types.binary, types.omap, types.pairs, types.set],
249
+ });
250
+ /** `value` with every `Date` — a value a caller built itself, never one the builder read — as its
251
+ * ISO-8601 UTC text, at any depth, so {@link serializeExecutionContext} accepts it. */
252
+ function withDatesAsWritten(value) {
253
+ if (value instanceof WrittenTimestamp)
254
+ return value;
255
+ if (value instanceof Date)
256
+ return new WrittenTimestamp(value.toISOString());
257
+ if (Array.isArray(value))
258
+ return value.map(withDatesAsWritten);
259
+ if (isRecord(value))
260
+ return Object.fromEntries(Object.entries(value).map(([key, entry]) => [key, withDatesAsWritten(entry)]));
261
+ return value;
262
+ }
263
+ /**
264
+ * The frontmatter of each document at `paths`, as commit `sha` holds it, read with
265
+ * {@link PAYLOAD_YAML_SCHEMA} so its timestamps keep their text (`bug-232`). Every path was read and
266
+ * parsed at `sha` by the scan already, with a schema that accepts the same documents, and each one
267
+ * has a frontmatter block: the element is found, and a document carried, by its frontmatter's `type`
268
+ * and `id`.
269
+ */
270
+ function writtenFrontmatter(root, sha, paths) {
271
+ return (0, storage_1.readPathsAtRev)(root, sha, [...paths]).map((raw) => (0, js_yaml_1.load)((0, storage_1.splitFrontmatter)(raw).frontmatter, { schema: PAYLOAD_YAML_SCHEMA }));
272
+ }
273
+ /** YAML for the payload: keys sorted ascending (§7), no line folding and no anchors, dates as written
274
+ * (`bug-232`), so the text is a function of the value alone. */
275
+ function canonicalYaml(value) {
276
+ return (0, js_yaml_1.dump)(withDatesAsWritten(value), { schema: PAYLOAD_YAML_SCHEMA, sortKeys: true, lineWidth: -1, noRefs: true });
277
+ }
278
+ function yamlBlock(value) {
279
+ return '```yaml\n' + canonicalYaml(value) + '```';
280
+ }
281
+ /** A body as §7 carries it: verbatim, without the blank lines before it or the whitespace after it. */
282
+ function trimBody(body) {
283
+ return body.replace(/^(?:[ \t]*\r?\n)+/, '').trimEnd();
284
+ }
285
+ /** The line that closes the body keyed `key` (`dl-150` B). */
286
+ function endMarker(key) {
287
+ return `<!-- end:${key} -->`;
288
+ }
289
+ /**
290
+ * A body between its markers: `<!-- begin:<key> -->`, the trimmed body, `<!-- end:<key> -->`, each on
291
+ * its own line; an empty body leaves the two markers adjacent.
292
+ */
293
+ function markedBody(key, body) {
294
+ const trimmed = trimBody(body);
295
+ return [`<!-- begin:${key} -->`, ...(trimmed.length > 0 ? [trimmed] : []), endMarker(key)].join('\n');
296
+ }
297
+ /**
298
+ * Whether `body`, once canonicalized (§7), holds the line that closes it — the one body a reader could
299
+ * not split by `dl-150` B's rule, so it never enters a payload.
300
+ */
301
+ function closesItself(key, body) {
302
+ const marker = endMarker(key);
303
+ return canonicalize(body).split('\n').includes(marker);
304
+ }
305
+ function selfClosingProblem(what, key) {
306
+ return `${what} cannot enter an execution context: its body holds the line ${JSON.stringify(endMarker(key))} that closes it`;
307
+ }
308
+ /** The marker key of a directive body. */
309
+ function directiveKey(id) {
310
+ return `directive:${id}`;
311
+ }
312
+ /** Whether a Memory document can be named in the payload: a string `type` and `id`, each fit for a
313
+ * heading and a marker (no control character, no `-->`). */
314
+ function isNameable(type, id) {
315
+ return (typeof type === 'string' &&
316
+ typeof id === 'string' &&
317
+ type.length > 0 &&
318
+ id.length > 0 &&
319
+ headerFieldProblem('type', type) === undefined &&
320
+ headerFieldProblem('id', id) === undefined);
321
+ }
322
+ /** §7's canonicalization: LF only, no trailing whitespace on any line, exactly one trailing `\n`. */
323
+ function canonicalize(text) {
324
+ return (text
325
+ .replace(/\r\n?/g, '\n')
326
+ .replace(/[ \t]+$/gm, '')
327
+ .replace(/\n+$/, '') + '\n');
328
+ }
329
+ /**
330
+ * Why `value` cannot sit in the payload's header comment, or `undefined` when it can. The header is one
331
+ * line inside `<!-- … -->`: a line break would split it, and `-->` would close the comment early and
332
+ * let the rest of the value pass for payload content. Control characters are refused with them.
333
+ */
334
+ function headerFieldProblem(name, value) {
335
+ // eslint-disable-next-line no-control-regex
336
+ if (/[\u0000-\u001f\u007f]/.test(value) || value.includes('-->')) {
337
+ return `invalid ${name} ${JSON.stringify(value)}: it may hold no control character and no '-->'`;
338
+ }
339
+ return undefined;
340
+ }
341
+ /** The first body in `context` that {@link closesItself}, as its refusal; `undefined` when none does.
342
+ * The element first, then directives in payload order. */
343
+ function selfClosingBody(context) {
344
+ const { element } = context;
345
+ const elementKey = `${element.type}:${element.id}`;
346
+ if (closesItself(elementKey, element.body))
347
+ return selfClosingProblem(`element '${elementKey}'`, elementKey);
348
+ for (const directive of context.directives) {
349
+ const key = directiveKey(directive.frontmatter.id);
350
+ if (closesItself(key, directive.body))
351
+ return selfClosingProblem(`directive '${directive.frontmatter.id}'`, key);
352
+ }
353
+ return undefined;
354
+ }
355
+ /**
356
+ * Render a context as `spec-012` §7's canonical Markdown payload, format {@link CONTEXT_PAYLOAD_FORMAT}
357
+ * (`dl-150` option B) — the bytes §8 holds identical across builds. Fixed headings in a fixed order,
358
+ * one blank line between blocks; frontmatter and DNA sections as fenced YAML with sorted keys; every
359
+ * directive and document body verbatim between `<!-- begin:<key> -->`/`<!-- end:<key> -->` markers
360
+ * (`<type>:<id>` for the element and Memory, `directive:<id>` for a directive), so a body's own
361
+ * headings never pass for §7's; ids rather than paths; the header names only the format, role, element
362
+ * and the resolved sha. `warnings` are not rendered.
363
+ *
364
+ * @throws Error `invalid execution context: missing '<section>' section` when `context` does not
365
+ * validate ({@link validateExecutionContext}): a partial payload is never rendered. Error `invalid
366
+ * role …` (or `element type`/`element id`/`directive id`) when a header field or a directive id holds
367
+ * a control character or `-->`; `invalid Memory document <path>: …` for a document it cannot name;
368
+ * `… cannot enter an execution context: its body holds the line … that closes it` for a body that
369
+ * holds its own end marker.
370
+ */
371
+ function serializeExecutionContext(context) {
372
+ const valid = validateExecutionContext(context);
373
+ if (!valid.ok)
374
+ throw new Error(valid.error.message);
375
+ const unsafe = headerFieldProblem('role', context.role) ??
376
+ headerFieldProblem('element type', context.element.type) ??
377
+ headerFieldProblem('element id', context.element.id) ??
378
+ context.directives.map((directive) => headerFieldProblem('directive id', directive.frontmatter.id)).find((problem) => problem !== undefined) ??
379
+ selfClosingBody(context);
380
+ if (unsafe !== undefined)
381
+ throw new Error(unsafe);
382
+ const { role, stateRef, element, dna, directives, memory } = context;
383
+ // The header comment sits on the title's next line, as §7's template shows.
384
+ const blocks = [
385
+ `# WingFoil Agent Context\n<!-- format: ${exports.CONTEXT_PAYLOAD_FORMAT} | role: ${role} | element: ${element.type}:${element.id} | state: ${stateRef} -->`,
386
+ ];
387
+ blocks.push('## 1. Task', yamlBlock(element.frontmatter), markedBody(`${element.type}:${element.id}`, element.body));
388
+ blocks.push('## 2. Project DNA');
389
+ for (const [name, value] of Object.entries(dna))
390
+ blocks.push(`### ${name}`, yamlBlock(value));
391
+ blocks.push(`## 3. Directives (${role} + global)`);
392
+ for (const directive of directives) {
393
+ blocks.push(`### ${directive.frontmatter.id}`, markedBody(directiveKey(directive.frontmatter.id), directive.body));
394
+ }
395
+ blocks.push(`## 4. Relevant Memory (${memory.length} documents)`);
396
+ for (const doc of memory) {
397
+ if (!isNameable(doc.type, doc.id)) {
398
+ throw new Error(`invalid Memory document ${doc.path}: an execution context names a document by a type and an id that hold no control character and no '-->'`);
399
+ }
400
+ const key = `${doc.type}:${doc.id}`;
401
+ if (closesItself(key, doc.body))
402
+ throw new Error(selfClosingProblem(`Memory document '${key}'`, key));
403
+ blocks.push(`### ${key}`, yamlBlock(doc.frontmatter), markedBody(key, doc.body));
404
+ }
405
+ return canonicalize(blocks.join('\n\n'));
406
+ }
407
+ function asNames(value) {
408
+ const entries = typeof value === 'string' ? [value] : Array.isArray(value) ? value : [];
409
+ return entries.filter((entry) => typeof entry === 'string' && entry.trim().length > 0);
410
+ }
411
+ /** A path with `\` read as `/` and no trailing `/`, so `src/core/` and `src/core` compare equal. */
412
+ function normalizePath(path) {
413
+ return path.replace(/\\/g, '/').replace(/\/+$/, '');
414
+ }
415
+ /** Leading characters an entry's token never starts with: quotes and backticks. */
416
+ const TOKEN_LEAD = /^[`'"]+/;
417
+ /** Trailing characters an entry's token never ends with: list and sentence punctuation, quotes and
418
+ * backticks (`bug-233`). */
419
+ const TOKEN_TRAIL = /[`'".,;:!?]+$/;
420
+ /**
421
+ * The tokens one `modules:`/`scope:` value names (`spec-012` §4, `bug-233`): parenthesised text is
422
+ * set aside, the rest is split on commas into entries, and each entry is read by its leading token
423
+ * with surrounding quotes, backticks and trailing punctuation stripped — `src/mcp/server.ts, src/cli
424
+ * (the \`wingfoil mcp\` command)` names `src/mcp/server.ts` and `src/cli`.
425
+ */
426
+ function entryTokens(entry) {
427
+ let text = entry;
428
+ for (let previous = ''; previous !== text;) {
429
+ previous = text;
430
+ text = text.replace(/\([^()]*\)/g, ' ');
431
+ }
432
+ return text
433
+ .split(',')
434
+ .map((part) => part.trim().split(/\s+/)[0].replace(TOKEN_LEAD, '').replace(TOKEN_TRAIL, ''))
435
+ .filter((token) => token.length > 0);
436
+ }
437
+ /** Whether `inner` equals `outer` or lies under it at a segment boundary. */
438
+ function isAtOrUnder(inner, outer) {
439
+ return outer.length > 0 && (inner === outer || inner.startsWith(`${outer}/`));
440
+ }
441
+ /**
442
+ * Whether one token of a `modules:`/`scope:` entry selects `module` (`spec-012` §4, approver ruling D3
443
+ * and `bug-233`): it equals the module's `name`, or — as a path, compared at segment boundaries — the
444
+ * module's `path` equals it, lies under it (`src` selects `src/core`), or holds it (`src/mcp/server.ts`
445
+ * selects `src/mcp`). `src/co` selects nothing.
446
+ */
447
+ function tokenSelectsModule(token, module) {
448
+ if (token === module.name)
449
+ return true;
450
+ if (module.path === undefined)
451
+ return false;
452
+ const named = normalizePath(token);
453
+ const path = normalizePath(module.path);
454
+ return isAtOrUnder(path, named) || isAtOrUnder(named, path);
455
+ }
456
+ /** The note recorded when the element names modules and none of them matches (ruling D3). */
457
+ function noModuleMatchNote(entries) {
458
+ return `no module matches the element's modules:/scope: (${entries.map((entry) => JSON.stringify(entry)).join(', ')}); all modules included`;
459
+ }
460
+ /** The top-level keys of a `dna.yaml` text that has already validated, in the order the file
461
+ * declares them. */
462
+ function declaredKeyOrder(raw, label) {
463
+ return Object.keys((0, validation_1.parseYaml)(raw, label));
464
+ }
465
+ /**
466
+ * `spec-012` §4, the `dna-loader`: `project`, `stacks` (`dl-151` A) and `team` always, `paths` whole
467
+ * (every category), and the `modules` the tokens of the element's `modules:`/`scope:` entries select
468
+ * ({@link entryTokens}, {@link tokenSelectsModule}), in
469
+ * `dna.yaml` order. Every module when it names none — and also when it names some and none matches,
470
+ * which then returns a note (ruling D3) for the caller's diagnostics. Sections are inserted in
471
+ * `declaredOrder`, the file's own key order.
472
+ */
473
+ function selectDnaSections(dna, declaredOrder, frontmatter) {
474
+ const entries = [...asNames(frontmatter.modules), ...asNames(frontmatter.scope)];
475
+ const tokens = entries.flatMap(entryTokens);
476
+ const matched = dna.modules.filter((module) => tokens.some((token) => tokenSelectsModule(token, module)));
477
+ const unmatched = entries.length > 0 && matched.length === 0;
478
+ const sections = {
479
+ project: dna.project,
480
+ modules: matched.length === 0 ? dna.modules : matched,
481
+ stacks: dna.stacks,
482
+ team: dna.team,
483
+ paths: dna.paths,
484
+ };
485
+ const selection = {};
486
+ for (const key of declaredOrder)
487
+ if (sections[key] !== undefined)
488
+ selection[key] = sections[key];
489
+ return unmatched
490
+ ? { selection: selection, note: noModuleMatchNote(entries) }
491
+ : { selection: selection };
492
+ }
493
+ /** The Markdown body of each resolved directive, read at `sha` (`DirectiveFile.path` is relative to
494
+ * `.wingfoil/`). */
495
+ function withBodies(root, sha, directives) {
496
+ return directives.map((directive) => {
497
+ const raw = (0, storage_1.readPathAtRev)(root, sha, `.wingfoil/${directive.path.split(/[\\/]/).join('/')}`) ?? '';
498
+ return { ...directive, body: (0, storage_1.splitFrontmatter)(raw).body };
499
+ });
500
+ }
501
+ function stringField(frontmatter, key) {
502
+ const value = frontmatter[key];
503
+ return typeof value === 'string' ? value : undefined;
504
+ }
505
+ /** The pillar file whose absence at `stateRef` leaves each section unset, keyed by the refusal. */
506
+ const ABSENT_PILLAR_FILE = {
507
+ [missingSection('element')]: loaders_1.MEMORY_YAML_PATH,
508
+ [missingSection('dna')]: loaders_1.DNA_YAML_PATH,
509
+ [missingSection('directives')]: loaders_1.ROLES_YAML_PATH,
510
+ };
511
+ function isPositiveInteger(value) {
512
+ return typeof value === 'number' && Number.isInteger(value) && value > 0;
513
+ }
514
+ /**
515
+ * A request the builder refuses before reading anything (`VALIDATION`): a role or element field that
516
+ * cannot sit in the payload header (`headerFieldProblem`), or limits that are not positive integers —
517
+ * `NaN`, a fraction, zero or a negative number would make §6's bounding meaningless.
518
+ */
519
+ function requestProblem(request) {
520
+ const header = headerFieldProblem('role', request.role) ??
521
+ headerFieldProblem('element type', request.element.type) ??
522
+ headerFieldProblem('element id', request.element.id);
523
+ if (header !== undefined)
524
+ return { code: 'VALIDATION', message: header };
525
+ const { limits } = request;
526
+ if (limits !== undefined && !(isPositiveInteger(limits.maxDocs) && isPositiveInteger(limits.maxBytes))) {
527
+ return {
528
+ code: 'VALIDATION',
529
+ message: `invalid context limits: maxDocs and maxBytes must be positive integers (got ${String(limits.maxDocs)}, ${String(limits.maxBytes)})`,
530
+ };
531
+ }
532
+ return undefined;
533
+ }
534
+ /** Ranks with no bound: used only to learn which unnameable documents would have been relevant. */
535
+ const UNBOUNDED = { maxDocs: Number.MAX_SAFE_INTEGER, maxBytes: Number.MAX_SAFE_INTEGER };
536
+ /**
537
+ * The Memory documents §7 can carry (`dl-150` B), before §6 ranks them: a document needs a nameable
538
+ * `type` and `id` ({@link isNameable}) for its heading and markers, and a body that does not hold its
539
+ * own end marker ({@link closesItself}). An unnameable document is reported only when §6 would have
540
+ * found it relevant — a repository's frontmatter-less files (grandfathered plans) would otherwise be
541
+ * reported in every context; a self-closing one is always reported. Neither takes a slot in the
542
+ * bounds, so the documents carried are what §6 selects among the rest.
543
+ */
544
+ function payloadCandidates(documents, element) {
545
+ const carried = [];
546
+ const unnamed = [];
547
+ const left = [];
548
+ for (const doc of documents) {
549
+ const { type, id } = doc.frontmatter;
550
+ if (!isNameable(type, id)) {
551
+ unnamed.push(doc);
552
+ continue;
553
+ }
554
+ const key = `${type}:${id}`;
555
+ if (closesItself(key, doc.body)) {
556
+ const reason = `its body holds the line ${JSON.stringify(endMarker(key))} that closes it in an execution context`;
557
+ left.push({ path: doc.path, diagnostic: (0, memory_1.memoryUnreadableDiagnostic)(doc.path, reason) });
558
+ }
559
+ else
560
+ carried.push(doc);
561
+ }
562
+ for (const doc of (0, relevance_1.selectRelevantMemoryDocuments)(unnamed, element, UNBOUNDED).documents) {
563
+ const reason = 'no string type and id, so an execution context cannot name it';
564
+ left.push({ path: doc.path, diagnostic: (0, memory_1.memoryUnreadableDiagnostic)(doc.path, reason) });
565
+ }
566
+ // A path is reported at most once, so no two compare equal.
567
+ left.sort((a, b) => (a.path < b.path ? -1 : 1));
568
+ return { carried, left: left.map((entry) => entry.diagnostic) };
569
+ }
570
+ /**
571
+ * The refusal of a subject that commit `sha` holds in a `format:` newer than this build reads (task-195,
572
+ * `bug-263`), or `undefined`. The tolerant scan leaves such a document out as `W_MEMORY_UNREADABLE`, so
573
+ * the subject looks absent; the lookup by (`type`, `id`) refuses exactly that case with the `dl-149`
574
+ * `ValidationError` (`E_INVALID_FORMAT`), which becomes `VALIDATION` here, as every verb that names the
575
+ * element refuses it. Called only when the scan did not find the subject, so a context that builds pays
576
+ * nothing for it.
577
+ */
578
+ function newerFormatSubject(root, sha, memoryYaml, wanted, label) {
579
+ try {
580
+ (0, memory_1.findMemoryDocumentByTypeAndIdAtRev)(root, sha, memoryYaml, wanted.type, wanted.id, { includeArchived: true });
581
+ }
582
+ catch (error) {
583
+ if (!(0, validation_1.isNewerFormatError)(error))
584
+ throw error;
585
+ return {
586
+ code: 'VALIDATION',
587
+ message: `element '${label}' at ${sha} is written in a newer format: ${error.message}`,
588
+ details: { issues: error.issues },
589
+ };
590
+ }
591
+ return undefined;
592
+ }
593
+ /**
594
+ * Build the execution context for `request` — `spec-012`'s single public entry (§1), the context
595
+ * `agent execute` (task-218) and the `{role}-session` Prompt (task-195) hand an agent.
596
+ *
597
+ * The §3 pipeline, every read at the one commit `request.stateRef` resolves to:
147
598
  *
148
- * `memory` resolves `element` via `findMemoryDocumentByTypeAndId`
149
- * (`task-011-mcp-resources-read-only`). Two properties of that primitive are inherited here and are
150
- * worth stating plainly:
599
+ * 1. **resolve-element**: every Memory document at that commit is read once
600
+ * (`loadMemoryDocumentsAtRev`); the element is found in that snapshot. Absent → `NOT_FOUND`;
601
+ * archived (`isArchivedStatus`) → `VALIDATION`, since an archived document never enters a context
602
+ * (REQ-STATE-06). A `draft` element assembles.
603
+ * 2. **load-dna** (§4): see `selectDnaSections`; modules match by name or path (ruling D3, `bug-233`).
604
+ * 3. **load-directives** (§5): {@link resolveRoleDirectives} over the directives and `roles.yaml` at the
605
+ * commit; its warnings become `context.warnings`.
606
+ * 4. **filter-memory** (§6): `selectRelevantMemoryDocuments` over the same snapshot, within
607
+ * `request.limits`, among the documents §7 can carry (`dl-150` B, `payloadCandidates`): one with
608
+ * no nameable `type` and `id` is left out, and reported only when it would have been relevant; one
609
+ * whose body holds its own end marker is left out and reported. Both reports are
610
+ * `W_MEMORY_UNREADABLE` lines on the success warnings, after the scan's own, in path order.
611
+ * 5. **validate** (P5.4.4 sc. 3) and **serialize** (§7).
151
612
  *
152
- * - It is **not** a single addressed read. It walks the Memory document paths derived from
153
- * `memoryYaml` in sorted order and YAML-parses each document's frontmatter until one matches
154
- * `element.type`/`element.id`, so cost grows with the size of the Memory tree (bounding that is
155
- * `task-035-bounded-context-relevance`'s REQ-PERF-05 scope, not this task's).
156
- * - It therefore **can throw**. An `element` that matches nothing yields an empty `memory` array
157
- * rather than an error — an unresolvable element is the caller's concern to surface — but a
158
- * `ValidationError` (`E_YAML_PARSE_ERROR`) propagates out of assembly if any document visited
159
- * during that walk has unparseable frontmatter. This function adds no `try`/`catch` of its own.
613
+ * A pillar file the commit does not hold leaves its section unset, and step 5 refuses the context:
614
+ * no `roles.yaml` → `missing 'directives'`, no `dna.yaml` → `missing 'dna'`, no `memory.yaml` →
615
+ * `missing 'element'`; the refusal's `details.cause` names the file (`no .wingfoil/roles.yaml at <sha>`).
616
+ * Before any read, a role or element field holding a control character or `-->`, or limits that are
617
+ * not positive integers, are refused as `VALIDATION`. After the reads, an element or directive body
618
+ * that holds its own end marker, or a directive id holding a control character or `-->`, refuses the
619
+ * context as `VALIDATION`: neither may be dropped (§5 never truncates a directive).
160
620
  *
161
- * `memory` **is** filtered by document status, in one direction only: a resolved element whose
162
- * `status` is archived — `{deprecated, superseded}`, per the shared {@link isArchivedStatus}
163
- * (`../memory`, the set ratified by `dl-028-archived-states-excluded-from-context`) — is dropped,
164
- * leaving `memory` empty. That is REQ-STATE-06's Fit Criterion as amended: "a `deprecated` or
165
- * `superseded` document never appears in an assembled agent context". The filter is applied to the
166
- * lookup's *result* rather than pushed into `findMemoryDocumentByTypeAndId`, because that same
167
- * primitive also serves `wingfoil://memory/{type}/{id}`, where explicit retrieval of archived content
168
- * must keep working.
621
+ * A subject the commit holds in a `format:` newer than this build reads is refused as `VALIDATION` with
622
+ * the `dl-149` `E_INVALID_FORMAT` text (task-195, `bug-263`), not reported as absent.
169
623
  *
170
- * `draft` is deliberately **not** excluded here, unlike in `./relevance.ts`. That module filters
171
- * *candidate* documents for relevance (spec-012 §6, which does bar `draft` from a context); this
172
- * function resolves the **subject** element the context is being assembled for (spec-012 §3's
173
- * `resolve-element` stage), and blanking the context for a task still in `draft` would defeat the
174
- * point of assembling it. dl-028 ratified the archived set as `{deprecated, superseded}` and did not
175
- * put `draft` in it.
624
+ * A Memory document that does not parse is left out and reported (task-171): as a `W_MEMORY_UNREADABLE`
625
+ * line in the result's `warnings` on success, and in `details.unreadable` of a `NOT_FOUND` refusal, so
626
+ * a subject that does not parse is not reported as merely absent. Neither reaches the payload.
176
627
  *
177
- * An archived element produces no warning: {@link ExecutionContext.warnings} carries
178
- * directive-resolution diagnostics only (dl-029, dl-037, dl-042), and adding an unratified entry would change a payload
179
- * REQ-SYS-07 governs. An archived element is therefore indistinguishable here from an unresolvable
180
- * one — both yield `memory: []`.
181
- */
182
- function assembleExecutionContext(inputs) {
183
- const { directives, warnings } = resolveRoleDirectives(inputs.directiveFiles, inputs.rolesYaml, inputs.role);
184
- const doc = (0, memory_1.findMemoryDocumentByTypeAndId)(inputs.root, inputs.memoryYaml, inputs.element.type, inputs.element.id);
185
- // `frontmatter` is untyped (`Record<string, unknown>`), so project `status` to the
186
- // `string | undefined` shape `isArchivedStatus` takes — a non-string `status` is never archived,
187
- // exactly as that predicate's contract states.
188
- const status = typeof doc?.frontmatter.status === 'string' ? doc.frontmatter.status : undefined;
189
- const memory = doc !== undefined && !(0, memory_1.isArchivedStatus)(status) ? [doc] : [];
190
- return { dna: inputs.dna, directives, memory, warnings };
628
+ * Expected failures are returned, never thrown: a `stateRef` that is malformed or names no commit is
629
+ * the `RevisionError`'s own `CoreError`. A pillar file (`dna.yaml`, `roles.yaml`, a directive) that
630
+ * does not parse still throws `ValidationError`, as its loader does.
631
+ */
632
+ function assembleExecutionContext(root, request) {
633
+ const refused = requestProblem(request);
634
+ if (refused !== undefined)
635
+ return (0, types_1.coreErr)(refused);
636
+ let sha;
637
+ try {
638
+ sha = (0, revision_1.resolveRevision)(root, request.stateRef);
639
+ }
640
+ catch (error) {
641
+ if (error instanceof revision_1.RevisionError)
642
+ return (0, types_1.coreErr)(error.toCoreError());
643
+ throw error;
644
+ }
645
+ const { role, element: wanted } = request;
646
+ const label = `${wanted.type}:${wanted.id}`;
647
+ // The scan is tolerant (task-171, `bug-031`): a document it cannot read is left out and reported as
648
+ // `W_MEMORY_UNREADABLE`, so one malformed sibling no longer fails every context. It reads archived
649
+ // documents too — the archived subject is refused below, and §6 drops archived candidates itself.
650
+ const diagnostics = [];
651
+ const memoryYaml = (0, loaders_1.loadMemoryYamlAtRev)(root, sha);
652
+ const documents = memoryYaml === null
653
+ ? null
654
+ : (0, memory_1.loadMemoryDocumentsAtRev)(root, sha, memoryYaml, { onDiagnostic: (diagnostic) => diagnostics.push(diagnostic) });
655
+ const unreadable = diagnostics.map(validation_1.formatDiagnostic);
656
+ const found = documents?.find((doc) => stringField(doc.frontmatter, 'type') === wanted.type && stringField(doc.frontmatter, 'id') === wanted.id);
657
+ if (documents !== null && found === undefined) {
658
+ // A subject written in a newer format exists: it is refused for its format (`bug-263`).
659
+ const newer = newerFormatSubject(root, sha, memoryYaml, wanted, label);
660
+ if (newer !== undefined)
661
+ return (0, types_1.coreErr)(newer);
662
+ // A subject whose own frontmatter does not parse is among the unreadable files: name them, so the
663
+ // refusal does not read as a bare "not found".
664
+ return (0, types_1.coreErr)({
665
+ code: 'NOT_FOUND',
666
+ message: `element '${label}' not found at ${sha}`,
667
+ ...(unreadable.length > 0 ? { details: { unreadable } } : {}),
668
+ });
669
+ }
670
+ const status = found === undefined ? undefined : stringField(found.frontmatter, 'status');
671
+ if ((0, memory_1.isArchivedStatus)(status)) {
672
+ return (0, types_1.coreErr)({
673
+ code: 'VALIDATION',
674
+ message: `element '${label}' is ${status}: an archived element never enters an execution context`,
675
+ });
676
+ }
677
+ const element = found === undefined ? undefined : { ...found, type: wanted.type, id: wanted.id };
678
+ const frontmatter = element?.frontmatter ?? {};
679
+ // `loadDnaYamlAtRev` validates; the raw text gives the declared section order, which the
680
+ // Zod-parsed object loses (schema keys come first there). `loadDnaYamlAtRev` is non-null whenever
681
+ // the raw read is: both read the same path at the same sha.
682
+ const dnaRaw = (0, storage_1.readPathAtRev)(root, sha, loaders_1.DNA_YAML_PATH);
683
+ const dnaSelected = dnaRaw === null
684
+ ? undefined
685
+ : selectDnaSections((0, loaders_1.loadDnaYamlAtRev)(root, sha), declaredKeyOrder(dnaRaw, `${sha}:${loaders_1.DNA_YAML_PATH}`), frontmatter);
686
+ const dna = dnaSelected?.selection;
687
+ const rolesYaml = (0, loaders_1.loadRolesYamlAtRev)(root, sha);
688
+ const resolution = rolesYaml === null ? undefined : resolveRoleDirectives((0, loaders_1.loadDirectivesAtRev)(root, sha), rolesYaml, role);
689
+ const directives = resolution === undefined ? undefined : withBodies(root, sha, resolution.directives);
690
+ const candidates = documents === null ? undefined : payloadCandidates(documents, { ...wanted, frontmatter });
691
+ const relevant = candidates === undefined
692
+ ? undefined
693
+ : (0, relevance_1.selectRelevantMemoryDocuments)(candidates.carried, { ...wanted, frontmatter }, request.limits ?? relevance_1.DEFAULT_CONTEXT_LIMITS);
694
+ // The payload carries the frontmatter as written (`bug-232`): the element and the selected documents
695
+ // are re-read at the commit with the payload's schema. Selection above used the scan's parse.
696
+ const carried = [...(element === undefined ? [] : [element]), ...(relevant?.documents ?? [])];
697
+ const written = writtenFrontmatter(root, sha, carried.map((doc) => doc.path));
698
+ const offset = carried.length - (relevant?.documents.length ?? 0);
699
+ const validated = validateExecutionContext({
700
+ role,
701
+ stateRef: sha,
702
+ element: element === undefined ? undefined : { ...element, frontmatter: written[0] },
703
+ dna,
704
+ directives,
705
+ memory: relevant?.documents.map((doc, index) => ({ ...doc, frontmatter: written[offset + index] })),
706
+ warnings: resolution?.warnings ?? [],
707
+ });
708
+ if (!validated.ok) {
709
+ // Every section the builder can leave unset is unset by an absent pillar file (an absent
710
+ // `memory.yaml` unsets `element` before `memory`), so the refusal always names one. The message
711
+ // stays P5.4.4's, verbatim.
712
+ const cause = `no ${ABSENT_PILLAR_FILE[validated.error.message]} at ${sha}`;
713
+ return (0, types_1.coreErr)({ ...validated.error, details: { cause } });
714
+ }
715
+ const context = validated.value;
716
+ const unfit = context.directives.map((directive) => headerFieldProblem('directive id', directive.frontmatter.id)).find((problem) => problem !== undefined) ??
717
+ selfClosingBody(context);
718
+ if (unfit !== undefined)
719
+ return (0, types_1.coreErr)({ code: 'VALIDATION', message: unfit });
720
+ // In §3 stage order: the DNA note (ruling D3), then the relevance note (P5.3.3 sc. 3).
721
+ const notes = [dnaSelected?.note, relevant?.note].filter((note) => note !== undefined);
722
+ // Unreadable files are about the repository, not the context: they ride the success-warning channel
723
+ // (task-169), as `memory search` carries them (task-171), and never enter the payload.
724
+ // `candidates` is set whenever `memory.yaml` is, and without it the context was refused above.
725
+ const warnings = [...unreadable, ...candidates.left.map(validation_1.formatDiagnostic)];
726
+ return (0, types_1.coreOk)({ context, payload: serializeExecutionContext(context), notes }, undefined, warnings);
191
727
  }
192
728
  //# sourceMappingURL=context.js.map