wingfoil 0.2.1

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 (339) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +334 -0
  3. package/dist/cli/error.d.ts +11 -0
  4. package/dist/cli/error.d.ts.map +1 -0
  5. package/dist/cli/error.js +27 -0
  6. package/dist/cli/error.js.map +1 -0
  7. package/dist/cli/exit.d.ts +19 -0
  8. package/dist/cli/exit.d.ts.map +1 -0
  9. package/dist/cli/exit.js +14 -0
  10. package/dist/cli/exit.js.map +1 -0
  11. package/dist/cli/index.d.ts +28 -0
  12. package/dist/cli/index.d.ts.map +1 -0
  13. package/dist/cli/index.js +36 -0
  14. package/dist/cli/index.js.map +1 -0
  15. package/dist/cli/init-command.d.ts +34 -0
  16. package/dist/cli/init-command.d.ts.map +1 -0
  17. package/dist/cli/init-command.js +100 -0
  18. package/dist/cli/init-command.js.map +1 -0
  19. package/dist/cli/mcp-command.d.ts +24 -0
  20. package/dist/cli/mcp-command.d.ts.map +1 -0
  21. package/dist/cli/mcp-command.js +42 -0
  22. package/dist/cli/mcp-command.js.map +1 -0
  23. package/dist/cli/output.d.ts +13 -0
  24. package/dist/cli/output.d.ts.map +1 -0
  25. package/dist/cli/output.js +28 -0
  26. package/dist/cli/output.js.map +1 -0
  27. package/dist/cli/program.d.ts +12 -0
  28. package/dist/cli/program.d.ts.map +1 -0
  29. package/dist/cli/program.js +279 -0
  30. package/dist/cli/program.js.map +1 -0
  31. package/dist/cli/registrar.d.ts +69 -0
  32. package/dist/cli/registrar.d.ts.map +1 -0
  33. package/dist/cli/registrar.js +82 -0
  34. package/dist/cli/registrar.js.map +1 -0
  35. package/dist/cli.d.ts +3 -0
  36. package/dist/cli.d.ts.map +1 -0
  37. package/dist/cli.js +45 -0
  38. package/dist/cli.js.map +1 -0
  39. package/dist/core/approval-authority.d.ts +83 -0
  40. package/dist/core/approval-authority.d.ts.map +1 -0
  41. package/dist/core/approval-authority.js +112 -0
  42. package/dist/core/approval-authority.js.map +1 -0
  43. package/dist/core/builtin-asset.d.ts +71 -0
  44. package/dist/core/builtin-asset.d.ts.map +1 -0
  45. package/dist/core/builtin-asset.js +137 -0
  46. package/dist/core/builtin-asset.js.map +1 -0
  47. package/dist/core/builtin-integrity.d.ts +32 -0
  48. package/dist/core/builtin-integrity.d.ts.map +1 -0
  49. package/dist/core/builtin-integrity.js +148 -0
  50. package/dist/core/builtin-integrity.js.map +1 -0
  51. package/dist/core/confinement.d.ts +57 -0
  52. package/dist/core/confinement.d.ts.map +1 -0
  53. package/dist/core/confinement.js +108 -0
  54. package/dist/core/confinement.js.map +1 -0
  55. package/dist/core/context.d.ts +187 -0
  56. package/dist/core/context.d.ts.map +1 -0
  57. package/dist/core/context.js +192 -0
  58. package/dist/core/context.js.map +1 -0
  59. package/dist/core/directive-assign.d.ts +131 -0
  60. package/dist/core/directive-assign.d.ts.map +1 -0
  61. package/dist/core/directive-assign.js +352 -0
  62. package/dist/core/directive-assign.js.map +1 -0
  63. package/dist/core/directives-list.d.ts +80 -0
  64. package/dist/core/directives-list.d.ts.map +1 -0
  65. package/dist/core/directives-list.js +148 -0
  66. package/dist/core/directives-list.js.map +1 -0
  67. package/dist/core/exit-code.d.ts +85 -0
  68. package/dist/core/exit-code.d.ts.map +1 -0
  69. package/dist/core/exit-code.js +163 -0
  70. package/dist/core/exit-code.js.map +1 -0
  71. package/dist/core/git-identity.d.ts +32 -0
  72. package/dist/core/git-identity.d.ts.map +1 -0
  73. package/dist/core/git-identity.js +72 -0
  74. package/dist/core/git-identity.js.map +1 -0
  75. package/dist/core/index.d.ts +388 -0
  76. package/dist/core/index.d.ts.map +1 -0
  77. package/dist/core/index.js +1331 -0
  78. package/dist/core/index.js.map +1 -0
  79. package/dist/core/init.d.ts +78 -0
  80. package/dist/core/init.d.ts.map +1 -0
  81. package/dist/core/init.js +167 -0
  82. package/dist/core/init.js.map +1 -0
  83. package/dist/core/loaders.d.ts +174 -0
  84. package/dist/core/loaders.d.ts.map +1 -0
  85. package/dist/core/loaders.js +364 -0
  86. package/dist/core/loaders.js.map +1 -0
  87. package/dist/core/memory-add-type.d.ts +43 -0
  88. package/dist/core/memory-add-type.d.ts.map +1 -0
  89. package/dist/core/memory-add-type.js +151 -0
  90. package/dist/core/memory-add-type.js.map +1 -0
  91. package/dist/core/memory-transition.d.ts +111 -0
  92. package/dist/core/memory-transition.d.ts.map +1 -0
  93. package/dist/core/memory-transition.js +269 -0
  94. package/dist/core/memory-transition.js.map +1 -0
  95. package/dist/core/registry.d.ts +189 -0
  96. package/dist/core/registry.d.ts.map +1 -0
  97. package/dist/core/registry.js +66 -0
  98. package/dist/core/registry.js.map +1 -0
  99. package/dist/core/relevance.d.ts +86 -0
  100. package/dist/core/relevance.d.ts.map +1 -0
  101. package/dist/core/relevance.js +258 -0
  102. package/dist/core/relevance.js.map +1 -0
  103. package/dist/core/require-reason.d.ts +27 -0
  104. package/dist/core/require-reason.d.ts.map +1 -0
  105. package/dist/core/require-reason.js +95 -0
  106. package/dist/core/require-reason.js.map +1 -0
  107. package/dist/core/types.d.ts +45 -0
  108. package/dist/core/types.d.ts.map +1 -0
  109. package/dist/core/types.js +22 -0
  110. package/dist/core/types.js.map +1 -0
  111. package/dist/core/usage-error.d.ts +20 -0
  112. package/dist/core/usage-error.d.ts.map +1 -0
  113. package/dist/core/usage-error.js +29 -0
  114. package/dist/core/usage-error.js.map +1 -0
  115. package/dist/core/write-guard.d.ts +99 -0
  116. package/dist/core/write-guard.d.ts.map +1 -0
  117. package/dist/core/write-guard.js +247 -0
  118. package/dist/core/write-guard.js.map +1 -0
  119. package/dist/directives/create.d.ts +47 -0
  120. package/dist/directives/create.d.ts.map +1 -0
  121. package/dist/directives/create.js +82 -0
  122. package/dist/directives/create.js.map +1 -0
  123. package/dist/directives/index.d.ts +20 -0
  124. package/dist/directives/index.d.ts.map +1 -0
  125. package/dist/directives/index.js +32 -0
  126. package/dist/directives/index.js.map +1 -0
  127. package/dist/directives/roles-edit.d.ts +53 -0
  128. package/dist/directives/roles-edit.d.ts.map +1 -0
  129. package/dist/directives/roles-edit.js +286 -0
  130. package/dist/directives/roles-edit.js.map +1 -0
  131. package/dist/directives/schema.d.ts +65 -0
  132. package/dist/directives/schema.d.ts.map +1 -0
  133. package/dist/directives/schema.js +68 -0
  134. package/dist/directives/schema.js.map +1 -0
  135. package/dist/dna/edit.d.ts +61 -0
  136. package/dist/dna/edit.d.ts.map +1 -0
  137. package/dist/dna/edit.js +429 -0
  138. package/dist/dna/edit.js.map +1 -0
  139. package/dist/dna/index.d.ts +24 -0
  140. package/dist/dna/index.d.ts.map +1 -0
  141. package/dist/dna/index.js +59 -0
  142. package/dist/dna/index.js.map +1 -0
  143. package/dist/dna/mutate.d.ts +74 -0
  144. package/dist/dna/mutate.d.ts.map +1 -0
  145. package/dist/dna/mutate.js +318 -0
  146. package/dist/dna/mutate.js.map +1 -0
  147. package/dist/dna/path.d.ts +175 -0
  148. package/dist/dna/path.d.ts.map +1 -0
  149. package/dist/dna/path.js +289 -0
  150. package/dist/dna/path.js.map +1 -0
  151. package/dist/dna/roles.d.ts +57 -0
  152. package/dist/dna/roles.d.ts.map +1 -0
  153. package/dist/dna/roles.js +50 -0
  154. package/dist/dna/roles.js.map +1 -0
  155. package/dist/dna/schema.d.ts +172 -0
  156. package/dist/dna/schema.d.ts.map +1 -0
  157. package/dist/dna/schema.js +182 -0
  158. package/dist/dna/schema.js.map +1 -0
  159. package/dist/dna/set.d.ts +145 -0
  160. package/dist/dna/set.d.ts.map +1 -0
  161. package/dist/dna/set.js +428 -0
  162. package/dist/dna/set.js.map +1 -0
  163. package/dist/mcp/dna-resource.d.ts +16 -0
  164. package/dist/mcp/dna-resource.d.ts.map +1 -0
  165. package/dist/mcp/dna-resource.js +56 -0
  166. package/dist/mcp/dna-resource.js.map +1 -0
  167. package/dist/mcp/index.d.ts +49 -0
  168. package/dist/mcp/index.d.ts.map +1 -0
  169. package/dist/mcp/index.js +60 -0
  170. package/dist/mcp/index.js.map +1 -0
  171. package/dist/mcp/memory-resource.d.ts +17 -0
  172. package/dist/mcp/memory-resource.d.ts.map +1 -0
  173. package/dist/mcp/memory-resource.js +133 -0
  174. package/dist/mcp/memory-resource.js.map +1 -0
  175. package/dist/mcp/prompt.d.ts +48 -0
  176. package/dist/mcp/prompt.d.ts.map +1 -0
  177. package/dist/mcp/prompt.js +176 -0
  178. package/dist/mcp/prompt.js.map +1 -0
  179. package/dist/mcp/read-only.d.ts +42 -0
  180. package/dist/mcp/read-only.d.ts.map +1 -0
  181. package/dist/mcp/read-only.js +93 -0
  182. package/dist/mcp/read-only.js.map +1 -0
  183. package/dist/mcp/registrar.d.ts +54 -0
  184. package/dist/mcp/registrar.d.ts.map +1 -0
  185. package/dist/mcp/registrar.js +72 -0
  186. package/dist/mcp/registrar.js.map +1 -0
  187. package/dist/mcp/server.d.ts +58 -0
  188. package/dist/mcp/server.d.ts.map +1 -0
  189. package/dist/mcp/server.js +64 -0
  190. package/dist/mcp/server.js.map +1 -0
  191. package/dist/mcp/workflow-resource.d.ts +17 -0
  192. package/dist/mcp/workflow-resource.d.ts.map +1 -0
  193. package/dist/mcp/workflow-resource.js +63 -0
  194. package/dist/mcp/workflow-resource.js.map +1 -0
  195. package/dist/memory/add.d.ts +50 -0
  196. package/dist/memory/add.d.ts.map +1 -0
  197. package/dist/memory/add.js +131 -0
  198. package/dist/memory/add.js.map +1 -0
  199. package/dist/memory/audit.d.ts +177 -0
  200. package/dist/memory/audit.d.ts.map +1 -0
  201. package/dist/memory/audit.js +287 -0
  202. package/dist/memory/audit.js.map +1 -0
  203. package/dist/memory/commit-message.d.ts +146 -0
  204. package/dist/memory/commit-message.d.ts.map +1 -0
  205. package/dist/memory/commit-message.js +203 -0
  206. package/dist/memory/commit-message.js.map +1 -0
  207. package/dist/memory/entry.d.ts +56 -0
  208. package/dist/memory/entry.d.ts.map +1 -0
  209. package/dist/memory/entry.js +28 -0
  210. package/dist/memory/entry.js.map +1 -0
  211. package/dist/memory/frontmatter-edit.d.ts +68 -0
  212. package/dist/memory/frontmatter-edit.d.ts.map +1 -0
  213. package/dist/memory/frontmatter-edit.js +333 -0
  214. package/dist/memory/frontmatter-edit.js.map +1 -0
  215. package/dist/memory/git-log.d.ts +32 -0
  216. package/dist/memory/git-log.d.ts.map +1 -0
  217. package/dist/memory/git-log.js +100 -0
  218. package/dist/memory/git-log.js.map +1 -0
  219. package/dist/memory/history.d.ts +142 -0
  220. package/dist/memory/history.d.ts.map +1 -0
  221. package/dist/memory/history.js +250 -0
  222. package/dist/memory/history.js.map +1 -0
  223. package/dist/memory/index.d.ts +58 -0
  224. package/dist/memory/index.d.ts.map +1 -0
  225. package/dist/memory/index.js +107 -0
  226. package/dist/memory/index.js.map +1 -0
  227. package/dist/memory/query.d.ts +150 -0
  228. package/dist/memory/query.d.ts.map +1 -0
  229. package/dist/memory/query.js +307 -0
  230. package/dist/memory/query.js.map +1 -0
  231. package/dist/memory/reject.d.ts +11 -0
  232. package/dist/memory/reject.d.ts.map +1 -0
  233. package/dist/memory/reject.js +32 -0
  234. package/dist/memory/reject.js.map +1 -0
  235. package/dist/memory/schema.d.ts +104 -0
  236. package/dist/memory/schema.d.ts.map +1 -0
  237. package/dist/memory/schema.js +161 -0
  238. package/dist/memory/schema.js.map +1 -0
  239. package/dist/memory/state-machine.d.ts +166 -0
  240. package/dist/memory/state-machine.d.ts.map +1 -0
  241. package/dist/memory/state-machine.js +431 -0
  242. package/dist/memory/state-machine.js.map +1 -0
  243. package/dist/memory/submit.d.ts +11 -0
  244. package/dist/memory/submit.d.ts.map +1 -0
  245. package/dist/memory/submit.js +44 -0
  246. package/dist/memory/submit.js.map +1 -0
  247. package/dist/storage/builtin-directives.d.ts +54 -0
  248. package/dist/storage/builtin-directives.d.ts.map +1 -0
  249. package/dist/storage/builtin-directives.js +152 -0
  250. package/dist/storage/builtin-directives.js.map +1 -0
  251. package/dist/storage/commit.d.ts +92 -0
  252. package/dist/storage/commit.d.ts.map +1 -0
  253. package/dist/storage/commit.js +201 -0
  254. package/dist/storage/commit.js.map +1 -0
  255. package/dist/storage/confinement.d.ts +93 -0
  256. package/dist/storage/confinement.d.ts.map +1 -0
  257. package/dist/storage/confinement.js +164 -0
  258. package/dist/storage/confinement.js.map +1 -0
  259. package/dist/storage/document.d.ts +27 -0
  260. package/dist/storage/document.d.ts.map +1 -0
  261. package/dist/storage/document.js +52 -0
  262. package/dist/storage/document.js.map +1 -0
  263. package/dist/storage/errors.d.ts +36 -0
  264. package/dist/storage/errors.d.ts.map +1 -0
  265. package/dist/storage/errors.js +46 -0
  266. package/dist/storage/errors.js.map +1 -0
  267. package/dist/storage/frontmatter.d.ts +27 -0
  268. package/dist/storage/frontmatter.d.ts.map +1 -0
  269. package/dist/storage/frontmatter.js +37 -0
  270. package/dist/storage/frontmatter.js.map +1 -0
  271. package/dist/storage/git-root.d.ts +17 -0
  272. package/dist/storage/git-root.d.ts.map +1 -0
  273. package/dist/storage/git-root.js +49 -0
  274. package/dist/storage/git-root.js.map +1 -0
  275. package/dist/storage/index.d.ts +29 -0
  276. package/dist/storage/index.d.ts.map +1 -0
  277. package/dist/storage/index.js +66 -0
  278. package/dist/storage/index.js.map +1 -0
  279. package/dist/storage/init-state.d.ts +9 -0
  280. package/dist/storage/init-state.d.ts.map +1 -0
  281. package/dist/storage/init-state.js +24 -0
  282. package/dist/storage/init-state.js.map +1 -0
  283. package/dist/storage/layout.d.ts +51 -0
  284. package/dist/storage/layout.d.ts.map +1 -0
  285. package/dist/storage/layout.js +88 -0
  286. package/dist/storage/layout.js.map +1 -0
  287. package/dist/storage/memory-path.d.ts +72 -0
  288. package/dist/storage/memory-path.d.ts.map +1 -0
  289. package/dist/storage/memory-path.js +127 -0
  290. package/dist/storage/memory-path.js.map +1 -0
  291. package/dist/storage/snapshot.d.ts +16 -0
  292. package/dist/storage/snapshot.d.ts.map +1 -0
  293. package/dist/storage/snapshot.js +72 -0
  294. package/dist/storage/snapshot.js.map +1 -0
  295. package/dist/storage/templates.d.ts +88 -0
  296. package/dist/storage/templates.d.ts.map +1 -0
  297. package/dist/storage/templates.js +422 -0
  298. package/dist/storage/templates.js.map +1 -0
  299. package/dist/validation/error-mapper.d.ts +16 -0
  300. package/dist/validation/error-mapper.d.ts.map +1 -0
  301. package/dist/validation/error-mapper.js +18 -0
  302. package/dist/validation/error-mapper.js.map +1 -0
  303. package/dist/validation/errors.d.ts +69 -0
  304. package/dist/validation/errors.d.ts.map +1 -0
  305. package/dist/validation/errors.js +69 -0
  306. package/dist/validation/errors.js.map +1 -0
  307. package/dist/validation/id.d.ts +16 -0
  308. package/dist/validation/id.d.ts.map +1 -0
  309. package/dist/validation/id.js +177 -0
  310. package/dist/validation/id.js.map +1 -0
  311. package/dist/validation/index.d.ts +18 -0
  312. package/dist/validation/index.d.ts.map +1 -0
  313. package/dist/validation/index.js +37 -0
  314. package/dist/validation/index.js.map +1 -0
  315. package/dist/validation/secret-scan.d.ts +129 -0
  316. package/dist/validation/secret-scan.d.ts.map +1 -0
  317. package/dist/validation/secret-scan.js +367 -0
  318. package/dist/validation/secret-scan.js.map +1 -0
  319. package/dist/validation/two-pass.d.ts +24 -0
  320. package/dist/validation/two-pass.d.ts.map +1 -0
  321. package/dist/validation/two-pass.js +24 -0
  322. package/dist/validation/two-pass.js.map +1 -0
  323. package/dist/validation/warning.d.ts +31 -0
  324. package/dist/validation/warning.d.ts.map +1 -0
  325. package/dist/validation/warning.js +81 -0
  326. package/dist/validation/warning.js.map +1 -0
  327. package/dist/validation/yaml.d.ts +9 -0
  328. package/dist/validation/yaml.d.ts.map +1 -0
  329. package/dist/validation/yaml.js +30 -0
  330. package/dist/validation/yaml.js.map +1 -0
  331. package/dist/workflow/index.d.ts +10 -0
  332. package/dist/workflow/index.d.ts.map +1 -0
  333. package/dist/workflow/index.js +16 -0
  334. package/dist/workflow/index.js.map +1 -0
  335. package/dist/workflow/schema.d.ts +89 -0
  336. package/dist/workflow/schema.d.ts.map +1 -0
  337. package/dist/workflow/schema.js +73 -0
  338. package/dist/workflow/schema.js.map +1 -0
  339. package/package.json +78 -0
@@ -0,0 +1,318 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyDnaMutation = applyDnaMutation;
4
+ const path_1 = require("./path");
5
+ /** A refusal, in the one shape every branch below returns. */
6
+ function refuse(message) {
7
+ return { ok: false, message };
8
+ }
9
+ /** Deep-clone the document so no branch can leave a half-applied mutation behind on a refusal. */
10
+ function clone(dna) {
11
+ return structuredClone(dna);
12
+ }
13
+ /** Coerce one `--entry-<field>` option string into the shape the entry schema declares for it. */
14
+ function coerce(raw, kind) {
15
+ if (kind === 'string-list')
16
+ return splitList(raw);
17
+ if (kind === 'number') {
18
+ const parsed = Number(raw);
19
+ return Number.isFinite(parsed) ? parsed : raw;
20
+ }
21
+ if (kind === 'boolean') {
22
+ if (raw === 'true')
23
+ return true;
24
+ if (raw === 'false')
25
+ return false;
26
+ return raw;
27
+ }
28
+ return raw;
29
+ }
30
+ /**
31
+ * Split a comma-separated option value — the shape used **only** where the schema declares
32
+ * `z.array(z.string())` (`paths.*`, `team.members[].roles`, `team.agents[].executes_as`). The precedent
33
+ * is `directive assign --directive testing,code-quality` (`task-056-role-based-directive-assignment`),
34
+ * so the CLI has one comma convention rather than two.
35
+ */
36
+ function splitList(raw) {
37
+ return raw
38
+ .split(',')
39
+ .map((part) => part.trim())
40
+ .filter((part) => part.length > 0);
41
+ }
42
+ /** The text-edit path for a target, with every collection segment replaced by the entry's resolved index. */
43
+ function textPath(dna, target) {
44
+ const steps = [];
45
+ let node = dna;
46
+ for (const segment of target.segments) {
47
+ if (Array.isArray(node)) {
48
+ const index = node.findIndex((entry) => isRecord(entry) && entry.name === segment);
49
+ steps.push({ index });
50
+ node = node[index];
51
+ }
52
+ else {
53
+ steps.push({ key: segment });
54
+ node = isRecord(node) ? node[segment] : undefined;
55
+ }
56
+ }
57
+ return steps;
58
+ }
59
+ /** Whether `value` is a plain object (not null, not an array). */
60
+ function isRecord(value) {
61
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
62
+ }
63
+ /**
64
+ * The container a path's last segment lives in.
65
+ *
66
+ * A **declared but absent** object on the way is created — that is what lets
67
+ * `dna set project.license --value MIT` fill an optional section the document omits — and this is deliberately
68
+ * NOT the creation `bug-084` filed: every segment here has already been resolved against the schema by
69
+ * `resolveDnaPath`, so nothing the schema does not declare can reach this function. An existing array is
70
+ * descended into by entry name rather than replaced, which is exactly what the old traversal got wrong.
71
+ */
72
+ function containerFor(dna, segments) {
73
+ let node = dna;
74
+ for (let i = 0; i < segments.length - 1; i += 1) {
75
+ const segment = segments[i];
76
+ if (Array.isArray(node)) {
77
+ const index = node.findIndex((entry) => isRecord(entry) && entry.name === segment);
78
+ node = node[index];
79
+ continue;
80
+ }
81
+ const child = node[segment];
82
+ if (Array.isArray(child) || isRecord(child)) {
83
+ node = child;
84
+ continue;
85
+ }
86
+ const created = {};
87
+ node[segment] = created;
88
+ node = created;
89
+ }
90
+ return node;
91
+ }
92
+ /**
93
+ * Read the list at `segments`, or `[]` when the schema declares it and the document omits it — which
94
+ * is how `dna add paths.tests --value test/` fills a category the file leaves out.
95
+ *
96
+ * The container is always a MAPPING: a list is reached through a mapping key, either a section's
97
+ * (`paths.sources`) or an entry's (`team.members.<name>.roles`), never as an element of another list,
98
+ * because the schema declares no list of lists and `resolveDnaPath` refuses one if it ever does.
99
+ */
100
+ function listAt(dna, target) {
101
+ const container = containerFor(dna, target.segments);
102
+ const key = target.segments[target.segments.length - 1];
103
+ const current = container[key];
104
+ const items = Array.isArray(current) ? current : [];
105
+ container[key] = items;
106
+ return { key, items };
107
+ }
108
+ /** Apply `fields` to `entry`, refusing an option the collection's entry schema does not declare. */
109
+ function applyFields(entry, fields, declared, collectionPath) {
110
+ for (const name of Object.keys(fields)) {
111
+ if (name === 'name') {
112
+ return `'name' is an entry's identity, not a field to update: it is what the path '${collectionPath}.<name>' addresses. Remove the entry and add it under the new name.`;
113
+ }
114
+ const field = declared.find((candidate) => candidate.name === name);
115
+ if (field === undefined) {
116
+ const known = declared.filter((candidate) => candidate.name !== 'name').map((candidate) => `--${(0, path_1.dnaEntryOptionName)(candidate.name)}`);
117
+ return `'--${(0, path_1.dnaEntryOptionName)(name)}' is not a field of '${collectionPath}' entries; they carry ${known.join(', ')}`;
118
+ }
119
+ entry[name] = coerce(fields[name], field.kind);
120
+ }
121
+ return undefined;
122
+ }
123
+ /**
124
+ * Apply one `add`/`remove`/`update` to `dna`, returning the new document and the minimal text edit that
125
+ * expresses it — or a refusal message the caller reports at exit `1` (`spec-005` §1, as ruled on
126
+ * `bug-076`: a well-formed invocation that fails on the content is a logic error, not a usage error).
127
+ *
128
+ * Every refusal names what failed and, where there is one, the verb that would have worked — the whole
129
+ * point of `bug-083`'s repair is that `dna set team.members '[…]'` used to fail with
130
+ * `expected array, received string` from a schema re-validation, which says nothing about how to reach
131
+ * the field.
132
+ *
133
+ * `schemaRoot` is passed straight to `resolveDnaPath` and defaults to `DnaYaml` there — the only schema
134
+ * any caller uses. It is a parameter for the same reason: the semantics below are a function of *a*
135
+ * schema (which field kinds exist, which are required), so they stay exercisable against shapes
136
+ * `spec-002` does not declare today rather than resting on an untested claim.
137
+ */
138
+ function applyDnaMutation(dna, request, schemaRoot) {
139
+ const resolved = (0, path_1.resolveDnaPath)(dna, request.field, schemaRoot);
140
+ if (!resolved.ok)
141
+ return refuse(resolved.message);
142
+ const target = resolved.target;
143
+ const fields = request.fields ?? {};
144
+ const next = clone(dna);
145
+ switch (target.kind) {
146
+ case 'section':
147
+ return refuse(`'${request.field}' is a section of dna.yaml, not a field: name a field inside it (for example '${request.field}.<field>')`);
148
+ case 'collection':
149
+ return mutateCollection(next, target, request, fields);
150
+ case 'entry':
151
+ return mutateEntry(next, target, request, fields);
152
+ case 'string-list':
153
+ return mutateStringList(next, target, request);
154
+ case 'scalar':
155
+ return mutateScalar(next, target, request);
156
+ }
157
+ }
158
+ /** The path ends at an array of objects: `add` creates an entry, `remove` drops one, `update` amends one. */
159
+ function mutateCollection(next, target, request, fields) {
160
+ const name = request.value;
161
+ if (name === undefined || name.length === 0) {
162
+ return refuse(`--value is required at '${target.path}': it names the entry (dl-081: --value is the entry's identity at a collection)`);
163
+ }
164
+ const { items } = listAt(next, target);
165
+ const index = items.findIndex((entry) => isRecord(entry) && entry.name === name);
166
+ const declared = target.entryFields ?? [];
167
+ if (request.verb === 'add') {
168
+ if (index >= 0) {
169
+ return refuse(`'${target.path}' already carries an entry named '${name}' — entry names are unique (dl-081); use \`dna update\` to change it`);
170
+ }
171
+ const entry = { name };
172
+ const failure = applyFields(entry, fields, declared, target.path);
173
+ if (failure !== undefined)
174
+ return refuse(failure);
175
+ const missing = declared
176
+ .filter((field) => field.required && field.name !== 'name' && entry[field.name] === undefined)
177
+ .map((field) => `--${(0, path_1.dnaEntryOptionName)(field.name)}`);
178
+ if (missing.length > 0) {
179
+ return refuse(`an entry of '${target.path}' requires ${missing.join(', ')}`);
180
+ }
181
+ const ordered = orderBySchema(entry, declared);
182
+ items.push(ordered);
183
+ return { ok: true, dna: next, edit: { kind: 'append-items', path: textPath(next, target), items: [ordered] } };
184
+ }
185
+ if (index < 0) {
186
+ return refuse(`no entry named '${name}' in '${target.path}'`);
187
+ }
188
+ if (request.verb === 'remove') {
189
+ items.splice(index, 1);
190
+ return { ok: true, dna: next, edit: { kind: 'remove-items', path: textPath(next, target), indexes: [index] } };
191
+ }
192
+ if (Object.keys(fields).length === 0) {
193
+ const known = declared.filter((field) => field.name !== 'name').map((field) => `--${(0, path_1.dnaEntryOptionName)(field.name)}`);
194
+ return refuse(`\`dna update ${target.path} --value ${name}\` carries no change: pass one of ${known.join(', ')}`);
195
+ }
196
+ const entry = items[index];
197
+ const failure = applyFields(entry, fields, declared, target.path);
198
+ if (failure !== undefined)
199
+ return refuse(failure);
200
+ return { ok: true, dna: next, edit: entryFieldEdit(next, target, index, fields, declared) };
201
+ }
202
+ /** The path ends at one entry (`modules.core`): the path already says which, so `--value` would repeat it. */
203
+ function mutateEntry(next, target, request, fields) {
204
+ const collectionPath = target.collectionPath;
205
+ const name = target.segments[target.segments.length - 1];
206
+ if (request.verb === 'add') {
207
+ return refuse(`'${target.path}' already exists: \`dna add ${collectionPath} --value <name>\` creates a new entry, \`dna update\` changes this one`);
208
+ }
209
+ if (request.value !== undefined) {
210
+ return refuse(`--value says nothing the path '${target.path}' has not already said: drop it, or address the collection with \`${collectionPath} --value ${name}\``);
211
+ }
212
+ // The collection resolved on the way to the entry, so this re-resolution against the clone cannot
213
+ // fail; it is done rather than threaded through because the clone's array is a different object.
214
+ const collection = (0, path_1.resolveDnaPath)(next, collectionPath);
215
+ if (!collection.ok)
216
+ return refuse(collection.message);
217
+ const { items } = listAt(next, collection.target);
218
+ const index = target.entryIndex;
219
+ if (request.verb === 'remove') {
220
+ items.splice(index, 1);
221
+ return { ok: true, dna: next, edit: { kind: 'remove-items', path: textPath(next, collection.target), indexes: [index] } };
222
+ }
223
+ const declared = target.entryFields ?? [];
224
+ if (Object.keys(fields).length === 0) {
225
+ const known = declared.filter((field) => field.name !== 'name').map((field) => `--${(0, path_1.dnaEntryOptionName)(field.name)}`);
226
+ return refuse(`\`dna update ${target.path}\` carries no change: pass one of ${known.join(', ')}`);
227
+ }
228
+ const entry = items[index];
229
+ const failure = applyFields(entry, fields, declared, collectionPath);
230
+ if (failure !== undefined)
231
+ return refuse(failure);
232
+ return { ok: true, dna: next, edit: entryFieldEdit(next, collection.target, index, fields, declared) };
233
+ }
234
+ /** The path ends at an array of strings: `add` appends, `remove` drops, `update` replaces the list. */
235
+ function mutateStringList(next, target, request) {
236
+ if (request.value === undefined) {
237
+ return refuse(`--value is required at '${target.path}'`);
238
+ }
239
+ const values = splitList(request.value);
240
+ if (values.length === 0) {
241
+ return refuse(`--value is required at '${target.path}'`);
242
+ }
243
+ const { items } = listAt(next, target);
244
+ const path = textPath(next, target);
245
+ if (request.verb === 'update') {
246
+ items.splice(0, items.length, ...values);
247
+ return { ok: true, dna: next, edit: { kind: 'replace-list', path, items: values } };
248
+ }
249
+ if (request.verb === 'add') {
250
+ for (const value of values) {
251
+ if (items.includes(value))
252
+ return refuse(`'${target.path}' already contains '${value}'`);
253
+ }
254
+ items.push(...values);
255
+ return { ok: true, dna: next, edit: { kind: 'append-items', path, items: values } };
256
+ }
257
+ const indexes = [];
258
+ for (const value of values) {
259
+ const index = items.indexOf(value);
260
+ if (index < 0)
261
+ return refuse(`'${target.path}' does not contain '${value}'`);
262
+ indexes.push(index);
263
+ }
264
+ const removed = new Set(indexes);
265
+ const kept = items.filter((_item, index) => !removed.has(index));
266
+ items.splice(0, items.length, ...kept);
267
+ return { ok: true, dna: next, edit: { kind: 'remove-items', path, indexes: [...indexes].sort((a, b) => a - b) } };
268
+ }
269
+ /** The path ends at a single value: `update` writes it, `remove` drops it when the schema allows, `add` does not apply. */
270
+ function mutateScalar(next, target, request) {
271
+ const key = target.segments[target.segments.length - 1];
272
+ const container = containerFor(next, target.segments);
273
+ if (request.verb === 'add') {
274
+ return refuse(`'${target.path}' holds a single value: use \`dna update ${target.path} --value <v>\` (or \`dna set ${target.path} --value <v>\`)`);
275
+ }
276
+ if (request.verb === 'remove') {
277
+ if (target.required) {
278
+ return refuse(`'${target.path}' is required by the dna.yaml schema and cannot be removed`);
279
+ }
280
+ if (!(key in container)) {
281
+ return refuse(`'${target.path}' is not set, so there is nothing to remove`);
282
+ }
283
+ delete container[key];
284
+ return { ok: true, dna: next, edit: { kind: 'delete-key', path: textPath(next, target) } };
285
+ }
286
+ if (request.value === undefined) {
287
+ return refuse(`--value is required at '${target.path}'`);
288
+ }
289
+ container[key] = request.value;
290
+ return { ok: true, dna: next, edit: { kind: 'set-scalar', path: textPath(next, target), value: request.value } };
291
+ }
292
+ /** Rewrite an entry's keys into schema order, so the same call always renders the same bytes (REQ-SYS-07). */
293
+ function orderBySchema(entry, declared) {
294
+ const ordered = {};
295
+ for (const field of declared) {
296
+ if (entry[field.name] !== undefined)
297
+ ordered[field.name] = entry[field.name];
298
+ }
299
+ for (const key of Object.keys(entry)) {
300
+ if (ordered[key] === undefined)
301
+ ordered[key] = entry[key];
302
+ }
303
+ return ordered;
304
+ }
305
+ /** One `set-scalar` per changed entry field, batched — the text editor applies them in order. */
306
+ function entryFieldEdit(dna, collection, index, fields, declared) {
307
+ const base = [...textPath(dna, collection), { index }];
308
+ const edits = Object.keys(fields).map((name) => {
309
+ const field = declared.find((candidate) => candidate.name === name);
310
+ return {
311
+ kind: 'set-scalar',
312
+ path: [...base, { key: name }],
313
+ value: coerce(fields[name], field?.kind ?? 'string'),
314
+ };
315
+ });
316
+ return edits.length === 1 ? edits[0] : { kind: 'batch', edits };
317
+ }
318
+ //# sourceMappingURL=mutate.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mutate.js","sourceRoot":"","sources":["../../src/dna/mutate.ts"],"names":[],"mappings":";;AAyMA,4CA0BC;AA9LD,iCAAoG;AAqBpG,8DAA8D;AAC9D,SAAS,MAAM,CAAC,OAAe;IAC7B,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,CAAC;AAChC,CAAC;AAED,kGAAkG;AAClG,SAAS,KAAK,CAAC,GAA4B;IACzC,OAAO,eAAe,CAAC,GAAG,CAAC,CAAC;AAC9B,CAAC;AAED,kGAAkG;AAClG,SAAS,MAAM,CAAC,GAAW,EAAE,IAA2B;IACtD,IAAI,IAAI,KAAK,aAAa;QAAE,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;IAClD,IAAI,IAAI,KAAK,QAAQ,EAAE,CAAC;QACtB,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,CAAC;QAC3B,OAAO,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC;IAChD,CAAC;IACD,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;QACvB,IAAI,GAAG,KAAK,MAAM;YAAE,OAAO,IAAI,CAAC;QAChC,IAAI,GAAG,KAAK,OAAO;YAAE,OAAO,KAAK,CAAC;QAClC,OAAO,GAAG,CAAC;IACb,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED;;;;;GAKG;AACH,SAAS,SAAS,CAAC,GAAW;IAC5B,OAAO,GAAG;SACP,KAAK,CAAC,GAAG,CAAC;SACV,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;SAC1B,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;AACvC,CAAC;AAED,6GAA6G;AAC7G,SAAS,QAAQ,CAAC,GAA4B,EAAE,MAAqB;IACnE,MAAM,KAAK,GAAkB,EAAE,CAAC;IAChC,IAAI,IAAI,GAAY,GAAG,CAAC;IACxB,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;QACtC,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YACnF,KAAK,CAAC,IAAI,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC;YACtB,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC;QACrB,CAAC;aAAM,CAAC;YACN,KAAK,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;YAC7B,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACpD,CAAC;IACH,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,kEAAkE;AAClE,SAAS,QAAQ,CAAC,KAAc;IAC9B,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED;;;;;;;;GAQG;AACH,SAAS,YAAY,CAAC,GAA4B,EAAE,QAA2B;IAC7E,IAAI,IAAI,GAAwC,GAAG,CAAC;IACpD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,QAAQ,CAAC,CAAC,CAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,CAAC,CAAC;YACnF,IAAI,GAAG,IAAI,CAAC,KAAK,CAA4B,CAAC;YAC9C,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,CAAC;QAC5B,IAAI,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;YAC5C,IAAI,GAAG,KAA4C,CAAC;YACpD,SAAS;QACX,CAAC;QACD,MAAM,OAAO,GAA4B,EAAE,CAAC;QAC5C,IAAI,CAAC,OAAO,CAAC,GAAG,OAAO,CAAC;QACxB,IAAI,GAAG,OAAO,CAAC;IACjB,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;;;GAOG;AACH,SAAS,MAAM,CAAC,GAA4B,EAAE,MAAqB;IACjE,MAAM,SAAS,GAAG,YAAY,CAAC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAA4B,CAAC;IAChF,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IACzD,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,CAAC;IAC/B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC;IACpD,SAAS,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC;IACvB,OAAO,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AACxB,CAAC;AAED,oGAAoG;AACpG,SAAS,WAAW,CAClB,KAA8B,EAC9B,MAAwC,EACxC,QAAkC,EAClC,cAAsB;IAEtB,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QACvC,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,OAAO,8EAA8E,cAAc,qEAAqE,CAAC;QAC3K,CAAC;QACD,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACpE,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;YACxB,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,KAAK,IAAA,yBAAkB,EAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACtI,OAAO,MAAM,IAAA,yBAAkB,EAAC,IAAI,CAAC,wBAAwB,cAAc,yBAAyB,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC;QACzH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,IAAI,CAAE,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;IAClD,CAAC;IACD,OAAO,SAAS,CAAC;AACnB,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAgB,gBAAgB,CAC9B,GAA4B,EAC5B,OAA2B,EAC3B,UAAsB;IAEtB,MAAM,QAAQ,GAAG,IAAA,qBAAc,EAAC,GAAG,EAAE,OAAO,CAAC,KAAK,EAAE,UAAU,CAAC,CAAC;IAChE,IAAI,CAAC,QAAQ,CAAC,EAAE;QAAE,OAAO,MAAM,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;IAElD,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,CAAC;IAC/B,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,EAAE,CAAC;IACpC,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAExB,QAAQ,MAAM,CAAC,IAAI,EAAE,CAAC;QACpB,KAAK,SAAS;YACZ,OAAO,MAAM,CACX,IAAI,OAAO,CAAC,KAAK,iFAAiF,OAAO,CAAC,KAAK,YAAY,CAC5H,CAAC;QACJ,KAAK,YAAY;YACf,OAAO,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACzD,KAAK,OAAO;YACV,OAAO,WAAW,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,CAAC,CAAC;QACpD,KAAK,aAAa;YAChB,OAAO,gBAAgB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;QACjD,KAAK,QAAQ;YACX,OAAO,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,CAAC,CAAC;IAC/C,CAAC;AACH,CAAC;AAED,6GAA6G;AAC7G,SAAS,gBAAgB,CACvB,IAA6B,EAC7B,MAAqB,EACrB,OAA2B,EAC3B,MAAwC;IAExC,MAAM,IAAI,GAAG,OAAO,CAAC,KAAK,CAAC;IAC3B,IAAI,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAC5C,OAAO,MAAM,CAAC,2BAA2B,MAAM,CAAC,IAAI,iFAAiF,CAAC,CAAC;IACzI,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,KAAK,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;IACjF,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAE1C,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,IAAI,KAAK,IAAI,CAAC,EAAE,CAAC;YACf,OAAO,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,qCAAqC,IAAI,sEAAsE,CAAC,CAAC;QAChJ,CAAC;QACD,MAAM,KAAK,GAA4B,EAAE,IAAI,EAAE,CAAC;QAChD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;QAClE,IAAI,OAAO,KAAK,SAAS;YAAE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;QAClD,MAAM,OAAO,GAAG,QAAQ;aACrB,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS,CAAC;aAC7F,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAA,yBAAkB,EAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACzD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACvB,OAAO,MAAM,CAAC,gBAAgB,MAAM,CAAC,IAAI,cAAc,OAAO,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,OAAO,GAAG,aAAa,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC/C,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QACpB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC,OAAO,CAAC,EAAE,EAAE,CAAC;IACjH,CAAC;IAED,IAAI,KAAK,GAAG,CAAC,EAAE,CAAC;QACd,OAAO,MAAM,CAAC,mBAAmB,IAAI,SAAS,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAChE,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IACjH,CAAC;IAED,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAA,yBAAkB,EAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtH,OAAO,MAAM,CAAC,gBAAgB,MAAM,CAAC,IAAI,YAAY,IAAI,qCAAqC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpH,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAA4B,CAAC;IACtD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,CAAC,IAAI,CAAC,CAAC;IAClE,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;IAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;AAC9F,CAAC;AAED,8GAA8G;AAC9G,SAAS,WAAW,CAClB,IAA6B,EAC7B,MAAqB,EACrB,OAA2B,EAC3B,MAAwC;IAExC,MAAM,cAAc,GAAG,MAAM,CAAC,cAAe,CAAC;IAC9C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IAC1D,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,+BAA+B,cAAc,wEAAwE,CAAC,CAAC;IACtJ,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,kCAAkC,MAAM,CAAC,IAAI,qEAAqE,cAAc,YAAY,IAAI,IAAI,CAAC,CAAC;IACtK,CAAC;IAED,kGAAkG;IAClG,iGAAiG;IACjG,MAAM,UAAU,GAAG,IAAA,qBAAc,EAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IACxD,IAAI,CAAC,UAAU,CAAC,EAAE;QAAE,OAAO,MAAM,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC;IACtD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,MAAM,CAAC,UAAW,CAAC;IAEjC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC;QACvB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,CAAC,KAAK,CAAC,EAAE,EAAE,CAAC;IAC5H,CAAC;IAED,MAAM,QAAQ,GAAG,MAAM,CAAC,WAAW,IAAI,EAAE,CAAC;IAC1C,IAAI,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrC,MAAM,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,IAAA,yBAAkB,EAAC,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACtH,OAAO,MAAM,CAAC,gBAAgB,MAAM,CAAC,IAAI,qCAAqC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACpG,CAAC;IACD,MAAM,KAAK,GAAG,KAAK,CAAC,KAAK,CAA4B,CAAC;IACtD,MAAM,OAAO,GAAG,WAAW,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,cAAc,CAAC,CAAC;IACrE,IAAI,OAAO,KAAK,SAAS;QAAE,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC;IAClD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,cAAc,CAAC,IAAI,EAAE,UAAU,CAAC,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,CAAC;AACzG,CAAC;AAED,uGAAuG;AACvG,SAAS,gBAAgB,CAAC,IAA6B,EAAE,MAAqB,EAAE,OAA2B;IACzG,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,2BAA2B,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,MAAM,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;IACxC,IAAI,MAAM,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACxB,OAAO,MAAM,CAAC,2BAA2B,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAC3D,CAAC;IACD,MAAM,EAAE,KAAK,EAAE,GAAG,MAAM,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IACvC,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAEpC,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,MAAM,CAAC,CAAC;QACzC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IACtF,CAAC;IAED,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;YAC3B,IAAI,KAAK,CAAC,QAAQ,CAAC,KAAK,CAAC;gBAAE,OAAO,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,uBAAuB,KAAK,GAAG,CAAC,CAAC;QAC3F,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC;IACtF,CAAC;IAED,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,MAAM,KAAK,GAAG,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QACnC,IAAI,KAAK,GAAG,CAAC;YAAE,OAAO,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,uBAAuB,KAAK,GAAG,CAAC,CAAC;QAC7E,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACtB,CAAC;IACD,MAAM,OAAO,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;IACjC,MAAM,IAAI,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,CAAC;IACjE,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,EAAE,GAAG,IAAI,CAAC,CAAC;IACvC,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,cAAc,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAG,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC;AACpH,CAAC;AAED,2HAA2H;AAC3H,SAAS,YAAY,CAAC,IAA6B,EAAE,MAAqB,EAAE,OAA2B;IACrG,MAAM,GAAG,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,CAAE,CAAC;IACzD,MAAM,SAAS,GAAG,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,QAAQ,CAA4B,CAAC;IAEjF,IAAI,OAAO,CAAC,IAAI,KAAK,KAAK,EAAE,CAAC;QAC3B,OAAO,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,4CAA4C,MAAM,CAAC,IAAI,gCAAgC,MAAM,CAAC,IAAI,iBAAiB,CAAC,CAAC;IACpJ,CAAC;IACD,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;QAC9B,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACpB,OAAO,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,4DAA4D,CAAC,CAAC;QAC7F,CAAC;QACD,IAAI,CAAC,CAAC,GAAG,IAAI,SAAS,CAAC,EAAE,CAAC;YACxB,OAAO,MAAM,CAAC,IAAI,MAAM,CAAC,IAAI,6CAA6C,CAAC,CAAC;QAC9E,CAAC;QACD,OAAO,SAAS,CAAC,GAAG,CAAC,CAAC;QACtB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC;IAC7F,CAAC;IACD,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS,EAAE,CAAC;QAChC,OAAO,MAAM,CAAC,2BAA2B,MAAM,CAAC,IAAI,GAAG,CAAC,CAAC;IAC3D,CAAC;IACD,SAAS,CAAC,GAAG,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC;IAC/B,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,EAAE,IAAI,EAAE,YAAY,EAAE,IAAI,EAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;AACnH,CAAC;AAED,8GAA8G;AAC9G,SAAS,aAAa,CAAC,KAA8B,EAAE,QAAkC;IACvF,MAAM,OAAO,GAA4B,EAAE,CAAC;IAC5C,KAAK,MAAM,KAAK,IAAI,QAAQ,EAAE,CAAC;QAC7B,IAAI,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;IAC/E,CAAC;IACD,KAAK,MAAM,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC;QACrC,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,SAAS;YAAE,OAAO,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC;IAC5D,CAAC;IACD,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,iGAAiG;AACjG,SAAS,cAAc,CACrB,GAA4B,EAC5B,UAAyB,EACzB,KAAa,EACb,MAAwC,EACxC,QAAkC;IAElC,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,GAAG,EAAE,UAAU,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;IACvD,MAAM,KAAK,GAAkB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QAC5D,MAAM,KAAK,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,SAAS,EAAE,EAAE,CAAC,SAAS,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;QACpE,OAAO;YACL,IAAI,EAAE,YAAqB;YAC3B,IAAI,EAAE,CAAC,GAAG,IAAI,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,CAAC;YAC9B,KAAK,EAAE,MAAM,CAAC,MAAM,CAAC,IAAI,CAAE,EAAE,KAAK,EAAE,IAAI,IAAI,QAAQ,CAAC;SACtD,CAAC;IACJ,CAAC,CAAC,CAAC;IACH,OAAO,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC;AACnE,CAAC"}
@@ -0,0 +1,175 @@
1
+ /**
2
+ * Schema-driven DNA path resolution — the single traversal every DNA **write** goes through
3
+ * (`dna set`, and `dna add|remove|update` since task-093-dna-mutation-surface-add-remove-update).
4
+ *
5
+ * It exists because the previous traversal had no notion of the schema at all: `setDnaValue` walked a
6
+ * dotted path treating every segment as an object key and **created** an object for any segment it
7
+ * could not descend into, so `dna set tech_stack.cli.framework Commander` (the then-current spelling,
8
+ * before `dl-082` moved the value into `--value`) wrote `stacks.cli.framework`
9
+ * — a key no schema declares — and committed it at exit `0`
10
+ * (`bug-084-dna-key-alias-writes-unschemad-keys`). `dl-081-dna-mutation-surface-shape`'s ratification
11
+ * makes the repair a **precondition** of the mutation surface rather than a follow-up to it: under
12
+ * add/remove/update semantics one cannot add to a collection that does not exist, so the traversal
13
+ * must be structure-aware and non-creating.
14
+ *
15
+ * The rule it implements, in the ratification's own words: **the DNA pillar accepts unknown keys when
16
+ * reading a document and refuses to write one.** Pass-through on read stays exactly as
17
+ * `spec-002-dna-yaml-schema` declares it (every node is `.passthrough()`, so a file written by a newer
18
+ * WingFoil still loads); it is the write side that is closed.
19
+ *
20
+ * Two further properties this module owns:
21
+ *
22
+ * - **Entries are addressed by `name`, never by index** (`dl-081`, settled in its approve commit).
23
+ * `team.members.roberto.roles` reaches one member's role list; `team.members.2.roles` does not
24
+ * resolve at all, because an index shifts the moment an entry is removed and a path written today
25
+ * would address a different entry tomorrow.
26
+ * - **A path segment may be quoted, and a quoted segment is taken verbatim, dots included**
27
+ * (`dl-083-dotted-entry-names-in-paths`, task-099). `stacks.technologies."Node.js".version`
28
+ * addresses the entry named `Node.js` — a name this repository's own `dna.yaml` carries, along with
29
+ * `Commander.js` and `AI agent (Claude/Cursor/etc.)`, which is why the alternative of forbidding
30
+ * dots in `name` was declined. The grammar lives in `splitDnaPath` (`./set.ts`); this module is one
31
+ * of its three callers and adds nothing to it.
32
+ * - **The schema is the only source of truth.** The traversal reads `DnaYaml` itself (Zod v4 exposes
33
+ * `def.shape` / `def.element` / `def.innerType`, and does so through `.passthrough()` and
34
+ * `.superRefine()` alike), never a hand-written field table, so the write surface cannot drift from
35
+ * the schema it writes as `spec-002` evolves.
36
+ *
37
+ * Pure and deterministic (REQ-SYS-07): no wall-clock, no randomness, no filesystem, and the document
38
+ * it is handed is never mutated — on a refusal as much as on a success.
39
+ */
40
+ import type { z } from 'zod';
41
+ /**
42
+ * The prefix every schema-derived entry-field option carries: `--entry-<field>`, spelled with the
43
+ * schema's own field name (`--entry-executes_as`, not `--entry-executes-as`).
44
+ *
45
+ * It exists because the option set is **derived** — `dnaEntryOptionNames()` reads `spec-002`'s entry
46
+ * schemas — while the global flags are **declared** (`spec-008` §2), and the two namespaces had no
47
+ * reason to stay disjoint. They did not: `TechEntry` declares `version`, so
48
+ * `dna add stacks.technologies --value Zod --category validation --version 4.0` reached Commander's
49
+ * program-level `-V, --version`, printed the CLI version, exited `0` and wrote nothing, while
50
+ * `--help` advertised the option as working. Measured on a real `wingfoil init` project.
51
+ *
52
+ * **It is not a `version` problem.** Driving a synthetic Commander tree with one subcommand option per
53
+ * global flag shows three distinct outcomes, two of them silent: `--version` fires the program's own
54
+ * action and exits; `--format` and `--verbose` are swallowed by the program-level option and simply
55
+ * do not appear in the subcommand's parsed options; `--color` and a non-colliding name survive. So
56
+ * the failure mode is "the value vanishes", and any future entry field named after any current or
57
+ * future global flag inherits it.
58
+ *
59
+ * **What an unprefixed spelling therefore does, which is two different things.** A name §2 does not
60
+ * declare (`--category`, `--email`) is refused by Commander as an unknown option, exit `1`. A name §2
61
+ * DOES declare — today exactly one, `version`, which is the whole overlap between the derived set and
62
+ * the global set — is consumed by the global instead and is never reported: that is the silent no-op
63
+ * above. `spec-008` §9's option row states both halves, because stating only the first is a claim
64
+ * that is false for the very field the section uses as its example.
65
+ *
66
+ * **Why a prefix rather than refusing to register a shadowing name.** Refusal trades a silent failure
67
+ * for a loud hole: `version` is a field `spec-002` declares on `TechEntry`, so refusing it would make
68
+ * a schema-declared field permanently unwritable, and `dl-081` ratified a surface that reaches every
69
+ * collection. Refusal is also unstable in the wrong direction — the global set can grow (`spec-008`
70
+ * §2 is amendable), and a new global flag would then retroactively disable an entry field that had
71
+ * been writable, breaking scripts with no code change nearby. A prefix removes the collision **by
72
+ * construction**, for every present and future name on both sides, and it is uniform rather than
73
+ * conditional: a rule that prefixed only the colliding names would make an option's spelling depend
74
+ * on a table declared elsewhere, so adding a global flag later would silently RENAME an existing
75
+ * option. `test/cli/derived-option-namespace.test.ts` holds the invariant that keeps this true,
76
+ * derived from the built program rather than from a hand-listed copy of `spec-008` §2.
77
+ */
78
+ export declare const DNA_ENTRY_OPTION_PREFIX: "entry-";
79
+ /** The CLI/MCP option name carrying one entry field — the single place the prefix is applied. */
80
+ export declare function dnaEntryOptionName(field: string): string;
81
+ /** The entry field an option name carries, or `undefined` when it is not an entry-field option. */
82
+ export declare function dnaEntryFieldOfOption(option: string): string | undefined;
83
+ /** The kind of node a resolved path lands on — what a verb is allowed to do there. */
84
+ export type DnaTargetKind =
85
+ /** An object node (`project`, `team`, `paths`): a section, not a writable field. */
86
+ 'section'
87
+ /** A single value (`project.license`, `modules.core.path`, `version`). */
88
+ | 'scalar'
89
+ /** An array of strings (`paths.sources`, `team.members.<name>.roles`). */
90
+ | 'string-list'
91
+ /** An array of objects (`modules`, `team.members`, `stacks.technologies`). */
92
+ | 'collection'
93
+ /** One element of a collection, addressed by its `name`. */
94
+ | 'entry';
95
+ /** The value shape of one field declared on a collection's entry object. */
96
+ export type DnaFieldKind = 'string' | 'number' | 'boolean' | 'string-list' | 'other';
97
+ /** One field a collection's entries may carry, as the schema declares it (used to build the CLI options). */
98
+ export interface DnaEntryField {
99
+ readonly name: string;
100
+ readonly kind: DnaFieldKind;
101
+ readonly required: boolean;
102
+ }
103
+ /** Where a dotted path landed: what kind of node, what is there today, and what may be written into it. */
104
+ export interface DnaPathTarget {
105
+ readonly kind: DnaTargetKind;
106
+ /** The path as given (paths are never rewritten — see {@link DNA_KEY_ALIASES}'s note in `./set.ts`). */
107
+ readonly path: string;
108
+ /**
109
+ * `path` parsed by `splitDnaPath`; for an `entry`, the last segment is the entry's `name`. A quoted
110
+ * segment contributes its name **without** the delimiters and with its dots intact, so
111
+ * `stacks.technologies."Node.js".version` yields four segments, not five (`dl-083`, task-099).
112
+ */
113
+ readonly segments: readonly string[];
114
+ /** The value in the document at this path, or `undefined` when the node is declared but absent. */
115
+ readonly value: unknown;
116
+ /** Whether the node is actually present in the document (a declared-but-absent node resolves with `false`). */
117
+ readonly exists: boolean;
118
+ /** Whether the schema requires this node (`kind: 'scalar'`/`'string-list'`) — i.e. whether it may be removed. */
119
+ readonly required?: boolean;
120
+ /** The entry's index inside its collection (`kind: 'entry'`). */
121
+ readonly entryIndex?: number;
122
+ /** The fields the entries of this collection may carry, in schema order (`kind: 'collection'` or `'entry'`). */
123
+ readonly entryFields?: readonly DnaEntryField[];
124
+ /** The path of the collection an `entry` belongs to (`kind: 'entry'`). */
125
+ readonly collectionPath?: string;
126
+ }
127
+ /** A resolved target, or the refusal message the caller reports at exit `1` (`spec-005` §1). */
128
+ export type DnaPathResolution = {
129
+ readonly ok: true;
130
+ readonly target: DnaPathTarget;
131
+ } | {
132
+ readonly ok: false;
133
+ readonly message: string;
134
+ };
135
+ /**
136
+ * Resolve `keyPath` against `DnaYaml` and `dna`, reporting what a verb may do at the end of it.
137
+ *
138
+ * Every refusal names the **full** path (so an error message is greppable against the invocation) and
139
+ * the part of it that failed. The four refusal families:
140
+ *
141
+ * - a segment the schema does not declare — `bug-084`, the reason this module exists;
142
+ * - a path that tries to descend through a value or through a list of values;
143
+ * - an index where an entry `name` is expected (`dl-081`: indices are not the addressing form);
144
+ * - an entry `name` the collection does not carry, or carries more than once. The second is
145
+ * unreachable through any CLI/MCP path once `DnaYaml`'s per-collection uniqueness refinement is in
146
+ * force (a duplicate-bearing document no longer loads), and is kept because this function is a pure
147
+ * helper that can be handed any object — including, in a test, one that never went through the
148
+ * loader.
149
+ *
150
+ * A **declared but absent** node is not a refusal: it resolves with `exists: false`, which is what lets
151
+ * `dna set project.license --value MIT` fill an optional section the document happens to omit. That is the
152
+ * precise line `bug-084` draws — creating a node the schema declares is legitimate; inventing one it
153
+ * does not declare is the defect.
154
+ *
155
+ * `schemaRoot` defaults to `DnaYaml` — the only schema any caller passes — and is a parameter because
156
+ * the traversal is a function of *a* schema and a document, not of this one: it keeps the
157
+ * "addressable shape" rules (which node kinds a path may end on, which it may descend through)
158
+ * testable against shapes `spec-002` does not declare today, rather than leaving them as assertions
159
+ * nothing exercises.
160
+ */
161
+ export declare function resolveDnaPath(dna: unknown, keyPath: string, schemaRoot?: z.ZodType): DnaPathResolution;
162
+ /**
163
+ * Every collection `DnaYaml` declares, as a dotted path — derived from the schema, in a fixed order
164
+ * (REQ-SYS-07). Used to build the union of `--<entry-field>` options the mutation verbs accept and to
165
+ * document the surface in `--help`; nothing here is hand-listed, so a collection added to `spec-002`
166
+ * becomes addressable without touching this module.
167
+ */
168
+ export declare function dnaCollectionPaths(): readonly string[];
169
+ /**
170
+ * The union of every field name the entries of every collection may carry, minus `name` (which travels
171
+ * in `--value`, per `dl-081`'s `--value`-is-the-identity convention), in a fixed order. This is the
172
+ * `--entry-<field>` option set `dna add`/`dna update` register on both surfaces (see {@link dnaEntryOptionName}).
173
+ */
174
+ export declare function dnaEntryOptionNames(): readonly string[];
175
+ //# sourceMappingURL=path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"path.d.ts","sourceRoot":"","sources":["../../src/dna/path.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAK7B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,eAAO,MAAM,uBAAuB,EAAG,QAAiB,CAAC;AAEzD,iGAAiG;AACjG,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,mGAAmG;AACnG,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAExE;AAED,sFAAsF;AACtF,MAAM,MAAM,aAAa;AACvB,oFAAoF;AAClF,SAAS;AACX,0EAA0E;GACxE,QAAQ;AACV,0EAA0E;GACxE,aAAa;AACf,8EAA8E;GAC5E,YAAY;AACd,4DAA4D;GAC1D,OAAO,CAAC;AAEZ,4EAA4E;AAC5E,MAAM,MAAM,YAAY,GAAG,QAAQ,GAAG,QAAQ,GAAG,SAAS,GAAG,aAAa,GAAG,OAAO,CAAC;AAErF,6GAA6G;AAC7G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,YAAY,CAAC;IAC5B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;CAC5B;AAED,2GAA2G;AAC3G,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,aAAa,CAAC;IAC7B,wGAAwG;IACxG,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB;;;;OAIG;IACH,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IACrC,mGAAmG;IACnG,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IACxB,+GAA+G;IAC/G,QAAQ,CAAC,MAAM,EAAE,OAAO,CAAC;IACzB,iHAAiH;IACjH,QAAQ,CAAC,QAAQ,CAAC,EAAE,OAAO,CAAC;IAC5B,iEAAiE;IACjE,QAAQ,CAAC,UAAU,CAAC,EAAE,MAAM,CAAC;IAC7B,gHAAgH;IAChH,QAAQ,CAAC,WAAW,CAAC,EAAE,SAAS,aAAa,EAAE,CAAC;IAChD,0EAA0E;IAC1E,QAAQ,CAAC,cAAc,CAAC,EAAE,MAAM,CAAC;CAClC;AAED,gGAAgG;AAChG,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,IAAI,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,aAAa,CAAA;CAAE,GAAG;IAAE,QAAQ,CAAC,EAAE,EAAE,KAAK,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AAsFzI;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,OAAO,EAAE,OAAO,EAAE,MAAM,EAAE,UAAU,GAAE,CAAC,CAAC,OAAiB,GAAG,iBAAiB,CA2FhH;AAOD;;;;;GAKG;AACH,wBAAgB,kBAAkB,IAAI,SAAS,MAAM,EAAE,CActD;AAED;;;;GAIG;AACH,wBAAgB,mBAAmB,IAAI,SAAS,MAAM,EAAE,CAavD"}