@event4u/agent-config 6.0.0 → 7.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1758) hide show
  1. package/.claude-plugin/marketplace.json +39 -7
  2. package/AGENTS.md +8 -7
  3. package/CHANGELOG.md +557 -422
  4. package/CONTRIBUTING.md +1 -1
  5. package/README.md +18 -16
  6. package/dist/agent-src/commands/agent-handoff.md +5 -4
  7. package/dist/agent-src/commands/agent-status.md +3 -2
  8. package/dist/agent-src/commands/agents/audit.md +4 -3
  9. package/dist/agent-src/commands/agents/init.md +4 -1
  10. package/dist/agent-src/commands/agents/optimize.md +5 -4
  11. package/dist/agent-src/commands/agents/user/accept.md +1 -0
  12. package/dist/agent-src/commands/agents/user/init.md +1 -0
  13. package/dist/agent-src/commands/agents/user/review.md +1 -0
  14. package/dist/agent-src/commands/agents/user/show.md +1 -0
  15. package/dist/agent-src/commands/agents/user/update.md +1 -0
  16. package/dist/agent-src/commands/agents/user.md +1 -0
  17. package/dist/agent-src/commands/agents.md +1 -0
  18. package/dist/agent-src/commands/analytics/prune.md +3 -2
  19. package/dist/agent-src/commands/analytics/show.md +3 -2
  20. package/dist/agent-src/commands/analytics.md +3 -2
  21. package/dist/agent-src/commands/analyze/decision.md +108 -0
  22. package/dist/agent-src/commands/analyze/incident.md +120 -0
  23. package/dist/agent-src/commands/analyze/near-miss.md +113 -0
  24. package/dist/agent-src/commands/analyze/postmortem.md +130 -0
  25. package/dist/agent-src/commands/analyze/premortem.md +104 -0
  26. package/dist/agent-src/commands/analyze-reference-repo.md +1 -0
  27. package/dist/agent-src/commands/analyze.md +124 -0
  28. package/dist/agent-src/commands/brand/identity.md +27 -0
  29. package/dist/agent-src/commands/brand/review.md +27 -0
  30. package/dist/agent-src/commands/brand/strategy.md +27 -0
  31. package/dist/agent-src/commands/brand/tokens.md +28 -0
  32. package/dist/agent-src/commands/brand/voice.md +27 -0
  33. package/dist/agent-src/commands/brand.md +58 -0
  34. package/dist/agent-src/commands/bug-fix.md +1 -0
  35. package/dist/agent-src/commands/bug-investigate.md +1 -0
  36. package/dist/agent-src/commands/challenge-me/vision.md +3 -2
  37. package/dist/agent-src/commands/challenge-me/with-docs.md +3 -2
  38. package/dist/agent-src/commands/challenge-me.md +3 -2
  39. package/dist/agent-src/commands/chat-history/import.md +9 -9
  40. package/dist/agent-src/commands/chat-history.md +32 -30
  41. package/dist/agent-src/commands/check-current-md.md +4 -3
  42. package/dist/agent-src/commands/commit/in-chunks.md +1 -0
  43. package/dist/agent-src/commands/commit.md +1 -0
  44. package/dist/agent-src/commands/condense.md +3 -2
  45. package/dist/agent-src/commands/context/create.md +1 -0
  46. package/dist/agent-src/commands/context/refactor.md +1 -0
  47. package/dist/agent-src/commands/context.md +1 -0
  48. package/dist/agent-src/commands/cost-report.md +5 -4
  49. package/dist/agent-src/commands/council/analysis.md +3 -2
  50. package/dist/agent-src/commands/council/debate.md +7 -6
  51. package/dist/agent-src/commands/council/default.md +48 -20
  52. package/dist/agent-src/commands/council/design.md +3 -2
  53. package/dist/agent-src/commands/council/optimize.md +3 -2
  54. package/dist/agent-src/commands/council/pr.md +3 -2
  55. package/dist/agent-src/commands/council.md +4 -3
  56. package/dist/agent-src/commands/e2e-heal.md +1 -0
  57. package/dist/agent-src/commands/e2e-plan.md +1 -0
  58. package/dist/agent-src/commands/estimate-ticket.md +1 -0
  59. package/dist/agent-src/commands/feature/dev.md +1 -0
  60. package/dist/agent-src/commands/feature/explore.md +1 -0
  61. package/dist/agent-src/commands/feature/plan.md +6 -6
  62. package/dist/agent-src/commands/feature/refactor.md +1 -0
  63. package/dist/agent-src/commands/feature/roadmap.md +1 -0
  64. package/dist/agent-src/commands/feature.md +1 -0
  65. package/dist/agent-src/commands/fix/ci.md +1 -0
  66. package/dist/agent-src/commands/fix/portability.md +4 -3
  67. package/dist/agent-src/commands/fix/pr-comments.md +147 -15
  68. package/dist/agent-src/commands/fix/refs.md +4 -3
  69. package/dist/agent-src/commands/fix/seeder.md +1 -0
  70. package/dist/agent-src/commands/fix.md +8 -8
  71. package/dist/agent-src/commands/ghostwriter/delete.md +1 -0
  72. package/dist/agent-src/commands/ghostwriter/fetch.md +1 -0
  73. package/dist/agent-src/commands/ghostwriter/list.md +1 -0
  74. package/dist/agent-src/commands/ghostwriter/show.md +1 -0
  75. package/dist/agent-src/commands/ghostwriter/write.md +1 -0
  76. package/dist/agent-src/commands/ghostwriter.md +1 -0
  77. package/dist/agent-src/commands/grill-me.md +3 -2
  78. package/dist/agent-src/commands/image/analyse.md +1 -0
  79. package/dist/agent-src/commands/image/create.md +1 -0
  80. package/dist/agent-src/commands/image/verify.md +1 -0
  81. package/dist/agent-src/commands/image.md +1 -0
  82. package/dist/agent-src/commands/implement-ticket.md +37 -6
  83. package/dist/agent-src/commands/jira-ticket.md +1 -0
  84. package/dist/agent-src/commands/judge/on-diff.md +1 -0
  85. package/dist/agent-src/commands/judge/solo.md +1 -0
  86. package/dist/agent-src/commands/judge/steps.md +1 -0
  87. package/dist/agent-src/commands/judge.md +1 -0
  88. package/dist/agent-src/commands/knowledge/cross-repo.md +2 -1
  89. package/dist/agent-src/commands/knowledge/forget.md +1 -0
  90. package/dist/agent-src/commands/knowledge/ingest.md +1 -0
  91. package/dist/agent-src/commands/knowledge/list.md +1 -0
  92. package/dist/agent-src/commands/knowledge.md +1 -0
  93. package/dist/agent-src/commands/memory/add.md +9 -7
  94. package/dist/agent-src/commands/memory/learn-low-impact.md +3 -2
  95. package/dist/agent-src/commands/memory/load.md +7 -7
  96. package/dist/agent-src/commands/memory/mine-session.md +39 -12
  97. package/dist/agent-src/commands/memory/promote.md +3 -2
  98. package/dist/agent-src/commands/memory/propose.md +7 -6
  99. package/dist/agent-src/commands/memory.md +3 -2
  100. package/dist/agent-src/commands/mission/upgrade.md +182 -0
  101. package/dist/agent-src/commands/mode.md +1 -0
  102. package/dist/agent-src/commands/module/create.md +1 -0
  103. package/dist/agent-src/commands/module/explore.md +1 -0
  104. package/dist/agent-src/commands/module.md +1 -0
  105. package/dist/agent-src/commands/optimize/agents-dir.md +1 -0
  106. package/dist/agent-src/commands/optimize/augmentignore.md +1 -0
  107. package/dist/agent-src/commands/optimize/rtk.md +1 -0
  108. package/dist/agent-src/commands/optimize/skills.md +3 -2
  109. package/dist/agent-src/commands/optimize-prompt.md +1 -0
  110. package/dist/agent-src/commands/optimize.md +1 -0
  111. package/dist/agent-src/commands/orchestrate.md +2 -1
  112. package/dist/agent-src/commands/override/create.md +1 -0
  113. package/dist/agent-src/commands/override/manage.md +1 -0
  114. package/dist/agent-src/commands/override.md +1 -0
  115. package/dist/agent-src/commands/package-reset.md +1 -0
  116. package/dist/agent-src/commands/package-test.md +1 -0
  117. package/dist/agent-src/commands/post-as/ghostwriter.md +1 -0
  118. package/dist/agent-src/commands/post-as/me.md +1 -0
  119. package/dist/agent-src/commands/post-as.md +1 -0
  120. package/dist/agent-src/commands/pr/create/description-only.md +1 -0
  121. package/dist/agent-src/commands/pr/create.md +31 -4
  122. package/dist/agent-src/commands/prediction-pool.md +1 -0
  123. package/dist/agent-src/commands/prepare-for-review.md +1 -0
  124. package/dist/agent-src/commands/profile/activate.md +1 -0
  125. package/dist/agent-src/commands/profile/deactivate.md +1 -0
  126. package/dist/agent-src/commands/profile/show.md +1 -0
  127. package/dist/agent-src/commands/profile.md +1 -0
  128. package/dist/agent-src/commands/project-analyze.md +1 -0
  129. package/dist/agent-src/commands/project-health.md +1 -0
  130. package/dist/agent-src/commands/quality-fix.md +1 -0
  131. package/dist/agent-src/commands/refine-ticket.md +1 -0
  132. package/dist/agent-src/commands/research/deep.md +1 -0
  133. package/dist/agent-src/commands/research/report.md +1 -0
  134. package/dist/agent-src/commands/research.md +1 -0
  135. package/dist/agent-src/commands/review-changes.md +9 -0
  136. package/dist/agent-src/commands/review-routing.md +1 -0
  137. package/dist/agent-src/commands/roadmap/ai-council.md +1 -0
  138. package/dist/agent-src/commands/roadmap/create.md +1 -0
  139. package/dist/agent-src/commands/roadmap/materialize.md +73 -0
  140. package/dist/agent-src/commands/roadmap/process-full.md +1 -0
  141. package/dist/agent-src/commands/roadmap/process-phase.md +1 -0
  142. package/dist/agent-src/commands/roadmap/process-step.md +1 -0
  143. package/dist/agent-src/commands/roadmap.md +1 -0
  144. package/dist/agent-src/commands/rule-compliance-audit.md +1 -0
  145. package/dist/agent-src/commands/security-audit-config.md +84 -0
  146. package/dist/agent-src/commands/set-cost-profile.md +1 -0
  147. package/dist/agent-src/commands/skill/preview.md +2 -1
  148. package/dist/agent-src/commands/skill.md +1 -0
  149. package/dist/agent-src/commands/skills/discover.md +2 -1
  150. package/dist/agent-src/commands/skills.md +1 -0
  151. package/dist/agent-src/commands/sync-agent-settings.md +1 -0
  152. package/dist/agent-src/commands/sync-gitignore/fix.md +1 -0
  153. package/dist/agent-src/commands/sync-gitignore.md +1 -0
  154. package/dist/agent-src/commands/tests/create.md +1 -0
  155. package/dist/agent-src/commands/tests/execute.md +1 -0
  156. package/dist/agent-src/commands/tests.md +1 -0
  157. package/dist/agent-src/commands/threat-model.md +5 -4
  158. package/dist/agent-src/commands/update-form-request-messages.md +1 -0
  159. package/dist/agent-src/commands/upstream-contribute.md +4 -3
  160. package/dist/agent-src/commands/video/from-script.md +3 -2
  161. package/dist/agent-src/commands/video/from-song.md +4 -3
  162. package/dist/agent-src/commands/video/scene.md +2 -1
  163. package/dist/agent-src/commands/video/stitch.md +1 -0
  164. package/dist/agent-src/commands/video/storyboard.md +2 -1
  165. package/dist/agent-src/commands/video.md +4 -3
  166. package/dist/agent-src/commands/work.md +1 -0
  167. package/dist/agent-src/contexts/augment-infrastructure.md +1 -1
  168. package/dist/agent-src/contexts/communication/rules-auto/skill-quality-mechanics.md +1 -1
  169. package/dist/agent-src/contexts/communication/rules-auto/slash-command-routing-policy-mechanics.md +2 -2
  170. package/dist/agent-src/contexts/communication/rules-auto/source-of-truth-mechanics.md +3 -3
  171. package/dist/agent-src/contexts/communication/rules-auto/think-before-action-mechanics.md +6 -6
  172. package/dist/agent-src/contexts/communication/rules-auto/user-interaction-mechanics.md +1 -1
  173. package/dist/agent-src/contexts/contracts/consumer-agents-md-guide.md +2 -2
  174. package/dist/agent-src/contexts/execution/evidence-discipline.md +153 -0
  175. package/dist/agent-src/contexts/execution/project-intelligence.md +264 -0
  176. package/dist/agent-src/contexts/execution/rdp-gate.md +75 -0
  177. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +2 -1
  178. package/dist/agent-src/contexts/subagent-configuration.md +1 -0
  179. package/dist/agent-src/personas/advisors/contrarian.md +1 -1
  180. package/dist/agent-src/personas/advisors/executor.md +1 -1
  181. package/dist/agent-src/personas/advisors/expansionist.md +1 -1
  182. package/dist/agent-src/personas/advisors/first-principles.md +1 -1
  183. package/dist/agent-src/personas/advisors/outsider.md +1 -1
  184. package/dist/agent-src/personas/ai-video-technical-director.md +1 -1
  185. package/dist/agent-src/personas/brand-strategist.md +74 -0
  186. package/dist/agent-src/personas/design-director.md +74 -0
  187. package/dist/agent-src/rules/autonomous-execution.md +12 -0
  188. package/dist/agent-src/rules/brand-consistency.md +77 -0
  189. package/dist/agent-src/rules/brand-source-of-truth.md +57 -0
  190. package/dist/agent-src/rules/direct-answers.md +2 -0
  191. package/dist/agent-src/rules/domain-safety-disclaimer.md +2 -0
  192. package/dist/agent-src/rules/external-reference-deep-dive.md +1 -1
  193. package/dist/agent-src/rules/git-history-discipline.md +48 -1
  194. package/dist/agent-src/rules/icon-consistency.md +53 -0
  195. package/dist/agent-src/rules/image-likeness-and-rights.md +67 -0
  196. package/dist/agent-src/rules/improve-before-implement.md +12 -0
  197. package/dist/agent-src/rules/lethal-trifecta-guard.md +80 -0
  198. package/dist/agent-src/rules/no-pr-progress-comments.md +3 -4
  199. package/dist/agent-src/rules/notes-first-reasoning.md +71 -0
  200. package/dist/agent-src/rules/persona-governance.md +2 -2
  201. package/dist/agent-src/rules/provider-lifecycle-discipline.md +3 -1
  202. package/dist/agent-src/rules/roadmap-progress-sync.md +58 -31
  203. package/dist/agent-src/rules/security-sensitive-stop.md +22 -3
  204. package/dist/agent-src/rules/size-enforcement.md +1 -1
  205. package/dist/agent-src/rules/source-confidentiality.md +97 -0
  206. package/dist/agent-src/rules/source-discovery-gate.md +98 -0
  207. package/dist/agent-src/rules/think-before-action.md +10 -1
  208. package/dist/agent-src/rules/ui-audit-gate.md +2 -0
  209. package/dist/agent-src/rules/untrusted-input-defense.md +76 -0
  210. package/dist/agent-src/rules/user-interaction.md +1 -1
  211. package/dist/agent-src/scripts/archive_completed_roadmaps.ts +392 -0
  212. package/dist/agent-src/scripts/update_roadmap_progress.ts +824 -0
  213. package/dist/agent-src/skills/adr-create/SKILL.md +5 -5
  214. package/dist/agent-src/skills/adversarial-review/SKILL.md +14 -0
  215. package/dist/agent-src/skills/agent-security-review/SKILL.md +113 -0
  216. package/dist/agent-src/skills/agent-security-review/evals/triggers.json +52 -0
  217. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +1 -1
  218. package/dist/agent-src/skills/ai-council/SKILL.md +4 -4
  219. package/dist/agent-src/skills/analysis-autonomous-mode/SKILL.md +9 -13
  220. package/dist/agent-src/skills/async-python-patterns/SKILL.md +1 -1
  221. package/dist/agent-src/skills/blade-ui/SKILL.md +12 -5
  222. package/dist/agent-src/skills/blameless-post-mortem/SKILL.md +199 -0
  223. package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +12 -11
  224. package/dist/agent-src/skills/brand/ATTRIBUTION.md +38 -0
  225. package/dist/agent-src/skills/brand/SKILL.md +115 -0
  226. package/dist/agent-src/skills/brand/data/archetypes.csv +13 -0
  227. package/dist/agent-src/skills/brand/data/color-psychology.csv +14 -0
  228. package/dist/agent-src/skills/brand/data/logo-style-fit.csv +13 -0
  229. package/dist/agent-src/skills/brand/data/manifest.json +226 -0
  230. package/dist/agent-src/skills/brand/data/messaging-frameworks.csv +13 -0
  231. package/dist/agent-src/skills/brand/data/naming-patterns.csv +13 -0
  232. package/dist/agent-src/skills/brand/data/typography-principles.csv +13 -0
  233. package/dist/agent-src/skills/brand/data/voice-tone.csv +13 -0
  234. package/dist/agent-src/skills/brand/evals/triggers.json +17 -0
  235. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +89 -0
  236. package/dist/agent-src/skills/brand-asset-generation/evals/triggers.json +17 -0
  237. package/dist/agent-src/skills/brand-audit/SKILL.md +67 -0
  238. package/dist/agent-src/skills/brand-audit/evals/triggers.json +17 -0
  239. package/dist/agent-src/skills/brand-identity/SKILL.md +101 -0
  240. package/dist/agent-src/skills/brand-identity/evals/triggers.json +17 -0
  241. package/dist/agent-src/skills/brand-strategy/SKILL.md +83 -0
  242. package/dist/agent-src/skills/brand-strategy/evals/triggers.json +17 -0
  243. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +102 -0
  244. package/dist/agent-src/skills/brand-to-tokens/evals/triggers.json +17 -0
  245. package/dist/agent-src/skills/brand-to-tokens/templates/marp-brand-deck.md.example +46 -0
  246. package/dist/agent-src/skills/brand-to-tokens/templates/reveal-brand-deck.yaml +32 -0
  247. package/dist/agent-src/skills/canvas-design/evals/triggers.json +1 -0
  248. package/dist/agent-src/skills/check-refs/SKILL.md +5 -5
  249. package/dist/agent-src/skills/code-review/SKILL.md +6 -15
  250. package/dist/agent-src/skills/command-routing/SKILL.md +1 -1
  251. package/dist/agent-src/skills/command-writing/SKILL.md +2 -2
  252. package/dist/agent-src/skills/complexity-first-planning/SKILL.md +96 -0
  253. package/dist/agent-src/skills/complexity-first-planning/evals/triggers.json +17 -0
  254. package/dist/agent-src/skills/context-authoring/SKILL.md +2 -2
  255. package/dist/agent-src/skills/context-document/SKILL.md +35 -2
  256. package/dist/agent-src/skills/copilot-config/SKILL.md +3 -4
  257. package/dist/agent-src/skills/corpus-grounding/evals/triggers.json +1 -0
  258. package/dist/agent-src/skills/corpus-grounding/scripts/bm25_search.ts +482 -0
  259. package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.ts +803 -0
  260. package/dist/agent-src/skills/corpus-grounding/scripts/ground.ts +541 -0
  261. package/dist/agent-src/skills/corpus-grounding/scripts/schema_validator.ts +309 -0
  262. package/dist/agent-src/skills/database/SKILL.md +26 -4
  263. package/dist/agent-src/skills/decision-record/SKILL.md +1 -1
  264. package/dist/agent-src/skills/decision-record/evals/triggers.json +17 -0
  265. package/dist/agent-src/skills/decision-review/SKILL.md +179 -0
  266. package/dist/agent-src/skills/defense-in-depth/SKILL.md +1 -1
  267. package/dist/agent-src/skills/description-assist/SKILL.md +1 -1
  268. package/dist/agent-src/skills/design-intelligence/SKILL.md +1 -1
  269. package/dist/agent-src/skills/design-intelligence/data/manifest.json +23 -6
  270. package/dist/agent-src/skills/design-intelligence/evals/triggers.json +1 -0
  271. package/dist/agent-src/skills/design-tokens/evals/triggers.json +1 -0
  272. package/dist/agent-src/skills/design-tokens/scripts/tokens.ts +888 -0
  273. package/dist/agent-src/skills/developer-like-execution/SKILL.md +5 -4
  274. package/dist/agent-src/skills/doc-coauthoring/evals/triggers.json +1 -0
  275. package/dist/agent-src/skills/eloquent/evals/triggers.json +1 -0
  276. package/dist/agent-src/skills/emit-tickets/SKILL.md +198 -0
  277. package/dist/agent-src/skills/error-handling-patterns/SKILL.md +1 -1
  278. package/dist/agent-src/skills/estimate-ticket/evals/triggers.json +1 -0
  279. package/dist/agent-src/skills/feature-planning/SKILL.md +2 -2
  280. package/dist/agent-src/skills/git-workflow/SKILL.md +33 -0
  281. package/dist/agent-src/skills/guideline-writing/SKILL.md +2 -2
  282. package/dist/agent-src/skills/iconography/SKILL.md +88 -0
  283. package/dist/agent-src/skills/iconography/evals/triggers.json +17 -0
  284. package/dist/agent-src/skills/image-analyser/evals/triggers.json +1 -0
  285. package/dist/agent-src/skills/image-creator/evals/triggers.json +1 -0
  286. package/dist/agent-src/skills/image-editing/SKILL.md +100 -0
  287. package/dist/agent-src/skills/image-editing/evals/triggers.json +17 -0
  288. package/dist/agent-src/skills/image-generation/SKILL.md +95 -0
  289. package/dist/agent-src/skills/image-generation/evals/triggers.json +17 -0
  290. package/dist/agent-src/skills/image-provider-routing/SKILL.md +96 -0
  291. package/dist/agent-src/skills/image-provider-routing/evals/triggers.json +17 -0
  292. package/dist/agent-src/skills/launch-readiness/SKILL.md +21 -0
  293. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +12 -8
  294. package/dist/agent-src/skills/lint-skills/SKILL.md +5 -5
  295. package/dist/agent-src/skills/logo-generation/SKILL.md +98 -0
  296. package/dist/agent-src/skills/logo-generation/evals/triggers.json +17 -0
  297. package/dist/agent-src/skills/markitdown/SKILL.md +1 -1
  298. package/dist/agent-src/skills/mcp-builder/SKILL.md +1 -1
  299. package/dist/agent-src/skills/md-language-check/SKILL.md +1 -1
  300. package/dist/agent-src/skills/memory-consolidation/SKILL.md +63 -17
  301. package/dist/agent-src/skills/motion-choreographer/SKILL.md +1 -1
  302. package/dist/agent-src/skills/php-coder/evals/triggers.json +1 -0
  303. package/dist/agent-src/skills/prediction-pool-optimizer/evals/triggers.json +1 -0
  304. package/dist/agent-src/skills/premortem/SKILL.md +137 -0
  305. package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +115 -0
  306. package/dist/agent-src/skills/prompt-engineering-image/evals/triggers.json +17 -0
  307. package/dist/agent-src/skills/prompt-engineering-patterns/SKILL.md +1 -1
  308. package/dist/agent-src/skills/prompt-validator/evals/triggers.json +1 -0
  309. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +12 -5
  310. package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.ts +388 -0
  311. package/dist/agent-src/skills/readme-writing-package/SKILL.md +1 -1
  312. package/dist/agent-src/skills/reasoning-orchestrator/SKILL.md +119 -0
  313. package/dist/agent-src/skills/reasoning-orchestrator/evals/triggers.json +17 -0
  314. package/dist/agent-src/skills/receiving-code-review/SKILL.md +6 -6
  315. package/dist/agent-src/skills/refine-prompt/SKILL.md +1 -1
  316. package/dist/agent-src/skills/refine-ticket/SKILL.md +1 -1
  317. package/dist/agent-src/skills/refine-ticket/evals/triggers.json +1 -0
  318. package/dist/agent-src/skills/repomix-packer/SKILL.md +1 -1
  319. package/dist/agent-src/skills/roadmap-management/SKILL.md +16 -3
  320. package/dist/agent-src/skills/roadmap-writing/SKILL.md +76 -0
  321. package/dist/agent-src/skills/root-cause-frameworks/SKILL.md +146 -0
  322. package/dist/agent-src/skills/rule-refactor/SKILL.md +9 -9
  323. package/dist/agent-src/skills/rule-writing/SKILL.md +7 -7
  324. package/dist/agent-src/skills/script-writing/SKILL.md +2 -2
  325. package/dist/agent-src/skills/secrets-management/SKILL.md +1 -1
  326. package/dist/agent-src/skills/security-audit/SKILL.md +5 -0
  327. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +19 -3
  328. package/dist/agent-src/skills/skill-management/SKILL.md +3 -3
  329. package/dist/agent-src/skills/skill-reviewer/SKILL.md +1 -1
  330. package/dist/agent-src/skills/skill-writing/SKILL.md +5 -5
  331. package/dist/agent-src/skills/skill-writing/evals/triggers.json +1 -0
  332. package/dist/agent-src/skills/source-discovery/SKILL.md +182 -0
  333. package/dist/agent-src/skills/standards-from-config/SKILL.md +93 -0
  334. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +10 -3
  335. package/dist/agent-src/skills/systematic-debugging/SKILL.md +7 -0
  336. package/dist/agent-src/skills/tailwind-engineer/scripts/tailwind_config_gen.ts +561 -0
  337. package/dist/agent-src/skills/testing-anti-patterns/SKILL.md +1 -1
  338. package/dist/agent-src/skills/testing-anti-patterns/process-anti-patterns.md +1 -1
  339. package/dist/agent-src/skills/threat-modeling/SKILL.md +1 -0
  340. package/dist/agent-src/skills/token-optimizer/SKILL.md +1 -1
  341. package/dist/agent-src/skills/typography-system/SKILL.md +138 -0
  342. package/dist/agent-src/skills/typography-system/evals/triggers.json +17 -0
  343. package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -3
  344. package/dist/agent-src/skills/verify-repair-loop/SKILL.md +209 -0
  345. package/dist/agent-src/skills/verify-repair-loop/evals/output-schema.yml +20 -0
  346. package/dist/agent-src/skills/verify-repair-loop/evals/triggers.json +17 -0
  347. package/dist/agent-src/templates/agent-settings.md +7 -0
  348. package/dist/agent-src/templates/agents/.gitattributes.fragment +0 -1
  349. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +4 -4
  350. package/dist/agent-src/templates/contexts/knowledge-card.md +69 -0
  351. package/dist/agent-src/templates/contexts/lesson-card.md +73 -0
  352. package/dist/agent-src/templates/roadmaps.md +29 -1
  353. package/dist/agent-src/templates/scripts/README.md +6 -6
  354. package/dist/agent-src/templates/scripts/check_memory.ts +640 -0
  355. package/dist/agent-src/templates/scripts/check_memory_proposal.ts +351 -0
  356. package/dist/agent-src/templates/scripts/implement_ticket/__main__.ts +27 -0
  357. package/dist/agent-src/templates/scripts/memory_hash.ts +333 -0
  358. package/dist/agent-src/templates/scripts/memory_lookup.ts +1067 -0
  359. package/dist/agent-src/templates/scripts/memory_report.ts +846 -0
  360. package/dist/agent-src/templates/scripts/memory_signal.ts +422 -0
  361. package/dist/agent-src/templates/scripts/memory_status.ts +191 -0
  362. package/dist/agent-src/templates/scripts/pr_review_routing.ts +523 -0
  363. package/dist/agent-src/templates/scripts/pr_risk_review.ts +0 -0
  364. package/dist/agent-src/templates/scripts/telemetry/aggregator.ts +0 -0
  365. package/dist/agent-src/templates/scripts/telemetry/boundary.ts +164 -0
  366. package/dist/agent-src/templates/scripts/telemetry/engagement.ts +479 -0
  367. package/dist/agent-src/templates/scripts/telemetry/report_renderer.ts +394 -0
  368. package/dist/agent-src/templates/scripts/telemetry/settings.ts +210 -0
  369. package/dist/agent-src/templates/scripts/telemetry_record.ts +255 -0
  370. package/dist/agent-src/templates/scripts/telemetry_report.ts +189 -0
  371. package/dist/agent-src/templates/scripts/telemetry_status.ts +312 -0
  372. package/dist/agent-src/templates/scripts/tier_usage_report.ts +597 -0
  373. package/dist/agent-src/templates/scripts/work_engine/__main__.ts +14 -0
  374. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.ts +1118 -0
  375. package/dist/agent-src/templates/scripts/work_engine/_lib/user_global_paths.ts +329 -0
  376. package/dist/agent-src/templates/scripts/work_engine/cli.ts +206 -0
  377. package/dist/agent-src/templates/scripts/work_engine/cli_args.ts +249 -0
  378. package/dist/agent-src/templates/scripts/work_engine/delivery_state.ts +225 -0
  379. package/dist/agent-src/templates/scripts/work_engine/directives/backend/analyze.ts +125 -0
  380. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.ts +189 -0
  381. package/dist/agent-src/templates/scripts/work_engine/directives/backend/index.ts +94 -0
  382. package/dist/agent-src/templates/scripts/work_engine/directives/backend/memory.ts +193 -0
  383. package/dist/agent-src/templates/scripts/work_engine/directives/backend/plan.ts +267 -0
  384. package/dist/agent-src/templates/scripts/work_engine/directives/backend/refine.ts +518 -0
  385. package/dist/agent-src/templates/scripts/work_engine/directives/backend/report.ts +379 -0
  386. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.ts +268 -0
  387. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.ts +258 -0
  388. package/dist/agent-src/templates/scripts/work_engine/directives/index.ts +32 -0
  389. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/contract.ts +243 -0
  390. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/index.ts +108 -0
  391. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.ts +259 -0
  392. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/ui.ts +216 -0
  393. package/dist/agent-src/templates/scripts/work_engine/directives/ui/_passthrough.ts +40 -0
  394. package/dist/agent-src/templates/scripts/work_engine/directives/ui/app_spec.ts +241 -0
  395. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +216 -0
  396. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.ts +506 -0
  397. package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.ts +325 -0
  398. package/dist/agent-src/templates/scripts/work_engine/directives/ui/index.ts +102 -0
  399. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +462 -0
  400. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +474 -0
  401. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +352 -0
  402. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.ts +33 -0
  403. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.ts +213 -0
  404. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/index.ts +111 -0
  405. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.ts +126 -0
  406. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/report.ts +112 -0
  407. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/test.ts +164 -0
  408. package/dist/agent-src/templates/scripts/work_engine/dispatcher.ts +515 -0
  409. package/dist/agent-src/templates/scripts/work_engine/emitters.ts +119 -0
  410. package/dist/agent-src/templates/scripts/work_engine/errors.ts +24 -0
  411. package/dist/agent-src/templates/scripts/work_engine/hook_bootstrap.ts +104 -0
  412. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.ts +176 -0
  413. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.ts +41 -0
  414. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.ts +89 -0
  415. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.ts +193 -0
  416. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.ts +304 -0
  417. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.ts +110 -0
  418. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.ts +118 -0
  419. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/index.ts +17 -0
  420. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.ts +161 -0
  421. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.ts +45 -0
  422. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/trace.ts +134 -0
  423. package/dist/agent-src/templates/scripts/work_engine/hooks/context.ts +94 -0
  424. package/dist/agent-src/templates/scripts/work_engine/hooks/events.ts +58 -0
  425. package/dist/agent-src/templates/scripts/work_engine/hooks/exceptions.ts +85 -0
  426. package/dist/agent-src/templates/scripts/work_engine/hooks/index.ts +27 -0
  427. package/dist/agent-src/templates/scripts/work_engine/hooks/registry.ts +66 -0
  428. package/dist/agent-src/templates/scripts/work_engine/hooks/runner.ts +90 -0
  429. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.ts +260 -0
  430. package/dist/agent-src/templates/scripts/work_engine/input_builders.ts +260 -0
  431. package/dist/agent-src/templates/scripts/work_engine/intent/classify.ts +466 -0
  432. package/dist/agent-src/templates/scripts/work_engine/migration/v0_to_v1.ts +531 -0
  433. package/dist/agent-src/templates/scripts/work_engine/orchestration.ts +366 -0
  434. package/dist/agent-src/templates/scripts/work_engine/persona_policy.ts +97 -0
  435. package/dist/agent-src/templates/scripts/work_engine/resolvers/diff.ts +135 -0
  436. package/dist/agent-src/templates/scripts/work_engine/resolvers/file.ts +175 -0
  437. package/dist/agent-src/templates/scripts/work_engine/resolvers/prompt.ts +115 -0
  438. package/dist/agent-src/templates/scripts/work_engine/scoring/confidence.ts +415 -0
  439. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.ts +466 -0
  440. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_trace.ts +298 -0
  441. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.ts +444 -0
  442. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +252 -0
  443. package/dist/agent-src/templates/scripts/work_engine/stack/runner.ts +745 -0
  444. package/dist/agent-src/templates/scripts/work_engine/state.ts +1151 -0
  445. package/dist/agent-src/templates/scripts/work_engine/state_io.ts +413 -0
  446. package/dist/agent-src/templates/tickets.md +120 -0
  447. package/dist/cli/agent-config.js +31 -300
  448. package/dist/cli/agent-config.js.map +1 -1
  449. package/dist/cli/commands/commands.js +11 -6
  450. package/dist/cli/commands/commands.js.map +1 -1
  451. package/dist/cli/commands/doctorShell.js +4 -22
  452. package/dist/cli/commands/doctorShell.js.map +1 -1
  453. package/dist/cli/commands/packs.js +1 -1
  454. package/dist/cli/commands/packs.js.map +1 -1
  455. package/dist/cli/commands/recordTriggerEval.js +179 -0
  456. package/dist/cli/commands/recordTriggerEval.js.map +1 -0
  457. package/dist/cli/commands/recordTriggerEval.test.js +113 -0
  458. package/dist/cli/commands/recordTriggerEval.test.js.map +1 -0
  459. package/dist/cli/commands/workspaces.js +1 -1
  460. package/dist/cli/commands/workspaces.js.map +1 -1
  461. package/dist/cli/discovery/loadManifest.js.map +1 -1
  462. package/dist/cli/main.js +330 -0
  463. package/dist/cli/main.js.map +1 -0
  464. package/dist/cli/python/knowledge_ingest.js +1048 -0
  465. package/dist/cli/python/knowledge_ingest.js.map +1 -0
  466. package/dist/cli/python/workspace_analytics.js +1085 -0
  467. package/dist/cli/python/workspace_analytics.js.map +1 -0
  468. package/dist/cli/python/workspace_crypto.js +544 -0
  469. package/dist/cli/python/workspace_crypto.js.map +1 -0
  470. package/dist/cli/python/workspace_documents.js +1216 -0
  471. package/dist/cli/python/workspace_documents.js.map +1 -0
  472. package/dist/cli/python/workspace_drive.js +574 -0
  473. package/dist/cli/python/workspace_drive.js.map +1 -0
  474. package/dist/cli/python/workspace_drive_health.js +628 -0
  475. package/dist/cli/python/workspace_drive_health.js.map +1 -0
  476. package/dist/cli/python/workspace_explain.js +765 -0
  477. package/dist/cli/python/workspace_explain.js.map +1 -0
  478. package/dist/cli/python/workspace_hosts.js +349 -0
  479. package/dist/cli/python/workspace_hosts.js.map +1 -0
  480. package/dist/cli/python/workspace_inbox.js +692 -0
  481. package/dist/cli/python/workspace_inbox.js.map +1 -0
  482. package/dist/cli/python/workspace_render.js +816 -0
  483. package/dist/cli/python/workspace_render.js.map +1 -0
  484. package/dist/cli/python/workspace_roles.js +487 -0
  485. package/dist/cli/python/workspace_roles.js.map +1 -0
  486. package/dist/cli/python/workspace_secrets.js +180 -0
  487. package/dist/cli/python/workspace_secrets.js.map +1 -0
  488. package/dist/cli/python/workspace_sessions.js +1079 -0
  489. package/dist/cli/python/workspace_sessions.js.map +1 -0
  490. package/dist/cli/python/workspace_skills.js +417 -0
  491. package/dist/cli/python/workspace_skills.js.map +1 -0
  492. package/dist/cli/registry.js +2 -0
  493. package/dist/cli/registry.js.map +1 -1
  494. package/dist/discovery/deprecation-report.md +1 -1
  495. package/dist/discovery/discovery-manifest.json +1802 -448
  496. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  497. package/dist/discovery/discovery-manifest.summary.md +12 -6
  498. package/dist/discovery/orphan-report.md +1 -1
  499. package/dist/discovery/packs.json +303 -43
  500. package/dist/discovery/trust-report.md +4 -4
  501. package/dist/discovery/workspaces.json +127 -41
  502. package/dist/install/install.mjs +13934 -0
  503. package/dist/mcp/registry-manifest.json +4 -4
  504. package/dist/router.json +1 -1
  505. package/dist/server/routes/wizard.js +54 -24
  506. package/dist/server/routes/wizard.js.map +1 -1
  507. package/dist/server/routes/workspace.js +44 -25
  508. package/dist/server/routes/workspace.js.map +1 -1
  509. package/dist/server/schemas/settings.js +33 -0
  510. package/dist/server/schemas/settings.js.map +1 -1
  511. package/docs/MIGRATION.md +1 -1
  512. package/docs/SKILL_CENSUS.md +344 -0
  513. package/docs/adrs/cost/0001-hard-stop-hook.md +5 -5
  514. package/docs/adrs/memory/0001-consumer-side-snapshot.md +15 -7
  515. package/docs/adrs/memory/README.md +6 -5
  516. package/docs/adrs/router/0001-three-tier-routing.md +2 -2
  517. package/docs/adrs/schema/0001-json-schema-frontmatter.md +2 -2
  518. package/docs/adrs/smoke/0001-per-tier-smoke-scripts.md +5 -5
  519. package/docs/adrs/telegraph/0001-default-off-until-bench.md +3 -3
  520. package/docs/architecture/augment-projection.md +1 -1
  521. package/docs/architecture/multi-tool-projection.md +3 -3
  522. package/docs/architecture.md +42 -11
  523. package/docs/archive/CHANGELOG-pre-2.2.0.md +30 -30
  524. package/docs/archive/CHANGELOG-pre-2.25.0.md +1 -1
  525. package/docs/archive/CHANGELOG-pre-4.5.0.md +1 -1
  526. package/docs/archive/CHANGELOG-pre-6.0.0.md +473 -0
  527. package/docs/benchmark.md +51 -53
  528. package/docs/benchmarks.md +2 -2
  529. package/docs/capability-matrix.md +32 -0
  530. package/docs/case-studies/frontend-design-positioning.md +86 -0
  531. package/docs/catalog.md +63 -15
  532. package/docs/command-flows.md +90 -92
  533. package/docs/command-naming-audit.md +60 -0
  534. package/docs/contracts/STABILITY.md +32 -0
  535. package/docs/contracts/adr-layout.md +2 -3
  536. package/docs/contracts/adr-level-6-productization.md +1 -1
  537. package/docs/contracts/agents-md-tech-stack.md +1 -1
  538. package/docs/contracts/ai-council-config.md +64 -29
  539. package/docs/contracts/analysis-memory-loop.md +149 -0
  540. package/docs/contracts/benchmark-ab-contract.md +3 -3
  541. package/docs/contracts/branch-protection-policy.md +27 -0
  542. package/docs/contracts/brand-token-consumption.md +69 -0
  543. package/docs/contracts/command-clusters.md +3 -2
  544. package/docs/contracts/command-surface-tiers.md +13 -0
  545. package/docs/contracts/cost-enforcement.md +1 -1
  546. package/docs/contracts/cost-summary-schema.md +1 -1
  547. package/docs/contracts/daily-workspace.md +1 -0
  548. package/docs/contracts/discovery-manifest.schema.json +25 -4
  549. package/docs/contracts/explain-modes.md +1 -1
  550. package/docs/contracts/implement-ticket-flow.md +15 -16
  551. package/docs/contracts/install-layout.md +249 -0
  552. package/docs/contracts/kernel-membership.md +1 -1
  553. package/docs/contracts/linear-ai-rules-inclusion.md +2 -2
  554. package/docs/contracts/linter-structural-model.md +1 -1
  555. package/docs/contracts/mcp-discovery-phase-notice.md +1 -1
  556. package/docs/contracts/mcp-tool-inventory.md +10 -10
  557. package/docs/contracts/measurement-baseline.md +1 -1
  558. package/docs/contracts/memory-visibility-v1.md +1 -5
  559. package/docs/contracts/multi-tool-projection-fidelity.md +1 -1
  560. package/docs/contracts/namespace.md +3 -3
  561. package/docs/contracts/no-runtime-boundary.md +56 -0
  562. package/docs/contracts/package-self-orientation.md +24 -0
  563. package/docs/contracts/persona-schema.md +1 -1
  564. package/docs/contracts/provider-lifecycle.md +3 -3
  565. package/docs/contracts/reasoning-discipline-protocol.md +83 -0
  566. package/docs/contracts/rule-classification.md +3 -3
  567. package/docs/contracts/rule-interactions.md +1 -1
  568. package/docs/contracts/skill-domains.md +1 -1
  569. package/docs/contracts/smoke-contracts.md +2 -2
  570. package/docs/contracts/surface-tiers.md +81 -0
  571. package/docs/contracts/ticket-bundle-format.md +228 -0
  572. package/docs/contracts/universal-skills.md +0 -1
  573. package/docs/contracts/workspace-boundary.md +84 -0
  574. package/docs/cookbook.md +152 -0
  575. package/docs/customization.md +15 -4
  576. package/docs/decisions/ADR-009-event4u-namespace.md +1 -1
  577. package/docs/decisions/ADR-013-discovery-frontmatter-contract.md +17 -1
  578. package/docs/decisions/ADR-026-explain-mode-translation.md +1 -1
  579. package/docs/decisions/ADR-056-unvalidated-video-adapters-disposition.md +1 -1
  580. package/docs/decisions/ADR-059-render-resume-filesystem-as-state.md +1 -1
  581. package/docs/decisions/ADR-060-comfyui-sandbox-model.md +1 -1
  582. package/docs/decisions/ADR-061-corpus-grounding-layer.md +48 -1
  583. package/docs/decisions/ADR-088-no-external-runtime-federation.md +26 -27
  584. package/docs/decisions/ADR-090-visibility-command-frontmatter-field.md +95 -0
  585. package/docs/decisions/ADR-091-split-meta-capability-packs.md +113 -0
  586. package/docs/decisions/ADR-092-defer-command-tier-alias-removal.md +93 -0
  587. package/docs/decisions/ADR-093-ai-council-config-user-global.md +111 -0
  588. package/docs/decisions/ADR-094-agent-memory-layer-removal.md +94 -0
  589. package/docs/decisions/ADR-095-workspace-boundary-contract.md +108 -0
  590. package/docs/decisions/ADR-096-analysis-workbench.md +110 -0
  591. package/docs/decisions/ADR-097-mission-recipe-privilege-boundary.md +121 -0
  592. package/docs/decisions/ADR-098-evidence-first-structure-discovery.md +154 -0
  593. package/docs/decisions/ADR-099-file-first-pattern-library.md +87 -0
  594. package/docs/decisions/ADR-100-global-knowledge-card-sharing.md +133 -0
  595. package/docs/decisions/ADR-101-ticket-bundle-emission.md +109 -0
  596. package/docs/decisions/ADR-102-ticket-handoff-paste-and-mcp.md +72 -0
  597. package/docs/decisions/ADR-103-global-knowledge-default-off-until-measured.md +92 -0
  598. package/docs/decisions/ADR-200-python-to-typescript-migration.md +193 -0
  599. package/docs/decisions/INDEX.md +15 -0
  600. package/docs/development.md +5 -7
  601. package/docs/distribution/mcp-submission-checklist.md +3 -3
  602. package/docs/featured-commands.md +1 -1
  603. package/docs/featured-skills.md +1 -1
  604. package/docs/getting-started-by-role.md +2 -0
  605. package/docs/getting-started.md +4 -4
  606. package/docs/guidelines/agent-infra/5w2h-analysis.md +1 -1
  607. package/docs/guidelines/agent-infra/comparison-matrix.md +1 -1
  608. package/docs/guidelines/agent-infra/corpus-grounding-authoring.md +1 -1
  609. package/docs/guidelines/agent-infra/critical-thinking.md +1 -1
  610. package/docs/guidelines/agent-infra/engineering-memory-data-format.md +1 -5
  611. package/docs/guidelines/agent-infra/failure-signatures.md +35 -0
  612. package/docs/guidelines/agent-infra/first-principles.md +1 -1
  613. package/docs/guidelines/agent-infra/frontier-reasoning-operating-profile.md +169 -0
  614. package/docs/guidelines/agent-infra/inversion-thinking.md +1 -1
  615. package/docs/guidelines/agent-infra/ios-simulator-guide.md +9 -14
  616. package/docs/guidelines/agent-infra/mcp-request-signing.md +19 -22
  617. package/docs/guidelines/agent-infra/memory-access.md +25 -31
  618. package/docs/guidelines/agent-infra/mental-models.md +1 -1
  619. package/docs/guidelines/agent-infra/model-recommendation.md +29 -0
  620. package/docs/guidelines/agent-infra/scqa-framework.md +3 -3
  621. package/docs/guidelines/agent-infra/security-lint-containment.md +81 -0
  622. package/docs/guidelines/agent-infra/six-hats.md +1 -1
  623. package/docs/guidelines/agent-infra/size-and-scope.md +17 -0
  624. package/docs/guidelines/agent-infra/skill-quality-checklist.md +2 -2
  625. package/docs/guidelines/agent-infra/systems-thinking.md +1 -1
  626. package/docs/guidelines/agent-infra/untrusted-input-spotlighting.md +72 -0
  627. package/docs/guides/frontend-design-corpus-refresh.md +83 -0
  628. package/docs/guides/skill-preview.md +1 -1
  629. package/docs/hook-payload-capture.md +4 -4
  630. package/docs/installation.md +1 -1
  631. package/docs/mcp.md +3 -3
  632. package/docs/migration/consumer-template-consumption-model.md +145 -0
  633. package/docs/migration/divergences/README.md +55 -0
  634. package/docs/migration/divergences/_template.md +50 -0
  635. package/docs/migration/divergences/bench-stats-float-precision.md +72 -0
  636. package/docs/migration/divergences/mcp-telemetry-node-sqlite.md +61 -0
  637. package/docs/migration/divergences/pack-mcp-content-gzip-body.md +53 -0
  638. package/docs/migration/divergences/src-scripts-build_cloud_bundle.md +63 -0
  639. package/docs/migration/divergences/src-scripts-check_memory.md +91 -0
  640. package/docs/migration/divergences/src-scripts-inventory_abstraction_budget.md +65 -0
  641. package/docs/migration/divergences/src-scripts-lint_marketplace.md +57 -0
  642. package/docs/migration/divergences/src-scripts-lint_mcp_registry_manifest.md +70 -0
  643. package/docs/migration/divergences/src-scripts-spotcheck_thin_root.md +60 -0
  644. package/docs/migration/divergences/src-scripts-validate_agent_settings.md +58 -0
  645. package/docs/migration/node-floor.md +86 -0
  646. package/docs/migration/yaml-roundtrip-spike.md +163 -0
  647. package/docs/parity/bench-external.json +58 -0
  648. package/docs/parity/external-runtime.md +46 -0
  649. package/docs/personas.md +6 -1
  650. package/docs/quality.md +3 -3
  651. package/docs/role-experiences.md +19 -0
  652. package/docs/safety.md +3 -3
  653. package/docs/setup/per-ide/windsurf.md +1 -1
  654. package/docs/skills-catalog.md +26 -2
  655. package/docs/threat-model.md +28 -0
  656. package/llms.txt +25 -1
  657. package/package.json +10 -15
  658. package/src/config/agent-settings.template.yml +128 -3
  659. package/src/config/discovery/packs.yml +60 -0
  660. package/src/config/discovery/unassigned-artefacts.yml +6 -0
  661. package/src/config/discovery/workspaces.yml +5 -3
  662. package/src/config/gitignore-block.txt +13 -0
  663. package/src/scripts/_cli/cmd_doctor.ts +2306 -0
  664. package/src/scripts/_cli/cmd_explain.ts +748 -0
  665. package/src/scripts/_cli/cmd_export.ts +375 -0
  666. package/src/scripts/_cli/cmd_migrate.ts +951 -0
  667. package/src/scripts/_cli/cmd_prune.ts +610 -0
  668. package/src/scripts/_cli/cmd_refresh.ts +530 -0
  669. package/src/scripts/_cli/cmd_settings_check.ts +407 -0
  670. package/src/scripts/_cli/cmd_settings_migrate.ts +344 -0
  671. package/src/scripts/_cli/cmd_sync.ts +381 -0
  672. package/src/scripts/_cli/cmd_uninstall.ts +833 -0
  673. package/src/scripts/_cli/cmd_update.ts +585 -0
  674. package/src/scripts/_cli/cmd_upgrade.ts +390 -0
  675. package/src/scripts/_cli/cmd_validate.ts +394 -0
  676. package/src/scripts/_cli/cmd_versions.ts +492 -0
  677. package/src/scripts/_cli/explain_last/assumptions.ts +114 -0
  678. package/src/scripts/_cli/explain_last/council.ts +197 -0
  679. package/src/scripts/_cli/explain_last/halt.ts +73 -0
  680. package/src/scripts/_cli/explain_last/index.ts +155 -0
  681. package/src/scripts/_cli/explain_last/inputs.ts +211 -0
  682. package/src/scripts/_cli/explain_last/memory.ts +231 -0
  683. package/src/scripts/_cli/explain_last/provider.ts +82 -0
  684. package/src/scripts/_cli/explain_last/render.ts +54 -0
  685. package/src/scripts/_cli/explain_last/route.ts +70 -0
  686. package/src/scripts/_cli/explain_last/scrubber.ts +138 -0
  687. package/src/scripts/_cli/explain_last/sections/assumptions.ts +51 -0
  688. package/src/scripts/_cli/explain_last/sections/council.ts +56 -0
  689. package/src/scripts/_cli/explain_last/sections/halt.ts +60 -0
  690. package/src/scripts/_cli/explain_last/sections/header.ts +50 -0
  691. package/src/scripts/_cli/explain_last/sections/index.ts +21 -0
  692. package/src/scripts/_cli/explain_last/sections/inputs.ts +63 -0
  693. package/src/scripts/_cli/explain_last/sections/memory.ts +124 -0
  694. package/src/scripts/_cli/explain_last/sections/pack.ts +42 -0
  695. package/src/scripts/_cli/explain_last/sections/provider.ts +51 -0
  696. package/src/scripts/_cli/explain_last/sections/route.ts +48 -0
  697. package/src/scripts/_cli/explain_last/state_loader.ts +119 -0
  698. package/src/scripts/_dispatch.bash +179 -163
  699. package/src/scripts/_lib/agent_settings.ts +1123 -0
  700. package/src/scripts/_lib/agent_src.ts +654 -0
  701. package/src/scripts/_lib/agents_overlay.ts +183 -0
  702. package/src/scripts/_lib/bench_ab_cache.ts +399 -0
  703. package/src/scripts/_lib/bench_ab_scoring.ts +352 -0
  704. package/src/scripts/_lib/bench_ab_scoring_v2.ts +751 -0
  705. package/src/scripts/_lib/bench_cost.ts +396 -0
  706. package/src/scripts/_lib/bench_quality.ts +237 -0
  707. package/src/scripts/_lib/bench_report.ts +255 -0
  708. package/src/scripts/_lib/bench_telegraph.ts +516 -0
  709. package/src/scripts/_lib/bench_telegraph_report.ts +272 -0
  710. package/src/scripts/_lib/changelog_eras.ts +398 -0
  711. package/src/scripts/_lib/claude_desktop_bundler.ts +324 -0
  712. package/src/scripts/_lib/cli_wrapper.ts +89 -0
  713. package/src/scripts/_lib/fs_atomic.ts +172 -0
  714. package/src/scripts/_lib/global_deploy_inventory.ts +639 -0
  715. package/src/scripts/_lib/install_layout.ts +87 -0
  716. package/src/scripts/_lib/install_regenerator.ts +157 -0
  717. package/src/scripts/_lib/installed_lock.ts +451 -0
  718. package/src/scripts/_lib/installed_tools.ts +518 -0
  719. package/src/scripts/_lib/json_pointers.ts +388 -0
  720. package/src/scripts/_lib/knowledge_global.ts +770 -0
  721. package/src/scripts/_lib/knowledge_global_promote.ts +453 -0
  722. package/src/scripts/_lib/knowledge_global_redaction.ts +448 -0
  723. package/src/scripts/_lib/link_crypto.ts +325 -0
  724. package/src/scripts/_lib/linked_projects.ts +613 -0
  725. package/src/scripts/_lib/model_tier.ts +65 -0
  726. package/src/scripts/_lib/module_detection.ts +275 -0
  727. package/src/scripts/_lib/node_sqlite.d.ts +32 -0
  728. package/src/scripts/_lib/pin_resolver.ts +264 -0
  729. package/src/scripts/_lib/py_random.ts +212 -0
  730. package/src/scripts/_lib/script_output.ts +147 -0
  731. package/src/scripts/_lib/security_lint.ts +623 -0
  732. package/src/scripts/_lib/surface_tiers.ts +127 -0
  733. package/src/scripts/_lib/token_count.ts +126 -0
  734. package/src/scripts/_lib/update_check.ts +297 -0
  735. package/src/scripts/_lib/user_global_paths.ts +329 -0
  736. package/src/scripts/_lib/value_ladder.ts +882 -0
  737. package/src/scripts/_lib/value_report.ts +617 -0
  738. package/src/scripts/_lib/zip_min.ts +175 -0
  739. package/src/scripts/adoption_report.ts +357 -0
  740. package/src/scripts/adoption_snapshot.ts +392 -0
  741. package/src/scripts/adoption_status.ts +424 -0
  742. package/src/scripts/adr/regenerate_index.ts +257 -0
  743. package/src/scripts/ai-image/adapters/flux.sh +45 -0
  744. package/src/scripts/ai-image/adapters/gemini-image.sh +45 -0
  745. package/src/scripts/ai-image/adapters/ideogram.sh +45 -0
  746. package/src/scripts/ai-image/adapters/recraft.sh +47 -0
  747. package/src/scripts/ai-video/adapters/comfyui.sh +3 -3
  748. package/src/scripts/ai-video/adapters/fal.sh +3 -3
  749. package/src/scripts/ai-video/adapters/gemini-veo.sh +3 -3
  750. package/src/scripts/ai-video/adapters/higgsfield.sh +3 -3
  751. package/src/scripts/ai-video/adapters/kling.sh +3 -3
  752. package/src/scripts/ai-video/adapters/musetalk.sh +2 -2
  753. package/src/scripts/ai-video/adapters/openai-images.sh +3 -3
  754. package/src/scripts/ai-video/adapters/replicate.sh +3 -3
  755. package/src/scripts/ai-video/adapters/sora.sh +3 -3
  756. package/src/scripts/ai-video/adapters/syncso.sh +3 -3
  757. package/src/scripts/ai-video/audio-adapters/allin1.sh +2 -2
  758. package/src/scripts/ai-video/audio-adapters/whisperx.sh +2 -2
  759. package/src/scripts/ai-video/lib/audio-adapter-contract.md +1 -1
  760. package/src/scripts/ai-video/lib/embed-provenance.sh +2 -2
  761. package/src/scripts/ai-video/lib/ingest-song.sh +2 -2
  762. package/src/scripts/ai-video/lib/parse-blueprint.sh +1 -1
  763. package/src/scripts/ai-video/lib/resume-scan.sh +2 -2
  764. package/src/scripts/ai-video/smoke-trace.sh +16 -7
  765. package/src/scripts/ai-video/stitch.sh +2 -2
  766. package/src/scripts/ai_council/_default_prices.ts +73 -0
  767. package/src/scripts/ai_council/advisors.ts +244 -0
  768. package/src/scripts/ai_council/airgap.ts +249 -0
  769. package/src/scripts/ai_council/budget_guard.ts +492 -0
  770. package/src/scripts/ai_council/bundler.ts +376 -0
  771. package/src/scripts/ai_council/cli_hints.ts +120 -0
  772. package/src/scripts/ai_council/clients.ts +2214 -0
  773. package/src/scripts/ai_council/compile_corpus.ts +681 -0
  774. package/src/scripts/ai_council/confidence_gate.ts +230 -0
  775. package/src/scripts/ai_council/config.ts +1729 -0
  776. package/src/scripts/ai_council/consensus.ts +551 -0
  777. package/src/scripts/ai_council/events_log.ts +327 -0
  778. package/src/scripts/ai_council/learn_low_impact_preview.ts +317 -0
  779. package/src/scripts/ai_council/low_impact.ts +1069 -0
  780. package/src/scripts/ai_council/low_impact_corpus.ts +662 -0
  781. package/src/scripts/ai_council/low_impact_intake.ts +222 -0
  782. package/src/scripts/ai_council/modes.ts +169 -0
  783. package/src/scripts/ai_council/necessity.ts +933 -0
  784. package/src/scripts/ai_council/orchestrator.ts +1689 -0
  785. package/src/scripts/ai_council/pricing.ts +267 -0
  786. package/src/scripts/ai_council/probation_gate.ts +282 -0
  787. package/src/scripts/ai_council/project_context.ts +308 -0
  788. package/src/scripts/ai_council/prompts.ts +600 -0
  789. package/src/scripts/ai_council/redact_low_impact_entry.ts +291 -0
  790. package/src/scripts/ai_council/replay.ts +314 -0
  791. package/src/scripts/ai_council/session.ts +558 -0
  792. package/src/scripts/ai_council/shadow_dispatch.ts +509 -0
  793. package/src/scripts/ai_council/solo_dispatch.ts +281 -0
  794. package/src/scripts/analysis_freshness.ts +343 -0
  795. package/src/scripts/annotate_discovery.ts +288 -0
  796. package/src/scripts/apply_modules_config.ts +537 -0
  797. package/src/scripts/audit_adr_coverage.ts +357 -0
  798. package/src/scripts/audit_auto_rules.ts +415 -0
  799. package/src/scripts/audit_cloud_compatibility.ts +608 -0
  800. package/src/scripts/audit_command_surface.ts +1227 -0
  801. package/src/scripts/audit_initial_context.ts +694 -0
  802. package/src/scripts/audit_likelihood.ts +434 -0
  803. package/src/scripts/audit_mcp_tools.ts +252 -0
  804. package/src/scripts/audit_overlap.ts +421 -0
  805. package/src/scripts/audit_skill_descriptions.ts +402 -0
  806. package/src/scripts/audit_skill_overlap.ts +576 -0
  807. package/src/scripts/audit_user_type_axis.ts +264 -0
  808. package/src/scripts/backfill_model_tier.ts +349 -0
  809. package/src/scripts/bench_ab_cache_dispatch.ts +126 -0
  810. package/src/scripts/bench_ab_clone.ts +610 -0
  811. package/src/scripts/bench_ab_diff.ts +609 -0
  812. package/src/scripts/bench_ab_integrity.ts +261 -0
  813. package/src/scripts/bench_ab_run.ts +417 -0
  814. package/src/scripts/bench_ab_task_runner.ts +1382 -0
  815. package/src/scripts/bench_ab_tracka_run.ts +436 -0
  816. package/src/scripts/bench_ab_v2_run.ts +585 -0
  817. package/src/scripts/bench_ab_v2_stats.ts +1018 -0
  818. package/src/scripts/bench_baseline_ready.ts +326 -0
  819. package/src/scripts/bench_condense_memory.ts +479 -0
  820. package/src/scripts/bench_drift_check.ts +503 -0
  821. package/src/scripts/bench_per_tool.ts +591 -0
  822. package/src/scripts/bench_rtk_savings.ts +710 -0
  823. package/src/scripts/bench_run.ts +509 -0
  824. package/src/scripts/bench_runner.ts +519 -0
  825. package/src/scripts/build_cloud_bundle.ts +692 -0
  826. package/src/scripts/build_discovery_manifest.ts +1371 -0
  827. package/src/scripts/build_linear_digest.ts +368 -0
  828. package/src/scripts/build_mcp_registry_manifest.ts +351 -0
  829. package/src/scripts/build_rule_trigger_matrix.ts +469 -0
  830. package/src/scripts/capture_showcase_session.ts +735 -0
  831. package/src/scripts/chat_history.ts +2301 -0
  832. package/src/scripts/check_always_budget.ts +694 -0
  833. package/src/scripts/check_artefact_checksums.ts +281 -0
  834. package/src/scripts/check_augment_description_cap.ts +133 -0
  835. package/src/scripts/check_augmentignore.ts +108 -0
  836. package/src/scripts/check_beta_review_markers.ts +234 -0
  837. package/src/scripts/check_bite_sized_granularity.ts +116 -0
  838. package/src/scripts/check_cluster_patterns.ts +285 -0
  839. package/src/scripts/check_command_count_messaging.ts +224 -0
  840. package/src/scripts/check_condensation.ts +900 -0
  841. package/src/scripts/check_condensed_paths.ts +414 -0
  842. package/src/scripts/check_context_paths.ts +388 -0
  843. package/src/scripts/check_council_config_location.ts +260 -0
  844. package/src/scripts/check_council_layout.ts +180 -0
  845. package/src/scripts/check_council_references.ts +345 -0
  846. package/src/scripts/check_discovery_determinism.ts +124 -0
  847. package/src/scripts/check_gate_paths.ts +230 -0
  848. package/src/scripts/check_iron_law_prominence.ts +298 -0
  849. package/src/scripts/check_kernel_rule_bundle.ts +242 -0
  850. package/src/scripts/check_knowledge_cards.ts +759 -0
  851. package/src/scripts/check_md_language.ts +291 -0
  852. package/src/scripts/check_memory.ts +845 -0
  853. package/src/scripts/check_memory_proposal.ts +351 -0
  854. package/src/scripts/check_module_management_neutral.ts +238 -0
  855. package/src/scripts/check_no_conflict_markers.ts +298 -0
  856. package/src/scripts/check_no_conflict_markers_allowlist.json +4 -0
  857. package/src/scripts/check_no_external_sources.ts +351 -0
  858. package/src/scripts/check_no_local_settings_committed.ts +69 -0
  859. package/src/scripts/check_no_new_legacy_path.ts +188 -0
  860. package/src/scripts/check_no_roadmap_refs.ts +304 -0
  861. package/src/scripts/check_one_off_location.ts +165 -0
  862. package/src/scripts/check_overlay_cascade_subdirs.ts +188 -0
  863. package/src/scripts/check_portability.ts +860 -0
  864. package/src/scripts/check_proposal.ts +0 -0
  865. package/src/scripts/check_public_catalog_links.ts +204 -0
  866. package/src/scripts/check_public_links.ts +357 -0
  867. package/src/scripts/check_references.ts +963 -0
  868. package/src/scripts/check_release_includes_discovery.ts +94 -0
  869. package/src/scripts/check_release_pr_shape.ts +222 -0
  870. package/src/scripts/check_release_published.ts +235 -0
  871. package/src/scripts/check_release_trunk_sync.ts +203 -0
  872. package/src/scripts/check_reply_consistency.ts +359 -0
  873. package/src/scripts/check_roadmap_trackable.ts +268 -0
  874. package/src/scripts/check_role_doc_links.ts +187 -0
  875. package/src/scripts/check_safety_floor_untouched.ts +160 -0
  876. package/src/scripts/check_skill_requires.ts +205 -0
  877. package/src/scripts/check_structural_breaking.ts +170 -0
  878. package/src/scripts/check_surface_tiers.ts +567 -0
  879. package/src/scripts/check_template_pin_drift.ts +222 -0
  880. package/src/scripts/check_test_coverage_diff.ts +235 -0
  881. package/src/scripts/check_token_optimizer_freshness.ts +183 -0
  882. package/src/scripts/check_trigger_evals.ts +375 -0
  883. package/src/scripts/check_update_banner.ts +143 -0
  884. package/src/scripts/ci_status.ts +0 -0
  885. package/src/scripts/ci_summary.ts +235 -0
  886. package/src/scripts/ci_time_ratio.ts +526 -0
  887. package/src/scripts/command_suggester/cooldown.ts +176 -0
  888. package/src/scripts/command_suggester/index.ts +41 -0
  889. package/src/scripts/command_suggester/loader.ts +205 -0
  890. package/src/scripts/command_suggester/match.ts +294 -0
  891. package/src/scripts/command_suggester/rank.ts +201 -0
  892. package/src/scripts/command_suggester/render.ts +122 -0
  893. package/src/scripts/command_suggester/sanitize.ts +114 -0
  894. package/src/scripts/command_suggester/settings.ts +186 -0
  895. package/src/scripts/command_suggester/types.ts +0 -0
  896. package/src/scripts/compile_router.ts +297 -0
  897. package/src/scripts/condense.sh +7 -1
  898. package/src/scripts/condense.ts +2035 -0
  899. package/src/scripts/condense_memory.ts +334 -0
  900. package/src/scripts/config/index.ts +15 -0
  901. package/src/scripts/config/packs.ts +310 -0
  902. package/src/scripts/config/presets.ts +369 -0
  903. package/src/scripts/config/profile_explain.ts +114 -0
  904. package/src/scripts/config/profiles.ts +277 -0
  905. package/src/scripts/config/session_profiles.ts +1064 -0
  906. package/src/scripts/context_hygiene_hook.ts +272 -0
  907. package/src/scripts/cost_by_conversation.ts +444 -0
  908. package/src/scripts/cost_summary.ts +407 -0
  909. package/src/scripts/council_cli.ts +2827 -0
  910. package/src/scripts/council_prune.ts +153 -0
  911. package/src/scripts/cross_repo_retrieve.ts +694 -0
  912. package/src/scripts/discovery_stats.ts +218 -0
  913. package/src/scripts/evidence_report.ts +580 -0
  914. package/src/scripts/external_sources_denylist.json +92 -0
  915. package/src/scripts/extract_audit_patterns.ts +394 -0
  916. package/src/scripts/first_run_gate_hook.ts +246 -0
  917. package/src/scripts/gen_discovery_baseline.ts +297 -0
  918. package/src/scripts/generate_capabilities_index.ts +496 -0
  919. package/src/scripts/generate_capability_matrix.ts +430 -0
  920. package/src/scripts/generate_catalog.ts +178 -0
  921. package/src/scripts/generate_command_flows.ts +316 -0
  922. package/src/scripts/generate_cookbook.ts +302 -0
  923. package/src/scripts/generate_index.ts +500 -0
  924. package/src/scripts/generate_ownership_matrix.ts +646 -0
  925. package/src/scripts/generate_pack_manifests.ts +1025 -0
  926. package/src/scripts/generate_role_experiences_catalog.ts +265 -0
  927. package/src/scripts/hermetic-install.sh +22 -11
  928. package/src/scripts/hook_manifest.yaml +37 -15
  929. package/src/scripts/hooks/augment-chat-history.sh +3 -10
  930. package/src/scripts/hooks/augment-context-hygiene.sh +3 -10
  931. package/src/scripts/hooks/augment-dispatcher.sh +3 -10
  932. package/src/scripts/hooks/augment-onboarding-gate.sh +3 -10
  933. package/src/scripts/hooks/augment-roadmap-progress.sh +3 -10
  934. package/src/scripts/hooks/block_no_verify.ts +413 -0
  935. package/src/scripts/hooks/cline-dispatcher.sh +3 -10
  936. package/src/scripts/hooks/cowork-dispatcher.sh +3 -14
  937. package/src/scripts/hooks/cursor-dispatcher.sh +3 -10
  938. package/src/scripts/hooks/dispatch_hook.ts +851 -0
  939. package/src/scripts/hooks/dispatch_issues.ts +226 -0
  940. package/src/scripts/hooks/envelope.ts +140 -0
  941. package/src/scripts/hooks/gemini-dispatcher.sh +3 -8
  942. package/src/scripts/hooks/replay_hook.ts +364 -0
  943. package/src/scripts/hooks/state_io.ts +293 -0
  944. package/src/scripts/hooks/windsurf-dispatcher.sh +3 -9
  945. package/src/scripts/hooks_doctor.ts +418 -0
  946. package/src/scripts/hooks_status.ts +292 -0
  947. package/src/scripts/injection_scan_hook.ts +285 -0
  948. package/src/scripts/install +36 -22
  949. package/src/scripts/install-hooks.sh +29 -12
  950. package/src/scripts/install.sh +38 -14
  951. package/src/scripts/install.ts +4515 -0
  952. package/src/scripts/inventory_abstraction_budget.ts +1104 -0
  953. package/src/scripts/inventory_frontmatter.ts +320 -0
  954. package/src/scripts/inventory_meta_layers.ts +516 -0
  955. package/src/scripts/iron_law_sha.ts +233 -0
  956. package/src/scripts/knowledge_global_cli.ts +1105 -0
  957. package/src/scripts/linked_projects_list.ts +310 -0
  958. package/src/scripts/lint_agent_security.ts +224 -0
  959. package/src/scripts/lint_agent_skill_names.ts +241 -0
  960. package/src/scripts/lint_agents_layout.ts +205 -0
  961. package/src/scripts/lint_agents_md.ts +294 -0
  962. package/src/scripts/lint_archived_skills.ts +309 -0
  963. package/src/scripts/lint_artefact_frontmatter.ts +359 -0
  964. package/src/scripts/lint_bench_ab.ts +319 -0
  965. package/src/scripts/lint_bench_corpus.ts +421 -0
  966. package/src/scripts/lint_command_flow_coverage.ts +231 -0
  967. package/src/scripts/lint_command_routing.ts +377 -0
  968. package/src/scripts/lint_command_tiers.ts +345 -0
  969. package/src/scripts/lint_command_verbs.ts +379 -0
  970. package/src/scripts/lint_commit_subjects.ts +243 -0
  971. package/src/scripts/lint_context_spine_usage.ts +198 -0
  972. package/src/scripts/lint_discovery_manifest.ts +540 -0
  973. package/src/scripts/lint_discovery_vocabulary.ts +393 -0
  974. package/src/scripts/lint_empty_roadmaps.ts +147 -0
  975. package/src/scripts/lint_eval_freshness.ts +335 -0
  976. package/src/scripts/lint_examples.ts +183 -0
  977. package/src/scripts/lint_explain_trace.ts +381 -0
  978. package/src/scripts/lint_featured_skills.ts +0 -0
  979. package/src/scripts/lint_flows.ts +701 -0
  980. package/src/scripts/lint_framework_leakage.ts +497 -0
  981. package/src/scripts/lint_framework_leakage_allowlist.json +8 -1
  982. package/src/scripts/lint_frontmatter_boilerplate.ts +356 -0
  983. package/src/scripts/lint_ghostwriter_source.ts +389 -0
  984. package/src/scripts/lint_global_paths.ts +420 -0
  985. package/src/scripts/lint_handoffs.ts +362 -0
  986. package/src/scripts/lint_hidden_unicode.ts +350 -0
  987. package/src/scripts/lint_hook_concern_budget.ts +319 -0
  988. package/src/scripts/lint_hook_manifest.ts +354 -0
  989. package/src/scripts/lint_instruction_smuggling.ts +173 -0
  990. package/src/scripts/lint_load_context.ts +371 -0
  991. package/src/scripts/lint_marketplace.ts +286 -0
  992. package/src/scripts/lint_marketplace_install_completeness.ts +309 -0
  993. package/src/scripts/lint_mcp_config_security.ts +225 -0
  994. package/src/scripts/lint_mcp_registry_manifest.ts +350 -0
  995. package/src/scripts/lint_media_policy_linkage.ts +224 -0
  996. package/src/scripts/lint_missions.ts +774 -0
  997. package/src/scripts/lint_model_tier_coverage.ts +151 -0
  998. package/src/scripts/lint_namespace.ts +295 -0
  999. package/src/scripts/lint_namespace_collisions.ts +203 -0
  1000. package/src/scripts/lint_new_skill_gate.ts +462 -0
  1001. package/src/scripts/lint_no_new_atomic_commands.ts +342 -0
  1002. package/src/scripts/lint_one_off_age.ts +348 -0
  1003. package/src/scripts/lint_orchestration_dsl.ts +377 -0
  1004. package/src/scripts/lint_orchestrator_auto_detect.ts +177 -0
  1005. package/src/scripts/lint_pack_boundaries.ts +366 -0
  1006. package/src/scripts/lint_pack_dependencies.ts +541 -0
  1007. package/src/scripts/lint_pack_first_win.ts +202 -0
  1008. package/src/scripts/lint_persona_governance.ts +292 -0
  1009. package/src/scripts/lint_positioning.ts +257 -0
  1010. package/src/scripts/lint_profile_overlay_set_only.ts +324 -0
  1011. package/src/scripts/lint_readme_jargon.ts +189 -0
  1012. package/src/scripts/lint_readme_size.ts +73 -0
  1013. package/src/scripts/lint_regression.ts +497 -0
  1014. package/src/scripts/lint_roadmap_ci_steps.ts +252 -0
  1015. package/src/scripts/lint_roadmap_complexity.ts +295 -0
  1016. package/src/scripts/lint_roadmap_later_disposition.ts +357 -0
  1017. package/src/scripts/lint_role_experiences.ts +410 -0
  1018. package/src/scripts/lint_rule_interactions.ts +281 -0
  1019. package/src/scripts/lint_rule_tiers.ts +169 -0
  1020. package/src/scripts/lint_showcase_sessions.ts +254 -0
  1021. package/src/scripts/lint_skill_frontmatter_safety.ts +279 -0
  1022. package/src/scripts/lint_skill_originality.ts +586 -0
  1023. package/src/scripts/lint_skill_originality_allowlist.json +20 -0
  1024. package/src/scripts/lint_skill_tools.ts +320 -0
  1025. package/src/scripts/lint_ticket_buildable.ts +1027 -0
  1026. package/src/scripts/lint_topics_yaml.ts +203 -0
  1027. package/src/scripts/lint_trust_coherence.ts +377 -0
  1028. package/src/scripts/lint_value_dashboard.ts +314 -0
  1029. package/src/scripts/lint_workflow_security.ts +637 -0
  1030. package/src/scripts/lint_workflow_security_allowlist.json +20 -0
  1031. package/src/scripts/lint_workspace_boundary.ts +248 -0
  1032. package/src/scripts/mcp_parity_smoke.ts +638 -0
  1033. package/src/scripts/mcp_render.ts +346 -0
  1034. package/src/scripts/mcp_server/__main__.ts +28 -0
  1035. package/src/scripts/mcp_server/catalog.ts +154 -0
  1036. package/src/scripts/mcp_server/consumer_tool_catalog.json +2 -3
  1037. package/src/scripts/mcp_server/index.ts +24 -0
  1038. package/src/scripts/mcp_server/metadata.ts +83 -0
  1039. package/src/scripts/mcp_server/prompts.ts +711 -0
  1040. package/src/scripts/mcp_server/resources.ts +343 -0
  1041. package/src/scripts/mcp_server/server.ts +439 -0
  1042. package/src/scripts/mcp_server/telemetry.ts +154 -0
  1043. package/src/scripts/mcp_server/tools.ts +1031 -0
  1044. package/src/scripts/mcp_setup.sh +25 -52
  1045. package/src/scripts/mcp_telemetry_health.ts +362 -0
  1046. package/src/scripts/mcp_telemetry_query.ts +371 -0
  1047. package/src/scripts/mcp_telemetry_store.ts +422 -0
  1048. package/src/scripts/measure_augment_budget.ts +453 -0
  1049. package/src/scripts/measure_density.ts +618 -0
  1050. package/src/scripts/measure_frugality_savings.ts +353 -0
  1051. package/src/scripts/measure_markitdown_lift.ts +299 -0
  1052. package/src/scripts/measure_patterns.ts +682 -0
  1053. package/src/scripts/measure_projection_bytes.ts +425 -0
  1054. package/src/scripts/measure_rule_budget.ts +627 -0
  1055. package/src/scripts/measure_skill_reduction.ts +442 -0
  1056. package/src/scripts/media/lib/adapter-common.sh +247 -0
  1057. package/src/scripts/media/lib/adapter-contract.md +329 -0
  1058. package/src/scripts/media/lib/fixtures/comfyui/result.json +1 -0
  1059. package/src/scripts/media/lib/fixtures/fal/result.json +1 -0
  1060. package/src/scripts/media/lib/fixtures/flux/asset-0001.png +0 -0
  1061. package/src/scripts/media/lib/fixtures/flux/result.json +1 -0
  1062. package/src/scripts/media/lib/fixtures/gemini-image/asset-0001.png +0 -0
  1063. package/src/scripts/media/lib/fixtures/gemini-image/result.json +1 -0
  1064. package/src/scripts/media/lib/fixtures/gemini-veo/result.json +1 -0
  1065. package/src/scripts/media/lib/fixtures/higgsfield/result.json +1 -0
  1066. package/src/scripts/media/lib/fixtures/ideogram/asset-0001.png +0 -0
  1067. package/src/scripts/media/lib/fixtures/ideogram/result.json +1 -0
  1068. package/src/scripts/media/lib/fixtures/kling/result.json +1 -0
  1069. package/src/scripts/media/lib/fixtures/musetalk/result.json +1 -0
  1070. package/src/scripts/media/lib/fixtures/openai-images/result.json +1 -0
  1071. package/src/scripts/media/lib/fixtures/recraft/asset-0001.svg +1 -0
  1072. package/src/scripts/media/lib/fixtures/recraft/result.json +1 -0
  1073. package/src/scripts/media/lib/fixtures/replicate/result.json +1 -0
  1074. package/src/scripts/media/lib/fixtures/sora/result.json +1 -0
  1075. package/src/scripts/media/lib/fixtures/syncso/result.json +1 -0
  1076. package/src/scripts/media/lib/load-config.sh +180 -0
  1077. package/src/scripts/media/lib/redact.sh +85 -0
  1078. package/src/scripts/memory_hash.ts +331 -0
  1079. package/src/scripts/memory_lookup.ts +1278 -0
  1080. package/src/scripts/memory_report.ts +845 -0
  1081. package/src/scripts/memory_signal.ts +417 -0
  1082. package/src/scripts/memory_status.ts +189 -0
  1083. package/src/scripts/migrate_command_suggestions.ts +341 -0
  1084. package/src/scripts/migrate_frontmatter_defaults.ts +539 -0
  1085. package/src/scripts/migration_status.ts +301 -0
  1086. package/src/scripts/mine_session.ts +645 -0
  1087. package/src/scripts/minimal_safe_diff_hook.ts +355 -0
  1088. package/src/scripts/move_artefact.ts +869 -0
  1089. package/src/scripts/new_skill.ts +404 -0
  1090. package/src/scripts/onboarding_gate_hook.ts +224 -0
  1091. package/src/scripts/pack_dependency_allowlist.json +2 -2
  1092. package/src/scripts/pack_mcp_content.ts +552 -0
  1093. package/src/scripts/parity/README.md +140 -0
  1094. package/src/scripts/parity/compare.ts +189 -0
  1095. package/src/scripts/parity/coverage_diff.ts +199 -0
  1096. package/src/scripts/parity/phase-manifest.json +93 -0
  1097. package/src/scripts/parity/phase_gate.ts +270 -0
  1098. package/src/scripts/parity/replay.ts +320 -0
  1099. package/src/scripts/pattern_share.ts +363 -0
  1100. package/src/scripts/plan_physical_move.ts +605 -0
  1101. package/src/scripts/prediction-pool/poisson_sim.ts +537 -0
  1102. package/src/scripts/prediction-pool/pool_winsim.ts +677 -0
  1103. package/src/scripts/prediction-pool/score_ev.ts +546 -0
  1104. package/src/scripts/print_required_checks.ts +249 -0
  1105. package/src/scripts/probe_projection_fidelity.ts +468 -0
  1106. package/src/scripts/probe_skill_registration.ts +787 -0
  1107. package/src/scripts/profile_staleness_hook.ts +169 -0
  1108. package/src/scripts/profile_use.ts +227 -0
  1109. package/src/scripts/project_thin_rules.ts +387 -0
  1110. package/src/scripts/propose_modules_config.ts +311 -0
  1111. package/src/scripts/prototype_lint_contradictions.ts +414 -0
  1112. package/src/scripts/prove_pack_extractable.ts +388 -0
  1113. package/src/scripts/readme_linter.ts +913 -0
  1114. package/src/scripts/redact_hook_capture.ts +325 -0
  1115. package/src/scripts/refine_ticket_detect.ts +703 -0
  1116. package/src/scripts/release.ts +1697 -0
  1117. package/src/scripts/render_benchmark_md.ts +664 -0
  1118. package/src/scripts/render_value_md.ts +506 -0
  1119. package/src/scripts/repro/repro_marketplace_install_gap.sh +1 -1
  1120. package/src/scripts/roadmap_progress_hook.ts +410 -0
  1121. package/src/scripts/router_telemetry.ts +972 -0
  1122. package/src/scripts/run.ts +98 -0
  1123. package/src/scripts/run_skill_evals.ts +477 -0
  1124. package/src/scripts/runtime_dispatcher.ts +586 -0
  1125. package/src/scripts/runtime_handler.ts +231 -0
  1126. package/src/scripts/runtime_registry.ts +394 -0
  1127. package/src/scripts/schemas/command.schema.json +7 -1
  1128. package/src/scripts/schemas/mission-catalog.schema.json +112 -0
  1129. package/src/scripts/schemas/mission.schema.json +87 -0
  1130. package/src/scripts/schemas/pack.schema.json +6 -0
  1131. package/src/scripts/schemas/rule.schema.json +1 -0
  1132. package/src/scripts/schemas/skill.schema.json +1 -0
  1133. package/src/scripts/schemas/ticket-manifest.schema.json +35 -0
  1134. package/src/scripts/schemas/ticket.schema.json +60 -0
  1135. package/src/scripts/score_skill_selection.ts +570 -0
  1136. package/src/scripts/security_audit_config.ts +423 -0
  1137. package/src/scripts/skill_collision_clusters.ts +448 -0
  1138. package/src/scripts/skill_discovery.ts +690 -0
  1139. package/src/scripts/skill_linter.ts +4276 -0
  1140. package/src/scripts/skill_overlap.ts +414 -0
  1141. package/src/scripts/skill_preview.ts +548 -0
  1142. package/src/scripts/skill_tools/audit_persona_coverage.ts +427 -0
  1143. package/src/scripts/skill_tools/audit_user_type_coverage.ts +507 -0
  1144. package/src/scripts/skill_tools/index.ts +28 -0
  1145. package/src/scripts/skill_tools/run_block_d_eval.ts +373 -0
  1146. package/src/scripts/skill_tools/score_skill_relevance.ts +475 -0
  1147. package/src/scripts/skill_tools/suggest_skill_for_task.ts +288 -0
  1148. package/src/scripts/skill_trigger_eval.ts +1046 -0
  1149. package/src/scripts/skill_usage_collect.ts +465 -0
  1150. package/src/scripts/skill_usage_report.ts +364 -0
  1151. package/src/scripts/smoke/kernel.sh +4 -5
  1152. package/src/scripts/smoke/router.sh +76 -76
  1153. package/src/scripts/smoke/schema.sh +2 -2
  1154. package/src/scripts/smoke/skills.sh +73 -52
  1155. package/src/scripts/smoke_path_resolution.ts +194 -0
  1156. package/src/scripts/smoke_quickstart.ts +224 -0
  1157. package/src/scripts/snapshot_agent_outputs.ts +375 -0
  1158. package/src/scripts/spotcheck_thin_root.ts +247 -0
  1159. package/src/scripts/surface-tiers.yml +68 -0
  1160. package/src/scripts/sync_agent_settings.ts +763 -0
  1161. package/src/scripts/sync_github_metadata.ts +550 -0
  1162. package/src/scripts/sync_gitignore.ts +630 -0
  1163. package/src/scripts/sync_yaml_rt.ts +910 -0
  1164. package/src/scripts/telegraph_stats.ts +447 -0
  1165. package/src/scripts/tool_registry.ts +330 -0
  1166. package/src/scripts/tools/adapter_errors.ts +93 -0
  1167. package/src/scripts/tools/base_adapter.ts +147 -0
  1168. package/src/scripts/tools/github_adapter.ts +229 -0
  1169. package/src/scripts/tools/jira_adapter.ts +196 -0
  1170. package/src/scripts/trigger_coverage.ts +251 -0
  1171. package/src/scripts/update_counts.ts +284 -0
  1172. package/src/scripts/update_prices.ts +219 -0
  1173. package/src/scripts/validate_agent_settings.ts +265 -0
  1174. package/src/scripts/validate_decision_engine.ts +366 -0
  1175. package/src/scripts/validate_discovery_manifest.ts +160 -0
  1176. package/src/scripts/validate_frontmatter.ts +1030 -0
  1177. package/src/scripts/validate_pack_yaml.ts +0 -0
  1178. package/src/scripts/validate_safe_paths.ts +164 -0
  1179. package/src/scripts/validate_telegraph_carveouts.ts +485 -0
  1180. package/src/scripts/verify_before_complete_hook.ts +306 -0
  1181. package/src/scripts/verify_physical_move.ts +411 -0
  1182. package/src/scripts/wrapper_freshness_hook.ts +179 -0
  1183. package/dist/agent-src/commands/chat-history/learn.md +0 -184
  1184. package/dist/agent-src/commands/chat-history/show.md +0 -113
  1185. package/dist/agent-src/commands/fix/pr-bot-comments.md +0 -157
  1186. package/dist/agent-src/commands/fix/pr-developer-comments.md +0 -163
  1187. package/dist/agent-src/scripts/update_roadmap_progress.py +0 -537
  1188. package/dist/agent-src/skills/corpus-grounding/scripts/bm25_search.py +0 -212
  1189. package/dist/agent-src/skills/corpus-grounding/scripts/decision_engine.py +0 -438
  1190. package/dist/agent-src/skills/corpus-grounding/scripts/ground.py +0 -166
  1191. package/dist/agent-src/skills/corpus-grounding/scripts/schema_validator.py +0 -160
  1192. package/dist/agent-src/skills/design-tokens/scripts/tokens.py +0 -296
  1193. package/dist/agent-src/skills/react-shadcn-ui/scripts/shadcn_add.py +0 -299
  1194. package/dist/agent-src/skills/tailwind-engineer/scripts/tailwind_config_gen.py +0 -463
  1195. package/dist/agent-src/templates/agents/memory/architecture-decisions.example.yml +0 -95
  1196. package/dist/agent-src/templates/scripts/check_memory.py +0 -283
  1197. package/dist/agent-src/templates/scripts/check_memory_proposal.py +0 -180
  1198. package/dist/agent-src/templates/scripts/implement_ticket/__init__.py +0 -94
  1199. package/dist/agent-src/templates/scripts/implement_ticket/__main__.py +0 -15
  1200. package/dist/agent-src/templates/scripts/memory_hash.py +0 -75
  1201. package/dist/agent-src/templates/scripts/memory_lookup.py +0 -577
  1202. package/dist/agent-src/templates/scripts/memory_report.py +0 -184
  1203. package/dist/agent-src/templates/scripts/memory_signal.py +0 -167
  1204. package/dist/agent-src/templates/scripts/memory_status.py +0 -257
  1205. package/dist/agent-src/templates/scripts/pr_review_routing.py +0 -340
  1206. package/dist/agent-src/templates/scripts/pr_risk_review.py +0 -211
  1207. package/dist/agent-src/templates/scripts/telemetry/__init__.py +0 -42
  1208. package/dist/agent-src/templates/scripts/telemetry/aggregator.py +0 -169
  1209. package/dist/agent-src/templates/scripts/telemetry/boundary.py +0 -171
  1210. package/dist/agent-src/templates/scripts/telemetry/engagement.py +0 -297
  1211. package/dist/agent-src/templates/scripts/telemetry/report_renderer.py +0 -197
  1212. package/dist/agent-src/templates/scripts/telemetry/settings.py +0 -177
  1213. package/dist/agent-src/templates/scripts/telemetry_record.py +0 -179
  1214. package/dist/agent-src/templates/scripts/telemetry_report.py +0 -161
  1215. package/dist/agent-src/templates/scripts/telemetry_status.py +0 -142
  1216. package/dist/agent-src/templates/scripts/tier_usage_report.py +0 -183
  1217. package/dist/agent-src/templates/scripts/work_engine/__init__.py +0 -58
  1218. package/dist/agent-src/templates/scripts/work_engine/__main__.py +0 -9
  1219. package/dist/agent-src/templates/scripts/work_engine/_lib/__init__.py +0 -7
  1220. package/dist/agent-src/templates/scripts/work_engine/_lib/agent_settings.py +0 -840
  1221. package/dist/agent-src/templates/scripts/work_engine/_lib/user_global_paths.py +0 -249
  1222. package/dist/agent-src/templates/scripts/work_engine/cli.py +0 -195
  1223. package/dist/agent-src/templates/scripts/work_engine/cli_args.py +0 -116
  1224. package/dist/agent-src/templates/scripts/work_engine/delivery_state.py +0 -137
  1225. package/dist/agent-src/templates/scripts/work_engine/directives/__init__.py +0 -33
  1226. package/dist/agent-src/templates/scripts/work_engine/directives/backend/__init__.py +0 -98
  1227. package/dist/agent-src/templates/scripts/work_engine/directives/backend/analyze.py +0 -98
  1228. package/dist/agent-src/templates/scripts/work_engine/directives/backend/implement.py +0 -145
  1229. package/dist/agent-src/templates/scripts/work_engine/directives/backend/memory.py +0 -136
  1230. package/dist/agent-src/templates/scripts/work_engine/directives/backend/plan.py +0 -175
  1231. package/dist/agent-src/templates/scripts/work_engine/directives/backend/refine.py +0 -396
  1232. package/dist/agent-src/templates/scripts/work_engine/directives/backend/report.py +0 -227
  1233. package/dist/agent-src/templates/scripts/work_engine/directives/backend/test.py +0 -180
  1234. package/dist/agent-src/templates/scripts/work_engine/directives/backend/verify.py +0 -170
  1235. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/__init__.py +0 -116
  1236. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/contract.py +0 -254
  1237. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/stitch.py +0 -229
  1238. package/dist/agent-src/templates/scripts/work_engine/directives/mixed/ui.py +0 -231
  1239. package/dist/agent-src/templates/scripts/work_engine/directives/ui/__init__.py +0 -113
  1240. package/dist/agent-src/templates/scripts/work_engine/directives/ui/_passthrough.py +0 -44
  1241. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.py +0 -241
  1242. package/dist/agent-src/templates/scripts/work_engine/directives/ui/audit.py +0 -414
  1243. package/dist/agent-src/templates/scripts/work_engine/directives/ui/design.py +0 -335
  1244. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.py +0 -513
  1245. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.py +0 -471
  1246. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/__init__.py +0 -119
  1247. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/_skipped.py +0 -37
  1248. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/apply.py +0 -165
  1249. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/refine.py +0 -66
  1250. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/report.py +0 -62
  1251. package/dist/agent-src/templates/scripts/work_engine/directives/ui_trivial/test.py +0 -115
  1252. package/dist/agent-src/templates/scripts/work_engine/dispatcher.py +0 -331
  1253. package/dist/agent-src/templates/scripts/work_engine/emitters.py +0 -68
  1254. package/dist/agent-src/templates/scripts/work_engine/errors.py +0 -19
  1255. package/dist/agent-src/templates/scripts/work_engine/hook_bootstrap.py +0 -91
  1256. package/dist/agent-src/templates/scripts/work_engine/hooks/__init__.py +0 -54
  1257. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/__init__.py +0 -35
  1258. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/_chat_history_base.py +0 -59
  1259. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_append.py +0 -43
  1260. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/chat_history_halt_append.py +0 -41
  1261. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_gate.py +0 -162
  1262. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/decision_trace.py +0 -163
  1263. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/directive_set_guard.py +0 -53
  1264. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/halt_surface_audit.py +0 -50
  1265. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/memory_visibility.py +0 -141
  1266. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/state_shape_validation.py +0 -52
  1267. package/dist/agent-src/templates/scripts/work_engine/hooks/builtin/trace.py +0 -84
  1268. package/dist/agent-src/templates/scripts/work_engine/hooks/context.py +0 -66
  1269. package/dist/agent-src/templates/scripts/work_engine/hooks/events.py +0 -44
  1270. package/dist/agent-src/templates/scripts/work_engine/hooks/exceptions.py +0 -79
  1271. package/dist/agent-src/templates/scripts/work_engine/hooks/registry.py +0 -60
  1272. package/dist/agent-src/templates/scripts/work_engine/hooks/runner.py +0 -73
  1273. package/dist/agent-src/templates/scripts/work_engine/hooks/settings.py +0 -196
  1274. package/dist/agent-src/templates/scripts/work_engine/input_builders.py +0 -163
  1275. package/dist/agent-src/templates/scripts/work_engine/intent/__init__.py +0 -47
  1276. package/dist/agent-src/templates/scripts/work_engine/intent/classify.py +0 -280
  1277. package/dist/agent-src/templates/scripts/work_engine/migration/__init__.py +0 -8
  1278. package/dist/agent-src/templates/scripts/work_engine/migration/v0_to_v1.py +0 -231
  1279. package/dist/agent-src/templates/scripts/work_engine/orchestration.py +0 -193
  1280. package/dist/agent-src/templates/scripts/work_engine/persona_policy.py +0 -85
  1281. package/dist/agent-src/templates/scripts/work_engine/resolvers/__init__.py +0 -22
  1282. package/dist/agent-src/templates/scripts/work_engine/resolvers/diff.py +0 -106
  1283. package/dist/agent-src/templates/scripts/work_engine/resolvers/file.py +0 -113
  1284. package/dist/agent-src/templates/scripts/work_engine/resolvers/prompt.py +0 -90
  1285. package/dist/agent-src/templates/scripts/work_engine/scoring/__init__.py +0 -14
  1286. package/dist/agent-src/templates/scripts/work_engine/scoring/confidence.py +0 -300
  1287. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_engine.py +0 -351
  1288. package/dist/agent-src/templates/scripts/work_engine/scoring/decision_trace.py +0 -141
  1289. package/dist/agent-src/templates/scripts/work_engine/scoring/memory_visibility.py +0 -284
  1290. package/dist/agent-src/templates/scripts/work_engine/stack/__init__.py +0 -31
  1291. package/dist/agent-src/templates/scripts/work_engine/stack/detect.py +0 -187
  1292. package/dist/agent-src/templates/scripts/work_engine/stack/runner.py +0 -481
  1293. package/dist/agent-src/templates/scripts/work_engine/state.py +0 -694
  1294. package/dist/agent-src/templates/scripts/work_engine/state_io.py +0 -202
  1295. package/dist/cli/python/resolvePython.js +0 -38
  1296. package/dist/cli/python/resolvePython.js.map +0 -1
  1297. package/docs/case-studies/frontend-design-vs-ui-ux-pro-max.md +0 -86
  1298. package/docs/contracts/agent-memory-contract.md +0 -159
  1299. package/docs/parity/bench-ruflo.json +0 -58
  1300. package/docs/parity/ruflo.md +0 -46
  1301. package/src/scripts/__pycache__/validate_frontmatter.cpython-312.pyc +0 -0
  1302. package/src/scripts/_archive/_backfill_skill_domains.py +0 -140
  1303. package/src/scripts/_archive/_bootstrap_tier_frontmatter.py +0 -151
  1304. package/src/scripts/_archive/_p43_bodies.py +0 -235
  1305. package/src/scripts/_archive/_p43_condense.py +0 -118
  1306. package/src/scripts/_archive/_p4_migrate.py +0 -199
  1307. package/src/scripts/_archive/_phase2_shim_helper.py +0 -109
  1308. package/src/scripts/_archive/_pilot_council_question.py +0 -57
  1309. package/src/scripts/_cli/__init__.py +0 -0
  1310. package/src/scripts/_cli/cmd_doctor.py +0 -1583
  1311. package/src/scripts/_cli/cmd_explain.py +0 -355
  1312. package/src/scripts/_cli/cmd_export.py +0 -157
  1313. package/src/scripts/_cli/cmd_migrate.py +0 -524
  1314. package/src/scripts/_cli/cmd_prune.py +0 -322
  1315. package/src/scripts/_cli/cmd_refresh.py +0 -179
  1316. package/src/scripts/_cli/cmd_settings_check.py +0 -171
  1317. package/src/scripts/_cli/cmd_settings_migrate.py +0 -147
  1318. package/src/scripts/_cli/cmd_sync.py +0 -166
  1319. package/src/scripts/_cli/cmd_uninstall.py +0 -476
  1320. package/src/scripts/_cli/cmd_update.py +0 -279
  1321. package/src/scripts/_cli/cmd_upgrade.py +0 -172
  1322. package/src/scripts/_cli/cmd_validate.py +0 -177
  1323. package/src/scripts/_cli/cmd_versions.py +0 -160
  1324. package/src/scripts/_cli/explain_last/__init__.py +0 -122
  1325. package/src/scripts/_cli/explain_last/assumptions.py +0 -59
  1326. package/src/scripts/_cli/explain_last/council.py +0 -105
  1327. package/src/scripts/_cli/explain_last/halt.py +0 -44
  1328. package/src/scripts/_cli/explain_last/inputs.py +0 -128
  1329. package/src/scripts/_cli/explain_last/memory.py +0 -94
  1330. package/src/scripts/_cli/explain_last/provider.py +0 -52
  1331. package/src/scripts/_cli/explain_last/render.py +0 -52
  1332. package/src/scripts/_cli/explain_last/route.py +0 -59
  1333. package/src/scripts/_cli/explain_last/scrubber.py +0 -105
  1334. package/src/scripts/_cli/explain_last/sections/__init__.py +0 -35
  1335. package/src/scripts/_cli/explain_last/sections/assumptions.py +0 -21
  1336. package/src/scripts/_cli/explain_last/sections/council.py +0 -27
  1337. package/src/scripts/_cli/explain_last/sections/halt.py +0 -31
  1338. package/src/scripts/_cli/explain_last/sections/header.py +0 -24
  1339. package/src/scripts/_cli/explain_last/sections/inputs.py +0 -27
  1340. package/src/scripts/_cli/explain_last/sections/memory.py +0 -21
  1341. package/src/scripts/_cli/explain_last/sections/pack.py +0 -16
  1342. package/src/scripts/_cli/explain_last/sections/provider.py +0 -26
  1343. package/src/scripts/_cli/explain_last/sections/route.py +0 -22
  1344. package/src/scripts/_cli/explain_last/state_loader.py +0 -76
  1345. package/src/scripts/_emit_domain_table.py +0 -35
  1346. package/src/scripts/_lib/__init__.py +0 -5
  1347. package/src/scripts/_lib/__pycache__/__init__.cpython-312.pyc +0 -0
  1348. package/src/scripts/_lib/__pycache__/agent_src.cpython-312.pyc +0 -0
  1349. package/src/scripts/_lib/agent_settings.py +0 -840
  1350. package/src/scripts/_lib/agent_src.py +0 -491
  1351. package/src/scripts/_lib/agents_overlay.py +0 -120
  1352. package/src/scripts/_lib/bench_ab_cache.py +0 -162
  1353. package/src/scripts/_lib/bench_ab_scoring.py +0 -209
  1354. package/src/scripts/_lib/bench_cost.py +0 -138
  1355. package/src/scripts/_lib/bench_quality.py +0 -118
  1356. package/src/scripts/_lib/bench_report.py +0 -149
  1357. package/src/scripts/_lib/bench_telegraph.py +0 -273
  1358. package/src/scripts/_lib/bench_telegraph_report.py +0 -151
  1359. package/src/scripts/_lib/changelog_eras.py +0 -330
  1360. package/src/scripts/_lib/claude_desktop_bundler.py +0 -238
  1361. package/src/scripts/_lib/cli_wrapper.py +0 -64
  1362. package/src/scripts/_lib/fs_atomic.py +0 -116
  1363. package/src/scripts/_lib/global_deploy_inventory.py +0 -282
  1364. package/src/scripts/_lib/install_regenerator.py +0 -134
  1365. package/src/scripts/_lib/installed_lock.py +0 -256
  1366. package/src/scripts/_lib/installed_tools.py +0 -381
  1367. package/src/scripts/_lib/json_pointers.py +0 -260
  1368. package/src/scripts/_lib/linked_projects.py +0 -238
  1369. package/src/scripts/_lib/model_tier.py +0 -52
  1370. package/src/scripts/_lib/module_detection.py +0 -223
  1371. package/src/scripts/_lib/pin_resolver.py +0 -152
  1372. package/src/scripts/_lib/script_output.py +0 -144
  1373. package/src/scripts/_lib/token_count.py +0 -95
  1374. package/src/scripts/_lib/update_check.py +0 -207
  1375. package/src/scripts/_lib/user_global_paths.py +0 -249
  1376. package/src/scripts/_lib/value_ladder.py +0 -696
  1377. package/src/scripts/_lib/value_report.py +0 -455
  1378. package/src/scripts/_phase4_bucket.py +0 -210
  1379. package/src/scripts/_pilot_measure.py +0 -53
  1380. package/src/scripts/_tmp_scan_framework_leakage.py +0 -119
  1381. package/src/scripts/adoption_report.py +0 -195
  1382. package/src/scripts/adoption_snapshot.py +0 -219
  1383. package/src/scripts/adoption_status.py +0 -166
  1384. package/src/scripts/adr/regenerate_index.py +0 -79
  1385. package/src/scripts/ai-video/lib/adapter-common.sh +0 -231
  1386. package/src/scripts/ai-video/lib/adapter-contract.md +0 -329
  1387. package/src/scripts/ai-video/lib/fixtures/comfyui/result.json +0 -1
  1388. package/src/scripts/ai-video/lib/fixtures/fal/result.json +0 -1
  1389. package/src/scripts/ai-video/lib/fixtures/gemini-veo/result.json +0 -1
  1390. package/src/scripts/ai-video/lib/fixtures/higgsfield/result.json +0 -1
  1391. package/src/scripts/ai-video/lib/fixtures/kling/result.json +0 -1
  1392. package/src/scripts/ai-video/lib/fixtures/musetalk/result.json +0 -1
  1393. package/src/scripts/ai-video/lib/fixtures/openai-images/result.json +0 -1
  1394. package/src/scripts/ai-video/lib/fixtures/replicate/result.json +0 -1
  1395. package/src/scripts/ai-video/lib/fixtures/sora/result.json +0 -1
  1396. package/src/scripts/ai-video/lib/fixtures/syncso/result.json +0 -1
  1397. package/src/scripts/ai-video/lib/load-config.sh +0 -180
  1398. package/src/scripts/ai-video/lib/redact.sh +0 -85
  1399. package/src/scripts/ai_council/__init__.py +0 -40
  1400. package/src/scripts/ai_council/_default_prices.py +0 -50
  1401. package/src/scripts/ai_council/advisors.py +0 -148
  1402. package/src/scripts/ai_council/airgap.py +0 -165
  1403. package/src/scripts/ai_council/budget_guard.py +0 -202
  1404. package/src/scripts/ai_council/bundler.py +0 -263
  1405. package/src/scripts/ai_council/cli_hints.py +0 -123
  1406. package/src/scripts/ai_council/clients.py +0 -1385
  1407. package/src/scripts/ai_council/compile_corpus.py +0 -179
  1408. package/src/scripts/ai_council/confidence_gate.py +0 -156
  1409. package/src/scripts/ai_council/config.py +0 -1364
  1410. package/src/scripts/ai_council/consensus.py +0 -329
  1411. package/src/scripts/ai_council/events_log.py +0 -141
  1412. package/src/scripts/ai_council/learn_low_impact_preview.py +0 -252
  1413. package/src/scripts/ai_council/low_impact.py +0 -714
  1414. package/src/scripts/ai_council/low_impact_corpus.py +0 -466
  1415. package/src/scripts/ai_council/low_impact_intake.py +0 -163
  1416. package/src/scripts/ai_council/modes.py +0 -131
  1417. package/src/scripts/ai_council/necessity.py +0 -782
  1418. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_2a4_acceptance.py +0 -208
  1419. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_add_quiet.py +0 -149
  1420. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_budget_v2_audit.py +0 -206
  1421. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_context_layer_v1_estimate.py +0 -67
  1422. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_context_layer_v1_review.py +0 -292
  1423. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_followups_review.py +0 -259
  1424. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_inject_quiet_flag.py +0 -33
  1425. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_measure_v2.sh +0 -36
  1426. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_measure_verbosity.sh +0 -26
  1427. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_nondestructive_inline_audit.py +0 -209
  1428. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_per_task.sh +0 -41
  1429. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_phase4_dispatch_latency.py +0 -108
  1430. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_phase6_trigger_jaccard.py +0 -92
  1431. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_phase_2a_budget_rebalance.py +0 -257
  1432. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_phase_2a_post_revert.py +0 -197
  1433. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_rebalancing_audit.py +0 -149
  1434. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_roundtrip.py +0 -111
  1435. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_rule_hardening_v1.py +0 -251
  1436. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_silent_taskfiles.py +0 -98
  1437. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_structural_open_questions.py +0 -232
  1438. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_structural_optimization.py +0 -144
  1439. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_structural_v3_gaps.py +0 -252
  1440. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_structural_v3_review.py +0 -240
  1441. package/src/scripts/ai_council/one_off_archive/2026-05/_one_off_tier_retrofit.py +0 -180
  1442. package/src/scripts/ai_council/orchestrator.py +0 -1206
  1443. package/src/scripts/ai_council/pricing.py +0 -215
  1444. package/src/scripts/ai_council/probation_gate.py +0 -152
  1445. package/src/scripts/ai_council/project_context.py +0 -159
  1446. package/src/scripts/ai_council/prompts.py +0 -567
  1447. package/src/scripts/ai_council/redact_low_impact_entry.py +0 -155
  1448. package/src/scripts/ai_council/replay.py +0 -155
  1449. package/src/scripts/ai_council/session.py +0 -366
  1450. package/src/scripts/ai_council/shadow_dispatch.py +0 -235
  1451. package/src/scripts/ai_council/solo_dispatch.py +0 -226
  1452. package/src/scripts/annotate_discovery.py +0 -149
  1453. package/src/scripts/apply_modules_config.py +0 -290
  1454. package/src/scripts/audit_adr_coverage.py +0 -175
  1455. package/src/scripts/audit_auto_rules.py +0 -175
  1456. package/src/scripts/audit_cloud_compatibility.py +0 -362
  1457. package/src/scripts/audit_command_surface.py +0 -669
  1458. package/src/scripts/audit_initial_context.py +0 -237
  1459. package/src/scripts/audit_likelihood.py +0 -148
  1460. package/src/scripts/audit_mcp_tools.py +0 -146
  1461. package/src/scripts/audit_overlap.py +0 -145
  1462. package/src/scripts/audit_skill_descriptions.py +0 -180
  1463. package/src/scripts/audit_skill_overlap.py +0 -207
  1464. package/src/scripts/audit_user_type_axis.py +0 -140
  1465. package/src/scripts/backfill_model_tier.py +0 -184
  1466. package/src/scripts/bench_ab_cache_dispatch.py +0 -68
  1467. package/src/scripts/bench_ab_clone.py +0 -170
  1468. package/src/scripts/bench_ab_diff.py +0 -220
  1469. package/src/scripts/bench_ab_integrity.py +0 -143
  1470. package/src/scripts/bench_ab_run.py +0 -235
  1471. package/src/scripts/bench_ab_task_runner.py +0 -369
  1472. package/src/scripts/bench_ab_tracka_run.py +0 -202
  1473. package/src/scripts/bench_baseline_ready.py +0 -108
  1474. package/src/scripts/bench_condense_memory.py +0 -168
  1475. package/src/scripts/bench_drift_check.py +0 -151
  1476. package/src/scripts/bench_per_tool.py +0 -216
  1477. package/src/scripts/bench_rtk_savings.py +0 -320
  1478. package/src/scripts/bench_run.py +0 -272
  1479. package/src/scripts/bench_runner.py +0 -158
  1480. package/src/scripts/build_cloud_bundle.py +0 -458
  1481. package/src/scripts/build_discovery_manifest.py +0 -747
  1482. package/src/scripts/build_linear_digest.py +0 -260
  1483. package/src/scripts/build_mcp_registry_manifest.py +0 -181
  1484. package/src/scripts/build_rule_trigger_matrix.py +0 -350
  1485. package/src/scripts/capture_showcase_session.py +0 -361
  1486. package/src/scripts/chat_history.py +0 -1799
  1487. package/src/scripts/check_always_budget.py +0 -532
  1488. package/src/scripts/check_artefact_checksums.py +0 -111
  1489. package/src/scripts/check_augment_description_cap.py +0 -79
  1490. package/src/scripts/check_augmentignore.py +0 -72
  1491. package/src/scripts/check_beta_review_markers.py +0 -127
  1492. package/src/scripts/check_bite_sized_granularity.py +0 -99
  1493. package/src/scripts/check_cluster_patterns.py +0 -206
  1494. package/src/scripts/check_command_count_messaging.py +0 -152
  1495. package/src/scripts/check_condensation.py +0 -375
  1496. package/src/scripts/check_condensed_paths.py +0 -231
  1497. package/src/scripts/check_context_paths.py +0 -202
  1498. package/src/scripts/check_council_layout.py +0 -125
  1499. package/src/scripts/check_council_references.py +0 -228
  1500. package/src/scripts/check_discovery_determinism.py +0 -70
  1501. package/src/scripts/check_gate_paths.py +0 -128
  1502. package/src/scripts/check_iron_law_prominence.py +0 -145
  1503. package/src/scripts/check_kernel_rule_bundle.py +0 -151
  1504. package/src/scripts/check_md_language.py +0 -161
  1505. package/src/scripts/check_memory.py +0 -443
  1506. package/src/scripts/check_memory_proposal.py +0 -182
  1507. package/src/scripts/check_module_management_neutral.py +0 -147
  1508. package/src/scripts/check_no_local_settings_committed.py +0 -51
  1509. package/src/scripts/check_no_new_legacy_path.py +0 -100
  1510. package/src/scripts/check_no_roadmap_refs.py +0 -155
  1511. package/src/scripts/check_one_off_location.py +0 -81
  1512. package/src/scripts/check_overlay_cascade_subdirs.py +0 -129
  1513. package/src/scripts/check_portability.py +0 -574
  1514. package/src/scripts/check_proposal.py +0 -269
  1515. package/src/scripts/check_public_catalog_links.py +0 -125
  1516. package/src/scripts/check_public_links.py +0 -185
  1517. package/src/scripts/check_references.py +0 -557
  1518. package/src/scripts/check_release_includes_discovery.py +0 -61
  1519. package/src/scripts/check_release_pr_shape.py +0 -123
  1520. package/src/scripts/check_release_published.py +0 -145
  1521. package/src/scripts/check_release_trunk_sync.py +0 -152
  1522. package/src/scripts/check_reply_consistency.py +0 -169
  1523. package/src/scripts/check_roadmap_trackable.py +0 -114
  1524. package/src/scripts/check_role_doc_links.py +0 -110
  1525. package/src/scripts/check_safety_floor_untouched.py +0 -125
  1526. package/src/scripts/check_skill_requires.py +0 -147
  1527. package/src/scripts/check_template_pin_drift.py +0 -129
  1528. package/src/scripts/check_test_coverage_diff.py +0 -180
  1529. package/src/scripts/check_token_optimizer_freshness.py +0 -146
  1530. package/src/scripts/check_update_banner.py +0 -86
  1531. package/src/scripts/ci_status.py +0 -301
  1532. package/src/scripts/ci_summary.py +0 -131
  1533. package/src/scripts/ci_time_ratio.py +0 -168
  1534. package/src/scripts/command_suggester/__init__.py +0 -51
  1535. package/src/scripts/command_suggester/cooldown.py +0 -132
  1536. package/src/scripts/command_suggester/loader.py +0 -73
  1537. package/src/scripts/command_suggester/match.py +0 -180
  1538. package/src/scripts/command_suggester/rank.py +0 -120
  1539. package/src/scripts/command_suggester/render.py +0 -86
  1540. package/src/scripts/command_suggester/sanitize.py +0 -113
  1541. package/src/scripts/command_suggester/settings.py +0 -127
  1542. package/src/scripts/command_suggester/types.py +0 -78
  1543. package/src/scripts/compile_router.py +0 -232
  1544. package/src/scripts/condense.py +0 -1919
  1545. package/src/scripts/condense_memory.py +0 -178
  1546. package/src/scripts/config/__init__.py +0 -9
  1547. package/src/scripts/config/packs.py +0 -157
  1548. package/src/scripts/config/presets.py +0 -224
  1549. package/src/scripts/config/profile_explain.py +0 -89
  1550. package/src/scripts/config/profiles.py +0 -191
  1551. package/src/scripts/config/session_profiles.py +0 -542
  1552. package/src/scripts/context_hygiene_hook.py +0 -181
  1553. package/src/scripts/cost_by_conversation.py +0 -78
  1554. package/src/scripts/cost_summary.py +0 -97
  1555. package/src/scripts/council_cli.py +0 -2557
  1556. package/src/scripts/council_prune.py +0 -81
  1557. package/src/scripts/cross_repo_retrieve.py +0 -172
  1558. package/src/scripts/discovery_stats.py +0 -70
  1559. package/src/scripts/extract_audit_patterns.py +0 -202
  1560. package/src/scripts/first_run_gate_hook.py +0 -179
  1561. package/src/scripts/gen_discovery_baseline.py +0 -127
  1562. package/src/scripts/generate_catalog.py +0 -116
  1563. package/src/scripts/generate_command_flows.py +0 -191
  1564. package/src/scripts/generate_index.py +0 -303
  1565. package/src/scripts/generate_ownership_matrix.py +0 -378
  1566. package/src/scripts/generate_pack_manifests.py +0 -340
  1567. package/src/scripts/hooks/__init__.py +0 -1
  1568. package/src/scripts/hooks/dispatch_hook.py +0 -461
  1569. package/src/scripts/hooks/dispatch_issues.py +0 -136
  1570. package/src/scripts/hooks/envelope.py +0 -98
  1571. package/src/scripts/hooks/replay_hook.py +0 -144
  1572. package/src/scripts/hooks/state_io.py +0 -145
  1573. package/src/scripts/hooks_doctor.py +0 -223
  1574. package/src/scripts/hooks_status.py +0 -157
  1575. package/src/scripts/install.py +0 -5183
  1576. package/src/scripts/inventory_abstraction_budget.py +0 -622
  1577. package/src/scripts/inventory_frontmatter.py +0 -164
  1578. package/src/scripts/inventory_meta_layers.py +0 -288
  1579. package/src/scripts/iron_law_sha.py +0 -107
  1580. package/src/scripts/linked_projects_list.py +0 -91
  1581. package/src/scripts/lint_agent_skill_names.py +0 -150
  1582. package/src/scripts/lint_agents_layout.py +0 -197
  1583. package/src/scripts/lint_agents_md.py +0 -210
  1584. package/src/scripts/lint_archived_skills.py +0 -159
  1585. package/src/scripts/lint_artefact_frontmatter.py +0 -188
  1586. package/src/scripts/lint_bench_ab.py +0 -172
  1587. package/src/scripts/lint_bench_corpus.py +0 -255
  1588. package/src/scripts/lint_command_flow_coverage.py +0 -132
  1589. package/src/scripts/lint_command_routing.py +0 -160
  1590. package/src/scripts/lint_command_tiers.py +0 -175
  1591. package/src/scripts/lint_command_verbs.py +0 -206
  1592. package/src/scripts/lint_commit_subjects.py +0 -139
  1593. package/src/scripts/lint_context_spine_usage.py +0 -137
  1594. package/src/scripts/lint_discovery_manifest.py +0 -176
  1595. package/src/scripts/lint_discovery_vocabulary.py +0 -220
  1596. package/src/scripts/lint_examples.py +0 -102
  1597. package/src/scripts/lint_explain_trace.py +0 -80
  1598. package/src/scripts/lint_featured_skills.py +0 -144
  1599. package/src/scripts/lint_flows.py +0 -215
  1600. package/src/scripts/lint_framework_leakage.py +0 -375
  1601. package/src/scripts/lint_frontmatter_boilerplate.py +0 -77
  1602. package/src/scripts/lint_ghostwriter_source.py +0 -242
  1603. package/src/scripts/lint_global_paths.py +0 -148
  1604. package/src/scripts/lint_handoffs.py +0 -217
  1605. package/src/scripts/lint_hook_concern_budget.py +0 -207
  1606. package/src/scripts/lint_hook_manifest.py +0 -217
  1607. package/src/scripts/lint_load_context.py +0 -196
  1608. package/src/scripts/lint_marketplace.py +0 -180
  1609. package/src/scripts/lint_marketplace_install_completeness.py +0 -198
  1610. package/src/scripts/lint_mcp_registry_manifest.py +0 -69
  1611. package/src/scripts/lint_media_policy_linkage.py +0 -140
  1612. package/src/scripts/lint_model_tier_coverage.py +0 -73
  1613. package/src/scripts/lint_namespace.py +0 -135
  1614. package/src/scripts/lint_namespace_collisions.py +0 -103
  1615. package/src/scripts/lint_new_skill_gate.py +0 -144
  1616. package/src/scripts/lint_no_new_atomic_commands.py +0 -180
  1617. package/src/scripts/lint_one_off_age.py +0 -184
  1618. package/src/scripts/lint_orchestration_dsl.py +0 -217
  1619. package/src/scripts/lint_orchestrator_auto_detect.py +0 -111
  1620. package/src/scripts/lint_pack_boundaries.py +0 -147
  1621. package/src/scripts/lint_pack_dependencies.py +0 -137
  1622. package/src/scripts/lint_pack_first_win.py +0 -121
  1623. package/src/scripts/lint_persona_governance.py +0 -164
  1624. package/src/scripts/lint_positioning.py +0 -143
  1625. package/src/scripts/lint_profile_overlay_set_only.py +0 -179
  1626. package/src/scripts/lint_readme_jargon.py +0 -131
  1627. package/src/scripts/lint_readme_size.py +0 -33
  1628. package/src/scripts/lint_regression.py +0 -251
  1629. package/src/scripts/lint_roadmap_ci_steps.py +0 -186
  1630. package/src/scripts/lint_roadmap_complexity.py +0 -220
  1631. package/src/scripts/lint_role_experiences.py +0 -255
  1632. package/src/scripts/lint_rule_interactions.py +0 -170
  1633. package/src/scripts/lint_rule_tiers.py +0 -90
  1634. package/src/scripts/lint_showcase_sessions.py +0 -148
  1635. package/src/scripts/lint_skill_tools.py +0 -168
  1636. package/src/scripts/lint_topics_yaml.py +0 -89
  1637. package/src/scripts/lint_trust_coherence.py +0 -212
  1638. package/src/scripts/lint_value_dashboard.py +0 -218
  1639. package/src/scripts/mcp_parity_smoke.py +0 -316
  1640. package/src/scripts/mcp_render.py +0 -173
  1641. package/src/scripts/mcp_server/__init__.py +0 -19
  1642. package/src/scripts/mcp_server/__main__.py +0 -12
  1643. package/src/scripts/mcp_server/catalog.py +0 -125
  1644. package/src/scripts/mcp_server/metadata.py +0 -75
  1645. package/src/scripts/mcp_server/prompts.py +0 -442
  1646. package/src/scripts/mcp_server/requirements.txt +0 -4
  1647. package/src/scripts/mcp_server/resources.py +0 -201
  1648. package/src/scripts/mcp_server/server.py +0 -270
  1649. package/src/scripts/mcp_server/telemetry.py +0 -128
  1650. package/src/scripts/mcp_server/tools.py +0 -950
  1651. package/src/scripts/mcp_telemetry_health.py +0 -214
  1652. package/src/scripts/mcp_telemetry_query.py +0 -203
  1653. package/src/scripts/mcp_telemetry_store.py +0 -211
  1654. package/src/scripts/measure_augment_budget.py +0 -214
  1655. package/src/scripts/measure_density.py +0 -232
  1656. package/src/scripts/measure_frugality_savings.py +0 -164
  1657. package/src/scripts/measure_markitdown_lift.py +0 -127
  1658. package/src/scripts/measure_patterns.py +0 -376
  1659. package/src/scripts/measure_projection_bytes.py +0 -159
  1660. package/src/scripts/measure_rule_budget.py +0 -347
  1661. package/src/scripts/measure_skill_reduction.py +0 -102
  1662. package/src/scripts/memory_hash.py +0 -75
  1663. package/src/scripts/memory_lookup.py +0 -705
  1664. package/src/scripts/memory_report.py +0 -336
  1665. package/src/scripts/memory_signal.py +0 -212
  1666. package/src/scripts/memory_status.py +0 -257
  1667. package/src/scripts/migrate_command_suggestions.py +0 -151
  1668. package/src/scripts/migrate_frontmatter_defaults.py +0 -245
  1669. package/src/scripts/mine_session.py +0 -279
  1670. package/src/scripts/minimal_safe_diff_hook.py +0 -245
  1671. package/src/scripts/move_artefact.py +0 -143
  1672. package/src/scripts/new_skill.py +0 -148
  1673. package/src/scripts/onboarding_gate_hook.py +0 -142
  1674. package/src/scripts/pack_mcp_content.py +0 -293
  1675. package/src/scripts/plan_physical_move.py +0 -353
  1676. package/src/scripts/prediction-pool/poisson_sim.py +0 -167
  1677. package/src/scripts/prediction-pool/pool_winsim.py +0 -236
  1678. package/src/scripts/prediction-pool/score_ev.py +0 -188
  1679. package/src/scripts/print_required_checks.py +0 -196
  1680. package/src/scripts/probe_projection_fidelity.py +0 -202
  1681. package/src/scripts/probe_skill_registration.py +0 -413
  1682. package/src/scripts/profile_staleness_hook.py +0 -69
  1683. package/src/scripts/profile_use.py +0 -164
  1684. package/src/scripts/project_thin_rules.py +0 -168
  1685. package/src/scripts/propose_modules_config.py +0 -145
  1686. package/src/scripts/prototype_lint_contradictions.py +0 -150
  1687. package/src/scripts/prove_pack_extractable.py +0 -187
  1688. package/src/scripts/readme_linter.py +0 -589
  1689. package/src/scripts/redact_hook_capture.py +0 -148
  1690. package/src/scripts/refine_ticket_detect.py +0 -646
  1691. package/src/scripts/release.py +0 -1091
  1692. package/src/scripts/render_benchmark_md.py +0 -312
  1693. package/src/scripts/render_value_md.py +0 -347
  1694. package/src/scripts/requirements-evals.txt +0 -8
  1695. package/src/scripts/roadmap_progress_hook.py +0 -274
  1696. package/src/scripts/router_telemetry.py +0 -470
  1697. package/src/scripts/run_skill_evals.py +0 -185
  1698. package/src/scripts/runtime_dispatcher.py +0 -276
  1699. package/src/scripts/runtime_handler.py +0 -148
  1700. package/src/scripts/runtime_registry.py +0 -166
  1701. package/src/scripts/score_skill_selection.py +0 -198
  1702. package/src/scripts/setup_eval_venv.sh +0 -58
  1703. package/src/scripts/skill_collision_clusters.py +0 -162
  1704. package/src/scripts/skill_discovery.py +0 -254
  1705. package/src/scripts/skill_linter.py +0 -3694
  1706. package/src/scripts/skill_overlap.py +0 -204
  1707. package/src/scripts/skill_preview.py +0 -179
  1708. package/src/scripts/skill_tools/__init__.py +0 -22
  1709. package/src/scripts/skill_tools/audit_persona_coverage.py +0 -147
  1710. package/src/scripts/skill_tools/audit_user_type_coverage.py +0 -148
  1711. package/src/scripts/skill_tools/run_block_d_eval.py +0 -129
  1712. package/src/scripts/skill_tools/score_skill_relevance.py +0 -169
  1713. package/src/scripts/skill_tools/suggest_skill_for_task.py +0 -113
  1714. package/src/scripts/skill_trigger_eval.py +0 -682
  1715. package/src/scripts/skill_usage_collect.py +0 -191
  1716. package/src/scripts/skill_usage_report.py +0 -162
  1717. package/src/scripts/smoke_path_resolution.py +0 -93
  1718. package/src/scripts/smoke_quickstart.py +0 -144
  1719. package/src/scripts/snapshot_agent_outputs.py +0 -144
  1720. package/src/scripts/spotcheck_thin_root.py +0 -134
  1721. package/src/scripts/sync_agent_settings.py +0 -180
  1722. package/src/scripts/sync_github_metadata.py +0 -147
  1723. package/src/scripts/sync_gitignore.py +0 -291
  1724. package/src/scripts/sync_yaml_rt.py +0 -734
  1725. package/src/scripts/telegraph_stats.py +0 -119
  1726. package/src/scripts/tool_registry.py +0 -146
  1727. package/src/scripts/tools/__init__.py +0 -1
  1728. package/src/scripts/tools/adapter_errors.py +0 -63
  1729. package/src/scripts/tools/base_adapter.py +0 -91
  1730. package/src/scripts/tools/github_adapter.py +0 -128
  1731. package/src/scripts/tools/jira_adapter.py +0 -115
  1732. package/src/scripts/trigger_coverage.py +0 -129
  1733. package/src/scripts/update_counts.py +0 -199
  1734. package/src/scripts/update_prices.py +0 -125
  1735. package/src/scripts/validate_agent_settings.py +0 -124
  1736. package/src/scripts/validate_decision_engine.py +0 -136
  1737. package/src/scripts/validate_discovery_manifest.py +0 -94
  1738. package/src/scripts/validate_frontmatter.py +0 -647
  1739. package/src/scripts/validate_pack_yaml.py +0 -179
  1740. package/src/scripts/validate_safe_paths.py +0 -118
  1741. package/src/scripts/validate_telegraph_carveouts.py +0 -129
  1742. package/src/scripts/verify_before_complete_hook.py +0 -216
  1743. package/src/scripts/verify_physical_move.py +0 -185
  1744. package/src/scripts/wrapper_freshness_hook.py +0 -86
  1745. /package/dist/agent-src/skills/design-intelligence/data/{typography.csv → font-pairings-reference.csv} +0 -0
  1746. /package/src/scripts/{ai-video → media}/lib/fixtures/allin1/analysis.json +0 -0
  1747. /package/src/scripts/{ai-video → media}/lib/fixtures/comfyui/scene-0001.mp4 +0 -0
  1748. /package/src/scripts/{ai-video → media}/lib/fixtures/fal/scene-0001.mp4 +0 -0
  1749. /package/src/scripts/{ai-video → media}/lib/fixtures/gemini-veo/scene-0001.mp4 +0 -0
  1750. /package/src/scripts/{ai-video → media}/lib/fixtures/higgsfield/scene-0001.mp4 +0 -0
  1751. /package/src/scripts/{ai-video → media}/lib/fixtures/kling/scene-0001.mp4 +0 -0
  1752. /package/src/scripts/{ai-video → media}/lib/fixtures/musetalk/lipsync-0001.mp4 +0 -0
  1753. /package/src/scripts/{ai-video → media}/lib/fixtures/openai-images/scene-0001.png +0 -0
  1754. /package/src/scripts/{ai-video → media}/lib/fixtures/replicate/scene-0001.mp4 +0 -0
  1755. /package/src/scripts/{ai-video → media}/lib/fixtures/sora/scene-0001.mp4 +0 -0
  1756. /package/src/scripts/{ai-video → media}/lib/fixtures/syncso/lipsync-0001.mp4 +0 -0
  1757. /package/src/scripts/{ai-video → media}/lib/fixtures/whisperx/transcript.json +0 -0
  1758. /package/src/scripts/{ai-video → media}/lib/telemetry.sh +0 -0
@@ -0,0 +1,2827 @@
1
+ #!/usr/bin/env node
2
+ /**
3
+ * Council CLI — `./agent-config council:{estimate,run,render}`.
4
+ *
5
+ * TypeScript twin of `council_cli.py` (py2ts Phase 1, ADR-200). Wraps
6
+ * `ai_council/orchestrator` for non-interactive callers. Subcommands:
7
+ *
8
+ * estimate Bundle + estimate per-member cost (no API call, no spend).
9
+ * run Same + estimate, then call the council. Requires --confirm.
10
+ * render Re-render a saved responses JSON to the markdown report.
11
+ *
12
+ * `./agent-config` is non-interactive by contract — the cost gate is an
13
+ * explicit `--confirm` flag, never an interactive y/n.
14
+ */
15
+ import * as fs from 'node:fs';
16
+ import * as path from 'node:path';
17
+ import { fileURLToPath, pathToFileURL } from 'node:url';
18
+
19
+ import { project_settings_path, resolve_project_root } from './_lib/agent_settings.js';
20
+ import { load_agent_settings } from './_lib/agent_settings.js';
21
+
22
+ import {
23
+ BundleTooLarge,
24
+ bundle_prompt,
25
+ bundle_roadmap,
26
+ } from './ai_council/bundler.js';
27
+ import type {
28
+ ExternalAIClient} from './ai_council/clients.js';
29
+ import {
30
+ DEFAULT_MAX_TOKENS,
31
+ UNLIMITED_TOKENS_FALLBACK,
32
+ AnthropicClient,
33
+ AnthropicCliClient,
34
+ CliClient,
35
+ CliClientError,
36
+ CouncilResponse,
37
+ GeminiClient,
38
+ GeminiCliClient,
39
+ ManualClient,
40
+ OpenAIClient,
41
+ OpenAICliClient,
42
+ PerplexityClient,
43
+ PerplexityCliClient,
44
+ XAIClient,
45
+ XAICliClient,
46
+ load_anthropic_key,
47
+ load_cli_call_counts,
48
+ load_openai_key,
49
+ quota_summary_line,
50
+ reset_cli_call_counts,
51
+ } from './ai_council/clients.js';
52
+ import type {
53
+ AdvisorPlan} from './ai_council/advisors.js';
54
+ import {
55
+ build_persona_labels,
56
+ plan_advisor_swap,
57
+ } from './ai_council/advisors.js';
58
+ import { format_install_hints } from './ai_council/cli_hints.js';
59
+ import {
60
+ type AdvisorConfig,
61
+ type CouncilConfig,
62
+ CouncilConfigError,
63
+ load_council_config,
64
+ resolve_api_key,
65
+ resolve_config_path,
66
+ } from './ai_council/config.js';
67
+ import { AuthCache, select_solo_member } from './ai_council/solo_dispatch.js';
68
+ import { InvalidModeError, resolve_mode } from './ai_council/modes.js';
69
+ import { appendEvent } from './ai_council/events_log.js';
70
+ import {
71
+ type ClassificationResult,
72
+ type SizeFitVerdict,
73
+ classify_necessity,
74
+ classify_size_fit,
75
+ downgrade_message,
76
+ educate_message,
77
+ } from './ai_council/necessity.js';
78
+ import type {
79
+ DebateCheckpoint} from './ai_council/orchestrator.js';
80
+ import {
81
+ ConsensusResult,
82
+ CostBudget,
83
+ CouncilQuestion,
84
+ DebateCapExceeded,
85
+ type DebateCostEstimate,
86
+ PeerReviewResult,
87
+ consult,
88
+ estimate,
89
+ estimate_debate_cost,
90
+ render,
91
+ run_consensus_scoring,
92
+ run_debate,
93
+ run_peer_review,
94
+ } from './ai_council/orchestrator.js';
95
+ import {
96
+ type PriceTable,
97
+ estimate_cost,
98
+ load_prices,
99
+ } from './ai_council/pricing.js';
100
+ import { detect_project_context } from './ai_council/project_context.js';
101
+ import {
102
+ DecisionReplayInputs,
103
+ render_decision_replay,
104
+ } from './ai_council/replay.js';
105
+ import {
106
+ Finding as ConsensusFinding,
107
+ FindingScore as ConsensusFindingScore,
108
+ aggregate_scores,
109
+ bucket_by_threshold,
110
+ } from './ai_council/consensus.js';
111
+ import * as _shadow from './ai_council/shadow_dispatch.js';
112
+ import * as _lowimpact from './ai_council/low_impact.js';
113
+
114
+ // ── argparse-style exit plumbing ────────────────────────────────────
115
+ // Mirror CPython argparse: a `prog: error: …` line on stderr + exit 2.
116
+ // `_ArgExit` unwinds the call stack after `process.exitCode` is set.
117
+ class _ArgExit extends Error {}
118
+
119
+ /** Mirror Python `argparse.ArgumentTypeError` (caught in `main` → exit 2). */
120
+ class ArgumentTypeError extends Error {}
121
+
122
+ const _PROG = 'agent-config council';
123
+
124
+ const SCHEMA_VERSION = 1;
125
+
126
+ /**
127
+ * Provider names accepted under `mode=api`. Mirrors the routing table
128
+ * in `_construct_api_member`; both must stay in sync.
129
+ */
130
+ const _API_PROVIDERS: ReadonlySet<string> = new Set([
131
+ 'anthropic',
132
+ 'openai',
133
+ 'gemini',
134
+ 'xai',
135
+ 'perplexity',
136
+ ]);
137
+
138
+ /**
139
+ * Provider names with a wired `mode=cli` subclass. Mirrors the routing
140
+ * table in `_construct_cli_member`; both must stay in sync.
141
+ */
142
+ const _CLI_PROVIDERS: ReadonlySet<string> = new Set([
143
+ 'anthropic',
144
+ 'openai',
145
+ 'gemini',
146
+ 'xai',
147
+ 'perplexity',
148
+ ]);
149
+
150
+ // `PACKAGE_ROOT` is where `ai_council/*` lives — fixed relative to this
151
+ // file. `REPO_ROOT` is the project the council operates on.
152
+ const _HERE = path.dirname(fileURLToPath(import.meta.url));
153
+ const [REPO_ROOT] = resolve_project_root(null);
154
+ const SETTINGS_FILE = project_settings_path(REPO_ROOT);
155
+ // User-global-first resolution (see `resolve_config_path`).
156
+ const AI_COUNCIL_FILE = resolve_config_path(REPO_ROOT);
157
+
158
+ // Canonical output dirs per ai-council § "Output path convention".
159
+ const COUNCIL_CANONICAL_DIRS: Record<string, string> = {
160
+ responses: 'agents/runtime/council/responses',
161
+ sessions: 'agents/runtime/council/sessions',
162
+ questions: 'agents/runtime/council/questions',
163
+ };
164
+
165
+ type Dict = Record<string, unknown>;
166
+
167
+ // ── Python-parity helpers ───────────────────────────────────────────
168
+
169
+ /**
170
+ * Format `x` to `ndigits` decimals using round-half-to-even, matching
171
+ * CPython's `format(x, ".<ndigits>f")` (the `:.4f` / `:.2f` f-strings).
172
+ */
173
+ function _pyFixed(x: number, ndigits: number): string {
174
+ if (!Number.isFinite(x)) {
175
+ return String(x);
176
+ }
177
+ const neg = x < 0 || Object.is(x, -0);
178
+ const abs = Math.abs(x);
179
+ const factor = Math.pow(10, ndigits);
180
+ const scaled = abs * factor;
181
+ const floor = Math.floor(scaled);
182
+ const frac = scaled - floor;
183
+ const tol = Math.max(Math.abs(scaled), 1) * 2 ** -40;
184
+ let rounded: number;
185
+ if (Math.abs(frac - 0.5) <= tol) {
186
+ rounded = floor % 2 === 0 ? floor : floor + 1;
187
+ } else {
188
+ rounded = Math.round(scaled);
189
+ }
190
+ let intStr = String(rounded);
191
+ let result: string;
192
+ if (ndigits === 0) {
193
+ result = intStr;
194
+ } else {
195
+ if (intStr.length <= ndigits) {
196
+ intStr = '0'.repeat(ndigits - intStr.length + 1) + intStr;
197
+ }
198
+ const whole = intStr.slice(0, intStr.length - ndigits);
199
+ const decimals = intStr.slice(intStr.length - ndigits);
200
+ result = `${whole}.${decimals}`;
201
+ }
202
+ if (neg && Number(result) !== 0) {
203
+ result = `-${result}`;
204
+ }
205
+ return result;
206
+ }
207
+
208
+ /** Python `round(value, ndigits)` — banker's rounding. */
209
+ function _pyRound(value: number, ndigits: number): number {
210
+ if (!Number.isFinite(value)) {
211
+ return value;
212
+ }
213
+ const factor = Math.pow(10, ndigits);
214
+ const scaled = value * factor;
215
+ const floor = Math.floor(scaled);
216
+ const frac = scaled - floor;
217
+ const tol = Math.max(Math.abs(scaled), 1) * 2 ** -40;
218
+ let rounded: number;
219
+ if (Math.abs(frac - 0.5) <= tol) {
220
+ rounded = floor % 2 === 0 ? floor : floor + 1;
221
+ } else {
222
+ rounded = Math.round(scaled);
223
+ }
224
+ return rounded / factor;
225
+ }
226
+
227
+ /** Python `repr()` for a string (single-quoted unless it embeds a `'`). */
228
+ function _pyReprStr(s: string): string {
229
+ if (s.includes("'") && !s.includes('"')) {
230
+ return `"${s}"`;
231
+ }
232
+ return `'${s.replace(/\\/g, '\\\\').replace(/'/g, "\\'")}'`;
233
+ }
234
+
235
+ /** Python `repr()` of a list of strings. */
236
+ function _pyReprStrList(items: readonly string[]): string {
237
+ return `[${items.map(_pyReprStr).join(', ')}]`;
238
+ }
239
+
240
+ /** Python `sorted(...)` of strings (code-point order). */
241
+ function _pySortedStr(items: Iterable<string>): string[] {
242
+ return [...items].sort((a, b) => (a < b ? -1 : a > b ? 1 : 0));
243
+ }
244
+
245
+ function _getattr<T>(obj: unknown, name: string, fallback: T): T {
246
+ if (obj !== null && typeof obj === 'object' && name in (obj as Dict)) {
247
+ const v = (obj as Dict)[name];
248
+ return v === undefined ? fallback : (v as T);
249
+ }
250
+ return fallback;
251
+ }
252
+
253
+ function _isDict(v: unknown): v is Dict {
254
+ return typeof v === 'object' && v !== null && !Array.isArray(v);
255
+ }
256
+
257
+ /** Python `int(x)` truncation toward zero for the loose ints. */
258
+ function _pyInt(v: unknown, fallback = 0): number {
259
+ if (v === null || v === undefined) {
260
+ return fallback;
261
+ }
262
+ const n = typeof v === 'number' ? v : Number(v);
263
+ if (!Number.isFinite(n)) {
264
+ return fallback;
265
+ }
266
+ return Math.trunc(n);
267
+ }
268
+
269
+ function _pyFloat(v: unknown, fallback = 0.0): number {
270
+ if (v === null || v === undefined) {
271
+ return fallback;
272
+ }
273
+ const n = typeof v === 'number' ? v : Number(v);
274
+ if (!Number.isFinite(n)) {
275
+ return fallback;
276
+ }
277
+ return n;
278
+ }
279
+
280
+ function _pyBool(v: unknown): boolean {
281
+ if (v === null || v === undefined) {
282
+ return false;
283
+ }
284
+ if (typeof v === 'boolean') {
285
+ return v;
286
+ }
287
+ if (typeof v === 'number') {
288
+ return v !== 0;
289
+ }
290
+ if (typeof v === 'string') {
291
+ return v.length > 0;
292
+ }
293
+ if (Array.isArray(v)) {
294
+ return v.length > 0;
295
+ }
296
+ if (v instanceof Map || v instanceof Set) {
297
+ return v.size > 0;
298
+ }
299
+ if (typeof v === 'object') {
300
+ return Object.keys(v as Dict).length > 0;
301
+ }
302
+ return Boolean(v);
303
+ }
304
+
305
+ /** `json.dumps(obj, indent=2)` byte-parity (ensure_ascii=True default). */
306
+ function _jsonDumpsIndent2(obj: unknown, level = 0): string {
307
+ const pad = ' '.repeat(level + 1);
308
+ const closePad = ' '.repeat(level);
309
+ if (obj === null || obj === undefined) {
310
+ return 'null';
311
+ }
312
+ if (typeof obj === 'boolean') {
313
+ return obj ? 'true' : 'false';
314
+ }
315
+ if (typeof obj === 'number') {
316
+ return _jsonNumber(obj);
317
+ }
318
+ if (typeof obj === 'string') {
319
+ return _jsonString(obj);
320
+ }
321
+ if (Array.isArray(obj)) {
322
+ if (obj.length === 0) {
323
+ return '[]';
324
+ }
325
+ const items = obj.map((v) => pad + _jsonDumpsIndent2(v, level + 1));
326
+ return `[\n${items.join(',\n')}\n${closePad}]`;
327
+ }
328
+ if (_isDict(obj)) {
329
+ const keys = Object.keys(obj as Dict);
330
+ if (keys.length === 0) {
331
+ return '{}';
332
+ }
333
+ const items = keys.map(
334
+ (k) => `${pad}${_jsonString(k)}: ${_jsonDumpsIndent2((obj as Dict)[k], level + 1)}`,
335
+ );
336
+ return `{\n${items.join(',\n')}\n${closePad}}`;
337
+ }
338
+ return 'null';
339
+ }
340
+
341
+ function _jsonNumber(n: number): string {
342
+ if (Number.isInteger(n) && Object.is(n, -0) === false) {
343
+ return String(n);
344
+ }
345
+ if (Object.is(n, -0)) {
346
+ return '-0.0';
347
+ }
348
+ return String(n);
349
+ }
350
+
351
+ function _jsonString(s: string): string {
352
+ // Python json.dumps default: ensure_ascii=True — escape non-ASCII as \uXXXX.
353
+ let out = '"';
354
+ for (const ch of s) {
355
+ const code = ch.codePointAt(0) as number;
356
+ if (ch === '"') {
357
+ out += '\\"';
358
+ } else if (ch === '\\') {
359
+ out += '\\\\';
360
+ } else if (ch === '\n') {
361
+ out += '\\n';
362
+ } else if (ch === '\r') {
363
+ out += '\\r';
364
+ } else if (ch === '\t') {
365
+ out += '\\t';
366
+ } else if (ch === '\b') {
367
+ out += '\\b';
368
+ } else if (ch === '\f') {
369
+ out += '\\f';
370
+ } else if (code < 0x20) {
371
+ out += `\\u${code.toString(16).padStart(4, '0')}`;
372
+ } else if (code < 0x7f) {
373
+ out += ch;
374
+ } else if (code <= 0xffff) {
375
+ out += `\\u${code.toString(16).padStart(4, '0')}`;
376
+ } else {
377
+ // surrogate pair
378
+ const c = code - 0x10000;
379
+ const hi = 0xd800 + (c >> 10);
380
+ const lo = 0xdc00 + (c & 0x3ff);
381
+ out += `\\u${hi.toString(16).padStart(4, '0')}\\u${lo.toString(16).padStart(4, '0')}`;
382
+ }
383
+ }
384
+ out += '"';
385
+ return out;
386
+ }
387
+
388
+ // ── output streams ──────────────────────────────────────────────────
389
+
390
+ function _stdout(s: string): void {
391
+ process.stdout.write(s);
392
+ }
393
+
394
+ function _stderr(s: string): void {
395
+ process.stderr.write(s);
396
+ }
397
+
398
+ class CouncilDisabledError extends Error {}
399
+
400
+ // ── settings loading ────────────────────────────────────────────────
401
+
402
+ function load_settings(
403
+ p: string = SETTINGS_FILE,
404
+ opts: { ai_council_path?: string } = {},
405
+ ): Dict {
406
+ const ai_council_path = opts.ai_council_path ?? AI_COUNCIL_FILE;
407
+ const settings = load_agent_settings({ project_path: p }) as Dict;
408
+ if (fs.existsSync(ai_council_path)) {
409
+ const cfg = load_council_config(ai_council_path);
410
+ settings['ai_council'] = _synthesize_ai_council_block(cfg);
411
+ }
412
+ return settings;
413
+ }
414
+
415
+ function _synthesize_ai_council_block(cfg: CouncilConfig): Dict {
416
+ const members: Dict = {};
417
+ for (const [name, m] of cfg.members) {
418
+ const entry: Dict = { enabled: m.enabled, model: m.model };
419
+ if (m.api_key_ref !== null) {
420
+ entry['api_key_ref'] = m.api_key_ref;
421
+ }
422
+ if (m.mode !== null) {
423
+ entry['mode'] = m.mode;
424
+ }
425
+ if (m.binary !== null) {
426
+ entry['binary'] = m.binary;
427
+ }
428
+ if (m.model_ladder && m.model_ladder.length > 0) {
429
+ entry['model_ladder'] = [...m.model_ladder];
430
+ }
431
+ members[name] = entry;
432
+ }
433
+ const advisors: Dict = {};
434
+ for (const [name, a] of cfg.advisors) {
435
+ const entry: Dict = {
436
+ enabled: a.enabled,
437
+ member: a.member,
438
+ persona: a.persona,
439
+ };
440
+ if (a.model !== null) {
441
+ entry['model'] = a.model;
442
+ }
443
+ advisors[name] = entry;
444
+ }
445
+ const lensCostDisclosure: Dict = {};
446
+ for (const [lens, cd] of cfg.lens_overrides.cost_disclosure) {
447
+ lensCostDisclosure[lens] = {
448
+ mode: cd.mode,
449
+ threshold_usd: cd.threshold_usd,
450
+ show_per_member: cd.show_per_member,
451
+ };
452
+ }
453
+ const lensModelDowngrade: Dict = {};
454
+ for (const [lens, md] of cfg.lens_overrides.model_downgrade) {
455
+ lensModelDowngrade[lens] = { enabled: md.enabled, auto_apply: md.auto_apply };
456
+ }
457
+ return {
458
+ enabled: cfg.enabled,
459
+ mode: cfg.defaults.mode,
460
+ min_rounds: cfg.defaults.min_rounds,
461
+ deep_min_rounds: cfg.defaults.deep_min_rounds,
462
+ max_output_tokens: cfg.defaults.max_output_tokens,
463
+ session_retention_days: cfg.defaults.session_retention_days,
464
+ debate_max_rounds: cfg.defaults.debate_max_rounds,
465
+ cost_budget: {
466
+ max_input_tokens: cfg.cost_budget.max_input_tokens,
467
+ max_output_tokens: cfg.cost_budget.max_output_tokens,
468
+ max_calls: cfg.cost_budget.max_calls,
469
+ max_total_usd: cfg.cost_budget.max_total_usd,
470
+ },
471
+ consensus_scoring: {
472
+ enabled: cfg.consensus_scoring.enabled,
473
+ strong_threshold: cfg.consensus_scoring.strong_threshold,
474
+ minority_threshold: cfg.consensus_scoring.minority_threshold,
475
+ lenses: [...cfg.consensus_scoring.lenses],
476
+ },
477
+ cli_call_budget: {
478
+ max_calls_per_day: _mapToObject(cfg.cli_call_budget.max_calls_per_day),
479
+ warn_at: cfg.cli_call_budget.warn_at,
480
+ },
481
+ necessity_classifier: {
482
+ enabled: cfg.necessity_classifier.enabled,
483
+ mode: cfg.necessity_classifier.mode,
484
+ user_explicit_mode: cfg.necessity_classifier.user_explicit_mode,
485
+ },
486
+ model_downgrade: {
487
+ enabled: cfg.model_downgrade.enabled,
488
+ auto_apply: cfg.model_downgrade.auto_apply,
489
+ },
490
+ debate: {
491
+ max_cost_usd: cfg.debate.max_cost_usd,
492
+ cost_disclosure: {
493
+ mode: cfg.debate.cost_disclosure.mode,
494
+ threshold_usd: cfg.debate.cost_disclosure.threshold_usd,
495
+ show_per_member: cfg.debate.cost_disclosure.show_per_member,
496
+ },
497
+ },
498
+ lens_overrides: {
499
+ necessity_classifier_mode: _mapToObject(
500
+ cfg.lens_overrides.necessity_classifier_mode,
501
+ ),
502
+ necessity_classifier_user_explicit_mode: _mapToObject(
503
+ cfg.lens_overrides.necessity_classifier_user_explicit_mode,
504
+ ),
505
+ model_downgrade: lensModelDowngrade,
506
+ cost_disclosure: lensCostDisclosure,
507
+ },
508
+ members,
509
+ advisors,
510
+ };
511
+ }
512
+
513
+ function _mapToObject<V>(m: ReadonlyMap<string, V>): Record<string, V> {
514
+ const out: Record<string, V> = {};
515
+ for (const [k, v] of m) {
516
+ out[k] = v;
517
+ }
518
+ return out;
519
+ }
520
+
521
+ // ── member construction ─────────────────────────────────────────────
522
+
523
+ interface BuildMembersOptions {
524
+ invocation_mode?: string | null;
525
+ model_overrides?: Record<string, string> | null;
526
+ siblings_overrides?: Record<string, string[]> | null;
527
+ skipped?: Dict[] | null;
528
+ }
529
+
530
+ function build_members(settings: Dict, opts: BuildMembersOptions = {}): ExternalAIClient[] {
531
+ const invocation_mode = opts.invocation_mode ?? null;
532
+ const model_overrides = opts.model_overrides ?? null;
533
+ const siblings_overrides = opts.siblings_overrides ?? null;
534
+ const skipped = opts.skipped ?? null;
535
+
536
+ const ai = _isDict(settings) ? ((settings['ai_council'] as Dict) || {}) : {};
537
+ if (!_pyBool(ai['enabled'])) {
538
+ throw new CouncilDisabledError(
539
+ 'ai_council.enabled is false in .agent-settings.yml — ' +
540
+ 'flip it on before invoking council:* commands.',
541
+ );
542
+ }
543
+ const members_cfg = (ai['members'] as Dict) || {};
544
+ const global_mode = ai['mode'] as string | null | undefined;
545
+ const cli_budget_cfg = _isDict(ai) ? ((ai['cli_call_budget'] as Dict) || {}) : {};
546
+ const cli_caps = _isDict(cli_budget_cfg)
547
+ ? ((cli_budget_cfg['max_calls_per_day'] as Dict) || {})
548
+ : {};
549
+ const cli_warn_at = _isDict(cli_budget_cfg)
550
+ ? _pyFloat(cli_budget_cfg['warn_at'] ?? 0.8, 0.8)
551
+ : 0.8;
552
+ const overrides = model_overrides || {};
553
+ const siblings = siblings_overrides || {};
554
+
555
+ const memberNames = new Set(Object.keys(members_cfg));
556
+ const unknown = _setDifference(Object.keys(overrides), memberNames);
557
+ if (unknown.length > 0) {
558
+ throw new CouncilDisabledError(
559
+ `--model targets unknown member(s) ${_pyReprStrList(_pySortedStr(unknown))}; ` +
560
+ `known members: ${_pyReprStrList(_pySortedStr(memberNames))}.`,
561
+ );
562
+ }
563
+ const unknown_sib = _setDifference(Object.keys(siblings), memberNames);
564
+ if (unknown_sib.length > 0) {
565
+ throw new CouncilDisabledError(
566
+ `--siblings targets unknown member(s) ${_pyReprStrList(_pySortedStr(unknown_sib))}; ` +
567
+ `known members: ${_pyReprStrList(_pySortedStr(memberNames))}.`,
568
+ );
569
+ }
570
+ const conflict = Object.keys(overrides).filter((k) => k in siblings);
571
+ if (conflict.length > 0) {
572
+ throw new CouncilDisabledError(
573
+ `--model and --siblings target the same member(s) ${_pyReprStrList(_pySortedStr(conflict))}; ` +
574
+ `pick one per provider per invocation.`,
575
+ );
576
+ }
577
+ const members: ExternalAIClient[] = [];
578
+ for (const name of Object.keys(members_cfg)) {
579
+ const cfg = ((members_cfg[name] as Dict) || {}) as Dict;
580
+ if (!_pyBool(cfg['enabled'])) {
581
+ if (name in siblings) {
582
+ throw new CouncilDisabledError(
583
+ `--siblings targets member ${_pyReprStr(name)} but it is not ` +
584
+ `enabled in .agent-settings.yml (ai_council.members.${name}.enabled).`,
585
+ );
586
+ }
587
+ continue;
588
+ }
589
+ const mode = resolve_mode(name, {
590
+ invocationMode: invocation_mode,
591
+ memberSettings: cfg,
592
+ globalMode: global_mode ?? null,
593
+ });
594
+ if (name in siblings) {
595
+ if (mode !== 'api') {
596
+ throw new CouncilDisabledError(
597
+ `--siblings requires mode=api for member ${_pyReprStr(name)} (got ${_pyReprStr(mode)}).`,
598
+ );
599
+ }
600
+ const api_key_ref = (cfg['api_key_ref'] as string | null) ?? null;
601
+ for (const sib_model of siblings[name] as string[]) {
602
+ members.push(_construct_api_member(name, sib_model, { api_key_ref }));
603
+ }
604
+ continue;
605
+ }
606
+ const model = (overrides[name] as string | undefined) || (cfg['model'] as string | undefined) || null;
607
+ if (mode === 'api' && _API_PROVIDERS.has(name)) {
608
+ members.push(
609
+ _construct_api_member(name, model, {
610
+ api_key_ref: (cfg['api_key_ref'] as string | null) ?? null,
611
+ }),
612
+ );
613
+ } else if (mode === 'cli' && _CLI_PROVIDERS.has(name)) {
614
+ try {
615
+ members.push(
616
+ _construct_cli_member(name, model, {
617
+ binary: (cfg['binary'] as string | null) ?? null,
618
+ max_calls_per_day: (cli_caps[name] as number | undefined) ?? null,
619
+ warn_at: cli_warn_at,
620
+ }),
621
+ );
622
+ } catch (exc) {
623
+ if (!(exc instanceof CliClientError)) {
624
+ throw exc;
625
+ }
626
+ const [, , display] = _CLI_FACTORY[name] as [
627
+ new (opts: { model: string }) => CliClient,
628
+ string,
629
+ string,
630
+ ];
631
+ const detail =
632
+ `${exc.message} Install the ${display} CLI or flip ` +
633
+ `ai_council.members.${name}.mode back to 'api'.`;
634
+ const entry: Dict = {
635
+ member: name,
636
+ reason: 'binary_missing',
637
+ detail,
638
+ };
639
+ if (skipped !== null) {
640
+ skipped.push(entry);
641
+ }
642
+ _stderr(`[council] SKIP ${name}: ${detail}\n`);
643
+ continue;
644
+ }
645
+ } else if (mode === 'cli') {
646
+ throw new CouncilDisabledError(
647
+ `member ${_pyReprStr(name)} resolves to mode=cli but no CLI client is ` +
648
+ `wired (known: ${_pyReprStrList(_pySortedStr(_CLI_PROVIDERS))}).`,
649
+ );
650
+ } else if (mode === 'manual') {
651
+ members.push(new ManualClient({ name, model: model || 'manual' }));
652
+ } else if (mode === 'playwright') {
653
+ throw new CouncilDisabledError(
654
+ `member ${_pyReprStr(name)} resolves to mode=playwright (Phase 2c, not wired).`,
655
+ );
656
+ } else {
657
+ throw new CouncilDisabledError(
658
+ `member ${_pyReprStr(name)} has no transport — mode=${mode}, ` +
659
+ `name not in ${_pyReprStrList(_pySortedStr(_API_PROVIDERS))}.`,
660
+ );
661
+ }
662
+ }
663
+ if (members.length === 0) {
664
+ if (skipped && skipped.length > 0) {
665
+ const names = skipped.map((s) => String(s['member'])).join(', ');
666
+ throw new CouncilDisabledError(
667
+ `no council member could be constructed — every enabled ` +
668
+ `member was skipped (${names}). See [council] SKIP entries ` +
669
+ `on stderr for the per-member reason.`,
670
+ );
671
+ }
672
+ throw new CouncilDisabledError(
673
+ 'no council member has `enabled: true` — enable at least one in ' +
674
+ '.agent-settings.yml under ai_council.members.*.',
675
+ );
676
+ }
677
+ return members;
678
+ }
679
+
680
+ function _setDifference(items: string[], known: Set<string>): string[] {
681
+ return items.filter((x) => !known.has(x));
682
+ }
683
+
684
+ function _build_advisor_plans(ai_cfg: Dict, repo_root: string): Map<string, AdvisorPlan> {
685
+ const raw = _isDict(ai_cfg) ? ai_cfg['advisors'] : null;
686
+ if (!_pyBool(raw)) {
687
+ return new Map();
688
+ }
689
+ const advisors = new Map<string, AdvisorConfig>();
690
+ for (const [name, entry] of Object.entries(raw as Dict)) {
691
+ if (!_isDict(entry)) {
692
+ continue;
693
+ }
694
+ advisors.set(name, {
695
+ name,
696
+ enabled: Boolean(_pyBool(entry['enabled'] ?? false)),
697
+ member: String(entry['member'] ?? ''),
698
+ persona: String(entry['persona'] ?? ''),
699
+ model: (entry['model'] as string | null) ?? null,
700
+ });
701
+ }
702
+ return plan_advisor_swap(advisors, repo_root);
703
+ }
704
+
705
+ function _advisor_model_overrides(
706
+ plans: Map<string, AdvisorPlan>,
707
+ explicit: Record<string, string> | null,
708
+ ): Record<string, string> {
709
+ const merged: Record<string, string> = {};
710
+ for (const [member, plan] of plans) {
711
+ if (plan.model_override) {
712
+ merged[member] = plan.model_override;
713
+ }
714
+ }
715
+ if (explicit) {
716
+ for (const [k, v] of Object.entries(explicit)) {
717
+ merged[k] = v;
718
+ }
719
+ }
720
+ return merged;
721
+ }
722
+
723
+ function _format_advisor_summary(
724
+ plans: Map<string, AdvisorPlan>,
725
+ members: ExternalAIClient[],
726
+ ): string {
727
+ if (plans.size === 0) {
728
+ return '';
729
+ }
730
+ const member_models = new Map<string, string>();
731
+ for (const m of members) {
732
+ member_models.set(m.name, m.model);
733
+ }
734
+ const rows: string[] = [];
735
+ for (const [member, plan] of plans) {
736
+ const model = member_models.get(member) ?? plan.model_override ?? '?';
737
+ rows.push(` advisor: ${plan.display_name} on ${member} via ${model}`);
738
+ }
739
+ return rows.join('\n');
740
+ }
741
+
742
+ function _construct_api_member(
743
+ name: string,
744
+ model: string | null,
745
+ opts: { api_key_ref?: string | null } = {},
746
+ ): ExternalAIClient {
747
+ const api_key_ref = opts.api_key_ref ?? null;
748
+ if (name === 'anthropic') {
749
+ const api_key = api_key_ref
750
+ ? resolve_api_key(api_key_ref, 'ai_council.members.anthropic')
751
+ : load_anthropic_key();
752
+ return new AnthropicClient({ model: model || 'claude-sonnet-4-5', api_key });
753
+ }
754
+ if (name === 'openai') {
755
+ const api_key = api_key_ref
756
+ ? resolve_api_key(api_key_ref, 'ai_council.members.openai')
757
+ : load_openai_key();
758
+ return new OpenAIClient({ model: model || 'gpt-4o', api_key });
759
+ }
760
+ if (name === 'gemini') {
761
+ if (!api_key_ref) {
762
+ throw new CouncilDisabledError(
763
+ "member 'gemini' requires api_key_ref in ~/.event4u/agent-config/settings/.ai-council.yml " +
764
+ '(e.g. `env:GEMINI_API_KEY`) — no legacy fallback.',
765
+ );
766
+ }
767
+ const api_key = resolve_api_key(api_key_ref, 'ai_council.members.gemini');
768
+ return new GeminiClient({ model: model || 'gemini-2.5-pro', api_key });
769
+ }
770
+ if (name === 'xai') {
771
+ if (!api_key_ref) {
772
+ throw new CouncilDisabledError(
773
+ "member 'xai' requires api_key_ref in ~/.event4u/agent-config/settings/.ai-council.yml " +
774
+ '(e.g. `env:XAI_API_KEY`) — no legacy fallback.',
775
+ );
776
+ }
777
+ const api_key = resolve_api_key(api_key_ref, 'ai_council.members.xai');
778
+ return new XAIClient({ model: model || 'grok-4', api_key });
779
+ }
780
+ if (name === 'perplexity') {
781
+ if (!api_key_ref) {
782
+ throw new CouncilDisabledError(
783
+ "member 'perplexity' requires api_key_ref in ~/.event4u/agent-config/settings/.ai-council.yml " +
784
+ '(e.g. `env:PERPLEXITY_API_KEY`) — no legacy fallback.',
785
+ );
786
+ }
787
+ const api_key = resolve_api_key(api_key_ref, 'ai_council.members.perplexity');
788
+ return new PerplexityClient({ model: model || 'sonar-pro', api_key });
789
+ }
790
+ throw new CouncilDisabledError(
791
+ `member ${_pyReprStr(name)} has no api transport ` +
792
+ `(known: ${_pyReprStrList(_pySortedStr(_API_PROVIDERS))}).`,
793
+ );
794
+ }
795
+
796
+ /**
797
+ * Provider → (class-ref, default_model, human_display) for cli-mode
798
+ * routing. The class ref is resolved at call time so tests that override
799
+ * the subclass keep working.
800
+ */
801
+ const _CLI_FACTORY: Record<
802
+ string,
803
+ [new (opts: { model: string; binary?: string | null; max_calls_per_day?: number | null; warn_at?: number }) => CliClient, string, string]
804
+ > = {
805
+ anthropic: [AnthropicCliClient, 'claude-sonnet-4-5', 'Claude'],
806
+ openai: [OpenAICliClient, 'gpt-5', 'Codex'],
807
+ gemini: [GeminiCliClient, 'gemini-2.5-pro', 'Gemini'],
808
+ xai: [XAICliClient, 'grok-4', 'Grok (community)'],
809
+ perplexity: [PerplexityCliClient, 'sonar-pro', 'Perplexity (community)'],
810
+ };
811
+
812
+ function _construct_cli_member(
813
+ name: string,
814
+ model: string | null,
815
+ opts: { binary?: string | null; max_calls_per_day?: number | null; warn_at?: number } = {},
816
+ ): ExternalAIClient {
817
+ const binary = opts.binary ?? null;
818
+ const max_calls_per_day = opts.max_calls_per_day ?? null;
819
+ const warn_at = opts.warn_at ?? 0.8;
820
+ if (name in _CLI_FACTORY) {
821
+ const [cls, default_model] = _CLI_FACTORY[name] as [
822
+ new (opts: { model: string; binary?: string | null; max_calls_per_day?: number | null; warn_at?: number }) => CliClient,
823
+ string,
824
+ string,
825
+ ];
826
+ return new cls({
827
+ model: model || default_model,
828
+ binary,
829
+ max_calls_per_day,
830
+ warn_at,
831
+ });
832
+ }
833
+ throw new CouncilDisabledError(
834
+ `member ${_pyReprStr(name)} has no cli transport ` +
835
+ `(known: ${_pyReprStrList(_pySortedStr(_CLI_PROVIDERS))}).`,
836
+ );
837
+ }
838
+
839
+ function build_question(opts: {
840
+ input_path: string;
841
+ input_mode: string;
842
+ max_tokens: number;
843
+ prompt_mode_override?: string | null;
844
+ }): [CouncilQuestion, string] {
845
+ const { input_path, input_mode, max_tokens } = opts;
846
+ const prompt_mode_override = opts.prompt_mode_override ?? null;
847
+ let ctx: { mode: string; text: string };
848
+ let artefact: string;
849
+ if (input_mode === 'prompt') {
850
+ const text = fs.readFileSync(input_path, 'utf-8');
851
+ ctx = bundle_prompt(text);
852
+ artefact = String(input_path);
853
+ } else if (input_mode === 'roadmap') {
854
+ ctx = bundle_roadmap(input_path);
855
+ artefact = String(input_path);
856
+ } else {
857
+ throw new ValueError(
858
+ `unsupported input mode: ${_pyReprStr(input_mode)} (use prompt | roadmap)`,
859
+ );
860
+ }
861
+ const mode = prompt_mode_override || ctx.mode;
862
+ return [new CouncilQuestion({ mode, user_prompt: ctx.text, max_tokens }), artefact];
863
+ }
864
+
865
+ class ValueError extends Error {}
866
+
867
+ function format_estimate_table(
868
+ members: ExternalAIClient[],
869
+ estimates: CostEstimateLike[],
870
+ opts: {
871
+ consensus_delta_usd?: number;
872
+ consensus_extra_calls?: number;
873
+ peer_review_delta_usd?: number;
874
+ peer_review_extra_calls?: number;
875
+ } = {},
876
+ ): string {
877
+ const consensus_delta_usd = opts.consensus_delta_usd ?? 0.0;
878
+ const consensus_extra_calls = opts.consensus_extra_calls ?? 0;
879
+ const peer_review_delta_usd = opts.peer_review_delta_usd ?? 0.0;
880
+ const peer_review_extra_calls = opts.peer_review_extra_calls ?? 0;
881
+
882
+ const rows: string[] = [];
883
+ for (let i = 0; i < members.length; i++) {
884
+ const m = members[i] as ExternalAIClient;
885
+ const e = estimates[i] as CostEstimateLike;
886
+ rows.push(
887
+ ` ${m.name}/${m.model}: ` +
888
+ `~${e.input_tokens} in + ${e.output_tokens} out = $${_pyFixed(_total_usd(e), 4)}`,
889
+ );
890
+ }
891
+ let total = estimates.reduce((acc, e) => acc + _total_usd(e), 0.0);
892
+ if (consensus_extra_calls > 0) {
893
+ rows.push(
894
+ ` +consensus scoring: +${consensus_extra_calls} calls ` +
895
+ `(~+$${_pyFixed(consensus_delta_usd, 4)})`,
896
+ );
897
+ total += consensus_delta_usd;
898
+ }
899
+ if (peer_review_extra_calls > 0) {
900
+ rows.push(
901
+ ` +peer-review: +${peer_review_extra_calls} calls ` +
902
+ `(~+$${_pyFixed(peer_review_delta_usd, 4)})`,
903
+ );
904
+ total += peer_review_delta_usd;
905
+ }
906
+ rows.push(` TOTAL: $${_pyFixed(total, 4)}`);
907
+ return rows.join('\n');
908
+ }
909
+
910
+ interface CostEstimateLike {
911
+ input_tokens: number;
912
+ output_tokens: number;
913
+ input_usd: number;
914
+ output_usd: number;
915
+ }
916
+
917
+ function _total_usd(e: CostEstimateLike): number {
918
+ return e.input_usd + e.output_usd;
919
+ }
920
+
921
+ function _consensus_cost_delta(
922
+ ai_cfg: Dict,
923
+ prompt_mode: string,
924
+ estimates: CostEstimateLike[],
925
+ _n_billable: number,
926
+ ): [number, number] {
927
+ const cs = (ai_cfg['consensus_scoring'] as Dict) || {};
928
+ if (!_pyBool(cs['enabled'])) {
929
+ return [0, 0.0];
930
+ }
931
+ const lenses = (cs['lenses'] as string[]) || ['analysis'];
932
+ if (!lenses.includes(prompt_mode)) {
933
+ return [0, 0.0];
934
+ }
935
+ const extra_calls = 2 * _n_billable;
936
+ const extra_usd = 2.0 * estimates.reduce((acc, e) => acc + _total_usd(e), 0.0);
937
+ return [extra_calls, extra_usd];
938
+ }
939
+
940
+ function _maybe_run_consensus(
941
+ ai_cfg: Dict,
942
+ question: CouncilQuestion,
943
+ members: ExternalAIClient[],
944
+ responses: CouncilResponse[],
945
+ budget: CostBudget,
946
+ table: PriceTable,
947
+ project: unknown,
948
+ args: Args,
949
+ ): ConsensusResult | null {
950
+ const cs = (ai_cfg['consensus_scoring'] as Dict) || {};
951
+ if (!_pyBool(cs['enabled'])) {
952
+ return null;
953
+ }
954
+ const lenses = (cs['lenses'] as string[]) || ['analysis'];
955
+ if (!lenses.includes(question.mode)) {
956
+ return null;
957
+ }
958
+ return run_consensus_scoring(members, responses, {
959
+ budget,
960
+ table,
961
+ project: project as never,
962
+ original_ask: args.original_ask,
963
+ max_tokens: question.max_tokens,
964
+ strong_threshold: _pyFloat(cs['strong_threshold'] ?? 0.7, 0.7),
965
+ minority_threshold: _pyFloat(cs['minority_threshold'] ?? 0.4, 0.4),
966
+ });
967
+ }
968
+
969
+ function _serialise_consensus(consensus: ConsensusResult): Dict {
970
+ const metadata: Dict = {};
971
+ for (const [fid, m] of consensus.metadata) {
972
+ metadata[fid] = {
973
+ mean_score: m.mean_score,
974
+ agreement_rate: (m as unknown as { agreement_rate: number }).agreement_rate,
975
+ consensus_strength: m.consensus_strength,
976
+ dissent_count: m.dissent_count,
977
+ scorers: [...m.scorers],
978
+ concur_count: m.concur_count,
979
+ dissent_reasons: m.dissent_reasons.map((pair) => [...pair]),
980
+ evidence_quality: m.evidence_quality,
981
+ };
982
+ }
983
+ return {
984
+ findings: consensus.findings.map((f) => ({ id: f.id, source: f.source, text: f.text })),
985
+ scores: consensus.scores.map((s) => ({
986
+ finding_id: s.finding_id,
987
+ scorer: s.scorer,
988
+ score: s.score,
989
+ agree: s.agree,
990
+ reason: s.reason,
991
+ })),
992
+ metadata,
993
+ extraction_responses: _serialise_responses(consensus.extraction_responses),
994
+ scoring_responses: _serialise_responses(consensus.scoring_responses),
995
+ };
996
+ }
997
+
998
+ function _decision_replay_settings(ai_cfg: Dict, lens: string): [boolean, boolean] {
999
+ const global_block = (ai_cfg['decision_replay'] as Dict) || {};
1000
+ let enabled: unknown = global_block['enabled'] === undefined ? true : global_block['enabled'];
1001
+ let include_args: unknown =
1002
+ global_block['include_member_arguments'] === undefined
1003
+ ? true
1004
+ : global_block['include_member_arguments'];
1005
+ const lenses = (ai_cfg['lenses'] as Dict) || {};
1006
+ const lens_block = ((lenses[lens] as Dict) || {})['decision_replay'];
1007
+ if (_isDict(lens_block)) {
1008
+ if ('enabled' in lens_block) {
1009
+ enabled = lens_block['enabled'];
1010
+ }
1011
+ if ('include_member_arguments' in lens_block) {
1012
+ include_args = lens_block['include_member_arguments'];
1013
+ }
1014
+ }
1015
+ return [Boolean(_pyBool(enabled)), Boolean(_pyBool(include_args))];
1016
+ }
1017
+
1018
+ function _maybe_write_decision_replay(opts: {
1019
+ ai_cfg: Dict;
1020
+ lens: string;
1021
+ out_path: string;
1022
+ consensus: ConsensusResult | null;
1023
+ deliberation: CouncilResponse[];
1024
+ original_ask: string;
1025
+ }): string | null {
1026
+ const [enabled, include_args] = _decision_replay_settings(opts.ai_cfg, opts.lens);
1027
+ if (!enabled || opts.consensus === null) {
1028
+ return null;
1029
+ }
1030
+ const replay = render_decision_replay(
1031
+ new DecisionReplayInputs({
1032
+ findings: [...opts.consensus.findings],
1033
+ scores: [...opts.consensus.scores],
1034
+ metadata: new Map(opts.consensus.metadata),
1035
+ deliberation: [...opts.deliberation],
1036
+ original_ask: opts.original_ask,
1037
+ include_member_arguments: include_args,
1038
+ }),
1039
+ );
1040
+ const target = path.join(path.dirname(opts.out_path), 'decision-replay.md');
1041
+ fs.mkdirSync(path.dirname(target), { recursive: true });
1042
+ fs.writeFileSync(target, replay, { encoding: 'utf-8' });
1043
+ return target;
1044
+ }
1045
+
1046
+ // ── peer-review ─────────────────────────────────────────────────────
1047
+
1048
+ function _peer_review_active(ai_cfg: Dict, args: Args): boolean {
1049
+ if (_getattr(args, 'peer_review', false)) {
1050
+ return true;
1051
+ }
1052
+ const pr_cfg = (ai_cfg['peer_review'] as Dict) || {};
1053
+ return Boolean(_pyBool(pr_cfg['enabled']));
1054
+ }
1055
+
1056
+ function _peer_review_cost_delta(
1057
+ ai_cfg: Dict,
1058
+ args: Args,
1059
+ estimates: CostEstimateLike[],
1060
+ n_billable: number,
1061
+ ): [number, number] {
1062
+ if (!_peer_review_active(ai_cfg, args)) {
1063
+ return [0, 0.0];
1064
+ }
1065
+ if (n_billable < 2) {
1066
+ return [0, 0.0];
1067
+ }
1068
+ const extra_calls = n_billable;
1069
+ const extra_usd = estimates.reduce((acc, e) => acc + _total_usd(e), 0.0);
1070
+ return [extra_calls, extra_usd];
1071
+ }
1072
+
1073
+ function _maybe_run_peer_review(
1074
+ ai_cfg: Dict,
1075
+ args: Args,
1076
+ question: CouncilQuestion,
1077
+ members: ExternalAIClient[],
1078
+ responses: CouncilResponse[],
1079
+ budget: CostBudget,
1080
+ table: PriceTable,
1081
+ project: unknown,
1082
+ opts: { persona_labels?: Map<string, string> | null } = {},
1083
+ ): PeerReviewResult | null {
1084
+ if (!_peer_review_active(ai_cfg, args)) {
1085
+ return null;
1086
+ }
1087
+ const result = run_peer_review(members, responses, {
1088
+ budget,
1089
+ table,
1090
+ project: project as never,
1091
+ original_ask: args.original_ask,
1092
+ max_tokens: question.max_tokens,
1093
+ persona_labels: opts.persona_labels ?? null,
1094
+ });
1095
+ if (result.responses.length === 0) {
1096
+ return null;
1097
+ }
1098
+ return result;
1099
+ }
1100
+
1101
+ function _serialise_peer_review(peer_review: PeerReviewResult): Dict {
1102
+ return {
1103
+ responses: _serialise_responses(peer_review.responses),
1104
+ label_to_source: _mapToObject(peer_review.label_to_source),
1105
+ persona_labels: _mapToObject(peer_review.persona_labels),
1106
+ };
1107
+ }
1108
+
1109
+ function _deserialise_peer_review(data: Dict | null | undefined): PeerReviewResult | null {
1110
+ if (!_pyBool(data)) {
1111
+ return null;
1112
+ }
1113
+ const d = data as Dict;
1114
+ return new PeerReviewResult({
1115
+ responses: _deserialise_responses((d['responses'] as Dict[]) || []),
1116
+ label_to_source: _objToMap((d['label_to_source'] as Dict) || {}),
1117
+ persona_labels: _objToMap((d['persona_labels'] as Dict) || {}),
1118
+ });
1119
+ }
1120
+
1121
+ function _objToMap(o: Dict): Map<string, string> {
1122
+ const m = new Map<string, string>();
1123
+ for (const [k, v] of Object.entries(o)) {
1124
+ m.set(k, String(v));
1125
+ }
1126
+ return m;
1127
+ }
1128
+
1129
+ // ── round / depth / token resolution ────────────────────────────────
1130
+
1131
+ function _resolve_rounds(args: Args, ai_cfg: Dict): number {
1132
+ if (_getattr<number | null>(args, 'rounds', null) !== null) {
1133
+ return _pyInt(args.rounds);
1134
+ }
1135
+ const min_rounds = _pyInt(ai_cfg['min_rounds'] ?? 2, 2);
1136
+ if (_getattr<string>(args, 'depth', 'standard') === 'deep') {
1137
+ const deep = _pyInt(ai_cfg['deep_min_rounds'] ?? min_rounds, min_rounds);
1138
+ return Math.max(deep, min_rounds);
1139
+ }
1140
+ return min_rounds;
1141
+ }
1142
+
1143
+ function _resolve_max_tokens(args: Args, ai_cfg: Dict): number {
1144
+ const cli = _getattr<number | null>(args, 'max_tokens', null);
1145
+ let value: number;
1146
+ if (cli !== null) {
1147
+ value = _pyInt(cli);
1148
+ } else if ('max_output_tokens' in ai_cfg) {
1149
+ value = _pyInt(ai_cfg['max_output_tokens'] ?? 0, 0);
1150
+ } else {
1151
+ value = DEFAULT_MAX_TOKENS;
1152
+ }
1153
+ if (value <= 0) {
1154
+ return UNLIMITED_TOKENS_FALLBACK;
1155
+ }
1156
+ return value;
1157
+ }
1158
+
1159
+ // ── subcommands ─────────────────────────────────────────────────────
1160
+
1161
+ function cmd_estimate(
1162
+ args: Args,
1163
+ opts: { settings?: Dict | null; members?: ExternalAIClient[] | null; table?: PriceTable | null } = {},
1164
+ ): number {
1165
+ let settings = opts.settings ?? null;
1166
+ let members = opts.members ?? null;
1167
+ let table = opts.table ?? null;
1168
+ if (settings === null) {
1169
+ settings = load_settings();
1170
+ }
1171
+ const ai_cfg = _isDict(settings) ? ((settings['ai_council'] as Dict) || {}) : {};
1172
+ const advisor_plans = _build_advisor_plans(ai_cfg, REPO_ROOT);
1173
+ const explicit_overrides = _parse_model_overrides(_getattr<string[] | null>(args, 'model', null));
1174
+ const skipped: Dict[] = [];
1175
+ if (members === null) {
1176
+ members = build_members(settings, {
1177
+ invocation_mode: args.mode_override,
1178
+ model_overrides: _advisor_model_overrides(advisor_plans, explicit_overrides),
1179
+ siblings_overrides: _parse_siblings_overrides(_getattr<string[] | null>(args, 'siblings', null)),
1180
+ skipped,
1181
+ });
1182
+ }
1183
+ if (table === null) {
1184
+ table = load_prices();
1185
+ }
1186
+ const [question] = build_question({
1187
+ input_path: args.question as string,
1188
+ input_mode: args.input_mode,
1189
+ max_tokens: _resolve_max_tokens(args, ai_cfg),
1190
+ prompt_mode_override: _getattr<string | null>(args, 'prompt_mode', null),
1191
+ });
1192
+ const project = detect_project_context(REPO_ROOT);
1193
+ const billable = members.filter((m) => _getattr(m, 'billable', true));
1194
+ const estimates = estimate(question, billable, table, {
1195
+ project,
1196
+ original_ask: args.original_ask,
1197
+ advisor_plans,
1198
+ });
1199
+ if (_getattr(args, 'debate', false)) {
1200
+ return _emit_debate_estimate(args, ai_cfg, members, billable, estimates, advisor_plans, { skipped });
1201
+ }
1202
+ const [extra_calls, extra_usd] = _consensus_cost_delta(ai_cfg, question.mode, estimates, billable.length);
1203
+ const [pr_extra_calls, pr_extra_usd] = _peer_review_cost_delta(ai_cfg, args, estimates, billable.length);
1204
+ _stdout(
1205
+ `council:estimate · mode=${question.mode} · members=${members.length} ` +
1206
+ `(billable=${billable.length})\n`,
1207
+ );
1208
+ const advisor_summary = _format_advisor_summary(advisor_plans, billable);
1209
+ if (advisor_summary) {
1210
+ _stdout(advisor_summary + '\n');
1211
+ }
1212
+ if (skipped.length > 0) {
1213
+ _stdout(format_install_hints(skipped) + '\n');
1214
+ }
1215
+ _stdout(
1216
+ format_estimate_table(billable, estimates, {
1217
+ consensus_delta_usd: extra_usd,
1218
+ consensus_extra_calls: extra_calls,
1219
+ peer_review_delta_usd: pr_extra_usd,
1220
+ peer_review_extra_calls: pr_extra_calls,
1221
+ }) + '\n',
1222
+ );
1223
+ return 0;
1224
+ }
1225
+
1226
+ function _emit_debate_estimate(
1227
+ args: Args,
1228
+ ai_cfg: Dict,
1229
+ members: ExternalAIClient[],
1230
+ billable: ExternalAIClient[],
1231
+ estimates: CostEstimateLike[],
1232
+ advisor_plans: Map<string, AdvisorPlan>,
1233
+ opts: { skipped?: Dict[] | null } = {},
1234
+ ): number {
1235
+ const skipped = opts.skipped ?? null;
1236
+ const min_rounds = _pyInt(ai_cfg['min_rounds'] ?? 2, 2);
1237
+ const max_rounds_cap = _pyInt(ai_cfg['debate_max_rounds'] ?? 4, 4);
1238
+ const requested = _getattr(args, 'rounds', null) !== null ? _pyInt(args.rounds) : min_rounds;
1239
+ if (requested < 1) {
1240
+ throw new ArgumentTypeError(`--rounds must be >= 1 (got ${requested})`);
1241
+ }
1242
+ if (requested > max_rounds_cap) {
1243
+ throw new ArgumentTypeError(
1244
+ `--rounds=${requested} exceeds debate_max_rounds=${max_rounds_cap}; ` +
1245
+ `raise the cap in ~/.event4u/agent-config/settings/.ai-council.yml or lower --rounds.`,
1246
+ );
1247
+ }
1248
+ const rounds = requested;
1249
+ const per_round_usd = estimates.reduce((acc, e) => acc + _total_usd(e), 0.0);
1250
+ const projected_total = per_round_usd * rounds;
1251
+ _stdout(
1252
+ `council:estimate · mode=debate · members=${members.length} ` +
1253
+ `(billable=${billable.length}) · rounds=${rounds} ` +
1254
+ `(cap=${max_rounds_cap})\n`,
1255
+ );
1256
+ const advisor_summary = _format_advisor_summary(advisor_plans, billable);
1257
+ if (advisor_summary) {
1258
+ _stdout(advisor_summary + '\n');
1259
+ }
1260
+ if (skipped && skipped.length > 0) {
1261
+ _stdout(format_install_hints(skipped) + '\n');
1262
+ }
1263
+ for (let round_idx = 1; round_idx <= rounds; round_idx++) {
1264
+ _stdout(`\nRound ${round_idx} of ${rounds}:\n`);
1265
+ _stdout(format_estimate_table(billable, estimates) + '\n');
1266
+ if (round_idx < rounds) {
1267
+ _stdout(' ' + '─'.repeat(40) + '\n');
1268
+ }
1269
+ }
1270
+ _stdout(`\n PROJECTED TOTAL (${rounds} rounds): $${_pyFixed(projected_total, 4)}\n`);
1271
+ _stdout(
1272
+ ' Note: progressive disclosure may stop the debate early; ' + 'this is an upper bound.\n',
1273
+ );
1274
+ return 0;
1275
+ }
1276
+
1277
+ function _serialise_responses(responses: CouncilResponse[]): Dict[] {
1278
+ const out: Dict[] = [];
1279
+ for (const r of responses) {
1280
+ const metadata: Dict = {};
1281
+ for (const [k, v] of Object.entries(r.metadata || {})) {
1282
+ metadata[k] = String(v);
1283
+ }
1284
+ out.push({
1285
+ provider: r.provider,
1286
+ model: r.model,
1287
+ text: r.text,
1288
+ input_tokens: r.input_tokens,
1289
+ output_tokens: r.output_tokens,
1290
+ latency_ms: r.latency_ms,
1291
+ error: r.error,
1292
+ metadata,
1293
+ });
1294
+ }
1295
+ return out;
1296
+ }
1297
+
1298
+ function _deserialise_responses(items: Dict[]): CouncilResponse[] {
1299
+ const out: CouncilResponse[] = [];
1300
+ for (const d of items) {
1301
+ out.push(
1302
+ new CouncilResponse({
1303
+ provider: (d['provider'] as string) ?? '',
1304
+ model: (d['model'] as string) ?? '',
1305
+ text: (d['text'] as string) ?? '',
1306
+ input_tokens: _pyInt(d['input_tokens'] ?? 0, 0),
1307
+ output_tokens: _pyInt(d['output_tokens'] ?? 0, 0),
1308
+ latency_ms: _pyInt(d['latency_ms'] ?? 0, 0),
1309
+ error: (d['error'] as string | null) ?? null,
1310
+ metadata: (d['metadata'] as Dict) || {},
1311
+ }),
1312
+ );
1313
+ }
1314
+ return out;
1315
+ }
1316
+
1317
+ function _deserialise_consensus(data: Dict | null | undefined): ConsensusResult | null {
1318
+ if (!_pyBool(data)) {
1319
+ return null;
1320
+ }
1321
+ const d = data as Dict;
1322
+ // Lazy import-equivalent — orchestrator/consensus already imported.
1323
+ const findings = ((d['findings'] as Dict[]) || []).map(
1324
+ (f) => new ConsensusFinding(f['id'] as string, f['source'] as string, f['text'] as string),
1325
+ );
1326
+ const scores = ((d['scores'] as Dict[]) || []).map(
1327
+ (s) =>
1328
+ new ConsensusFindingScore(
1329
+ s['finding_id'] as string,
1330
+ s['scorer'] as string,
1331
+ _pyInt(s['score']),
1332
+ Boolean(_pyBool(s['agree'])),
1333
+ (s['reason'] as string) ?? '',
1334
+ ),
1335
+ );
1336
+ const metadata = aggregate_scores(findings, scores);
1337
+ const bucket = bucket_by_threshold(findings, metadata);
1338
+ return new ConsensusResult({
1339
+ bucket,
1340
+ findings,
1341
+ scores,
1342
+ metadata,
1343
+ extraction_responses: _deserialise_responses((d['extraction_responses'] as Dict[]) || []),
1344
+ scoring_responses: _deserialise_responses((d['scoring_responses'] as Dict[]) || []),
1345
+ });
1346
+ }
1347
+
1348
+ function _resolve_necessity_mode(ai_cfg: Dict, lens: string, invocation = 'agent'): [boolean, string] {
1349
+ const nc_block = (ai_cfg['necessity_classifier'] as Dict) || {};
1350
+ const enabled = nc_block['enabled'] === undefined ? true : Boolean(_pyBool(nc_block['enabled']));
1351
+ const lens_overrides = (ai_cfg['lens_overrides'] as Dict) || {};
1352
+ let global_mode: string;
1353
+ let overrides: Dict;
1354
+ if (invocation === 'user_explicit') {
1355
+ global_mode = String(nc_block['user_explicit_mode'] ?? 'warn-only');
1356
+ overrides = (lens_overrides['necessity_classifier_user_explicit_mode'] as Dict) || {};
1357
+ } else {
1358
+ global_mode = String(nc_block['mode'] ?? 'educate');
1359
+ overrides = (lens_overrides['necessity_classifier_mode'] as Dict) || {};
1360
+ }
1361
+ const resolved = lens in overrides ? overrides[lens] : global_mode;
1362
+ return [enabled, String(resolved)];
1363
+ }
1364
+
1365
+ function _provider_caps_snapshot(ai_cfg: Dict): Record<string, Record<string, string>> {
1366
+ const members = (ai_cfg['members'] as Dict) || {};
1367
+ const snapshot: Record<string, Record<string, string>> = {};
1368
+ if (!_isDict(members)) {
1369
+ return snapshot;
1370
+ }
1371
+ for (const [name, cfg] of Object.entries(members)) {
1372
+ if (!_isDict(cfg) || !(cfg['enabled'] === undefined ? true : _pyBool(cfg['enabled']))) {
1373
+ continue;
1374
+ }
1375
+ snapshot[String(name)] = {
1376
+ mode: String(cfg['mode'] ?? ''),
1377
+ model: String(cfg['model'] ?? ''),
1378
+ };
1379
+ }
1380
+ return snapshot;
1381
+ }
1382
+
1383
+ function _necessity_gate(opts: {
1384
+ prompt: string;
1385
+ lens: string;
1386
+ invocation: string;
1387
+ proceed_anyway: boolean;
1388
+ ai_cfg: Dict;
1389
+ stdout?: ((s: string) => void) | null;
1390
+ original_ask?: string;
1391
+ }): [boolean, number, ClassificationResult | null] {
1392
+ const out = opts.stdout ?? _stdout;
1393
+ const [enabled, mode] = _resolve_necessity_mode(opts.ai_cfg, opts.lens, opts.invocation);
1394
+ if (!enabled || mode === 'off') {
1395
+ return [true, 0, null];
1396
+ }
1397
+ const result = classify_necessity(opts.prompt, opts.lens, opts.invocation as never);
1398
+ const caps = _provider_caps_snapshot(opts.ai_cfg);
1399
+ const hashed = (opts.original_ask || '') || opts.prompt;
1400
+
1401
+ const _emit = (action: string): void => {
1402
+ appendEvent({
1403
+ lens: opts.lens,
1404
+ invocation: opts.invocation,
1405
+ action,
1406
+ verdict: result.verdict,
1407
+ category: result.category,
1408
+ mode,
1409
+ provider_caps: caps,
1410
+ original_ask: hashed,
1411
+ });
1412
+ };
1413
+
1414
+ if (result.verdict !== 'unnecessary') {
1415
+ if (result.verdict === 'borderline') {
1416
+ out(
1417
+ `council:necessity · borderline (${result.category}) · ` +
1418
+ `${result.rationale}\n`,
1419
+ );
1420
+ }
1421
+ _emit('proceed');
1422
+ return [true, 0, result];
1423
+ }
1424
+ // verdict === "unnecessary"
1425
+ if (mode === 'warn-only') {
1426
+ out(
1427
+ `council:necessity · warn-only (${result.category}) · ` +
1428
+ `${result.rationale}\n`,
1429
+ );
1430
+ _emit('proceed');
1431
+ return [true, 0, result];
1432
+ }
1433
+ if (mode === 'block') {
1434
+ out(
1435
+ `council:necessity · skipped (${result.category}) · ` +
1436
+ `${result.rationale}\n` +
1437
+ `council:necessity · mode=block — \`--proceed-anyway\` has ` +
1438
+ `no effect on the block path.\n`,
1439
+ );
1440
+ _emit('skip_necessity');
1441
+ return [false, 0, result];
1442
+ }
1443
+ // mode === "educate"
1444
+ if (opts.invocation === 'agent') {
1445
+ out(
1446
+ `council:necessity · skipped (agent, ${result.category}) · ` +
1447
+ `${result.rationale}\n`,
1448
+ );
1449
+ _emit('skip_necessity');
1450
+ return [false, 0, result];
1451
+ }
1452
+ // invocation === "user_explicit"
1453
+ if (opts.proceed_anyway) {
1454
+ out(
1455
+ `council:necessity · override (user_explicit + ` +
1456
+ `--proceed-anyway, ${result.category}) · ` +
1457
+ `${result.rationale}\n`,
1458
+ );
1459
+ _emit('proceed');
1460
+ return [true, 0, result];
1461
+ }
1462
+ out(educate_message(result, opts.lens) + '\n');
1463
+ _emit('skip_necessity');
1464
+ return [false, 2, result];
1465
+ }
1466
+
1467
+ function _resolve_model_downgrade(ai_cfg: Dict, lens: string): [boolean, boolean] {
1468
+ const md_block = (ai_cfg['model_downgrade'] as Dict) || {};
1469
+ let enabled = md_block['enabled'] === undefined ? true : Boolean(_pyBool(md_block['enabled']));
1470
+ let auto_apply = md_block['auto_apply'] === undefined ? false : Boolean(_pyBool(md_block['auto_apply']));
1471
+ const overrides = ((ai_cfg['lens_overrides'] as Dict) || {})['model_downgrade'] || {};
1472
+ const lens_override = _isDict(overrides) ? (overrides as Dict)[lens] : null;
1473
+ if (_isDict(lens_override)) {
1474
+ enabled = lens_override['enabled'] === undefined ? enabled : Boolean(_pyBool(lens_override['enabled']));
1475
+ auto_apply =
1476
+ lens_override['auto_apply'] === undefined ? auto_apply : Boolean(_pyBool(lens_override['auto_apply']));
1477
+ }
1478
+ return [enabled, auto_apply];
1479
+ }
1480
+
1481
+ function _size_fit_gate(opts: {
1482
+ prompt: string;
1483
+ lens: string;
1484
+ members: ExternalAIClient[];
1485
+ ai_cfg: Dict;
1486
+ stdout?: ((s: string) => void) | null;
1487
+ }): Array<[string, SizeFitVerdict, boolean]> {
1488
+ const out = opts.stdout ?? _stdout;
1489
+ const [enabled, auto_apply] = _resolve_model_downgrade(opts.ai_cfg, opts.lens);
1490
+ const decisions: Array<[string, SizeFitVerdict, boolean]> = [];
1491
+ if (!enabled) {
1492
+ return decisions;
1493
+ }
1494
+ const members_cfg = (opts.ai_cfg['members'] as Dict) || {};
1495
+ for (const member of opts.members) {
1496
+ const member_cfg = (members_cfg[member.name] as Dict) || {};
1497
+ const ladder = (member_cfg['model_ladder'] as string[]) || [];
1498
+ if (ladder.length === 0) {
1499
+ continue;
1500
+ }
1501
+ const verdict = classify_size_fit(opts.prompt, member.model, ladder, opts.lens);
1502
+ let applied = false;
1503
+ if (!verdict.fit && verdict.suggested_model) {
1504
+ if (auto_apply) {
1505
+ out(
1506
+ `council:size-fit · ${member.name} · auto-downgrade ` +
1507
+ `\`${member.model}\` → \`${verdict.suggested_model}\` · ` +
1508
+ `${verdict.reason}\n`,
1509
+ );
1510
+ member.model = verdict.suggested_model;
1511
+ applied = true;
1512
+ } else {
1513
+ out(
1514
+ `council:size-fit · ${member.name} · ` +
1515
+ `${downgrade_message(verdict, member.model)}\n`,
1516
+ );
1517
+ }
1518
+ }
1519
+ decisions.push([member.name, verdict, applied]);
1520
+ }
1521
+ return decisions;
1522
+ }
1523
+
1524
+ function _resolve_cost_disclosure(ai_cfg: Dict, lens: string): [string, number, boolean] {
1525
+ const debate_block = (ai_cfg['debate'] as Dict) || {};
1526
+ const debate_disc = (debate_block['cost_disclosure'] as Dict) || {};
1527
+ let mode: string;
1528
+ let threshold: number;
1529
+ let show_per_member: boolean;
1530
+ if (lens === 'debate') {
1531
+ mode = String(debate_disc['mode'] ?? 'always');
1532
+ threshold = _pyFloat(debate_disc['threshold_usd'] ?? 1.0, 1.0);
1533
+ show_per_member = debate_disc['show_per_member'] === undefined ? true : Boolean(_pyBool(debate_disc['show_per_member']));
1534
+ } else {
1535
+ mode = 'off';
1536
+ threshold = 1.0;
1537
+ show_per_member = true;
1538
+ }
1539
+ const overrides = ((ai_cfg['lens_overrides'] as Dict) || {})['cost_disclosure'] || {};
1540
+ const lens_override = _isDict(overrides) ? (overrides as Dict)[lens] : null;
1541
+ if (_isDict(lens_override)) {
1542
+ mode = String(lens_override['mode'] ?? mode);
1543
+ threshold = _pyFloat(lens_override['threshold_usd'] ?? threshold, threshold);
1544
+ show_per_member =
1545
+ lens_override['show_per_member'] === undefined
1546
+ ? show_per_member
1547
+ : Boolean(_pyBool(lens_override['show_per_member']));
1548
+ }
1549
+ return [mode, threshold, show_per_member];
1550
+ }
1551
+
1552
+ function _format_cost_disclosure(
1553
+ est: DebateCostEstimate,
1554
+ opts: { lens: string; show_per_member: boolean },
1555
+ ): string {
1556
+ const { lens, show_per_member } = opts;
1557
+ const lines: string[] = [
1558
+ `council:${lens} · cost-disclosure · estimated ` +
1559
+ `$${_pyFixed(est.low_usd, 4)} – $${_pyFixed(est.high_usd, 4)} ` +
1560
+ `(expected $${_pyFixed(est.expected_usd, 4)}) across ` +
1561
+ `${est.per_member.length} billable members × ${est.rounds} rounds`,
1562
+ ];
1563
+ if (show_per_member && est.per_member.length > 0) {
1564
+ lines.push(' per member:');
1565
+ for (const pm of est.per_member) {
1566
+ lines.push(
1567
+ ` · ${_ljust(String(pm['name']), 14)} ${_ljust(String(pm['model']), 22)} ` +
1568
+ `$${_pyFixed(pm['low_usd'] as number, 4)} – $${_pyFixed(pm['high_usd'] as number, 4)}`,
1569
+ );
1570
+ }
1571
+ }
1572
+ if (est.subscription_members.length > 0) {
1573
+ lines.push(' subscription (no USD spend):');
1574
+ for (const sm of est.subscription_members) {
1575
+ const label = (sm['subscription_label'] as string) || (sm['transport'] as string) || '';
1576
+ lines.push(` · ${_ljust(String(sm['name']), 14)} ${_ljust(String(sm['model']), 22)} (${label})`);
1577
+ }
1578
+ }
1579
+ return lines.join('\n') + '\n';
1580
+ }
1581
+
1582
+ /** Python `str.ljust(width)` — pad with spaces on the right. */
1583
+ function _ljust(s: string, width: number): string {
1584
+ return s.length >= width ? s : s + ' '.repeat(width - s.length);
1585
+ }
1586
+
1587
+ function _debate_refusal_cap(ai_cfg: Dict): number {
1588
+ const debate_block = (ai_cfg['debate'] as Dict) || {};
1589
+ return _pyFloat(debate_block['max_cost_usd'] ?? 5.0, 5.0) || 0.0;
1590
+ }
1591
+
1592
+ function _emit_shadow_slo_banner(): void {
1593
+ try {
1594
+ // Lazy import to mirror Python's in-function import (and to avoid a
1595
+ // load-time dependency on the shadow log path).
1596
+ const sd = _shadow;
1597
+ const [rate, n] = sd.compute_disagreement_rate(sd.SHADOW_LOG_PATH);
1598
+ if (n === 0) {
1599
+ return;
1600
+ }
1601
+ _stdout(sd.slo_banner(rate, n) + '\n');
1602
+ } catch {
1603
+ return;
1604
+ }
1605
+ }
1606
+
1607
+ function _apply_solo_dispatch(members: ExternalAIClient[]): [ExternalAIClient[], string | null] {
1608
+ let cfg: CouncilConfig;
1609
+ try {
1610
+ cfg = load_council_config(AI_COUNCIL_FILE);
1611
+ } catch (exc) {
1612
+ if (exc instanceof CouncilConfigError || _isFileNotFound(exc)) {
1613
+ return [members, null];
1614
+ }
1615
+ throw exc;
1616
+ }
1617
+ if (cfg.routing.solo_member_fallback_chain.length === 0) {
1618
+ return [
1619
+ members,
1620
+ 'council:solo · WARN · --single requested but ' +
1621
+ 'routing.solo_member_fallback_chain is empty — ' +
1622
+ 'escalating to full council.',
1623
+ ];
1624
+ }
1625
+ const runtime_names = new Set(members.map((m) => _getattr(m, 'name', '')));
1626
+ const pick = select_solo_member(cfg.routing, cfg.members, {
1627
+ auth_cache: new AuthCache(),
1628
+ probe: (name: string) => runtime_names.has(name),
1629
+ });
1630
+ if (pick === null) {
1631
+ return [
1632
+ members,
1633
+ 'council:solo · WARN · solo dispatch unavailable ' +
1634
+ '(no chain member runtime-present) — escalating to ' +
1635
+ 'full council.',
1636
+ ];
1637
+ }
1638
+ const filtered = members.filter((m) => _getattr(m, 'name', '') === pick);
1639
+ if (filtered.length === 0) {
1640
+ return [
1641
+ members,
1642
+ 'council:solo · WARN · selected member vanished ' +
1643
+ 'between probe and filter — escalating to full council.',
1644
+ ];
1645
+ }
1646
+ return [
1647
+ filtered,
1648
+ `council:solo · dispatching to ${pick} only ` + `(routing.solo_member_fallback_chain).`,
1649
+ ];
1650
+ }
1651
+
1652
+ function cmd_run(
1653
+ args: Args,
1654
+ opts: { settings?: Dict | null; members?: ExternalAIClient[] | null; table?: PriceTable | null } = {},
1655
+ ): number {
1656
+ let settings = opts.settings ?? null;
1657
+ let members = opts.members ?? null;
1658
+ let table = opts.table ?? null;
1659
+ if (settings === null) {
1660
+ settings = load_settings();
1661
+ }
1662
+ const ai_cfg = _isDict(settings) ? ((settings['ai_council'] as Dict) || {}) : {};
1663
+ const advisor_plans = _build_advisor_plans(ai_cfg, REPO_ROOT);
1664
+ const explicit_overrides = _parse_model_overrides(_getattr<string[] | null>(args, 'model', null));
1665
+ const skipped: Dict[] = [];
1666
+ if (members === null) {
1667
+ members = build_members(settings, {
1668
+ invocation_mode: args.mode_override,
1669
+ model_overrides: _advisor_model_overrides(advisor_plans, explicit_overrides),
1670
+ siblings_overrides: _parse_siblings_overrides(_getattr<string[] | null>(args, 'siblings', null)),
1671
+ skipped,
1672
+ });
1673
+ }
1674
+ if (_getattr(args, 'single', false)) {
1675
+ const [filtered, solo_banner] = _apply_solo_dispatch(members);
1676
+ members = filtered;
1677
+ if (solo_banner) {
1678
+ _stdout(solo_banner + '\n');
1679
+ }
1680
+ _emit_shadow_slo_banner();
1681
+ }
1682
+ if (table === null) {
1683
+ table = load_prices();
1684
+ }
1685
+ const [question, artefact] = build_question({
1686
+ input_path: args.question as string,
1687
+ input_mode: args.input_mode,
1688
+ max_tokens: _resolve_max_tokens(args, ai_cfg),
1689
+ prompt_mode_override: _getattr<string | null>(args, 'prompt_mode', null),
1690
+ });
1691
+ const [proceed, gate_exit] = _necessity_gate({
1692
+ prompt: question.user_prompt,
1693
+ lens: question.mode,
1694
+ invocation: _getattr(args, 'invocation', 'agent'),
1695
+ proceed_anyway: _getattr(args, 'proceed_anyway', false),
1696
+ ai_cfg,
1697
+ original_ask: _getattr(args, 'original_ask', '') || '',
1698
+ });
1699
+ if (!proceed) {
1700
+ return gate_exit;
1701
+ }
1702
+ _size_fit_gate({
1703
+ prompt: question.user_prompt,
1704
+ lens: question.mode,
1705
+ members,
1706
+ ai_cfg,
1707
+ });
1708
+ const project = detect_project_context(REPO_ROOT);
1709
+ const billable = members.filter((m) => _getattr(m, 'billable', true));
1710
+ const estimates = estimate(question, billable, table, {
1711
+ project,
1712
+ original_ask: args.original_ask,
1713
+ advisor_plans,
1714
+ });
1715
+ const [extra_calls, extra_usd] = _consensus_cost_delta(ai_cfg, question.mode, estimates, billable.length);
1716
+ const [pr_extra_calls, pr_extra_usd] = _peer_review_cost_delta(ai_cfg, args, estimates, billable.length);
1717
+ _stdout(
1718
+ `council:run · mode=${question.mode} · members=${members.length} ` +
1719
+ `(billable=${billable.length})\n`,
1720
+ );
1721
+ const advisor_summary = _format_advisor_summary(advisor_plans, billable);
1722
+ if (advisor_summary) {
1723
+ _stdout(advisor_summary + '\n');
1724
+ }
1725
+ if (skipped.length > 0) {
1726
+ _stdout(format_install_hints(skipped) + '\n');
1727
+ }
1728
+ _stdout(
1729
+ format_estimate_table(billable, estimates, {
1730
+ consensus_delta_usd: extra_usd,
1731
+ consensus_extra_calls: extra_calls,
1732
+ peer_review_delta_usd: pr_extra_usd,
1733
+ peer_review_extra_calls: pr_extra_calls,
1734
+ }) + '\n',
1735
+ );
1736
+
1737
+ // Step-8 P1 — pre-run quota summary.
1738
+ const cli_members = members.filter((m) => m instanceof CliClient);
1739
+ const [summary, warn_providers] = quota_summary_line(cli_members as CliClient[]);
1740
+ if (summary) {
1741
+ _stdout(summary + '\n');
1742
+ for (const prov of warn_providers) {
1743
+ _stdout(`council:quota · WARN · ${prov} near limit\n`);
1744
+ }
1745
+ }
1746
+
1747
+ // Phase 8 step 5 — opt-in cost disclosure for non-debate lenses.
1748
+ const [disc_mode, disc_threshold, disc_show] = _resolve_cost_disclosure(ai_cfg, question.mode);
1749
+ if (disc_mode !== 'off') {
1750
+ const run_estimate = estimate_debate_cost(question, members, table, {
1751
+ rounds: 1,
1752
+ project,
1753
+ original_ask: args.original_ask,
1754
+ advisor_plans,
1755
+ });
1756
+ if (disc_mode === 'always' || (disc_mode === 'above_threshold' && run_estimate.expected_usd > disc_threshold)) {
1757
+ _stdout(_format_cost_disclosure(run_estimate, { lens: question.mode, show_per_member: disc_show }));
1758
+ }
1759
+ }
1760
+
1761
+ if (!args.confirm) {
1762
+ _stdout(
1763
+ '\nNo --confirm flag — estimate only. Re-run with --confirm to ' +
1764
+ 'invoke the council and write the response.\n',
1765
+ );
1766
+ return 0;
1767
+ }
1768
+
1769
+ const cost_cfg = (ai_cfg['cost_budget'] as Dict) || {};
1770
+ const budget = new CostBudget({
1771
+ max_input_tokens: _pyInt(cost_cfg['max_input_tokens'] ?? 50_000, 50_000),
1772
+ max_output_tokens: _pyInt(cost_cfg['max_output_tokens'] ?? 20_000, 20_000),
1773
+ max_calls: _pyInt(cost_cfg['max_calls'] ?? 10, 10),
1774
+ max_total_usd: _pyFloat(cost_cfg['max_total_usd'] ?? 0.0, 0.0) || 0.0,
1775
+ });
1776
+ const rounds = _resolve_rounds(args, ai_cfg);
1777
+ const responses = consult(members, question, budget, {
1778
+ table,
1779
+ project,
1780
+ original_ask: args.original_ask,
1781
+ rounds,
1782
+ advisor_plans,
1783
+ });
1784
+ const persona_labels = build_persona_labels(advisor_plans, billable);
1785
+ const peer_review = _maybe_run_peer_review(
1786
+ ai_cfg,
1787
+ args,
1788
+ question,
1789
+ members,
1790
+ responses,
1791
+ budget,
1792
+ table,
1793
+ project,
1794
+ { persona_labels },
1795
+ );
1796
+ const consensus = _maybe_run_consensus(ai_cfg, question, members, responses, budget, table, project, args);
1797
+ const estimated_total = estimates.reduce((acc, e) => acc + _total_usd(e), 0.0);
1798
+ let actual_total = 0.0;
1799
+ const all_responses: CouncilResponse[] = [...responses];
1800
+ if (peer_review !== null) {
1801
+ all_responses.push(...peer_review.responses);
1802
+ }
1803
+ if (consensus !== null) {
1804
+ all_responses.push(...consensus.extraction_responses);
1805
+ all_responses.push(...consensus.scoring_responses);
1806
+ }
1807
+ for (const r of all_responses) {
1808
+ if (r.error) {
1809
+ continue;
1810
+ }
1811
+ const ce = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table);
1812
+ actual_total += ce.input_usd + ce.output_usd;
1813
+ }
1814
+ const payload: Dict = {
1815
+ schema_version: SCHEMA_VERSION,
1816
+ mode: question.mode,
1817
+ prompt_mode: _getattr<string | null>(args, 'prompt_mode', null),
1818
+ prose_synthesis: _getattr<boolean | null>(args, 'prose_synthesis', null),
1819
+ peer_review_enabled: _peer_review_active(ai_cfg, args),
1820
+ artefact,
1821
+ original_ask: args.original_ask,
1822
+ members: members.map((m) => `${m.name}/${m.model}`),
1823
+ rounds,
1824
+ cost_usd_estimated: _pyRound(estimated_total, 6),
1825
+ cost_usd_actual: _pyRound(actual_total, 6),
1826
+ responses: _serialise_responses(responses),
1827
+ };
1828
+ if (peer_review !== null) {
1829
+ payload['peer_review'] = _serialise_peer_review(peer_review);
1830
+ }
1831
+ if (consensus !== null) {
1832
+ payload['consensus'] = _serialise_consensus(consensus);
1833
+ }
1834
+ const out_path = _validate_council_output_path(args.output as string, {
1835
+ kind: 'responses',
1836
+ subcommand: 'run',
1837
+ });
1838
+ fs.mkdirSync(path.dirname(_resolveTarget(out_path)), { recursive: true });
1839
+ fs.writeFileSync(_resolveTarget(out_path), _jsonDumpsIndent2(payload) + '\n', { encoding: 'utf-8' });
1840
+ _stdout(
1841
+ `\ncouncil:run · wrote ${out_path} ` +
1842
+ `(estimated $${_pyFixed(estimated_total, 4)} / actual $${_pyFixed(actual_total, 4)})\n`,
1843
+ );
1844
+ const replay_path = _maybe_write_decision_replay({
1845
+ ai_cfg,
1846
+ lens: question.mode,
1847
+ out_path: _resolveTarget(out_path),
1848
+ consensus,
1849
+ deliberation: responses,
1850
+ original_ask: args.original_ask,
1851
+ });
1852
+ if (replay_path !== null) {
1853
+ _stdout(`council:run · wrote ${replay_path}\n`);
1854
+ }
1855
+ const errors = responses.filter((r) => r.error);
1856
+ return errors.length > 0 && errors.length === responses.length ? 1 : 0;
1857
+ }
1858
+
1859
+ function _debate_round_filename(round_number: number): string {
1860
+ return `debate-round-${round_number}.json`;
1861
+ }
1862
+
1863
+ function _write_debate_round(
1864
+ out_dir: string,
1865
+ round_number: number,
1866
+ responses: CouncilResponse[],
1867
+ opts: {
1868
+ question: CouncilQuestion;
1869
+ members: ExternalAIClient[];
1870
+ artefact: string;
1871
+ original_ask: string;
1872
+ total_planned_rounds: number;
1873
+ table: PriceTable;
1874
+ prompt_mode: string | null;
1875
+ prose_synthesis: boolean | null;
1876
+ },
1877
+ ): string {
1878
+ fs.mkdirSync(_resolveTarget(out_dir), { recursive: true });
1879
+ let actual_total = 0.0;
1880
+ for (const r of responses) {
1881
+ if (r.error) {
1882
+ continue;
1883
+ }
1884
+ const ce = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, opts.table);
1885
+ actual_total += ce.input_usd + ce.output_usd;
1886
+ }
1887
+ const payload: Dict = {
1888
+ schema_version: SCHEMA_VERSION,
1889
+ mode: opts.question.mode,
1890
+ prompt_mode: opts.prompt_mode,
1891
+ prose_synthesis: opts.prose_synthesis,
1892
+ artefact: opts.artefact,
1893
+ original_ask: opts.original_ask,
1894
+ members: opts.members.map((m) => `${m.name}/${m.model}`),
1895
+ debate_round: round_number,
1896
+ debate_total_rounds: opts.total_planned_rounds,
1897
+ rounds: 1,
1898
+ cost_usd_actual: _pyRound(actual_total, 6),
1899
+ responses: _serialise_responses(responses),
1900
+ };
1901
+ const out_path = path.join(_resolveTarget(out_dir), _debate_round_filename(round_number));
1902
+ fs.writeFileSync(out_path, _jsonDumpsIndent2(payload) + '\n', { encoding: 'utf-8' });
1903
+ return out_path;
1904
+ }
1905
+
1906
+ function _load_debate_seed(p: string, expected_members: ExternalAIClient[]): CouncilResponse[] {
1907
+ if (!fs.existsSync(p)) {
1908
+ throw new FileNotFoundError(`--continue-as-debate path not found: ${p}`);
1909
+ }
1910
+ const payload = JSON.parse(fs.readFileSync(p, 'utf-8')) as Dict;
1911
+ const source_members = ((payload['members'] as string[]) || []).slice();
1912
+ const expected_labels = expected_members.map((m) => `${m.name}/${m.model}`);
1913
+ if (!_listEq(source_members, expected_labels)) {
1914
+ throw new CouncilDisabledError(
1915
+ `--continue-as-debate member mismatch: source session has ` +
1916
+ `${_pyReprStrList(source_members)}, current invocation has ${_pyReprStrList(expected_labels)}. ` +
1917
+ `Re-run with matching members or drop --continue-as-debate.`,
1918
+ );
1919
+ }
1920
+ return _deserialise_responses((payload['responses'] as Dict[]) || []);
1921
+ }
1922
+
1923
+ function _listEq(a: string[], b: string[]): boolean {
1924
+ if (a.length !== b.length) {
1925
+ return false;
1926
+ }
1927
+ return a.every((v, i) => v === b[i]);
1928
+ }
1929
+
1930
+ function _make_debate_continue_prompt(opts: {
1931
+ auto_continue: boolean;
1932
+ stream?: ((s: string) => void) | null;
1933
+ }): DebateContinueCallback | null {
1934
+ if (opts.auto_continue) {
1935
+ return null;
1936
+ }
1937
+ const out = opts.stream ?? _stdout;
1938
+ const _prompt = (checkpoint: DebateCheckpoint): boolean => {
1939
+ out(
1940
+ `\ndebate:checkpoint round=${checkpoint.completed_round}/` +
1941
+ `${checkpoint.total_planned_rounds} ` +
1942
+ `cost_so_far=$${_pyFixed(checkpoint.cost_so_far_usd, 4)} ` +
1943
+ `next_round_estimate=$${_pyFixed(checkpoint.next_round_estimate_usd, 4)} ` +
1944
+ `— continue? [y/N]: `,
1945
+ );
1946
+ // Non-interactive: a blank/EOF stdin read is treated as "N".
1947
+ const answer = _readStdinLine();
1948
+ return answer === 'y' || answer === 'yes';
1949
+ };
1950
+ return _prompt;
1951
+ }
1952
+
1953
+ type DebateContinueCallback = (checkpoint: DebateCheckpoint) => boolean;
1954
+
1955
+ function _readStdinLine(): string {
1956
+ try {
1957
+ const buf = Buffer.alloc(4096);
1958
+ const fd = 0;
1959
+ const n = fs.readSync(fd, buf, 0, buf.length, null);
1960
+ return buf.toString('utf-8', 0, n).split('\n')[0]?.trim().toLowerCase() ?? '';
1961
+ } catch {
1962
+ return '';
1963
+ }
1964
+ }
1965
+
1966
+ function cmd_debate(
1967
+ args: Args,
1968
+ opts: { settings?: Dict | null; members?: ExternalAIClient[] | null; table?: PriceTable | null } = {},
1969
+ ): number {
1970
+ let settings = opts.settings ?? null;
1971
+ let members = opts.members ?? null;
1972
+ let table = opts.table ?? null;
1973
+ if (settings === null) {
1974
+ settings = load_settings();
1975
+ }
1976
+ const ai_cfg = _isDict(settings) ? ((settings['ai_council'] as Dict) || {}) : {};
1977
+ const advisor_plans = _build_advisor_plans(ai_cfg, REPO_ROOT);
1978
+ const explicit_overrides = _parse_model_overrides(_getattr<string[] | null>(args, 'model', null));
1979
+ const skipped: Dict[] = [];
1980
+ if (members === null) {
1981
+ members = build_members(settings, {
1982
+ invocation_mode: args.mode_override,
1983
+ model_overrides: _advisor_model_overrides(advisor_plans, explicit_overrides),
1984
+ siblings_overrides: _parse_siblings_overrides(_getattr<string[] | null>(args, 'siblings', null)),
1985
+ skipped,
1986
+ });
1987
+ }
1988
+ if (table === null) {
1989
+ table = load_prices();
1990
+ }
1991
+ const [question, artefact] = build_question({
1992
+ input_path: args.question as string,
1993
+ input_mode: args.input_mode,
1994
+ max_tokens: _resolve_max_tokens(args, ai_cfg),
1995
+ prompt_mode_override: 'debate',
1996
+ });
1997
+ const [proceed, gate_exit] = _necessity_gate({
1998
+ prompt: question.user_prompt,
1999
+ lens: 'debate',
2000
+ invocation: _getattr(args, 'invocation', 'agent'),
2001
+ proceed_anyway: _getattr(args, 'proceed_anyway', false),
2002
+ ai_cfg,
2003
+ original_ask: _getattr(args, 'original_ask', '') || '',
2004
+ });
2005
+ if (!proceed) {
2006
+ return gate_exit;
2007
+ }
2008
+ _size_fit_gate({ prompt: question.user_prompt, lens: 'debate', members, ai_cfg });
2009
+ const project = detect_project_context(REPO_ROOT);
2010
+ const billable = members.filter((m) => _getattr(m, 'billable', true));
2011
+
2012
+ const max_rounds_cap = _pyInt(ai_cfg['debate_max_rounds'] ?? 4, 4);
2013
+ const requested = _getattr(args, 'rounds', null) !== null ? _pyInt(args.rounds) : 2;
2014
+ if (requested < 1) {
2015
+ throw new ArgumentTypeError(`--rounds must be >= 1 (got ${requested})`);
2016
+ }
2017
+ if (requested > max_rounds_cap) {
2018
+ throw new ArgumentTypeError(
2019
+ `--rounds=${requested} exceeds debate_max_rounds=${max_rounds_cap}; ` +
2020
+ `raise the cap in ~/.event4u/agent-config/settings/.ai-council.yml or lower --rounds.`,
2021
+ );
2022
+ }
2023
+ const rounds = requested;
2024
+
2025
+ const estimates = estimate(question, billable, table, {
2026
+ project,
2027
+ original_ask: args.original_ask,
2028
+ advisor_plans,
2029
+ });
2030
+ const per_round_usd = estimates.reduce((acc, e) => acc + _total_usd(e), 0.0);
2031
+ const projected_total = per_round_usd * rounds;
2032
+ _stdout(
2033
+ `council:debate · members=${members.length} (billable=${billable.length}) ` +
2034
+ `· rounds=${rounds} (cap=${max_rounds_cap})\n`,
2035
+ );
2036
+ const advisor_summary = _format_advisor_summary(advisor_plans, billable);
2037
+ if (advisor_summary) {
2038
+ _stdout(advisor_summary + '\n');
2039
+ }
2040
+ if (skipped.length > 0) {
2041
+ _stdout(format_install_hints(skipped) + '\n');
2042
+ }
2043
+ _stdout(format_estimate_table(billable, estimates) + '\n');
2044
+ _stdout(
2045
+ ` × ${rounds} rounds (worst case, before progressive disclosure)\n` +
2046
+ ` PROJECTED TOTAL: $${_pyFixed(projected_total, 4)}\n`,
2047
+ );
2048
+
2049
+ const debate_estimate = estimate_debate_cost(question, members, table, {
2050
+ rounds,
2051
+ project,
2052
+ original_ask: args.original_ask,
2053
+ advisor_plans,
2054
+ });
2055
+ const [disc_mode, disc_threshold, disc_show] = _resolve_cost_disclosure(ai_cfg, 'debate');
2056
+ const should_disclose =
2057
+ disc_mode === 'always' || (disc_mode === 'above_threshold' && debate_estimate.expected_usd > disc_threshold);
2058
+ if (should_disclose) {
2059
+ _stdout(_format_cost_disclosure(debate_estimate, { lens: 'debate', show_per_member: disc_show }));
2060
+ }
2061
+ const cap = _debate_refusal_cap(ai_cfg);
2062
+ if (cap > 0 && debate_estimate.high_usd > cap) {
2063
+ _stderr(
2064
+ `❌ council:debate refused · high-end estimate ` +
2065
+ `$${_pyFixed(debate_estimate.high_usd, 4)} exceeds ` +
2066
+ `debate.max_cost_usd=$${_pyFixed(cap, 2)}. Lower --rounds, drop ` +
2067
+ `members, or raise the cap in ~/.event4u/agent-config/settings/.ai-council.yml.\n`,
2068
+ );
2069
+ return 4;
2070
+ }
2071
+
2072
+ if (!args.confirm) {
2073
+ _stdout(
2074
+ '\nNo --confirm flag — estimate only. Re-run with --confirm to ' + 'start the debate.\n',
2075
+ );
2076
+ return 0;
2077
+ }
2078
+
2079
+ const cost_cfg = (ai_cfg['cost_budget'] as Dict) || {};
2080
+ const budget = new CostBudget({
2081
+ max_input_tokens: _pyInt(cost_cfg['max_input_tokens'] ?? 50_000, 50_000),
2082
+ max_output_tokens: _pyInt(cost_cfg['max_output_tokens'] ?? 20_000, 20_000),
2083
+ max_calls: _pyInt(cost_cfg['max_calls'] ?? 10, 10),
2084
+ max_total_usd: _pyFloat(cost_cfg['max_total_usd'] ?? 0.0, 0.0) || 0.0,
2085
+ });
2086
+
2087
+ const out_dir = _validate_council_output_path(args.output as string, {
2088
+ kind: 'responses',
2089
+ subcommand: 'debate',
2090
+ });
2091
+ let seed: CouncilResponse[] | null = null;
2092
+ if (_getattr(args, 'continue_as_debate', null)) {
2093
+ seed = _load_debate_seed(args.continue_as_debate as string, billable);
2094
+ _stdout(
2095
+ `council:debate · seeding round 1 from ` +
2096
+ `${args.continue_as_debate} (${seed.length} responses)\n`,
2097
+ );
2098
+ }
2099
+
2100
+ const written: string[] = [];
2101
+
2102
+ const _on_round_complete = (round_number: number, results: CouncilResponse[]): void => {
2103
+ const p = _write_debate_round(out_dir, round_number, results, {
2104
+ question,
2105
+ members: members as ExternalAIClient[],
2106
+ artefact,
2107
+ original_ask: args.original_ask,
2108
+ total_planned_rounds: rounds,
2109
+ table: table as PriceTable,
2110
+ prompt_mode: 'debate',
2111
+ prose_synthesis: _getattr<boolean | null>(args, 'prose_synthesis', null),
2112
+ });
2113
+ written.push(p);
2114
+ const errors = results.filter((r) => r.error);
2115
+ _stdout(`council:debate · wrote ${p} ` + `(${results.length - errors.length}/${results.length} ok)\n`);
2116
+ };
2117
+
2118
+ const on_continue = _make_debate_continue_prompt({
2119
+ auto_continue: Boolean(_getattr(args, 'auto_continue', false)),
2120
+ });
2121
+
2122
+ let all_rounds: CouncilResponse[][];
2123
+ try {
2124
+ all_rounds = run_debate(members, question, {
2125
+ budget,
2126
+ table,
2127
+ project,
2128
+ original_ask: args.original_ask,
2129
+ max_rounds: rounds,
2130
+ on_round_complete: _on_round_complete,
2131
+ on_continue,
2132
+ advisor_plans,
2133
+ seed_round_1: seed,
2134
+ });
2135
+ } catch (exc) {
2136
+ if (exc instanceof DebateCapExceeded) {
2137
+ _stderr(
2138
+ `❌ council:debate cap reached after round ${exc.completed_round}: ` +
2139
+ `${exc.message}\n` +
2140
+ `Partial debate persisted under ${out_dir} ` +
2141
+ `(${written.length} rounds).\n`,
2142
+ );
2143
+ return 3;
2144
+ }
2145
+ throw exc;
2146
+ }
2147
+
2148
+ let actual_total = 0.0;
2149
+ for (const rnd of all_rounds) {
2150
+ for (const r of rnd) {
2151
+ if (r.error) {
2152
+ continue;
2153
+ }
2154
+ const ce = estimate_cost(r.provider, r.model, r.input_tokens, r.output_tokens, table);
2155
+ actual_total += ce.input_usd + ce.output_usd;
2156
+ }
2157
+ }
2158
+ _stdout(
2159
+ `\ncouncil:debate · ${all_rounds.length} round(s) complete · ` +
2160
+ `actual $${_pyFixed(actual_total, 4)} (cap projection $${_pyFixed(projected_total, 4)})\n`,
2161
+ );
2162
+ const last = all_rounds.length > 0 ? (all_rounds[all_rounds.length - 1] as CouncilResponse[]) : [];
2163
+ const errors_last = last.filter((r) => r.error);
2164
+ return errors_last.length > 0 && errors_last.length === last.length ? 1 : 0;
2165
+ }
2166
+
2167
+ function cmd_render(args: Args): number {
2168
+ const payload = JSON.parse(fs.readFileSync(args.responses as string, 'utf-8')) as Dict;
2169
+ const items = (payload['responses'] as Dict[]) || [];
2170
+ const explicit = _getattr<string | null>(args, 'prompt_mode', null);
2171
+ const mode = explicit || (payload['prompt_mode'] as string | null) || (payload['mode'] as string | null);
2172
+ let prose = _getattr<boolean | null>(args, 'prose_synthesis', null);
2173
+ if (prose === null) {
2174
+ prose = (payload['prose_synthesis'] as boolean | null) ?? null;
2175
+ }
2176
+ const consensus = _deserialise_consensus(payload['consensus'] as Dict);
2177
+ const peer_review = _deserialise_peer_review(payload['peer_review'] as Dict);
2178
+ const body = render(_deserialise_responses(items), {
2179
+ mode: mode ?? null,
2180
+ prose_synthesis: prose,
2181
+ consensus,
2182
+ peer_review,
2183
+ });
2184
+ if (_getattr<string | null>(args, 'output', null)) {
2185
+ const out_path = _validate_council_output_path(args.output as string, {
2186
+ kind: 'sessions',
2187
+ subcommand: 'render',
2188
+ });
2189
+ fs.mkdirSync(path.dirname(_resolveTarget(out_path)), { recursive: true });
2190
+ fs.writeFileSync(_resolveTarget(out_path), body + '\n', { encoding: 'utf-8' });
2191
+ _stdout(`council:render · wrote ${out_path}\n`);
2192
+ return 0;
2193
+ }
2194
+ _stdout(body + '\n');
2195
+ return 0;
2196
+ }
2197
+
2198
+ function _cmd_replay_low_impact_stats(args: Args): number {
2199
+ const li = _lowimpact;
2200
+ const responses_path = args.responses as string;
2201
+ const log_path = path.join(path.dirname(responses_path), 'low-impact-resolutions.md');
2202
+ if (!fs.existsSync(log_path)) {
2203
+ _stdout(
2204
+ 'council:replay · no low-impact-resolutions.md alongside ' +
2205
+ `${responses_path} — session had no fast-path entries.\n`,
2206
+ );
2207
+ return 0;
2208
+ }
2209
+ const body = fs.readFileSync(log_path, 'utf-8');
2210
+ const stats = li.parse_low_impact_log(body);
2211
+ const out = li.render_low_impact_stats(stats);
2212
+ if (_getattr<string | null>(args, 'output', null)) {
2213
+ const target = _validate_council_output_path(args.output as string, {
2214
+ kind: 'sessions',
2215
+ subcommand: 'replay',
2216
+ });
2217
+ fs.mkdirSync(path.dirname(_resolveTarget(target)), { recursive: true });
2218
+ fs.writeFileSync(_resolveTarget(target), out, { encoding: 'utf-8' });
2219
+ _stdout(`council:replay · wrote ${target}\n`);
2220
+ return 0;
2221
+ }
2222
+ _stdout(out);
2223
+ return 0;
2224
+ }
2225
+
2226
+ function cmd_replay(args: Args): number {
2227
+ if (_getattr(args, 'low_impact_stats', false)) {
2228
+ return _cmd_replay_low_impact_stats(args);
2229
+ }
2230
+ const payload = JSON.parse(fs.readFileSync(args.responses as string, 'utf-8')) as Dict;
2231
+ const consensus = _deserialise_consensus(payload['consensus'] as Dict);
2232
+ if (consensus === null) {
2233
+ _stderr(
2234
+ '❌ council:replay: payload has no `consensus` block — ' +
2235
+ 'rerun with consensus_scoring enabled for this lens.\n',
2236
+ );
2237
+ return 2;
2238
+ }
2239
+ const deliberation = _deserialise_responses((payload['responses'] as Dict[]) || []);
2240
+ const include_args =
2241
+ args.include_member_arguments !== null && args.include_member_arguments !== undefined
2242
+ ? Boolean(args.include_member_arguments)
2243
+ : true;
2244
+ const body = render_decision_replay(
2245
+ new DecisionReplayInputs({
2246
+ findings: [...consensus.findings],
2247
+ scores: [...consensus.scores],
2248
+ metadata: new Map(consensus.metadata),
2249
+ deliberation,
2250
+ original_ask: String(payload['original_ask'] ?? ''),
2251
+ include_member_arguments: include_args,
2252
+ }),
2253
+ );
2254
+ if (_getattr<string | null>(args, 'output', null)) {
2255
+ const out_path = _validate_council_output_path(args.output as string, {
2256
+ kind: 'sessions',
2257
+ subcommand: 'replay',
2258
+ });
2259
+ fs.mkdirSync(path.dirname(_resolveTarget(out_path)), { recursive: true });
2260
+ fs.writeFileSync(_resolveTarget(out_path), body, { encoding: 'utf-8' });
2261
+ _stdout(`council:replay · wrote ${out_path}\n`);
2262
+ } else {
2263
+ _stdout(body);
2264
+ }
2265
+ return 0;
2266
+ }
2267
+
2268
+ function cmd_shadow_report(args: Args): number {
2269
+ const sd = _shadow;
2270
+ const log_path = args.log ? args.log : sd.SHADOW_LOG_PATH;
2271
+ const [rate, n] = sd.compute_disagreement_rate(log_path, { windowDays: _pyInt(args.window_days, 7) });
2272
+ _stdout(sd.slo_banner(rate, n) + '\n');
2273
+ return 0;
2274
+ }
2275
+
2276
+ function cmd_quota(args: Args, opts: { settings?: Dict | null } = {}): number {
2277
+ const s = opts.settings !== undefined && opts.settings !== null ? opts.settings : load_settings();
2278
+ const ai_cfg = _isDict(s) ? ((s['ai_council'] as Dict) || {}) : {};
2279
+ const cli_budget_cfg = _isDict(ai_cfg) ? ((ai_cfg['cli_call_budget'] as Dict) || {}) : {};
2280
+ const caps = _isDict(cli_budget_cfg) ? ((cli_budget_cfg['max_calls_per_day'] as Dict) || {}) : {};
2281
+ const warn_at = _isDict(cli_budget_cfg) ? _pyFloat(cli_budget_cfg['warn_at'] ?? 0.8, 0.8) : 0.8;
2282
+
2283
+ if (_getattr<string | null>(args, 'reset', null)) {
2284
+ const provider = args.reset as string;
2285
+ if (!_getattr(args, 'confirm', false)) {
2286
+ _stderr(`❌ council:quota: --reset ${provider} requires --confirm.\n`);
2287
+ return 2;
2288
+ }
2289
+ reset_cli_call_counts(provider);
2290
+ _stdout(`council:quota · reset · ${provider}\n`);
2291
+ return 0;
2292
+ }
2293
+
2294
+ const counts = load_cli_call_counts();
2295
+ if (Object.keys(caps).length === 0) {
2296
+ _stdout(
2297
+ 'council:quota · no providers have a configured ' +
2298
+ 'cli_call_budget.max_calls_per_day cap.\n',
2299
+ );
2300
+ return 0;
2301
+ }
2302
+ for (const provider of _pySortedStr(Object.keys(caps))) {
2303
+ const limit = _pyInt(caps[provider]);
2304
+ const used = _pyInt(counts[provider] ?? 0, 0);
2305
+ const ratio = limit > 0 ? used / limit : 0.0;
2306
+ let status = 'ok';
2307
+ if (used >= limit) {
2308
+ status = 'exhausted';
2309
+ } else if (ratio >= warn_at) {
2310
+ status = 'warn';
2311
+ }
2312
+ _stdout(`council:quota · ${provider} · ${used}/${limit} · ${status}\n`);
2313
+ }
2314
+ return 0;
2315
+ }
2316
+
2317
+ // ── output-path validation ──────────────────────────────────────────
2318
+
2319
+ function _validate_council_output_path(
2320
+ path_str: string,
2321
+ opts: { kind: string; subcommand: string },
2322
+ ): string {
2323
+ const expected_rel = COUNCIL_CANONICAL_DIRS[opts.kind] as string;
2324
+ const expected_abs = _resolveReal(path.join(REPO_ROOT, expected_rel));
2325
+ const target = path.isAbsolute(path_str) ? path_str : path.join(REPO_ROOT, path_str);
2326
+ const target_resolved = _resolveReal(target);
2327
+ if (!_isRelativeTo(target_resolved, expected_abs)) {
2328
+ throw new ArgumentTypeError(
2329
+ `council:${opts.subcommand} --output must live under ` +
2330
+ `${expected_rel}/ (per ai-council § Output path convention); ` +
2331
+ `got ${_pyReprStr(path_str)}.`,
2332
+ );
2333
+ }
2334
+ // Python returns the original `Path(path_str)` (unresolved).
2335
+ return path_str;
2336
+ }
2337
+
2338
+ /**
2339
+ * Resolve `--output` to the on-disk write target. The validator returns
2340
+ * the original (possibly relative) string for echo; writes anchor it to
2341
+ * `REPO_ROOT` when relative, mirroring Python `Path(path_str)` semantics
2342
+ * under the CLI's cwd-at-REPO_ROOT contract.
2343
+ */
2344
+ function _resolveTarget(path_str: string): string {
2345
+ return path.isAbsolute(path_str) ? path_str : path.join(REPO_ROOT, path_str);
2346
+ }
2347
+
2348
+ /** Python `Path.resolve()` — best-effort realpath, falls back to absolute. */
2349
+ function _resolveReal(p: string): string {
2350
+ const abs = path.resolve(p);
2351
+ try {
2352
+ return fs.realpathSync(abs);
2353
+ } catch {
2354
+ return abs;
2355
+ }
2356
+ }
2357
+
2358
+ /** Python `Path.relative_to` membership test (raises ValueError on failure). */
2359
+ function _isRelativeTo(target: string, base: string): boolean {
2360
+ if (target === base) {
2361
+ return true;
2362
+ }
2363
+ const rel = path.relative(base, target);
2364
+ return rel !== '' && !rel.startsWith('..') && !path.isAbsolute(rel);
2365
+ }
2366
+
2367
+ // ── argparse parsing ────────────────────────────────────────────────
2368
+
2369
+ class FileNotFoundError extends Error {}
2370
+
2371
+ interface Args {
2372
+ cmd: string | null;
2373
+ question?: string | null;
2374
+ input_mode: string;
2375
+ prompt_mode: string | null;
2376
+ max_tokens: number | null;
2377
+ mode_override: string | null;
2378
+ model: string[] | null;
2379
+ siblings: string[] | null;
2380
+ original_ask: string;
2381
+ peer_review: boolean;
2382
+ // run / debate
2383
+ output?: string | null;
2384
+ confirm: boolean;
2385
+ rounds: number | null;
2386
+ depth: string;
2387
+ invocation: string;
2388
+ proceed_anyway: boolean;
2389
+ single: boolean;
2390
+ prose_synthesis: boolean | null;
2391
+ auto_continue: boolean;
2392
+ continue_as_debate: string | null;
2393
+ // render / replay
2394
+ responses?: string | null;
2395
+ include_member_arguments: boolean | null;
2396
+ low_impact_stats: boolean;
2397
+ // quota
2398
+ reset: string | null;
2399
+ // shadow-report
2400
+ log: string | null;
2401
+ window_days: number;
2402
+ }
2403
+
2404
+ const _SUBCOMMANDS = ['estimate', 'run', 'debate', 'render', 'replay', 'quota', 'shadow-report'];
2405
+
2406
+ const _TOP_USAGE =
2407
+ `usage: ${_PROG} [-h]\n` +
2408
+ ` {estimate,run,debate,render,replay,quota,shadow-report}\n` +
2409
+ ` ...\n`;
2410
+
2411
+ function _topError(message: string): never {
2412
+ _stderr(_TOP_USAGE);
2413
+ _stderr(`${_PROG}: error: ${message}\n`);
2414
+ process.exitCode = 2;
2415
+ throw new _ArgExit();
2416
+ }
2417
+
2418
+ function _subError(action: string, usage: string, message: string): never {
2419
+ _stderr(usage);
2420
+ _stderr(`${_PROG} ${action}: error: ${message}\n`);
2421
+ process.exitCode = 2;
2422
+ throw new _ArgExit();
2423
+ }
2424
+
2425
+ function _defaultArgs(): Args {
2426
+ return {
2427
+ cmd: null,
2428
+ question: null,
2429
+ input_mode: 'prompt',
2430
+ prompt_mode: null,
2431
+ max_tokens: null,
2432
+ mode_override: null,
2433
+ model: null,
2434
+ siblings: null,
2435
+ original_ask: '',
2436
+ peer_review: false,
2437
+ output: null,
2438
+ confirm: false,
2439
+ rounds: null,
2440
+ depth: 'standard',
2441
+ invocation: 'agent',
2442
+ proceed_anyway: false,
2443
+ single: false,
2444
+ prose_synthesis: null,
2445
+ auto_continue: false,
2446
+ continue_as_debate: null,
2447
+ responses: null,
2448
+ include_member_arguments: null,
2449
+ low_impact_stats: false,
2450
+ reset: null,
2451
+ log: null,
2452
+ window_days: 7,
2453
+ };
2454
+ }
2455
+
2456
+ /** Per-subcommand usage lines (first line only is asserted in tests). */
2457
+ function _usageFor(cmd: string): string {
2458
+ return `usage: ${_PROG} ${cmd} [-h] ...\n`;
2459
+ }
2460
+
2461
+ interface OptSpec {
2462
+ flag: string;
2463
+ takesValue: boolean;
2464
+ choices?: string[] | null;
2465
+ isInt?: boolean;
2466
+ apply: (out: Args, value: string | null) => void;
2467
+ }
2468
+
2469
+ function _commonInputSpecs(): OptSpec[] {
2470
+ return [
2471
+ { flag: '--input-mode', takesValue: true, choices: ['prompt', 'roadmap'], apply: (o, v) => (o.input_mode = v as string) },
2472
+ { flag: '--prompt-mode', takesValue: true, choices: ['pr', 'design', 'optimize', 'analysis'], apply: (o, v) => (o.prompt_mode = v) },
2473
+ { flag: '--max-tokens', takesValue: true, isInt: true, apply: (o, v) => (o.max_tokens = v === null ? null : parseInt(v, 10)) },
2474
+ { flag: '--mode-override', takesValue: true, choices: ['api', 'manual'], apply: (o, v) => (o.mode_override = v) },
2475
+ { flag: '--model', takesValue: true, apply: (o, v) => { (o.model ??= []).push(v as string); } },
2476
+ { flag: '--siblings', takesValue: true, apply: (o, v) => { (o.siblings ??= []).push(v as string); } },
2477
+ { flag: '--original-ask', takesValue: true, apply: (o, v) => (o.original_ask = v as string) },
2478
+ { flag: '--peer-review', takesValue: false, apply: (o) => (o.peer_review = true) },
2479
+ ];
2480
+ }
2481
+
2482
+ function _specsFor(cmd: string): { positionals: string[]; opts: OptSpec[]; requiredOpts: string[] } {
2483
+ const common = _commonInputSpecs();
2484
+ switch (cmd) {
2485
+ case 'estimate':
2486
+ return {
2487
+ positionals: ['question'],
2488
+ opts: [
2489
+ ...common,
2490
+ { flag: '--debate', takesValue: false, apply: (o) => (o.peer_review = o.peer_review) || ((o as Args & { debate?: boolean }).debate = true) },
2491
+ { flag: '--rounds', takesValue: true, isInt: true, apply: (o, v) => (o.rounds = v === null ? null : parseInt(v, 10)) },
2492
+ ],
2493
+ requiredOpts: [],
2494
+ };
2495
+ case 'run':
2496
+ return {
2497
+ positionals: ['question'],
2498
+ opts: [
2499
+ ...common,
2500
+ { flag: '--output', takesValue: true, apply: (o, v) => (o.output = v) },
2501
+ { flag: '--confirm', takesValue: false, apply: (o) => (o.confirm = true) },
2502
+ { flag: '--rounds', takesValue: true, isInt: true, apply: (o, v) => (o.rounds = v === null ? null : parseInt(v, 10)) },
2503
+ { flag: '--depth', takesValue: true, choices: ['standard', 'deep'], apply: (o, v) => (o.depth = v as string) },
2504
+ { flag: '--invocation', takesValue: true, choices: ['agent', 'user_explicit'], apply: (o, v) => (o.invocation = v as string) },
2505
+ { flag: '--proceed-anyway', takesValue: false, apply: (o) => (o.proceed_anyway = true) },
2506
+ { flag: '--single', takesValue: false, apply: (o) => (o.single = true) },
2507
+ { flag: '--prose-synthesis', takesValue: false, apply: (o) => (o.prose_synthesis = true) },
2508
+ { flag: '--no-prose-synthesis', takesValue: false, apply: (o) => (o.prose_synthesis = false) },
2509
+ ],
2510
+ requiredOpts: ['--output'],
2511
+ };
2512
+ case 'debate':
2513
+ return {
2514
+ positionals: ['question'],
2515
+ opts: [
2516
+ ...common,
2517
+ { flag: '--output', takesValue: true, apply: (o, v) => (o.output = v) },
2518
+ { flag: '--confirm', takesValue: false, apply: (o) => (o.confirm = true) },
2519
+ { flag: '--rounds', takesValue: true, isInt: true, apply: (o, v) => (o.rounds = v === null ? null : parseInt(v, 10)) },
2520
+ { flag: '--auto-continue', takesValue: false, apply: (o) => (o.auto_continue = true) },
2521
+ { flag: '--continue-as-debate', takesValue: true, apply: (o, v) => (o.continue_as_debate = v) },
2522
+ { flag: '--invocation', takesValue: true, choices: ['agent', 'user_explicit'], apply: (o, v) => (o.invocation = v as string) },
2523
+ { flag: '--proceed-anyway', takesValue: false, apply: (o) => (o.proceed_anyway = true) },
2524
+ { flag: '--prose-synthesis', takesValue: false, apply: (o) => (o.prose_synthesis = true) },
2525
+ { flag: '--no-prose-synthesis', takesValue: false, apply: (o) => (o.prose_synthesis = false) },
2526
+ ],
2527
+ requiredOpts: ['--output'],
2528
+ };
2529
+ case 'render':
2530
+ return {
2531
+ positionals: ['responses'],
2532
+ opts: [
2533
+ { flag: '--prompt-mode', takesValue: true, choices: ['default', 'pr', 'design', 'optimize', 'analysis', 'prompt', 'roadmap', 'diff', 'files'], apply: (o, v) => (o.prompt_mode = v) },
2534
+ { flag: '--output', takesValue: true, apply: (o, v) => (o.output = v) },
2535
+ { flag: '--prose-synthesis', takesValue: false, apply: (o) => (o.prose_synthesis = true) },
2536
+ { flag: '--no-prose-synthesis', takesValue: false, apply: (o) => (o.prose_synthesis = false) },
2537
+ ],
2538
+ requiredOpts: [],
2539
+ };
2540
+ case 'replay':
2541
+ return {
2542
+ positionals: ['responses'],
2543
+ opts: [
2544
+ { flag: '--output', takesValue: true, apply: (o, v) => (o.output = v) },
2545
+ { flag: '--redact-member-arguments', takesValue: false, apply: (o) => (o.include_member_arguments = false) },
2546
+ { flag: '--include-member-arguments', takesValue: false, apply: (o) => (o.include_member_arguments = true) },
2547
+ { flag: '--low-impact-stats', takesValue: false, apply: (o) => (o.low_impact_stats = true) },
2548
+ ],
2549
+ requiredOpts: [],
2550
+ };
2551
+ case 'quota':
2552
+ return {
2553
+ positionals: [],
2554
+ opts: [
2555
+ { flag: '--reset', takesValue: true, apply: (o, v) => (o.reset = v) },
2556
+ { flag: '--confirm', takesValue: false, apply: (o) => (o.confirm = true) },
2557
+ ],
2558
+ requiredOpts: [],
2559
+ };
2560
+ case 'shadow-report':
2561
+ return {
2562
+ positionals: [],
2563
+ opts: [
2564
+ { flag: '--log', takesValue: true, apply: (o, v) => (o.log = v) },
2565
+ { flag: '--window-days', takesValue: true, isInt: true, apply: (o, v) => (o.window_days = v === null ? 7 : parseInt(v, 10)) },
2566
+ ],
2567
+ requiredOpts: [],
2568
+ };
2569
+ default:
2570
+ return { positionals: [], opts: [], requiredOpts: [] };
2571
+ }
2572
+ }
2573
+
2574
+ function _parseArgs(argv: string[]): Args {
2575
+ const out = _defaultArgs();
2576
+
2577
+ // Top-level: a required subcommand positional.
2578
+ if (argv.includes('-h') || argv.includes('--help')) {
2579
+ // --help anywhere before a subcommand prints top help (exit 0).
2580
+ if (argv.length === 0 || argv[0] === '-h' || argv[0] === '--help') {
2581
+ _stdout(_TOP_USAGE);
2582
+ process.exitCode = 0;
2583
+ throw new _ArgExit();
2584
+ }
2585
+ }
2586
+ if (argv.length === 0) {
2587
+ _topError('the following arguments are required: cmd');
2588
+ }
2589
+ const first = argv[0] as string;
2590
+ if (first.startsWith('-')) {
2591
+ // No subcommand chosen before a flag.
2592
+ _topError('the following arguments are required: cmd');
2593
+ }
2594
+ if (!_SUBCOMMANDS.includes(first)) {
2595
+ const choices = _SUBCOMMANDS.map((c) => `'${c}'`).join(', ');
2596
+ _topError(`argument cmd: invalid choice: '${first}' (choose from ${choices})`);
2597
+ }
2598
+ out.cmd = first;
2599
+ const rest = argv.slice(1);
2600
+ const usage = _usageFor(first);
2601
+ const { positionals, opts, requiredOpts } = _specsFor(first);
2602
+
2603
+ // Sub-help.
2604
+ if (rest.includes('-h') || rest.includes('--help')) {
2605
+ _stdout(usage);
2606
+ process.exitCode = 0;
2607
+ throw new _ArgExit();
2608
+ }
2609
+
2610
+ const optByFlag = new Map<string, OptSpec>();
2611
+ for (const o of opts) {
2612
+ optByFlag.set(o.flag, o);
2613
+ }
2614
+ const seenRequired = new Set<string>();
2615
+ const positionalValues: string[] = [];
2616
+
2617
+ const valueOf = (token: string, flag: string, i: number): { value: string; nextI: number } => {
2618
+ const eqPrefix = `${flag}=`;
2619
+ if (token.startsWith(eqPrefix)) {
2620
+ return { value: token.slice(eqPrefix.length), nextI: i };
2621
+ }
2622
+ const next = rest[i + 1];
2623
+ if (next === undefined) {
2624
+ _subError(first, usage, `argument ${flag}: expected one argument`);
2625
+ }
2626
+ return { value: next, nextI: i + 1 };
2627
+ };
2628
+
2629
+ for (let i = 0; i < rest.length; i++) {
2630
+ const token = rest[i] as string;
2631
+ if (token.startsWith('--')) {
2632
+ const flagName = token.includes('=') ? token.slice(0, token.indexOf('=')) : token;
2633
+ const spec = optByFlag.get(flagName);
2634
+ if (spec === undefined) {
2635
+ // argparse bubbles unrecognized args to the TOP parser.
2636
+ _topError(`unrecognized arguments: ${token}`);
2637
+ }
2638
+ if (!spec.takesValue) {
2639
+ if (token.includes('=')) {
2640
+ _subError(first, usage, `argument ${flagName}: ignored explicit argument '${token.slice(token.indexOf('=') + 1)}'`);
2641
+ }
2642
+ spec.apply(out, null);
2643
+ if (requiredOpts.includes(flagName)) {
2644
+ seenRequired.add(flagName);
2645
+ }
2646
+ continue;
2647
+ }
2648
+ const { value, nextI } = valueOf(token, flagName, i);
2649
+ i = nextI;
2650
+ if (spec.choices && !spec.choices.includes(value)) {
2651
+ const choices = spec.choices.map((c) => `'${c}'`).join(', ');
2652
+ _subError(first, usage, `argument ${flagName}: invalid choice: '${value}' (choose from ${choices})`);
2653
+ }
2654
+ if (spec.isInt && !_isIntLiteral(value)) {
2655
+ _subError(first, usage, `argument ${flagName}: invalid int value: '${value}'`);
2656
+ }
2657
+ spec.apply(out, value);
2658
+ if (requiredOpts.includes(flagName)) {
2659
+ seenRequired.add(flagName);
2660
+ }
2661
+ } else if (token.startsWith('-') && token !== '-') {
2662
+ _topError(`unrecognized arguments: ${token}`);
2663
+ } else {
2664
+ positionalValues.push(token);
2665
+ }
2666
+ }
2667
+
2668
+ // Assign positionals.
2669
+ if (positionalValues.length < positionals.length) {
2670
+ const missing = positionals.slice(positionalValues.length);
2671
+ _subError(first, usage, `the following arguments are required: ${missing.join(', ')}`);
2672
+ }
2673
+ if (positionalValues.length > positionals.length) {
2674
+ const extra = positionalValues.slice(positionals.length);
2675
+ _topError(`unrecognized arguments: ${extra.join(' ')}`);
2676
+ }
2677
+ for (let j = 0; j < positionals.length; j++) {
2678
+ const name = positionals[j] as string;
2679
+ (out as unknown as Dict)[name] = positionalValues[j];
2680
+ }
2681
+
2682
+ // Required options.
2683
+ const missingReq = requiredOpts.filter((f) => !seenRequired.has(f));
2684
+ if (missingReq.length > 0) {
2685
+ _subError(first, usage, `the following arguments are required: ${missingReq.join(', ')}`);
2686
+ }
2687
+
2688
+ return out;
2689
+ }
2690
+
2691
+ /** Mirror argparse `type=int`: accept an optionally-signed integer literal. */
2692
+ function _isIntLiteral(s: string): boolean {
2693
+ return /^[+-]?\d+$/.test(s.trim());
2694
+ }
2695
+
2696
+ function _parse_model_overrides(items: string[] | null): Record<string, string> {
2697
+ const out: Record<string, string> = {};
2698
+ for (const raw of items || []) {
2699
+ if (!raw.includes('=')) {
2700
+ throw new ArgumentTypeError(`--model expects '<member>=<model-id>', got ${_pyReprStr(raw)}.`);
2701
+ }
2702
+ const idx = raw.indexOf('=');
2703
+ const name = raw.slice(0, idx).trim();
2704
+ const model = raw.slice(idx + 1).trim();
2705
+ if (!name || !model) {
2706
+ throw new ArgumentTypeError(`--model member and model-id must both be non-empty: ${_pyReprStr(raw)}.`);
2707
+ }
2708
+ out[name] = model;
2709
+ }
2710
+ return out;
2711
+ }
2712
+
2713
+ function _parse_siblings_overrides(items: string[] | null): Record<string, string[]> {
2714
+ const out: Record<string, string[]> = {};
2715
+ for (const raw of items || []) {
2716
+ if (!raw.includes('=')) {
2717
+ throw new ArgumentTypeError(`--siblings expects '<member>=<model1>,<model2>[,...]', got ${_pyReprStr(raw)}.`);
2718
+ }
2719
+ const idx = raw.indexOf('=');
2720
+ const name = raw.slice(0, idx).trim();
2721
+ const models = raw
2722
+ .slice(idx + 1)
2723
+ .split(',')
2724
+ .map((m) => m.trim())
2725
+ .filter((m) => m.length > 0);
2726
+ if (!name || models.length === 0) {
2727
+ throw new ArgumentTypeError(`--siblings member and model list must both be non-empty: ${_pyReprStr(raw)}.`);
2728
+ }
2729
+ if (new Set(models).size < 2) {
2730
+ throw new ArgumentTypeError(`--siblings requires ≥ 2 distinct models for ${_pyReprStr(name)}, got ${_pyReprStrList(models)}.`);
2731
+ }
2732
+ if (name in out) {
2733
+ throw new ArgumentTypeError(`--siblings repeated for member ${_pyReprStr(name)}; combine into one flag.`);
2734
+ }
2735
+ out[name] = models;
2736
+ }
2737
+ return out;
2738
+ }
2739
+
2740
+ function _isFileNotFound(exc: unknown): boolean {
2741
+ return (
2742
+ exc instanceof FileNotFoundError ||
2743
+ (exc instanceof Error && (exc as NodeJS.ErrnoException).code === 'ENOENT')
2744
+ );
2745
+ }
2746
+
2747
+ // ── main ────────────────────────────────────────────────────────────
2748
+
2749
+ function main(argv: string[] | null = null): number {
2750
+ const args = _parseArgs(argv ?? process.argv.slice(2));
2751
+ try {
2752
+ if (args.cmd === 'estimate') {
2753
+ return cmd_estimate(args);
2754
+ }
2755
+ if (args.cmd === 'run') {
2756
+ return cmd_run(args);
2757
+ }
2758
+ if (args.cmd === 'debate') {
2759
+ return cmd_debate(args);
2760
+ }
2761
+ if (args.cmd === 'render') {
2762
+ return cmd_render(args);
2763
+ }
2764
+ if (args.cmd === 'replay') {
2765
+ return cmd_replay(args);
2766
+ }
2767
+ if (args.cmd === 'quota') {
2768
+ return cmd_quota(args);
2769
+ }
2770
+ if (args.cmd === 'shadow-report') {
2771
+ return cmd_shadow_report(args);
2772
+ }
2773
+ } catch (exc) {
2774
+ if (exc instanceof CouncilDisabledError) {
2775
+ _stderr(`❌ council:${args.cmd}: ${exc.message}\n`);
2776
+ return 2;
2777
+ }
2778
+ if (
2779
+ exc instanceof BundleTooLarge ||
2780
+ exc instanceof InvalidModeError ||
2781
+ exc instanceof FileNotFoundError ||
2782
+ exc instanceof ArgumentTypeError ||
2783
+ exc instanceof ValueError ||
2784
+ _isFileNotFound(exc)
2785
+ ) {
2786
+ _stderr(`❌ council:${args.cmd}: ${(exc as Error).message}\n`);
2787
+ return 2;
2788
+ }
2789
+ throw exc;
2790
+ }
2791
+ return 1;
2792
+ }
2793
+
2794
+ // CLI entry.
2795
+ const _isCliEntry =
2796
+ process.argv[1] !== undefined &&
2797
+ import.meta.url === pathToFileURL(path.resolve(process.argv[1] as string)).href;
2798
+
2799
+ if (_isCliEntry) {
2800
+ try {
2801
+ process.exitCode = main(process.argv.slice(2));
2802
+ } catch (err) {
2803
+ if (!(err instanceof _ArgExit)) {
2804
+ throw err;
2805
+ }
2806
+ // process.exitCode already set by the argparse-style error path.
2807
+ }
2808
+ }
2809
+
2810
+ export {
2811
+ main,
2812
+ build_members,
2813
+ build_question,
2814
+ cmd_estimate,
2815
+ cmd_run,
2816
+ cmd_debate,
2817
+ cmd_render,
2818
+ cmd_replay,
2819
+ cmd_quota,
2820
+ cmd_shadow_report,
2821
+ load_settings,
2822
+ format_estimate_table,
2823
+ _parse_model_overrides,
2824
+ _parse_siblings_overrides,
2825
+ _synthesize_ai_council_block,
2826
+ CouncilDisabledError,
2827
+ };