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,34 +1,34 @@
1
1
  /**
2
- * DirectiveFrontmatter schema (task-004-decoupled-pillars, REQ-SYS-02) — the fourth pillar named by
3
- * this task's Acceptance Criteria ("memory.yaml, dna.yaml, directives/*.yaml, and workflows.yaml
4
- * each validate against their own Zod schema independently").
2
+ * DirectiveFrontmatter schema (task-004-decoupled-pillars, REQ-SYS-02) — the Directives pillar's
3
+ * per-file YAML frontmatter shape, validated independently of the other three pillars (`memory.yaml`,
4
+ * `dna.yaml`, `workflows.yaml`).
5
5
  *
6
- * UNLIKE memory.yaml/dna.yaml/workflows.yaml, there is currently no dedicated, approved tech-spec
7
- * for the Directives pillar's own file shape: spec-010-memory-frontmatter-schema's scope is
8
- * explicitly `docs/04_memory/**\/*.md frontmatter` (Memory documents), not
9
- * `.wingfoil/directives/**` (Directives files are `.md` with YAML frontmatter, not `.yaml` — the
10
- * AC's "directives/*.yaml" phrasing does not match the real file extension either). This schema is
11
- * therefore an [AUTHORING]-level minimal shape, grounded directly in the fields every one of the
12
- * twelve real files under `.wingfoil/directives/custom/*.md` actually carries (`id`,
13
- * `name`, `type: directive`, `kind`, `title`, `tags`, `ref`, and — on three files — `scope`), not a
14
- * transcription of an approved spec. See this task's Execution Notes for why this was not treated
15
- * as a hard STOP (design-gap) and the follow-up this leaves for the reviewer/approver (a candidate
16
- * `spec-013-directive-frontmatter-schema`).
6
+ * The shape is specified by `spec-013-directive-frontmatter-schema` (`approved`), which `task-004`'s
7
+ * fast-follow wrote to close the traceability gap this schema was first shipped with: its field table
8
+ * is the authority for every key below, and this file is its reference implementation. The files are
9
+ * `.md` with YAML frontmatter, not `.yaml` (spec-013 Context corrects REQ-SYS-02's
10
+ * "directives/*.yaml" wording).
17
11
  *
18
- * `name` is REQUIRED, not merely observed: REQ-SYS-02's own traceability cites
19
- * `p3-directives/P3.5-project-directives.feature`, whose "Error - a directive file missing required
20
- * header fields" scenario is explicit ("Given a custom directive file lacks its required 'name'
21
- * header ... Then loading reports the file as invalid") — the one piece of that BDD contract this
22
- * schema honors even without a tech-spec of its own.
12
+ * `name` is REQUIRED as a `[SPEC]` field: `p3-directives/P3.5-project-directives.feature`'s "Error - a
13
+ * directive file missing required header fields" scenario reports a file lacking `name` as invalid.
14
+ * The other required keys are `[AUTHORING]` (spec-013 Consequences).
15
+ *
16
+ * `scope` and `version` are declared optional keys since `task-144` (spec-013 Revision 2026-10-01;
17
+ * bug-113, bug-148): a directive carrying either one no longer prints spec-009's unknown-field warning.
18
+ * `scope` does not decide anything — `roles.yaml`'s `global:` list is the authority on which directives
19
+ * bind every role, and `directives list` reports a disagreement between the two (`src/core/directive-scope.ts`).
23
20
  *
24
21
  * `.passthrough()` per spec-009-validation-strategy §2, matching every other pillar schema.
25
22
  */
26
23
  import { z } from 'zod';
27
24
  /**
28
- * The YAML frontmatter of a `.wingfoil/directives/**\/*.md` file — the minimal [AUTHORING] shape
29
- * grounded in the fields the real custom directive files carry (see the module doc for why there is
30
- * no dedicated tech-spec). `name` is required per REQ-SYS-08's BDD contract. `.passthrough()` per
31
- * spec-009 §2.
25
+ * The YAML frontmatter of a `.wingfoil/directives/**\/*.md` file, per `spec-013`'s field table. `name`
26
+ * is required per P3.5's BDD contract. `scope` is any string: `global` is the one value spec-013
27
+ * defines, and `directives list` reports any other rather than failing the pillar (forward
28
+ * compatibility, approver ruling R2 2026-10-02). `version` is a string or a number, like
29
+ * `memory.yaml`'s and `roles.yaml`'s (R1); `./version` warns when a number loses what was written.
30
+ * `format` is the frontmatter's format, distinct from `version` (`dl-149`, task-251: absent = 1).
31
+ * `.passthrough()` per spec-009 §2.
32
32
  */
33
33
  export declare const DirectiveFrontmatter: z.ZodObject<{
34
34
  id: z.ZodString;
@@ -38,25 +38,30 @@ export declare const DirectiveFrontmatter: z.ZodObject<{
38
38
  title: z.ZodString;
39
39
  tags: z.ZodOptional<z.ZodArray<z.ZodString>>;
40
40
  ref: z.ZodOptional<z.ZodArray<z.ZodString>>;
41
+ scope: z.ZodOptional<z.ZodString>;
42
+ version: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
43
+ format: z.ZodOptional<z.ZodNumber>;
41
44
  }, z.core.$loose>;
42
45
  /** Parsed shape of the {@link DirectiveFrontmatter} schema. */
43
46
  export type DirectiveFrontmatter = z.infer<typeof DirectiveFrontmatter>;
44
47
  /**
45
48
  * `.wingfoil/roles.yaml` schema (task-037-role-task-scoped-context, REQ-STATE-05's
46
49
  * `directive-loader`, P3.2/P3.7) — the role → directive binding config
47
- * `resolveRoleDirectives`/`assembleExecutionContext` (`src/core/context.ts`) resolve against. Same
48
- * [AUTHORING]-level rationale as {@link DirectiveFrontmatter}: no dedicated tech-spec covers this
49
- * pillar's own file shapes yet (spec-012-context-loader-relevance-filtering §5 describes the
50
- * `directive-loader`'s *behavior* — "look up the request role in `roles.yaml`" — but not roles.yaml's
51
- * own schema), so this is grounded directly in the fields the real, live
50
+ * `resolveRoleDirectives`/`assembleExecutionContext` (`src/core/context.ts`) resolve against. An
51
+ * [AUTHORING]-level shape: `spec-013` specifies the directive files only, and
52
+ * spec-012-context-loader-relevance-filtering §5 describes the `directive-loader`'s *behavior* — "look
53
+ * up the request role in `roles.yaml`" — but not roles.yaml's own schema, so this is grounded directly
54
+ * in the fields the real, live
52
55
  * `.wingfoil/roles.yaml` file carries: `version`, `assignments` (role name -> directive id
53
56
  * array), and `global` (directive ids applied to every role). `assignments` keys are role names
54
57
  * (validated against `dna.yaml`'s `team.roles` catalogue elsewhere, by REQ-SYS-08/task-034 — NOT here,
55
58
  * to keep this pillar's schema independent per REQ-SYS-02); `assignments` values and `global` entries
56
- * are directive **ids** (`DirectiveFrontmatter.id`), not `name`s. `.passthrough()` per spec-009 §2.
59
+ * are directive **ids** (`DirectiveFrontmatter.id`), not `name`s. `format` is the file's format
60
+ * (`dl-149`, task-251: absent = 1). `.passthrough()` per spec-009 §2.
57
61
  */
58
62
  export declare const RolesYaml: z.ZodObject<{
59
63
  version: z.ZodOptional<z.ZodNumber>;
64
+ format: z.ZodOptional<z.ZodNumber>;
60
65
  assignments: z.ZodRecord<z.ZodString, z.ZodArray<z.ZodString>>;
61
66
  global: z.ZodDefault<z.ZodArray<z.ZodString>>;
62
67
  }, z.core.$loose>;
@@ -1 +1 @@
1
- {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/directives/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;iBAUjB,CAAC;AACjB,+DAA+D;AAC/D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,SAAS;;;;iBAMN,CAAC;AACjB,oDAAoD;AACpD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC"}
1
+ {"version":3,"file":"schema.d.ts","sourceRoot":"","sources":["../../src/directives/schema.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAIxB;;;;;;;;GAQG;AACH,eAAO,MAAM,oBAAoB;;;;;;;;;;;iBAajB,CAAC;AACjB,+DAA+D;AAC/D,MAAM,MAAM,oBAAoB,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,oBAAoB,CAAC,CAAC;AAExE;;;;;;;;;;;;;;GAcG;AACH,eAAO,MAAM,SAAS;;;;;iBAON,CAAC;AACjB,oDAAoD;AACpD,MAAM,MAAM,SAAS,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,SAAS,CAAC,CAAC"}
@@ -2,36 +2,37 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.RolesYaml = exports.DirectiveFrontmatter = void 0;
4
4
  /**
5
- * DirectiveFrontmatter schema (task-004-decoupled-pillars, REQ-SYS-02) — the fourth pillar named by
6
- * this task's Acceptance Criteria ("memory.yaml, dna.yaml, directives/*.yaml, and workflows.yaml
7
- * each validate against their own Zod schema independently").
5
+ * DirectiveFrontmatter schema (task-004-decoupled-pillars, REQ-SYS-02) — the Directives pillar's
6
+ * per-file YAML frontmatter shape, validated independently of the other three pillars (`memory.yaml`,
7
+ * `dna.yaml`, `workflows.yaml`).
8
8
  *
9
- * UNLIKE memory.yaml/dna.yaml/workflows.yaml, there is currently no dedicated, approved tech-spec
10
- * for the Directives pillar's own file shape: spec-010-memory-frontmatter-schema's scope is
11
- * explicitly `docs/04_memory/**\/*.md frontmatter` (Memory documents), not
12
- * `.wingfoil/directives/**` (Directives files are `.md` with YAML frontmatter, not `.yaml` — the
13
- * AC's "directives/*.yaml" phrasing does not match the real file extension either). This schema is
14
- * therefore an [AUTHORING]-level minimal shape, grounded directly in the fields every one of the
15
- * twelve real files under `.wingfoil/directives/custom/*.md` actually carries (`id`,
16
- * `name`, `type: directive`, `kind`, `title`, `tags`, `ref`, and — on three files — `scope`), not a
17
- * transcription of an approved spec. See this task's Execution Notes for why this was not treated
18
- * as a hard STOP (design-gap) and the follow-up this leaves for the reviewer/approver (a candidate
19
- * `spec-013-directive-frontmatter-schema`).
9
+ * The shape is specified by `spec-013-directive-frontmatter-schema` (`approved`), which `task-004`'s
10
+ * fast-follow wrote to close the traceability gap this schema was first shipped with: its field table
11
+ * is the authority for every key below, and this file is its reference implementation. The files are
12
+ * `.md` with YAML frontmatter, not `.yaml` (spec-013 Context corrects REQ-SYS-02's
13
+ * "directives/*.yaml" wording).
20
14
  *
21
- * `name` is REQUIRED, not merely observed: REQ-SYS-02's own traceability cites
22
- * `p3-directives/P3.5-project-directives.feature`, whose "Error - a directive file missing required
23
- * header fields" scenario is explicit ("Given a custom directive file lacks its required 'name'
24
- * header ... Then loading reports the file as invalid") — the one piece of that BDD contract this
25
- * schema honors even without a tech-spec of its own.
15
+ * `name` is REQUIRED as a `[SPEC]` field: `p3-directives/P3.5-project-directives.feature`'s "Error - a
16
+ * directive file missing required header fields" scenario reports a file lacking `name` as invalid.
17
+ * The other required keys are `[AUTHORING]` (spec-013 Consequences).
18
+ *
19
+ * `scope` and `version` are declared optional keys since `task-144` (spec-013 Revision 2026-10-01;
20
+ * bug-113, bug-148): a directive carrying either one no longer prints spec-009's unknown-field warning.
21
+ * `scope` does not decide anything — `roles.yaml`'s `global:` list is the authority on which directives
22
+ * bind every role, and `directives list` reports a disagreement between the two (`src/core/directive-scope.ts`).
26
23
  *
27
24
  * `.passthrough()` per spec-009-validation-strategy §2, matching every other pillar schema.
28
25
  */
29
26
  const zod_1 = require("zod");
27
+ const format_1 = require("../validation/format");
30
28
  /**
31
- * The YAML frontmatter of a `.wingfoil/directives/**\/*.md` file — the minimal [AUTHORING] shape
32
- * grounded in the fields the real custom directive files carry (see the module doc for why there is
33
- * no dedicated tech-spec). `name` is required per REQ-SYS-08's BDD contract. `.passthrough()` per
34
- * spec-009 §2.
29
+ * The YAML frontmatter of a `.wingfoil/directives/**\/*.md` file, per `spec-013`'s field table. `name`
30
+ * is required per P3.5's BDD contract. `scope` is any string: `global` is the one value spec-013
31
+ * defines, and `directives list` reports any other rather than failing the pillar (forward
32
+ * compatibility, approver ruling R2 2026-10-02). `version` is a string or a number, like
33
+ * `memory.yaml`'s and `roles.yaml`'s (R1); `./version` warns when a number loses what was written.
34
+ * `format` is the frontmatter's format, distinct from `version` (`dl-149`, task-251: absent = 1).
35
+ * `.passthrough()` per spec-009 §2.
35
36
  */
36
37
  exports.DirectiveFrontmatter = zod_1.z
37
38
  .object({
@@ -42,25 +43,30 @@ exports.DirectiveFrontmatter = zod_1.z
42
43
  title: zod_1.z.string(),
43
44
  tags: zod_1.z.array(zod_1.z.string()).optional(),
44
45
  ref: zod_1.z.array(zod_1.z.string()).optional(),
46
+ scope: zod_1.z.string().optional(),
47
+ version: zod_1.z.union([zod_1.z.string(), zod_1.z.number()]).optional(),
48
+ format: (0, format_1.formatField)(format_1.DIRECTIVE_FORMAT),
45
49
  })
46
50
  .passthrough();
47
51
  /**
48
52
  * `.wingfoil/roles.yaml` schema (task-037-role-task-scoped-context, REQ-STATE-05's
49
53
  * `directive-loader`, P3.2/P3.7) — the role → directive binding config
50
- * `resolveRoleDirectives`/`assembleExecutionContext` (`src/core/context.ts`) resolve against. Same
51
- * [AUTHORING]-level rationale as {@link DirectiveFrontmatter}: no dedicated tech-spec covers this
52
- * pillar's own file shapes yet (spec-012-context-loader-relevance-filtering §5 describes the
53
- * `directive-loader`'s *behavior* — "look up the request role in `roles.yaml`" — but not roles.yaml's
54
- * own schema), so this is grounded directly in the fields the real, live
54
+ * `resolveRoleDirectives`/`assembleExecutionContext` (`src/core/context.ts`) resolve against. An
55
+ * [AUTHORING]-level shape: `spec-013` specifies the directive files only, and
56
+ * spec-012-context-loader-relevance-filtering §5 describes the `directive-loader`'s *behavior* — "look
57
+ * up the request role in `roles.yaml`" — but not roles.yaml's own schema, so this is grounded directly
58
+ * in the fields the real, live
55
59
  * `.wingfoil/roles.yaml` file carries: `version`, `assignments` (role name -> directive id
56
60
  * array), and `global` (directive ids applied to every role). `assignments` keys are role names
57
61
  * (validated against `dna.yaml`'s `team.roles` catalogue elsewhere, by REQ-SYS-08/task-034 — NOT here,
58
62
  * to keep this pillar's schema independent per REQ-SYS-02); `assignments` values and `global` entries
59
- * are directive **ids** (`DirectiveFrontmatter.id`), not `name`s. `.passthrough()` per spec-009 §2.
63
+ * are directive **ids** (`DirectiveFrontmatter.id`), not `name`s. `format` is the file's format
64
+ * (`dl-149`, task-251: absent = 1). `.passthrough()` per spec-009 §2.
60
65
  */
61
66
  exports.RolesYaml = zod_1.z
62
67
  .object({
63
68
  version: zod_1.z.number().optional(),
69
+ format: (0, format_1.formatField)(format_1.ROLES_YAML_FORMAT),
64
70
  assignments: zod_1.z.record(zod_1.z.string(), zod_1.z.array(zod_1.z.string())),
65
71
  global: zod_1.z.array(zod_1.z.string()).default([]),
66
72
  })
@@ -1 +1 @@
1
- {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/directives/schema.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,6BAAwB;AAExB;;;;;GAKG;AACU,QAAA,oBAAoB,GAAG,OAAC;KAClC,MAAM,CAAC;IACN,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IAC5B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;IACjB,IAAI,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,GAAG,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;CACpC,CAAC;KACD,WAAW,EAAE,CAAC;AAIjB;;;;;;;;;;;;;GAaG;AACU,QAAA,SAAS,GAAG,OAAC;KACvB,MAAM,CAAC;IACN,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,WAAW,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,MAAM,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACxC,CAAC;KACD,WAAW,EAAE,CAAC"}
1
+ {"version":3,"file":"schema.js","sourceRoot":"","sources":["../../src/directives/schema.ts"],"names":[],"mappings":";;;AAAA;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,6BAAwB;AAExB,iDAAwF;AAExF;;;;;;;;GAQG;AACU,QAAA,oBAAoB,GAAG,OAAC;KAClC,MAAM,CAAC;IACN,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE;IACd,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,IAAI,EAAE,OAAC,CAAC,OAAO,CAAC,WAAW,CAAC;IAC5B,IAAI,EAAE,OAAC,CAAC,MAAM,EAAE;IAChB,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE;IACjB,IAAI,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACpC,GAAG,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,QAAQ,EAAE;IACnC,KAAK,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC5B,OAAO,EAAE,OAAC,CAAC,KAAK,CAAC,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,QAAQ,EAAE;IACrD,MAAM,EAAE,IAAA,oBAAW,EAAC,yBAAgB,CAAC;CACtC,CAAC;KACD,WAAW,EAAE,CAAC;AAIjB;;;;;;;;;;;;;;GAcG;AACU,QAAA,SAAS,GAAG,OAAC;KACvB,MAAM,CAAC;IACN,OAAO,EAAE,OAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;IAC9B,MAAM,EAAE,IAAA,oBAAW,EAAC,0BAAiB,CAAC;IACtC,WAAW,EAAE,OAAC,CAAC,MAAM,CAAC,OAAC,CAAC,MAAM,EAAE,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC;IACtD,MAAM,EAAE,OAAC,CAAC,KAAK,CAAC,OAAC,CAAC,MAAM,EAAE,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC;CACxC,CAAC;KACD,WAAW,EAAE,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * A directive's `version:` frontmatter key is never a reason to fail the Directives pillar
3
+ * (`spec-013-directive-frontmatter-schema`, Revision 2026-10-01; approver ruling R1 at `task-144`'s
4
+ * review, 2026-10-02). It accepts a string or a number, like `memory.yaml`'s and `roles.yaml`'s own
5
+ * `version`. Two cases still deserve a word to the author, and this module decides them over the parsed
6
+ * frontmatter plus the frontmatter's own text:
7
+ *
8
+ * - **An unquoted number that does not read back as written.** YAML reads `version: 1.10` as the
9
+ * number `1.1`, and `version: 1.0` as `1`: the digits the author typed are lost. The value loads as
10
+ * parsed, and the warning tells the author to quote it.
11
+ * - **A value that is neither a string nor a number** (a list, a mapping, a boolean). It is dropped
12
+ * before validation, with a warning, so the rest of the file — and every other directive — still
13
+ * loads.
14
+ *
15
+ * Pure (REQ-SYS-07): the caller decides where the warning goes (`loadDirectiveInventory` puts it in its
16
+ * `warnings` as `directive '<.wingfoil/directives/…>': <warning>`).
17
+ */
18
+ /** The parsed frontmatter, possibly without its `version`, and the warning to show, if any. */
19
+ export interface DirectiveVersionCheck {
20
+ readonly data: unknown;
21
+ readonly warning: string | null;
22
+ }
23
+ /**
24
+ * Check `data.version` against the text it was parsed from. Returns `data` unchanged unless the
25
+ * version is neither a string nor a number, in which case a shallow copy without `version` is returned.
26
+ */
27
+ export declare function checkDirectiveVersion(data: unknown, frontmatterText: string): DirectiveVersionCheck;
28
+ //# sourceMappingURL=version.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.d.ts","sourceRoot":"","sources":["../../src/directives/version.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AAEH,+FAA+F;AAC/F,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;CACjC;AAWD;;;GAGG;AACH,wBAAgB,qBAAqB,CAAC,IAAI,EAAE,OAAO,EAAE,eAAe,EAAE,MAAM,GAAG,qBAAqB,CAenG"}
@@ -0,0 +1,51 @@
1
+ "use strict";
2
+ /**
3
+ * A directive's `version:` frontmatter key is never a reason to fail the Directives pillar
4
+ * (`spec-013-directive-frontmatter-schema`, Revision 2026-10-01; approver ruling R1 at `task-144`'s
5
+ * review, 2026-10-02). It accepts a string or a number, like `memory.yaml`'s and `roles.yaml`'s own
6
+ * `version`. Two cases still deserve a word to the author, and this module decides them over the parsed
7
+ * frontmatter plus the frontmatter's own text:
8
+ *
9
+ * - **An unquoted number that does not read back as written.** YAML reads `version: 1.10` as the
10
+ * number `1.1`, and `version: 1.0` as `1`: the digits the author typed are lost. The value loads as
11
+ * parsed, and the warning tells the author to quote it.
12
+ * - **A value that is neither a string nor a number** (a list, a mapping, a boolean). It is dropped
13
+ * before validation, with a warning, so the rest of the file — and every other directive — still
14
+ * loads.
15
+ *
16
+ * Pure (REQ-SYS-07): the caller decides where the warning goes (`loadDirectiveInventory` puts it in its
17
+ * `warnings` as `directive '<.wingfoil/directives/…>': <warning>`).
18
+ */
19
+ Object.defineProperty(exports, "__esModule", { value: true });
20
+ exports.checkDirectiveVersion = checkDirectiveVersion;
21
+ /**
22
+ * The scalar written after `version:` on its own top-level line of `frontmatterText`, or `null` when
23
+ * there is no such line. A trailing `# comment` is not part of the value.
24
+ */
25
+ function writtenVersionToken(frontmatterText) {
26
+ const match = /^version:[ \t]*([^\s#]+)/m.exec(frontmatterText);
27
+ return match?.[1] ?? null;
28
+ }
29
+ /**
30
+ * Check `data.version` against the text it was parsed from. Returns `data` unchanged unless the
31
+ * version is neither a string nor a number, in which case a shallow copy without `version` is returned.
32
+ */
33
+ function checkDirectiveVersion(data, frontmatterText) {
34
+ if (data === null || typeof data !== 'object' || Array.isArray(data) || !('version' in data)) {
35
+ return { data, warning: null };
36
+ }
37
+ const { version, ...rest } = data;
38
+ if (typeof version === 'string')
39
+ return { data, warning: null };
40
+ if (typeof version === 'number') {
41
+ const written = writtenVersionToken(frontmatterText);
42
+ if (written === null || written === String(version))
43
+ return { data, warning: null };
44
+ return {
45
+ data,
46
+ warning: `version: ${written} reads as the number ${String(version)}; quote it (version: "${written}") to keep it as written`,
47
+ };
48
+ }
49
+ return { data: rest, warning: 'version must be a string or a number; ignored' };
50
+ }
51
+ //# sourceMappingURL=version.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"version.js","sourceRoot":"","sources":["../../src/directives/version.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;GAgBG;;AAqBH,sDAeC;AA5BD;;;GAGG;AACH,SAAS,mBAAmB,CAAC,eAAuB;IAClD,MAAM,KAAK,GAAG,2BAA2B,CAAC,IAAI,CAAC,eAAe,CAAC,CAAC;IAChE,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,SAAgB,qBAAqB,CAAC,IAAa,EAAE,eAAuB;IAC1E,IAAI,IAAI,KAAK,IAAI,IAAI,OAAO,IAAI,KAAK,QAAQ,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,SAAS,IAAI,IAAI,CAAC,EAAE,CAAC;QAC7F,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;IACD,MAAM,EAAE,OAAO,EAAE,GAAG,IAAI,EAAE,GAAG,IAA+B,CAAC;IAC7D,IAAI,OAAO,OAAO,KAAK,QAAQ;QAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IAChE,IAAI,OAAO,OAAO,KAAK,QAAQ,EAAE,CAAC;QAChC,MAAM,OAAO,GAAG,mBAAmB,CAAC,eAAe,CAAC,CAAC;QACrD,IAAI,OAAO,KAAK,IAAI,IAAI,OAAO,KAAK,MAAM,CAAC,OAAO,CAAC;YAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;QACpF,OAAO;YACL,IAAI;YACJ,OAAO,EAAE,YAAY,OAAO,wBAAwB,MAAM,CAAC,OAAO,CAAC,yBAAyB,OAAO,0BAA0B;SAC9H,CAAC;IACJ,CAAC;IACD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,OAAO,EAAE,+CAA+C,EAAE,CAAC;AAClF,CAAC"}
@@ -42,8 +42,9 @@ export type DnaTextEdit =
42
42
  };
43
43
  /**
44
44
  * Apply `edit` to the RAW TEXT of a `dna.yaml`, editing as few lines as possible, and return the new
45
- * text — or `undefined`, deliberately and not as an error, when no provably-minimal edit exists, so the
46
- * caller falls back to the whole-file `dump()`.
45
+ * text — or `undefined`, deliberately and not as an error, when no provably-minimal edit exists. The
46
+ * caller then refuses the write, or rewrites the whole file when `--force` authorizes it and says that
47
+ * the comments were not kept (task-193, `runDnaMutation` in `src/core`).
47
48
  *
48
49
  * `intended` is the document the mutation produced (`applyDnaMutation`'s `dna`). It serves twice: an
49
50
  * inline flow sequence is re-rendered from it rather than patched token-by-token, and — the part that
@@ -52,10 +53,10 @@ export type DnaTextEdit =
52
53
  * while key values are the contract; a mis-located edit fails the comparison and costs the comments,
53
54
  * never the content.
54
55
  *
55
- * Declines (returns `undefined`) when: the text is not one valid YAML document; a step of the path is
56
- * absent from the text; the target or a value it must rewrite spans more than its own line (a block
57
- * scalar, a nested block); a value has no single-line YAML form; or the result does not read back as
58
- * `intended`.
56
+ * Declines (returns `undefined`) when: the text is not one valid YAML document; an absent step of the
57
+ * path cannot be inserted (a sequence index, or a parent holding an inline value other than `{}`); the
58
+ * target spans more than its own line as a nested block (a block scalar is replaced, not declined); a
59
+ * value has no single-line YAML form; or the result does not read back as `intended`.
59
60
  */
60
61
  export declare function applyDnaEditInText(text: string, edit: DnaTextEdit, intended: unknown): string | undefined;
61
62
  //# sourceMappingURL=edit.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/dna/edit.ts"],"names":[],"mappings":"AA0BA,gGAAgG;AAChG,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,oFAAoF;AACpF,MAAM,MAAM,WAAW;AACrB,8FAA8F;AAC5F;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACjG,iFAAiF;GAC/E;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE;AACxE,uDAAuD;GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE;AAC9G,sEAAsE;GACpE;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;AAC/G,gEAAgE;GAC9D;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE;AAC9G,oGAAoG;GAClG;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE,CAAC;AA8YvE;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAkBzG"}
1
+ {"version":3,"file":"edit.d.ts","sourceRoot":"","sources":["../../src/dna/edit.ts"],"names":[],"mappings":"AA6BA,gGAAgG;AAChG,MAAM,MAAM,WAAW,GAAG;IAAE,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAEhF,oFAAoF;AACpF,MAAM,MAAM,WAAW;AACrB,8FAA8F;AAC5F;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAA;CAAE;AACjG,iFAAiF;GAC/E;IAAE,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE;AACxE,uDAAuD;GACrD;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE;AAC9G,sEAAsE;GACpE;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;AAC/G,gEAAgE;GAC9D;IAAE,QAAQ,CAAC,IAAI,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,SAAS,WAAW,EAAE,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,OAAO,EAAE,CAAA;CAAE;AAC9G,oGAAoG;GAClG;IAAE,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,SAAS,WAAW,EAAE,CAAA;CAAE,CAAC;AA8bvE;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,EAAE,QAAQ,EAAE,OAAO,GAAG,MAAM,GAAG,SAAS,CAyBzG"}
package/dist/dna/edit.js CHANGED
@@ -16,9 +16,12 @@ exports.applyDnaEditInText = applyDnaEditInText;
16
16
  *
17
17
  * The safety contract is `setDnaValueInText`'s, unchanged and strengthened: every candidate edit is
18
18
  * verified by re-parsing it and comparing the **whole document** against the intended object before it
19
- * is returned, and anything that cannot be done provably-minimally returns `undefined` so the caller
20
- * falls back to `dump()` rather than writing something subtly wrong. A mis-located edit therefore
21
- * cannot corrupt a file; at worst it costs the comments.
19
+ * is returned, and anything that cannot be done provably-minimally returns `undefined` rather than
20
+ * writing something subtly wrong. A mis-located edit therefore cannot corrupt a file. Since task-193
21
+ * (`bug-019`, `bug-126`) the caller no longer falls back to `dump()` on its own: it refuses the write
22
+ * unless `--force` authorizes the whole-file rewrite, and a forced rewrite is reported in a warning.
23
+ * Absent keys (with absent parents), block-scalar values and CRLF files are edited here, so that
24
+ * refusal is left to shapes such as a key under a non-empty flow mapping.
22
25
  *
23
26
  * Pure and deterministic (REQ-SYS-07): a function of `(text, edit, intended)` alone — no wall-clock, no
24
27
  * randomness, no filesystem, and the input text is never mutated.
@@ -134,7 +137,7 @@ function locate(lines, path) {
134
137
  }
135
138
  /**
136
139
  * Render a value as the single-line YAML token `js-yaml` itself would emit — which is what keeps this
137
- * editor's bytes identical to the whole-file `dump()` fallback's at the same position, including
140
+ * editor's bytes identical to the `--force`d whole-file `dump()`'s at the same position, including
138
141
  * defensive quoting (`'2'` stays a string, `'y'` is quoted because YAML 1.1 reads a bare `y` as a
139
142
  * boolean).
140
143
  *
@@ -221,7 +224,14 @@ function deepEqual(a, b) {
221
224
  return false;
222
225
  return leftKeys.every((key) => Object.prototype.hasOwnProperty.call(right, key) && deepEqual(left[key], right[key]));
223
226
  }
224
- /** Write a value at the mapping key the path ends on, inserting the key when the block does not carry it. */
227
+ /**
228
+ * Write a value at the mapping key the path ends on, inserting the key — and any of its parent keys the
229
+ * text does not carry — when it is absent ({@link insertMissingPath}).
230
+ *
231
+ * A key holding a block scalar (`>-`, `|`) is rewritten as a one-line key and its continuation lines
232
+ * are dropped: those lines ARE the old value, so removing them is the edit, not a loss (task-193,
233
+ * `bug-019`). An inline comment on the key line is kept, as for any other rewrite.
234
+ */
225
235
  function editSetScalar(lines, path, value) {
226
236
  const scalar = renderInline(value);
227
237
  const parentPath = path.slice(0, -1);
@@ -229,21 +239,62 @@ function editSetScalar(lines, path, value) {
229
239
  if (last === undefined || !('key' in last))
230
240
  return undefined;
231
241
  const parent = locate(lines, parentPath);
232
- if (parent === undefined)
242
+ const existing = parent === undefined ? undefined : findKey(lines, parent.region, parent.indent, last.key);
243
+ if (existing === undefined) {
244
+ return insertMissingPath(lines, path, (indent) => [`${' '.repeat(indent)}${last.key}: ${scalar}`]);
245
+ }
246
+ const region = blockRegion(lines, existing);
247
+ const currentValue = (0, set_1.valueOf)(existing.rest);
248
+ if (currentValue.startsWith('|') || currentValue.startsWith('>')) {
249
+ lines.splice(existing.line, Math.max(region.end, existing.line + 1) - existing.line, rewriteKeyLine(lines[existing.line], existing, scalar));
250
+ return lines;
251
+ }
252
+ // A value that continues past its own line (a nested block) has no one-line edit.
253
+ if (region.end > existing.line + 1)
233
254
  return undefined;
234
- const existing = findKey(lines, parent.region, parent.indent, last.key);
235
- if (existing !== undefined) {
236
- // A value that continues past its own line (a block scalar, a nested block) has no one-line edit.
237
- const currentValue = (0, set_1.valueOf)(existing.rest);
238
- if (currentValue.startsWith('|') || currentValue.startsWith('>'))
239
- return undefined;
240
- if (blockRegion(lines, existing).end > existing.line + 1)
255
+ lines[existing.line] = rewriteKeyLine(lines[existing.line], existing, scalar);
256
+ return lines;
257
+ }
258
+ /**
259
+ * Insert a key the text does not carry, together with every ancestor key it does not carry either
260
+ * (task-193, `bug-126`: the first `dna add team.agents` on a file with no `agents:`, or a
261
+ * `dna set project.name` on a file with no `project:`). The deepest ancestor the text DOES carry is the
262
+ * parent; each missing key is written on its own line, two columns deeper than the one before, at the
263
+ * end of the parent's content (before any trailing comment block, which introduces what comes next).
264
+ * `render` writes the last key's own line(s) at the indentation it is handed.
265
+ *
266
+ * Declines when a missing step is a sequence index (there is no entry to descend into), or when the
267
+ * parent key holds an inline value — a flow mapping `{ a: 1 }`, a plain scalar — under which no block
268
+ * line can be added. An empty flow mapping `{}` holds nothing to lose, so it is opened into a block
269
+ * (`paths: {}` becomes `paths:`) and the key inserted below it.
270
+ */
271
+ function insertMissingPath(lines, path, render) {
272
+ let depth = path.length - 1;
273
+ let parent = locate(lines, path.slice(0, depth));
274
+ while (parent === undefined) {
275
+ depth -= 1;
276
+ parent = locate(lines, path.slice(0, depth));
277
+ }
278
+ const missing = path.slice(depth);
279
+ if (!missing.every((step) => 'key' in step))
280
+ return undefined;
281
+ const key = parent.key;
282
+ if (key !== undefined) {
283
+ const currentValue = (0, set_1.valueOf)(key.rest);
284
+ if (currentValue === '{}') {
285
+ lines[key.line] = rewriteKeyLine(lines[key.line], key, '').replace(/: $/, ':');
286
+ }
287
+ else if (currentValue !== '') {
241
288
  return undefined;
242
- lines[existing.line] = rewriteKeyLine(lines[existing.line], existing, scalar);
243
- return lines;
289
+ }
244
290
  }
291
+ const keys = missing.map((step) => step.key);
292
+ const opened = keys.slice(0, -1).map((name, level) => `${' '.repeat(parent.indent + 2 * level)}${name}:`);
293
+ const tail = render(parent.indent + 2 * opened.length);
294
+ if (tail === undefined)
295
+ return undefined;
245
296
  // `lastContentLine` returns `region.start - 1` for an empty block, so the insert lands at its start.
246
- lines.splice(lastContentLine(lines, parent.region) + 1, 0, `${' '.repeat(parent.indent)}${last.key}: ${scalar}`);
297
+ lines.splice(lastContentLine(lines, parent.region) + 1, 0, ...opened, ...tail);
247
298
  return lines;
248
299
  }
249
300
  /** Drop the mapping key the path ends on, together with the block hanging below it. */
@@ -258,7 +309,18 @@ function editDeleteKey(lines, path) {
258
309
  /** Append items to the sequence the path ends on, in whichever form that sequence is written. */
259
310
  function editAppendItems(lines, path, items, intended) {
260
311
  const cursor = locate(lines, path);
261
- if (cursor?.key === undefined)
312
+ if (cursor === undefined) {
313
+ // The sequence is absent from the text (the first entry of `team.agents`, task-193 / `bug-126`):
314
+ // open it under its parent, with the new items as its first lines.
315
+ const last = path[path.length - 1];
316
+ if (last === undefined || !('key' in last))
317
+ return undefined;
318
+ return insertMissingPath(lines, path, (indent) => {
319
+ const rendered = renderItems(items, indent + 2);
320
+ return rendered === undefined ? undefined : [`${' '.repeat(indent)}${last.key}:`, ...rendered];
321
+ });
322
+ }
323
+ if (cursor.key === undefined)
262
324
  return undefined;
263
325
  const key = cursor.key;
264
326
  const currentValue = (0, set_1.valueOf)(key.rest);
@@ -374,25 +436,11 @@ function applyOne(lines, edit, intended) {
374
436
  }
375
437
  }
376
438
  }
377
- /**
378
- * The one shape the walker above cannot reach: a scalar whose PARENT key is itself absent from the
379
- * text, so there is no block to insert into (`project.name` in a file with no `project:` at all).
380
- * `setDnaValueInText` (`task-063`) already solves exactly that — it inserts the missing tail of a
381
- * mapping path, comments intact — so it is reused rather than re-implemented, for the mapping-only
382
- * paths it understands. Anything else still falls through to the caller's `dump()`.
383
- */
384
- function insertMissingScalarPath(text, edit) {
385
- if (edit.kind !== 'set-scalar' || typeof edit.value !== 'string')
386
- return undefined;
387
- if (!edit.path.every((step) => 'key' in step))
388
- return undefined;
389
- const keyPath = edit.path.map((step) => step.key).join('.');
390
- return (0, set_1.setDnaValueInText)(text, keyPath, edit.value);
391
- }
392
439
  /**
393
440
  * Apply `edit` to the RAW TEXT of a `dna.yaml`, editing as few lines as possible, and return the new
394
- * text — or `undefined`, deliberately and not as an error, when no provably-minimal edit exists, so the
395
- * caller falls back to the whole-file `dump()`.
441
+ * text — or `undefined`, deliberately and not as an error, when no provably-minimal edit exists. The
442
+ * caller then refuses the write, or rewrites the whole file when `--force` authorizes it and says that
443
+ * the comments were not kept (task-193, `runDnaMutation` in `src/core`).
396
444
  *
397
445
  * `intended` is the document the mutation produced (`applyDnaMutation`'s `dna`). It serves twice: an
398
446
  * inline flow sequence is re-rendered from it rather than patched token-by-token, and — the part that
@@ -401,10 +449,10 @@ function insertMissingScalarPath(text, edit) {
401
449
  * while key values are the contract; a mis-located edit fails the comparison and costs the comments,
402
450
  * never the content.
403
451
  *
404
- * Declines (returns `undefined`) when: the text is not one valid YAML document; a step of the path is
405
- * absent from the text; the target or a value it must rewrite spans more than its own line (a block
406
- * scalar, a nested block); a value has no single-line YAML form; or the result does not read back as
407
- * `intended`.
452
+ * Declines (returns `undefined`) when: the text is not one valid YAML document; an absent step of the
453
+ * path cannot be inserted (a sequence index, or a parent holding an inline value other than `{}`); the
454
+ * target spans more than its own line as a nested block (a block scalar is replaced, not declined); a
455
+ * value has no single-line YAML form; or the result does not read back as `intended`.
408
456
  */
409
457
  function applyDnaEditInText(text, edit, intended) {
410
458
  try {
@@ -413,10 +461,15 @@ function applyDnaEditInText(text, edit, intended) {
413
461
  catch {
414
462
  return undefined;
415
463
  }
416
- const edited = applyOne(text.split('\n'), edit, intended) ?? insertMissingScalarPath(text, edit);
464
+ // CRLF line endings (task-193, `bug-019`): the key-line pattern cannot span a `\r`, so a file whose
465
+ // every line ends in CRLF is edited in its LF form and written back with CRLF. A file mixing the two
466
+ // has no single ending to restore and is edited as it is, where its LF lines allow.
467
+ const crlf = text.includes('\r\n') && !text.replace(/\r\n/g, '').includes('\n');
468
+ const source = crlf ? text.replace(/\r\n/g, '\n') : text;
469
+ const edited = applyOne(source.split('\n'), edit, intended);
417
470
  if (edited === undefined)
418
471
  return undefined;
419
- const result = Array.isArray(edited) ? edited.join('\n') : edited;
472
+ const result = edited.join('\n');
420
473
  let parsed;
421
474
  try {
422
475
  parsed = (0, js_yaml_1.load)(result);
@@ -424,6 +477,8 @@ function applyDnaEditInText(text, edit, intended) {
424
477
  catch {
425
478
  return undefined;
426
479
  }
427
- return deepEqual(parsed, intended) ? result : undefined;
480
+ if (!deepEqual(parsed, intended))
481
+ return undefined;
482
+ return crlf ? result.replace(/\n/g, '\r\n') : result;
428
483
  }
429
484
  //# sourceMappingURL=edit.js.map