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
@@ -15,26 +15,88 @@ export declare function slugifyTitle(title: string): string;
15
15
  * default rather than writing an empty list).
16
16
  */
17
17
  export declare function parseTags(raw: string | undefined): string[] | undefined;
18
- /** Whether an `id_pattern` contains a `{n}`-family numeric token (e.g. `task-{n}-{slug}`) — i.e. it
19
- * needs a sequence counter resolved before {@link generateId} can render it. */
18
+ /** Whether an `id_pattern` contains a `{n}`-family numeric token (e.g. `task-{n}-{slug}`, `u-{n:1}`) —
19
+ * i.e. it needs a sequence counter resolved before {@link generateId} can render it. */
20
20
  export declare function hasNumericToken(idPattern: string): boolean;
21
21
  /**
22
- * The directory that holds every document of a type: the type's `path` pattern
23
- * (spec-001-memory-yaml-schema `MemoryTypeEntry.path`, e.g. `docs/memory/decision/{id}.md`) rendered
24
- * with a dummy `{id}` and reduced to its containing directory. The directory portion never depends on
25
- * the concrete id value, so this is well-defined before the id is generated (used by
26
- * {@link nextSequenceNumber} to count existing siblings). `values` fills any other path token —
27
- * `{release-line}`, `{scope}` — from `memory add --set` (task-110); `id` is always the dummy.
22
+ * The author date git would record for a commit made now at `root`, as git's internal
23
+ * `<seconds> <offset>` pair (`1790731800 -0200`): `GIT_AUTHOR_DATE` when it is set, in any format git
24
+ * accepts, otherwise the system clock — read ONCE, through `git var GIT_AUTHOR_IDENT` (task-163,
25
+ * `bug-158`). `memory add` builds `{date}` from it ({@link formatIdDate}) and records the add commit
26
+ * with this same author date (passed back as `@<seconds> <offset>`: git reads a bare pair as a
27
+ * timestamp only from 9 digits of seconds up), so the id and the commit cannot disagree, and a caller (a test, a
28
+ * replay) fixes the date the way it fixes any git author date.
29
+ *
30
+ * `identity` is passed to git as `GIT_AUTHOR_NAME`/`GIT_AUTHOR_EMAIL`: the identity was already
31
+ * resolved and checked (`requireGitIdentity`), and only the date part of git's answer is read.
32
+ *
33
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when git refuses (e.g. a `GIT_AUTHOR_DATE` it
34
+ * cannot parse) or answers in a shape that is not `… <seconds> <offset>`.
35
+ */
36
+ export declare function readAuthorDate(root: string, identity: {
37
+ readonly name: string;
38
+ readonly email: string;
39
+ }): string;
40
+ /**
41
+ * The `<seconds> <offset>` date that ends a git ident line (`Name <email> 1790731800 -0200`). Pure.
42
+ *
43
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when the line does not end with one.
44
+ */
45
+ export declare function identDate(ident: string): string;
46
+ /**
47
+ * `{date}`'s value (`spec-001`'s placeholder table): the UTC calendar date `YYYYMMDD` of a git
48
+ * `<seconds> <offset>` date ({@link readAuthorDate}). The offset does not move the instant, so
49
+ * `23:30 -0200` on the 29th is the 30th. Pure.
50
+ */
51
+ export declare function formatIdDate(gitDate: string): string;
52
+ /**
53
+ * The highest `{n}` value among `paths` (repository-relative, `/`-separated) that the type's `path`
54
+ * pattern and materialized `id_pattern` match, or `0` when none does (`spec-001` "Counter algorithm",
55
+ * `dl-101` §2 (a)). The **highest**, not a count, so a gap never reissues a number (`bug-087`); and a
56
+ * maximum, so the answer is independent of the order `paths` arrive in (REQ-SYS-07).
28
57
  */
29
- export declare function resolveTypeDirectory(root: string, pathPattern: string, values?: Readonly<Record<string, string>>): string;
58
+ export declare function highestSequenceNumber(paths: Iterable<string>, pathPattern: string, idPattern: string): number;
30
59
  /**
31
- * The next sequence number for a `{n}`-token id: `1 +` the count of existing files in `dir` whose
32
- * basename (sans `.md`) matches `idPattern` (`patternToRegExp`, task-002). Deterministic — a count is
33
- * independent of directory-entry order (REQ-SYS-07) — and confined to this type's own directory, so
34
- * unrelated files never perturb it. Returns `1` when the directory does not yet exist.
60
+ * The commits of the refs a number or a WIP slot can be taken on (`dl-101` §2 (a)): the tip of every
61
+ * local branch (`refs/heads/*`) and remote-tracking ref (`refs/remotes/*`), and `HEAD` (a detached
62
+ * `HEAD` is on no branch; an unborn one adds nothing), as full shas, de-duplicated and sorted
63
+ * (REQ-SYS-07). No network: the remote-tracking refs are what the last `git fetch` left (`dl-101`
64
+ * §1.1).
65
+ *
66
+ * The one listing of "every ref" both wider reads use — `memory add`'s `{n}` counter
67
+ * ({@link nextSequenceNumber}) and the WIP-limit holder count (`requireWipSlot`, `dl-156` Q1 (a),
68
+ * task-274) — so the two cannot disagree about which refs exist (`command-baseline`, *Declared
69
+ * baselines*).
70
+ *
71
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when a git read fails.
35
72
  */
36
- export declare function nextSequenceNumber(dir: string, idPattern: string): number;
37
- /** The fields `memory.add` pins on the freshly-created draft document (P1.3 memory.add / spec-010). */
73
+ export declare function refBaselineCommits(root: string): string[];
74
+ /**
75
+ * The next sequence number for a `{n}`-token id: `1 +` the highest number any baseline holds for this
76
+ * type — every local branch, remote-tracking ref, `HEAD`, the index and the untracked working-tree
77
+ * files ({@link sequenceCandidatePaths}) — over every folder the type's `path` can resolve to
78
+ * ({@link highestSequenceNumber}). `1` when nothing matches. Ratified `dl-101` §2 (a) (task-128,
79
+ * `bug-087`, `bug-162`); `spec-001` "Counter algorithm".
80
+ *
81
+ * @param root - The repository root.
82
+ * @param pathPattern - The type's committed `path` pattern, e.g. `docs/04_memory/{release}/{id}.md`.
83
+ * @param idPattern - The type's `id_pattern` with its field tokens already materialized.
84
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when a git read fails.
85
+ */
86
+ export declare function nextSequenceNumber(root: string, pathPattern: string, idPattern: string): number;
87
+ /**
88
+ * Which ids of a type with `path` pattern `pathPattern` exist on any baseline a number can be taken on —
89
+ * the ones {@link nextSequenceNumber} reads (every local branch, remote-tracking ref, `HEAD`, the index and
90
+ * the untracked working-tree files; `dl-101` §2 (a)) — in any folder the pattern resolves to: every token
91
+ * other than `{id}` matches one or more path segments. The paths are listed once; the returned predicate
92
+ * answers for any id. `workflow start` asks it of a derived or `--set phase=` plan id (`spec-017` §7.1,
93
+ * task-217): ids are unique per type, so a plan held by another branch, or under another `{scope}`,
94
+ * occupies its id.
95
+ *
96
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when a git read fails.
97
+ */
98
+ export declare function idOccupancy(root: string, pathPattern: string): (id: string) => boolean;
99
+ /** The fields `memory.add` pins on the freshly-created document (P1.3 memory.add / spec-010). */
38
100
  export interface AddDocumentFields {
39
101
  readonly id: string;
40
102
  readonly title: string;
@@ -46,16 +108,27 @@ export interface AddDocumentFields {
46
108
  * or appended when the scaffold has none.
47
109
  */
48
110
  readonly fields?: readonly (readonly [string, string])[];
111
+ /**
112
+ * The initial `status`: the head of the type's machine (`spec-001`; `bug-214`, task-180), which
113
+ * `memory add` resolves from the committed `memory.yaml`. Defaults to `draft`, the head of the
114
+ * built-in default machine.
115
+ */
116
+ readonly status?: string;
49
117
  }
50
118
  /**
51
119
  * Copy a type's `template.file` scaffold verbatim and fill only the frontmatter skeleton `memory.add`
52
120
  * pins (P1.3; spec-010-memory-frontmatter-schema): the generated `id`, the `--title`, the
53
- * initial `status: draft`, when `--tags` was supplied the `tags` flow sequence, and the `--set` fields
121
+ * initial `status` (the head of the type's machine, {@link AddDocumentFields.status}), when `--tags`
122
+ * was supplied the `tags` flow sequence, and the `--set` fields
54
123
  * {@link AddDocumentFields.fields} carries (task-110). Every other
55
124
  * field (notably `type` and `tmpl_version`, spec-010: not touched by add) and the whole body are left
56
125
  * exactly as the scaffold had them. `title`/`tags` are JSON-quoted (valid YAML double-quoted scalars /
57
126
  * flow sequences), so an arbitrary title with spaces or colons is written safely.
58
127
  *
128
+ * Each field is set through `./frontmatter-edit`'s shared setter, the one the transition verbs use
129
+ * (task-163, `bug-033`): only a TOP-LEVEL key is matched, so a nested key of the same name is never
130
+ * edited, and an edited line keeps the scaffold's inline `# comment`.
131
+ *
59
132
  * @throws when the scaffold has no frontmatter block (a malformed template — a config error surfaced
60
133
  * as a thrown `Error` the core op maps to a `CoreError`).
61
134
  */
@@ -85,17 +158,30 @@ export declare function parseSetOptions(raw: string | readonly string[] | undefi
85
158
  */
86
159
  export declare function unknownSetNames(values: Readonly<Record<string, string>>, idPattern: string, pathPattern: string): string[];
87
160
  /**
88
- * Materialize an `id_pattern`'s frontmatter and context tokens (`{kind}`, `{version}`, `{workflow}`,
89
- * …) from the `--set` values, leaving `{slug}`, the `{n}` family and the not-yet-implemented
90
- * `{date}`/`{author}` in place — `spec-001`'s fixed expansion order (`{date}` → `{author}` → field and
91
- * context tokens → `{slug}` → `{n}`), so the `{n}` counter regexp built from the result sees a
92
- * fully-materialized prefix (task-110).
161
+ * The values of the tokens `memory add` sources itself rather than from `--set` (`spec-001`'s
162
+ * placeholder table, task-163): `{date}` and `{author}`. Each is needed only when the pattern has the
163
+ * token, and is read once per add by the caller.
164
+ */
165
+ export interface IdTokenSources {
166
+ /** The add commit's author date as git's `<seconds> <offset>` ({@link readAuthorDate}). */
167
+ readonly date?: string;
168
+ /** The git author name the add commit records (`requireGitIdentity`), before slugging. */
169
+ readonly authorName?: string;
170
+ }
171
+ /**
172
+ * Materialize an `id_pattern`'s `{date}`, `{author}`, frontmatter and context tokens (`{kind}`,
173
+ * `{version}`, `{workflow}`, …), leaving `{slug}` and the `{n}` family in place — `spec-001`'s fixed
174
+ * expansion order (`{date}` → `{author}` → field and context tokens → `{slug}` → `{n}`), so the
175
+ * `{n}` counter regexp built from the result sees a fully-materialized prefix (task-110). `{date}` is
176
+ * the UTC `YYYYMMDD` of `sources.date` ({@link formatIdDate}); `{author}` the slug of
177
+ * `sources.authorName` ({@link slugifyTitle}) — task-163, `bug-158`.
93
178
  *
94
179
  * @throws {@link ValidationError} naming every field token with no value
95
- * (`missing value for token {<name>}: give it with --set <name>=<value>`) and every value outside
96
- * the ID character class, in pattern order — the same `E_INVALID_ID` code `generateId` raises.
180
+ * (`missing value for token {<name>}: give it with --set <name>=<value>`), an `{author}` whose
181
+ * name slugs to nothing, and every value outside the ID character class, in pattern order — the
182
+ * same `E_INVALID_ID` code `generateId` raises.
97
183
  */
98
- export declare function expandFieldTokens(idPattern: string, values: Readonly<Record<string, string>>): string;
184
+ export declare function expandFieldTokens(idPattern: string, values: Readonly<Record<string, string>>, sources?: IdTokenSources): string;
99
185
  /**
100
186
  * The `--set` values `memory add` writes into the new document's frontmatter, as `[name, value]`
101
187
  * pairs sorted by name (REQ-SYS-07). A field token is always written, so the id and the field cannot
@@ -1 +1 @@
1
- {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/memory/add.ts"],"names":[],"mappings":"AAoBA;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAOvE;AAED;gFACgF;AAChF,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAClC,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EACnB,MAAM,GAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAM,GAC5C,MAAM,CAER;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQzE;AAED,uGAAuG;AACvG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;CAC1D;AAsBD;;;;;;;;;;;GAWG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAiBrF;AAkBD,iGAAiG;AACjG,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,gBAAgB,CA4B7F;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACxC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,CAIV;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,iBAAiB,CAAC,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,MAAM,CAiBrG;AAMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAQ5G"}
1
+ {"version":3,"file":"add.d.ts","sourceRoot":"","sources":["../../src/memory/add.ts"],"names":[],"mappings":"AAqBA;;;;;;;;;GASG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAOlD;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,GAAG,SAAS,CAOvE;AAED;wFACwF;AACxF,wBAAgB,eAAe,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAK1D;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,QAAQ,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAAG,MAAM,CAKhH;AAED;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAM/C;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAGpD;AAwBD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAQ7G;AA+BD;;;;;;;;;;;;;GAaG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,EAAE,CAOzD;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,MAAM,CAG/F;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CActF;AAED,iGAAiG;AACjG,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAClC;;;;;OAKG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EAAE,CAAC;IACzD;;;;OAIG;IACH,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAQD;;;;;;;;;;;;;;;;GAgBG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAmBrF;AA+CD,iGAAiG;AACjG,MAAM,MAAM,gBAAgB,GACxB;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,GACxE;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAErD;;;;;;;;GAQG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,MAAM,EAAE,GAAG,SAAS,GAAG,gBAAgB,CA2B7F;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAC7B,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACxC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,MAAM,GAClB,MAAM,EAAE,CAIV;AAED;;;;GAIG;AACH,MAAM,WAAW,cAAc;IAC7B,2FAA2F;IAC3F,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,0FAA0F;IAC1F,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;CAC9B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,SAAS,EAAE,MAAM,EACjB,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,EACxC,OAAO,GAAE,cAAmB,GAC3B,MAAM,CAwBR;AAMD;;;;;;GAMG;AACH,wBAAgB,aAAa,CAAC,QAAQ,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,EAAE,CAS5G"}
@@ -3,8 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.slugifyTitle = slugifyTitle;
4
4
  exports.parseTags = parseTags;
5
5
  exports.hasNumericToken = hasNumericToken;
6
- exports.resolveTypeDirectory = resolveTypeDirectory;
6
+ exports.readAuthorDate = readAuthorDate;
7
+ exports.identDate = identDate;
8
+ exports.formatIdDate = formatIdDate;
9
+ exports.highestSequenceNumber = highestSequenceNumber;
10
+ exports.refBaselineCommits = refBaselineCommits;
7
11
  exports.nextSequenceNumber = nextSequenceNumber;
12
+ exports.idOccupancy = idOccupancy;
8
13
  exports.renderAddDocument = renderAddDocument;
9
14
  exports.parseSetOptions = parseSetOptions;
10
15
  exports.unknownSetNames = unknownSetNames;
@@ -17,14 +22,16 @@ exports.writtenFields = writtenFields;
17
22
  * thin composition and the id/slug/document-render logic is independently unit-testable.
18
23
  *
19
24
  * Every function here is deterministic (REQ-SYS-07): a slug is a pure function of the title, the
20
- * rendered document a pure function of `(scaffold, id, title, tags)`, and the sequence counter a pure
21
- * function of the committed on-disk state (a stable count, order-independent) — no wall-clock, no
22
- * randomness, no unordered iteration in a value that reaches the produced id or document.
25
+ * rendered document a pure function of `(scaffold, id, title, tags)`, and the sequence counter a
26
+ * maximum over the paths every ref and the working tree hold (order-independent, task-128) — no
27
+ * randomness and no unordered iteration in a value that reaches the produced id or document. The one
28
+ * time read is `{date}`'s ({@link readAuthorDate}, task-163): a write path, not a context-building
29
+ * one, taken once per add from the author date git records for the add commit, so a caller fixes it
30
+ * with `GIT_AUTHOR_DATE` and the id never disagrees with its own commit.
23
31
  */
24
- const fs_1 = require("fs");
25
- const path_1 = require("path");
26
32
  const storage_1 = require("../storage");
27
33
  const validation_1 = require("../validation");
34
+ const frontmatter_edit_1 = require("./frontmatter-edit");
28
35
  const TOKEN_RE = /\{([^{}]+)\}/g;
29
36
  /**
30
37
  * Turn a human `--title` into a single, valid `[a-z0-9-.]` ID slug piece (spec-009-validation-strategy
@@ -56,70 +63,205 @@ function parseTags(raw) {
56
63
  .filter((tag) => tag.length > 0);
57
64
  return tags.length > 0 ? tags : undefined;
58
65
  }
59
- /** Whether an `id_pattern` contains a `{n}`-family numeric token (e.g. `task-{n}-{slug}`) — i.e. it
60
- * needs a sequence counter resolved before {@link generateId} can render it. */
66
+ /** Whether an `id_pattern` contains a `{n}`-family numeric token (e.g. `task-{n}-{slug}`, `u-{n:1}`) —
67
+ * i.e. it needs a sequence counter resolved before {@link generateId} can render it. */
61
68
  function hasNumericToken(idPattern) {
62
69
  for (const match of idPattern.matchAll(TOKEN_RE)) {
63
- if (/^n+$/.test(match[1] ?? ''))
70
+ if ((0, validation_1.isNumericToken)(match[1] ?? ''))
64
71
  return true;
65
72
  }
66
73
  return false;
67
74
  }
68
75
  /**
69
- * The directory that holds every document of a type: the type's `path` pattern
70
- * (spec-001-memory-yaml-schema `MemoryTypeEntry.path`, e.g. `docs/memory/decision/{id}.md`) rendered
71
- * with a dummy `{id}` and reduced to its containing directory. The directory portion never depends on
72
- * the concrete id value, so this is well-defined before the id is generated (used by
73
- * {@link nextSequenceNumber} to count existing siblings). `values` fills any other path token —
74
- * `{release-line}`, `{scope}` — from `memory add --set` (task-110); `id` is always the dummy.
76
+ * The author date git would record for a commit made now at `root`, as git's internal
77
+ * `<seconds> <offset>` pair (`1790731800 -0200`): `GIT_AUTHOR_DATE` when it is set, in any format git
78
+ * accepts, otherwise the system clock — read ONCE, through `git var GIT_AUTHOR_IDENT` (task-163,
79
+ * `bug-158`). `memory add` builds `{date}` from it ({@link formatIdDate}) and records the add commit
80
+ * with this same author date (passed back as `@<seconds> <offset>`: git reads a bare pair as a
81
+ * timestamp only from 9 digits of seconds up), so the id and the commit cannot disagree, and a caller (a test, a
82
+ * replay) fixes the date the way it fixes any git author date.
83
+ *
84
+ * `identity` is passed to git as `GIT_AUTHOR_NAME`/`GIT_AUTHOR_EMAIL`: the identity was already
85
+ * resolved and checked (`requireGitIdentity`), and only the date part of git's answer is read.
86
+ *
87
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when git refuses (e.g. a `GIT_AUTHOR_DATE` it
88
+ * cannot parse) or answers in a shape that is not `… <seconds> <offset>`.
75
89
  */
76
- function resolveTypeDirectory(root, pathPattern, values = {}) {
77
- return (0, path_1.dirname)((0, path_1.join)(root, (0, storage_1.renderMemoryPath)(pathPattern, { ...values, id: '__id__' })));
90
+ function readAuthorDate(root, identity) {
91
+ const answer = (0, storage_1.runGitRead)(root, ['var', 'GIT_AUTHOR_IDENT'], {
92
+ env: { GIT_AUTHOR_NAME: identity.name, GIT_AUTHOR_EMAIL: identity.email },
93
+ }).stdout;
94
+ return identDate(answer);
78
95
  }
79
96
  /**
80
- * The next sequence number for a `{n}`-token id: `1 +` the count of existing files in `dir` whose
81
- * basename (sans `.md`) matches `idPattern` (`patternToRegExp`, task-002). Deterministic — a count is
82
- * independent of directory-entry order (REQ-SYS-07) — and confined to this type's own directory, so
83
- * unrelated files never perturb it. Returns `1` when the directory does not yet exist.
97
+ * The `<seconds> <offset>` date that ends a git ident line (`Name <email> 1790731800 -0200`). Pure.
98
+ *
99
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when the line does not end with one.
84
100
  */
85
- function nextSequenceNumber(dir, idPattern) {
86
- if (!(0, fs_1.existsSync)(dir) || !(0, fs_1.statSync)(dir).isDirectory())
87
- return 1;
88
- const re = (0, validation_1.patternToRegExp)(idPattern);
89
- let count = 0;
90
- for (const entry of (0, fs_1.readdirSync)(dir).sort()) {
91
- if (entry.endsWith('.md') && re.test(entry.slice(0, -'.md'.length)))
92
- count += 1;
101
+ function identDate(ident) {
102
+ const date = /> (-?[0-9]+ [+-][0-9]{4})$/.exec(ident.trim())?.[1];
103
+ if (date === undefined) {
104
+ throw new storage_1.StorageError(storage_1.E_GIT_READ_FAILED, `git var GIT_AUTHOR_IDENT gave no author date: "${ident.trim()}"`);
93
105
  }
94
- return count + 1;
106
+ return date;
95
107
  }
96
108
  /**
97
- * Escape a literal string for safe insertion into a `RegExp` source (a frontmatter key here). */
98
- function escapeRegExp(value) {
99
- return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
109
+ * `{date}`'s value (`spec-001`'s placeholder table): the UTC calendar date `YYYYMMDD` of a git
110
+ * `<seconds> <offset>` date ({@link readAuthorDate}). The offset does not move the instant, so
111
+ * `23:30 -0200` on the 29th is the 30th. Pure.
112
+ */
113
+ function formatIdDate(gitDate) {
114
+ const seconds = Number.parseInt(gitDate, 10);
115
+ return new Date(seconds * 1000).toISOString().slice(0, 10).replace(/-/g, '');
116
+ }
117
+ /** A non-`{id}` `path` token as the counter matches it: one or more path segments (`dl-101` (a)). */
118
+ const PATH_TOKEN_SOURCE = '[^/]+(?:/[^/]+)*';
119
+ /**
120
+ * The RegExp a repository-relative path of this type matches, with the `{n}` value as group 1: the
121
+ * `path` pattern with `{id}` replaced by the (materialized) `id_pattern` and **every other token a
122
+ * wildcard**, whatever value this add gives it — so a `task`'s counter spans every
123
+ * `docs/04_memory/{release}/` folder, not only the one being added to (`bug-162`).
124
+ */
125
+ function sequencePathRegExp(pathPattern, idPattern) {
126
+ const idSource = (0, validation_1.patternToSource)(idPattern, { captureNumeric: true });
127
+ let source = '^';
128
+ let last = 0;
129
+ for (const match of pathPattern.matchAll(TOKEN_RE)) {
130
+ const index = match.index;
131
+ source += escapeRegExp(pathPattern.slice(last, index));
132
+ source += match[1] === 'id' ? `(?:${idSource})` : PATH_TOKEN_SOURCE;
133
+ last = index + match[0].length;
134
+ }
135
+ return new RegExp(`${source}${escapeRegExp(pathPattern.slice(last))}$`);
100
136
  }
101
137
  /**
102
- * Set one frontmatter field on the raw frontmatter text, line-based: replace the value on the existing
103
- * `^<indent>key:` line if present (preserving the scaffold's ordering, comments and other fields
104
- * verbatim — the P1.3 memory.add contract copies the scaffold verbatim), otherwise append the field. `valueYaml`
105
- * is the already-serialized YAML scalar/flow value (e.g. a JSON-quoted string, a flow sequence).
138
+ * The highest `{n}` value among `paths` (repository-relative, `/`-separated) that the type's `path`
139
+ * pattern and materialized `id_pattern` match, or `0` when none does (`spec-001` "Counter algorithm",
140
+ * `dl-101` §2 (a)). The **highest**, not a count, so a gap never reissues a number (`bug-087`); and a
141
+ * maximum, so the answer is independent of the order `paths` arrive in (REQ-SYS-07).
106
142
  */
107
- function setFrontmatterField(frontmatter, key, valueYaml) {
108
- const re = new RegExp(`^([ \\t]*)${escapeRegExp(key)}:.*$`, 'm');
109
- if (re.test(frontmatter)) {
110
- return frontmatter.replace(re, (_match, indent) => `${indent}${key}: ${valueYaml}`);
143
+ function highestSequenceNumber(paths, pathPattern, idPattern) {
144
+ const re = sequencePathRegExp(pathPattern, idPattern);
145
+ let highest = 0;
146
+ for (const path of paths) {
147
+ const digits = re.exec(path)?.[1];
148
+ if (digits !== undefined)
149
+ highest = Math.max(highest, Number.parseInt(digits, 10));
111
150
  }
112
- return `${frontmatter}\n${key}: ${valueYaml}`;
151
+ return highest;
152
+ }
153
+ /** The literal directory a `path` pattern starts with (up to its last `/` before any token), or `''`. */
154
+ function literalPrefix(pathPattern) {
155
+ const head = pathPattern.split('{', 1)[0];
156
+ return head.slice(0, head.lastIndexOf('/') + 1);
157
+ }
158
+ /**
159
+ * Every repository-relative path under `prefix` that any baseline a number can be taken on holds —
160
+ * `command-baseline`'s declared baseline for `memory add`'s counter (`dl-101` §2 (a), `dl-080`):
161
+ *
162
+ * - the tree of every local branch (`refs/heads/*`) and remote-tracking ref (`refs/remotes/*`), and
163
+ * of `HEAD` (a detached `HEAD` is on no branch);
164
+ * - the working tree as git sees it: the index and the untracked, non-ignored files.
165
+ *
166
+ * No network: the remote-tracking refs are what the last `git fetch` left (`dl-101` §1.1). Commits are
167
+ * de-duplicated and visited in sorted order, and the result is sorted (REQ-SYS-07).
168
+ */
169
+ function sequenceCandidatePaths(root, prefix) {
170
+ const pathspec = prefix.length === 0 ? [] : ['--', prefix];
171
+ const paths = new Set();
172
+ const worktree = (0, storage_1.runGitRead)(root, ['ls-files', '-z', '--cached', '--others', '--exclude-standard', ...pathspec]);
173
+ for (const path of worktree.stdout.split('\0'))
174
+ if (path.length > 0)
175
+ paths.add(path);
176
+ // One batched read for every commit, not one `git ls-tree` each (`bug-178`, task-142): the number of
177
+ // git processes no longer grows with the number of branches and remote-tracking refs.
178
+ for (const path of (0, storage_1.listPathsAtRevs)(root, refBaselineCommits(root), prefix))
179
+ paths.add(path);
180
+ return [...paths].sort();
181
+ }
182
+ /**
183
+ * The commits of the refs a number or a WIP slot can be taken on (`dl-101` §2 (a)): the tip of every
184
+ * local branch (`refs/heads/*`) and remote-tracking ref (`refs/remotes/*`), and `HEAD` (a detached
185
+ * `HEAD` is on no branch; an unborn one adds nothing), as full shas, de-duplicated and sorted
186
+ * (REQ-SYS-07). No network: the remote-tracking refs are what the last `git fetch` left (`dl-101`
187
+ * §1.1).
188
+ *
189
+ * The one listing of "every ref" both wider reads use — `memory add`'s `{n}` counter
190
+ * ({@link nextSequenceNumber}) and the WIP-limit holder count (`requireWipSlot`, `dl-156` Q1 (a),
191
+ * task-274) — so the two cannot disagree about which refs exist (`command-baseline`, *Declared
192
+ * baselines*).
193
+ *
194
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when a git read fails.
195
+ */
196
+ function refBaselineCommits(root) {
197
+ const refs = (0, storage_1.runGitRead)(root, ['for-each-ref', '--format=%(objectname)', 'refs/heads', 'refs/remotes']);
198
+ // `--verify --quiet` exits 1, printing nothing, on an unborn `HEAD`: an answer, not a failure.
199
+ const head = (0, storage_1.runGitRead)(root, ['rev-parse', '--verify', '--quiet', 'HEAD^{commit}'], { accepted: [0, 1] });
200
+ const commits = new Set(`${refs.stdout}\n${head.stdout}`.split('\n').map((sha) => sha.trim()));
201
+ commits.delete('');
202
+ return [...commits].sort();
203
+ }
204
+ /**
205
+ * The next sequence number for a `{n}`-token id: `1 +` the highest number any baseline holds for this
206
+ * type — every local branch, remote-tracking ref, `HEAD`, the index and the untracked working-tree
207
+ * files ({@link sequenceCandidatePaths}) — over every folder the type's `path` can resolve to
208
+ * ({@link highestSequenceNumber}). `1` when nothing matches. Ratified `dl-101` §2 (a) (task-128,
209
+ * `bug-087`, `bug-162`); `spec-001` "Counter algorithm".
210
+ *
211
+ * @param root - The repository root.
212
+ * @param pathPattern - The type's committed `path` pattern, e.g. `docs/04_memory/{release}/{id}.md`.
213
+ * @param idPattern - The type's `id_pattern` with its field tokens already materialized.
214
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when a git read fails.
215
+ */
216
+ function nextSequenceNumber(root, pathPattern, idPattern) {
217
+ const prefix = literalPrefix(pathPattern);
218
+ return highestSequenceNumber(sequenceCandidatePaths(root, prefix), pathPattern, idPattern) + 1;
219
+ }
220
+ /**
221
+ * Which ids of a type with `path` pattern `pathPattern` exist on any baseline a number can be taken on —
222
+ * the ones {@link nextSequenceNumber} reads (every local branch, remote-tracking ref, `HEAD`, the index and
223
+ * the untracked working-tree files; `dl-101` §2 (a)) — in any folder the pattern resolves to: every token
224
+ * other than `{id}` matches one or more path segments. The paths are listed once; the returned predicate
225
+ * answers for any id. `workflow start` asks it of a derived or `--set phase=` plan id (`spec-017` §7.1,
226
+ * task-217): ids are unique per type, so a plan held by another branch, or under another `{scope}`,
227
+ * occupies its id.
228
+ *
229
+ * @throws {@link StorageError} `E_GIT_READ_FAILED` when a git read fails.
230
+ */
231
+ function idOccupancy(root, pathPattern) {
232
+ const paths = sequenceCandidatePaths(root, literalPrefix(pathPattern));
233
+ return (id) => {
234
+ let source = '^';
235
+ let last = 0;
236
+ for (const match of pathPattern.matchAll(TOKEN_RE)) {
237
+ const index = match.index;
238
+ source += escapeRegExp(pathPattern.slice(last, index));
239
+ source += match[1] === 'id' ? escapeRegExp(id) : PATH_TOKEN_SOURCE;
240
+ last = index + match[0].length;
241
+ }
242
+ const re = new RegExp(`${source}${escapeRegExp(pathPattern.slice(last))}$`);
243
+ return paths.some((path) => re.test(path));
244
+ };
245
+ }
246
+ /**
247
+ * Escape a literal string for safe insertion into a `RegExp` source (a frontmatter key here). */
248
+ function escapeRegExp(value) {
249
+ return value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
113
250
  }
114
251
  /**
115
252
  * Copy a type's `template.file` scaffold verbatim and fill only the frontmatter skeleton `memory.add`
116
253
  * pins (P1.3; spec-010-memory-frontmatter-schema): the generated `id`, the `--title`, the
117
- * initial `status: draft`, when `--tags` was supplied the `tags` flow sequence, and the `--set` fields
254
+ * initial `status` (the head of the type's machine, {@link AddDocumentFields.status}), when `--tags`
255
+ * was supplied the `tags` flow sequence, and the `--set` fields
118
256
  * {@link AddDocumentFields.fields} carries (task-110). Every other
119
257
  * field (notably `type` and `tmpl_version`, spec-010: not touched by add) and the whole body are left
120
258
  * exactly as the scaffold had them. `title`/`tags` are JSON-quoted (valid YAML double-quoted scalars /
121
259
  * flow sequences), so an arbitrary title with spaces or colons is written safely.
122
260
  *
261
+ * Each field is set through `./frontmatter-edit`'s shared setter, the one the transition verbs use
262
+ * (task-163, `bug-033`): only a TOP-LEVEL key is matched, so a nested key of the same name is never
263
+ * edited, and an edited line keeps the scaffold's inline `# comment`.
264
+ *
123
265
  * @throws when the scaffold has no frontmatter block (a malformed template — a config error surfaced
124
266
  * as a thrown `Error` the core op maps to a `CoreError`).
125
267
  */
@@ -128,18 +270,20 @@ function renderAddDocument(scaffold, fields) {
128
270
  if (frontmatter === null) {
129
271
  throw new Error('memory template scaffold has no frontmatter block');
130
272
  }
131
- let fm = frontmatter;
132
- fm = setFrontmatterField(fm, 'id', fields.id);
133
- fm = setFrontmatterField(fm, 'title', JSON.stringify(fields.title));
134
- fm = setFrontmatterField(fm, 'status', 'draft');
273
+ // Rebuilt as `memory add` always wrote it (a `---` line, the frontmatter, a `---` line, the body),
274
+ // then edited in place by the shared setter.
275
+ let document = `---\n${frontmatter}\n---\n${body}`;
276
+ document = (0, frontmatter_edit_1.setFrontmatterEntry)(document, 'id', fields.id);
277
+ document = (0, frontmatter_edit_1.setFrontmatterEntry)(document, 'title', JSON.stringify(fields.title));
278
+ document = (0, frontmatter_edit_1.setFrontmatterEntry)(document, 'status', fields.status ?? 'draft');
135
279
  if (fields.tags !== undefined) {
136
280
  const flow = `[${fields.tags.map((tag) => JSON.stringify(tag)).join(',')}]`;
137
- fm = setFrontmatterField(fm, 'tags', flow);
281
+ document = (0, frontmatter_edit_1.setFrontmatterEntry)(document, 'tags', flow);
138
282
  }
139
283
  for (const [name, value] of fields.fields ?? []) {
140
- fm = setFrontmatterField(fm, name, JSON.stringify(value));
284
+ document = (0, frontmatter_edit_1.setFrontmatterEntry)(document, name, JSON.stringify(value));
141
285
  }
142
- return `---\n${fm}\n---\n${body}`;
286
+ return document;
143
287
  }
144
288
  /**
145
289
  * Names `memory add --set` refuses (`spec-008-cli-grammar` §10): the fields `memory add` fills itself
@@ -147,6 +291,19 @@ function renderAddDocument(scaffold, fields) {
147
291
  * their own (`n`, `slug`, `date`, `author` — `spec-001`'s placeholder table).
148
292
  */
149
293
  const RESERVED_SET_NAMES = new Set(['id', 'type', 'status', 'title', 'tags', 'n', 'slug', 'date', 'author']);
294
+ /**
295
+ * The refusal of a reserved `--set` name, saying where its value comes from (`spec-008` §10). `date`
296
+ * and `author` name their source, which is not an option of `memory add` (task-163, `bug-158`: the
297
+ * generic sentence was false while nothing filled them, and unhelpful once something did).
298
+ */
299
+ function reservedSetMessage(name) {
300
+ const prefix = `invalid flag value: --set cannot set "${name}": memory add fills`;
301
+ if (name === 'date')
302
+ return `${prefix} {date} from the add commit's author date (GIT_AUTHOR_DATE, or the clock)`;
303
+ if (name === 'author')
304
+ return `${prefix} {author} from the git author name`;
305
+ return `${prefix} it itself or through its own option`;
306
+ }
150
307
  /** A `--set` field name: `[a-z][a-z0-9_-]*` — the same shape `idPatternIssues` accepts for a token. */
151
308
  const SET_NAME_RE = /^[a-z][a-z0-9_-]*$/;
152
309
  /**
@@ -154,6 +311,24 @@ const SET_NAME_RE = /^[a-z][a-z0-9_-]*$/;
154
311
  * written into the document only where its template declares a field of that name.
155
312
  */
156
313
  const CONTEXT_TOKENS = new Set(['workflow', 'phase', 'scope']);
314
+ /**
315
+ * The spelling refusal of a `--set` value read as a path (task-281, `bug-325`; `spec-008` §10), or `null`.
316
+ * A token value may be substituted into the type's `path` pattern, so it must be a relative path whose
317
+ * segments (split on `/` and `\`) are neither empty nor `.` / `..` — first match wins: absolute, empty
318
+ * segment, dot segment. Applied to every `--set` value, because which names are path tokens is known only
319
+ * from the committed `memory.yaml`, and spelling is decided before anything is read (exit 2).
320
+ */
321
+ function pathSpellingRefusal(name, value) {
322
+ if (/^[/\\]/.test(value) || /^[A-Za-z]:/.test(value))
323
+ return `invalid flag value: --set ${name} must be a relative path, got "${value}"`;
324
+ const segments = value.split(/[/\\]/);
325
+ if (segments.includes(''))
326
+ return `invalid flag value: --set ${name} holds an empty path segment: "${value}"`;
327
+ if (segments.some((segment) => segment === '.' || segment === '..')) {
328
+ return `invalid flag value: --set ${name} holds a '.' or '..' path segment: "${value}"`;
329
+ }
330
+ return null;
331
+ }
157
332
  /**
158
333
  * Parse `memory add`'s repeatable `--set <name>=<value>` occurrences (`spec-008-cli-grammar` §10,
159
334
  * task-110). The CLI hands every occurrence as a string array; a single string is one occurrence;
@@ -177,14 +352,14 @@ function parseSetOptions(raw) {
177
352
  return { ok: false, message: `invalid flag value: --set name "${name}" is not a field name ([a-z][a-z0-9_-]*)` };
178
353
  }
179
354
  if (RESERVED_SET_NAMES.has(name)) {
180
- return {
181
- ok: false,
182
- message: `invalid flag value: --set cannot set "${name}": memory add fills it itself or through its own option`,
183
- };
355
+ return { ok: false, message: reservedSetMessage(name) };
184
356
  }
185
357
  if (value.trim().length === 0) {
186
358
  return { ok: false, message: `invalid flag value: --set ${name} must not be blank` };
187
359
  }
360
+ const spelling = pathSpellingRefusal(name, value);
361
+ if (spelling !== null)
362
+ return { ok: false, message: spelling };
188
363
  if (Object.prototype.hasOwnProperty.call(values, name)) {
189
364
  return { ok: false, message: `invalid flag value: --set ${name} given more than once` };
190
365
  }
@@ -203,20 +378,31 @@ function unknownSetNames(values, idPattern, pathPattern) {
203
378
  return Object.keys(values).filter((name) => !tokens.has(name));
204
379
  }
205
380
  /**
206
- * Materialize an `id_pattern`'s frontmatter and context tokens (`{kind}`, `{version}`, `{workflow}`,
207
- * …) from the `--set` values, leaving `{slug}`, the `{n}` family and the not-yet-implemented
208
- * `{date}`/`{author}` in place — `spec-001`'s fixed expansion order (`{date}` → `{author}` → field and
209
- * context tokens → `{slug}` → `{n}`), so the `{n}` counter regexp built from the result sees a
210
- * fully-materialized prefix (task-110).
381
+ * Materialize an `id_pattern`'s `{date}`, `{author}`, frontmatter and context tokens (`{kind}`,
382
+ * `{version}`, `{workflow}`, …), leaving `{slug}` and the `{n}` family in place — `spec-001`'s fixed
383
+ * expansion order (`{date}` → `{author}` → field and context tokens → `{slug}` → `{n}`), so the
384
+ * `{n}` counter regexp built from the result sees a fully-materialized prefix (task-110). `{date}` is
385
+ * the UTC `YYYYMMDD` of `sources.date` ({@link formatIdDate}); `{author}` the slug of
386
+ * `sources.authorName` ({@link slugifyTitle}) — task-163, `bug-158`.
211
387
  *
212
388
  * @throws {@link ValidationError} naming every field token with no value
213
- * (`missing value for token {<name>}: give it with --set <name>=<value>`) and every value outside
214
- * the ID character class, in pattern order — the same `E_INVALID_ID` code `generateId` raises.
389
+ * (`missing value for token {<name>}: give it with --set <name>=<value>`), an `{author}` whose
390
+ * name slugs to nothing, and every value outside the ID character class, in pattern order — the
391
+ * same `E_INVALID_ID` code `generateId` raises.
215
392
  */
216
- function expandFieldTokens(idPattern, values) {
393
+ function expandFieldTokens(idPattern, values, sources = {}) {
217
394
  const issues = [];
218
395
  const expanded = idPattern.replace(TOKEN_RE, (whole, token) => {
219
- if (/^n+$/.test(token) || RESERVED_SET_NAMES.has(token))
396
+ if (token === 'date' && sources.date !== undefined)
397
+ return formatIdDate(sources.date);
398
+ if (token === 'author' && sources.authorName !== undefined) {
399
+ const author = slugifyTitle(sources.authorName);
400
+ if (author.length > 0)
401
+ return author;
402
+ issues.push(fieldIssue(idPattern, `value for token {author} is empty once the git author name "${sources.authorName}" is slugged`));
403
+ return whole;
404
+ }
405
+ if ((0, validation_1.isNumericToken)(token) || RESERVED_SET_NAMES.has(token))
220
406
  return whole;
221
407
  const value = values[token];
222
408
  if (value === undefined) {
@@ -245,7 +431,8 @@ function fieldIssue(pattern, message) {
245
431
  */
246
432
  function writtenFields(scaffold, values) {
247
433
  const { frontmatter } = (0, storage_1.splitFrontmatter)(scaffold);
248
- const declared = (key) => frontmatter !== null && new RegExp(`^[ \\t]*${escapeRegExp(key)}:`, 'm').test(frontmatter);
434
+ // A top-level key only (task-163): a nested key of the same name is not a declaration of the field.
435
+ const declared = (key) => frontmatter !== null && new RegExp(`^${escapeRegExp(key)}:(?:[ \\t\\r]|$)`, 'm').test(frontmatter);
249
436
  return Object.keys(values)
250
437
  .sort()
251
438
  .filter((name) => !CONTEXT_TOKENS.has(name) || declared(name))