@event4u/agent-config 14.9.0 → 14.11.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 (426) hide show
  1. package/.augment-plugin/marketplace.json +3 -3
  2. package/.augment-plugin/plugin.json +1 -1
  3. package/.claude-plugin/marketplace.json +1 -1
  4. package/CHANGELOG.md +384 -0
  5. package/README.md +1 -1
  6. package/dist/agent-src/commands/design.md +88 -0
  7. package/dist/agent-src/commands/project/analyze.md +47 -0
  8. package/dist/agent-src/commands/review/changes.md +67 -6
  9. package/dist/agent-src/commands/roadmap/create.md +49 -0
  10. package/dist/agent-src/commands/roadmap/next.md +27 -11
  11. package/dist/agent-src/commands/roadmap/process-full.md +14 -0
  12. package/dist/agent-src/commands/video/from-script.md +60 -3
  13. package/dist/agent-src/commands/video/stitch.md +14 -0
  14. package/dist/agent-src/contexts/communication/rules-auto/guidelines-mechanics.md +1 -0
  15. package/dist/agent-src/contexts/execution/roadmap-process-loop.md +154 -2
  16. package/dist/agent-src/rules/active-remediation.md +3 -3
  17. package/dist/agent-src/rules/code-provenance.md +2 -2
  18. package/dist/agent-src/rules/context-hygiene.md +13 -33
  19. package/dist/agent-src/rules/council-availability.md +2 -2
  20. package/dist/agent-src/rules/decision-revisit-gate.md +3 -1
  21. package/dist/agent-src/rules/design-fidelity.md +18 -0
  22. package/dist/agent-src/rules/design-review-after-ui-write.md +2 -2
  23. package/dist/agent-src/rules/evaluator-independence.md +56 -44
  24. package/dist/agent-src/rules/fix-what-you-see.md +9 -1
  25. package/dist/agent-src/rules/framework-neutrality-in-generic-skills.md +1 -1
  26. package/dist/agent-src/rules/minimal-safe-diff.md +14 -20
  27. package/dist/agent-src/rules/missing-skill-recovery.md +13 -1
  28. package/dist/agent-src/rules/playbook-precedence.md +105 -0
  29. package/dist/agent-src/rules/recurring-criticism.md +3 -1
  30. package/dist/agent-src/rules/roadmap-progress-sync.md +14 -13
  31. package/dist/agent-src/rules/scale-discipline.md +24 -0
  32. package/dist/agent-src/rules/security-sensitive-stop.md +2 -2
  33. package/dist/agent-src/rules/settings-ask-protocol.md +2 -2
  34. package/dist/agent-src/rules/ui-audit-gate.md +27 -15
  35. package/dist/agent-src/rules/untrusted-input-defense.md +2 -2
  36. package/dist/agent-src/skills/accessibility-auditor/SKILL.md +19 -0
  37. package/dist/agent-src/skills/adr-create/SKILL.md +7 -0
  38. package/dist/agent-src/skills/agents-md-thin-root/SKILL.md +33 -0
  39. package/dist/agent-src/skills/ai-council/references/advanced-modes.md +17 -3
  40. package/dist/agent-src/skills/ai-council/references/output-and-synthesis.md +31 -0
  41. package/dist/agent-src/skills/ai-council/references/procedure.md +19 -0
  42. package/dist/agent-src/skills/alerting-doctrine/SKILL.md +225 -0
  43. package/dist/agent-src/skills/alerting-doctrine/evals/triggers.json +17 -0
  44. package/dist/agent-src/skills/async-python-patterns/SKILL.md +1 -1
  45. package/dist/agent-src/skills/authz-review/SKILL.md +0 -1
  46. package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +32 -0
  47. package/dist/agent-src/skills/brand/SKILL.md +3 -0
  48. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +3 -0
  49. package/dist/agent-src/skills/brand-audit/SKILL.md +3 -0
  50. package/dist/agent-src/skills/brand-identity/SKILL.md +3 -0
  51. package/dist/agent-src/skills/brand-strategy/SKILL.md +3 -0
  52. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -0
  53. package/dist/agent-src/skills/check-refs/SKILL.md +3 -0
  54. package/dist/agent-src/skills/code-refactoring/SKILL.md +1 -1
  55. package/dist/agent-src/skills/code-review/SKILL.md +11 -0
  56. package/dist/agent-src/skills/command-routing/SKILL.md +6 -0
  57. package/dist/agent-src/skills/condense-memory/SKILL.md +4 -1
  58. package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
  59. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +4 -1
  60. package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +10 -0
  61. package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -0
  62. package/dist/agent-src/skills/design-intelligence/SKILL.md +3 -0
  63. package/dist/agent-src/skills/design-intelligence/data/landing.csv +36 -35
  64. package/dist/agent-src/skills/design-intelligence/data/stacks/threejs.csv +1 -0
  65. package/dist/agent-src/skills/design-review/SKILL.md +80 -2
  66. package/dist/agent-src/skills/design-review/references/verification-automation.md +41 -0
  67. package/dist/agent-src/skills/design-system-capture/SKILL.md +35 -40
  68. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +50 -0
  69. package/dist/agent-src/skills/design-tokens/SKILL.md +3 -0
  70. package/dist/agent-src/skills/design-variations/SKILL.md +3 -0
  71. package/dist/agent-src/skills/developer-like-execution/SKILL.md +3 -0
  72. package/dist/agent-src/skills/discovery-interview/SKILL.md +1 -1
  73. package/dist/agent-src/skills/doc-coauthoring/SKILL.md +1 -1
  74. package/dist/agent-src/skills/docx-authoring/SKILL.md +1 -1
  75. package/dist/agent-src/skills/editorial-calendar/SKILL.md +1 -1
  76. package/dist/agent-src/skills/estimate-ticket/SKILL.md +3 -0
  77. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +20 -3
  78. package/dist/agent-src/skills/fe-design/SKILL.md +74 -41
  79. package/dist/agent-src/skills/fe-design/evals/triggers.json +65 -53
  80. package/dist/agent-src/skills/fe-design/references/craft-floor.md +52 -0
  81. package/dist/agent-src/skills/fe-design/references/source-led-port.md +36 -0
  82. package/dist/agent-src/skills/file-editor/SKILL.md +5 -0
  83. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
  84. package/dist/agent-src/skills/git-workflow/SKILL.md +3 -0
  85. package/dist/agent-src/skills/github-ci/SKILL.md +1 -1
  86. package/dist/agent-src/skills/html-deck/SKILL.md +3 -0
  87. package/dist/agent-src/skills/iconography/SKILL.md +3 -0
  88. package/dist/agent-src/skills/image-editing/SKILL.md +3 -0
  89. package/dist/agent-src/skills/image-generation/SKILL.md +3 -0
  90. package/dist/agent-src/skills/image-provider-routing/SKILL.md +3 -0
  91. package/dist/agent-src/skills/incident-commander/SKILL.md +10 -0
  92. package/dist/agent-src/skills/js-library-packaging/SKILL.md +173 -0
  93. package/dist/agent-src/skills/js-library-packaging/evals/triggers.json +17 -0
  94. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +270 -0
  95. package/dist/agent-src/skills/judge-artifact-completeness/SKILL.md +1 -1
  96. package/dist/agent-src/skills/judge-injection-defense/SKILL.md +1 -1
  97. package/dist/agent-src/skills/laravel-migration/SKILL.md +3 -0
  98. package/dist/agent-src/skills/laravel-validation/SKILL.md +1 -1
  99. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +3 -0
  100. package/dist/agent-src/skills/legal-intake-triage/SKILL.md +1 -1
  101. package/dist/agent-src/skills/legal-practice-profile/SKILL.md +1 -1
  102. package/dist/agent-src/skills/lint-skills/SKILL.md +3 -0
  103. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +3 -0
  104. package/dist/agent-src/skills/logging-monitoring/SKILL.md +234 -51
  105. package/dist/agent-src/skills/logo-generation/SKILL.md +3 -0
  106. package/dist/agent-src/skills/md-language-check/SKILL.md +3 -0
  107. package/dist/agent-src/skills/messaging-architecture/SKILL.md +1 -1
  108. package/dist/agent-src/skills/migration-architect/SKILL.md +1 -1
  109. package/dist/agent-src/skills/module-detect-on-the-fly/SKILL.md +1 -1
  110. package/dist/agent-src/skills/module-management/SKILL.md +1 -1
  111. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +149 -0
  112. package/dist/agent-src/skills/monorepo-workspace/evals/triggers.json +17 -0
  113. package/dist/agent-src/skills/motion-choreographer/SKILL.md +7 -1
  114. package/dist/agent-src/skills/multi-tenancy/SKILL.md +4 -0
  115. package/dist/agent-src/skills/onboarding-program/SKILL.md +1 -1
  116. package/dist/agent-src/skills/operational-readiness/SKILL.md +184 -0
  117. package/dist/agent-src/skills/operational-readiness/evals/triggers.json +17 -0
  118. package/dist/agent-src/skills/override-management/SKILL.md +3 -0
  119. package/dist/agent-src/skills/perf-feedback-craft/SKILL.md +1 -1
  120. package/dist/agent-src/skills/persona-improvement/SKILL.md +3 -0
  121. package/dist/agent-src/skills/pest-testing/SKILL.md +3 -0
  122. package/dist/agent-src/skills/playbook-authoring/SKILL.md +162 -0
  123. package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -0
  124. package/dist/agent-src/skills/privacy-review/SKILL.md +3 -0
  125. package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +3 -0
  126. package/dist/agent-src/skills/prompt-optimizer/SKILL.md +1 -1
  127. package/dist/agent-src/skills/quality-tools/SKILL.md +5 -0
  128. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +52 -21
  129. package/dist/agent-src/skills/readme-reviewer/SKILL.md +3 -0
  130. package/dist/agent-src/skills/readme-writing/SKILL.md +3 -0
  131. package/dist/agent-src/skills/readme-writing-package/SKILL.md +3 -0
  132. package/dist/agent-src/skills/receiving-code-review/SKILL.md +3 -3
  133. package/dist/agent-src/skills/refine-prompt/SKILL.md +3 -0
  134. package/dist/agent-src/skills/refine-ticket/SKILL.md +3 -0
  135. package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
  136. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  137. package/dist/agent-src/skills/roadmap-writing/SKILL.md +23 -41
  138. package/dist/agent-src/skills/roadmap-writing/references/follow-up-roadmap-shape.md +47 -0
  139. package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +22 -6
  140. package/dist/agent-src/skills/runway-cognition/SKILL.md +3 -0
  141. package/dist/agent-src/skills/scene-expander/SKILL.md +1 -1
  142. package/dist/agent-src/skills/scene-expander/scene-blueprint.schema.yaml +26 -0
  143. package/dist/agent-src/skills/secrets-management/SKILL.md +5 -1
  144. package/dist/agent-src/skills/server-hardening/SKILL.md +159 -0
  145. package/dist/agent-src/skills/server-hardening/evals/triggers.json +17 -0
  146. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +3 -0
  147. package/dist/agent-src/skills/skill-management/SKILL.md +3 -0
  148. package/dist/agent-src/skills/skill-reviewer/SKILL.md +3 -0
  149. package/dist/agent-src/skills/skill-writing/SKILL.md +6 -0
  150. package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +3 -0
  151. package/dist/agent-src/skills/storybook-workshop/SKILL.md +194 -0
  152. package/dist/agent-src/skills/storybook-workshop/evals/triggers.json +17 -0
  153. package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.ts +134 -0
  154. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
  155. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +25 -0
  156. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +12 -0
  157. package/dist/agent-src/skills/systematic-debugging/SKILL.md +1 -1
  158. package/dist/agent-src/skills/terraform/SKILL.md +3 -0
  159. package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -1
  160. package/dist/agent-src/skills/threat-modeling/SKILL.md +0 -3
  161. package/dist/agent-src/skills/token-optimizer/SKILL.md +3 -0
  162. package/dist/agent-src/skills/typography-system/SKILL.md +3 -0
  163. package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -1
  164. package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -0
  165. package/dist/agent-src/skills/using-git-worktrees/SKILL.md +1 -1
  166. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -0
  167. package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -2
  168. package/dist/agent-src/skills/wireframe/SKILL.md +3 -0
  169. package/dist/agent-src/skills/wireframe/references/story-beat-ledger.schema.json +115 -0
  170. package/dist/agent-src/skills/workspace-link/SKILL.md +131 -0
  171. package/dist/agent-src/skills/workspace-link/evals/triggers.json +17 -0
  172. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  173. package/dist/agent-src/templates/playbook.md +75 -0
  174. package/dist/agent-src/templates/roadmaps.md +37 -0
  175. package/dist/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  176. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  177. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  178. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  179. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  180. package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  181. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  182. package/dist/cli/commands/uiAudit.js +221 -0
  183. package/dist/cli/commands/uiAudit.js.map +1 -0
  184. package/dist/cli/commands/uiRender.js +206 -0
  185. package/dist/cli/commands/uiRender.js.map +1 -0
  186. package/dist/cli/main.js +22 -1
  187. package/dist/cli/main.js.map +1 -1
  188. package/dist/cli/mcp/content.js +64 -1
  189. package/dist/cli/mcp/content.js.map +1 -1
  190. package/dist/cli/mcp/dispatch.js +175 -10
  191. package/dist/cli/mcp/dispatch.js.map +1 -1
  192. package/dist/cli/registry.js +3 -0
  193. package/dist/cli/registry.js.map +1 -1
  194. package/dist/cli-delegate/{chunk-H4VIVD4C.js → chunk-236PNQZK.js} +413 -391
  195. package/dist/cli-delegate/{chunk-G23AT6GD.js → chunk-DMSZHXZS.js} +57 -1
  196. package/dist/cli-delegate/{chunk-77GR3VD4.js → chunk-FF7WAFMR.js} +58 -3
  197. package/dist/cli-delegate/{chunk-PLSG6UL5.js → chunk-K4FFODTS.js} +341 -204
  198. package/dist/cli-delegate/{chunk-YM4GZDJG.js → chunk-L43NCYPB.js} +5 -0
  199. package/dist/cli-delegate/{chunk-B2ERU2VA.js → chunk-WOKWX5PL.js} +1 -1
  200. package/dist/cli-delegate/cmd_brand_status.js +8 -6
  201. package/dist/cli-delegate/cmd_conformance.js +3 -3
  202. package/dist/cli-delegate/cmd_doctor.js +3 -3
  203. package/dist/cli-delegate/cmd_export.js +4 -4
  204. package/dist/cli-delegate/cmd_handoff.js +1 -1
  205. package/dist/cli-delegate/cmd_preflight.js +2 -2
  206. package/dist/cli-delegate/cmd_prune.js +4 -4
  207. package/dist/cli-delegate/cmd_session_recycle.js +70 -9
  208. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  209. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  210. package/dist/cli-delegate/cmd_sync.js +4 -4
  211. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  212. package/dist/cli-delegate/cmd_validate.js +4 -4
  213. package/dist/discovery/deprecation-report.md +1 -1
  214. package/dist/discovery/discovery-manifest.json +380 -145
  215. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  216. package/dist/discovery/discovery-manifest.summary.md +4 -4
  217. package/dist/discovery/dormancy-report.md +1 -1
  218. package/dist/discovery/orphan-report.md +1 -1
  219. package/dist/discovery/packs.json +18 -8
  220. package/dist/discovery/trust-report.md +3 -3
  221. package/dist/discovery/workspaces.json +16 -6
  222. package/dist/hooks/dispatch.js +2337 -1436
  223. package/dist/install/install.mjs +795 -708
  224. package/dist/mcp/registry-manifest.json +3 -3
  225. package/dist/mcp/server.json +2 -2
  226. package/dist/mcp/server.mjs +1685 -1250
  227. package/dist/router.json +1 -1
  228. package/dist/scripts/_lib/lean_projection_mode.js +40 -0
  229. package/dist/scripts/_lib/lean_projection_mode.js.map +1 -0
  230. package/dist/scripts/_lib/scoped_projection.js +84 -0
  231. package/dist/scripts/_lib/scoped_projection.js.map +1 -1
  232. package/dist/scripts/_lib/ui_surface.js +89 -0
  233. package/dist/scripts/_lib/ui_surface.js.map +1 -0
  234. package/dist/scripts/condense.js +6 -10
  235. package/dist/scripts/condense.js.map +1 -1
  236. package/dist/scripts/project_thin_rules.js +40 -2
  237. package/dist/scripts/project_thin_rules.js.map +1 -1
  238. package/dist/server/schemas/settings.js +3 -0
  239. package/dist/server/schemas/settings.js.map +1 -1
  240. package/dist/shared/skillRanking.js +159 -0
  241. package/dist/shared/skillRanking.js.map +1 -0
  242. package/docs/contracts/provider-lifecycle.md +47 -18
  243. package/docs/contracts/settings-classes.md +14 -4
  244. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +49 -0
  245. package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
  246. package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +45 -1
  247. package/docs/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
  248. package/docs/guidelines/design-antipatterns.md +4 -2
  249. package/docs/guidelines/design-asset-discipline.md +38 -0
  250. package/docs/guidelines/design-fidelity-mechanics.md +45 -29
  251. package/docs/guidelines/design-handover-extraction.md +35 -5
  252. package/docs/guidelines/design-modes.md +41 -1
  253. package/docs/guidelines/monorepo-antipatterns.md +141 -0
  254. package/llms.txt +50 -39
  255. package/package.json +1 -1
  256. package/src/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  257. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  258. package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  259. package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  260. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  261. package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  262. package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  263. package/src/config/agent-settings.template.yml +28 -0
  264. package/src/config/assurance-capability-registry.json +223 -0
  265. package/src/config/assurance-threshold-budget.json +65 -0
  266. package/src/config/ci-local-parity.yml +14 -0
  267. package/src/config/discovery/unassigned-artefacts.yml +2 -0
  268. package/src/config/dispatch-economy-metrics.json +4 -2
  269. package/src/config/evaluator-budgets.json +14 -14
  270. package/src/config/gate-coverage.yml +227 -8
  271. package/src/config/gate-violation-baselines.json +76 -72
  272. package/src/config/hook-latency-budget.json +1 -0
  273. package/src/config/hook-token-budget.json +137 -125
  274. package/src/config/pack-size-budget.json +4 -2
  275. package/src/config/preamble-payload-budget.json +71 -67
  276. package/src/config/quorum-attendance-budget.json +12 -4
  277. package/src/config/rule-activation-census.json +7 -3
  278. package/src/config/rule-enforcement-baseline.json +0 -1
  279. package/src/config/rule-stub-ceilings.json +112 -91
  280. package/src/scripts/_cli/cmd_doctor.ts +15 -16
  281. package/src/scripts/_cli/doctor_install_mode.ts +49 -0
  282. package/src/scripts/_cli/doctor_overrides.ts +154 -0
  283. package/src/scripts/_dispatch.bash +17 -0
  284. package/src/scripts/_lib/as_of.ts +412 -0
  285. package/src/scripts/_lib/exec_evidence.ts +7 -0
  286. package/src/scripts/_lib/hook_settings.ts +33 -0
  287. package/src/scripts/_lib/host_listing_model.ts +192 -0
  288. package/src/scripts/_lib/lean_projection_mode.ts +44 -0
  289. package/src/scripts/_lib/mcp_bridge.ts +199 -0
  290. package/src/scripts/_lib/review_independence.ts +62 -10
  291. package/src/scripts/_lib/rule_injection.ts +239 -0
  292. package/src/scripts/_lib/run_checkpoint.ts +54 -1
  293. package/src/scripts/_lib/scoped_projection.ts +96 -0
  294. package/src/scripts/_lib/session_register.ts +44 -2
  295. package/src/scripts/_lib/skill_catalogue.ts +38 -2
  296. package/src/scripts/_lib/transcript_reads.ts +207 -0
  297. package/src/scripts/_lib/ui_authority.test.ts +251 -0
  298. package/src/scripts/_lib/ui_authority.ts +343 -0
  299. package/src/scripts/ai-video/adapters/fal.sh +8 -3
  300. package/src/scripts/ai-video/adapters/gemini-veo.sh +10 -0
  301. package/src/scripts/ai-video/adapters/higgsfield.sh +10 -2
  302. package/src/scripts/ai-video/adapters/kling.sh +10 -0
  303. package/src/scripts/ai-video/adapters/sora.sh +10 -0
  304. package/src/scripts/ai-video/lib/calibrate-cost.sh +145 -0
  305. package/src/scripts/ai-video/lib/model-capabilities/README.md +53 -7
  306. package/src/scripts/ai-video/lib/model-capabilities/comfyui.json +15 -3
  307. package/src/scripts/ai-video/lib/model-capabilities/fal.json +36 -6
  308. package/src/scripts/ai-video/lib/model-capabilities/gemini-veo.json +23 -0
  309. package/src/scripts/ai-video/lib/model-capabilities/higgsfield.json +23 -0
  310. package/src/scripts/ai-video/lib/model-capabilities/kling.json +23 -0
  311. package/src/scripts/ai-video/lib/model-capabilities/musetalk.json +8 -2
  312. package/src/scripts/ai-video/lib/model-capabilities/replicate.json +36 -6
  313. package/src/scripts/ai-video/lib/model-capabilities/sora.json +45 -0
  314. package/src/scripts/ai-video/lib/model-capabilities/syncso.json +8 -2
  315. package/src/scripts/ai-video/lib/parse-blueprint.sh +52 -5
  316. package/src/scripts/ai-video/lib/resume-scan.sh +92 -3
  317. package/src/scripts/ai-video/lib/seam-plan.sh +212 -0
  318. package/src/scripts/ai-video/smoke-trace.sh +450 -2
  319. package/src/scripts/ai-video/stitch.sh +191 -10
  320. package/src/scripts/ai-video/test-pipeline.sh +84 -6
  321. package/src/scripts/ai_council/cli_agency_bounds.ts +139 -0
  322. package/src/scripts/ai_council/cli_least_agency_canary.ts +347 -0
  323. package/src/scripts/ai_council/clients.ts +3 -2
  324. package/src/scripts/ai_council/consensus.ts +63 -6
  325. package/src/scripts/ai_council/events_log.ts +46 -1
  326. package/src/scripts/ai_council/orchestrator.ts +103 -108
  327. package/src/scripts/ai_council/orchestrator_results.ts +166 -0
  328. package/src/scripts/ai_council/prompts.ts +12 -5
  329. package/src/scripts/ai_council/quorum.ts +82 -1
  330. package/src/scripts/ai_council/quorum_wiring.ts +82 -5
  331. package/src/scripts/ai_council/seating.ts +211 -0
  332. package/src/scripts/ai_council/stance_tally.ts +22 -0
  333. package/src/scripts/bench_hook_latency.ts +62 -0
  334. package/src/scripts/build_proof.ts +12 -1
  335. package/src/scripts/capture_skill_catalogue.ts +21 -0
  336. package/src/scripts/check_always_budget.ts +2 -1
  337. package/src/scripts/check_augmentignore.ts +2 -1
  338. package/src/scripts/check_beta_review_markers.ts +2 -1
  339. package/src/scripts/check_composite_arming.ts +364 -0
  340. package/src/scripts/check_corpus_staleness.ts +2 -1
  341. package/src/scripts/check_council_pin_staleness.ts +3 -1
  342. package/src/scripts/check_enforcement_coverage.ts +116 -3
  343. package/src/scripts/check_enforcement_denominator.ts +365 -0
  344. package/src/scripts/check_gate_coverage.ts +2 -1
  345. package/src/scripts/check_hook_bundle_freshness.ts +13 -1
  346. package/src/scripts/check_knowledge_cards.ts +2 -1
  347. package/src/scripts/check_knowledge_pages.ts +3 -2
  348. package/src/scripts/check_memory.ts +2 -1
  349. package/src/scripts/check_no_automerge_key.ts +287 -0
  350. package/src/scripts/check_pack_conformance_fixture.ts +565 -0
  351. package/src/scripts/check_pack_passport_reconciliation.ts +274 -0
  352. package/src/scripts/check_proposal.ts +2 -1
  353. package/src/scripts/check_reach_staleness.ts +2 -1
  354. package/src/scripts/check_release_adjacent_health.ts +2 -1
  355. package/src/scripts/check_release_pr_shape.ts +5 -0
  356. package/src/scripts/check_review_schema.ts +34 -1
  357. package/src/scripts/check_roadmap_trackable.ts +48 -3
  358. package/src/scripts/check_source_size_budget.ts +2 -1
  359. package/src/scripts/check_standing_payload_delta.ts +505 -0
  360. package/src/scripts/check_trigger_evals.ts +2 -1
  361. package/src/scripts/classify_change_risk.ts +281 -0
  362. package/src/scripts/compute_skill_tiers.ts +186 -0
  363. package/src/scripts/condense.ts +8 -13
  364. package/src/scripts/council_attendance_metrics.ts +183 -0
  365. package/src/scripts/council_cli.ts +10 -8
  366. package/src/scripts/council_parse_rate.ts +116 -0
  367. package/src/scripts/derive_playbooks.ts +406 -0
  368. package/src/scripts/design_slop_rules.test.ts +7 -0
  369. package/src/scripts/design_slop_rules.ts +56 -2
  370. package/src/scripts/dispatch_r2_reviewer.ts +16 -0
  371. package/src/scripts/frontend_corpus_hash.ts +116 -0
  372. package/src/scripts/generate_pack_manifests.ts +78 -0
  373. package/src/scripts/grade_target_readiness.ts +478 -0
  374. package/src/scripts/hook_manifest.json +1 -1
  375. package/src/scripts/hook_manifest.yaml +97 -16
  376. package/src/scripts/hooks/concern_registry.ts +4 -0
  377. package/src/scripts/hooks/design_pass_hook.ts +356 -0
  378. package/src/scripts/hooks/rtk_wrap_hook.ts +30 -7
  379. package/src/scripts/hooks/rule_inject_hook.ts +318 -0
  380. package/src/scripts/hot_context_hook.ts +74 -7
  381. package/src/scripts/install.ts +40 -89
  382. package/src/scripts/lint_adapter_tier.ts +663 -0
  383. package/src/scripts/lint_archived_skills.ts +93 -0
  384. package/src/scripts/lint_budget_ownership.ts +2 -1
  385. package/src/scripts/lint_deterministic_time.ts +470 -0
  386. package/src/scripts/lint_framework_leakage.ts +5 -0
  387. package/src/scripts/lint_handoffs.ts +525 -1
  388. package/src/scripts/lint_judge_prompt_expectation.ts +155 -0
  389. package/src/scripts/lint_marketplace.ts +88 -0
  390. package/src/scripts/lint_media_policy_linkage.ts +140 -1
  391. package/src/scripts/lint_one_off_age.ts +6 -1
  392. package/src/scripts/lint_override_kernel_guard.ts +87 -5
  393. package/src/scripts/lint_roadmap_complexity.ts +56 -0
  394. package/src/scripts/lint_rule_enforcement_declaration.ts +24 -7
  395. package/src/scripts/lint_rule_norm_pin.ts +321 -0
  396. package/src/scripts/lint_spawn_payload.ts +42 -5
  397. package/src/scripts/lint_symptom_intake.ts +2 -1
  398. package/src/scripts/mcp_parity_smoke.ts +30 -4
  399. package/src/scripts/mcp_render.ts +66 -1
  400. package/src/scripts/mcp_tool_fingerprint.ts +241 -0
  401. package/src/scripts/measure_risk_class_drift.ts +140 -0
  402. package/src/scripts/measure_skill_ranker_baseline.ts +212 -0
  403. package/src/scripts/media/lib/adapter-common.sh +211 -1
  404. package/src/scripts/media/lib/adapter-contract.md +74 -6
  405. package/src/scripts/model_rule_injection.ts +907 -0
  406. package/src/scripts/project_thin_rules.ts +45 -2
  407. package/src/scripts/release.ts +66 -860
  408. package/src/scripts/release_drill.ts +59 -3
  409. package/src/scripts/release_env.ts +298 -0
  410. package/src/scripts/release_publication.ts +720 -0
  411. package/src/scripts/roadmap_context.ts +778 -0
  412. package/src/scripts/schemas/fidelity-measurement-sheet.schema.json +169 -0
  413. package/src/scripts/schemas/pack.schema.json +62 -4
  414. package/src/scripts/schemas/rule.schema.json +24 -2
  415. package/src/scripts/schemas/skill.schema.json +41 -2
  416. package/src/scripts/schemas/ui-authority.schema.json +114 -0
  417. package/src/scripts/session_register_hook.ts +29 -3
  418. package/src/scripts/sessions_cli.ts +67 -3
  419. package/src/scripts/skill_tools/score_skill_relevance.ts +36 -53
  420. package/src/scripts/tighten_skill_descriptions.ts +264 -0
  421. package/src/scripts/token_sink_report.ts +239 -0
  422. package/src/scripts/trigger_coverage.ts +122 -3
  423. package/src/scripts/update_counts.ts +7 -3
  424. package/src/scripts/validate_frontmatter.ts +66 -0
  425. package/src/server/schemas/settings.ts +5 -0
  426. package/src/shared/skillRanking.ts +183 -0
@@ -21,6 +21,10 @@
21
21
  // Failure normalisation (one member's exception → `error`-set
22
22
  // CouncilResponse, never raise) is unchanged.
23
23
 
24
+ import { ConsensusResult, CouncilQuestion, PeerReviewResult } from './orchestrator_results.js';
25
+ import type { RunConsensusScoringOptions, RunPeerReviewOptions } from './orchestrator_results.js';
26
+ export { ConsensusResult, CouncilQuestion, PeerReviewResult } from './orchestrator_results.js';
27
+ export type { RunConsensusScoringOptions, RunPeerReviewOptions } from './orchestrator_results.js';
24
28
  import {
25
29
  record_spend as _record_daily_spend,
26
30
  today_spend_usd as _today_spend_usd,
@@ -42,7 +46,7 @@ import {
42
46
  anonymize_findings,
43
47
  anonymize_responses,
44
48
  bucket_by_threshold,
45
- parse_findings_response,
49
+ parse_findings_outcome,
46
50
  parse_scores_response,
47
51
  } from './consensus.js';
48
52
  import type {
@@ -119,9 +123,9 @@ import {
119
123
  _setdefault,
120
124
  } from './py_parity.js';
121
125
 
122
- import { CHAIRMAN_FIELDS_ADDENDUM, render_deanonymization_block } from './blind_review.js';
126
+ import { CHAIRMAN_FIELDS_ADDENDUM, render_deanonymization_block, deterministic_shuffle_indices } from './blind_review.js';
123
127
  import type { AbsentReason } from './transport_resolver.js';
124
- import { isSoloConcluded, type QuorumResult } from './quorum.js';
128
+ import { formatAttendanceCaveats, isSoloConcluded, type QuorumResult } from './quorum.js';
125
129
  import { isEmptyHandoff, type HandoffEnvelope } from './handoff.js';
126
130
 
127
131
 
@@ -150,17 +154,6 @@ function _label(idx: number): string {
150
154
 
151
155
  // ── dataclasses ───────────────────────────────────────────────────────
152
156
 
153
- export class CouncilQuestion {
154
- mode: string; // one of: prompt, roadmap, diff, files
155
- user_prompt: string; // bundled artefact text
156
- max_tokens: number;
157
-
158
- constructor(args: { mode: string; user_prompt: string; max_tokens?: number }) {
159
- this.mode = args.mode;
160
- this.user_prompt = args.user_prompt;
161
- this.max_tokens = args.max_tokens ?? DEFAULT_MAX_TOKENS;
162
- }
163
- }
164
157
 
165
158
  // Callback signature: receive event → return True (proceed) or False (skip + tag error).
166
159
  export type OnOverrunCallback = (event: OverrunEvent) => boolean;
@@ -1434,44 +1427,7 @@ export function run_debate(
1434
1427
  return all_rounds;
1435
1428
  }
1436
1429
 
1437
- /**
1438
- * Bundle returned by `run_peer_review()` (Phase 5 / F1).
1439
- *
1440
- * `responses` carries the per-reviewer critiques. `label_to_source`
1441
- * is the anonymisation map captured server-side so the audit-trail
1442
- * JSON can rehydrate it without leaking provider identity to the
1443
- * member at prompt time.
1444
- *
1445
- * `persona_labels` is the (optional) Phase 6 / Step 3a wiring: when
1446
- * the deliberation was an advisor-mode run, the source → persona
1447
- * map flows through to the renderer so peer-review output can render
1448
- * as `Response A (Contrarian)`. Plain-member runs leave it empty.
1449
- */
1450
- export class PeerReviewResult {
1451
- responses: CouncilResponse[];
1452
- label_to_source: Map<string, string>;
1453
- persona_labels: Map<string, string>;
1454
1430
 
1455
- constructor(args: {
1456
- responses: CouncilResponse[];
1457
- label_to_source: Map<string, string>;
1458
- persona_labels: Map<string, string>;
1459
- }) {
1460
- this.responses = args.responses;
1461
- this.label_to_source = args.label_to_source;
1462
- this.persona_labels = args.persona_labels;
1463
- }
1464
- }
1465
-
1466
- export interface RunPeerReviewOptions {
1467
- budget?: CostBudget | null;
1468
- table?: PriceTable | null;
1469
- on_overrun?: OnOverrunCallback | null;
1470
- project?: ProjectContext | null;
1471
- original_ask?: string;
1472
- max_tokens?: number;
1473
- persona_labels?: Map<string, string> | null;
1474
- }
1475
1431
 
1476
1432
  /**
1477
1433
  * Karpathy peer-review pass (Phase 5 / F1).
@@ -1537,12 +1493,23 @@ export function run_peer_review(
1537
1493
 
1538
1494
  const persona_labels = new Map<string, string>(opts.persona_labels ?? []);
1539
1495
  const review_responses: CouncilResponse[] = [];
1540
- // ── final label_to_source map captured from the LAST member call
1541
- // so the renderer / JSON dump has the deterministic A/B mapping.
1542
- // Each member sees a different N-1 subset (self filtered), but the
1543
- // ordering of `by_source` stays stable, so the label assignment is
1544
- // deterministic per artefact run.
1545
- let last_label_to_source = new Map<string, string>();
1496
+ // ── What is deterministic here, and what is NOT — corrected 2026-08-23 (step 1.3).
1497
+ //
1498
+ // DETERMINISTIC: the iteration order of `by_source`, and therefore the input order
1499
+ // handed to `anonymize_responses`. Two runs over the same config produce the same
1500
+ // per-reviewer mapping.
1501
+ //
1502
+ // NOT deterministic ACROSS REVIEWERS, and this is what the old comment got wrong by
1503
+ // calling it "the deterministic A/B mapping": every reviewer receives a different
1504
+ // self-filtered subset, and `anonymize_responses` restarts its label counter on each
1505
+ // call (`consensus.ts:437`). So `Response-A` denotes a DIFFERENT member for every
1506
+ // reviewer, by construction. A single map cannot express that, and the one that used
1507
+ // to live here was overwritten per reviewer — so the artefact carried the last
1508
+ // reviewer's mapping for every quote in it.
1509
+ //
1510
+ // `by_reviewer` is the authoritative structure. `last_label_to_source` survives only
1511
+ // as the serialised compatibility field (`council_cli.ts:1480`/`:1492`).
1512
+ const label_to_source_by_reviewer = new Map<string, Map<string, string>>();
1546
1513
 
1547
1514
  for (const reviewer of members) {
1548
1515
  const scorer = `${reviewer.name}:${reviewer.model}`;
@@ -1558,13 +1525,31 @@ export function run_peer_review(
1558
1525
  if (others_pairs.length === 0) {
1559
1526
  continue;
1560
1527
  }
1561
- const [anon_text, label_to_source] = anonymize_responses(others_pairs, {
1528
+ // Step 1.5 — SEEDED order, not input order.
1529
+ //
1530
+ // Before this, `others_pairs` reached `anonymize_responses` in `by_source`
1531
+ // iteration order, so which member became `Response-A` was a pure function of
1532
+ // config order: identical across runs AND inferable from position. That is the
1533
+ // leak `blind_review.ts:52-54` already argues against for its own path ("which
1534
+ // pair becomes `Response-A` is not simply input order, so position alone leaks
1535
+ // nothing") — the two paths contradicted each other in code until now.
1536
+ //
1537
+ // Seed = the original ask plus the deliberation bodies. Run-scoped and
1538
+ // REPLAYABLE from the artefact's own contents; never `Math.random`, never
1539
+ // `Date`, because a label order nobody can reproduce makes the de-anonymization
1540
+ // block unverifiable. The reviewer is deliberately NOT in the seed: one shuffle
1541
+ // per run, so a reader comparing two reviewers' critiques of the same member is
1542
+ // comparing the same label.
1543
+ const shuffle_seed = [opts.original_ask ?? '', ...[...by_source.values()].map((r) => r.text)].join('\0');
1544
+ const order = deterministic_shuffle_indices(shuffle_seed, others_pairs.length);
1545
+ const shuffled_pairs = order.map((i) => others_pairs[i]!);
1546
+ const [anon_text, label_to_source] = anonymize_responses(shuffled_pairs, {
1562
1547
  persona_labels,
1563
1548
  });
1564
1549
  if (anon_text.size === 0) {
1565
1550
  continue;
1566
1551
  }
1567
- last_label_to_source = label_to_source;
1552
+ label_to_source_by_reviewer.set(scorer, label_to_source);
1568
1553
  const question = new CouncilQuestion({
1569
1554
  mode: 'prompt',
1570
1555
  user_prompt: build_peer_review_user_prompt(anon_text),
@@ -1579,54 +1564,22 @@ export function run_peer_review(
1579
1564
  review_responses.push(...reviewed);
1580
1565
  }
1581
1566
 
1567
+ // DERIVED after the loop, never assigned inside it (step 1.2's verify is a grep for
1568
+ // exactly that). The compatibility field is the last reviewer's mapping, and deriving
1569
+ // it here rather than accumulating it makes that explicit: nothing in the loop
1570
+ // pretends to maintain a run-wide map.
1571
+ const reviewer_maps = [...label_to_source_by_reviewer.values()];
1572
+ const flat_compat = reviewer_maps.length === 0 ? new Map<string, string>() : reviewer_maps[reviewer_maps.length - 1]!;
1573
+
1582
1574
  return new PeerReviewResult({
1583
1575
  responses: review_responses,
1584
- label_to_source: last_label_to_source,
1576
+ label_to_source_by_reviewer,
1577
+ label_to_source: flat_compat,
1585
1578
  persona_labels,
1586
1579
  });
1587
1580
  }
1588
1581
 
1589
- /**
1590
- * Bundle returned by `run_consensus_scoring()`.
1591
- *
1592
- * `bucket` is renderer-ready; `findings`, `scores`, and `metadata`
1593
- * are kept for audit-trail JSON (council-sessions/*.json).
1594
- */
1595
- export class ConsensusResult {
1596
- bucket: ConsensusBucket;
1597
- findings: Finding[];
1598
- scores: FindingScore[];
1599
- metadata: Map<string, ConsensusMetadata>;
1600
- extraction_responses: CouncilResponse[];
1601
- scoring_responses: CouncilResponse[];
1602
1582
 
1603
- constructor(args: {
1604
- bucket: ConsensusBucket;
1605
- findings: Finding[];
1606
- scores: FindingScore[];
1607
- metadata: Map<string, ConsensusMetadata>;
1608
- extraction_responses: CouncilResponse[];
1609
- scoring_responses: CouncilResponse[];
1610
- }) {
1611
- this.bucket = args.bucket;
1612
- this.findings = args.findings;
1613
- this.scores = args.scores;
1614
- this.metadata = args.metadata;
1615
- this.extraction_responses = args.extraction_responses;
1616
- this.scoring_responses = args.scoring_responses;
1617
- }
1618
- }
1619
-
1620
- export interface RunConsensusScoringOptions {
1621
- budget?: CostBudget | null;
1622
- table?: PriceTable | null;
1623
- on_overrun?: OnOverrunCallback | null;
1624
- project?: ProjectContext | null;
1625
- original_ask?: string;
1626
- max_tokens?: number;
1627
- strong_threshold?: number;
1628
- minority_threshold?: number;
1629
- }
1630
1583
 
1631
1584
  /**
1632
1585
  * Two-pass consensus round (Phase 4 / F3).
@@ -1672,6 +1625,13 @@ export function run_consensus_scoring(
1672
1625
  }
1673
1626
  const extraction_responses: CouncilResponse[] = [];
1674
1627
  const all_findings: Finding[] = [];
1628
+ // Per-member extraction outcome — step 2.2. Recorded rather than derived from the
1629
+ // findings count, because "zero findings" and "could not be read" are different facts
1630
+ // and the count cannot tell them apart. `parsed-after-reask` is kept distinct from
1631
+ // `parsed`: a member that needed a second ask is a signal about the prompt or the
1632
+ // member, and collapsing it into `parsed` would hide the only evidence that the
1633
+ // re-ask is doing anything.
1634
+ const parse_outcomes = new Map<string, string>();
1675
1635
  for (const resp of deliberation_responses) {
1676
1636
  const member = member_by_name.get(resp.provider);
1677
1637
  if (member === undefined || resp.error || !_pyStrip(resp.text)) {
@@ -1693,9 +1653,45 @@ export function run_consensus_scoring(
1693
1653
  continue;
1694
1654
  }
1695
1655
  const source = `${member.name}:${member.model}`;
1696
- all_findings.push(
1697
- ...parse_findings_response(extracted[0]!.text, { source }),
1698
- );
1656
+ let ex = parse_findings_outcome(extracted[0]!.text, { source });
1657
+
1658
+ // Step 2.2 — ONE bounded re-ask on `parse_failed`, and one only.
1659
+ //
1660
+ // A member that said something no parser could read used to be indistinguishable
1661
+ // from a member that found nothing: `parse_findings_response` returned `[]` for
1662
+ // both, and this loop pushed the empty array with no branch. So an unparseable
1663
+ // answer counted as a clean zero-findings review.
1664
+ //
1665
+ // ONE re-ask, not a loop. A re-ask is a paid call, and an unbounded retry turns
1666
+ // one unparseable answer into open-ended spend — the failure mode the N=3
1667
+ // validation budget exists for, reached here by a different road. `empty` is NOT
1668
+ // re-asked: a member that said nothing has nothing to restate, and re-asking it
1669
+ // buys a second silence.
1670
+ if (ex.outcome === 'parse_failed') {
1671
+ const retry_q = new CouncilQuestion({
1672
+ mode: 'prompt',
1673
+ user_prompt:
1674
+ build_extraction_user_prompt(resp.text) +
1675
+ '\n\nYour previous answer could not be parsed. Reply with ONLY a JSON ' +
1676
+ 'array of {"id": string, "text": string} objects, no prose before or ' +
1677
+ 'after it. An empty array [] is a valid answer meaning you found nothing.',
1678
+ max_tokens,
1679
+ });
1680
+ const retried = consult([member], retry_q, budget, {
1681
+ table,
1682
+ on_overrun,
1683
+ project,
1684
+ original_ask,
1685
+ });
1686
+ extraction_responses.push(...retried);
1687
+ if (retried.length > 0 && !retried[0]!.error) {
1688
+ ex = parse_findings_outcome(retried[0]!.text, { source });
1689
+ }
1690
+ parse_outcomes.set(source, ex.outcome === 'parsed' ? 'parsed-after-reask' : 'parse_failed');
1691
+ } else {
1692
+ parse_outcomes.set(source, ex.outcome);
1693
+ }
1694
+ all_findings.push(...ex.findings);
1699
1695
  }
1700
1696
 
1701
1697
  if (all_findings.length === 0) {
@@ -1704,6 +1700,7 @@ export function run_consensus_scoring(
1704
1700
  findings: [],
1705
1701
  scores: [],
1706
1702
  metadata: new Map(),
1703
+ parse_outcomes,
1707
1704
  extraction_responses,
1708
1705
  scoring_responses: [],
1709
1706
  });
@@ -1761,6 +1758,7 @@ export function run_consensus_scoring(
1761
1758
  findings: all_findings,
1762
1759
  scores: all_scores,
1763
1760
  metadata,
1761
+ parse_outcomes,
1764
1762
  extraction_responses,
1765
1763
  scoring_responses,
1766
1764
  });
@@ -2061,11 +2059,8 @@ function _render_quorum_line(q: QuorumResult): string {
2061
2059
  // so 2-of-4 rendered as plain "concluded" with nothing to stop a reader
2062
2060
  // inferring convergence. Same sentence as stdout on purpose — one wording,
2063
2061
  // so neither surface can drift into being the softer one again.
2064
- const degraded =
2065
- q.present < q.total
2066
- ? ` ⚠️ DEGRADED — ${String(q.total - q.present)} member(s) did not answer; this is not convergence.`
2067
- : '';
2068
- return `**Quorum:** ${q.present}/${q.total} present, needed ${q.threshold} — ${verdict}.${solo}${degraded}`;
2062
+ // Wording shared with the stdout mirror; `formatAttendanceCaveats` owns it.
2063
+ return `**Quorum:** ${q.present}/${q.total} present, needed ${q.threshold} — ${verdict}.${solo}${formatAttendanceCaveats(q)}`;
2069
2064
  }
2070
2065
 
2071
2066
  /**
@@ -0,0 +1,166 @@
1
+ /**
2
+ * The two result bundles `orchestrator.ts` returns — extracted, a PURE MOVE.
3
+ *
4
+ * The reason is arithmetic. `orchestrator.ts` sits ~850 lines above the 1,500-line
5
+ * ceiling, so `check_source_size_budget` refuses ANY net growth in it: Phases 1 and 2 of
6
+ * `road-to-council-evidence-integrity` added 122 lines and the gate said so, correctly.
7
+ * Raising the baseline is what that gate's own message calls a defect rather than a fix.
8
+ *
9
+ * These two classes are the cleanest movable unit in the file: they are data carriers with
10
+ * no logic and no dependency on anything else in the orchestrator, so moving them changes
11
+ * no behaviour. `orchestrator.ts` re-exports both, so every existing import path keeps
12
+ * resolving.
13
+ *
14
+ * Extracting a data carrier rather than shaving the new documentation was the choice: the
15
+ * alternative was compressing comments that explain WHY a per-reviewer map exists and why
16
+ * the re-ask is bounded at one, which buys the same green from worse code.
17
+ */
18
+ import type { CouncilResponse } from './clients.js';
19
+ import { DEFAULT_MAX_TOKENS } from './clients.js';
20
+ import type { CostBudget } from './spend_gate.js';
21
+ import type { PriceTable } from './pricing.js';
22
+ import type { ProjectContext } from './project_context.js';
23
+ // TYPE-ONLY back-import. `OnOverrunCallback` is declared in orchestrator.ts, which also
24
+ // imports types from here — legal and runtime-free, because both directions are erased.
25
+ // The alternative was leaving the two options interfaces behind, which would have meant
26
+ // finding 19 lines elsewhere for no design reason.
27
+ import type { OnOverrunCallback } from './orchestrator.js';
28
+ import type { ConsensusBucket, ConsensusMetadata, Finding, FindingScore } from './consensus.js';
29
+
30
+ /**
31
+ * Bundle returned by `run_peer_review()` (Phase 5 / F1).
32
+ *
33
+ * `responses` carries the per-reviewer critiques. `label_to_source`
34
+ * is the anonymisation map captured server-side so the audit-trail
35
+ * JSON can rehydrate it without leaking provider identity to the
36
+ * member at prompt time.
37
+ *
38
+ * `persona_labels` is the (optional) Phase 6 / Step 3a wiring: when
39
+ * the deliberation was an advisor-mode run, the source → persona
40
+ * map flows through to the renderer so peer-review output can render
41
+ * as `Response A (Contrarian)`. Plain-member runs leave it empty.
42
+ */
43
+ /**
44
+ * One question put to the council. Moved here with the result bundles: it is the same
45
+ * kind of thing — a data carrier with no logic — and `orchestrator.ts` re-exports it, so
46
+ * every import path is unchanged.
47
+ */
48
+ export class CouncilQuestion {
49
+ mode: string; // one of: prompt, roadmap, diff, files
50
+ user_prompt: string; // bundled artefact text
51
+ max_tokens: number;
52
+
53
+ constructor(args: { mode: string; user_prompt: string; max_tokens?: number }) {
54
+ this.mode = args.mode;
55
+ this.user_prompt = args.user_prompt;
56
+ this.max_tokens = args.max_tokens ?? DEFAULT_MAX_TOKENS;
57
+ }
58
+ }
59
+
60
+ export class PeerReviewResult {
61
+ responses: CouncilResponse[];
62
+ /**
63
+ * PER-REVIEWER label→source attribution — the authoritative mapping.
64
+ *
65
+ * Keyed by `provider:model`, because that is the identity `by_source` uses and the
66
+ * identity a quote in the artefact has to resolve against. Added by step 1.2 of
67
+ * `road-to-council-evidence-integrity`: each reviewer sees a DIFFERENT
68
+ * self-filtered subset, and `anonymize_responses` restarts its label counter per
69
+ * call, so `Response-A` means a different member for every reviewer. One map
70
+ * cannot express that.
71
+ */
72
+ label_to_source_by_reviewer: Map<string, Map<string, string>>;
73
+ /**
74
+ * Flat compatibility view — the LAST reviewer's mapping, kept only because
75
+ * `council_cli.ts:1480` serialises this field and `:1492` reads it back.
76
+ *
77
+ * It is wrong for any reviewer but the last, and it is retained rather than
78
+ * removed so the serialisation contract does not break in the same change that
79
+ * fixes the attribution. Read `label_to_source_by_reviewer` for anything that
80
+ * resolves a quote.
81
+ */
82
+ label_to_source: Map<string, string>;
83
+ persona_labels: Map<string, string>;
84
+
85
+ constructor(args: {
86
+ responses: CouncilResponse[];
87
+ label_to_source_by_reviewer?: Map<string, Map<string, string>>;
88
+ label_to_source: Map<string, string>;
89
+ persona_labels: Map<string, string>;
90
+ }) {
91
+ this.responses = args.responses;
92
+ this.label_to_source_by_reviewer = args.label_to_source_by_reviewer ?? new Map();
93
+ this.label_to_source = args.label_to_source;
94
+ this.persona_labels = args.persona_labels;
95
+ }
96
+ }
97
+
98
+ /**
99
+ * Bundle returned by `run_consensus_scoring()`.
100
+ *
101
+ * `bucket` is renderer-ready; `findings`, `scores`, and `metadata`
102
+ * are kept for audit-trail JSON (council-sessions/*.json).
103
+ */
104
+ export class ConsensusResult {
105
+ bucket: ConsensusBucket;
106
+ findings: Finding[];
107
+ scores: FindingScore[];
108
+ metadata: Map<string, ConsensusMetadata>;
109
+ /**
110
+ * Per-member extraction outcome, keyed by `provider:model` — step 2.2 of
111
+ * `road-to-council-evidence-integrity`.
112
+ *
113
+ * `parsed` · `parsed-after-reask` · `empty` · `parse_failed`. Recorded rather than
114
+ * derived from the findings count, because "found nothing" and "could not be read"
115
+ * are different facts and a count cannot tell them apart — which is exactly how an
116
+ * unparseable answer used to read as a clean zero-findings review.
117
+ *
118
+ * `parsed-after-reask` is deliberately distinct from `parsed`: a member needing a
119
+ * second ask is a signal about the prompt or the member, and folding it into `parsed`
120
+ * would hide the only evidence that the re-ask does anything.
121
+ *
122
+ * Additive and optional, so no existing constructor call changes.
123
+ */
124
+ parse_outcomes: Map<string, string>;
125
+ extraction_responses: CouncilResponse[];
126
+ scoring_responses: CouncilResponse[];
127
+
128
+ constructor(args: {
129
+ bucket: ConsensusBucket;
130
+ findings: Finding[];
131
+ scores: FindingScore[];
132
+ metadata: Map<string, ConsensusMetadata>;
133
+ parse_outcomes?: Map<string, string>;
134
+ extraction_responses: CouncilResponse[];
135
+ scoring_responses: CouncilResponse[];
136
+ }) {
137
+ this.bucket = args.bucket;
138
+ this.findings = args.findings;
139
+ this.scores = args.scores;
140
+ this.metadata = args.metadata;
141
+ this.parse_outcomes = args.parse_outcomes ?? new Map();
142
+ this.extraction_responses = args.extraction_responses;
143
+ this.scoring_responses = args.scoring_responses;
144
+ }
145
+ }
146
+
147
+ export interface RunPeerReviewOptions {
148
+ budget?: CostBudget | null;
149
+ table?: PriceTable | null;
150
+ on_overrun?: OnOverrunCallback | null;
151
+ project?: ProjectContext | null;
152
+ original_ask?: string;
153
+ max_tokens?: number;
154
+ persona_labels?: Map<string, string> | null;
155
+ }
156
+
157
+ export interface RunConsensusScoringOptions {
158
+ budget?: CostBudget | null;
159
+ table?: PriceTable | null;
160
+ on_overrun?: OnOverrunCallback | null;
161
+ project?: ProjectContext | null;
162
+ original_ask?: string;
163
+ max_tokens?: number;
164
+ strong_threshold?: number;
165
+ minority_threshold?: number;
166
+ }
@@ -120,9 +120,11 @@ MUST:
120
120
  suggestion. No hand-wave "this is probably slow".
121
121
  3. State at least one suggestion you explicitly REJECT as
122
122
  low-leverage, so the user does not over-engineer.
123
- 4. Mark at least one suggestion as hypothesis (requires measurement
124
- before committing) versus confirmed (already supported by the
125
- evidence in the artefact).`;
123
+ 4. Mark at least one suggestion \`evidence: speculative\` (requires
124
+ measurement before committing) against at least one marked
125
+ \`evidence: confirmed\` (already supported by the artefact). Use the
126
+ same three-term scale as every other lens — \`confirmed\` |
127
+ \`inferred\` | \`speculative\` — never a lens-local synonym.`;
126
128
 
127
129
  export const ANALYSIS_MODE = `The artefact is a local analysis output (from a project analyzer,
128
130
  audit script, or codebase scan). Critique the **analysis itself**, not
@@ -315,8 +317,13 @@ metadata shape as Top-10.
315
317
 
316
318
  ### Outliers
317
319
  Single-reviewer findings the others did not engage with. Keep them
318
- — they are signal for a future deeper analysis pass — but mark each
319
- as \`unverified-by-council\`.
320
+ — they are signal for a future deeper analysis pass — and give each
321
+ the SAME metadata shape as Top-10, including its \`evidence:\` term.
322
+ The heading is the corroboration statement: everything under it was
323
+ raised by one reviewer and engaged with by none. Do not invent a
324
+ separate certainty word for that; \`evidence:\` measures how well a
325
+ finding is supported, and being alone in raising it is a different
326
+ property the section already carries.
320
327
 
321
328
  ### Kill criteria
322
329
  Observable conditions that would falsify the analysis's leading finding
@@ -37,6 +37,23 @@ export interface QuorumResult {
37
37
  readonly total: number;
38
38
  /** Members that actually produced a usable response. */
39
39
  readonly present: number;
40
+ /**
41
+ * Members that answered with something no parser could read.
42
+ *
43
+ * Deliberately OPTIONAL and omitted when zero, never defaulted to `0`. Every
44
+ * assertion over a `QuorumResult` in this tree is an exact-shape `toEqual`,
45
+ * and the field also rides into `payload['quorum']`, so a defaulted key would
46
+ * be a silent breaking change to a serialized surface for the overwhelmingly
47
+ * common case where nothing was unparseable.
48
+ *
49
+ * Such a member is NOT in `present`: the byte check that admits it
50
+ * (`text.trim() !== ''`) is true of a prose refusal, which is exactly the
51
+ * "looked more settled than the run was" shape the empty-body fix already
52
+ * closed one case of. It is not plainly absent either — it answered, and the
53
+ * distinction is what a reader needs to tell "found nothing" from
54
+ * "said something unreadable".
55
+ */
56
+ readonly unparsed?: number;
40
57
  }
41
58
 
42
59
  /**
@@ -76,11 +93,75 @@ export function evaluateQuorum(
76
93
  total: number,
77
94
  present: number,
78
95
  setting: QuorumSetting = 'majority',
96
+ unparsed = 0,
79
97
  ): QuorumResult {
80
98
  const threshold = resolveQuorumThreshold(total, setting);
81
99
  const clampedPresent = Math.min(Math.max(present, 0), total);
82
100
  const status: QuorumStatus = clampedPresent >= threshold ? 'concluded' : 'inconclusive';
83
- return { status, threshold, total, present: clampedPresent };
101
+ const clampedUnparsed = Math.min(Math.max(unparsed, 0), total - clampedPresent);
102
+ // Spread-on-condition rather than a defaulted key — see `QuorumResult.unparsed`.
103
+ return { status, threshold, total, present: clampedPresent, ...(clampedUnparsed > 0 ? { unparsed: clampedUnparsed } : {}) };
104
+ }
105
+
106
+ /**
107
+ * Move `n` members out of `present` and into the unparsed bucket.
108
+ *
109
+ * The run path derives findings-parse outcomes only AFTER `_postRunQuorum` has
110
+ * emitted the post-run attendance event, and that ordering is deliberate: the
111
+ * event is a TRANSPORT-level reading and stays one, so a consumer computing an
112
+ * attendance rate over the log keeps the denominator it has always had. The
113
+ * rendered artefact is where AC-2 asks for the distinction, and this is how it
114
+ * gets there — the same reading, re-derived once the parser has spoken.
115
+ *
116
+ * `threshold` is not recomputed: it resolves from `total` and the configured
117
+ * setting, neither of which this function touches. `status` IS recomputed,
118
+ * because moving a member out of `present` can legitimately turn a concluded
119
+ * pass inconclusive — which is the whole point, and the same consequence the
120
+ * empty-body fix already accepted.
121
+ */
122
+ export function withUnparsed(q: QuorumResult, unparsed: number): QuorumResult {
123
+ if (unparsed <= 0) {
124
+ return q;
125
+ }
126
+ const present = Math.max(0, q.present - unparsed);
127
+ const moved = q.present - present;
128
+ return {
129
+ status: present >= q.threshold ? 'concluded' : 'inconclusive',
130
+ threshold: q.threshold,
131
+ total: q.total,
132
+ present,
133
+ ...(moved > 0 ? { unparsed: moved } : {}),
134
+ };
135
+ }
136
+
137
+ /**
138
+ * The attendance caveats both banners append — ONE wording, one place.
139
+ *
140
+ * `orchestrator.ts::_render_quorum_line` and `quorum_wiring.ts::_format_quorum_line`
141
+ * are deliberate mirrors, and the DEGRADED sentence carries a note explaining
142
+ * that they must stay byte-identical "so neither surface can drift into being
143
+ * the softer one again". Two copies of a sentence with that requirement is a
144
+ * drift waiting to happen, so Step 2.3 extracted it here rather than adding a
145
+ * third clause to each copy by hand.
146
+ *
147
+ * Two caveats, and they are disjoint on purpose:
148
+ *
149
+ * - `did not answer` counts only the SILENT members. An unparsed member
150
+ * answered, so counting it here would make the line contradict itself — the
151
+ * exact "says something the run did not establish" failure this roadmap is
152
+ * about, in the sentence written to prevent it.
153
+ * - `present-unparsed` counts the members whose answer no parser could read.
154
+ */
155
+ export function formatAttendanceCaveats(q: QuorumResult): string {
156
+ const unparsed = q.unparsed ?? 0;
157
+ const silent = q.total - q.present - unparsed;
158
+ const degraded =
159
+ silent > 0 ? ` ⚠️ DEGRADED — ${String(silent)} member(s) did not answer; this is not convergence.` : '';
160
+ const unreadable =
161
+ unparsed > 0
162
+ ? ` ⚠️ ${String(unparsed)} present-unparsed — answered, and no parser could read it; not counted toward attendance.`
163
+ : '';
164
+ return `${degraded}${unreadable}`;
84
165
  }
85
166
 
86
167
  /**