izanagi-ai 3.17.1 → 3.20.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 (378) hide show
  1. package/.manifest +21 -21
  2. package/AGENTS.md +11 -11
  3. package/CHANGELOG.md +198 -0
  4. package/README.md +306 -276
  5. package/ROADMAP.md +542 -222
  6. package/RULES.md +27 -34
  7. package/SYSTEM.md +393 -311
  8. package/dist/cli/commands/approve.d.ts +6 -1
  9. package/dist/cli/commands/approve.d.ts.map +1 -1
  10. package/dist/cli/commands/approve.js +9 -3
  11. package/dist/cli/commands/approve.js.map +1 -1
  12. package/dist/cli/commands/benchmark.d.ts +6 -1
  13. package/dist/cli/commands/benchmark.d.ts.map +1 -1
  14. package/dist/cli/commands/benchmark.js +190 -16
  15. package/dist/cli/commands/benchmark.js.map +1 -1
  16. package/dist/cli/commands/dashboard.d.ts +6 -1
  17. package/dist/cli/commands/dashboard.d.ts.map +1 -1
  18. package/dist/cli/commands/dashboard.js +9 -3
  19. package/dist/cli/commands/dashboard.js.map +1 -1
  20. package/dist/cli/commands/diagnose.d.ts +6 -1
  21. package/dist/cli/commands/diagnose.d.ts.map +1 -1
  22. package/dist/cli/commands/diagnose.js +10 -5
  23. package/dist/cli/commands/diagnose.js.map +1 -1
  24. package/dist/cli/commands/doctor.d.ts +6 -1
  25. package/dist/cli/commands/doctor.d.ts.map +1 -1
  26. package/dist/cli/commands/doctor.js +10 -5
  27. package/dist/cli/commands/doctor.js.map +1 -1
  28. package/dist/cli/commands/explain.d.ts.map +1 -1
  29. package/dist/cli/commands/explain.js +31 -0
  30. package/dist/cli/commands/explain.js.map +1 -1
  31. package/dist/cli/commands/memory.d.ts +7 -1
  32. package/dist/cli/commands/memory.d.ts.map +1 -1
  33. package/dist/cli/commands/memory.js +10 -4
  34. package/dist/cli/commands/memory.js.map +1 -1
  35. package/dist/cli/commands/models.d.ts.map +1 -1
  36. package/dist/cli/commands/models.js +36 -4
  37. package/dist/cli/commands/models.js.map +1 -1
  38. package/dist/cli/commands/reject.d.ts +6 -1
  39. package/dist/cli/commands/reject.d.ts.map +1 -1
  40. package/dist/cli/commands/reject.js +9 -3
  41. package/dist/cli/commands/reject.js.map +1 -1
  42. package/dist/cli/commands/resume.d.ts +6 -1
  43. package/dist/cli/commands/resume.d.ts.map +1 -1
  44. package/dist/cli/commands/resume.js +8 -2
  45. package/dist/cli/commands/resume.js.map +1 -1
  46. package/dist/cli/commands/run.d.ts +66 -1
  47. package/dist/cli/commands/run.d.ts.map +1 -1
  48. package/dist/cli/commands/run.js +301 -8
  49. package/dist/cli/commands/run.js.map +1 -1
  50. package/dist/cli/commands/trace.js +2 -0
  51. package/dist/cli/commands/trace.js.map +1 -1
  52. package/dist/cli/index.d.ts.map +1 -1
  53. package/dist/cli/index.js +110 -83
  54. package/dist/cli/index.js.map +1 -1
  55. package/dist/installer.d.ts +19 -0
  56. package/dist/installer.d.ts.map +1 -1
  57. package/dist/installer.js +25 -0
  58. package/dist/installer.js.map +1 -1
  59. package/dist/runtime/artifacts/registry.d.ts +152 -0
  60. package/dist/runtime/artifacts/registry.d.ts.map +1 -1
  61. package/dist/runtime/artifacts/registry.js +207 -0
  62. package/dist/runtime/artifacts/registry.js.map +1 -1
  63. package/dist/runtime/benchmarks/arena.d.ts +96 -1
  64. package/dist/runtime/benchmarks/arena.d.ts.map +1 -1
  65. package/dist/runtime/benchmarks/arena.js +76 -1
  66. package/dist/runtime/benchmarks/arena.js.map +1 -1
  67. package/dist/runtime/benchmarks/registry.d.ts +39 -2
  68. package/dist/runtime/benchmarks/registry.d.ts.map +1 -1
  69. package/dist/runtime/benchmarks/registry.js +167 -12
  70. package/dist/runtime/benchmarks/registry.js.map +1 -1
  71. package/dist/runtime/benchmarks/runner.d.ts +51 -1
  72. package/dist/runtime/benchmarks/runner.d.ts.map +1 -1
  73. package/dist/runtime/benchmarks/runner.js +110 -17
  74. package/dist/runtime/benchmarks/runner.js.map +1 -1
  75. package/dist/runtime/contracts/acceptance.d.ts +66 -0
  76. package/dist/runtime/contracts/acceptance.d.ts.map +1 -0
  77. package/dist/runtime/contracts/acceptance.js +179 -0
  78. package/dist/runtime/contracts/acceptance.js.map +1 -0
  79. package/dist/runtime/contracts/artifacts.d.ts.map +1 -1
  80. package/dist/runtime/contracts/artifacts.js +55 -1
  81. package/dist/runtime/contracts/artifacts.js.map +1 -1
  82. package/dist/runtime/contracts/task-contract.d.ts +25 -0
  83. package/dist/runtime/contracts/task-contract.d.ts.map +1 -1
  84. package/dist/runtime/contracts/task-contract.js.map +1 -1
  85. package/dist/runtime/execute.d.ts +66 -3
  86. package/dist/runtime/execute.d.ts.map +1 -1
  87. package/dist/runtime/execute.js +116 -9
  88. package/dist/runtime/execute.js.map +1 -1
  89. package/dist/runtime/llm/client.d.ts +6 -0
  90. package/dist/runtime/llm/client.d.ts.map +1 -1
  91. package/dist/runtime/llm/client.js +12 -3
  92. package/dist/runtime/llm/client.js.map +1 -1
  93. package/dist/runtime/memory/decisions.d.ts +56 -0
  94. package/dist/runtime/memory/decisions.d.ts.map +1 -1
  95. package/dist/runtime/memory/decisions.js +77 -0
  96. package/dist/runtime/memory/decisions.js.map +1 -1
  97. package/dist/runtime/memory/store.d.ts +36 -1
  98. package/dist/runtime/memory/store.d.ts.map +1 -1
  99. package/dist/runtime/memory/store.js +77 -0
  100. package/dist/runtime/memory/store.js.map +1 -1
  101. package/dist/runtime/model/router.d.ts +19 -0
  102. package/dist/runtime/model/router.d.ts.map +1 -1
  103. package/dist/runtime/model/router.js +52 -5
  104. package/dist/runtime/model/router.js.map +1 -1
  105. package/dist/runtime/notify/webhook.d.ts +27 -0
  106. package/dist/runtime/notify/webhook.d.ts.map +1 -1
  107. package/dist/runtime/notify/webhook.js +11 -0
  108. package/dist/runtime/notify/webhook.js.map +1 -1
  109. package/dist/runtime/observability/events.d.ts +1 -1
  110. package/dist/runtime/observability/events.d.ts.map +1 -1
  111. package/dist/runtime/observability/events.js.map +1 -1
  112. package/dist/runtime/orchestration/commander.d.ts +142 -0
  113. package/dist/runtime/orchestration/commander.d.ts.map +1 -1
  114. package/dist/runtime/orchestration/commander.js +400 -13
  115. package/dist/runtime/orchestration/commander.js.map +1 -1
  116. package/dist/runtime/orchestration/context-resolver.d.ts +35 -0
  117. package/dist/runtime/orchestration/context-resolver.d.ts.map +1 -1
  118. package/dist/runtime/orchestration/context-resolver.js +85 -33
  119. package/dist/runtime/orchestration/context-resolver.js.map +1 -1
  120. package/dist/runtime/orchestration/deadline.d.ts +57 -0
  121. package/dist/runtime/orchestration/deadline.d.ts.map +1 -0
  122. package/dist/runtime/orchestration/deadline.js +114 -0
  123. package/dist/runtime/orchestration/deadline.js.map +1 -0
  124. package/dist/runtime/orchestration/delivery.d.ts +139 -0
  125. package/dist/runtime/orchestration/delivery.d.ts.map +1 -0
  126. package/dist/runtime/orchestration/delivery.js +310 -0
  127. package/dist/runtime/orchestration/delivery.js.map +1 -0
  128. package/dist/runtime/orchestration/grounding.d.ts +41 -0
  129. package/dist/runtime/orchestration/grounding.d.ts.map +1 -0
  130. package/dist/runtime/orchestration/grounding.js +94 -0
  131. package/dist/runtime/orchestration/grounding.js.map +1 -0
  132. package/dist/runtime/orchestration/subgraph.d.ts +5 -0
  133. package/dist/runtime/orchestration/subgraph.d.ts.map +1 -1
  134. package/dist/runtime/orchestration/subgraph.js +38 -5
  135. package/dist/runtime/orchestration/subgraph.js.map +1 -1
  136. package/dist/runtime/orchestration/test-gate.d.ts +46 -0
  137. package/dist/runtime/orchestration/test-gate.d.ts.map +1 -0
  138. package/dist/runtime/orchestration/test-gate.js +88 -0
  139. package/dist/runtime/orchestration/test-gate.js.map +1 -0
  140. package/dist/runtime/orchestrator.d.ts +140 -3
  141. package/dist/runtime/orchestrator.d.ts.map +1 -1
  142. package/dist/runtime/orchestrator.js +585 -34
  143. package/dist/runtime/orchestrator.js.map +1 -1
  144. package/dist/runtime/recovery/healing.d.ts +28 -1
  145. package/dist/runtime/recovery/healing.d.ts.map +1 -1
  146. package/dist/runtime/recovery/healing.js +95 -15
  147. package/dist/runtime/recovery/healing.js.map +1 -1
  148. package/dist/runtime/registry/capabilities.d.ts +30 -0
  149. package/dist/runtime/registry/capabilities.d.ts.map +1 -1
  150. package/dist/runtime/registry/capabilities.js +23 -0
  151. package/dist/runtime/registry/capabilities.js.map +1 -1
  152. package/dist/runtime/routing/resolver.d.ts +18 -1
  153. package/dist/runtime/routing/resolver.d.ts.map +1 -1
  154. package/dist/runtime/routing/resolver.js +52 -11
  155. package/dist/runtime/routing/resolver.js.map +1 -1
  156. package/dist/runtime/security/policy.d.ts +21 -0
  157. package/dist/runtime/security/policy.d.ts.map +1 -1
  158. package/dist/runtime/security/policy.js +38 -0
  159. package/dist/runtime/security/policy.js.map +1 -1
  160. package/dist/runtime/tests/acceptance.test.d.ts +10 -0
  161. package/dist/runtime/tests/acceptance.test.d.ts.map +1 -0
  162. package/dist/runtime/tests/acceptance.test.js +160 -0
  163. package/dist/runtime/tests/acceptance.test.js.map +1 -0
  164. package/dist/runtime/tests/arena.test.js +125 -2
  165. package/dist/runtime/tests/arena.test.js.map +1 -1
  166. package/dist/runtime/tests/artifact-reuse.test.d.ts +13 -0
  167. package/dist/runtime/tests/artifact-reuse.test.d.ts.map +1 -0
  168. package/dist/runtime/tests/artifact-reuse.test.js +192 -0
  169. package/dist/runtime/tests/artifact-reuse.test.js.map +1 -0
  170. package/dist/runtime/tests/benchmark-report-path.test.d.ts +15 -0
  171. package/dist/runtime/tests/benchmark-report-path.test.d.ts.map +1 -0
  172. package/dist/runtime/tests/benchmark-report-path.test.js +120 -0
  173. package/dist/runtime/tests/benchmark-report-path.test.js.map +1 -0
  174. package/dist/runtime/tests/benchmark.test.js +18 -0
  175. package/dist/runtime/tests/benchmark.test.js.map +1 -1
  176. package/dist/runtime/tests/budget-cache.test.js +122 -5
  177. package/dist/runtime/tests/budget-cache.test.js.map +1 -1
  178. package/dist/runtime/tests/budget-ceilings.test.d.ts +2 -0
  179. package/dist/runtime/tests/budget-ceilings.test.d.ts.map +1 -0
  180. package/dist/runtime/tests/budget-ceilings.test.js +162 -0
  181. package/dist/runtime/tests/budget-ceilings.test.js.map +1 -0
  182. package/dist/runtime/tests/cancellation.test.d.ts +2 -0
  183. package/dist/runtime/tests/cancellation.test.d.ts.map +1 -0
  184. package/dist/runtime/tests/cancellation.test.js +171 -0
  185. package/dist/runtime/tests/cancellation.test.js.map +1 -0
  186. package/dist/runtime/tests/capability-fields.test.d.ts +2 -0
  187. package/dist/runtime/tests/capability-fields.test.d.ts.map +1 -0
  188. package/dist/runtime/tests/capability-fields.test.js +76 -0
  189. package/dist/runtime/tests/capability-fields.test.js.map +1 -0
  190. package/dist/runtime/tests/checkpoint.test.js +11 -0
  191. package/dist/runtime/tests/checkpoint.test.js.map +1 -1
  192. package/dist/runtime/tests/concurrency-degradation.test.js +27 -0
  193. package/dist/runtime/tests/concurrency-degradation.test.js.map +1 -1
  194. package/dist/runtime/tests/critique-loop.test.js +1 -0
  195. package/dist/runtime/tests/critique-loop.test.js.map +1 -1
  196. package/dist/runtime/tests/deadline.test.d.ts +2 -0
  197. package/dist/runtime/tests/deadline.test.d.ts.map +1 -0
  198. package/dist/runtime/tests/deadline.test.js +94 -0
  199. package/dist/runtime/tests/deadline.test.js.map +1 -0
  200. package/dist/runtime/tests/decision-journal.test.d.ts +10 -0
  201. package/dist/runtime/tests/decision-journal.test.d.ts.map +1 -0
  202. package/dist/runtime/tests/decision-journal.test.js +104 -0
  203. package/dist/runtime/tests/decision-journal.test.js.map +1 -0
  204. package/dist/runtime/tests/delivery.test.d.ts +10 -0
  205. package/dist/runtime/tests/delivery.test.d.ts.map +1 -0
  206. package/dist/runtime/tests/delivery.test.js +348 -0
  207. package/dist/runtime/tests/delivery.test.js.map +1 -0
  208. package/dist/runtime/tests/doc-version-freshness.test.d.ts +2 -0
  209. package/dist/runtime/tests/doc-version-freshness.test.d.ts.map +1 -0
  210. package/dist/runtime/tests/doc-version-freshness.test.js +99 -0
  211. package/dist/runtime/tests/doc-version-freshness.test.js.map +1 -0
  212. package/dist/runtime/tests/e2e-scenarios.test.d.ts +15 -0
  213. package/dist/runtime/tests/e2e-scenarios.test.d.ts.map +1 -0
  214. package/dist/runtime/tests/e2e-scenarios.test.js +304 -0
  215. package/dist/runtime/tests/e2e-scenarios.test.js.map +1 -0
  216. package/dist/runtime/tests/frontmatter-block-list.test.d.ts +2 -0
  217. package/dist/runtime/tests/frontmatter-block-list.test.d.ts.map +1 -0
  218. package/dist/runtime/tests/frontmatter-block-list.test.js +103 -0
  219. package/dist/runtime/tests/frontmatter-block-list.test.js.map +1 -0
  220. package/dist/runtime/tests/groundedness.test.d.ts +15 -0
  221. package/dist/runtime/tests/groundedness.test.d.ts.map +1 -0
  222. package/dist/runtime/tests/groundedness.test.js +206 -0
  223. package/dist/runtime/tests/groundedness.test.js.map +1 -0
  224. package/dist/runtime/tests/grounding.test.d.ts +10 -0
  225. package/dist/runtime/tests/grounding.test.d.ts.map +1 -0
  226. package/dist/runtime/tests/grounding.test.js +254 -0
  227. package/dist/runtime/tests/grounding.test.js.map +1 -0
  228. package/dist/runtime/tests/healing.test.js +39 -0
  229. package/dist/runtime/tests/healing.test.js.map +1 -1
  230. package/dist/runtime/tests/human-required.test.d.ts +10 -0
  231. package/dist/runtime/tests/human-required.test.d.ts.map +1 -0
  232. package/dist/runtime/tests/human-required.test.js +126 -0
  233. package/dist/runtime/tests/human-required.test.js.map +1 -0
  234. package/dist/runtime/tests/judge.test.js +33 -4
  235. package/dist/runtime/tests/judge.test.js.map +1 -1
  236. package/dist/runtime/tests/lineage.test.d.ts +9 -0
  237. package/dist/runtime/tests/lineage.test.d.ts.map +1 -0
  238. package/dist/runtime/tests/lineage.test.js +113 -0
  239. package/dist/runtime/tests/lineage.test.js.map +1 -0
  240. package/dist/runtime/tests/materialize.test.d.ts +15 -0
  241. package/dist/runtime/tests/materialize.test.d.ts.map +1 -0
  242. package/dist/runtime/tests/materialize.test.js +241 -0
  243. package/dist/runtime/tests/materialize.test.js.map +1 -0
  244. package/dist/runtime/tests/model-catalog-freshness.test.d.ts +17 -0
  245. package/dist/runtime/tests/model-catalog-freshness.test.d.ts.map +1 -0
  246. package/dist/runtime/tests/model-catalog-freshness.test.js +91 -0
  247. package/dist/runtime/tests/model-catalog-freshness.test.js.map +1 -0
  248. package/dist/runtime/tests/model-role-routing.test.js +16 -5
  249. package/dist/runtime/tests/model-role-routing.test.js.map +1 -1
  250. package/dist/runtime/tests/model.test.js +7 -2
  251. package/dist/runtime/tests/model.test.js.map +1 -1
  252. package/dist/runtime/tests/optional-reinforcement.test.d.ts +2 -0
  253. package/dist/runtime/tests/optional-reinforcement.test.d.ts.map +1 -0
  254. package/dist/runtime/tests/optional-reinforcement.test.js +60 -0
  255. package/dist/runtime/tests/optional-reinforcement.test.js.map +1 -0
  256. package/dist/runtime/tests/orchestrator.test.js +5 -0
  257. package/dist/runtime/tests/orchestrator.test.js.map +1 -1
  258. package/dist/runtime/tests/plan-candidates.test.d.ts +10 -0
  259. package/dist/runtime/tests/plan-candidates.test.d.ts.map +1 -0
  260. package/dist/runtime/tests/plan-candidates.test.js +107 -0
  261. package/dist/runtime/tests/plan-candidates.test.js.map +1 -0
  262. package/dist/runtime/tests/policy-external-tool.test.d.ts +10 -0
  263. package/dist/runtime/tests/policy-external-tool.test.d.ts.map +1 -0
  264. package/dist/runtime/tests/policy-external-tool.test.js +116 -0
  265. package/dist/runtime/tests/policy-external-tool.test.js.map +1 -0
  266. package/dist/runtime/tests/project-test.test.d.ts +10 -0
  267. package/dist/runtime/tests/project-test.test.d.ts.map +1 -0
  268. package/dist/runtime/tests/project-test.test.js +177 -0
  269. package/dist/runtime/tests/project-test.test.js.map +1 -0
  270. package/dist/runtime/tests/replan-reachability.test.d.ts +2 -0
  271. package/dist/runtime/tests/replan-reachability.test.d.ts.map +1 -0
  272. package/dist/runtime/tests/replan-reachability.test.js +129 -0
  273. package/dist/runtime/tests/replan-reachability.test.js.map +1 -0
  274. package/dist/runtime/tests/replan.test.js +1 -0
  275. package/dist/runtime/tests/replan.test.js.map +1 -1
  276. package/dist/runtime/tests/routing-per-node.test.d.ts +2 -0
  277. package/dist/runtime/tests/routing-per-node.test.d.ts.map +1 -0
  278. package/dist/runtime/tests/routing-per-node.test.js +84 -0
  279. package/dist/runtime/tests/routing-per-node.test.js.map +1 -0
  280. package/dist/runtime/tests/run-guarantees.test.d.ts +2 -0
  281. package/dist/runtime/tests/run-guarantees.test.d.ts.map +1 -0
  282. package/dist/runtime/tests/run-guarantees.test.js +230 -0
  283. package/dist/runtime/tests/run-guarantees.test.js.map +1 -0
  284. package/dist/runtime/tests/scheduler.test.js +16 -0
  285. package/dist/runtime/tests/scheduler.test.js.map +1 -1
  286. package/dist/runtime/tests/semantic-memory.test.d.ts +9 -0
  287. package/dist/runtime/tests/semantic-memory.test.d.ts.map +1 -0
  288. package/dist/runtime/tests/semantic-memory.test.js +105 -0
  289. package/dist/runtime/tests/semantic-memory.test.js.map +1 -0
  290. package/dist/runtime/tests/skill-metadata.test.d.ts +14 -0
  291. package/dist/runtime/tests/skill-metadata.test.d.ts.map +1 -0
  292. package/dist/runtime/tests/skill-metadata.test.js +97 -0
  293. package/dist/runtime/tests/skill-metadata.test.js.map +1 -0
  294. package/dist/runtime/tests/state-root.test.d.ts +15 -0
  295. package/dist/runtime/tests/state-root.test.d.ts.map +1 -0
  296. package/dist/runtime/tests/state-root.test.js +108 -0
  297. package/dist/runtime/tests/state-root.test.js.map +1 -0
  298. package/dist/runtime/tests/subgraph.test.js +32 -0
  299. package/dist/runtime/tests/subgraph.test.js.map +1 -1
  300. package/dist/runtime/tests/tool-node.test.js +1 -0
  301. package/dist/runtime/tests/tool-node.test.js.map +1 -1
  302. package/dist/runtime/tests/trajectories.test.js +1 -1
  303. package/dist/runtime/tests/trajectories.test.js.map +1 -1
  304. package/dist/runtime/token/budget.d.ts +12 -0
  305. package/dist/runtime/token/budget.d.ts.map +1 -1
  306. package/dist/runtime/token/budget.js +17 -0
  307. package/dist/runtime/token/budget.js.map +1 -1
  308. package/dist/runtime/token/execution-budget.d.ts +9 -0
  309. package/dist/runtime/token/execution-budget.d.ts.map +1 -1
  310. package/dist/runtime/token/execution-budget.js +39 -12
  311. package/dist/runtime/token/execution-budget.js.map +1 -1
  312. package/dist/runtime/tools/file-manifest.d.ts +83 -0
  313. package/dist/runtime/tools/file-manifest.d.ts.map +1 -0
  314. package/dist/runtime/tools/file-manifest.js +182 -0
  315. package/dist/runtime/tools/file-manifest.js.map +1 -0
  316. package/dist/runtime/tools/input-refs.d.ts +58 -0
  317. package/dist/runtime/tools/input-refs.d.ts.map +1 -0
  318. package/dist/runtime/tools/input-refs.js +112 -0
  319. package/dist/runtime/tools/input-refs.js.map +1 -0
  320. package/dist/runtime/tools/project-survey.d.ts +85 -0
  321. package/dist/runtime/tools/project-survey.d.ts.map +1 -0
  322. package/dist/runtime/tools/project-survey.js +232 -0
  323. package/dist/runtime/tools/project-survey.js.map +1 -0
  324. package/dist/runtime/tools/project-test.d.ts +132 -0
  325. package/dist/runtime/tools/project-test.d.ts.map +1 -0
  326. package/dist/runtime/tools/project-test.js +253 -0
  327. package/dist/runtime/tools/project-test.js.map +1 -0
  328. package/dist/runtime/tools/registry.d.ts +20 -1
  329. package/dist/runtime/tools/registry.d.ts.map +1 -1
  330. package/dist/runtime/tools/registry.js +118 -1
  331. package/dist/runtime/tools/registry.js.map +1 -1
  332. package/dist/runtime/types.d.ts +98 -1
  333. package/dist/runtime/types.d.ts.map +1 -1
  334. package/dist/runtime/verification/engine.d.ts +42 -3
  335. package/dist/runtime/verification/engine.d.ts.map +1 -1
  336. package/dist/runtime/verification/engine.js +68 -3
  337. package/dist/runtime/verification/engine.js.map +1 -1
  338. package/dist/runtime/verification/groundedness.d.ts +66 -0
  339. package/dist/runtime/verification/groundedness.d.ts.map +1 -0
  340. package/dist/runtime/verification/groundedness.js +168 -0
  341. package/dist/runtime/verification/groundedness.js.map +1 -0
  342. package/dist/scripts/bump.js +7 -0
  343. package/dist/scripts/bump.js.map +1 -1
  344. package/dist/scripts/doc-version.d.ts +46 -0
  345. package/dist/scripts/doc-version.d.ts.map +1 -0
  346. package/dist/scripts/doc-version.js +87 -0
  347. package/dist/scripts/doc-version.js.map +1 -0
  348. package/dist/scripts/release.js +13 -0
  349. package/dist/scripts/release.js.map +1 -1
  350. package/dist/sdk.d.ts +109 -3
  351. package/dist/sdk.d.ts.map +1 -1
  352. package/dist/sdk.js +62 -2
  353. package/dist/sdk.js.map +1 -1
  354. package/docs/HANDOFF.md +123 -9
  355. package/docs/RUNTIME-PENDING.md +122 -72
  356. package/package.json +100 -100
  357. package/skills/animation-web/SKILL.md +11 -0
  358. package/skills/anti-ai-slop/SKILL.md +10 -0
  359. package/skills/conversion-copywriting/SKILL.md +73 -64
  360. package/skills/deep-research/SKILL.md +9 -0
  361. package/skills/design-directions/SKILL.md +11 -0
  362. package/skills/editorial-layout/SKILL.md +94 -85
  363. package/skills/frontend/SKILL.md +12 -0
  364. package/skills/graphql/SKILL.md +11 -0
  365. package/skills/iac-terraform/SKILL.md +10 -0
  366. package/skills/logging-expert/SKILL.md +9 -0
  367. package/skills/memoria-projeto/SKILL.md +10 -0
  368. package/skills/motion-design/SKILL.md +11 -0
  369. package/skills/observability-expert/SKILL.md +11 -0
  370. package/skills/parallel-agents/SKILL.md +9 -0
  371. package/skills/payments-billing/SKILL.md +100 -89
  372. package/skills/qa/SKILL.md +14 -0
  373. package/skills/security-privacy/SKILL.md +11 -0
  374. package/skills/software-architect/SKILL.md +12 -0
  375. package/skills/tdd/SKILL.md +10 -0
  376. package/skills/ui-ux-pro-max/SKILL.md +12 -0
  377. package/skills/web-perf-seo/SKILL.md +12 -0
  378. package/skills/webgl-3d/SKILL.md +10 -0
package/.manifest CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "izanagi-ai",
3
- "version": "3.17.1",
3
+ "version": "3.20.1",
4
4
  "description": "Izanagi AI - Modular Skill-Oriented AI Prompt & Agent Framework for Autonomous Software Engineering",
5
5
  "author": "Pedro Henrique Sanches Leal",
6
6
  "license": "MIT",
7
7
  "homepage": "https://github.com/pedrohenriquesanchesleal4-debug/izanagi-ai#readme",
8
- "generatedAt": "2026-09-02T13:43:32.890Z",
8
+ "generatedAt": "2026-09-08T13:16:30.474Z",
9
9
  "agents": [
10
10
  {
11
11
  "id": "adversarial-critic",
@@ -541,7 +541,7 @@
541
541
  },
542
542
  {
543
543
  "id": "ai-slop",
544
- "name": "Anti AI-Slop (Zero \"Cara de IA\")",
544
+ "name": "anti-ai-slop",
545
545
  "version": "1.0.0",
546
546
  "path": "skills/anti-ai-slop/SKILL.md"
547
547
  },
@@ -565,7 +565,7 @@
565
565
  },
566
566
  {
567
567
  "id": "architect",
568
- "name": "Software Architect",
568
+ "name": "software-architect",
569
569
  "version": "1.0.0",
570
570
  "path": "skills/software-architect/SKILL.md"
571
571
  },
@@ -619,7 +619,7 @@
619
619
  },
620
620
  {
621
621
  "id": "billing",
622
- "name": "Skill Payments & Billing — Izanagi",
622
+ "name": "payments-billing",
623
623
  "version": "1.0.0",
624
624
  "path": "skills/payments-billing/SKILL.md"
625
625
  },
@@ -703,7 +703,7 @@
703
703
  },
704
704
  {
705
705
  "id": "conversion-copywriting",
706
- "name": "Skill Conversion Copywriting — Izanagi",
706
+ "name": "conversion-copywriting",
707
707
  "version": "1.0.0",
708
708
  "path": "skills/conversion-copywriting/SKILL.md"
709
709
  },
@@ -739,7 +739,7 @@
739
739
  },
740
740
  {
741
741
  "id": "deep-research",
742
- "name": "Deep Research — Pesquisa Multi-Fonte com Síntese",
742
+ "name": "deep-research",
743
743
  "version": "1.0.0",
744
744
  "path": "skills/deep-research/SKILL.md"
745
745
  },
@@ -751,7 +751,7 @@
751
751
  },
752
752
  {
753
753
  "id": "design-directions",
754
- "name": "Design Directions (Style Selector por Indústria)",
754
+ "name": "design-directions",
755
755
  "version": "1.0.0",
756
756
  "path": "skills/design-directions/SKILL.md"
757
757
  },
@@ -763,7 +763,7 @@
763
763
  },
764
764
  {
765
765
  "id": "design-system",
766
- "name": "UI/UX Pro Max — Design Intelligence",
766
+ "name": "ui-ux-pro-max",
767
767
  "version": "1.0.0",
768
768
  "path": "skills/ui-ux-pro-max/SKILL.md"
769
769
  },
@@ -793,7 +793,7 @@
793
793
  },
794
794
  {
795
795
  "id": "editorial-layout",
796
- "name": "Skill Editorial Layout — Izanagi",
796
+ "name": "editorial-layout",
797
797
  "version": "1.0.0",
798
798
  "path": "skills/editorial-layout/SKILL.md"
799
799
  },
@@ -817,7 +817,7 @@
817
817
  },
818
818
  {
819
819
  "id": "fan-out",
820
- "name": "Parallel Agents (Fan-Out & Swarm Orchestration)",
820
+ "name": "parallel-agents",
821
821
  "version": "1.0.0",
822
822
  "path": "skills/parallel-agents/SKILL.md"
823
823
  },
@@ -835,13 +835,13 @@
835
835
  },
836
836
  {
837
837
  "id": "frontend",
838
- "name": "Skill Frontend — Izanagi",
838
+ "name": "frontend",
839
839
  "version": "1.0.0",
840
840
  "path": "skills/frontend/SKILL.md"
841
841
  },
842
842
  {
843
843
  "id": "graphql",
844
- "name": "Skill GraphQL — Izanagi",
844
+ "name": "graphql",
845
845
  "version": "1.0.0",
846
846
  "path": "skills/graphql/SKILL.md"
847
847
  },
@@ -871,7 +871,7 @@
871
871
  },
872
872
  {
873
873
  "id": "iac-terraform",
874
- "name": "Skill IaC & Terraform — Izanagi",
874
+ "name": "iac-terraform",
875
875
  "version": "1.0.0",
876
876
  "path": "skills/iac-terraform/SKILL.md"
877
877
  },
@@ -883,7 +883,7 @@
883
883
  },
884
884
  {
885
885
  "id": "logging",
886
- "name": "Logging Expert",
886
+ "name": "logging-expert",
887
887
  "version": "1.0.0",
888
888
  "path": "skills/logging-expert/SKILL.md"
889
889
  },
@@ -895,7 +895,7 @@
895
895
  },
896
896
  {
897
897
  "id": "memoria-projeto",
898
- "name": "Memória do projeto",
898
+ "name": "memoria-projeto",
899
899
  "version": "1.0.0",
900
900
  "path": "skills/memoria-projeto/SKILL.md"
901
901
  },
@@ -919,7 +919,7 @@
919
919
  },
920
920
  {
921
921
  "id": "observability",
922
- "name": "Observability Expert (Tracing Distribuído e Logs Estruturados)",
922
+ "name": "observability-expert",
923
923
  "version": "1.0.0",
924
924
  "path": "skills/observability-expert/SKILL.md"
925
925
  },
@@ -961,7 +961,7 @@
961
961
  },
962
962
  {
963
963
  "id": "qa",
964
- "name": "Quality Assurance — Manual Operacional",
964
+ "name": "qa",
965
965
  "version": "1.0.0",
966
966
  "path": "skills/qa/SKILL.md"
967
967
  },
@@ -1015,7 +1015,7 @@
1015
1015
  },
1016
1016
  {
1017
1017
  "id": "security-privacy",
1018
- "name": "Security & Privacy — Manual Operacional",
1018
+ "name": "security-privacy",
1019
1019
  "version": "1.0.0",
1020
1020
  "path": "skills/security-privacy/SKILL.md"
1021
1021
  },
@@ -1069,7 +1069,7 @@
1069
1069
  },
1070
1070
  {
1071
1071
  "id": "tdd",
1072
- "name": "TDD — Test-Driven Development (Iron Law)",
1072
+ "name": "tdd",
1073
1073
  "version": "1.0.0",
1074
1074
  "path": "skills/tdd/SKILL.md"
1075
1075
  },
@@ -1129,7 +1129,7 @@
1129
1129
  },
1130
1130
  {
1131
1131
  "id": "web-perf-engineer",
1132
- "name": "Web Performance & SEO — Manual Operacional",
1132
+ "name": "web-perf-seo",
1133
1133
  "version": "1.0.0",
1134
1134
  "path": "skills/web-perf-seo/SKILL.md"
1135
1135
  },
package/AGENTS.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # AGENTS.md: Izanagi AI Framework Reference
2
2
 
3
- > Version 3.9.0
3
+ > Version 3.20.0
4
4
  > Modular Skill-Oriented AI Prompt & Agent Framework for Autonomous Software Engineering
5
5
  > Multi-CLI: Opencode · Claude Code · Codex · Cursor · Copilot · Kimi (Smart Auto-Detection & Selective Generation)
6
6
 
@@ -46,18 +46,18 @@ O framework conta com **22 agentes especializados** em `agents/*.json` + orquest
46
46
 
47
47
  ---
48
48
 
49
- ## 3. Arquitetura Poliglota (Waves 1–4)
49
+ ## 3. Arquitetura Poliglota
50
50
 
51
51
  Coexistência **Strangler Fig** (ADR-001): o legado npm (`src/`, CLI `izanagi`) permanece intocado e publicável; o crescimento novo vive num SDK TypeScript + 4 núcleos nativos, orquestrados pela CLI de nova geração (`packages/cli`, binário `izanagi-next`). Referência canônica de contratos IPC, error codes (`-32001..-32005`), env vars e ADRs: **`docs/POLYGLOT.md`** (ADRs integrais em `.agents/memoria/decisoes.md`, gitignored).
52
52
 
53
53
  | Componente | Linguagem | Responsabilidade | Como testar |
54
54
  |---|---|---|---|
55
- | `crates/izanagi_core` | Rust | Quality engine: 7 heurísticas anti-slop sobre TS/Python/Go; protocolo NDJSON stdin/stdout (`validate`/`rules`/`version`) + op `scan-rationalizations` (`--file=<path>` / `--stdin`, exit 0/1/2); bindings WASM feature-gated (`--features wasm`, subcomandos `--version`/`--help`) | `cargo test --workspace` (111 testes) · `cargo check -p izanagi_core --features wasm` |
55
+ | `crates/izanagi_core` | Rust | Quality engine: 7 heurísticas anti-slop sobre TS/Python/Go; protocolo NDJSON stdin/stdout (`validate`/`rules`/`version`) + op `scan-rationalizations` (`--file=<path>` / `--stdin`, exit 0/1/2); bindings WASM feature-gated (`--features wasm`, subcomandos `--version`/`--help`) | `cargo test --workspace` (126 testes declarados no fonte) · `cargo check -p izanagi_core --features wasm` |
56
56
  | `crates/izanagi_mcp` | Rust | Cliente MCP JSON-RPC 2.0 sobre stdio: discovery + invocação pontual (`izanagi-mcp call --tool=<name>`) | incluso no `cargo test --workspace` |
57
57
  | `go-services/swarm_orchestrator` | Go | Orquestrador de swarm (Uber Fx): pipeline architect→engineer→qa→security via JSON-RPC 2.0 sobre UDS com event push | `(cd go-services/swarm_orchestrator && go build ./... && go vet ./... && go test ./...)` |
58
- | `python-engine/ast_analyzer` | Python ≥3.10 | Análise semântica multilíngue: símbolos, complexidade ciclomática, imports (tree-sitter + fallback estrutural) | `(cd python-engine && .venv/bin/python -m pytest tests/ -q)` (70 testes) |
58
+ | `python-engine/ast_analyzer` | Python ≥3.10 | Análise semântica multilíngue: símbolos, complexidade ciclomática, imports (tree-sitter + fallback estrutural) | `(cd python-engine && .venv/bin/python -m pytest tests/ -q)` (41 testes; o venv não é versionado) |
59
59
  | `packages/sdk` | TypeScript | `@izanagi/sdk`: clientes tipados strict para os 4 núcleos + catálogo de skills; zero deps runtime | `(cd packages/sdk && npm install && npm test)` |
60
- | `packages/cli` | TypeScript | Binário `izanagi-next`: run em 4 fases com auto-heal (N=2), `agent list`, `skill list`, `gates check`; exit codes próprios (0 ok · 1 gate/falha · 2 uso · 3 ambiente) | smoke manual (`help`, `agent list`) — suíte própria pendente |
60
+ | `packages/cli` | TypeScript | Binário `izanagi-next`: run em 4 fases com auto-heal (N=2), `agent list`, `skill list`, `gates check`; exit codes próprios (0 ok · 1 gate/falha · 2 uso · 3 ambiente) | `npm test` dentro de `packages/cli` (13 testes em `tests/{run,skill}.test.ts`) |
61
61
  | `packages/skill-migrator` · `agent-migrator` | Node ESM | Migradores determinísticos idempotentes: skills v1→v2 (106 módulos) e agents JSON→YAML (22) — ADR-004/005 | `node packages/agent-migrator/cli.mjs --check` · `node packages/skill-migrator/cli.mjs --dry-run` |
62
62
 
63
63
  **Gotchas poliglotas:**
@@ -73,7 +73,7 @@ Coexistência **Strangler Fig** (ADR-001): o legado npm (`src/`, CLI `izanagi`)
73
73
  # Legado npm (raiz)
74
74
  npm install # instala deps
75
75
  npm run build # tsc && node dist/scripts/generate-manifest.js
76
- npm test # build + node --test dist/runtime/tests/*.test.js (284 testes)
76
+ npm test # build + node --test dist/runtime/tests/*.test.js (764 testes)
77
77
  npm run verify # build + teste de instalação em sandbox (passa todos os pack IDs)
78
78
  npm run doctor # node bin/izanagi.js doctor [--deep]: auditoria de integridade
79
79
  npm run bump:patch # npm version patch --no-git-tag-version (também minor/major)
@@ -81,7 +81,7 @@ npm publish # prepublishOnly roda build; depois: git push
81
81
 
82
82
  # Núcleos poliglotas
83
83
  cargo build --workspace # Rust: bins izanagi-core / izanagi-mcp em target/debug/
84
- cargo test --workspace # 111 testes (core + mcp)
84
+ cargo test --workspace # 126 testes declarados no fonte (core + mcp)
85
85
  cargo check -p izanagi_core --features wasm # type-check dos bindings WASM (ADR-003)
86
86
  (cd go-services/swarm_orchestrator && go build ./... && go vet ./... && go test ./...)
87
87
  (cd python-engine && .venv/bin/python -m pip install -r requirements-dev.txt && .venv/bin/python -m pytest tests/ -q)
@@ -97,7 +97,7 @@ node packages/skill-migrator/cli.mjs --dry-run # valida migração skil
97
97
  **Gotchas críticos:**
98
98
  - `dist/` é gitignored e `bin/izanagi.js` importa de `../dist/cli/index.js`: **rode `npm run build` antes de qualquer comando CLI local** (`doctor`, `polyglot status`, `export`...), senão roda código obsoleto ou quebra. O mesmo vale para `packages/*/dist`: rode o build do package antes de consumir SDK/CLI-next.
99
99
  - `doctor`: instalação completa do usuário = `.agents/agents/` contendo agentes em **JSON** (formato distribuído); os YAMLs derivados do repo-fonte não caracterizam instalação.
100
- - Há test runner real (`node:test`, 284 testes em `src/runtime/tests/`). Verificação = `npm test` + `npm run verify` + `npm run doctor` + suítes poliglotas da seção 3.
100
+ - Há test runner real (`node:test`, 764 testes em `src/runtime/tests/`). Verificação = `npm test` + `npm run verify` + `npm run doctor` + suítes poliglotas da seção 3.
101
101
  - Padrão de commit do repo: `chore: bump to vX.Y.Z` para bumps e `feat:`/`fix:`/`docs:` descritivos em PT-BR para mudanças.
102
102
 
103
103
  ---
@@ -105,7 +105,7 @@ node packages/skill-migrator/cli.mjs --dry-run # valida migração skil
105
105
  ## 5. Estrutura do Framework
106
106
 
107
107
  **Legado (fonte canônica de agentes e skills):**
108
- - `core/`: 14 engines (.md, incluindo `skill-composer.md`, `checkpoint-healing-engine.md`, `quality-gates.md`) + **`skill-resolver.json`** (mapa alias → target, 258 aliases, 16 `compositions`)
108
+ - `core/`: 15 engines (.md, incluindo `skill-composer.md`, `checkpoint-healing-engine.md`, `quality-gates.md`) + **`skill-resolver.json`** (mapa alias → target, 258 aliases, 16 `compositions`)
109
109
  - `agents/`: 22 definições de agentes em JSON (fonte da verdade para os comandos) com `chains` compostas e Agent Genome (13 campos); derivados YAML em `.agents/agents/*.yaml` gerados pelo agent-migrator — proibido editar YAML à mão
110
110
  - `skills/`: legado histórico v1 (fonte do migrador). Catálogo ativo **v2**: `.skills/<name>/SKILL.md` (106 módulos; front-matter `name/description/version/category/tools.mcp` + seções Triggering Criteria / Step-by-Step Workflow / Verification Steps / Common Rationalizations / Red Flags; subpastas `references/`)
111
111
  - `references/`: curadoria de referências reais por domínio (webgl-3d, scrollytelling, ui-design-systems, stack-2026, performance-seo)
@@ -117,7 +117,7 @@ node packages/skill-migrator/cli.mjs --dry-run # valida migração skil
117
117
  **Poliglota (crescimento novo):**
118
118
  - `crates/`: workspace Rust na raiz — `izanagi_core` (quality engine + bindings WASM feature-gated), `izanagi_mcp` (cliente MCP stdio); `Cargo.lock` commitado
119
119
  - `go-services/swarm_orchestrator/`: orquestrador Go (Uber Fx, JSON-RPC 2.0 sobre UDS, event push, artefatos por estágio)
120
- - `python-engine/`: analisador AST multilíngue (tree-sitter + fallback, ~70 testes, venv em `.venv/`)
120
+ - `python-engine/`: analisador AST multilíngue (tree-sitter + fallback, 41 testes; venv em `.venv/`, criado localmente e não versionado)
121
121
  - `packages/`: `sdk` (`@izanagi/sdk`), `cli` (binário `izanagi-next`), `skill-migrator`, `agent-migrator` — todos `private`
122
122
  - `docs/POLYGLOT.md`: referência canônica da topologia poliglota (contratos IPC, tabela de env vars, gaps conhecidos, resumo dos ADRs)
123
123
 
@@ -163,7 +163,7 @@ O framework funciona em qualquer CLI de IA que leia `AGENTS.md` e possui adapter
163
163
  | **Kimi CLI** | `kimi.md` + `.kimi/README.md` | compatível com convenção `.opencode/` |
164
164
 
165
165
  - `izanagi init` possui **detecção inteligente de CLI**: auto-detecta a CLI/IDE em uso (ou permite selecionar via `--cli opencode|cursor|claude|codex|copilot|kimi|all`), gerando **apenas** o adaptador necessário para manter o workspace limpo e sem poluição visual.
166
- - `izanagi export --cli opencode|claude|codex|cursor|copilot|kimi|all` regenera os adapters sob demanda (idempotente: nunca sobrescreve arquivos existentes).
166
+ - `izanagi export --cli opencode|claude|codex|cursor|copilot|kimi|all` regenera os adapters sob demanda. **Idempotente com uma regra:** arquivo que carrega o `GENERATED_MARKER` é reescrito; arquivo sem o marker (ou seja, editado à mão) é preservado intocado. "Nunca sobrescreve arquivos existentes" era a leitura errada disso: quem editou o gerado sem tirar o marker perde a edição.
167
167
 
168
168
  ---
169
169
 
package/CHANGELOG.md CHANGED
@@ -4,6 +4,204 @@
4
4
 
5
5
  ---
6
6
 
7
+ ## [3.20.1]: 2026-09-08
8
+
9
+ ### Fixed
10
+ - **`project.test` não executava nada no Windows, e a v3.20.0 foi publicada assim.** `spawn('npm.cmd', …, { shell: false })` sai `EINVAL`: desde o CVE-2024-27980 o Node recusa lançar `.cmd`/`.bat` sem shell. O `try/catch` do arquivo transformava o throw em `error` com `passed` ausente, o que é o comportamento correto para "não medi". O efeito, porém, era o item 1 da v3.20.0 (a métrica de teste vinda de um exit code) degradar para "não medi" em toda máquina Windows. Os dois testes de exit code de `project-test.test.ts` falhavam lá e passavam no Linux, e a Verificação da v3.20.0 afirmava "837, 837 passando" a partir de uma medição feita só no Linux, listando um único vermelho conhecido de Windows quando eram três.
11
+ - **O conserto não custa a garantia do arquivo.** As duas saídas óbvias (`shell: true` e `cmd.exe /d /s /c`) recolocariam um interpretador de comandos no caminho, que é exatamente o que `shell: false` remove. A escolhida é outra: `resolveNpmCli()` acha o entrypoint JS do npm (ao lado do `node` no Windows, em `../lib/node_modules` em Unix) e o `spawn` passa a ser `process.execPath` com o npm como argumento de arquivo: sem shell, e com o binário mais confiável disponível, que é o mesmo node que executa o runtime. Se nenhum layout resolver, o chamador fica com o binário `npm` do PATH e o `EINVAL` volta a ser reportado como erro: "não medi" continua sendo ausência de `passed`, nunca reprovação.
12
+ - **`TestRunner` ganhou `execFile`/`execArgs`, e o rótulo continua sendo o comando.** O que vai ao `spawn` e o que vai ao artefato deixaram de ser o mesmo par: `command`/`args` seguem `npm test --silent` nas duas plataformas, porque `node …/npm-cli.js test` diria COMO, não O QUÊ.
13
+
14
+ ### Verificação
15
+ - **838 testes, 837 passando** (medido em 2026-09-08, no **Windows**). O único vermelho é `polyglot: bin Rust presente com --version barato`, anterior à rearquitetura: a fixture escreve um binário falso com shebang bash, e o Windows não honra shebang nem executa arquivo sem extensão conhecida. Continua aberto porque consertá-lo exigiria um condicional de plataforma, e o número deixaria de ser o mesmo nos dois sistemas.
16
+ - O teste novo ("o que vai ao spawn nunca é um `.cmd`, e o rótulo continua sendo o comando") trava o motivo, não só o sintoma: afirma que o binário do `spawn` é `process.execPath` e que nenhum `.cmd` chega lá.
17
+
18
+ ### Compatibility
19
+ - Nenhuma breaking change. `TestRunner.execFile` e `.execArgs` são opcionais, e `command`/`args` mantêm o valor de antes.
20
+
21
+ ---
22
+
23
+ ## [3.20.0]: 2026-09-05
24
+
25
+ ### Rodada de fechamento dos catorze itens abertos (2026-09-05)
26
+
27
+ A auditoria de 2026-09-04 fechou doze tetos sem caller e deixou **catorze itens
28
+ abertos**, cada um com critério de pronto escrito no `RUNTIME-PENDING.md`. Esta
29
+ rodada fecha os catorze. O padrão que eles compartilhavam continua sendo o mesmo
30
+ que o `HANDOFF.md` diz combater, agora numa segunda forma: não é o limite
31
+ declarado que nada aplica, é a **evidência declarada que ninguém produz** —
32
+ métrica de teste vinda de um texto que um agente escreveu, critério de aceite
33
+ que fala da forma e nunca do pedido, memória que se escreve e não se lê, journal
34
+ que se lê e não se consulta.
35
+
36
+ ### Added
37
+ - **`project.test` e o check `exit-zero`: a métrica de teste passa a vir de um exit code.** A camada determinística tinha oito checks e nenhum executava nada; `testResults` vinha de um artefato `test-results` que um AGENTE escreveu, ou seja, do mesmo processo que deveria estar sendo testado. Com `--verify-tests`, o nó `verify-tests` roda o comando de teste do PROJETO no fim do grafo e `passed` é `exitCode === 0`, decidido pelo sistema operacional. **Isto não afrouxa o isolamento do `code.execute`:** a diferença é a fonte do comando. No `code.execute` o código vem do modelo, e por isso roda sem subprocesso, sem env herdado e sem rede confiável; aqui o comando vem do manifesto do projeto, o binário sai de uma allowlist fixa do runtime, o `spawn` é `shell: false` (sem expansão, sem `&&`, sem pipe) e nenhum campo de entrada carrega comando. Opt-in porque executa um processo do projeto com o ambiente herdado: a mesma confiança de digitar `npm test`.
38
+ - **`--acceptance`: o critério do usuário passa a ser cobrado.** Todo critério era derivado do SCHEMA do artefato, então "adicionar paginação em GET /users" não produzia nenhum critério sobre paginação, e não existia flag, campo de SDK ou input para fornecer um. Prefixo conhecido (`contains:`, `not-contains:`, `matches:`, `min-size:`, `file-exists:`, `json-field:`, `references-exist`) vira check determinístico; prosa vira critério semântico, que precisa de juiz e sem juiz fica `UNVERIFIED`. O default é semântico de propósito: transformar uma frase em `contains` da frase inteira reprovaria toda entrega correta escrita com outras palavras, e um check inventado é pior que nenhum porque parece evidência.
39
+ - **`--min-quality`: estratégias comparadas contra um piso.** Não existiam candidatos nem piso configurável (`minQuality`/`qualityFloor` tinham zero ocorrências no código), então "respeitando a qualidade mínima configurada" não tinha o que respeitar. Agora os modos até o sugerido viram candidatos, cada um estimado pelo mesmo caminho de roteamento da execução, e vence o mais barato que atinge o piso. Piso inalcançável **não sobe o modo em silêncio**: o plano segue no modo sugerido e declara que não cumpriu, porque subir seria o orçamento decidindo escopo.
40
+ - **`--reuse-artifacts`: reuso de artefato entre runs.** `readContent` só era chamado por `izanagi explain`; um segundo run do mesmo objetivo refazia tudo. A parte que importa é a invalidação, e ela vem declarada antes do cache: a chave cobre tipo, objetivo, restrições, critérios, agente, papel, checksums dos insumos EM ORDEM e a impressão do projeto; run sem survey é chave DIFERENTE de run com survey; o prazo (7 dias) expira o que a chave não consegue ver. O artefato reaproveitado entra no lugar da CHAMADA e passa pela verificação inteira: o que se economiza é a chamada, não a prova.
41
+ - **`--allow-tool` e `--verify-tests` na CLI.** A allowlist de tools existia no Orchestrator, no SDK e no caso de benchmark, e `izanagi run` não tinha flag para ela.
42
+ - **`HUMAN_REQUIRED`: teto esgotado deixa de se confundir com falha por bug.** Cada abort por teto marca qual (`attempts`/`time`/`tokens`/`cost`) e o status do run muda. O veredito da AVALIAÇÃO continua `FAIL`, porque ela mede a entrega e a entrega não fechou: os dois campos convivem por medirem coisas diferentes. O exit code segue 1, não 2 — o 2 significa "retomável por `izanagi approve`", e um orçamento estourado não é.
43
+ - **`ArtifactRegistry.lineage()` e `.compare()`.** As arestas de dependência estavam gravadas desde sempre e a leitura parava no primeiro vizinho; num grafo de sete nós, um salto nunca responde "de onde veio isto?". A travessia é em largura, com marca de visitado (ciclo termina em vez de girar), e `compare()` diz o que MUDOU entre versões, não só quanto o score caiu.
44
+ - **`ArtifactRecord.checksum` (sha256 completo) e `.metadata` livre.** `hash` continua sha1 truncado em 12 hex porque é o que os registros gravados carregam: 48 bits bastam para "é o mesmo artefato de novo?", não para "este arquivo é exatamente o que eu gravei". `metadata` tem teto de 4KB e é recusado INTEIRO quando estoura.
45
+ - **`EXTERNAL-TOOL-001`: tool registrada em runtime exige aprovação humana.** O default-allow da `PolicyEngine` permanece, com o motivo escrito (a `ToolRegistry` já nega o que o contrato não concedeu, a allowlist já nega o que não foi declarado, e se a política também fosse portão de concessão haveria três lugares decidindo a mesma coisa). O caso em que "não previsto" era perigoso ganhou regra própria. E `PolicyDecision.requiresApproval`, que existia e ninguém lia, virou pausa por `izanagi approve` em vez de falha que o healing retentaria contra uma porta fechada.
46
+ - **`ExecutionEvidence.modelCalls` / `.agentCalls` / `.successRate` e `benchmark run --execute --compare`.** A comparação antigo vs novo cobria três dimensões e só sobre o PLANO. Chamadas contam por TENTATIVA, porque é o que a fatura conta, e nó reaproveitado não conta — é justamente a diferença que a comparação precisa enxergar.
47
+ - **`triggers` e `capabilities` declarados nas 22 skills mais acionadas.** Das 106 skills, ZERO declaravam qualquer um dos dois: o haystack de `rankSkills` incluía dois arrays sempre vazios e o ranking escolhia entre 106 descrições soltas. Escritos à mão: derivar dos títulos de seção produziria "Identidade" e "Processo" como capacidade, e derivar da description colocaria as mesmas palavras duas vezes.
48
+ - **`MemoryStore.appendKnowledge`.** A camada semântica era lida e nunca escrita pelo runtime: `.agents/memoria/semantica.md` só mudava quando uma pessoa o editava, e o que o runtime gravava (`addLearning`) vive numa lista plana que a busca não alcança.
49
+
50
+ ### Changed
51
+ - **O Decision Journal deixa de ser write-only.** Cada decisão leva o objetivo do run; o fim do run carimba o veredito (`recordOutcome`, que não reescreve o que já foi carimbado); o planejamento consulta por semelhança de objetivo (`findRelevant`, só decisões com resultado conhecido). Um agente escolhido duas vezes para um objetivo semelhante, com os dois runs sem fechar e nenhum sucesso no meio, sai da disputa — e a troca vale também nos nós vindos do template do workflow. Duas falhas e não uma: um incidente pode ter sido provider fora do ar.
52
+ - **`MemoryStore.search()` passa a ser consultado DURANTE o run.** Era chamado só pela CLI e pelo benchmark; dentro de um run, a única recuperação era padrão de falha. Agora o Context Resolver busca pelo objetivo de cada tarefa, com teto de 2 entradas e 600 chars, e um store por run. Numa rodada de correção o bloco fica de fora: o que falta ali é a correção, não mais contexto.
53
+ - **`maxCost` vira limite do Healer.** `HealingInput` tinha tempo, tokens e tentativas; o custo só agia por `ExecutionBudget.spend`, ou seja DEPOIS de a chamada acontecer. Curar é decidir gastar mais uma chamada, e essa decisão passa a consultar o dinheiro antes.
54
+ - **A nota de um caso de benchmark passa a incluir os validators.** Era só a razão de artefatos: um caso cujos arquivos apareceram e cujos validators reprovaram TODOS saía com `score: 1.00, passed: false`, e `compareBaselines` rankeia por `avgScore` — o baseline que acertou os nomes de arquivo e errou o conteúdo vencia o que acertou o conteúdo.
55
+
56
+ ### Fixed
57
+ - **O total de tokens do trace saía 60% acima da telemetria do MESMO run.** `addTokens(result.tokens, result.tokens * 0.6)` soma os dois argumentos, e `result.tokens` é o total do provider (`input + output`), não a entrada. É o número que a CLI imprime, que `izanagi trace` mostra, que o dashboard exibe, que o webhook envia e que a Arena soma. Teste novo trava o invariante: trace e telemetria contam o mesmo run.
58
+ - **Validators de um caso de benchmark liam o CAMINHO, não o arquivo.** Num output de diretório, `has-owasp` media se a palavra "owasp" estava no nome da pasta temporária: o validator passava ou reprovava por uma propriedade do diretório de trabalho.
59
+ - **O registry de benchmark aceitava caso pela metade num `catch` vazio.** Um JSON sem `expectedArtifacts` chegava ao runner, estourava dentro do `try` da suíte, e o relatório culpava a execução por um defeito da definição. Caso recusado agora diz o motivo e o arquivo.
60
+ - **Toda métrica declarada por um caso recebia a mesma razão de artefatos.** O relatório salvo mostrava `correctness`, `security` e `architecture` com o mesmo número: três medidas independentes que eram uma medida repetida três vezes. O que não é medido sai em `metricsNotMeasured`.
61
+ - **A varredura anti-stub reprovava a evidência de uma suíte VERDE.** O runner de testes do Node imprime `ℹ todo 0` no resumo, e o artefato `test-run` de uma suíte 100% verde era reprovado por "stub detectado: TODO". A varredura pressupõe texto autoral; schema de saída capturada agora a desliga.
62
+ - **`unmet` misturava reprovado com não-comprovado.** Um critério semântico sem juiz aparecia lado a lado com um check que de fato falhou, e quem lesse a linha (ou a restrição que o replanejamento deriva dali) trataria "não medi" como "está errado". Agora o não-comprovado vem marcado `[sem evidência]`.
63
+ - **Dois objetos git vazios impediam o push.** `src/cli/commands/benchmark.ts` e `src/runtime/types.ts` tinham blobs truncados a zero byte no object store local, referenciados por oito dos nove commits da rodada. Reconstruídos byte a byte a partir dos blobs vizinhos legíveis, com o hash conferido antes de gravar: `git fsck` limpo, e nenhum commit reescrito.
64
+
65
+ ### Compatibility
66
+ - Nenhuma breaking change. As quatro capacidades novas são **opt-in** (`--verify-tests`, `--acceptance`, `--min-quality`, `--reuse-artifacts`): sem elas, o plano, o grafo e o veredito são byte a byte os de antes, e há teste que mede isso.
67
+ - `OrchestrationResult.status` e `IzanagiRunResult.status` ganharam o valor `HUMAN_REQUIRED`. Quem faz `switch` exaustivo sobre o status precisa tratá-lo; quem compara com `'PASS'` não muda. O exit code da CLI é o mesmo de antes.
68
+ - `PlanEstimate.quality` é campo novo e obrigatório no tipo. Quem constrói um `PlanEstimate` à mão (fixtures de teste) precisa declará-lo; quem consome o que o `Commander.estimate` devolve não muda.
69
+ - `ArtifactSchema.capturedOutput`, `ArtifactRecord.checksum`, `.metadata` e `.reuseKey` são opcionais: registro escrito por versão anterior continua legível.
70
+
71
+ ### Verificação
72
+ - **837 testes, 837 passando** (medido em 2026-09-05, Linux). O vermelho conhecido de Windows (`polyglot: bin Rust presente com --version barato`) é anterior e independente. **Esta linha estava errada, e a 3.20.1 diz por quê:** no Windows eram três vermelhos, não um, e os dois extras eram justamente os de `project.test`.
73
+ - `izanagi run "documentar a funcao de soma" --output docs --verify-tests --mode orchestrated` num projeto de fixture: suíte verde → `PASS`, 7/7 VERIFIED, `testResults=1`, score 1.00; suíte vermelha → `BLOCKED`, 6/7 VERIFIED, `testResults=0`, regressão nomeando `npm test --silent` com exit 1.
74
+ - `izanagi run "..." --reuse-artifacts` duas vezes: run 1 gasta 900 tokens com cache 0/3; run 2 gasta **0 tokens** com cache 3/3, e continua `PASS` com 4/4 VERIFIED.
75
+ - `izanagi run "..." --min-quality`: piso 0.4 escolhe `autonomous` ($0.0011, o único que atinge); piso 0.3 escolhe `assisted` ($0.0000, mesmo piso atingido por menos).
76
+ - `izanagi benchmark run security --execute --compare`: tokens -300 (1500 → 1200), model calls -1 (5 → 4), agent calls -1 (3 → 2), latência +50ms, verificação n/a → 100%, sucesso 100% nos dois.
77
+
78
+ ---
79
+
80
+ ## [3.19.0]: 2026-09-04
81
+
82
+ > **A 3.18.0 nunca chegou ao npm.** Ela foi para o GitHub e o `npm publish` não
83
+ > aconteceu, então o registro parou na 3.17.1: esta release leva as duas rodadas
84
+ > juntas. Mesma classe de incidente que a v3.4.0 (registrada na Fase 6 do
85
+ > `ROADMAP.md`), e o motivo de existir o gate de banner de versão descrito
86
+ > abaixo: "publicado" e "commitado" não são a mesma afirmação.
87
+
88
+ ### Rodada de auditoria do runtime contra a especificação (2026-09-04)
89
+
90
+ Auditoria dos 49 itens de "Definition of Done" da especificação de evolução do runtime contra o código real, item por item. O `RUNTIME-PENDING.md` afirmava **nenhum item aberto**; a auditoria encontrou **doze tetos, campos e caminhos que existiam no código e não tinham caller**, mais um bug de formato entre produtor e consumidor do mesmo repositório. Nenhum deles é feature nova: são peças que o próprio runtime já declarava ter.
91
+
92
+ O padrão é sempre o mesmo, e é o que o `HANDOFF.md` diz combater: **um limite declarado que nada aplica**.
93
+
94
+ ### Added
95
+ - **Cancelamento cooperativo do run** (`OrchestratorOptions.signal`, `IzanagiRunOptions.signal`). O único `AbortSignal` do repositório era o timeout de `fetch` do cliente de modelo: não havia como parar um run, e o prazo por nó tirava o nó do caminho deixando a requisição em voo consumindo cota de um run que ninguém mais esperava. O sinal é conferido no topo de cada batch (o único ponto do laço onde parar não deixa trabalho pela metade), desce até a requisição por `CompletionOptions.signal` (combinado com o timeout HTTP via `AbortSignal.any`) e recusa a chamada antes de gastá-la quando já está abortado. **Ctrl-C na CLI cancela em vez de matar o processo**, e é a combinação com o checkpoint por batch que dá o valor: o progresso já pago fica em disco e `izanagi resume <run-id>` retoma dali. Um segundo Ctrl-C força a saída (exit 130). Run cancelado é `non-recoverable` no `Healer`: curar seria desobedecer quem cancelou.
96
+ - **Prazo por nó aplicado de verdade** (`runtime/orchestration/deadline.ts`). `node.timeoutMs` é escrito por TODO o caminho de planejamento (templates do Planner, os quatro modos do Commander, os três nós de tool) e vira `TaskContract.budget.maxTimeMs`: nada no runtime lia nenhum dos dois. Um provider pendurado, ou uma tool externa registrada por `ToolRegistry.register`, travava o nó até o timeout HTTP do cliente de modelo; uma tool sem cliente HTTP travava indefinidamente. Vale o MENOR entre contrato e nó; ausência, zero e negativo significam "sem prazo", nunca "prazo zero". **A diferença entre prazo e cancelamento está declarada no arquivo:** prazo tira o nó do caminho do grafo e é retentável; cancelamento é do run inteiro, aborta a chamada em voo e não é retentável.
97
+ - **`allowedTools`: allowlist de tools do run inteiro** (`OrchestratorOptions.allowedTools`, `IzanagiRunOptions.allowedTools`). Camada distinta da permissão do contrato: a permissão diz o que a TAREFA pode fazer, a allowlist diz o que este RUN pode usar, sem depender de nenhum contrato estar correto. Conferida ANTES da permissão e da política. Lista vazia é allowlist vazia (proíbe toda tool), ausência é "sem allowlist": a diferença é a forma de declarar "este run não usa tool".
98
+ - **`BenchmarkCase.budget` / `.mode` / `.allowedTools`.** A base oficial de benchmark não tinha como declarar o teto sob o qual um caso deve ser resolvido: `benchmark run --execute` rodava todo caso sem orçamento, sem modo e sem restrição de tool. "Budget" e "allowed tools" eram observados no relatório e nunca impostos na execução, então um caso resolvido com dez vezes o orçamento passava igual.
99
+ - **`task.verification.passed` / `task.verification.failed`: verificação por TAREFA.** `quality_gate.*` e `verification.completed` são do RUN (veredito final agregado, emitidos uma vez). Uma tarefa que reprovava a verificação não emitia evento nenhum, e o dado só aparecia em `result.verification` depois do await: quem observava o run em tempo real não tinha como saber que um nó reprovou. Aliases de SDK: `task:verification:failed` / `task:verification:passed`. Os antigos `verification:*` continuam apontando para o veredito do run, sem breaking change.
100
+ - **`--max-concurrency N` em `izanagi run`.** O SDK sempre pôde declarar `budgetLimits.maxConcurrency`; a CLI não tinha por onde. Valor inválido é ignorado em vez de virar 0, porque 0 significa "sem teto" no pool: o oposto do que quem passa um número pediu.
101
+ - **`ExecutionBudget.remainingTokens`.** Saldo do teto do run, nunca negativo. Existe para alimentar o roteamento por nó.
102
+ - **`AgentCapability.modelHint` / `.declaredPermissions` / `.evaluation`.** Os 22 agentes core declaram `model`, `permissions` e `evaluation.metrics` em 22/22 arquivos, e o `parse()` do registry descartava os três. `declaredPermissions` tem esse nome porque a distinção é de segurança: é prosa do autor do agente (`"ler agents/"`), **não** o formato `fs:read`/`shell` que a `PolicyEngine` autoriza. Um agente não se autoriza declarando o que quer. `modelHint` é preferência, não id de catálogo: o modelo continua saindo do papel.
103
+ - **`scripts/doc-version.ts` e o gate de banner de versão.** `bump.ts` e `release.ts` mexiam só no `package.json`, e nada conferia o resto: `ROADMAP`, `ARCHITECTURE`, `SYSTEM` e `RULES` diziam **3.10.0** e `AGENTS.md` **3.9.0** com o código em 3.18.0. Oito minors de drift, e a v3.6.0 já tinha corrigido isso à mão uma vez. O gate compara MAJOR.MINOR (patch é conserto, não mudança de arquitetura), `bump` imprime a lista do que revisar, e `release` **interrompe antes do publish** (`IZANAGI_ALLOW_DOC_DRIFT=1` libera). O banner NÃO é estampado automaticamente: escrever `3.19.0` num documento que ninguém leu é justamente afirmar um número que não aconteceu.
104
+
105
+ ### Fixed
106
+ - **`recordRetry()` não tinha caller de produção.** Existia desde a v3.14.0, e por isso `telemetry.retries`, `RunTrace.retries` e o teto `budgetLimits.maxRetries` (plumbado do SDK e da CLI até o `ExecutionBudget`) eram estruturalmente mortos: `izanagi budget`, `izanagi trace` e o dashboard mostravam **0 retries** num run que tinha retentado três vezes, enquanto a Arena, contando por `node.attempts`, relatava o número certo. Duas contas do mesmo fato e só uma verdadeira. Agora conta no ponto da reexecução, ANTES de gastar a chamada, e `maxRetries` barra. Aprovação pendente não conta como retentativa (o ramo `pending` devolve a tentativa).
107
+ - **`maxAgents` contava e não barrava.** O retorno booleano de `recordAgent` era descartado.
108
+ - **Teto de run estourado era classificado como falha transitória e RETENTADO.** A mensagem do teto de tool calls contém a palavra "tool" e casava com a regra `/tool|mcp|exec|command failed|exit code/` do `Healer`, virando `kind: 'tool'`, que é recuperável: o runtime retentava um limite que não se move entre tentativas, gastando orçamento numa porta que continuaria fechada. Nova regra `non-recoverable` para teto excedido, posicionada antes da de `tool`.
109
+ - **O Plano B do Commander era praticamente inalcançável.** `replan` só era acionado por falha de PLANEJAMENTO (mensagem casando `/plan|graph|cycle|topological/`). Reprovação da Verification Engine classifica como `validation` e ia direto para "troca a skill e tenta de novo", com o MESMO agente, MESMO papel e MESMA decomposição, até esgotar `maxAttempts`: o caminho de falha mais comum do runtime era exatamente o "repetir" que o replanejamento existe para evitar. Agora a 1ª falha de validação troca a skill (a correção mais barata primeiro) e a 2ª vai para o replan. Na prática alcança modo `autonomous`, que é onde há tentativa sobrando, e é onde o replanejamento deve viver.
110
+ - **O `RoutingContext` era congelado no run inteiro.** Montado uma vez em `buildExecutionPlan` com `reasoningRequirement: 'medium'`, `risk: 0.2`, o `tokenBudget` do run e nenhum `historicalPerformance`, e reusado em todo nó. O `scoreModel` do `ModelRouter` lê todos esses campos: **metade dos critérios de roteamento estava implementada no scorer e nunca era alimentada**, e dentro de um run o modelo escolhido era função só do papel. `contextForNode` passa a derivar por tarefa: janela do teto da tarefa (limitada pelo saldo do run), risco da prioridade do contrato, raciocínio do papel, `requiresTools` do nó de tool e o histórico medido pela memória.
111
+ - **`LOCAL_MAX_CONCURRENCY` era código morto.** A constante existia desde a v3.13.0 com o motivo escrito no arquivo ("GPU única não ganha nada com paralelismo") e zero referências no repositório: com `--local` o pool continuava em 3, disparando três requisições simultâneas contra a mesma GPU. Teto explícito do usuário vence, porque é ordem e não heurística.
112
+ - **`parseFrontmatter` não lia lista de bloco YAML, e a `SkillFactory` só escreve lista de bloco.** Produtor e consumidor do mesmo repositório em formatos incompatíveis, com perda silenciosa: `triggers:` casava com o regex de chave e gravava string vazia, as linhas ` - valor` não casavam com nada, e `readSkill` derivava `[]`. Toda skill gerada pela Factory, e toda skill sintetizada por trajetória (que usa o mesmo escritor), perdia justamente o metadado pelo qual `rankSkills` a encontraria. Chave sem valor e sem itens segue string vazia, nunca `[]`: ausência de valor não é lista vazia. Chave aninhada (`tools:` para `mcp:`) continua fora de escopo, e declarado.
113
+ - **`optional` decidia por id literal (`new Set(['critic'])`).** Um template de workflow do projeto do usuário com o nó de crítica sob outro nome, ou um agente gerado que produz `critique`, nunca era marcado como opcional: nem o early stopping nem o corte de opcionais por pressão de orçamento o alcançavam. A decisão passa a sair do QUE o nó produz. `evaluation` deliberadamente NÃO é reforço: pular o avaliador porque tudo passou seria pular quem afirma que passou.
114
+ - **Um run cancelado tinha o checkpoint APAGADO.** `checkpoints.delete` roda em todo veredito terminal, com a premissa "não há mais o que retomar". Para cancelamento a premissa é falsa justamente aí: quem cancelou parou trabalho que ainda fazia sentido, e apagar o checkpoint tornava `izanagi resume` impossível no único caso em que ele é claramente o que se quer. Encontrado escrevendo o teste de cancelamento.
115
+ - **Falha `non-recoverable` era RETENTADA quando casava com um padrão de falha da memória.** O passo de "padrão conhecido" do `Healer` vinha antes de a classificação decidir, e devolve `retryNow: true`: uma permissão negada gravada na memória era retentada, contra a regra que o próprio `KIND_RULES` declara na primeira linha. Valia desde antes desta rodada para permissão negada; passou a valer também para teto de run e cancelamento.
116
+ - **Checkpoint era salvo só no fim da tentativa, não a cada batch.** O docstring de `captureCheckpoint` já dizia "chamado a cada rodada de batches" e não era verdade: um run interrompido no meio do grafo (Ctrl-C, crash, queda de rede) descartava todos os nós já concluídos daquela tentativa, e o `izanagi resume` recomeçava a tentativa inteira, pagando de novo chamadas de modelo já pagas. Persistido ao fim de cada batch, ANTES de decidir sobre a falha: o que terminou não se perde porque um irmão falhou.
117
+ - **`VerificationEngine.isDone` não tinha caller, e o docstring dele contradizia o código.** Dizia "UNVERIFIED nunca é tratado como sucesso" enquanto o orquestrador marcava o nó `succeeded` e seguia. O nó CONTINUA seguindo, e isso é a decisão: sem juiz semântico (o default sem provider, e o de `--no-judge`) todo critério semântico fica sem evidência conclusiva, e derrubar o nó transformaria "não medi" em "está errado". O que faltava era o nó **carregar o fato**: `node.metadata.unverified` com status, motivo e critérios não comprovados, mais uma mensagem A2A de tipo `evidence`. Aprovado sem prova precisa ser distinguível de comprovado por quem lê o grafo.
118
+ - **A lista literal de 19 agentes no `orchestrator.ts`.** Ela decide se a Agent Factory deve gerar um agente novo, e esquecia 3 dos 22 core (`ai-engineer`, `evaluator`, `form-engineer`) além de ignorar qualquer agente do projeto do usuário: o runtime podia sintetizar um agente para uma lacuna já coberta em disco. Passa pelo `AgentCapabilityRegistry`, com fallback para a lista antiga quando não há `agents/` legível. Este é o caminho legado, sem Commander, e projeto sem agentes em disco não deve deixar de rodar por isso.
119
+
120
+ ### Tests
121
+ - **764 testes, 763 passando** (69 novos). O único vermelho segue sendo `polyglot: bin Rust presente com --version barato`, que escreve um binário falso com shebang bash: não roda no Windows, passa no Linux, e é anterior a esta rodada.
122
+ - Novos arquivos: `cancellation.test.ts`, `deadline.test.ts`, `budget-ceilings.test.ts`, `frontmatter-block-list.test.ts`, `routing-per-node.test.ts`, `replan-reachability.test.ts`, `optional-reinforcement.test.ts`, `run-guarantees.test.ts`, `capability-fields.test.ts`, `doc-version-freshness.test.ts`.
123
+ - Cada teto agora tem teste que MEDE o teto, não só a contagem: `maxRetries` barrando a reexecução, `maxAgents` barrando o agente, allowlist recusando a tool, prazo derrubando um producer que nunca resolve. Limite testado é um limite; limite só documentado é esperança.
124
+ - `deadline.test.ts` fixa um limite que só aparece em produção: trabalho que **falha depois do prazo** não pode virar `unhandledRejection` e derrubar o processo. Um nó lento não é um crash do run.
125
+
126
+ ### Compatibility
127
+ - **Nenhum breaking change de API.** `allowedTools`, `maxConcurrency`, `BenchmarkCase.budget`/`.mode`/`.allowedTools`, `remainingTokens`, `modelHint`, `declaredPermissions`, `evaluation` e os dois eventos novos são adições opcionais. `routeRole` ganhou um terceiro parâmetro opcional; os aliases `verification:*` do SDK continuam apontando para o veredito do run.
128
+ - **Muda comportamento observável em quatro pontos, todos porque um teto passou a valer:** um run com `maxRetries`/`maxAgents` declarado agora falha o nó ao estourar (antes seguia); `--local` serializa o pool; um nó com `timeoutMs` declarado agora pode falhar por prazo; e uma 2ª falha de validação em modo `autonomous` replaneja em vez de retentar.
129
+ - `release` passa a interromper antes do publish quando um banner de versão está desatualizado. `IZANAGI_ALLOW_DOC_DRIFT=1` publica com a drift registrada.
130
+
131
+ ---
132
+
133
+ ### Rodada anterior de auditoria de documentação
134
+
135
+ Rodada de auditoria: três defeitos encontrados lendo o código contra a documentação, nenhum deles procurado. Todos da mesma família (o framework afirmando um número ou um caminho que ninguém conferiu), que é a família que o `HANDOFF.md` diz combater.
136
+
137
+ ### Added
138
+ - **`ModelProvider.pricingAsOf`: a tabela de preços declara a própria data.** Preço em código-fonte apodrece sem avisar, e `estimateCostForRole` alimenta o teto de `ExecutionBudget`: preço velho é teto errado, e o teto é o que decide degradar, rebaixar papel ou pedir aprovação humana. `izanagi models` passa a mostrar a idade da tabela por provider e avisa acima de `STALE_CATALOG_AFTER_DAYS` (120 dias, escolha declarada e não medida). Provider self-hosted não declara data, porque custo 0 é fato e não cotação. Campo opcional no tipo: catálogo de projeto existente não quebra.
139
+ - **`catalogAgeDays()` / `isCatalogStale()`** em `runtime/model/router.ts`. Sem data declarada a idade é `null`, nunca `0`: idade 0 afirmaria "o preço é de hoje", que é exatamente a afirmação impossível sem a data. Mesma regra de "ausência não é aprovação" já aplicada às métricas.
140
+ - **`benchmarkReportsDir(stateDir)`** em `runtime/benchmarks/runner.ts`: fonte única do diretório de relatórios, usada pela escrita, pela leitura e pela mensagem que anuncia a escrita.
141
+ - **`MemoryStore.stateFilePath` / `.memoryDirPath`**: onde o store de fato lê e grava, para que quem imprime o caminho imprima o mesmo que a escrita usou.
142
+
143
+ ### Fixed
144
+ - **O catálogo default de modelos estava uma geração atrás, e isso não era cosmético.** `claude-opus-4-1` (premium), `claude-sonnet-4-5` (balanced) e `gpt-4.1` (premium, o default do papel `commander`) saíram do catálogo. Entraram, com fonte e data consultadas em 2026-09-03: `claude-opus-5` e `claude-sonnet-5`; `gpt-5.6-sol`; `gemini-3.8-flash` e `gemini-3.1-pro-preview`. Um id retirado da API faz a chamada falhar; um preço de geração anterior faz o teto de orçamento mentir. Dois cuidados registrados no código: `gpt-5.6-sol` entra com janela **272000** e não 1050000 (1M é opt-in experimental, e acima de 272K a entrada custa 2x e a saída 1.5x, então planejar contra 1M mentiria para cima), e `gemini-3.5-flash-lite` ficou **fora** apesar de ser mais barato, porque a janela de contexto dele não estava documentada na consulta: janela chutada num roteador que decide por contexto é pior que um modelo a menos.
145
+ - **O caminho impresso do relatório de benchmark não era o caminho onde o relatório estava.** A escrita sempre foi para a raiz de estado (`<projeto>/.agents` num projeto inicializado); as três mensagens da CLI eram um literal `.izanagi/state/benchmarks/`, relativo ao `cwd`. Neste repositório esse diretório existe e guarda relatórios de agosto: caminho errado que parece certo é pior que caminho ausente, porque o número velho é lido como se fosse o novo. Agora a mensagem sai do mesmo cálculo da escrita. Mesma correção em `izanagi memory inspect`, que imprimia `.izanagi/state/runtime-state.json` sem raiz.
146
+ - **`memoryCommand` e `dashboardCommand` recebiam `stateDir` num parâmetro chamado `baseDir`.** Funcionalmente corretos (a chamada em `cli/index.ts` sempre passou a raiz certa), mas é exatamente a confusão de raiz que já produziu dois bugs neste runtime. Renomeados.
147
+ - **Documentação: `docs/HANDOFF.md` e `README.md` afirmavam 674 testes.** O medido era 682, e o `CHANGELOG.md` da mesma versão já dizia 682. Drift contra a regra do próprio `HANDOFF.md` ("só entra o que é verificável no código"). O `HANDOFF.md` também citava `.izanagi/state/benchmarks/` nos critérios de pronto, herdando o caminho errado da CLI.
148
+
149
+ ### Tests
150
+ - 695 testes, 694 passando (13 novos: 5 em `benchmark-report-path.test.ts`, 8 em `model-catalog-freshness.test.ts`). O único vermelho segue sendo `polyglot: bin Rust presente com --version barato`, que não roda no Windows e é anterior a esta rodada.
151
+ - **Dois testes existentes fixavam id de modelo no fonte e quebraram na atualização de catálogo** (`model.test.ts`, `model-role-routing.test.ts`). Reescritos para derivar o id do catálogo em tempo de teste: o que eles afirmam é o pin vencer a heurística e env vencer config, e nada disso tem a ver com id nenhum. Um id hardcoded ali volta a quebrar na próxima atualização, que é a lição do achado.
152
+ - `model-catalog-freshness.test.ts` fixa duas invariantes que o conserto de valor sozinho não protege: nenhum id de geração retirada volta ao catálogo, e cada tier pago mantém a ordem de custo que `demoteRole` presume (se um preço novo invertesse a ordem, a degradação por orçamento passaria a AUMENTAR o gasto, em silêncio).
153
+
154
+ ### Compatibility
155
+ - Nenhum breaking change de API. `pricingAsOf` é opcional. `benchmarkReportsDir`, `catalogAgeDays`, `isCatalogStale`, `STALE_CATALOG_AFTER_DAYS`, `MemoryStore.stateFilePath` e `.memoryDirPath` são adições. Os renames de parâmetro são posicionais e internos à CLI.
156
+ - **Muda comportamento para quem não configura modelo:** o papel `commander` deixa de rotear para `gpt-4.1`. Quem dependia de um id específico deve fixá-lo em `.izanagi/izanagi.config.json` → `roles`, ou declarar o próprio catálogo em `models`.
157
+
158
+ ---
159
+
160
+ ## [3.18.0]: 2026-09-02
161
+
162
+ O caminho seguro de tool existia desde a 3.15.0, era testado, e nenhum `izanagi run` passava por ele. Nesta versão o planejamento gera dois nós de tool em produção: um que **lê o projeto** antes de decidir, outro que **entrega arquivo** no fim.
163
+
164
+ ### Added
165
+ - **`--output <dir>` / `output` no SDK — nó `deliver`.** Primeiro nó `kind: 'tool'` gerado pelo planejamento em produção. Grava o que o run produziu num documento único dentro do projeto, com contrato concedendo `fs:write` e mais nada. A verificação do nó confere o arquivo escrito: um critério `file-exists` sobre arquivo que ninguém escreveu passa quando o arquivo já existia por outro motivo; aqui ele passa a significar "o runtime gravou isto". O nome sai do objetivo, então repetir o mesmo objetivo reescreve a mesma entrega — entrega é produto, e o histórico continua em `.izanagi/state/`. `IzanagiRunResult.deliveredTo` só aparece quando a gravação realmente aconteceu.
166
+ - **`project.survey` — nó `survey` na cabeça do grafo.** Levantamento determinístico do repositório: stack por manifesto e por volume de arquivo, manifestos resumidos, árvore por extensão, entrypoints e o começo do README. Não custa token; tem teto de profundidade (3) e de entradas, e **declara o próprio corte** (`truncated` é campo obrigatório do schema). Só as raízes do grafo dependem dele — repetir o levantamento em cada prompt seria a duplicação de contexto que a arquitetura proíbe. Ligado por default quando o diretório tem manifesto reconhecido; `--no-survey` desliga; modo `direct` nunca paga.
167
+ - **Marcadores de input de tool** (`runtime/tools/input-refs.ts`): `{ $artifact: '<nó>' }` e `{ $deliverable: true }` resolvidos deterministicamente na hora da chamada, porque um nó de tool é declarado no plano antes de existir o que ele vai gravar. Referência a nó inexistente é erro, nunca string vazia. `code.execute` recusa marcador em qualquer campo do input: levar saída de modelo para dentro de código executado é injeção com outro nome.
168
+ - **Kinds de artefato `delivery` e `project-survey`**, com schema próprio. `delivery` exige `written` (o comprovante da escrita, não o conteúdo); `project-survey` exige `root`, `stack`, `tree` e `truncated`.
169
+ - **`OrchestratorOptions.workspaceDir`**: raiz do projeto do usuário, separada da raiz do framework.
170
+
171
+ - **`project.materialize` — nó `materialize`, o código do agente vira arquivo.** O Blueprint Engine já definia o contrato de materialização (declare a árvore, escreva cada arquivo completo, zero stub) mas só em `--prompt-only`: um texto para a pessoa colar em outra ferramenta. Dentro do runtime o contrato não existia, e o código entregue ia para o content store como texto. Agora o contrato da tarefa PEDE o formato (`### FILE: <caminho>` + bloco de código) e um parser determinístico o materializa. **A fronteira que torna isto defensável**: os arquivos vão para um subdiretório da SAÍDA (`<output>/<slug do objetivo>/`), nunca por cima do código do projeto — o que o runtime produz fica num lugar que o usuário nomeou e pode revisar, apagar ou copiar. **Tudo ou nada**: a validação roda sobre o manifesto inteiro antes de qualquer escrita, porque "6 arquivos escritos, 3 recusados" é o relatório que engana. Recusa caminho absoluto, escape de diretório, caminho duplicado, arquivo vazio e arquivo com marca de trabalho não feito. Só entra no plano quando existe artefato que pode carregar código (`implementation`, `fixes`, `database-schema`, `api-contract`).
172
+ - **Fundamentação medida e reportada em `izanagi run`**: dos caminhos que os artefatos citaram, quantos existem no projeto. É a única métrica que fala sobre o CONTEÚDO e não sobre a mecânica do runtime — verificação alta com fundamentação baixa é um run que cumpriu todos os critérios de schema descrevendo um projeto que não existe, e essa combinação é invisível em qualquer outra métrica. Conta REFERÊNCIAS e não artefatos (um plano que cita vinte caminhos e uma ADR que cita um não podem pesar igual). A Arena tem o campo e o agrega, mas **não o mede nos casos embutidos de propósito**: eles são tarefas sintéticas ("desenhe a arquitetura de um monólito modular para um SaaS de faturamento") que não falam do projeto onde o comando roda — um artefato correto para o caso citaria `src/modules/billing/` e sairia como não fundamentado em qualquer projeto real. O número existiria, pareceria significativo, e mediria a coisa errada; o relatório diz `n/a`. É o instrumento que a pergunta em aberto "o grounding melhora o resultado?" precisa para deixar de ser argumento e virar número.
173
+ - **`produced` no payload de `--json` e do webhook**: o que o run gravou no projeto — o documento entregue e os arquivos materializados —, em caminhos RELATIVOS. É o que faltava para um agendador saber se há trabalho novo no disco sem abrir o trace. Caminho é metadado e cabe na regra do payload; caminho absoluto não cabe, porque carrega o diretório do usuário para um endpoint que costuma ser um canal de equipe. Ausente quando nada foi gravado, e ausência ali significa "não gravou", não "não sei".
174
+ - **Teto total do documento entregue** (512KB). O teto por seção (128KB) sozinho não limitava nada: um run de nove nós produzia um documento de mais de um megabyte. Passado o teto, as seções seguintes entram como referência para `.izanagi/state/artifacts/` em vez de conteúdo — o leitor continua sabendo que o artefato existe e onde encontrá-lo inteiro.
175
+ - **Outcome `not-applicable` na Verification Engine.** Distinto de `unknown`, e a diferença não é cosmética: `unknown` é "havia uma pergunta e a resposta não foi obtida" (juiz ausente) e NUNCA vira aprovação; `not-applicable` é "a pergunta não existe para este artefato". Groundedness sobre uma ADR que não cita arquivo nenhum não está sem resposta — está respondida por vacuidade. Sem essa distinção, o check novo derrubava todo artefato de prosa para `UNVERIFIED` e um `izanagi run` headless completo caía de `PASS` para `FAIL`. Critério inaplicável sai da conta: não conta como aprovado (não houve prova) nem como pendente (não há o que provar).
176
+ - **Check determinístico `references-exist` (groundedness).** A Verification Engine perguntava se o artefato tem os campos do schema e o tamanho mínimo; não perguntava se o conteúdo corresponde a alguma realidade — e é por aí que a alucinação passava: um plano bem formatado, com todos os campos, citando `app/controllers/users_controller.rb` num projeto sem `app/`. O check extrai as referências de caminho e olha o disco. A pergunta NÃO é "todos os arquivos citados existem?" (um plano legítimo propõe arquivos novos, e reprovar isso viraria ruído contra o trabalho): é **"o LUGAR citado existe?"**. Cobrado só quando o run leu o projeto (`survey` ligado) — exigir um layout que nunca foi mostrado ao agente seria reprovar por informação que o runtime decidiu não dar. Artefato que não cita caminho nenhum fica `UNKNOWN`, nunca aprovado.
177
+
178
+ ### Fixed
179
+ - **A telemetria de custo subestimava o gasto, e justamente na chamada que estourava o teto.** `ExecutionBudget.spend()` é chamado DEPOIS da resposta do modelo — os tokens já foram consumidos e o provider já cobrou —, mas recusava sem registrar quando o gasto passava de um teto. O run parava (certo), e reportava o consumo ATÉ a última chamada permitida (errado): num caso medido, `$0.001` de `$0.051` realmente gastos. Agora registra sempre e decide depois; parar continua sendo responsabilidade de quem chama, pelo `ok: false`. É a mesma classe do bug corrigido em `d1193ef` (resumo por fase divergindo da telemetria), num caminho que aquela correção não cobria.
180
+ - **O resultado do gasto do juiz semântico era ignorado.** Com a fase `evaluation` esgotada, cada nó seguinte continuava chamando o juiz: o teto de avaliação era decorativo. Agora o juiz é desligado no primeiro gasto recusado, com span `budget:judge-off` no trace, e o critério semântico volta a `UNVERIFIED` — nunca aprovação por omissão. Reprovar o nó seria pior: o trabalho dele não tem culpa do orçamento de verificação ter acabado.
181
+ - **O cache guardava resposta que reprovava na validação.** Na própria retentativa ela não voltava (a correção muda o system prompt, e portanto a chave), mas o run SEGUINTE com o mesmo objetivo recomeçava a partir da resposta que já se sabia ruim — deterministicamente, sempre. Um cache que existe para economizar não pode guardar o que já foi reprovado: o barato ali é repetir o erro. Agora só entra a resposta que produz artefato válido, conferida com a MESMA validação do Orchestrator (memoizada por `(kind, hash)`, então não paga segunda conta).
182
+ - **O cache de resposta ficou no `baseDir` na separação de raízes.** Ele vive em `.izanagi/state/cache/responses` — é estado pelo mesmo critério de trace e memória —, e num projeto sem `izanagi init` as respostas de todo projeto continuavam se acumulando dentro da instalação do pacote.
183
+ - **`izanagi diagnose` lia o `runtime-state.json` da instalação do framework**, então reportava "presente" olhando o estado de outro lugar.
184
+ - **A telemetria afirmava paralelismo no momento em que ele era cortado.** `recordParallelBatch` recebia o tamanho do batch ANTES do teto de concorrência entrar, então um batch de 5 com pool de 1 aparecia como "paralelo 5" — e isso acontecia justamente no caso da degradação `reduce-parallelism`. Agora conta o paralelismo EFETIVO (`min(batch, pool)`).
185
+ - **Decompor podia AUMENTAR o orçamento do pai.** O piso de 512 tokens por sub-tarefa existe para que uma sub-tarefa minúscula não gaste a chamada sem produzir nada — mas o piso sozinho quebrava a regra que ele servia: com 2000 tokens e 5 sub-tarefas, cada uma recebia 512 e o subgrafo saía com 2560. Decompor virava a forma de multiplicar o orçamento, que é exatamente o incentivo que "decompor não libera orçamento" existe para eliminar. Agora a LARGURA é limitada pelo que o pai paga no piso: quem não tem orçamento para duas sub-tarefas não decompõe, e um corte de largura é registrado em `issues` em vez de acontecer em silêncio.
186
+ - **Sub-tarefa herdava as permissões do pai.** Hoje seriam inertes (só nó de tool as usa, e sub-tarefa não tem tool), mas conceder privilégio que ninguém vai usar é como um privilégio usado indevidamente começa. Menor privilégio é por construção, não por acidente de quem consome.
187
+ - **A memória contava retentativa como recorrência.** O `Healer` registrava o padrão de falha conhecido a cada chamada de cura, e o orquestrador criava um `Healer` novo por rodada: um único incidente com três retries virava "3 ocorrências" e somava +0.09 de confiança. A memória passava a medir teimosia do runtime em vez de recorrência do problema — e é a recorrência que decide se um padrão vira conhecimento reutilizável e se o planejamento sobe o modo. Agora o `Healer` é do run e conta uma vez por `nó:padrão`: dentro do run é o mesmo incidente, entre runs é recorrência de verdade.
188
+ - **`budgetLimits.maxTokens` era descartado em silêncio.** Custo, tempo, agentes, retries e tool calls do `budgetLimits` eram honrados; o teto de tokens era substituído pelo do plano sem erro nem aviso. Agora vale o MENOR dos dois: nenhum dos dois pode afrouxar o outro.
189
+ - **Estado de projeto vazava para dentro da instalação do framework.** `resolveFrameworkRoot` responde "de onde leio agentes e skills?" e cai na instalação do pacote quando o projeto não tem `.agents/` — correto para assets. O estado (`.izanagi/state`: trace, artefatos **com conteúdo**, memória, checkpoints, decisões, aprovações) usava a mesma raiz, então todo projeto sem `izanagi init` gravava dentro de `node_modules/izanagi-ai/`, compartilhado com todos os outros. Consequências reais: `izanagi trace` listava execução de outro projeto, artefato de um projeto era legível de outro, e `npm update izanagi-ai` apagava o histórico. Novo `resolveStateRoot` e `OrchestratorOptions.stateDir` (default `baseDir`, então nenhum caller existente muda). **Projeto inicializado não muda de lugar** — mover o estado apagaria o histórico de quem já usa; o que muda é só o caso quebrado. Encontrado procurando o trace de um run de teste e achando 300 traces de outros projetos no diretório do framework.
190
+ - **Sandbox de tool e `file-exists` resolviam contra a raiz do FRAMEWORK.** `baseDir` é `<projeto>/.agents` num projeto inicializado, ou a própria instalação do pacote quando não há uma. Um nó `fs.read` lia dentro de `.agents/` em vez do projeto, e um check `file-exists` procurava o arquivo no lugar errado. Rodando de dentro do checkout do framework as duas coincidem, que é exatamente por que passava despercebido.
191
+ - **Nó que terminava `failed` sem produzir artefato era invisível para a avaliação final.** `correctness` é a média das verificações registradas e `artifactValidity` a razão dos artefatos existentes: as duas ignoram quem não chegou a produzir nada. Na prática, um nó abortado por permissão negada deixava o run terminar `PASS` com score alto. Agora cada nó falho entra como regressão — nó `optional` fica de fora, porque reforço que falha não invalida evidência que passou.
192
+ - **Replanejamento apagava o contrato de um nó de tool.** `contractFor` por cima de um contrato de tool removeria `tool` e `permissions`, e o nó viraria uma chamada de modelo com o mesmo id: a "correção" seria uma regressão silenciosa. Nó de tool não tem plano B estrutural (não há agente para trocar nem papel para subir) e volta para a fila com o mesmo contrato, com o motivo registrado nas decisões.
193
+ - **Duas fixtures de teste mediam a coisa errada.** `orchestrator.test.ts` e `checkpoint.test.ts` não cobriam o schema de `critique`/`test-plan`: o nó produzia artefato inválido, terminava `failed`, e o run seguia `PASS`. Só apareceu quando nó falho passou a contar.
194
+
195
+ ### Compatibility
196
+ - **Nenhuma quebra.** Sem `--output` e sem `--survey`, o plano é byte-a-byte o de antes e nenhum nó do grafo recebe permissão. `workspaceDir` tem default `baseDir`, então todo caller existente do `Orchestrator` mantém o comportamento exato — a CLI e o SDK declaram o valor novo.
197
+ - **Mudança de veredito possível**: um run cujo nó falhava sem produzir artefato passava a `PASS` e agora sai `FAIL`. Isso é a correção, não a regressão: o run reportava sucesso com uma tarefa não executada.
198
+
199
+ ### Tests
200
+ - **Suíte de cenários ponta a ponta** (`e2e-scenarios.test.ts`): os dez cenários que a arquitetura precisa cobrir — trivial, médio, complexo, paralelo, falha, retentativa, escalada de papel, estouro de orçamento, parada antecipada e aprovação humana — cada um passando pelo Commander e pelo Orchestrator de verdade. Só o producer é injetado: substituir qualquer outra peça faria o teste medir a substituição em vez do runtime. Os outros arquivos testam peças; este testa comportamento observável de um run inteiro.
201
+ - 682 testes, 682 passando (110 novos: 23 em `delivery.test.ts`, 18 em `grounding.test.ts`, 17 em `groundedness.test.ts`, 20 em `materialize.test.ts`, 10 em `e2e-scenarios.test.ts`, 5 em `state-root.test.ts`, 5 em `arena.test.ts`).
202
+
203
+ ---
204
+
7
205
  ## [3.17.1]: 2026-09-02
8
206
 
9
207
  ### Fixed