agent-nuvira 3.3.1 → 3.3.4

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 (466) hide show
  1. package/README.md +18 -13
  2. package/dist/agent-sdk/src/agent.d.ts +2 -0
  3. package/dist/agent-sdk/src/agent.d.ts.map +1 -1
  4. package/dist/agent-sdk/src/define.d.ts +64 -0
  5. package/dist/agent-sdk/src/define.d.ts.map +1 -0
  6. package/dist/agent-sdk/src/define.js +76 -0
  7. package/dist/agent-sdk/src/define.js.map +1 -0
  8. package/dist/agent-sdk/src/index.d.ts +9 -0
  9. package/dist/agent-sdk/src/index.d.ts.map +1 -1
  10. package/dist/agent-sdk/src/index.js +9 -0
  11. package/dist/agent-sdk/src/index.js.map +1 -1
  12. package/dist/agent-sdk/src/scaffold.d.ts +11 -0
  13. package/dist/agent-sdk/src/scaffold.d.ts.map +1 -1
  14. package/dist/agent-sdk/src/scaffold.js +16 -6
  15. package/dist/agent-sdk/src/scaffold.js.map +1 -1
  16. package/dist/agents/agents/runner.d.ts +9 -0
  17. package/dist/agents/agents/runner.d.ts.map +1 -1
  18. package/dist/agents/agents/runner.js +34 -12
  19. package/dist/agents/agents/runner.js.map +1 -1
  20. package/dist/agents/agents/writer-tool-calling.d.ts.map +1 -1
  21. package/dist/agents/agents/writer-tool-calling.js +7 -2
  22. package/dist/agents/agents/writer-tool-calling.js.map +1 -1
  23. package/dist/agents/agents/writer.d.ts.map +1 -1
  24. package/dist/agents/agents/writer.js +7 -1
  25. package/dist/agents/agents/writer.js.map +1 -1
  26. package/dist/agents/artifact-verification.d.ts +102 -0
  27. package/dist/agents/artifact-verification.d.ts.map +1 -0
  28. package/dist/agents/artifact-verification.js +216 -0
  29. package/dist/agents/artifact-verification.js.map +1 -0
  30. package/dist/agents/checkpoint-store.d.ts +73 -0
  31. package/dist/agents/checkpoint-store.d.ts.map +1 -1
  32. package/dist/agents/checkpoint-store.js +161 -0
  33. package/dist/agents/checkpoint-store.js.map +1 -1
  34. package/dist/agents/credential-store.d.ts +120 -0
  35. package/dist/agents/credential-store.d.ts.map +1 -1
  36. package/dist/agents/credential-store.js +358 -19
  37. package/dist/agents/credential-store.js.map +1 -1
  38. package/dist/agents/long-form-plan.d.ts.map +1 -1
  39. package/dist/agents/long-form-plan.js +2 -1
  40. package/dist/agents/long-form-plan.js.map +1 -1
  41. package/dist/agents/orchestrator.d.ts +10 -1
  42. package/dist/agents/orchestrator.d.ts.map +1 -1
  43. package/dist/agents/orchestrator.js +239 -79
  44. package/dist/agents/orchestrator.js.map +1 -1
  45. package/dist/agents/phase-engine.d.ts +61 -0
  46. package/dist/agents/phase-engine.d.ts.map +1 -1
  47. package/dist/agents/phase-engine.js +68 -2
  48. package/dist/agents/phase-engine.js.map +1 -1
  49. package/dist/agents/prompt-assembly.d.ts +11 -0
  50. package/dist/agents/prompt-assembly.d.ts.map +1 -1
  51. package/dist/agents/prompt-assembly.js +17 -0
  52. package/dist/agents/prompt-assembly.js.map +1 -1
  53. package/dist/agents/release-preflight.d.ts +121 -0
  54. package/dist/agents/release-preflight.d.ts.map +1 -0
  55. package/dist/agents/release-preflight.js +259 -0
  56. package/dist/agents/release-preflight.js.map +1 -0
  57. package/dist/agents/release-runner.d.ts +157 -0
  58. package/dist/agents/release-runner.d.ts.map +1 -0
  59. package/dist/agents/release-runner.js +719 -0
  60. package/dist/agents/release-runner.js.map +1 -0
  61. package/dist/agents/step-handoff.d.ts +190 -0
  62. package/dist/agents/step-handoff.d.ts.map +1 -0
  63. package/dist/agents/step-handoff.js +443 -0
  64. package/dist/agents/step-handoff.js.map +1 -0
  65. package/dist/cli/agent.d.ts +2 -2
  66. package/dist/cli/agent.js +10 -10
  67. package/dist/cli/benchmark.d.ts.map +1 -1
  68. package/dist/cli/benchmark.js +11 -4
  69. package/dist/cli/benchmark.js.map +1 -1
  70. package/dist/cli/chat.d.ts +94 -0
  71. package/dist/cli/chat.d.ts.map +1 -1
  72. package/dist/cli/chat.js +379 -24
  73. package/dist/cli/chat.js.map +1 -1
  74. package/dist/cli/cli-program.d.ts.map +1 -1
  75. package/dist/cli/cli-program.js +8 -0
  76. package/dist/cli/cli-program.js.map +1 -1
  77. package/dist/cli/config.d.ts.map +1 -1
  78. package/dist/cli/config.js +9 -1
  79. package/dist/cli/config.js.map +1 -1
  80. package/dist/cli/credentials.d.ts +28 -0
  81. package/dist/cli/credentials.d.ts.map +1 -0
  82. package/dist/cli/credentials.js +213 -0
  83. package/dist/cli/credentials.js.map +1 -0
  84. package/dist/cli/doctor.d.ts.map +1 -1
  85. package/dist/cli/doctor.js +3 -2
  86. package/dist/cli/doctor.js.map +1 -1
  87. package/dist/cli/edit.js +2 -2
  88. package/dist/cli/eval.d.ts +17 -0
  89. package/dist/cli/eval.d.ts.map +1 -1
  90. package/dist/cli/eval.js +105 -2
  91. package/dist/cli/eval.js.map +1 -1
  92. package/dist/cli/execute.d.ts +16 -1
  93. package/dist/cli/execute.d.ts.map +1 -1
  94. package/dist/cli/execute.js +192 -22
  95. package/dist/cli/execute.js.map +1 -1
  96. package/dist/cli/failover-runner.d.ts.map +1 -1
  97. package/dist/cli/failover-runner.js +9 -3
  98. package/dist/cli/failover-runner.js.map +1 -1
  99. package/dist/cli/loop-executor.d.ts +55 -0
  100. package/dist/cli/loop-executor.d.ts.map +1 -1
  101. package/dist/cli/loop-executor.js +285 -19
  102. package/dist/cli/loop-executor.js.map +1 -1
  103. package/dist/cli/model.d.ts.map +1 -1
  104. package/dist/cli/model.js +9 -8
  105. package/dist/cli/model.js.map +1 -1
  106. package/dist/cli/models.d.ts +1 -1
  107. package/dist/cli/models.js +4 -4
  108. package/dist/cli/nlu.d.ts.map +1 -1
  109. package/dist/cli/nlu.js +8 -2
  110. package/dist/cli/nlu.js.map +1 -1
  111. package/dist/cli/parity.d.ts +85 -0
  112. package/dist/cli/parity.d.ts.map +1 -0
  113. package/dist/cli/parity.js +506 -0
  114. package/dist/cli/parity.js.map +1 -0
  115. package/dist/cli/plan.d.ts.map +1 -1
  116. package/dist/cli/plan.js +2 -1
  117. package/dist/cli/plan.js.map +1 -1
  118. package/dist/cli/publish.d.ts +22 -0
  119. package/dist/cli/publish.d.ts.map +1 -1
  120. package/dist/cli/publish.js +109 -13
  121. package/dist/cli/publish.js.map +1 -1
  122. package/dist/cli/retrieval.d.ts.map +1 -1
  123. package/dist/cli/retrieval.js +5 -4
  124. package/dist/cli/retrieval.js.map +1 -1
  125. package/dist/cli/sdk.js +4 -4
  126. package/dist/cli/sdk.js.map +1 -1
  127. package/dist/cli/trace.d.ts.map +1 -1
  128. package/dist/cli/trace.js +2 -1
  129. package/dist/cli/trace.js.map +1 -1
  130. package/dist/cli/workflow.js +2 -2
  131. package/dist/cli/workflow.js.map +1 -1
  132. package/dist/config/live-credentials.d.ts +57 -0
  133. package/dist/config/live-credentials.d.ts.map +1 -0
  134. package/dist/config/live-credentials.js +126 -0
  135. package/dist/config/live-credentials.js.map +1 -0
  136. package/dist/config/paths.d.ts +18 -0
  137. package/dist/config/paths.d.ts.map +1 -1
  138. package/dist/config/paths.js +25 -0
  139. package/dist/config/paths.js.map +1 -1
  140. package/dist/config/types.d.ts +44 -0
  141. package/dist/config/types.d.ts.map +1 -1
  142. package/dist/federation/a2a-types.js +1 -1
  143. package/dist/federation/a2a-types.js.map +1 -1
  144. package/dist/findings/verdicts.d.ts +241 -0
  145. package/dist/findings/verdicts.d.ts.map +1 -0
  146. package/dist/findings/verdicts.js +284 -0
  147. package/dist/findings/verdicts.js.map +1 -0
  148. package/dist/gateway/adapters.d.ts +65 -0
  149. package/dist/gateway/adapters.d.ts.map +1 -1
  150. package/dist/gateway/adapters.js +216 -10
  151. package/dist/gateway/adapters.js.map +1 -1
  152. package/dist/gateway/channel-directory.d.ts +31 -0
  153. package/dist/gateway/channel-directory.d.ts.map +1 -1
  154. package/dist/gateway/channel-directory.js +40 -0
  155. package/dist/gateway/channel-directory.js.map +1 -1
  156. package/dist/gateway/gateway-log.d.ts +1 -1
  157. package/dist/gateway/gateway-log.d.ts.map +1 -1
  158. package/dist/gateway/gateway-log.js.map +1 -1
  159. package/dist/gateway/hooks.d.ts +87 -19
  160. package/dist/gateway/hooks.d.ts.map +1 -1
  161. package/dist/gateway/hooks.js +62 -23
  162. package/dist/gateway/hooks.js.map +1 -1
  163. package/dist/gateway/inbound-media.d.ts +147 -0
  164. package/dist/gateway/inbound-media.d.ts.map +1 -0
  165. package/dist/gateway/inbound-media.js +317 -0
  166. package/dist/gateway/inbound-media.js.map +1 -0
  167. package/dist/gateway/inbox.d.ts +8 -1
  168. package/dist/gateway/inbox.d.ts.map +1 -1
  169. package/dist/gateway/inbox.js.map +1 -1
  170. package/dist/gateway/platform-config.d.ts +14 -0
  171. package/dist/gateway/platform-config.d.ts.map +1 -1
  172. package/dist/gateway/platform-config.js +26 -8
  173. package/dist/gateway/platform-config.js.map +1 -1
  174. package/dist/gateway/realtime.d.ts +114 -0
  175. package/dist/gateway/realtime.d.ts.map +1 -0
  176. package/dist/gateway/realtime.js +402 -0
  177. package/dist/gateway/realtime.js.map +1 -0
  178. package/dist/gateway/registry.d.ts +31 -0
  179. package/dist/gateway/registry.d.ts.map +1 -1
  180. package/dist/gateway/registry.js +224 -4
  181. package/dist/gateway/registry.js.map +1 -1
  182. package/dist/gateway/whatsapp/baileys-bridge.d.ts +11 -1
  183. package/dist/gateway/whatsapp/baileys-bridge.d.ts.map +1 -1
  184. package/dist/gateway/whatsapp/baileys-bridge.js +123 -4
  185. package/dist/gateway/whatsapp/baileys-bridge.js.map +1 -1
  186. package/dist/gateway/whatsapp/bridge.d.ts +6 -2
  187. package/dist/gateway/whatsapp/bridge.d.ts.map +1 -1
  188. package/dist/gateway/whatsapp/bridge.js.map +1 -1
  189. package/dist/index.js +8 -0
  190. package/dist/index.js.map +1 -1
  191. package/dist/inference/factory.d.ts +14 -0
  192. package/dist/inference/factory.d.ts.map +1 -1
  193. package/dist/inference/factory.js +17 -0
  194. package/dist/inference/factory.js.map +1 -1
  195. package/dist/inference/groq-adapter.d.ts +2 -0
  196. package/dist/inference/groq-adapter.d.ts.map +1 -1
  197. package/dist/inference/groq-adapter.js +16 -6
  198. package/dist/inference/groq-adapter.js.map +1 -1
  199. package/dist/inference/model-validator.d.ts +6 -1
  200. package/dist/inference/model-validator.d.ts.map +1 -1
  201. package/dist/inference/model-validator.js +7 -2
  202. package/dist/inference/model-validator.js.map +1 -1
  203. package/dist/inference/route-resolver.d.ts +116 -0
  204. package/dist/inference/route-resolver.d.ts.map +1 -0
  205. package/dist/inference/route-resolver.js +159 -0
  206. package/dist/inference/route-resolver.js.map +1 -0
  207. package/dist/inference/tools.d.ts.map +1 -1
  208. package/dist/inference/tools.js +29 -0
  209. package/dist/inference/tools.js.map +1 -1
  210. package/dist/learning/autonomy-policy.d.ts +18 -0
  211. package/dist/learning/autonomy-policy.d.ts.map +1 -1
  212. package/dist/learning/autonomy-policy.js +35 -0
  213. package/dist/learning/autonomy-policy.js.map +1 -1
  214. package/dist/learning/benchmark.d.ts.map +1 -1
  215. package/dist/learning/benchmark.js +3 -2
  216. package/dist/learning/benchmark.js.map +1 -1
  217. package/dist/learning/continuation.d.ts.map +1 -1
  218. package/dist/learning/continuation.js +2 -1
  219. package/dist/learning/continuation.js.map +1 -1
  220. package/dist/learning/cost-tracker.d.ts.map +1 -1
  221. package/dist/learning/cost-tracker.js +2 -1
  222. package/dist/learning/cost-tracker.js.map +1 -1
  223. package/dist/learning/deferred-task.d.ts.map +1 -1
  224. package/dist/learning/deferred-task.js +13 -4
  225. package/dist/learning/deferred-task.js.map +1 -1
  226. package/dist/learning/eval-framework.d.ts.map +1 -1
  227. package/dist/learning/eval-framework.js +2 -1
  228. package/dist/learning/eval-framework.js.map +1 -1
  229. package/dist/learning/long-form.d.ts.map +1 -1
  230. package/dist/learning/long-form.js +2 -1
  231. package/dist/learning/long-form.js.map +1 -1
  232. package/dist/learning/model-registry.d.ts.map +1 -1
  233. package/dist/learning/model-registry.js +2 -1
  234. package/dist/learning/model-registry.js.map +1 -1
  235. package/dist/learning/reasoning-cache.d.ts.map +1 -1
  236. package/dist/learning/reasoning-cache.js +2 -1
  237. package/dist/learning/reasoning-cache.js.map +1 -1
  238. package/dist/learning/reasoning-trace.d.ts +38 -2
  239. package/dist/learning/reasoning-trace.d.ts.map +1 -1
  240. package/dist/learning/reasoning-trace.js +91 -1
  241. package/dist/learning/reasoning-trace.js.map +1 -1
  242. package/dist/learning/resilient-call.d.ts.map +1 -1
  243. package/dist/learning/resilient-call.js +31 -18
  244. package/dist/learning/resilient-call.js.map +1 -1
  245. package/dist/learning/retrieval.d.ts.map +1 -1
  246. package/dist/learning/retrieval.js +2 -1
  247. package/dist/learning/retrieval.js.map +1 -1
  248. package/dist/learning/seeded-benchmark.d.ts +160 -0
  249. package/dist/learning/seeded-benchmark.d.ts.map +1 -0
  250. package/dist/learning/seeded-benchmark.js +321 -0
  251. package/dist/learning/seeded-benchmark.js.map +1 -0
  252. package/dist/learning/seeded-bugs.d.ts +142 -0
  253. package/dist/learning/seeded-bugs.d.ts.map +1 -0
  254. package/dist/learning/seeded-bugs.js +535 -0
  255. package/dist/learning/seeded-bugs.js.map +1 -0
  256. package/dist/learning/skill-store.d.ts.map +1 -1
  257. package/dist/learning/skill-store.js +30 -9
  258. package/dist/learning/skill-store.js.map +1 -1
  259. package/dist/learning/step-checkpoint.d.ts +127 -0
  260. package/dist/learning/step-checkpoint.d.ts.map +1 -0
  261. package/dist/learning/step-checkpoint.js +244 -0
  262. package/dist/learning/step-checkpoint.js.map +1 -0
  263. package/dist/mcp/catalog.js +2 -3
  264. package/dist/mcp/catalog.js.map +1 -1
  265. package/dist/mcp/manager.d.ts.map +1 -1
  266. package/dist/mcp/manager.js +5 -3
  267. package/dist/mcp/manager.js.map +1 -1
  268. package/dist/nlu/intent-confirm.d.ts +23 -1
  269. package/dist/nlu/intent-confirm.d.ts.map +1 -1
  270. package/dist/nlu/intent-confirm.js +85 -2
  271. package/dist/nlu/intent-confirm.js.map +1 -1
  272. package/dist/nlu/learnings.d.ts +7 -0
  273. package/dist/nlu/learnings.d.ts.map +1 -1
  274. package/dist/nlu/learnings.js +7 -0
  275. package/dist/nlu/learnings.js.map +1 -1
  276. package/dist/observability/debug-log.d.ts +250 -0
  277. package/dist/observability/debug-log.d.ts.map +1 -0
  278. package/dist/observability/debug-log.js +500 -0
  279. package/dist/observability/debug-log.js.map +1 -0
  280. package/dist/observability/event-bus.d.ts.map +1 -1
  281. package/dist/observability/event-bus.js +4 -1
  282. package/dist/observability/event-bus.js.map +1 -1
  283. package/dist/observability/otel.d.ts +278 -0
  284. package/dist/observability/otel.d.ts.map +1 -0
  285. package/dist/observability/otel.js +590 -0
  286. package/dist/observability/otel.js.map +1 -0
  287. package/dist/parity/drivers.d.ts +99 -0
  288. package/dist/parity/drivers.d.ts.map +1 -0
  289. package/dist/parity/drivers.js +1362 -0
  290. package/dist/parity/drivers.js.map +1 -0
  291. package/dist/parity/graph.d.ts +73 -0
  292. package/dist/parity/graph.d.ts.map +1 -0
  293. package/dist/parity/graph.js +162 -0
  294. package/dist/parity/graph.js.map +1 -0
  295. package/dist/parity/matrix.d.ts +105 -0
  296. package/dist/parity/matrix.d.ts.map +1 -0
  297. package/dist/parity/matrix.js +352 -0
  298. package/dist/parity/matrix.js.map +1 -0
  299. package/dist/parity/observation.d.ts +444 -0
  300. package/dist/parity/observation.d.ts.map +1 -0
  301. package/dist/parity/observation.js +333 -0
  302. package/dist/parity/observation.js.map +1 -0
  303. package/dist/parity/scenarios.d.ts +229 -0
  304. package/dist/parity/scenarios.d.ts.map +1 -0
  305. package/dist/parity/scenarios.js +175 -0
  306. package/dist/parity/scenarios.js.map +1 -0
  307. package/dist/parity/surfaces.d.ts +122 -0
  308. package/dist/parity/surfaces.d.ts.map +1 -0
  309. package/dist/parity/surfaces.js +190 -0
  310. package/dist/parity/surfaces.js.map +1 -0
  311. package/dist/runtime/fault-injection.d.ts +173 -0
  312. package/dist/runtime/fault-injection.d.ts.map +1 -0
  313. package/dist/runtime/fault-injection.js +281 -0
  314. package/dist/runtime/fault-injection.js.map +1 -0
  315. package/dist/skills/secret-capture.d.ts.map +1 -1
  316. package/dist/skills/secret-capture.js +9 -4
  317. package/dist/skills/secret-capture.js.map +1 -1
  318. package/dist/tools/child-agent-entry.d.ts +23 -0
  319. package/dist/tools/child-agent-entry.d.ts.map +1 -0
  320. package/dist/tools/child-agent-entry.js +129 -0
  321. package/dist/tools/child-agent-entry.js.map +1 -0
  322. package/dist/tools/child-agent-runtime.d.ts +124 -0
  323. package/dist/tools/child-agent-runtime.d.ts.map +1 -0
  324. package/dist/tools/child-agent-runtime.js +704 -0
  325. package/dist/tools/child-agent-runtime.js.map +1 -0
  326. package/dist/tools/coding-tools.d.ts.map +1 -1
  327. package/dist/tools/coding-tools.js +82 -10
  328. package/dist/tools/coding-tools.js.map +1 -1
  329. package/dist/tools/credentials-tool.d.ts +24 -0
  330. package/dist/tools/credentials-tool.d.ts.map +1 -0
  331. package/dist/tools/credentials-tool.js +125 -0
  332. package/dist/tools/credentials-tool.js.map +1 -0
  333. package/dist/tools/delegation-system.d.ts +31 -0
  334. package/dist/tools/delegation-system.d.ts.map +1 -1
  335. package/dist/tools/delegation-system.js +70 -9
  336. package/dist/tools/delegation-system.js.map +1 -1
  337. package/dist/tools/extract/docx.d.ts +27 -0
  338. package/dist/tools/extract/docx.d.ts.map +1 -0
  339. package/dist/tools/extract/docx.js +48 -0
  340. package/dist/tools/extract/docx.js.map +1 -0
  341. package/dist/tools/extract/html-text.d.ts +27 -0
  342. package/dist/tools/extract/html-text.d.ts.map +1 -0
  343. package/dist/tools/extract/html-text.js +86 -0
  344. package/dist/tools/extract/html-text.js.map +1 -0
  345. package/dist/tools/extract/pdf-ocr.d.ts +58 -0
  346. package/dist/tools/extract/pdf-ocr.d.ts.map +1 -0
  347. package/dist/tools/extract/pdf-ocr.js +116 -0
  348. package/dist/tools/extract/pdf-ocr.js.map +1 -0
  349. package/dist/tools/extract/pdf.d.ts +65 -0
  350. package/dist/tools/extract/pdf.d.ts.map +1 -0
  351. package/dist/tools/extract/pdf.js +197 -0
  352. package/dist/tools/extract/pdf.js.map +1 -0
  353. package/dist/tools/extract/pptx.d.ts +32 -0
  354. package/dist/tools/extract/pptx.d.ts.map +1 -0
  355. package/dist/tools/extract/pptx.js +77 -0
  356. package/dist/tools/extract/pptx.js.map +1 -0
  357. package/dist/tools/extract/xlsx.d.ts +47 -0
  358. package/dist/tools/extract/xlsx.d.ts.map +1 -0
  359. package/dist/tools/extract/xlsx.js +111 -0
  360. package/dist/tools/extract/xlsx.js.map +1 -0
  361. package/dist/tools/finding-tool.d.ts +76 -0
  362. package/dist/tools/finding-tool.d.ts.map +1 -0
  363. package/dist/tools/finding-tool.js +125 -0
  364. package/dist/tools/finding-tool.js.map +1 -0
  365. package/dist/tools/git-tool.d.ts +25 -7
  366. package/dist/tools/git-tool.d.ts.map +1 -1
  367. package/dist/tools/git-tool.js +155 -15
  368. package/dist/tools/git-tool.js.map +1 -1
  369. package/dist/tools/loop-project-context.d.ts.map +1 -1
  370. package/dist/tools/loop-project-context.js +16 -0
  371. package/dist/tools/loop-project-context.js.map +1 -1
  372. package/dist/tools/loop-route-feed.d.ts +57 -0
  373. package/dist/tools/loop-route-feed.d.ts.map +1 -0
  374. package/dist/tools/loop-route-feed.js +101 -0
  375. package/dist/tools/loop-route-feed.js.map +1 -0
  376. package/dist/tools/messaging-tools.d.ts +41 -11
  377. package/dist/tools/messaging-tools.d.ts.map +1 -1
  378. package/dist/tools/messaging-tools.js +104 -55
  379. package/dist/tools/messaging-tools.js.map +1 -1
  380. package/dist/tools/neutts-synth.d.ts +27 -3
  381. package/dist/tools/neutts-synth.d.ts.map +1 -1
  382. package/dist/tools/neutts-synth.js +57 -13
  383. package/dist/tools/neutts-synth.js.map +1 -1
  384. package/dist/tools/pipeline-tool.d.ts +43 -1
  385. package/dist/tools/pipeline-tool.d.ts.map +1 -1
  386. package/dist/tools/pipeline-tool.js +21 -4
  387. package/dist/tools/pipeline-tool.js.map +1 -1
  388. package/dist/tools/publish-tool.d.ts.map +1 -1
  389. package/dist/tools/publish-tool.js +76 -10
  390. package/dist/tools/publish-tool.js.map +1 -1
  391. package/dist/tools/read-extract.d.ts +116 -45
  392. package/dist/tools/read-extract.d.ts.map +1 -1
  393. package/dist/tools/read-extract.js +494 -158
  394. package/dist/tools/read-extract.js.map +1 -1
  395. package/dist/tools/registry.d.ts +23 -3
  396. package/dist/tools/registry.d.ts.map +1 -1
  397. package/dist/tools/registry.js +196 -29
  398. package/dist/tools/registry.js.map +1 -1
  399. package/dist/tools/run-terminal.d.ts +9 -0
  400. package/dist/tools/run-terminal.d.ts.map +1 -1
  401. package/dist/tools/run-terminal.js +80 -2
  402. package/dist/tools/run-terminal.js.map +1 -1
  403. package/dist/tools/subagent-refusal.d.ts +15 -0
  404. package/dist/tools/subagent-refusal.d.ts.map +1 -0
  405. package/dist/tools/subagent-refusal.js +18 -0
  406. package/dist/tools/subagent-refusal.js.map +1 -0
  407. package/dist/tools/subagent-spawner.d.ts +122 -0
  408. package/dist/tools/subagent-spawner.d.ts.map +1 -1
  409. package/dist/tools/subagent-spawner.js +249 -28
  410. package/dist/tools/subagent-spawner.js.map +1 -1
  411. package/dist/tools/tool-hooks.d.ts +177 -0
  412. package/dist/tools/tool-hooks.d.ts.map +1 -0
  413. package/dist/tools/tool-hooks.js +427 -0
  414. package/dist/tools/tool-hooks.js.map +1 -0
  415. package/dist/tools/tool-loop.d.ts +94 -5
  416. package/dist/tools/tool-loop.d.ts.map +1 -1
  417. package/dist/tools/tool-loop.js +315 -9
  418. package/dist/tools/tool-loop.js.map +1 -1
  419. package/dist/tools/tool-refusal.d.ts +68 -0
  420. package/dist/tools/tool-refusal.d.ts.map +1 -0
  421. package/dist/tools/tool-refusal.js +78 -0
  422. package/dist/tools/tool-refusal.js.map +1 -0
  423. package/dist/tools/toolsets.d.ts +8 -0
  424. package/dist/tools/toolsets.d.ts.map +1 -1
  425. package/dist/tools/toolsets.js +14 -4
  426. package/dist/tools/toolsets.js.map +1 -1
  427. package/dist/tools/vision-tools.d.ts +88 -83
  428. package/dist/tools/vision-tools.d.ts.map +1 -1
  429. package/dist/tools/vision-tools.js +134 -103
  430. package/dist/tools/vision-tools.js.map +1 -1
  431. package/dist/tools/worktree.d.ts +210 -0
  432. package/dist/tools/worktree.d.ts.map +1 -0
  433. package/dist/tools/worktree.js +374 -0
  434. package/dist/tools/worktree.js.map +1 -0
  435. package/dist/utils/format.d.ts +3 -0
  436. package/dist/utils/format.d.ts.map +1 -0
  437. package/dist/utils/format.js +32 -0
  438. package/dist/utils/format.js.map +1 -0
  439. package/dist/web-dashboard/attachment-extract.d.ts +64 -0
  440. package/dist/web-dashboard/attachment-extract.d.ts.map +1 -0
  441. package/dist/web-dashboard/attachment-extract.js +154 -0
  442. package/dist/web-dashboard/attachment-extract.js.map +1 -0
  443. package/dist/web-dashboard/chat-console.d.ts +108 -1
  444. package/dist/web-dashboard/chat-console.d.ts.map +1 -1
  445. package/dist/web-dashboard/chat-console.js +36 -0
  446. package/dist/web-dashboard/chat-console.js.map +1 -1
  447. package/dist/web-dashboard/hub-data.d.ts +37 -0
  448. package/dist/web-dashboard/hub-data.d.ts.map +1 -1
  449. package/dist/web-dashboard/hub-data.js +61 -1
  450. package/dist/web-dashboard/hub-data.js.map +1 -1
  451. package/dist/web-dashboard/server.d.ts +14 -0
  452. package/dist/web-dashboard/server.d.ts.map +1 -1
  453. package/dist/web-dashboard/server.js +247 -13
  454. package/dist/web-dashboard/server.js.map +1 -1
  455. package/dist/web-dashboard/src/types.d.ts +196 -48
  456. package/dist/web-dashboard/src/types.d.ts.map +1 -1
  457. package/dist/workflow/registry.js +1 -1
  458. package/dist/workflow/registry.js.map +1 -1
  459. package/package.json +22 -6
  460. package/src/web-dashboard/public/assets/{index-Cyd6tIew.css → index-XJjj2cBX.css} +1 -1
  461. package/src/web-dashboard/public/assets/index-YWF9FpwQ.js +207 -0
  462. package/src/web-dashboard/public/assets/index-YWF9FpwQ.js.map +1 -0
  463. package/src/web-dashboard/public/index.html +2 -2
  464. package/dist/tools/child-agent-worker.js +0 -212
  465. package/src/web-dashboard/public/assets/index-CjvoBhlz.js +0 -207
  466. package/src/web-dashboard/public/assets/index-CjvoBhlz.js.map +0 -1
@@ -0,0 +1,719 @@
1
+ /**
2
+ * Release runners — the DETERMINISTIC half of the publish pipeline.
3
+ *
4
+ * `nuvira publish` defines its phases as goals ("Bump version (patch), update
5
+ * CHANGELOG.md with release notes") and used to hand every one of them to the
6
+ * LLM orchestrator. That made a mechanical release depend on plan quality and
7
+ * provider health: a live 3.3.2 run planned an unrelated job (add
8
+ * `standard-version`, write a new `scripts/release.ts`) instead of bumping the
9
+ * version, and the write steps then failed under a rate-limited provider. A
10
+ * release is not a creative task — every step here is a command with a known
11
+ * correct outcome — so each phase now carries a RUNNER, and the orchestrator is
12
+ * only used for phases that have none (e.g. the free-text `evaluate` phase of
13
+ * `nuvira phase add`).
14
+ *
15
+ * Properties that matter:
16
+ * - A runner reads the world at RUN time (version, changelog, branch, remote)
17
+ * rather than closing over state, so a phase resumed later in a new process
18
+ * sees the same facts the filesystem does.
19
+ * - Nothing is invented: the changelog entry is built from `git log`, and the
20
+ * commit headline is the changelog heading when one exists.
21
+ * - An author-written `## vX.Y.Z` section in CHANGELOG.md is LEFT ALONE. The
22
+ * generated entry is a fallback for the case where nobody wrote one, never an
23
+ * overwrite of prose a human wrote.
24
+ * - Failures carry the command's own output as the error, so the summary line
25
+ * the user reads says what npm/git actually said.
26
+ * - A phase refuses the work it must not do, rather than doing it and reporting
27
+ * afterwards: the git phase will not tag a release that changes the dependency
28
+ * set, and the version phase will not commit a version whose pinned artifacts
29
+ * are stale.
30
+ */
31
+ import { execSync } from 'node:child_process';
32
+ import { existsSync, mkdtempSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
33
+ import { tmpdir } from 'node:os';
34
+ import { join } from 'node:path';
35
+ import { TEST_UNSAFE_ENV_KEYS, stripTestUnsafeEnv } from '../config/live-credentials.js';
36
+ import { logger } from '../utils/logger.js';
37
+ /** Phase ids produced by `buildPublishPhases` — the runner table's keys. */
38
+ export const RELEASE_PHASE_IDS = {
39
+ tests: 'phase-1-tests',
40
+ version: 'phase-2-version',
41
+ git: 'phase-3-git',
42
+ npm: 'phase-4-npm',
43
+ github: 'phase-5-github',
44
+ };
45
+ /**
46
+ * Run a command and never throw — the caller decides what a non-zero exit
47
+ * means. `2>&1` keeps stderr in the captured text because that is where npm,
48
+ * git and gh put the sentence that explains a failure.
49
+ */
50
+ function run(command, timeoutMs = 600_000, cwd, env) {
51
+ try {
52
+ const output = execSync(`${command} 2>&1`, {
53
+ cwd: cwd || process.cwd(),
54
+ timeout: timeoutMs,
55
+ encoding: 'utf-8',
56
+ stdio: 'pipe',
57
+ // Undefined keeps the inherited environment; a caller passes `env` to
58
+ // spawn WITHOUT something this process holds (the test phase passes a
59
+ // credential-stripped copy — see `src/config/live-credentials.ts`).
60
+ ...(env ? { env } : {}),
61
+ });
62
+ return { ok: true, output: (output || '').trim() };
63
+ }
64
+ catch (err) {
65
+ const error = err;
66
+ return { ok: false, output: (error.stdout || error.stderr || error.message || '').trim() };
67
+ }
68
+ }
69
+ function tail(text, max = 300) {
70
+ const trimmed = text.trim();
71
+ return trimmed.length > max ? `…${trimmed.slice(-max)}` : trimmed;
72
+ }
73
+ /** Read what failed out of a vitest run, in a form a caller can act on. */
74
+ export function testFailureShape(output) {
75
+ // vitest colours the `FAIL` marker, so escape sequences sit BETWEEN the marker
76
+ // and the path and a plain match finds nothing. Measured: the first version of
77
+ // this digest named the failure kind and no file at all.
78
+ const clean = output.replace(/\u001B\[[0-9;]*[A-Za-z]/g, '');
79
+ const files = [
80
+ ...new Set([...clean.matchAll(/(?:FAIL\s+|❯\s+)(tests\/[^\s(]+)/g)].map((m) => m[1])),
81
+ ];
82
+ const kinds = [
83
+ ...new Set([
84
+ ...clean.matchAll(/Test timed out in \d+ ?ms/g),
85
+ ...clean.matchAll(/Timed out waiting for [^\n]+/g),
86
+ ...clean.matchAll(/AssertionError/g),
87
+ ...clean.matchAll(/Unhandled [Ee]rrors?/g),
88
+ ].map((m) => m[0])),
89
+ ];
90
+ const notTimeouts = kinds.filter((kind) => !/timed out|Timed out/.test(kind));
91
+ return { files, kinds, timeoutsOnly: kinds.length > 0 && notTimeouts.length === 0 };
92
+ }
93
+ /**
94
+ * The digest a failed Test Verification reports: which files, what kind, and
95
+ * whether the shape is the one that means "re-run before blaming the code".
96
+ */
97
+ export function testFailureDigest(output, context) {
98
+ const { files, kinds, timeoutsOnly } = testFailureShape(output);
99
+ const lines = [];
100
+ if (files.length > 0) {
101
+ const shown = files.slice(0, 10).join(', ');
102
+ lines.push(`${files.length} failing file(s): ${shown}${files.length > 10 ? `, +${files.length - 10} more` : ''}`);
103
+ }
104
+ if (kinds.length > 0)
105
+ lines.push(`failure kinds: ${kinds.slice(0, 6).join('; ')}`);
106
+ if (timeoutsOnly) {
107
+ lines.push('every failure is a TIMEOUT: a timeout is about scheduling or a live network path, not an ' +
108
+ 'assertion — re-run before treating this as a code regression');
109
+ }
110
+ if (context)
111
+ lines.push(context);
112
+ return lines.join('\n');
113
+ }
114
+ export function readManifest(cwd = process.cwd()) {
115
+ const path = join(cwd, 'package.json');
116
+ try {
117
+ if (!existsSync(path))
118
+ return null;
119
+ return JSON.parse(readFileSync(path, 'utf-8'));
120
+ }
121
+ catch {
122
+ return null;
123
+ }
124
+ }
125
+ export function readVersion(cwd = process.cwd()) {
126
+ return readManifest(cwd)?.version || '';
127
+ }
128
+ /** Pure version arithmetic — exported so it can be pinned by test. */
129
+ export function bumpVersionString(current, bumpType) {
130
+ const parts = current.split('.').map((p) => Number.parseInt(p, 10) || 0);
131
+ while (parts.length < 3)
132
+ parts.push(0);
133
+ if (bumpType === 'major')
134
+ return `${parts[0] + 1}.0.0`;
135
+ if (bumpType === 'minor')
136
+ return `${parts[0]}.${parts[1] + 1}.0`;
137
+ return `${parts[0]}.${parts[1]}.${parts[2] + 1}`;
138
+ }
139
+ /** The tag this release is measured from — version tags only (`v3.3.1`). */
140
+ export function lastReleaseTag() {
141
+ const tagged = run('git describe --tags --abbrev=0 --match "v[0-9]*"', 15_000);
142
+ if (tagged.ok && tagged.output)
143
+ return tagged.output.split('\n')[0].trim();
144
+ // No version tag yet: measure from the root commit so the entry is not empty.
145
+ const root = run('git rev-list --max-parents=0 HEAD', 15_000);
146
+ return root.ok ? root.output.split('\n')[0].trim() : '';
147
+ }
148
+ export function commitsSince(base) {
149
+ if (!base)
150
+ return [];
151
+ const log = run(`git log --oneline --no-decorate ${base}..HEAD`, 15_000);
152
+ if (!log.ok)
153
+ return [];
154
+ return log.output.split('\n').map((l) => l.trim()).filter(Boolean);
155
+ }
156
+ /** Does CHANGELOG.md already have a section for this version? Section = `## vX.Y.Z`. */
157
+ export function hasChangelogSection(version, changelog) {
158
+ if (!changelog)
159
+ return false;
160
+ const escaped = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
161
+ // `\b` is not enough: '3.3' followed by '.1' IS a word boundary, so '3.3'
162
+ // would match the '## v3.3.1' heading and the release would keep a section
163
+ // belonging to a different version.
164
+ return new RegExp(`^##\\s*v?${escaped}(?![0-9.])`, 'm').test(changelog);
165
+ }
166
+ /**
167
+ * The headline of `## vX.Y.Z — headline`, used as the commit subject.
168
+ * Returns '' when the section carries no headline.
169
+ */
170
+ export function changelogHeadline(version, changelog) {
171
+ const escaped = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
172
+ const match = changelog.match(new RegExp(`^##\\s*v?${escaped}\\s*[—-]\\s*(.+)$`, 'm'));
173
+ return match ? match[1].trim() : '';
174
+ }
175
+ /** The full text of the `## vX.Y.Z` section, for GitHub release notes. */
176
+ export function changelogSection(version, changelog) {
177
+ const escaped = version.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
178
+ const heading = new RegExp(`^##\\s*v?${escaped}(?![0-9.]).*$`, 'm');
179
+ const start = changelog.search(heading);
180
+ if (start === -1)
181
+ return '';
182
+ const rest = changelog.slice(start);
183
+ const nextSection = rest.slice(1).search(/^##\s/m);
184
+ return (nextSection === -1 ? rest : rest.slice(0, nextSection + 1)).trim();
185
+ }
186
+ function readChangelog(cwd = process.cwd()) {
187
+ const path = join(cwd, 'CHANGELOG.md');
188
+ try {
189
+ return existsSync(path) ? readFileSync(path, 'utf-8') : '';
190
+ }
191
+ catch {
192
+ return '';
193
+ }
194
+ }
195
+ // ─── Phase 1: tests ─────────────────────────────────────────────────────────
196
+ export async function runTestsPhase() {
197
+ const manifest = readManifest();
198
+ if (!manifest?.scripts?.test) {
199
+ return { success: true, summary: 'No test script in package.json — nothing to run' };
200
+ }
201
+ // Generous: a full suite on a large project runs for minutes, and a timeout
202
+ // here would read as "tests failed" for a suite that was still passing.
203
+ //
204
+ // The suite is spawned WITHOUT the credentials this process holds. The release
205
+ // legitimately loads `~/.nuvira/.env` to push and publish, and it used to hand
206
+ // that same environment to `npm test` — so tests conditioned on a provider key
207
+ // woke up and took real network paths, and Phase 1 failed on the operator's
208
+ // shell rather than on the code. See `src/config/live-credentials.ts`.
209
+ // What the suite is NOT being told, reported on failure so the operator can
210
+ // rule the environment in or out instead of re-deriving it.
211
+ const withheld = TEST_UNSAFE_ENV_KEYS.filter((key) => process.env[key] !== undefined);
212
+ const withheldNote = withheld.length
213
+ ? `note: ${withheld.length} credential(s) were withheld from the suite (${withheld.slice(0, 5).join(', ')}${withheld.length > 5 ? ', …' : ''}), so a live-credential cause is already ruled out`
214
+ : undefined;
215
+ const startedAt = Date.now();
216
+ const result = run('npm test', 1_800_000, undefined, stripTestUnsafeEnv());
217
+ if (!result.ok) {
218
+ const shape = testFailureShape(result.output);
219
+ const firstRunMs = Date.now() - startedAt;
220
+ // RETRY ONCE, and only for the signature that means "reproduce before you
221
+ // conclude": every failure a timeout, on a run short enough that a second
222
+ // one stays cheap (10 minutes). This is the judgement a human makes by hand
223
+ // after a timing-shaped failure — re-run it — and a pipeline that grades a
224
+ // release without it reports flakes as regressions. A timeout-only failure
225
+ // that REPEATS is reported as real, with both attempts named.
226
+ if (shape.timeoutsOnly && shape.files.length > 0 && firstRunMs < 600_000) {
227
+ const retry = run('npm test', 1_800_000, undefined, stripTestUnsafeEnv());
228
+ if (retry.ok) {
229
+ const passed = retry.output.match(/Tests\s+.*?(\d+)\s+passed/);
230
+ return {
231
+ success: true,
232
+ summary: `Tests passed on retry (${passed ? passed[1] : 'all'} passing) — the first run had ` +
233
+ `${shape.files.length} timeout-only failure(s), which did not reproduce`,
234
+ details: tail(retry.output, 800),
235
+ };
236
+ }
237
+ return {
238
+ success: false,
239
+ summary: 'Test suite failed twice, timeouts only',
240
+ error: [
241
+ testFailureDigest(result.output, withheldNote),
242
+ 'the retry failed the same way, so treat it as real',
243
+ tail(retry.output, 400),
244
+ ]
245
+ .filter(Boolean)
246
+ .join('\n'),
247
+ };
248
+ }
249
+ const files = shape.files.length;
250
+ return {
251
+ success: false,
252
+ summary: files ? `Test suite failed (${files} file(s))` : 'Test suite failed',
253
+ error: [testFailureDigest(result.output, withheldNote), tail(result.output, 400)]
254
+ .filter(Boolean)
255
+ .join('\n'),
256
+ };
257
+ }
258
+ const passed = result.output.match(/Tests\s+.*?(\d+)\s+passed/);
259
+ return {
260
+ success: true,
261
+ summary: passed ? `Tests passed (${passed[1]} passing)` : 'Tests passed',
262
+ details: tail(result.output, 800),
263
+ };
264
+ }
265
+ // ─── Phase 2: version bump + changelog ──────────────────────────────────────
266
+ export async function runVersionBumpPhase(bumpType = 'patch') {
267
+ const cwd = process.cwd();
268
+ const pkgPath = join(cwd, 'package.json');
269
+ const manifest = readManifest(cwd);
270
+ if (!manifest) {
271
+ return { success: false, summary: 'No package.json found', error: `Expected ${pkgPath}` };
272
+ }
273
+ const current = manifest.version || '0.0.0';
274
+ const next = bumpVersionString(current, bumpType);
275
+ if (next === current) {
276
+ return { success: false, summary: `Version did not change (${current})`, error: 'Bump produced the same version' };
277
+ }
278
+ manifest.version = next;
279
+ writeFileSync(pkgPath, JSON.stringify(manifest, null, 2) + '\n', 'utf-8');
280
+ // The lockfile's OWN version fields are the ones npm compares; leaving them
281
+ // stale makes `npm ci` in a fresh checkout disagree with package.json.
282
+ const lockPath = join(cwd, 'package-lock.json');
283
+ let lockSynced = false;
284
+ try {
285
+ if (existsSync(lockPath)) {
286
+ const lock = JSON.parse(readFileSync(lockPath, 'utf-8'));
287
+ lock.version = next;
288
+ if (lock.packages?.[''])
289
+ lock.packages[''].version = next;
290
+ writeFileSync(lockPath, JSON.stringify(lock, null, 2) + '\n', 'utf-8');
291
+ lockSynced = true;
292
+ }
293
+ }
294
+ catch (err) {
295
+ logger.warn(` ⚠️ Could not sync package-lock.json: ${err}`);
296
+ }
297
+ // Changelog: an author-written section wins. Only write a generated one when
298
+ // the version has no section at all.
299
+ const changelog = readChangelog(cwd);
300
+ let changelogNote = 'kept the existing entry';
301
+ if (!hasChangelogSection(next, changelog)) {
302
+ const commits = commitsSince(lastReleaseTag());
303
+ const date = new Date().toISOString().slice(0, 10);
304
+ const bullets = commits.length
305
+ ? commits.map((c) => `- ${c}`).join('\n')
306
+ : '- No commits recorded since the previous release.';
307
+ const entry = `## v${next} — released ${date}\n\n${bullets}\n\n`;
308
+ const header = '# Changelog\n';
309
+ const body = changelog.startsWith(header)
310
+ ? header + '\n' + entry + changelog.slice(header.length).replace(/^\n+/, '')
311
+ : entry + changelog;
312
+ writeFileSync(join(cwd, 'CHANGELOG.md'), body, 'utf-8');
313
+ changelogNote = `added an entry from ${commits.length} commit(s)`;
314
+ }
315
+ // Version-pinned artifacts — the recorder the release docs pin to, the
316
+ // dashboard bundle that inlines the version — must move in the SAME commit as
317
+ // the version. They did not, and the 3.3.2 release is what found it: the
318
+ // pipeline bumped, committed and pushed, and then `prepublishOnly`'s test run
319
+ // failed on the staleness guard ("cast records v3.3.1 but package.json is
320
+ // v3.3.2"), so the publish could not complete. The v3.3.1 release had fixed
321
+ // this by hand, which is exactly the sign it belongs in the pipeline.
322
+ const artifacts = await regenerateVersionPinnedArtifacts();
323
+ if (!artifacts.success) {
324
+ return {
325
+ success: false,
326
+ summary: `Bumped to ${next}, but its version-pinned artifacts could not be regenerated`,
327
+ error: artifacts.error,
328
+ };
329
+ }
330
+ const parts = [
331
+ `Bumped ${current} -> ${next} (${bumpType})`,
332
+ `changelog ${changelogNote}`,
333
+ lockSynced ? 'lockfile synced' : null,
334
+ artifacts.summary,
335
+ ].filter(Boolean);
336
+ return { success: true, summary: parts.join('; ') };
337
+ }
338
+ /**
339
+ * Which dependencies differ between HEAD and the working tree.
340
+ *
341
+ * Compares every dependency section as a SET, so a pure reformat is not a
342
+ * finding while an added, removed or re-ranged package is — and reports the
343
+ * packages by name so the message is actionable rather than "package.json
344
+ * changed".
345
+ */
346
+ const DEP_SECTIONS = ['dependencies', 'devDependencies', 'optionalDependencies', 'peerDependencies'];
347
+ /** The dependency sections of a parsed manifest, as one `section::name` set. */
348
+ function dependencySet(manifest) {
349
+ const out = {};
350
+ for (const section of DEP_SECTIONS) {
351
+ const bag = manifest[section];
352
+ if (!bag || typeof bag !== 'object')
353
+ continue;
354
+ for (const [name, range] of Object.entries(bag)) {
355
+ out[`${section}::${name}`] = String(range);
356
+ }
357
+ }
358
+ return out;
359
+ }
360
+ export function dependencyDelta(cwd = process.cwd()) {
361
+ const sections = DEP_SECTIONS;
362
+ const local = readManifest(cwd);
363
+ if (!local)
364
+ return [];
365
+ const headRaw = run('git show HEAD:package.json', 15_000, cwd);
366
+ if (!headRaw.ok || !headRaw.output.trim())
367
+ return []; // no HEAD yet — nothing to compare
368
+ let head;
369
+ try {
370
+ head = JSON.parse(headRaw.output);
371
+ }
372
+ catch {
373
+ return [];
374
+ }
375
+ const changes = [];
376
+ for (const section of sections) {
377
+ const before = (head[section] ?? {});
378
+ const after = (local[section] ?? {});
379
+ for (const name of new Set([...Object.keys(before), ...Object.keys(after)])) {
380
+ if (before[name] === after[name])
381
+ continue;
382
+ if (!(name in before))
383
+ changes.push(`+${name} (${section})`);
384
+ else if (!(name in after))
385
+ changes.push(`-${name} (${section})`);
386
+ else
387
+ changes.push(`~${name} ${before[name]} → ${after[name]} (${section})`);
388
+ }
389
+ }
390
+ return changes.sort();
391
+ }
392
+ /**
393
+ * Which dependencies moved in a NESTED manifest — staged content vs HEAD's.
394
+ *
395
+ * `null` means NO CLAIM CAN BE MADE: the staged content cannot be read, the file
396
+ * is new (there is no HEAD side), or it is not JSON. A caller must treat `null`
397
+ * as unverifiable rather than as "nothing moved" — this guard exists so a
398
+ * dependency cannot enter a tagged release unseen, and "I could not read it" is
399
+ * not "it is fine".
400
+ */
401
+ export function nestedDependencyDelta(path, cwd = process.cwd()) {
402
+ const staged = run(`git show :"${path}"`, 20_000, cwd);
403
+ const head = run(`git show "HEAD:${path}"`, 20_000, cwd);
404
+ if (!staged.ok || !head.ok)
405
+ return null;
406
+ let before;
407
+ let after;
408
+ try {
409
+ before = JSON.parse(head.output);
410
+ after = JSON.parse(staged.output);
411
+ }
412
+ catch {
413
+ return null;
414
+ }
415
+ if (!before || !after || typeof before !== 'object' || typeof after !== 'object')
416
+ return null;
417
+ const b = dependencySet(before);
418
+ const a = dependencySet(after);
419
+ const changes = [];
420
+ for (const key of new Set([...Object.keys(b), ...Object.keys(a)])) {
421
+ if (b[key] === a[key])
422
+ continue;
423
+ const [section, name] = key.split('::');
424
+ if (!(key in b))
425
+ changes.push(`+${name} (${section})`);
426
+ else if (!(key in a))
427
+ changes.push(`-${name} (${section})`);
428
+ else
429
+ changes.push(`~${name} ${b[key]} → ${a[key]} (${section})`);
430
+ }
431
+ return changes.sort();
432
+ }
433
+ /**
434
+ * Decide what a release commit should do about the nested manifests it carries.
435
+ *
436
+ * WHY IT IS NOT "refuse every nested manifest edit". That was the first version,
437
+ * and it produced a FALSE POSITIVE the first time it ran for real: three
438
+ * sub-package manifests (`packages/sdk`, `src/agent-sdk`, `vscode-extension`)
439
+ * whose entire diff was a `repository` / `homepage` URL pointing at the new docs
440
+ * repo. No dependencies moved, yet the release could not be completed without
441
+ * `NUVIRA_ALLOW_DEP_CHANGES=1` — and an override that gets used on a false alarm
442
+ * is an override that stops meaning anything. A URL edit and a dependency edit
443
+ * are distinguishable, so the guard distinguishes them and keeps its teeth for
444
+ * the case it was built for.
445
+ *
446
+ * Lockfiles stay unverifiable on purpose: `yarn.lock`, `pnpm-lock.yaml` and
447
+ * `bun.lock` are not JSON, and a nested lockfile only moves when its sibling's
448
+ * dependencies do.
449
+ */
450
+ export function evaluateNestedManifests(paths, deltaOf) {
451
+ const moved = [];
452
+ const unverifiable = [];
453
+ for (const path of paths) {
454
+ if (!path.endsWith('package.json')) {
455
+ unverifiable.push(path);
456
+ continue;
457
+ }
458
+ const delta = deltaOf(path);
459
+ if (delta === null) {
460
+ unverifiable.push(path);
461
+ continue;
462
+ }
463
+ moved.push(...delta.map((entry) => `${path}: ${entry}`));
464
+ }
465
+ return { moved, unverifiable };
466
+ }
467
+ /**
468
+ * Run the project's own hook for artifacts that embed the version.
469
+ *
470
+ * The hook is an explicit npm script rather than a guess at which directories
471
+ * are generated: a project that needs one declares `release:artifacts`, and a
472
+ * project without it skips this cleanly. Guessing by path ("rebuild if `public/`
473
+ * is tracked") would be wrong in both directions, and wrong silently.
474
+ */
475
+ export async function regenerateVersionPinnedArtifacts() {
476
+ const manifest = readManifest();
477
+ const hook = manifest?.scripts?.['release:artifacts'];
478
+ if (!hook) {
479
+ return { success: true, summary: 'no release:artifacts hook to run' };
480
+ }
481
+ const result = run('npm run release:artifacts', 1_800_000);
482
+ if (!result.ok) {
483
+ return {
484
+ success: false,
485
+ summary: 'release:artifacts failed',
486
+ error: tail(result.output, 400),
487
+ };
488
+ }
489
+ return { success: true, summary: 'version-pinned artifacts regenerated' };
490
+ }
491
+ // ─── Phase 3: git commit, tag, push ─────────────────────────────────────────
492
+ export async function runGitPhase() {
493
+ const version = readVersion();
494
+ if (!version) {
495
+ return { success: false, summary: 'Cannot tag without a version', error: 'package.json has no version' };
496
+ }
497
+ const tag = `v${version}`;
498
+ // ── A release commit changes the VERSION, not the dependency set ──────────
499
+ // Checked against HEAD, so it is independent of when the change appeared. The
500
+ // incident: two dependencies were written into `package.json` mid-release by
501
+ // something outside the pipeline, and this phase's `git add -A` was one step
502
+ // from committing them into a tagged, published release whose code never
503
+ // referenced either. A dependency change is a decision with its own commit,
504
+ // never a side effect of cutting a release.
505
+ const deps = dependencyDelta();
506
+ if (deps.length > 0 && process.env.NUVIRA_ALLOW_DEP_CHANGES !== '1') {
507
+ return {
508
+ success: false,
509
+ summary: 'Refusing to tag a release that changes dependencies',
510
+ error: `${deps.join(', ')} differ from HEAD. A release commit must not introduce or remove ` +
511
+ 'dependencies — commit that change on its own (and say why), or set NUVIRA_ALLOW_DEP_CHANGES=1 ' +
512
+ 'if the dependency change is genuinely part of this release.',
513
+ };
514
+ }
515
+ const branchResult = run('git rev-parse --abbrev-ref HEAD', 15_000);
516
+ const branch = branchResult.ok ? branchResult.output.trim() : 'main';
517
+ const remotes = run('git remote', 15_000);
518
+ if (!remotes.ok || !remotes.output.trim()) {
519
+ return { success: false, summary: 'No git remote configured', error: 'Add a remote: git remote add origin <url>' };
520
+ }
521
+ const remote = remotes.output.split('\n')[0].trim();
522
+ // Stage everything the release touched (version bump, changelog, lockfile).
523
+ const staged = run('git add -A', 30_000);
524
+ if (!staged.ok) {
525
+ return { success: false, summary: 'git add failed', error: tail(staged.output) };
526
+ }
527
+ // ── What the commit will actually CONTAIN ──────────────────────────────
528
+ // `git add -A` stages the whole working tree, which is right for a release
529
+ // (it ships the work), but it means the commit's contents have to be READ
530
+ // rather than assumed. The dependency guard above only reads the ROOT
531
+ // manifest, so a NESTED manifest — a sub-package's package.json or lockfile —
532
+ // could still carry a dependency change into a tagged, published release
533
+ // unseen. That is the same supply-chain event one level down, so it gets the
534
+ // same rule: refuse it unless the operator says the change is intended.
535
+ const stagedList = run('git diff --cached --name-only', 30_000);
536
+ const stagedPaths = stagedList.ok
537
+ ? stagedList.output.split('\n').map((p) => p.trim()).filter(Boolean)
538
+ : [];
539
+ const ROOT_MANIFESTS = new Set([
540
+ 'package.json', 'package-lock.json', 'npm-shrinkwrap.json',
541
+ 'yarn.lock', 'pnpm-lock.yaml', 'bun.lock',
542
+ ]);
543
+ const NESTED_MANIFEST_RE = /(^|\/)(package\.json|package-lock\.json|npm-shrinkwrap\.json|yarn\.lock|pnpm-lock\.yaml|bun\.lock)$/;
544
+ const nestedManifests = stagedPaths.filter((p) => !ROOT_MANIFESTS.has(p) && NESTED_MANIFEST_RE.test(p));
545
+ const nestedVerdict = nestedManifests.length > 0
546
+ ? evaluateNestedManifests(nestedManifests, (path) => nestedDependencyDelta(path))
547
+ : { moved: [], unverifiable: [] };
548
+ if ((nestedVerdict.moved.length > 0 || nestedVerdict.unverifiable.length > 0) &&
549
+ process.env.NUVIRA_ALLOW_DEP_CHANGES !== '1') {
550
+ const findings = [];
551
+ if (nestedVerdict.moved.length > 0) {
552
+ findings.push(`dependency edits: ${nestedVerdict.moved.join(', ')}`);
553
+ }
554
+ if (nestedVerdict.unverifiable.length > 0) {
555
+ findings.push(`cannot verify (new, unreadable, or a lockfile this pipeline cannot compare): ${nestedVerdict.unverifiable.join(', ')}`);
556
+ }
557
+ return {
558
+ success: false,
559
+ summary: 'Refusing to tag a release that changes a nested dependency manifest',
560
+ error: `${nestedManifests.join(', ')} would enter this release commit — ${findings.join('; ')}. ` +
561
+ 'A release commit must not carry a dependency change it cannot name: commit it on its ' +
562
+ 'own (and say why), or set NUVIRA_ALLOW_DEP_CHANGES=1 if it is genuinely part of this release.',
563
+ };
564
+ }
565
+ const status = run('git status --short', 30_000);
566
+ const changedCount = status.ok ? status.output.split('\n').filter(Boolean).length : 0;
567
+ // Names, not just a count: the live incident was one `git add -A` from
568
+ // committing two packages nobody had declared, and "21 files changed" said
569
+ // nothing about them. The list is bounded because a release commit can
570
+ // legitimately be large, and it is reported on the success path too — the
571
+ // point is that the operator can SEE what shipped.
572
+ const stagedNote = stagedPaths.length
573
+ ? `staging ${stagedPaths.length} path(s): ${stagedPaths.slice(0, 40).join(', ')}` +
574
+ (stagedPaths.length > 40 ? ` …and ${stagedPaths.length - 40} more` : '')
575
+ : 'nothing staged';
576
+ // Reported, not assumed: "these nested manifests were checked and carry no
577
+ // dependency edit" is a fact the operator can verify, unlike silence.
578
+ const nestedNote = nestedManifests.length > 0
579
+ ? `; ${nestedManifests.length} nested manifest(s) verified dependency-free: ${nestedManifests.join(', ')}`
580
+ : '';
581
+ let committed = false;
582
+ if (changedCount > 0) {
583
+ const headline = changelogHeadline(version, readChangelog());
584
+ const message = headline ? `Release ${tag}: ${headline}` : `Release ${tag}`;
585
+ const dir = mkdtempSync(join(tmpdir(), 'nuvira-release-'));
586
+ const msgFile = join(dir, 'commit-msg.txt');
587
+ writeFileSync(msgFile, message + '\n', 'utf-8');
588
+ const commit = run(`git commit -F "${msgFile}"`, 60_000);
589
+ try {
590
+ unlinkSync(msgFile);
591
+ }
592
+ catch { /* best-effort */ }
593
+ if (!commit.ok) {
594
+ return { success: false, summary: 'git commit failed', error: tail(commit.output) };
595
+ }
596
+ committed = true;
597
+ }
598
+ const existingTag = run(`git tag -l "${tag}"`, 15_000);
599
+ let createdTag = false;
600
+ if (!existingTag.ok || existingTag.output.trim() !== tag) {
601
+ const tagResult = run(`git tag -a "${tag}" -m "Release ${tag}"`, 30_000);
602
+ if (!tagResult.ok) {
603
+ return { success: false, summary: `Failed to create tag ${tag}`, error: tail(tagResult.output) };
604
+ }
605
+ createdTag = true;
606
+ }
607
+ const pushBranch = run(`git push -u "${remote}" "${branch}"`, 180_000);
608
+ if (!pushBranch.ok) {
609
+ return {
610
+ success: false,
611
+ summary: `Push to ${remote}/${branch} failed`,
612
+ error: tail(pushBranch.output, 400),
613
+ };
614
+ }
615
+ const pushTag = run(`git push "${remote}" "${tag}"`, 120_000);
616
+ if (!pushTag.ok) {
617
+ return {
618
+ success: false,
619
+ summary: `Committed and pushed ${branch}, but pushing tag ${tag} failed`,
620
+ error: tail(pushTag.output, 400),
621
+ };
622
+ }
623
+ const parts = [committed ? `committed ${changedCount} file(s)` : 'nothing to commit',
624
+ createdTag ? `tagged ${tag}` : `${tag} already existed`,
625
+ `pushed to ${remote}/${branch}`,
626
+ `${stagedNote}${nestedNote}`,
627
+ ];
628
+ return { success: true, summary: parts.join('; ') };
629
+ }
630
+ // ─── Phase 4: npm build + publish ───────────────────────────────────────────
631
+ /** Turn npm's exit text into the sentence the user needs. */
632
+ export function describeNpmError(output) {
633
+ if (output.includes('ENEEDAUTH'))
634
+ return 'Authentication required — set NPM_TOKEN (nuvira credentials set NPM_TOKEN)';
635
+ if (output.includes('E403') || /\b403\b/.test(output) || output.includes('not_logged_in') || output.includes('unauthorized')) {
636
+ return 'Not authorized to publish — check the npm token and its permissions';
637
+ }
638
+ if (output.includes('cannot publish over previously published version')) {
639
+ return 'Version already published — bump to a new version';
640
+ }
641
+ if (output.includes('E402') || output.includes('unpaid'))
642
+ return 'Payment required — check the npm account';
643
+ if (output.includes('E404'))
644
+ return 'Package not found — check the name and registry';
645
+ return tail(output, 400);
646
+ }
647
+ export async function runNpmPhase() {
648
+ const manifest = readManifest();
649
+ if (!manifest) {
650
+ return { success: false, summary: 'No package.json found', error: 'Cannot publish without a manifest' };
651
+ }
652
+ const version = manifest.version || '';
653
+ if (manifest.scripts?.build) {
654
+ const build = run('npm run build', 1_200_000);
655
+ if (!build.ok) {
656
+ return { success: false, summary: 'Build failed — publish aborted', error: tail(build.output, 400) };
657
+ }
658
+ }
659
+ // `npm publish` runs the project's own `prepublishOnly` — here that is
660
+ // `npm run build && npm test`, which takes ~10 minutes on this repo. Timing
661
+ // out mid-publish would leave a release half-shipped, so this is deliberately
662
+ // long rather than tidy.
663
+ const publish = run('npm publish', 2_700_000);
664
+ if (!publish.ok) {
665
+ return { success: false, summary: `npm publish failed for ${version}`, error: describeNpmError(publish.output) };
666
+ }
667
+ return { success: true, summary: `Published agent-nuvira@${version} to the npm registry`, details: tail(publish.output, 400) };
668
+ }
669
+ // ─── Phase 5: GitHub release ────────────────────────────────────────────────
670
+ export async function runGitHubReleasePhase() {
671
+ const gh = run('gh --version', 15_000);
672
+ if (!gh.ok) {
673
+ return {
674
+ success: false,
675
+ summary: 'GitHub CLI not available',
676
+ error: 'Install the gh CLI (https://cli.github.com) or create the release from the pushed tag',
677
+ };
678
+ }
679
+ const version = readVersion();
680
+ if (!version) {
681
+ return { success: false, summary: 'Cannot name a release without a version', error: 'package.json has no version' };
682
+ }
683
+ const tag = `v${version}`;
684
+ const existing = run(`gh release view "${tag}"`, 30_000);
685
+ if (existing.ok) {
686
+ return { success: true, summary: `GitHub release ${tag} already exists` };
687
+ }
688
+ // Notes come from the changelog section for this version; when nobody wrote
689
+ // one, fall back to the commit list rather than shipping an empty release.
690
+ const section = changelogSection(version, readChangelog());
691
+ const notes = section || commitsSince(lastReleaseTag()).map((c) => `- ${c}`).join('\n') || `Release ${tag}`;
692
+ const dir = mkdtempSync(join(tmpdir(), 'nuvira-release-notes-'));
693
+ const notesFile = join(dir, 'notes.md');
694
+ writeFileSync(notesFile, notes + '\n', 'utf-8');
695
+ const create = run(`gh release create "${tag}" --title "${tag}" --notes-file "${notesFile}"`, 120_000);
696
+ try {
697
+ unlinkSync(notesFile);
698
+ }
699
+ catch { /* best-effort */ }
700
+ if (!create.ok) {
701
+ return { success: false, summary: `Could not create GitHub release ${tag}`, error: tail(create.output, 400) };
702
+ }
703
+ return { success: true, summary: `Created GitHub release ${tag}`, details: tail(create.output, 200) };
704
+ }
705
+ // ─── Runner table ───────────────────────────────────────────────────────────
706
+ /**
707
+ * The deterministic implementation for every phase `buildPublishPhases`
708
+ * produces. A phase whose id is absent here keeps the orchestrator.
709
+ */
710
+ export function createReleaseRunners(bumpType) {
711
+ return {
712
+ [RELEASE_PHASE_IDS.tests]: runTestsPhase,
713
+ [RELEASE_PHASE_IDS.version]: () => runVersionBumpPhase(bumpType),
714
+ [RELEASE_PHASE_IDS.git]: runGitPhase,
715
+ [RELEASE_PHASE_IDS.npm]: runNpmPhase,
716
+ [RELEASE_PHASE_IDS.github]: runGitHubReleasePhase,
717
+ };
718
+ }
719
+ //# sourceMappingURL=release-runner.js.map