@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
@@ -19,9 +19,33 @@
19
19
  #
20
20
  # Usage:
21
21
  # bash src/scripts/ai-video/smoke-trace.sh --provider <id> [--live] [--out <dir>]
22
+ # bash src/scripts/ai-video/smoke-trace.sh index [--traces <dir>] [--out <file>]
23
+ # bash src/scripts/ai-video/smoke-trace.sh assumed <adapter>
22
24
  #
23
25
  # Exit: 0 = trace captured (dry-run plumbing OK, or live success),
24
26
  # non-zero = adapter/harness error (recorded in the trace + stderr).
27
+ #
28
+ # Subcommand `index` — the reviewer-reachable projection of the local traces.
29
+ # The raw traces are deliberately local-only (commit d7f5d5d3c, 2026-06-10):
30
+ # they carry request bodies, provider response bodies and signed URLs, and
31
+ # `git ls-files` over the trace path returns 0. That decision stands. What it
32
+ # left broken is that a reviewer holding a clone could not check an adapter's
33
+ # `# Lifecycle: stable` claim at all. `index` fixes exactly that, and nothing
34
+ # else: it emits a FIVE-FIELD row per trace — provider, trace_id,
35
+ # captured_at, model, sha256 — and copies no trace content whatsoever. The
36
+ # allowlist is the security property, not a formatting choice: exclusion by
37
+ # construction, never a redaction pass over a body that might hide a secret
38
+ # the scrub did not know about (`domain-safety-pii` § Surface 2 states the
39
+ # preference; this is that preference applied).
40
+ #
41
+ # `model` is the FILESYSTEM-SAFE SLUG the capture path wrote into the
42
+ # filename (`/` → `_`), never the provider's model id reversed back out —
43
+ # that transformation is lossy and guessing its inverse would be a fabricated
44
+ # field. Consumers match by applying the same forward substitution.
45
+ #
46
+ # An absent trace directory is a REFUSAL, not an empty index: a zero-row
47
+ # index is indistinguishable from "no evidence exists", and writing one would
48
+ # turn a missing input into a published claim.
25
49
  set -euo pipefail
26
50
 
27
51
  ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/../../.." && pwd)"
@@ -35,10 +59,409 @@ ADAPTER_DIRS=(
35
59
  # shellcheck source=/dev/null
36
60
  . "${ROOT}/src/scripts/media/lib/adapter-common.sh"
37
61
 
62
+ # --- Subcommands -------------------------------------------------------------
63
+ # Dispatched before the flag parser so the capture path below is unchanged for
64
+ # every caller that does not name a subcommand.
65
+
66
+ _st_sha256() {
67
+ if command -v shasum >/dev/null 2>&1; then
68
+ shasum -a 256 "$1" | cut -d' ' -f1
69
+ elif command -v sha256sum >/dev/null 2>&1; then
70
+ sha256sum "$1" | cut -d' ' -f1
71
+ else
72
+ echo "smoke-trace: need shasum or sha256sum" >&2; exit 3
73
+ fi
74
+ }
75
+
76
+ # Recover the model slug from a trace filename, given the provider.
77
+ # Layout written by the capture path above:
78
+ # <provider>[-<model_slug>]-<mode>-<TS>.json mode = live | dry-run
79
+ # Strip from the right (TS, then mode), then the provider prefix; whatever is
80
+ # left is the slug, and an empty remainder means the trace named no model.
81
+ _st_model_slug() {
82
+ local stem="$1" provider="$2" rest
83
+ rest="$(printf '%s' "${stem}" | sed -E 's/-[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}-[0-9]{2}-[0-9]{2}Z$//')"
84
+ rest="$(printf '%s' "${rest}" | sed -E 's/-(live|dry-run)$//')"
85
+ case "${rest}" in
86
+ "${provider}") printf '' ;;
87
+ "${provider}-"*) printf '%s' "${rest#"${provider}-"}" ;;
88
+ *) printf '' ;;
89
+ esac
90
+ }
91
+
92
+ _st_index() {
93
+ local traces_dir="${ROOT}/agents/reference/ai-video/smoke-traces"
94
+ local out_file="${ROOT}/agents/evidence/ai-video/trace-index.json"
95
+ while [ $# -gt 0 ]; do
96
+ case "$1" in
97
+ --traces) traces_dir="${2:-}"; shift 2 ;;
98
+ --out) out_file="${2:-}"; shift 2 ;;
99
+ *) echo "smoke-trace index: unknown arg '$1'" >&2; exit 2 ;;
100
+ esac
101
+ done
102
+ command -v jq >/dev/null 2>&1 || { echo "smoke-trace: jq required" >&2; exit 3; }
103
+ [ -d "${traces_dir}" ] || {
104
+ echo "smoke-trace index: trace directory not found: ${traces_dir}" >&2
105
+ echo "smoke-trace index: refusing to write an empty index — a zero-row index reads as 'no evidence exists', which is a different claim from 'the traces are not on this disk'." >&2
106
+ exit 7
107
+ }
108
+
109
+ local rows="[]" f stem provider captured slug model_json sha
110
+ for f in "${traces_dir}"/*.json; do
111
+ [ -f "${f}" ] || continue
112
+ stem="$(basename "${f}" .json)"
113
+ provider="$(jq -r '.provider // empty' "${f}" 2>/dev/null || true)"
114
+ captured="$(jq -r '.captured_utc // empty' "${f}" 2>/dev/null || true)"
115
+ if [ -z "${provider}" ] || [ -z "${captured}" ]; then
116
+ echo "smoke-trace index: skipping ${stem} (no .provider/.captured_utc — not a trace)" >&2
117
+ continue
118
+ fi
119
+ slug="$(_st_model_slug "${stem}" "${provider}")"
120
+ if [ -n "${slug}" ]; then
121
+ model_json="$(jq -nc --arg m "${slug}" '$m')"
122
+ else
123
+ model_json="null"
124
+ fi
125
+ sha="$(_st_sha256 "${f}")"
126
+ rows="$(printf '%s' "${rows}" | jq -c \
127
+ --arg p "${provider}" --arg t "${stem}" --arg c "${captured}" \
128
+ --argjson m "${model_json}" --arg s "${sha}" \
129
+ '. + [{provider:$p, trace_id:$t, captured_at:$c, model:$m, sha256:$s}]')"
130
+ done
131
+
132
+ mkdir -p "$(dirname "${out_file}")"
133
+ # Sorted by trace_id so a regeneration is byte-identical and a diff is real.
134
+ printf '%s' "${rows}" | jq --sort-keys 'sort_by(.trace_id)' > "${out_file}"
135
+ printf 'smoke-trace index: %s rows -> %s\n' \
136
+ "$(jq 'length' "${out_file}")" "${out_file#"${ROOT}/"}" >&2
137
+ }
138
+
139
+ # `assumed` — every ASSUMED-tagged field in an adapter, with its line. A field
140
+ # stays ASSUMED until a live trace confirms it; this makes the count auditable
141
+ # instead of a number somebody has to re-grep by hand.
142
+ #
143
+ # `--all` reports `<domain>\t<adapter>\t<count>` and a total. `--domain
144
+ # <ai-video|ai-image>` narrows it, and the narrowing is not cosmetic: the
145
+ # ai-image adapters carry one ASSUMED tag each and belong to a different
146
+ # adapter population than the video set, so a single undifferentiated total
147
+ # answers no question anybody actually asks. (Measured 2026-08-23: ai-video 21
148
+ # across 7 adapters, ai-image 4 across 4, 25 in all.)
149
+ _st_assumed() {
150
+ local target="${1:-}" want_domain="" d f found="" domain
151
+ shift || true
152
+ while [ $# -gt 0 ]; do
153
+ case "$1" in
154
+ --domain) want_domain="${2:-}"; shift 2 ;;
155
+ *) echo "smoke-trace assumed: unknown arg '$1'" >&2; exit 2 ;;
156
+ esac
157
+ done
158
+ [ -n "${target}" ] || { echo "usage: smoke-trace.sh assumed <adapter|--all> [--domain <id>]" >&2; exit 2; }
159
+ if [ "${target}" = "--all" ]; then
160
+ local total=0 n
161
+ for d in "${ADAPTER_DIRS[@]}"; do
162
+ [ -d "${d}" ] || continue
163
+ domain="$(basename "$(dirname "${d}")")"
164
+ [ -z "${want_domain}" ] || [ "${want_domain}" = "${domain}" ] || continue
165
+ for f in "${d}"/*.sh; do
166
+ [ -f "${f}" ] || continue
167
+ n="$(grep -c 'ASSUMED' "${f}" 2>/dev/null || true)"
168
+ [ -n "${n}" ] || n=0
169
+ [ "${n}" -gt 0 ] || continue
170
+ printf '%s\t%s\t%s\n' "${domain}" "$(basename "${f}" .sh)" "${n}"
171
+ total=$((total + n))
172
+ done
173
+ done
174
+ printf 'total\t%s\n' "${total}"
175
+ return 0
176
+ fi
177
+ for d in "${ADAPTER_DIRS[@]}"; do
178
+ [ -f "${d}/${target}.sh" ] && { found="${d}/${target}.sh"; break; }
179
+ done
180
+ [ -n "${found}" ] || { echo "smoke-trace assumed: no adapter for '${target}'" >&2; exit 2; }
181
+ grep -n 'ASSUMED' "${found}" || true
182
+ }
183
+
184
+ # --- Image / video similarity primitives ------------------------------------
185
+ # ffmpeg's psnr and ssim filters, parsed to one number on stdout. Split out so
186
+ # the threshold logic is testable on two PNGs without any provider call.
187
+ #
188
+ # `inf` is a REAL answer and is printed as `inf`: two byte-identical frames have
189
+ # no error to measure. Mapping it to a large finite number would make an exact
190
+ # match indistinguishable from a very good one, and every caller here wants the
191
+ # distinction.
192
+
193
+ _st_need_ffmpeg() {
194
+ command -v ffmpeg >/dev/null 2>&1 || { echo "smoke-trace: ffmpeg required for this subcommand" >&2; exit 3; }
195
+ }
196
+
197
+ # _st_psnr <ref> <cmp> -> average PSNR in dB, or `inf`
198
+ _st_psnr() {
199
+ local ref="$1" cmp="$2" out
200
+ [ -r "${ref}" ] || { echo "smoke-trace psnr: cannot read ${ref}" >&2; exit 7; }
201
+ [ -r "${cmp}" ] || { echo "smoke-trace psnr: cannot read ${cmp}" >&2; exit 7; }
202
+ out="$(ffmpeg -hide_banner -nostdin -i "${ref}" -i "${cmp}" -lavfi psnr -f null - 2>&1 \
203
+ | sed -nE 's/.*PSNR .*average:([0-9.]+|inf).*/\1/p' | tail -1)"
204
+ [ -n "${out}" ] || { echo "smoke-trace psnr: ffmpeg produced no PSNR line (mismatched dimensions?)" >&2; exit 8; }
205
+ printf '%s' "${out}"
206
+ }
207
+
208
+ # _st_ssim <ref> <cmp> -> All-channel SSIM in 0..1, or `inf` never (SSIM is bounded)
209
+ _st_ssim() {
210
+ local ref="$1" cmp="$2" out
211
+ [ -r "${ref}" ] || { echo "smoke-trace ssim: cannot read ${ref}" >&2; exit 7; }
212
+ [ -r "${cmp}" ] || { echo "smoke-trace ssim: cannot read ${cmp}" >&2; exit 7; }
213
+ out="$(ffmpeg -hide_banner -nostdin -i "${ref}" -i "${cmp}" -lavfi ssim -f null - 2>&1 \
214
+ | sed -nE 's/.*SSIM .*All:([0-9.]+).*/\1/p' | tail -1)"
215
+ [ -n "${out}" ] || { echo "smoke-trace ssim: ffmpeg produced no SSIM line (mismatched dimensions?)" >&2; exit 8; }
216
+ printf '%s' "${out}"
217
+ }
218
+
219
+ # Numeric comparison that treats `inf` as above every threshold.
220
+ _st_ge() {
221
+ local value="$1" threshold="$2"
222
+ [ "${value}" = "inf" ] && return 0
223
+ node -e 'process.exit(Number(process.argv[1]) >= Number(process.argv[2]) ? 0 : 1)' "${value}" "${threshold}"
224
+ }
225
+
226
+ # The frame-0 identity threshold. 30 dB is the roadmap's stated number and is a
227
+ # STATED DEFAULT, not a measured optimum: it asks "is frame 0 the input still,
228
+ # modulo codec noise", which is a different and much easier question than seam
229
+ # quality — so the "PSNR is the wrong metric for seams" caveat does not transfer
230
+ # here. Revisit-if a model passes at 30 dB while a human says frame 0 is a
231
+ # different image, or fails at 30 dB while a human says it is the same one.
232
+ ST_FRAME0_PSNR_MIN="${AIV_FRAME0_PSNR_MIN:-30}"
233
+
234
+ # psnr / ssim / frame0-verdict — the testable primitives.
235
+ _st_metric() {
236
+ local kind="$1"; shift
237
+ _st_need_ffmpeg
238
+ case "${kind}" in
239
+ psnr) _st_psnr "$@"; printf '\n' ;;
240
+ ssim) _st_ssim "$@"; printf '\n' ;;
241
+ frame0)
242
+ local v; v="$(_st_psnr "$@")"
243
+ if _st_ge "${v}" "${ST_FRAME0_PSNR_MIN}"; then
244
+ printf '{"psnr_frame0":"%s","threshold":%s,"start_frame":true}\n' "${v}" "${ST_FRAME0_PSNR_MIN}"
245
+ else
246
+ printf '{"psnr_frame0":"%s","threshold":%s,"start_frame":false}\n' "${v}" "${ST_FRAME0_PSNR_MIN}"
247
+ fi
248
+ ;;
249
+ *) echo "smoke-trace: unknown metric '${kind}'" >&2; exit 2 ;;
250
+ esac
251
+ }
252
+
253
+ # `seam-score <a.mp4> <b.mp4>` — the diagnostic Phase 4 measures with (4.2).
254
+ # The LAST frame of a and the FIRST frame of b are the boundary pair a viewer
255
+ # actually sees across a cut, so those are the two frames scored. Both metrics
256
+ # are emitted because the pre-registered question is which of them (if either)
257
+ # tracks human judgement — picking one here would answer the question the
258
+ # falsifier exists to ask.
259
+ _st_seam_score() {
260
+ local a="${1:-}" b="${2:-}" work last first
261
+ [ -n "${a}" ] && [ -n "${b}" ] || { echo "usage: smoke-trace.sh seam-score <a.mp4> <b.mp4>" >&2; exit 2; }
262
+ _st_need_ffmpeg
263
+ [ -r "${a}" ] || { echo "smoke-trace seam-score: cannot read ${a}" >&2; exit 7; }
264
+ [ -r "${b}" ] || { echo "smoke-trace seam-score: cannot read ${b}" >&2; exit 7; }
265
+ work="$(mktemp -d -t aiv-seam-XXXXXX)"
266
+ trap 'rm -rf "${work}"' RETURN
267
+ last="${work}/last.png"
268
+ first="${work}/first.png"
269
+ # -sseof seeks from the end; 0.15 s back lands inside the final GOP on every
270
+ # frame rate this pipeline emits, and -frames:v 1 takes the first frame after
271
+ # the seek rather than a decoded-but-discarded one.
272
+ ffmpeg -hide_banner -loglevel error -nostdin -y -sseof -0.15 -i "${a}" -frames:v 1 -update 1 "${last}" \
273
+ || { echo "smoke-trace seam-score: could not extract the last frame of ${a}" >&2; exit 8; }
274
+ ffmpeg -hide_banner -loglevel error -nostdin -y -i "${b}" -frames:v 1 -update 1 "${first}" \
275
+ || { echo "smoke-trace seam-score: could not extract the first frame of ${b}" >&2; exit 8; }
276
+ printf '{"a":"%s","b":"%s","psnr":"%s","ssim":"%s","note":"diagnostic only — no threshold is a gate until the falsifier decides one (agents/evidence/analysis/seam-score-falsifier.md)"}\n' \
277
+ "${a}" "${b}" "$(_st_psnr "${last}" "${first}")" "$(_st_ssim "${last}" "${first}")"
278
+ }
279
+
280
+ # `probe-frame-lock <adapter> <model>` — does this model actually accept a start
281
+ # frame, and does the rendered clip's frame 0 come back as that frame?
282
+ #
283
+ # COSTS MONEY. Guarded by the same AIV_DRYRUN default as every other live path:
284
+ # without an explicit AIV_DRYRUN=false it prints the plan and the estimate and
285
+ # exits 0 without submitting. The end-frame side deliberately records NO
286
+ # pass/fail number: whether a clip ENDS on a given composition is a judgement
287
+ # about composition, not an identity check, and a dB figure there would be a
288
+ # fabricated verdict wearing a measurement's clothes — it stores the extracted
289
+ # end frame beside the target for a human instead.
290
+ _st_probe_frame_lock() {
291
+ local adapter_id="${1:-}" model="${2:-}" still="" end_still="" out_dir=""
292
+ shift 2 2>/dev/null || true
293
+ while [ $# -gt 0 ]; do
294
+ case "$1" in
295
+ --still) still="${2:-}"; shift 2 ;;
296
+ --end-still) end_still="${2:-}"; shift 2 ;;
297
+ --out) out_dir="${2:-}"; shift 2 ;;
298
+ *) echo "smoke-trace probe-frame-lock: unknown arg '$1'" >&2; exit 2 ;;
299
+ esac
300
+ done
301
+ [ -n "${adapter_id}" ] && [ -n "${model}" ] \
302
+ || { echo "usage: smoke-trace.sh probe-frame-lock <adapter> <model> [--still <png>] [--end-still <png>] [--out <dir>]" >&2; exit 2; }
303
+
304
+ local adapter=""
305
+ for d in "${ADAPTER_DIRS[@]}"; do
306
+ [ -f "${d}/${adapter_id}.sh" ] && { adapter="${d}/${adapter_id}.sh"; break; }
307
+ done
308
+ [ -n "${adapter}" ] || { echo "smoke-trace probe-frame-lock: no adapter for '${adapter_id}'" >&2; exit 2; }
309
+
310
+ local manifest="${ROOT}/src/scripts/ai-video/lib/model-capabilities/${adapter_id}.json"
311
+ local min_dur cost aspect
312
+ min_dur="$(jq -r --arg m "${model}" '.models[$m].min_duration // empty' "${manifest}" 2>/dev/null || true)"
313
+ cost="$(jq -r --arg m "${model}" '.models[$m].cost_per_second_usd // empty' "${manifest}" 2>/dev/null || true)"
314
+ aspect="$(jq -r --arg m "${model}" '.models[$m].aspect[0] // "16:9"' "${manifest}" 2>/dev/null || printf '16:9')"
315
+ [ -n "${min_dur}" ] || min_dur=4
316
+ local est="unknown"
317
+ if [ -n "${cost}" ] && [ "${cost}" != "null" ]; then
318
+ est="$(node -e 'process.stdout.write(String(Number(process.argv[1]) * Number(process.argv[2])))' "${cost}" "${min_dur}")"
319
+ fi
320
+
321
+ local dryrun="${AIV_DRYRUN:-true}"
322
+ case "${dryrun}" in false|FALSE|0|no|NO) dryrun=0 ;; *) dryrun=1 ;; esac
323
+
324
+ if [ "${dryrun}" -eq 1 ]; then
325
+ jq -nc --arg a "${adapter_id}" --arg m "${model}" --arg d "${min_dur}" \
326
+ --arg asp "${aspect}" --arg est "${est}" '{
327
+ dry_run: true, adapter: $a, model: $m, duration_s: ($d|tonumber), aspect: $asp,
328
+ estimated_usd: $est,
329
+ plan: "render one clip from the fixture still at the cheapest duration, extract frame 0, PSNR against the still",
330
+ note: "NO submit performed. Set AIV_DRYRUN=false to spend. The end-frame side records the extracted end frame for a human and no pass/fail number."
331
+ }'
332
+ return 0
333
+ fi
334
+
335
+ # Argument validation BEFORE the ffmpeg probe, deliberately. A missing
336
+ # `--still` is a usage error: the command is malformed on every machine, and
337
+ # the message should not depend on which tools happen to be installed. A
338
+ # missing ffmpeg is an environment error for a call that would never have been
339
+ # made anyway. Ordering them the other way made this path report
340
+ # "ffmpeg required" on a CI runner with no ffmpeg, hiding the real mistake.
341
+ [ -n "${still}" ] || { echo "smoke-trace probe-frame-lock: --still <png> is required for a live probe" >&2; exit 2; }
342
+ [ -r "${still}" ] || { echo "smoke-trace probe-frame-lock: cannot read --still ${still}" >&2; exit 7; }
343
+ _st_need_ffmpeg
344
+ out_dir="${out_dir:-${ROOT}/agents/reference/ai-video/smoke-traces/frame-lock}"
345
+ mkdir -p "${out_dir}"
346
+ local stamp clip frame0
347
+ stamp="$(date -u +%Y-%m-%dT%H-%M-%SZ)"
348
+ clip="${out_dir}/${adapter_id}-$(printf '%s' "${model}" | tr '/' '_')-${stamp}.mp4"
349
+ frame0="${clip%.mp4}-frame0.png"
350
+
351
+ local stdin_json
352
+ stdin_json="$(jq -nc --arg m "${model}" --arg ref "${still}" --arg asp "${aspect}" --argjson dur "${min_dur}" '{
353
+ prompt: {style:"frame-lock probe", subject:"the supplied still, continuing",
354
+ environment:"as in the still", action:"minimal motion", camera:"locked",
355
+ lens:"as in the still", lighting:"as in the still", mood:"neutral"},
356
+ duration: $dur, aspect: $asp, seed: 1, model_id: $m, ref_images: [$ref]
357
+ } + (if $end != "" then {end_image: $end} else {} end)' --arg end "${end_still}")"
358
+
359
+ AIV_DRYRUN=false AIV_OUT="${clip}" printf '%s' "${stdin_json}" | bash "${adapter}" run >/dev/null \
360
+ || { echo "smoke-trace probe-frame-lock: adapter run failed for ${adapter_id}/${model}" >&2; exit 8; }
361
+ ffmpeg -hide_banner -loglevel error -nostdin -y -i "${clip}" -frames:v 1 -update 1 "${frame0}" \
362
+ || { echo "smoke-trace probe-frame-lock: could not extract frame 0 from ${clip}" >&2; exit 8; }
363
+
364
+ local psnr verdict
365
+ psnr="$(_st_psnr "${still}" "${frame0}")"
366
+ if _st_ge "${psnr}" "${ST_FRAME0_PSNR_MIN}"; then verdict=true; else verdict=false; fi
367
+
368
+ # Write the probed fact into the manifest. `start_frame` is set from the
369
+ # measurement in BOTH directions — a failed probe writes `false` with the
370
+ # measured value kept, never `null`, because "we looked and it did not hold"
371
+ # is a different fact from "nobody looked".
372
+ local tmp; tmp="$(mktemp)"
373
+ jq --arg m "${model}" --argjson v "${verdict}" --arg p "${psnr}" --arg d "${stamp%T*}" '
374
+ .models[$m].start_frame = $v
375
+ | .models[$m].frame_lock = {probed_at: $d, psnr_frame0: $p}
376
+ ' "${manifest}" > "${tmp}" && mv "${tmp}" "${manifest}"
377
+
378
+ local end_note="not probed (no --end-still)"
379
+ if [ -n "${end_still}" ]; then
380
+ local endframe="${clip%.mp4}-endframe.png"
381
+ ffmpeg -hide_banner -loglevel error -nostdin -y -sseof -0.15 -i "${clip}" -frames:v 1 -update 1 "${endframe}" || true
382
+ end_note="end frame extracted to ${endframe} beside ${end_still} — composition is a human judgement, no number recorded"
383
+ fi
384
+
385
+ jq -nc --arg a "${adapter_id}" --arg m "${model}" --arg p "${psnr}" \
386
+ --argjson v "${verdict}" --arg d "${stamp%T*}" --arg clip "${clip}" --arg en "${end_note}" '{
387
+ adapter:$a, model:$m, psnr_frame0:$p, start_frame:$v, probed_at:$d, clip:$clip, end_frame_side:$en
388
+ }'
389
+ }
390
+
391
+ # `cost-ledger append` — the ONLY sanctioned route from a charged figure back
392
+ # into a modeled one (roadmap 2.3).
393
+ #
394
+ # The gap this closes is narrow and was mis-stated before reproduction: the
395
+ # read-back already existed. `lib/resume-scan.sh` reads `cost.json .charged_usd`
396
+ # and sums it as `spent_usd`, and the from-song command writes that file after
397
+ # every live scene. What did NOT exist is any path from that number back into
398
+ # `manifest.cost_per_second_usd` — money was spent, recorded, and never read
399
+ # into the model it contradicted.
400
+ #
401
+ # `charged` is `null`, never `0`, when nothing was charged or the charge is
402
+ # unknown. A missing price and a free render are different facts, and `0` erases
403
+ # the difference in the one direction that silently lowers every future
404
+ # estimate. `--charged` accepts the literal `null` for exactly this reason.
405
+ _st_cost_ledger() {
406
+ local sub="${1:-}"; shift || true
407
+ local ledger="${ROOT}/agents/evidence/ai-video/cost-ledger.jsonl"
408
+ case "${sub}" in
409
+ append)
410
+ local adapter="" model="" modeled="null" charged="null" note="" date_s="" out=""
411
+ while [ $# -gt 0 ]; do
412
+ case "$1" in
413
+ --adapter) adapter="${2:-}"; shift 2 ;;
414
+ --model) model="${2:-}"; shift 2 ;;
415
+ --modeled) modeled="${2:-null}"; shift 2 ;;
416
+ --charged) charged="${2:-null}"; shift 2 ;;
417
+ --note) note="${2:-}"; shift 2 ;;
418
+ --date) date_s="${2:-}"; shift 2 ;;
419
+ --ledger) ledger="${2:-}"; shift 2 ;;
420
+ *) echo "smoke-trace cost-ledger append: unknown arg '$1'" >&2; exit 2 ;;
421
+ esac
422
+ done
423
+ [ -n "${adapter}" ] && [ -n "${model}" ] \
424
+ || { echo "usage: smoke-trace.sh cost-ledger append --adapter <id> --model <id> [--modeled <usd>] [--charged <usd|null>] [--note <text>]" >&2; exit 2; }
425
+ [ -n "${date_s}" ] || date_s="$(date -u +%Y-%m-%d)"
426
+ # An empty string is NOT zero and is NOT a number: normalise it to null
427
+ # rather than letting jq coerce it.
428
+ [ -n "${modeled}" ] || modeled="null"
429
+ [ -n "${charged}" ] || charged="null"
430
+ out="$(jq -nc --arg a "${adapter}" --arg m "${model}" --arg d "${date_s}" --arg n "${note}" \
431
+ --argjson modeled "${modeled}" --argjson charged "${charged}" '{
432
+ adapter:$a, model:$m, modeled:$modeled, charged:$charged, date:$d
433
+ } + (if $n == "" then {} else {note:$n} end)')" \
434
+ || { echo "smoke-trace cost-ledger: --modeled/--charged must be a number or the literal null" >&2; exit 7; }
435
+ mkdir -p "$(dirname "${ledger}")"
436
+ printf '%s\n' "${out}" >> "${ledger}"
437
+ printf '%s\n' "${out}"
438
+ ;;
439
+ "") echo "usage: smoke-trace.sh cost-ledger append …" >&2; exit 2 ;;
440
+ *) echo "smoke-trace cost-ledger: unknown subcommand '${sub}'" >&2; exit 2 ;;
441
+ esac
442
+ }
443
+
444
+ case "${1:-}" in
445
+ index) shift; _st_index "$@"; exit 0 ;;
446
+ cost-ledger) shift; _st_cost_ledger "$@"; exit 0 ;;
447
+ assumed) shift; _st_assumed "$@"; exit 0 ;;
448
+ psnr) shift; _st_metric psnr "$@"; exit 0 ;;
449
+ ssim) shift; _st_metric ssim "$@"; exit 0 ;;
450
+ frame0) shift; _st_metric frame0 "$@"; exit 0 ;;
451
+ seam-score) shift; _st_seam_score "$@"; exit 0 ;;
452
+ probe-frame-lock) shift; _st_probe_frame_lock "$@"; exit 0 ;;
453
+ esac
454
+ # --- end subcommands ---------------------------------------------------------
455
+
38
456
  PROVIDER=""
39
457
  MODE="dry-run"
40
458
  MODEL=""
41
459
  REF_IMAGE=""
460
+ # Comma-separated ASSUMED field names this trace confirms (0.5). Empty is the
461
+ # honest default: a capture confirms nothing until the operator names what it
462
+ # confirmed, and `[]` is what every trace written before this field existed
463
+ # would have carried.
464
+ CONFIRMS=""
42
465
  OUT_DIR="${ROOT}/agents/reference/ai-video/smoke-traces"
43
466
  while [ $# -gt 0 ]; do
44
467
  case "$1" in
@@ -46,6 +469,7 @@ while [ $# -gt 0 ]; do
46
469
  --model) MODEL="${2:-}"; shift 2 ;;
47
470
  --ref-image) REF_IMAGE="${2:-}"; shift 2 ;;
48
471
  --live) MODE="live"; shift ;;
472
+ --confirms) CONFIRMS="${2:-}"; shift 2 ;;
49
473
  --out) OUT_DIR="${2:-}"; shift 2 ;;
50
474
  *) echo "smoke-trace: unknown arg '$1'" >&2; exit 2 ;;
51
475
  esac
@@ -173,15 +597,39 @@ AUDIO_EMB="$(jq -r 'if .audio_embedded == true then "true" else "false" end' <<<
173
597
  NOTE="dry-run = plumbing proof (no network/spend); NOT a real validation. Run --live with a provider key for the real smoke trace."
174
598
  [ "${MODE}" = "live" ] && NOTE="live round-trip against the real provider API (real spend)."
175
599
 
600
+ # recheck_by — a vendor capability is a dated observation, never a permanent
601
+ # fact. Endpoints have gained and lost frame conditioning inside a few weeks,
602
+ # so every trace states when its claim stops being evidence. Same idiom as
603
+ # `keep-beta-until` in docs/contracts/skill-bundled-assets.md; the window is
604
+ # ONE constant, shared with lint_adapter_tier.ts's staleness check, so the two
605
+ # cannot drift apart.
606
+ RECHECK_DAYS="${AIV_TRACE_RECHECK_DAYS:-180}"
607
+ RECHECK_BY="$(TS="${TS}" D="${RECHECK_DAYS}" node -e '
608
+ const ts = process.env.TS;
609
+ // Capture stamps are filesystem-safe: 2026-06-10T12-36-49Z -> ISO.
610
+ const iso = ts.replace(/T(\d{2})-(\d{2})-(\d{2})Z$/, "T$1:$2:$3Z");
611
+ const t = new Date(iso);
612
+ if (Number.isNaN(t.getTime())) { process.stdout.write(""); process.exit(0); }
613
+ t.setUTCDate(t.getUTCDate() + Number(process.env.D));
614
+ process.stdout.write(t.toISOString().slice(0, 10));
615
+ ')"
616
+
617
+ CONFIRMS_JSON="$(printf '%s' "${CONFIRMS}" | tr ',' '\n' \
618
+ | sed -E 's/^[[:space:]]*//; s/[[:space:]]*$//' | sed '/^$/d' \
619
+ | jq -R . | jq -sc .)"
620
+
176
621
  jq -n \
177
622
  --arg provider "${PROVIDER}" --arg tier "${TIER}" --arg mode "${MODE}" \
178
623
  --arg ts "${TS}" --argjson phases "${PHASES}" \
179
624
  --arg video "${VIDEO_PATH}" --arg artifact_ok "${ARTIFACT_OK}" \
180
625
  --arg cost "${COST}" --argjson audio "${AUDIO_EMB}" \
181
626
  --argjson success "${SUCCESS}" --arg note "${NOTE}" \
627
+ --arg recheck "${RECHECK_BY}" --argjson confirms "${CONFIRMS_JSON}" \
182
628
  '{provider:$provider, lifecycle_tier:$tier, mode:$mode, captured_utc:$ts,
183
- success:$success, video_path:$video, artifact_path_validated:$artifact_ok,
184
- cost_estimate:$cost, audio_embedded:$audio, phases:$phases, note:$note}' \
629
+ recheck_by:$recheck, success:$success, video_path:$video,
630
+ artifact_path_validated:$artifact_ok, cost_estimate:$cost,
631
+ audio_embedded:$audio, assumed_fields_confirmed:$confirms,
632
+ phases:$phases, note:$note}' \
185
633
  > "${TRACE}"
186
634
 
187
635
  echo "smoke-trace: ${MODE} ${PROVIDER} (tier=${TIER}) success=${SUCCESS} → ${TRACE#"${ROOT}/"}"