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
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DRY_RUN_FLAG = void 0;
4
+ exports.runAsDryRun = runAsDryRun;
5
+ /**
6
+ * `--dry-run` for every mutating operation (task-210, `dl-106` W2, `spec-008-cli-grammar` §2).
7
+ *
8
+ * A surface runs an operation through {@link runAsDryRun} instead of calling its `fn` directly. The
9
+ * operation itself never learns of the mode: the commit primitive (`writeAndCommit`, `src/storage`)
10
+ * plans the commit instead of making it (`src/storage/dry-run.ts`). So every operation registered
11
+ * `mutates: true` — those in `CORE_MODULES` today and any added later — takes the flag by construction,
12
+ * and `test/cli/dry-run.integration.test.ts` holds each of them to it.
13
+ */
14
+ const storage_1 = require("../storage");
15
+ const types_1 = require("./types");
16
+ /**
17
+ * The flag the CLI registrar adds to every command whose operation `mutates` (`src/cli/registrar.ts`).
18
+ * An operation never declares it; a command whose operation writes nothing does not take it.
19
+ */
20
+ exports.DRY_RUN_FLAG = {
21
+ name: 'dry-run',
22
+ description: 'print the commit this command would make (subject, paths, diff) and write nothing',
23
+ };
24
+ /**
25
+ * Run `run` — one operation's `fn` — as a dry run:
26
+ *
27
+ * - it reached its commit → a success whose value is the {@link DryRunPlan} (exit `0`), with no
28
+ * `commit`, since none was made, and the warnings the operation handed to the commit primitive
29
+ * (`CommitOptions.warnings`) — the ones the real run would print;
30
+ * - it refused before writing → its own failed result, unchanged, so the exit code is the refusal's;
31
+ * - it threw → the same throw, for the surface to render as it renders any thrown error;
32
+ * - it succeeded without committing (a change that is already in place) → its own result, which is
33
+ * what the real run would print too.
34
+ *
35
+ * A dry run stops at the operation's first commit (see `src/storage/dry-run.ts`).
36
+ */
37
+ async function runAsDryRun(run) {
38
+ const outcome = await (0, storage_1.captureDryRun)(run);
39
+ if (outcome.kind === 'planned')
40
+ return (0, types_1.coreOk)(outcome.plan, undefined, outcome.warnings);
41
+ if (outcome.kind === 'threw')
42
+ throw outcome.error;
43
+ return outcome.value;
44
+ }
45
+ //# sourceMappingURL=dry-run.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dry-run.js","sourceRoot":"","sources":["../../src/core/dry-run.ts"],"names":[],"mappings":";;;AAsCA,kCAKC;AA3CD;;;;;;;;GAQG;AACH,wCAA4D;AAG5D,mCAAkD;AAIlD;;;GAGG;AACU,QAAA,YAAY,GAAa;IACpC,IAAI,EAAE,SAAS;IACf,WAAW,EAAE,mFAAmF;CACjG,CAAC;AAEF;;;;;;;;;;;;GAYG;AACI,KAAK,UAAU,WAAW,CAAI,GAAiC;IACpE,MAAM,OAAO,GAAG,MAAM,IAAA,uBAAa,EAAC,GAAG,CAAC,CAAC;IACzC,IAAI,OAAO,CAAC,IAAI,KAAK,SAAS;QAAE,OAAO,IAAA,cAAM,EAAC,OAAO,CAAC,IAAI,EAAE,SAAS,EAAE,OAAO,CAAC,QAAQ,CAAC,CAAC;IACzF,IAAI,OAAO,CAAC,IAAI,KAAK,OAAO;QAAE,MAAM,OAAO,CAAC,KAAK,CAAC;IAClD,OAAO,OAAO,CAAC,KAAK,CAAC;AACvB,CAAC"}
@@ -0,0 +1,23 @@
1
+ /**
2
+ * The element-ref, `<type>:<id>` (`spec-008` §7): how a surface names one Memory element by type —
3
+ * the `{role}-session` Prompt's `element` argument (task-195, `spec-004` §3.1) and `agent execute
4
+ * --element` (`spec-016`, task-218). One parser, so both surfaces accept and refuse the same strings.
5
+ *
6
+ * The grammar (`spec-008` §7, as tightened by task-195): exactly one `:`; a non-empty `<type>` before it
7
+ * and a non-empty `<id>` after it; no whitespace, no control character, and no `-->` anywhere — the
8
+ * `spec-012` §7 payload header and its `<!-- begin:<type>:<id> -->` markers could not carry one. Nothing
9
+ * else is checked here: whether `<type>` is a `memory.yaml` type and whether `<id>` names an element are
10
+ * questions for whoever resolves the ref.
11
+ */
12
+ import type { ExecutionContextElement } from './context';
13
+ import { type CoreResult } from './types';
14
+ /** The refusal text of a malformed element-ref: the ref as a JSON string, so no byte of it is lost or interpreted. */
15
+ export declare function malformedElementRefMessage(ref: string): string;
16
+ /**
17
+ * Parse `ref` as an element-ref.
18
+ *
19
+ * @returns The `{type, id}` it names, or `VALIDATION` with {@link malformedElementRefMessage} when it
20
+ * does not follow the grammar in this module's doc.
21
+ */
22
+ export declare function parseElementRef(ref: string): CoreResult<ExecutionContextElement>;
23
+ //# sourceMappingURL=element-ref.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element-ref.d.ts","sourceRoot":"","sources":["../../src/core/element-ref.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AACzD,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAK3D,sHAAsH;AACtH,wBAAgB,0BAA0B,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,GAAG,UAAU,CAAC,uBAAuB,CAAC,CAIhF"}
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.malformedElementRefMessage = malformedElementRefMessage;
4
+ exports.parseElementRef = parseElementRef;
5
+ const types_1 = require("./types");
6
+ // eslint-disable-next-line no-control-regex
7
+ const ELEMENT_REF = /^([^:\s\u0000-\u001f\u007f]+):([^:\s\u0000-\u001f\u007f]+)$/;
8
+ /** The refusal text of a malformed element-ref: the ref as a JSON string, so no byte of it is lost or interpreted. */
9
+ function malformedElementRefMessage(ref) {
10
+ return `malformed element-ref ${JSON.stringify(ref)}: expected <type>:<id>`;
11
+ }
12
+ /**
13
+ * Parse `ref` as an element-ref.
14
+ *
15
+ * @returns The `{type, id}` it names, or `VALIDATION` with {@link malformedElementRefMessage} when it
16
+ * does not follow the grammar in this module's doc.
17
+ */
18
+ function parseElementRef(ref) {
19
+ const match = ELEMENT_REF.exec(ref);
20
+ if (match === null || ref.includes('-->'))
21
+ return (0, types_1.coreErr)({ code: 'VALIDATION', message: malformedElementRefMessage(ref) });
22
+ return (0, types_1.coreOk)({ type: match[1], id: match[2] });
23
+ }
24
+ //# sourceMappingURL=element-ref.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"element-ref.js","sourceRoot":"","sources":["../../src/core/element-ref.ts"],"names":[],"mappings":";;AAkBA,gEAEC;AAQD,0CAIC;AApBD,mCAA2D;AAE3D,4CAA4C;AAC5C,MAAM,WAAW,GAAG,6DAA6D,CAAC;AAElF,sHAAsH;AACtH,SAAgB,0BAA0B,CAAC,GAAW;IACpD,OAAO,yBAAyB,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,wBAAwB,CAAC;AAC9E,CAAC;AAED;;;;;GAKG;AACH,SAAgB,eAAe,CAAC,GAAW;IACzC,MAAM,KAAK,GAAG,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;IACpC,IAAI,KAAK,KAAK,IAAI,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC;QAAE,OAAO,IAAA,eAAO,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,0BAA0B,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;IAC5H,OAAO,IAAA,cAAM,EAAC,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAE,EAAE,CAAC,CAAC;AACpD,CAAC"}
@@ -0,0 +1,20 @@
1
+ import type { CoreError } from './types';
2
+ /** One operator-facing entry of a refusal: the file an issue names and/or its explanation. */
3
+ export interface ErrorDetail {
4
+ readonly file?: string;
5
+ readonly detail?: string;
6
+ }
7
+ /**
8
+ * The operator-facing details of `error`, in issue order (REQ-SYS-07 — the order core recorded, never
9
+ * re-sorted). An issue contributes an entry only when it names a non-empty `file` or `detail`, and the
10
+ * entry carries only the fields it has. Anything else in `details` is ignored: the list is empty for
11
+ * an error with no `details.issues`, which is the case for every error that carried no details before.
12
+ *
13
+ * A `file` the error's `message` already contains, verbatim, is not repeated (task-130 review):
14
+ * `ValidationError`'s message embeds `(<file>)` for every issue, so repeating it would print the path
15
+ * twice. The entry keeps its `detail`, and an entry left with neither field is dropped. What remains is
16
+ * exactly what the reason does not already say — for the illegal-transition refusal, whose message is
17
+ * the bare `dl-032` contract string, both the file and the explanation.
18
+ */
19
+ export declare function errorDetails(error: CoreError): readonly ErrorDetail[];
20
+ //# sourceMappingURL=error-details.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-details.d.ts","sourceRoot":"","sources":["../../src/core/error-details.ts"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAEzC,8FAA8F;AAC9F,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC;CAC1B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,YAAY,CAAC,KAAK,EAAE,SAAS,GAAG,SAAS,WAAW,EAAE,CAgBrE"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.errorDetails = errorDetails;
4
+ /**
5
+ * What of a {@link CoreError}'s `details` every surface shows (task-130, `dl-055` option 1,
6
+ * `spec-005` §3, `spec-004`).
7
+ *
8
+ * Every core refusal built from a `ValidationError` carries `details: { issues }`, and two fields of
9
+ * an issue are for the operator: the `file` it was found in (`bug-031`'s missing file name) and the
10
+ * `detail` that explains a pinned contract message (`dl-032` option (c)). Until this module no surface
11
+ * read either. A spec-003 loader refusal (task-136) carries `details: { diagnostics }` instead; each
12
+ * diagnostic is shown in the reason form (see `diagnosticDetails`). Deciding *which* fields are shown once, here, is what keeps the CLI (`src/cli/error.ts`)
13
+ * and the MCP registrar (`src/mcp/registrar.ts`) from drifting apart (REQ-SYS-05); each surface only
14
+ * decides how to write the list in its own format.
15
+ */
16
+ const validation_1 = require("../validation");
17
+ /**
18
+ * The operator-facing details of `error`, in issue order (REQ-SYS-07 — the order core recorded, never
19
+ * re-sorted). An issue contributes an entry only when it names a non-empty `file` or `detail`, and the
20
+ * entry carries only the fields it has. Anything else in `details` is ignored: the list is empty for
21
+ * an error with no `details.issues`, which is the case for every error that carried no details before.
22
+ *
23
+ * A `file` the error's `message` already contains, verbatim, is not repeated (task-130 review):
24
+ * `ValidationError`'s message embeds `(<file>)` for every issue, so repeating it would print the path
25
+ * twice. The entry keeps its `detail`, and an entry left with neither field is dropped. What remains is
26
+ * exactly what the reason does not already say — for the illegal-transition refusal, whose message is
27
+ * the bare `dl-032` contract string, both the file and the explanation.
28
+ */
29
+ function errorDetails(error) {
30
+ const diagnostics = error.details?.diagnostics;
31
+ if (Array.isArray(diagnostics))
32
+ return diagnosticDetails(error.message, diagnostics);
33
+ const issues = error.details?.issues;
34
+ if (!Array.isArray(issues))
35
+ return [];
36
+ const entries = [];
37
+ for (const issue of issues) {
38
+ if (typeof issue !== 'object' || issue === null)
39
+ continue;
40
+ const { file, detail } = issue;
41
+ const entry = {
42
+ ...(typeof file === 'string' && file !== '' && !error.message.includes(file) ? { file } : {}),
43
+ ...(typeof detail === 'string' && detail !== '' ? { detail } : {}),
44
+ };
45
+ if (entry.file !== undefined || entry.detail !== undefined)
46
+ entries.push(entry);
47
+ }
48
+ return entries;
49
+ }
50
+ /**
51
+ * The details of a refusal that carries spec-003 `diagnostics` (task-136) rather than `issues`: one
52
+ * entry per diagnostic, in the loader's order, its `detail` the diagnostic in the reason form
53
+ * (`formatDiagnostic`: code, path, file and message), so every further error and every warning reaches
54
+ * the operator. The diagnostic the reason already is — the first error — is not repeated.
55
+ */
56
+ function diagnosticDetails(reason, diagnostics) {
57
+ const entries = [];
58
+ for (const diagnostic of diagnostics) {
59
+ const line = (0, validation_1.formatDiagnostic)(diagnostic);
60
+ if (line !== reason)
61
+ entries.push({ detail: line });
62
+ }
63
+ return entries;
64
+ }
65
+ //# sourceMappingURL=error-details.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"error-details.js","sourceRoot":"","sources":["../../src/core/error-details.ts"],"names":[],"mappings":";;AAiCA,oCAgBC;AAjDD;;;;;;;;;;;GAWG;AACH,8CAAkE;AASlE;;;;;;;;;;;GAWG;AACH,SAAgB,YAAY,CAAC,KAAgB;IAC3C,MAAM,WAAW,GAAG,KAAK,CAAC,OAAO,EAAE,WAAW,CAAC;IAC/C,IAAI,KAAK,CAAC,OAAO,CAAC,WAAW,CAAC;QAAE,OAAO,iBAAiB,CAAC,KAAK,CAAC,OAAO,EAAE,WAAoC,CAAC,CAAC;IAC9G,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,EAAE,MAAM,CAAC;IACrC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC;QAAE,OAAO,EAAE,CAAC;IACtC,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,KAAK,IAAI,MAA4B,EAAE,CAAC;QACjD,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,SAAS;QAC1D,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,KAA6C,CAAC;QACvE,MAAM,KAAK,GAAgB;YACzB,GAAG,CAAC,OAAO,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC7F,GAAG,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SACnE,CAAC;QACF,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,MAAM,KAAK,SAAS;YAAE,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IAClF,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;;GAKG;AACH,SAAS,iBAAiB,CAAC,MAAc,EAAE,WAAkC;IAC3E,MAAM,OAAO,GAAkB,EAAE,CAAC;IAClC,KAAK,MAAM,UAAU,IAAI,WAAW,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,IAAA,6BAAgB,EAAC,UAAU,CAAC,CAAC;QAC1C,IAAI,IAAI,KAAK,MAAM;YAAE,OAAO,CAAC,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC;IACtD,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"exit-code.d.ts","sourceRoot":"","sources":["../../src/core/exit-code.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,SAAS,EAAiB,UAAU,EAAE,MAAM,SAAS,CAAC;AAGpE,wGAAwG;AACxG,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAgBjC,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAE3D;AAED,kGAAkG;AAClG,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,QAAQ,CAEvE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAqDD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,gBAAgB,CAM5E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,QAAQ,CAEvE;AAED,sGAAsG;AACtG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAS9D"}
1
+ {"version":3,"file":"exit-code.d.ts","sourceRoot":"","sources":["../../src/core/exit-code.ts"],"names":[],"mappings":"AAyBA,OAAO,KAAK,EAAE,SAAS,EAAiB,UAAU,EAAE,MAAM,SAAS,CAAC;AAGpE,wGAAwG;AACxG,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAgBjC,+DAA+D;AAC/D,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,QAAQ,CAE3D;AAED,kGAAkG;AAClG,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,UAAU,CAAC,OAAO,CAAC,GAAG,QAAQ,CAEvE;AAED;;;;;;GAMG;AACH,MAAM,WAAW,YAAY;IAC3B,sFAAsF;IACtF,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,gGAAgG;IAChG,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAC;CAC3B;AAoDD;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iEAAiE;IACjE,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;IAC5B;;;;;;OAMG;IACH,QAAQ,CAAC,cAAc,EAAE,OAAO,CAAC;CAClC;AAED;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,YAAY,GAAG,gBAAgB,CAM5E;AAED;;;;GAIG;AACH,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,YAAY,GAAG,QAAQ,CAEvE;AAED,sGAAsG;AACtG,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,QAAQ,EAAE,QAAQ,CAAC;CAC7B;AAED;;;;;;;;;;;;GAYG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAS9D"}
@@ -64,13 +64,12 @@ function exitCodeForResult(result) {
64
64
  * version surface: a Commander upgrade that renames or adds one must revisit this set, which is why
65
65
  * the codes are listed explicitly here rather than inferred from the suggested exit code.
66
66
  *
67
- * One of them, `commander.excessArguments`, is reached in production only by the two hand-wired
68
- * bootstrap commands (`wingfoil init extra` → `error: too many arguments for 'init'…`, exit `2`,
69
- * pinned by `test/cli/commander-parse-exit-codes.integration.test.ts`). A command derived from
70
- * `CORE_MODULES` never raises it: `src/cli/program.ts` registers a declared positional as an optional
71
- * variadic list and lets a command without one accept excess operands (task-120), so
72
- * `wingfoil dna show project extra` is accepted and an extra positional on a write verb is refused by
73
- * WingFoil's own check instead, already at exit `2`.
67
+ * One of them, `commander.excessArguments`, is reached by no shipped command: a command derived from
68
+ * `CORE_MODULES` registers a declared positional as an optional variadic list and lets a command
69
+ * without one accept excess operands (task-120), and the two hand-wired bootstrap commands `init` and
70
+ * `mcp` accept them too (task-165, `bug-179`), so a surplus operand is refused by WingFoil's own check
71
+ * (`extraOperandsReason`, task-129), already at exit `2`. The code stays in the set so that a command
72
+ * registered later without that opt-in still exits `2` on Commander's refusal.
74
73
  */
75
74
  const USAGE_ERROR_PARSE_CODES = new Set([
76
75
  'commander.unknownCommand',
@@ -1 +1 @@
1
- {"version":3,"file":"exit-code.js","sourceRoot":"","sources":["../../src/core/exit-code.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"exit-code.js","sourceRoot":"","sources":["../../src/core/exit-code.ts"],"names":[],"mappings":"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"}
@@ -9,24 +9,59 @@ import { type CoreResult } from './types';
9
9
  * only ever looks at the *current* live git config). Pure predicate — no git/filesystem access.
10
10
  */
11
11
  export declare function isConfiguredIdentity(name: string, email: string): boolean;
12
- /** The `user.name`/`user.email` pair `readGitIdentity` resolves at a given root — either may be `''` (unset). */
12
+ /**
13
+ * The author identity {@link readGitIdentity} resolves at a given root — either field may be `''`
14
+ * (unresolved). It is the one value a mutating operation checks (REQ-SEC-01), authorizes
15
+ * (REQ-SEC-03), writes into an `Approver:` line and pins as its commit's author (task-132, `bug-149`).
16
+ */
13
17
  export interface GitIdentity {
14
18
  readonly name: string;
15
19
  readonly email: string;
16
20
  }
17
21
  /**
18
- * Read the live `user.name`/`user.email` git identity configured at `root`, with no "is it valid"
19
- * judgement of its own (that is {@link isConfiguredIdentity}'s job) — the single read primitive both
20
- * {@link requireGitIdentity} (REQ-SEC-01) and `src/core/approval-authority.ts`'s
21
- * `requireApprovalAuthority` (REQ-SEC-03, task-040-role-based-approval-authority) build on, so the two
22
- * checks never each re-implement their own `git config` read.
22
+ * Resolve the identity git would record as the author of a commit made at `root` — `GIT_AUTHOR_NAME`
23
+ * / `GIT_AUTHOR_EMAIL`, then `author.name` / `author.email`, then `user.name` / `user.email`, each
24
+ * field independently, as `git commit` does — with no "is it valid" judgement of its own (that is
25
+ * {@link isConfiguredIdentity}'s job).
26
+ *
27
+ * Before task-132 this read `user.*` alone, while the commit itself was authored by git's precedence,
28
+ * so with `GIT_AUTHOR_EMAIL` set the identity an approval was authorized for and the one it was
29
+ * recorded under could differ (`bug-149`). Reading in git's order makes the value the one the user
30
+ * meant; the transition verbs then pin it as the commit's author (`commitMemoryTransition`, through
31
+ * `GIT_AUTHOR_*` in the commit's environment), so the recorded author is this value by construction
32
+ * rather than by agreement between two readers.
33
+ *
34
+ * One `git config` subprocess (it used to be two per read, and an approval read three times — six
35
+ * subprocesses, `dl-064` Context (ii)). Called once per operation, by {@link requireGitIdentity}; the
36
+ * result is passed on, never re-read (`dl-064` B.1).
37
+ *
38
+ * A git that cannot be run resolves nothing here: both fields are `''`, as before task-284. Only
39
+ * {@link requireGitIdentity} turns that case into its own refusal; this reader has no error channel
40
+ * and its read-only caller (`workflow next --assigned-to me`) treats an unresolved email as no member.
23
41
  */
24
42
  export declare function readGitIdentity(root: string): GitIdentity;
25
43
  /**
26
- * Verify a git identity is configured at `root` before a state mutation. Returns a
27
- * `CoreResult.error` (code `VALIDATION` — a failed precondition, mapped to exit `1` by
28
- * `exitCodeForError`) carrying the exact REQ-SEC-01 message when either `user.name` or `user.email`
29
- * is unset; otherwise `ok`.
44
+ * Verify that a commit made at `root` now would be attributable, and return its author. Every
45
+ * mutating operation runs this before it reads or writes anything else (REQ-SEC-01), so a refusal
46
+ * leaves the repository exactly as it was.
47
+ *
48
+ * Three refusals, all exit `1` by `exitCodeForError`:
49
+ *
50
+ * - **git could not be run** (`IO`, task-284, `bug-377`) — the `git config` spawn itself failed
51
+ * ({@link readIdentityConfig}): `could not run git: <cause>`, the cause being the spawn error's
52
+ * message (`spawnSync git ENOENT`). git is the storage, so this is a failure of the storage, not of
53
+ * the identity, and REQ-SEC-01's message would point the user at the wrong thing.
54
+ * - **Unresolved** (`VALIDATION`) — the author's or the committer's name or email does not resolve
55
+ * ({@link resolveField}): REQ-SEC-01's exact message. The committer is checked too because
56
+ * `git commit` refuses without one: an author supplied by `GIT_AUTHOR_*` or `author.*` alone passed
57
+ * this check after task-132's first pass, and `git commit` then died on "Committer identity
58
+ * unknown" AFTER the document had been written and staged (task-132 review, finding 1).
59
+ * - **Unusable** (`VALIDATION`) — one of the four values holds `<`, `>` or a control character
60
+ * ({@link hasUnsafeIdentityCharacter}): `git identity not usable: the <role> <field> contains '<',
61
+ * '>' or a control character`.
62
+ *
63
+ * On success the value is the author — the one "who" every later step uses: the authority check,
64
+ * the `Approver:` line and the commit author (`dl-064` B.1, task-132) — never read again.
30
65
  */
31
- export declare function requireGitIdentity(root: string): CoreResult<void>;
66
+ export declare function requireGitIdentity(root: string): CoreResult<GitIdentity>;
32
67
  //# sourceMappingURL=git-identity.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-identity.d.ts","sourceRoot":"","sources":["../../src/core/git-identity.ts"],"names":[],"mappings":"AAaA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAqB3D;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzE;AAED,iHAAiH;AACjH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAEzD;AAED;;;;;GAKG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,IAAI,CAAC,CAMjE"}
1
+ {"version":3,"file":"git-identity.d.ts","sourceRoot":"","sources":["../../src/core/git-identity.ts"],"names":[],"mappings":"AAcA,OAAO,EAAmB,KAAK,UAAU,EAAE,MAAM,SAAS,CAAC;AAwD3D;;;;;;;;GAQG;AACH,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAEzE;AAED;;;;GAIG;AACH,MAAM,WAAW,WAAW;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;CACxB;AA0CD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,WAAW,CAGzD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,UAAU,CAAC,WAAW,CAAC,CAoBxE"}
@@ -9,8 +9,9 @@ exports.requireGitIdentity = requireGitIdentity;
9
9
  *
10
10
  * Git identity is WingFoil's sole attribution mechanism: the commit author *is* the "who" of the
11
11
  * audit trail (adr-001 / adr-006 — no separate auth/session/IAM layer). So every state-mutating
12
- * operation must refuse to run when `user.name`/`user.email` are unset, rather than produce a commit
13
- * with an unattributable author. This check lives in `src/core` so the CLI and every MCP Tool enforce
12
+ * operation must refuse to run when no author or no committer resolves (`user.name`/`user.email`, or
13
+ * what outranks them for git: `GIT_AUTHOR_*`/`author.*`, `GIT_COMMITTER_*`/`committer.*` — task-132),
14
+ * rather than produce a commit with an unattributable author, or fail half-way through one. This check lives in `src/core` so the CLI and every MCP Tool enforce
14
15
  * it identically by construction (REQ-SYS-05) — a mutation calls it first and returns its
15
16
  * `CoreResult.error` unchanged, so the surface renders the exact message and writes nothing.
16
17
  */
@@ -18,21 +19,49 @@ const node_child_process_1 = require("node:child_process");
18
19
  const types_1 = require("./types");
19
20
  /** Exact refusal message required by REQ-SEC-01's fit criterion — do not reword. */
20
21
  const IDENTITY_ERROR = 'git identity not configured (user.name/user.email)';
22
+ /** The six config keys an author or committer identity can come from, as `git config` prints them. */
23
+ const IDENTITY_KEYS = /^(author|committer|user)\.(name|email)$/;
21
24
  /**
22
- * The effective value of a git config `key` at `root`, or `''` when it is unset — git exits non-zero
23
- * for an unset key, which we treat as absent (the same "empty means unconfigured" contract the check
24
- * relies on). Resolves local → global → system exactly as any git command would.
25
+ * The effective values of `author.*`, `committer.*` and `user.*` (`name`, `email`) at `root`, in ONE
26
+ * `git config` subprocess. `--get-regexp` lists every scope's entry, lowest precedence first
27
+ * (system, global, local), so the last value seen for a key is the effective one, exactly as
28
+ * `git config <key>` would answer. `-z` keeps a value with unusual bytes intact.
29
+ *
30
+ * Three outcomes (task-284, `bug-377`):
31
+ *
32
+ * - **git could not be run** — the spawn itself failed (`ENOENT`: no `git` on `PATH`; `EACCES`: not
33
+ * executable; `EPERM`: a sandbox forbids it), so git never answered: `ran: false`, with the spawn
34
+ * error's message (`spawnSync git ENOENT`) as the cause. Before task-284 this read as "no value", and
35
+ * the check sent the user to configure an identity that may have been right. An output past
36
+ * `spawnSync`'s default `maxBuffer` also sets the spawn error (`ENOBUFS`) and takes this branch, read
37
+ * as `could not run git: spawnSync git ENOBUFS`.
38
+ * - **git ran and exited non-zero** — `1` when no key matches, `128` for a root git cannot enter or a
39
+ * config file it cannot parse, or a signal: every key is absent, the "empty means unconfigured"
40
+ * contract the check relies on, kept on purpose for these exits (the approver's ruling on task-284,
41
+ * D2).
42
+ * - **exit `0`** — the values git printed. A key that is unset is simply absent.
25
43
  */
26
- function readGitConfig(root, key) {
27
- try {
28
- // `env: process.env` is passed explicitly (identical to the default in production): it makes git's
29
- // config resolution follow the current environment by design, so a caller/test can scope it via
30
- // `GIT_CONFIG_GLOBAL`/`GIT_CONFIG_SYSTEM`/`GIT_CONFIG_NOSYSTEM` deterministically.
31
- return (0, node_child_process_1.execFileSync)('git', ['-C', root, 'config', key], { encoding: 'utf-8', env: process.env }).trim();
32
- }
33
- catch {
34
- return '';
44
+ function readIdentityConfig(root) {
45
+ // `env: process.env` is passed explicitly (identical to the default in production): it makes git's
46
+ // config resolution follow the current environment by design, so a caller/test can scope it via
47
+ // `GIT_CONFIG_GLOBAL`/`GIT_CONFIG_SYSTEM`/`GIT_CONFIG_NOSYSTEM` deterministically.
48
+ const run = (0, node_child_process_1.spawnSync)('git', ['-C', root, 'config', '-z', '--get-regexp', IDENTITY_KEYS.source], {
49
+ encoding: 'utf-8',
50
+ env: process.env,
51
+ stdio: ['ignore', 'pipe', 'ignore'],
52
+ });
53
+ if (run.error !== undefined)
54
+ return { ran: false, cause: run.error.message };
55
+ const values = new Map();
56
+ if (run.status !== 0)
57
+ return { ran: true, values };
58
+ for (const record of run.stdout.split('\0')) {
59
+ const newline = record.indexOf('\n');
60
+ if (newline < 0)
61
+ continue;
62
+ values.set(record.slice(0, newline), record.slice(newline + 1).trim());
35
63
  }
64
+ return { ran: true, values };
36
65
  }
37
66
  /**
38
67
  * The single source of truth for "a configured/attributable identity": non-empty `name` AND
@@ -47,26 +76,110 @@ function isConfiguredIdentity(name, email) {
47
76
  return name.length > 0 && email.length > 0;
48
77
  }
49
78
  /**
50
- * Read the live `user.name`/`user.email` git identity configured at `root`, with no "is it valid"
51
- * judgement of its own (that is {@link isConfiguredIdentity}'s job) — the single read primitive both
52
- * {@link requireGitIdentity} (REQ-SEC-01) and `src/core/approval-authority.ts`'s
53
- * `requireApprovalAuthority` (REQ-SEC-03, task-040-role-based-approval-authority) build on, so the two
54
- * checks never each re-implement their own `git config` read.
79
+ * One field of the `role` identity, resolved in `git commit`'s own order: the `GIT_AUTHOR_*` /
80
+ * `GIT_COMMITTER_*` environment variable, then the `author.*` / `committer.*` config key, then
81
+ * `user.*`. A variable that is SET wins even when blank, never falling back: git refuses a blank name
82
+ * ("empty ident name not allowed") and records a blank email as `<>`; a blank one resolves to `''`
83
+ * and the check refuses both (task-132 review, finding 4). A blank config value falls through to the next key.
84
+ *
85
+ * Deliberately NOT followed further down git's chain: the `EMAIL` environment variable and git's
86
+ * hostname guess. Both are what REQ-SEC-01 exists to refuse — an identity nobody configured — and the
87
+ * check's message names `user.name`/`user.email` as the thing to set.
88
+ */
89
+ function resolveField(config, role, field) {
90
+ const fromEnv = process.env[`GIT_${role.toUpperCase()}_${field.toUpperCase()}`];
91
+ if (fromEnv !== undefined)
92
+ return fromEnv.trim();
93
+ const fromRole = config.get(`${role}.${field}`) ?? '';
94
+ if (fromRole.length > 0)
95
+ return fromRole;
96
+ return config.get(`user.${field}`) ?? '';
97
+ }
98
+ function resolveIdentity(config, role) {
99
+ return { name: resolveField(config, role, 'name'), email: resolveField(config, role, 'email') };
100
+ }
101
+ /**
102
+ * Whether `value` holds a character git's ident format cannot carry verbatim: `<` and `>` delimit the
103
+ * email in a commit's `author`/`committer` header, and a control character (newline included) can end
104
+ * a line of the commit body. Either lets a recorded identity, or an `Approver:` line built from it,
105
+ * say something other than what was authorized (task-132 review, finding 2).
106
+ */
107
+ function hasUnsafeIdentityCharacter(value) {
108
+ for (const char of value) {
109
+ const code = char.codePointAt(0) ?? 0;
110
+ if (char === '<' || char === '>' || code < 0x20 || code === 0x7f)
111
+ return true;
112
+ }
113
+ return false;
114
+ }
115
+ /**
116
+ * Resolve the identity git would record as the author of a commit made at `root` — `GIT_AUTHOR_NAME`
117
+ * / `GIT_AUTHOR_EMAIL`, then `author.name` / `author.email`, then `user.name` / `user.email`, each
118
+ * field independently, as `git commit` does — with no "is it valid" judgement of its own (that is
119
+ * {@link isConfiguredIdentity}'s job).
120
+ *
121
+ * Before task-132 this read `user.*` alone, while the commit itself was authored by git's precedence,
122
+ * so with `GIT_AUTHOR_EMAIL` set the identity an approval was authorized for and the one it was
123
+ * recorded under could differ (`bug-149`). Reading in git's order makes the value the one the user
124
+ * meant; the transition verbs then pin it as the commit's author (`commitMemoryTransition`, through
125
+ * `GIT_AUTHOR_*` in the commit's environment), so the recorded author is this value by construction
126
+ * rather than by agreement between two readers.
127
+ *
128
+ * One `git config` subprocess (it used to be two per read, and an approval read three times — six
129
+ * subprocesses, `dl-064` Context (ii)). Called once per operation, by {@link requireGitIdentity}; the
130
+ * result is passed on, never re-read (`dl-064` B.1).
131
+ *
132
+ * A git that cannot be run resolves nothing here: both fields are `''`, as before task-284. Only
133
+ * {@link requireGitIdentity} turns that case into its own refusal; this reader has no error channel
134
+ * and its read-only caller (`workflow next --assigned-to me`) treats an unresolved email as no member.
55
135
  */
56
136
  function readGitIdentity(root) {
57
- return { name: readGitConfig(root, 'user.name'), email: readGitConfig(root, 'user.email') };
137
+ const config = readIdentityConfig(root);
138
+ return resolveIdentity(config.ran ? config.values : new Map(), 'author');
58
139
  }
59
140
  /**
60
- * Verify a git identity is configured at `root` before a state mutation. Returns a
61
- * `CoreResult.error` (code `VALIDATION` — a failed precondition, mapped to exit `1` by
62
- * `exitCodeForError`) carrying the exact REQ-SEC-01 message when either `user.name` or `user.email`
63
- * is unset; otherwise `ok`.
141
+ * Verify that a commit made at `root` now would be attributable, and return its author. Every
142
+ * mutating operation runs this before it reads or writes anything else (REQ-SEC-01), so a refusal
143
+ * leaves the repository exactly as it was.
144
+ *
145
+ * Three refusals, all exit `1` by `exitCodeForError`:
146
+ *
147
+ * - **git could not be run** (`IO`, task-284, `bug-377`) — the `git config` spawn itself failed
148
+ * ({@link readIdentityConfig}): `could not run git: <cause>`, the cause being the spawn error's
149
+ * message (`spawnSync git ENOENT`). git is the storage, so this is a failure of the storage, not of
150
+ * the identity, and REQ-SEC-01's message would point the user at the wrong thing.
151
+ * - **Unresolved** (`VALIDATION`) — the author's or the committer's name or email does not resolve
152
+ * ({@link resolveField}): REQ-SEC-01's exact message. The committer is checked too because
153
+ * `git commit` refuses without one: an author supplied by `GIT_AUTHOR_*` or `author.*` alone passed
154
+ * this check after task-132's first pass, and `git commit` then died on "Committer identity
155
+ * unknown" AFTER the document had been written and staged (task-132 review, finding 1).
156
+ * - **Unusable** (`VALIDATION`) — one of the four values holds `<`, `>` or a control character
157
+ * ({@link hasUnsafeIdentityCharacter}): `git identity not usable: the <role> <field> contains '<',
158
+ * '>' or a control character`.
159
+ *
160
+ * On success the value is the author — the one "who" every later step uses: the authority check,
161
+ * the `Approver:` line and the commit author (`dl-064` B.1, task-132) — never read again.
64
162
  */
65
163
  function requireGitIdentity(root) {
66
- const { name, email } = readGitIdentity(root);
67
- if (!isConfiguredIdentity(name, email)) {
164
+ const read = readIdentityConfig(root);
165
+ if (!read.ran)
166
+ return (0, types_1.coreErr)({ code: 'IO', message: `could not run git: ${read.cause}` });
167
+ const config = read.values;
168
+ const author = resolveIdentity(config, 'author');
169
+ const committer = resolveIdentity(config, 'committer');
170
+ if (!isConfiguredIdentity(author.name, author.email) || !isConfiguredIdentity(committer.name, committer.email)) {
68
171
  return (0, types_1.coreErr)({ code: 'VALIDATION', message: IDENTITY_ERROR });
69
172
  }
70
- return (0, types_1.coreOk)(undefined);
173
+ for (const [role, identity] of [['author', author], ['committer', committer]]) {
174
+ for (const field of ['name', 'email']) {
175
+ if (hasUnsafeIdentityCharacter(identity[field])) {
176
+ return (0, types_1.coreErr)({
177
+ code: 'VALIDATION',
178
+ message: `git identity not usable: the ${role} ${field} contains '<', '>' or a control character`,
179
+ });
180
+ }
181
+ }
182
+ }
183
+ return (0, types_1.coreOk)(author);
71
184
  }
72
185
  //# sourceMappingURL=git-identity.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"git-identity.js","sourceRoot":"","sources":["../../src/core/git-identity.ts"],"names":[],"mappings":";;AA2CA,oDAEC;AAeD,0CAEC;AAQD,gDAMC;AA5ED;;;;;;;;;;GAUG;AACH,2DAAkD;AAElD,mCAA2D;AAE3D,oFAAoF;AACpF,MAAM,cAAc,GAAG,oDAAoD,CAAC;AAE5E;;;;GAIG;AACH,SAAS,aAAa,CAAC,IAAY,EAAE,GAAW;IAC9C,IAAI,CAAC;QACH,mGAAmG;QACnG,gGAAgG;QAChG,mFAAmF;QACnF,OAAO,IAAA,iCAAY,EAAC,KAAK,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,QAAQ,EAAE,GAAG,CAAC,EAAE,EAAE,QAAQ,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;IAC1G,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;AACH,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,oBAAoB,CAAC,IAAY,EAAE,KAAa;IAC9D,OAAO,IAAI,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;AAC7C,CAAC;AAQD;;;;;;GAMG;AACH,SAAgB,eAAe,CAAC,IAAY;IAC1C,OAAO,EAAE,IAAI,EAAE,aAAa,CAAC,IAAI,EAAE,WAAW,CAAC,EAAE,KAAK,EAAE,aAAa,CAAC,IAAI,EAAE,YAAY,CAAC,EAAE,CAAC;AAC9F,CAAC;AAED;;;;;GAKG;AACH,SAAgB,kBAAkB,CAAC,IAAY;IAC7C,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;IAC9C,IAAI,CAAC,oBAAoB,CAAC,IAAI,EAAE,KAAK,CAAC,EAAE,CAAC;QACvC,OAAO,IAAA,eAAO,EAAC,EAAE,IAAI,EAAE,YAAY,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC,CAAC;IAClE,CAAC;IACD,OAAO,IAAA,cAAM,EAAO,SAAS,CAAC,CAAC;AACjC,CAAC"}
1
+ {"version":3,"file":"git-identity.js","sourceRoot":"","sources":["../../src/core/git-identity.ts"],"names":[],"mappings":"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"}