@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
@@ -8,12 +8,53 @@
8
8
  #
9
9
  # Usage:
10
10
  # stitch.sh <manifest.json> <output.mp4>
11
+ # [--mode cut|handoff]
12
+ # [--xfade <seconds>]
11
13
  # [--skip-scene <id> ...]
12
14
  # [--abort-on-missing | --continue]
13
15
  #
14
- # NOT a flag: --crossfade. It is parsed and REFUSED (exit 2). See
15
- # "Refused flags" below — it is listed so a caller who read the old
16
- # usage line gets an error instead of a hard cut.
16
+ # Modes:
17
+ # --mode cut (DEFAULT) `ffmpeg -f concat -c copy`. Stream copy, no
18
+ # generation loss, no filtergraph. Byte-for-byte the
19
+ # behaviour this script has always had; passing the flag
20
+ # explicitly changes nothing.
21
+ # --mode handoff Re-encode path (`libx264 -crf 20 -g 8 +faststart -an`)
22
+ # for continuity chains, where clip i+1 was conditioned on
23
+ # the rendered last frame of clip i. Video only: `-an`
24
+ # DROPS every audio track, which is stated on stderr on
25
+ # every run rather than discovered in the output.
26
+ #
27
+ # --xfade <s> Only valid with `--mode handoff`; ceiling 0.25 s. A short
28
+ # fade applied ONLY at seams whose manifest row says
29
+ # `continuity: handoff|connector` — insurance against a
30
+ # visible pop, never a transition effect. Cut seams in the
31
+ # same run stay hard cuts. Offsets are computed from
32
+ # ffprobe'd durations, not from the manifest's declared
33
+ # ones: the accumulated-length-minus-fade arithmetic is the
34
+ # classic trap here and a declared duration that is 40 ms
35
+ # off silently shifts every later seam.
36
+ #
37
+ # NOT a flag: --crossfade. It is parsed and REFUSED (exit 2) in EVERY mode.
38
+ # See "Refused flags" below — it is listed so a caller who read the old usage
39
+ # line gets an error instead of a hard cut. `--mode handoff --xfade <s>` is
40
+ # the supported way to ask for a fade.
41
+ #
42
+ # port_invariants — what must survive a re-implementation:
43
+ # 1. hard-cut default — `--mode cut` is the default and stream-copies
44
+ # (`-c copy`); a port that re-encodes by default has changed the output
45
+ # of every existing caller without telling anyone.
46
+ # 2. refusal over silent downgrade — an unimplemented or out-of-bounds
47
+ # request exits non-zero BEFORE any work, and never falls through to a
48
+ # near-miss (`--crossfade`, `--xfade` above 0.25 s, `--xfade` in cut
49
+ # mode, an unknown flag, a missing clip). Reporting success for output
50
+ # the caller did not ask for is the one failure this script exists to
51
+ # not have.
52
+ # 3. handoff frame = rendered frame — a handoff seam joins clips where the
53
+ # later one was conditioned on the earlier one's RENDERED last frame,
54
+ # never on its own still. A port that re-conditions from the source
55
+ # still produces a plausible-looking chain that does not actually
56
+ # continue the shot.
57
+ # Contract: docs/contracts/skill-bundled-assets.md § Port invariants.
17
58
  #
18
59
  # Failure semantics:
19
60
  # - Missing clip → fail loud with scene_id and re-render hint
@@ -40,6 +81,10 @@
40
81
  # only --skip-scene and --continue and rejects anything else. So the
41
82
  # honest state is a refusal, not a silent downgrade and not a
42
83
  # filtergraph shipped into a script with no test harness.
84
+ # The re-encode path this refusal used to ask for now exists as
85
+ # `--mode handoff` (+ optional `--xfade <s>`), with a test harness
86
+ # under tests/scripts/. The refusal stays: `--crossfade` named a
87
+ # transition on the stream-copy path, which is still impossible.
43
88
 
44
89
  set -euo pipefail
45
90
 
@@ -58,27 +103,59 @@ esac
58
103
  MANIFEST="${1:-}"
59
104
  OUTPUT="${2:-}"
60
105
  [ -n "${MANIFEST}" ] && [ -n "${OUTPUT}" ] \
61
- || aiv_die 2 "usage: stitch.sh <manifest.json> <output.mp4> [--skip-scene <id>] [--abort-on-missing|--continue]"
106
+ || aiv_die 2 "usage: stitch.sh <manifest.json> <output.mp4> [--mode cut|handoff] [--xfade <seconds>] [--skip-scene <id>] [--abort-on-missing|--continue]"
62
107
  [ -r "${MANIFEST}" ] || aiv_die 2 "manifest not readable: ${MANIFEST}"
63
108
  shift 2 || true
64
109
 
65
110
  SKIP_IDS=""
66
111
  MISSING_POLICY="abort"
112
+ MODE="cut"
113
+ XFADE=""
114
+ XFADE_MAX="0.25"
67
115
  while [ "$#" -gt 0 ]; do
68
116
  case "$1" in
69
117
  --skip-scene) SKIP_IDS="${SKIP_IDS} ${2:-}"; shift 2 ;;
70
118
  --abort-on-missing) MISSING_POLICY="abort"; shift ;;
71
119
  --continue) MISSING_POLICY="continue"; shift ;;
120
+ --mode) MODE="${2:-}"; shift 2 ;;
121
+ --xfade) XFADE="${2:-}"; shift 2 ;;
72
122
  --crossfade)
73
123
  # Refused HERE — before the dry-run branch, before ffmpeg, before any
74
124
  # output. The old code warned after the dry-run exit and then concatenated
75
125
  # anyway, so a caller asking for a crossfade got a hard cut and exit 0.
76
- aiv_die 2 "stitch.sh: --crossfade is not implemented and will not be silently downgraded. The output path is 'ffmpeg -f concat -c copy', and stream copy precludes any filtergraph, so xfade/acrossfade require a re-encode path this script does not have. Re-run without --crossfade for a hard-cut concat, or open a roadmap item for the re-encode path."
126
+ aiv_die 2 "stitch.sh: --crossfade is not implemented and will not be silently downgraded. The output path of --mode cut is 'ffmpeg -f concat -c copy', and stream copy precludes any filtergraph, so xfade/acrossfade cannot exist there. Re-run without --crossfade for a hard-cut concat, or use '--mode handoff --xfade <seconds>' (ceiling ${XFADE_MAX}s) for the re-encode path, which applies the fade only at seams whose manifest row says continuity: handoff|connector."
77
127
  ;;
78
128
  *) aiv_die 2 "stitch.sh: unknown flag '$1'" ;;
79
129
  esac
80
130
  done
81
131
 
132
+ case "${MODE}" in
133
+ cut|handoff) ;;
134
+ *) aiv_die 2 "stitch.sh: unknown --mode '${MODE}' (expected cut|handoff)" ;;
135
+ esac
136
+
137
+ if [ -n "${XFADE}" ]; then
138
+ # Refused, never ignored: an --xfade the run cannot honour would otherwise
139
+ # deliver a hard cut and report success — the exact shape of the --crossfade
140
+ # defect above.
141
+ [ "${MODE}" = "handoff" ] \
142
+ || aiv_die 2 "stitch.sh: --xfade requires '--mode handoff' — the cut path is 'ffmpeg -f concat -c copy' and stream copy precludes a filtergraph. Re-run with --mode handoff, or drop --xfade for a hard-cut concat."
143
+ printf '%s' "${XFADE}" | grep -Eq '^[0-9]+(\.[0-9]+)?$' \
144
+ || aiv_die 2 "stitch.sh: --xfade must be a non-negative number of seconds, got '${XFADE}'"
145
+ awk -v x="${XFADE}" -v m="${XFADE_MAX}" 'BEGIN { exit !(x > 0 && x <= m) }' \
146
+ || aiv_die 2 "stitch.sh: --xfade ${XFADE}s is outside the allowed range (0 < s <= ${XFADE_MAX}) — a longer fade is a transition effect, not seam insurance"
147
+ fi
148
+
149
+ # The plan/success JSON gains a `mode` key ONLY in handoff mode. Even an
150
+ # additive key changes the stdout every existing caller reads, and "cut behaves
151
+ # as it does today" is the invariant that path is held to. Absent means cut.
152
+ MODE_JSON=""
153
+ if [ "${MODE}" = "handoff" ]; then
154
+ MODE_JSON=',"mode":"handoff"'
155
+ printf 'stitch: --mode handoff RE-ENCODES (libx264 -crf 20 -g 8 +faststart -an) — the cut path stream-copies. Audio is dropped by -an; mux a bed afterwards if the chain needs one.\n' >&2
156
+ [ "${DRYRUN_FLAG}" -eq 0 ] && aiv_require_cmd ffprobe
157
+ fi
158
+
82
159
  skip_match() {
83
160
  local id="$1" s
84
161
  for s in ${SKIP_IDS}; do
@@ -92,6 +169,11 @@ WORK_DIR="$(mktemp -d -t aiv-stitch-XXXXXX)"
92
169
  trap 'rm -rf "${WORK_DIR}"' EXIT
93
170
  CONCAT_LIST="${WORK_DIR}/concat.txt"
94
171
  : > "${CONCAT_LIST}"
172
+ # Ordered `<continuity>\t<validated path>` rows — the handoff filtergraph needs
173
+ # to know WHICH seams may fade, and the concat demuxer list cannot carry that.
174
+ # Written only in handoff mode, so the cut path is untouched.
175
+ SEQ_LIST="${WORK_DIR}/seq.tsv"
176
+ : > "${SEQ_LIST}"
95
177
 
96
178
  # Accept both bare-array manifests and the documented object shape
97
179
  # (`{ "scenes": [...] }`). Field names tolerate the legacy
@@ -107,6 +189,14 @@ while IFS= read -r row; do
107
189
  clip_path="$(printf '%s' "${row}" | jq -r '.clip_path // .expected_clip')"
108
190
  audio_embedded="$(printf '%s' "${row}" | jq -r '.audio_embedded // false')"
109
191
  audio_path="$(printf '%s' "${row}" | jq -r '.audio_path // empty')"
192
+ continuity="cut"
193
+ if [ "${MODE}" = "handoff" ]; then
194
+ continuity="$(printf '%s' "${row}" | jq -r '.continuity // "cut"')"
195
+ case "${continuity}" in
196
+ cut|handoff|connector) ;;
197
+ *) aiv_die 2 "stitch.sh: scene=${scene_id} unknown continuity '${continuity}' (expected cut|handoff|connector)" ;;
198
+ esac
199
+ fi
110
200
 
111
201
  case "${clip_path}" in
112
202
  /*) ;;
@@ -155,8 +245,14 @@ while IFS= read -r row; do
155
245
  -c:v copy -c:a aac -shortest "${muxed}" >/dev/null \
156
246
  || aiv_die 8 "ffmpeg mux failed for scene=${scene_id}"
157
247
  printf "file '%s'\n" "${muxed}" >> "${CONCAT_LIST}"
248
+ if [ "${MODE}" = "handoff" ]; then
249
+ printf '%s\t%s\n' "${continuity}" "${muxed}" >> "${SEQ_LIST}"
250
+ fi
158
251
  else
159
252
  printf "file '%s'\n" "${clip_path}" >> "${CONCAT_LIST}"
253
+ if [ "${MODE}" = "handoff" ]; then
254
+ printf '%s\t%s\n' "${continuity}" "${clip_path}" >> "${SEQ_LIST}"
255
+ fi
160
256
  fi
161
257
  count=$((count + 1))
162
258
  done <<EOF
@@ -168,12 +264,97 @@ EOF
168
264
  if [ "${DRYRUN_FLAG}" -eq 1 ]; then
169
265
  printf 'stitch: dry-run plan (output=%s, scenes=%d):\n' "${OUTPUT}" "${count}" >&2
170
266
  printf '%b' "${plan}" >&2
171
- printf '{"output":"%s","scenes":%d,"missing":0,"dry_run":true}\n' "${OUTPUT}" "${count}"
267
+ printf '{"output":"%s","scenes":%d,"missing":0,"dry_run":true%s}\n' \
268
+ "${OUTPUT}" "${count}" "${MODE_JSON}"
172
269
  exit 0
173
270
  fi
174
271
 
175
- ffmpeg -loglevel error -y -f concat -safe 0 -i "${CONCAT_LIST}" \
176
- -c copy "${OUTPUT}" >/dev/null \
177
- || aiv_die 8 "ffmpeg concat failed (manifest=${MANIFEST}, output=${OUTPUT})"
272
+ # The re-encode settings are one constant, used by both handoff branches, so a
273
+ # port cannot drift them apart.
274
+ HANDOFF_VCODEC="libx264"
275
+ HANDOFF_ARGS="-crf 20 -g 8 -pix_fmt yuv420p -movflags +faststart -an"
276
+
277
+ _probe_duration() {
278
+ ffprobe -v error -show_entries format=duration -of csv=p=0 "$1" 2>/dev/null \
279
+ | head -1
280
+ }
281
+
282
+ if [ "${MODE}" = "handoff" ]; then
283
+ seq_count="$(wc -l < "${SEQ_LIST}" | tr -d ' ')"
284
+ [ "${seq_count}" -gt 0 ] || aiv_die 7 "stitch: handoff mode found no usable clips"
285
+
286
+ if [ -z "${XFADE}" ] || [ "${seq_count}" -eq 1 ]; then
287
+ # No fade requested (or nothing to fade across): the seams stay hard cuts,
288
+ # the only difference from --mode cut is the re-encode. Same concat demuxer,
289
+ # so clip order and skip handling are shared with the cut path.
290
+ # shellcheck disable=SC2086
291
+ ffmpeg -loglevel error -y -f concat -safe 0 -i "${CONCAT_LIST}" \
292
+ -c:v "${HANDOFF_VCODEC}" ${HANDOFF_ARGS} "${OUTPUT}" >/dev/null \
293
+ || aiv_die 8 "ffmpeg handoff re-encode failed (manifest=${MANIFEST}, output=${OUTPUT})"
294
+ else
295
+ # Filtergraph path. Every input is normalised to the FIRST clip's frame
296
+ # rate and to yuv420p/SAR 1 — xfade refuses mismatched inputs, and a
297
+ # mismatch here would surface as an opaque filter error rather than as the
298
+ # source-clip problem it is.
299
+ first_clip="$(sed -n '1p' "${SEQ_LIST}" | cut -f2)"
300
+ rate="$(ffprobe -v error -select_streams v:0 -show_entries stream=r_frame_rate \
301
+ -of csv=p=0 "${first_clip}" 2>/dev/null | head -1)"
302
+ [ -n "${rate}" ] || aiv_die 8 "stitch: cannot read frame rate of ${first_clip}"
303
+
304
+ ff_inputs=""
305
+ filter=""
306
+ i=0
307
+ while [ "${i}" -lt "${seq_count}" ]; do
308
+ line_no=$((i + 1))
309
+ p="$(sed -n "${line_no}p" "${SEQ_LIST}" | cut -f2)"
310
+ ff_inputs="${ff_inputs} -i ${p}"
311
+ filter="${filter}[${i}:v]fps=${rate},format=yuv420p,setsar=1,settb=AVTB[n${i}];"
312
+ i=$((i + 1))
313
+ done
314
+
315
+ acc_label="[n0]"
316
+ acc_dur="$(_probe_duration "$(sed -n '1p' "${SEQ_LIST}" | cut -f2)")"
317
+ [ -n "${acc_dur}" ] || aiv_die 8 "stitch: cannot read duration of the first clip"
318
+ faded=0
319
+ i=1
320
+ while [ "${i}" -lt "${seq_count}" ]; do
321
+ line_no=$((i + 1))
322
+ cont="$(sed -n "${line_no}p" "${SEQ_LIST}" | cut -f1)"
323
+ p="$(sed -n "${line_no}p" "${SEQ_LIST}" | cut -f2)"
324
+ dur="$(_probe_duration "${p}")"
325
+ [ -n "${dur}" ] || aiv_die 8 "stitch: cannot read duration of ${p}"
326
+ if [ "${cont}" = "handoff" ] || [ "${cont}" = "connector" ]; then
327
+ # offset = accumulated length so far MINUS the fade; the fade eats the
328
+ # tail of the accumulated stream, so the total shortens by exactly one
329
+ # xfade per faded seam.
330
+ offset="$(awk -v a="${acc_dur}" -v x="${XFADE}" 'BEGIN { printf "%.6f", a - x }')"
331
+ awk -v o="${offset}" 'BEGIN { exit !(o > 0) }' \
332
+ || aiv_die 7 "stitch: --xfade ${XFADE}s does not fit before seam ${i} (accumulated length ${acc_dur}s)"
333
+ filter="${filter}${acc_label}[n${i}]xfade=transition=fade:duration=${XFADE}:offset=${offset}[x${i}];"
334
+ acc_dur="$(awk -v a="${acc_dur}" -v d="${dur}" -v x="${XFADE}" 'BEGIN { printf "%.6f", a + d - x }')"
335
+ faded=$((faded + 1))
336
+ else
337
+ filter="${filter}${acc_label}[n${i}]concat=n=2:v=1:a=0[x${i}];"
338
+ acc_dur="$(awk -v a="${acc_dur}" -v d="${dur}" 'BEGIN { printf "%.6f", a + d }')"
339
+ fi
340
+ acc_label="[x${i}]"
341
+ i=$((i + 1))
342
+ done
343
+ filter="${filter%;}"
344
+
345
+ printf 'stitch: handoff filtergraph — %d clip(s), %d faded seam(s) at %ss, %d hard cut(s)\n' \
346
+ "${seq_count}" "${faded}" "${XFADE}" "$((seq_count - 1 - faded))" >&2
347
+
348
+ # shellcheck disable=SC2086
349
+ ffmpeg -loglevel error -y ${ff_inputs} -filter_complex "${filter}" \
350
+ -map "${acc_label}" -c:v "${HANDOFF_VCODEC}" ${HANDOFF_ARGS} "${OUTPUT}" >/dev/null \
351
+ || aiv_die 8 "ffmpeg handoff xfade failed (manifest=${MANIFEST}, output=${OUTPUT})"
352
+ fi
353
+ else
354
+ ffmpeg -loglevel error -y -f concat -safe 0 -i "${CONCAT_LIST}" \
355
+ -c copy "${OUTPUT}" >/dev/null \
356
+ || aiv_die 8 "ffmpeg concat failed (manifest=${MANIFEST}, output=${OUTPUT})"
357
+ fi
178
358
 
179
- printf '{"output":"%s","scenes":%d,"missing":%d}\n' "${OUTPUT}" "${count}" "${missing}"
359
+ printf '{"output":"%s","scenes":%d,"missing":%d%s}\n' \
360
+ "${OUTPUT}" "${count}" "${missing}" "${MODE_JSON}"
@@ -19,6 +19,10 @@
19
19
  # PNG magic; pairwise NCC ≥ 0.95 when `compare` is available.
20
20
  # When unavailable, asserts byte-identity (the three frames are
21
21
  # committed identical for the offline path).
22
+ # 7. end_image refusal: an adapter handed `end_image` for a model whose
23
+ # model-capabilities entry answers `end_frame: null` exits non-zero
24
+ # and names the model — it never drops the image (adapter-contract.md
25
+ # § end_image, exit 12).
22
26
  #
23
27
  # Exit 0 = all assertions pass; 1 = at least one failure (counted +
24
28
  # summarized at the end).
@@ -47,7 +51,7 @@ require jq || exit 1
47
51
  printf '\n== test-pipeline.sh — banana-arc golden run (offline) ==\n\n'
48
52
 
49
53
  # ---------------------------------------------------------------- 1
50
- printf '[1/6] parse-blueprint vs. expected.json\n'
54
+ printf '[1/8] parse-blueprint vs. expected.json\n'
51
55
  SCENES="01-simple 02-dialogue-native-audio 03-edge-duration"
52
56
  for s in $SCENES; do
53
57
  actual="$(bash "$ROOT/src/scripts/ai-video/lib/parse-blueprint.sh" "$PROJECT/scenes/$s/blueprint.txt" 2>/dev/null \
@@ -63,7 +67,7 @@ for s in $SCENES; do
63
67
  done
64
68
 
65
69
  # ---------------------------------------------------------------- 2
66
- printf '\n[2/6] character.json descriptors verbatim in prompt.subject\n'
70
+ printf '\n[2/8] character.json descriptors verbatim in prompt.subject\n'
67
71
  SILHOUETTE="$(jq -r '.characters[0].silhouette' "$PROJECT/character.json")"
68
72
  PALETTE="$(jq -r '.characters[0].palette' "$PROJECT/character.json")"
69
73
  WARDROBE="$(jq -r '.characters[0].wardrobe' "$PROJECT/character.json")"
@@ -84,7 +88,7 @@ for s in $SCENES; do
84
88
  done
85
89
 
86
90
  # ---------------------------------------------------------------- 3
87
- printf '\n[3/6] audio.* branching matches manifest\n'
91
+ printf '\n[3/8] audio.* branching matches manifest\n'
88
92
  for entry in 01-simple:false 02-dialogue-native-audio:true 03-edge-duration:false; do
89
93
  s="${entry%%:*}"
90
94
  want="${entry##*:}"
@@ -98,7 +102,7 @@ for entry in 01-simple:false 02-dialogue-native-audio:true 03-edge-duration:fals
98
102
  done
99
103
 
100
104
  # ---------------------------------------------------------------- 4
101
- printf '\n[4/6] adapter capability declarations\n'
105
+ printf '\n[4/8] adapter capability declarations\n'
102
106
  declare_caps() {
103
107
  local adapter="$1"; local expected="$2"
104
108
  local out got
@@ -116,7 +120,7 @@ declare_caps sora "native"
116
120
  declare_caps kling "none"
117
121
 
118
122
  # ---------------------------------------------------------------- 5
119
- printf '\n[5/6] stitch.sh dry-run returns manifest output path\n'
123
+ printf '\n[5/8] stitch.sh dry-run returns manifest output path\n'
120
124
  STITCH_OUT="$(jq -r '.stitch_output' "$PROJECT/manifest.json")"
121
125
  stitch_log="$(AIV_DRYRUN=true bash "$ROOT/src/scripts/ai-video/stitch.sh" \
122
126
  "$PROJECT/manifest.json" "$PROJECT/$STITCH_OUT" 2>&1 || true)"
@@ -126,7 +130,7 @@ case "$stitch_log" in
126
130
  esac
127
131
 
128
132
  # ---------------------------------------------------------------- 6
129
- printf '\n[6/6] visual regression (locked.png pairwise)\n'
133
+ printf '\n[6/8] visual regression (locked.png pairwise)\n'
130
134
  PNG_MAGIC="$(printf '\x89PNG\r\n\x1a\n')"
131
135
  prev=""
132
136
  have_compare=0
@@ -160,6 +164,80 @@ for s in $SCENES; do
160
164
  prev="$f"
161
165
  done
162
166
 
167
+ # ---------------------------------------------------------------- 7
168
+ printf '\n[7/8] end_image is refused, never dropped\n'
169
+ END_ADAPTER="kling"
170
+ END_MODEL="kling-v2-master"
171
+ END_MANIFEST="$ROOT/src/scripts/ai-video/lib/model-capabilities/$END_ADAPTER.json"
172
+
173
+ # Precondition: the entry must actually answer end_frame:null, or this case
174
+ # proves nothing. A probed `true` here would make the refusal wrong, not this
175
+ # assertion stale — so it is checked, not assumed.
176
+ end_declared="$(jq -r --arg m "$END_MODEL" \
177
+ '.models[$m] // {} | .end_frame | if . == null then "null" else tostring end' \
178
+ "$END_MANIFEST" 2>/dev/null || echo missing)"
179
+ if [ "$end_declared" = "null" ]; then
180
+ ok "$END_ADAPTER/$END_MODEL declares end_frame=null (unknown)"
181
+ else
182
+ fail "$END_ADAPTER/$END_MODEL declares end_frame=$end_declared — expected null for this case"
183
+ fi
184
+
185
+ end_stdin='{"prompt":{"subject":"a lone figure","action":"turns toward the door"},"duration":5,"end_image":"/tmp/aiv-end-frame.png"}'
186
+ end_out="$(printf '%s' "$end_stdin" \
187
+ | AIV_DRYRUN=true AIV_MODEL="$END_MODEL" \
188
+ bash "$ROOT/src/scripts/ai-video/adapters/$END_ADAPTER.sh" submit 2>&1)"
189
+ end_rc=$?
190
+
191
+ if [ "$end_rc" -eq 0 ]; then
192
+ fail "$END_ADAPTER: end_image was accepted (exit 0) — the image was dropped silently"
193
+ else
194
+ case "$end_out" in
195
+ *"$END_MODEL"*end_frame*|*end_frame*"$END_MODEL"*)
196
+ ok "$END_ADAPTER: end_image refused with exit $end_rc, naming $END_MODEL and end_frame";;
197
+ *)
198
+ fail "$END_ADAPTER: exit $end_rc but the message names neither the model nor the field (got: $end_out)";;
199
+ esac
200
+ fi
201
+
202
+ # ---------------------------------------------------------------- 8
203
+ printf '\n[8/8] cost calibration prints modeled-vs-charged and does not re-confirm on null\n'
204
+ CAL_PROJECT="$(mktemp -d -t aiv-cal-XXXXXX)"
205
+ mkdir -p "$CAL_PROJECT/scenes/0001"
206
+ printf '{"duration":5}\n' > "$CAL_PROJECT/scenes/0001/prompt.json"
207
+ CAL_ADAPTER="fal"
208
+ CAL_MODEL="fal-ai/ltx-2/text-to-video"
209
+
210
+ # No cost.json: nothing has been charged. This is the dry-run shape, and it is
211
+ # the case that matters most — `charged: null` must extrapolate nothing and must
212
+ # NOT halt, because treating an absent charge as 0 would make every future
213
+ # estimate quietly cheaper.
214
+ cal_out="$(bash "$ROOT/src/scripts/ai-video/lib/calibrate-cost.sh" \
215
+ "$CAL_PROJECT" 0001 --adapter "$CAL_ADAPTER" --model "$CAL_MODEL" \
216
+ --scenes 4 --no-append 2>&1)" && cal_rc=0 || cal_rc=$?
217
+
218
+ case "$cal_out" in
219
+ *"modeled \$"*"charged null"*) ok "calibration line prints modeled vs charged with charged: null" ;;
220
+ *) fail "calibration line missing or malformed (got: $cal_out)" ;;
221
+ esac
222
+ if [ "$cal_rc" -eq 0 ]; then
223
+ ok "charged: null does not re-confirm (exit 0)"
224
+ else
225
+ fail "charged: null re-confirmed with exit $cal_rc — an absent charge is not an overrun"
226
+ fi
227
+
228
+ # Sensitivity: the halt must actually fire when a charge genuinely overruns, or
229
+ # the exit-0 assertion above would pass against a script that never halts.
230
+ printf '{"charged_usd":1.60}\n' > "$CAL_PROJECT/scenes/0001/cost.json"
231
+ cal_over="$(bash "$ROOT/src/scripts/ai-video/lib/calibrate-cost.sh" \
232
+ "$CAL_PROJECT" 0001 --adapter "$CAL_ADAPTER" --model "$CAL_MODEL" \
233
+ --scenes 4 --no-append 2>&1)" && cal_over_rc=0 || cal_over_rc=$?
234
+ if [ "$cal_over_rc" -eq 13 ]; then
235
+ ok "a charge over the tolerance halts with exit 13 for re-confirmation"
236
+ else
237
+ fail "an overrun exited $cal_over_rc, expected 13 (got: $cal_over)"
238
+ fi
239
+ rm -rf "$CAL_PROJECT"
240
+
163
241
  # ----------------------------------------------------------------
164
242
  printf '\n----------------\nresult: %d passed · %d failed\n' "$PASS" "$FAIL"
165
243
  if [ "$FAIL" -gt 0 ]; then
@@ -0,0 +1,139 @@
1
+ /**
2
+ * The agency bound each CLI council member is spawned under — one definition.
3
+ *
4
+ * A council member is a text-in/text-out oracle: it reads a question and returns
5
+ * an opinion. It never edits, never runs a command, never fetches. Every CLI here
6
+ * is an AGENTIC binary that grants tools by default, so an unbounded spawn hands
7
+ * a read-write agent to a role that needs none of it — the over-broad grant
8
+ * `tool-safety` § Least Agency exists to refuse.
9
+ *
10
+ * ## Why this is a module and not five literals in `clients.ts`
11
+ *
12
+ * The flags appeared in two places at once: the `_build_command` of each client,
13
+ * and `cli_least_agency_canary.ts`, which must spawn the SAME argv to prove the
14
+ * bound is honoured. Two copies of a value whose entire purpose is to be
15
+ * verified is a drift waiting to happen — the canary would keep passing against
16
+ * a flag `clients.ts` had stopped sending.
17
+ *
18
+ * ## Every entry is PROBED, and carries the version it was probed against
19
+ *
20
+ * A flag that exists in one release and not the next is a claim with a shelf
21
+ * life. `probed_version` is the string that CLI's own `--version` printed on
22
+ * `probed_on`; a member whose binary could not be resolved carries `null` for
23
+ * both and is an honest null, never a guessed flag.
24
+ *
25
+ * ## `control` is a permissive VALUE, not the absence of `bound`
26
+ *
27
+ * Measured 2026-08-23: with no `--sandbox` in argv at all, codex answers
28
+ * `patch rejected: writing is blocked by read-only sandbox; rejected by user
29
+ * approval settings` — its ambient default is already restrictive. So "omit the
30
+ * bound" is not an unbounded control there, and a canary using one is confounded
31
+ * by a per-machine setting it never recorded. The control is the smallest
32
+ * documented step ABOVE the bound, never the widest.
33
+ */
34
+
35
+ /** One member's bound, its control counterpart, and the probe behind them. */
36
+ export interface AgencyBound {
37
+ /** Council member key (`anthropic`, `openai`, …). */
38
+ readonly member: string;
39
+ /** The binary the transport resolves. */
40
+ readonly binary: string;
41
+ /** The argv fragment that bounds the spawn. Empty = no bound determined. */
42
+ readonly bound: readonly string[];
43
+ /**
44
+ * The permissive counterpart the canary uses as its control. Empty means
45
+ * "omit the bound", which is only correct where the CLI's default genuinely
46
+ * grants the capability — verified per member, never assumed.
47
+ */
48
+ readonly control: readonly string[];
49
+ /** What that CLI's own `--version` printed, or null when the binary is absent. */
50
+ readonly probed_version: string | null;
51
+ /** ISO date of the probe, or null when the binary is absent. */
52
+ readonly probed_on: string | null;
53
+ /** Why this flag and not a sibling — the part a reader cannot re-derive. */
54
+ readonly rationale: string;
55
+ }
56
+
57
+ export const AGENCY_BOUNDS: readonly AgencyBound[] = [
58
+ {
59
+ member: 'anthropic',
60
+ binary: 'claude',
61
+ bound: ['--tools', ''],
62
+ // Omission IS the control here, and it is verified rather than assumed:
63
+ // the control arm created the sentinel on 2026-08-23, so the default
64
+ // genuinely grants the write capability.
65
+ control: [],
66
+ probed_version: '2.1.241 (Claude Code)',
67
+ probed_on: '2026-08-23',
68
+ rationale:
69
+ '`claude` grants its full built-in tool set by default; `""` is the documented "disable all tools" value. ' +
70
+ 'Predates this module — added after a live context-window overflow rather than a security pass, which is ' +
71
+ 'why the canary exists at all.',
72
+ },
73
+ {
74
+ member: 'openai',
75
+ binary: 'codex',
76
+ bound: ['--sandbox', 'read-only'],
77
+ control: ['--sandbox', 'workspace-write'],
78
+ probed_version: 'codex-cli 0.148.0',
79
+ probed_on: '2026-08-23',
80
+ rationale:
81
+ '`codex exec --help` documents `-s, --sandbox <SANDBOX_MODE>` with `read-only`, `workspace-write`, ' +
82
+ '`danger-full-access`. It sits BESIDE `--skip-git-repo-check`, never instead of it: the trust gate is what ' +
83
+ 'makes a worktree usable at all, the sandbox bounds what the session may then do, and before this the argv ' +
84
+ 'carried the guard REMOVAL with no counterpart. Control is `workspace-write`, the smallest documented step ' +
85
+ 'up — never `danger-full-access`.',
86
+ },
87
+ {
88
+ member: 'gemini',
89
+ binary: 'gemini',
90
+ bound: ['--approval-mode', 'plan'],
91
+ control: ['--approval-mode', 'auto_edit'],
92
+ probed_version: '0.50.0',
93
+ probed_on: '2026-08-23',
94
+ rationale:
95
+ '`gemini --help` lists `plan (read-only mode)`. NOT `--allowed-tools`, which the same help marks ' +
96
+ '`DEPRECATED: Use Policy Engine instead` — pinning to it would bind the council to a surface the vendor is ' +
97
+ 'retiring. The siblings move the wrong way: `-y/--yolo` auto-accepts every action, `auto_edit` auto-approves ' +
98
+ 'edit tools, which is exactly why `auto_edit` is the control and not the bound.',
99
+ },
100
+ {
101
+ member: 'xai',
102
+ binary: 'grok',
103
+ bound: [],
104
+ control: [],
105
+ probed_version: null,
106
+ probed_on: null,
107
+ rationale:
108
+ 'not-probed — binary absent on the probing machine. No flag is guessed: a member whose bound was never ' +
109
+ 'determined must not be rendered as bounded.',
110
+ },
111
+ {
112
+ member: 'perplexity',
113
+ binary: 'perplexity',
114
+ bound: [],
115
+ control: [],
116
+ probed_version: null,
117
+ probed_on: null,
118
+ rationale: 'not-probed — binary absent on the probing machine. Same refusal to guess as `xai`.',
119
+ },
120
+ ];
121
+
122
+ /** The bound argv fragment for a member, or `[]` when none was determined. */
123
+ export function boundFor(member: string): readonly string[] {
124
+ return AGENCY_BOUNDS.find((b) => b.member === member)?.bound ?? [];
125
+ }
126
+
127
+ /**
128
+ * Documented flags that LIFT an agency bound.
129
+ *
130
+ * A bound is only a bound if the argv cannot also carry the flag that removes
131
+ * it, and a presence check on the bound alone passes with both present.
132
+ */
133
+ export const AGENCY_BYPASS_FLAGS: readonly string[] = [
134
+ '--dangerously-bypass-approvals-and-sandbox',
135
+ '--dangerously-bypass-hook-trust',
136
+ '--yolo',
137
+ 'danger-full-access',
138
+ 'workspace-write',
139
+ ];