@event4u/agent-config 14.10.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 (399) 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 +335 -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/authz-review/SKILL.md +0 -1
  45. package/dist/agent-src/skills/blast-radius-analyzer/SKILL.md +32 -0
  46. package/dist/agent-src/skills/brand/SKILL.md +3 -0
  47. package/dist/agent-src/skills/brand-asset-generation/SKILL.md +3 -0
  48. package/dist/agent-src/skills/brand-audit/SKILL.md +3 -0
  49. package/dist/agent-src/skills/brand-identity/SKILL.md +3 -0
  50. package/dist/agent-src/skills/brand-strategy/SKILL.md +3 -0
  51. package/dist/agent-src/skills/brand-to-tokens/SKILL.md +3 -0
  52. package/dist/agent-src/skills/check-refs/SKILL.md +3 -0
  53. package/dist/agent-src/skills/code-review/SKILL.md +11 -0
  54. package/dist/agent-src/skills/command-routing/SKILL.md +6 -0
  55. package/dist/agent-src/skills/condense-memory/SKILL.md +3 -0
  56. package/dist/agent-src/skills/context-authoring/SKILL.md +1 -1
  57. package/dist/agent-src/skills/conventional-commits-writing/SKILL.md +3 -0
  58. package/dist/agent-src/skills/copilot-agents-optimization/SKILL.md +10 -0
  59. package/dist/agent-src/skills/corpus-grounding/SKILL.md +3 -0
  60. package/dist/agent-src/skills/design-intelligence/SKILL.md +3 -0
  61. package/dist/agent-src/skills/design-intelligence/data/landing.csv +36 -35
  62. package/dist/agent-src/skills/design-intelligence/data/stacks/threejs.csv +1 -0
  63. package/dist/agent-src/skills/design-review/SKILL.md +79 -1
  64. package/dist/agent-src/skills/design-review/references/verification-automation.md +41 -0
  65. package/dist/agent-src/skills/design-system-capture/SKILL.md +35 -40
  66. package/dist/agent-src/skills/design-system-capture/references/import-procedure.md +50 -0
  67. package/dist/agent-src/skills/design-tokens/SKILL.md +3 -0
  68. package/dist/agent-src/skills/design-variations/SKILL.md +3 -0
  69. package/dist/agent-src/skills/developer-like-execution/SKILL.md +3 -0
  70. package/dist/agent-src/skills/estimate-ticket/SKILL.md +3 -0
  71. package/dist/agent-src/skills/existing-ui-audit/SKILL.md +20 -3
  72. package/dist/agent-src/skills/fe-design/SKILL.md +74 -41
  73. package/dist/agent-src/skills/fe-design/evals/triggers.json +65 -53
  74. package/dist/agent-src/skills/fe-design/references/craft-floor.md +52 -0
  75. package/dist/agent-src/skills/fe-design/references/source-led-port.md +36 -0
  76. package/dist/agent-src/skills/file-editor/SKILL.md +5 -0
  77. package/dist/agent-src/skills/finishing-a-development-branch/SKILL.md +2 -2
  78. package/dist/agent-src/skills/git-workflow/SKILL.md +3 -0
  79. package/dist/agent-src/skills/html-deck/SKILL.md +3 -0
  80. package/dist/agent-src/skills/iconography/SKILL.md +3 -0
  81. package/dist/agent-src/skills/image-editing/SKILL.md +3 -0
  82. package/dist/agent-src/skills/image-generation/SKILL.md +3 -0
  83. package/dist/agent-src/skills/image-provider-routing/SKILL.md +3 -0
  84. package/dist/agent-src/skills/incident-commander/SKILL.md +10 -0
  85. package/dist/agent-src/skills/js-library-packaging/SKILL.md +173 -0
  86. package/dist/agent-src/skills/js-library-packaging/evals/triggers.json +17 -0
  87. package/dist/agent-src/skills/js-library-packaging/scripts/check_package_surface.ts +270 -0
  88. package/dist/agent-src/skills/laravel-migration/SKILL.md +3 -0
  89. package/dist/agent-src/skills/learning-to-rule-or-skill/SKILL.md +3 -0
  90. package/dist/agent-src/skills/lint-skills/SKILL.md +3 -0
  91. package/dist/agent-src/skills/llm-provider-knowledge/SKILL.md +3 -0
  92. package/dist/agent-src/skills/logging-monitoring/SKILL.md +234 -51
  93. package/dist/agent-src/skills/logo-generation/SKILL.md +3 -0
  94. package/dist/agent-src/skills/md-language-check/SKILL.md +3 -0
  95. package/dist/agent-src/skills/monorepo-workspace/SKILL.md +149 -0
  96. package/dist/agent-src/skills/monorepo-workspace/evals/triggers.json +17 -0
  97. package/dist/agent-src/skills/motion-choreographer/SKILL.md +6 -0
  98. package/dist/agent-src/skills/multi-tenancy/SKILL.md +4 -0
  99. package/dist/agent-src/skills/operational-readiness/SKILL.md +184 -0
  100. package/dist/agent-src/skills/operational-readiness/evals/triggers.json +17 -0
  101. package/dist/agent-src/skills/override-management/SKILL.md +3 -0
  102. package/dist/agent-src/skills/persona-improvement/SKILL.md +3 -0
  103. package/dist/agent-src/skills/pest-testing/SKILL.md +3 -0
  104. package/dist/agent-src/skills/playbook-authoring/SKILL.md +162 -0
  105. package/dist/agent-src/skills/playwright-testing/SKILL.md +3 -0
  106. package/dist/agent-src/skills/privacy-review/SKILL.md +3 -0
  107. package/dist/agent-src/skills/prompt-engineering-image/SKILL.md +3 -0
  108. package/dist/agent-src/skills/quality-tools/SKILL.md +5 -0
  109. package/dist/agent-src/skills/react-shadcn-ui/SKILL.md +52 -21
  110. package/dist/agent-src/skills/readme-reviewer/SKILL.md +3 -0
  111. package/dist/agent-src/skills/readme-writing/SKILL.md +3 -0
  112. package/dist/agent-src/skills/readme-writing-package/SKILL.md +3 -0
  113. package/dist/agent-src/skills/receiving-code-review/SKILL.md +2 -2
  114. package/dist/agent-src/skills/refine-prompt/SKILL.md +3 -0
  115. package/dist/agent-src/skills/refine-ticket/SKILL.md +3 -0
  116. package/dist/agent-src/skills/requesting-code-review/SKILL.md +2 -2
  117. package/dist/agent-src/skills/review-routing/SKILL.md +2 -2
  118. package/dist/agent-src/skills/roadmap-writing/SKILL.md +23 -41
  119. package/dist/agent-src/skills/roadmap-writing/references/follow-up-roadmap-shape.md +47 -0
  120. package/dist/agent-src/skills/rtk-output-filtering/SKILL.md +22 -6
  121. package/dist/agent-src/skills/runway-cognition/SKILL.md +3 -0
  122. package/dist/agent-src/skills/scene-expander/scene-blueprint.schema.yaml +26 -0
  123. package/dist/agent-src/skills/secrets-management/SKILL.md +4 -0
  124. package/dist/agent-src/skills/server-hardening/SKILL.md +159 -0
  125. package/dist/agent-src/skills/server-hardening/evals/triggers.json +17 -0
  126. package/dist/agent-src/skills/skill-improvement-pipeline/SKILL.md +3 -0
  127. package/dist/agent-src/skills/skill-management/SKILL.md +3 -0
  128. package/dist/agent-src/skills/skill-reviewer/SKILL.md +3 -0
  129. package/dist/agent-src/skills/skill-writing/SKILL.md +6 -0
  130. package/dist/agent-src/skills/spreadsheet-authoring/SKILL.md +3 -0
  131. package/dist/agent-src/skills/storybook-workshop/SKILL.md +194 -0
  132. package/dist/agent-src/skills/storybook-workshop/evals/triggers.json +17 -0
  133. package/dist/agent-src/skills/storybook-workshop/scripts/story_contrast_floor.ts +134 -0
  134. package/dist/agent-src/skills/subagent-orchestration/SKILL.md +1 -1
  135. package/dist/agent-src/skills/subagent-orchestration/prompts/README.md +25 -0
  136. package/dist/agent-src/skills/supply-chain-intake/SKILL.md +12 -0
  137. package/dist/agent-src/skills/systematic-debugging/SKILL.md +1 -1
  138. package/dist/agent-src/skills/terraform/SKILL.md +3 -0
  139. package/dist/agent-src/skills/test-driven-development/SKILL.md +1 -1
  140. package/dist/agent-src/skills/threat-modeling/SKILL.md +0 -3
  141. package/dist/agent-src/skills/token-optimizer/SKILL.md +3 -0
  142. package/dist/agent-src/skills/typography-system/SKILL.md +3 -0
  143. package/dist/agent-src/skills/ui-component-architect/SKILL.md +9 -1
  144. package/dist/agent-src/skills/upstream-contribute/SKILL.md +3 -0
  145. package/dist/agent-src/skills/validate-feature-fit/SKILL.md +3 -0
  146. package/dist/agent-src/skills/verify-completion-evidence/SKILL.md +2 -2
  147. package/dist/agent-src/skills/wireframe/SKILL.md +3 -0
  148. package/dist/agent-src/skills/wireframe/references/story-beat-ledger.schema.json +115 -0
  149. package/dist/agent-src/skills/workspace-link/SKILL.md +131 -0
  150. package/dist/agent-src/skills/workspace-link/evals/triggers.json +17 -0
  151. package/dist/agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  152. package/dist/agent-src/templates/playbook.md +75 -0
  153. package/dist/agent-src/templates/roadmaps.md +37 -0
  154. package/dist/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  155. package/dist/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  156. package/dist/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  157. package/dist/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  158. package/dist/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  159. package/dist/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  160. package/dist/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  161. package/dist/cli/commands/uiAudit.js +221 -0
  162. package/dist/cli/commands/uiAudit.js.map +1 -0
  163. package/dist/cli/commands/uiRender.js +206 -0
  164. package/dist/cli/commands/uiRender.js.map +1 -0
  165. package/dist/cli/main.js +22 -1
  166. package/dist/cli/main.js.map +1 -1
  167. package/dist/cli/mcp/content.js +64 -1
  168. package/dist/cli/mcp/content.js.map +1 -1
  169. package/dist/cli/mcp/dispatch.js +175 -10
  170. package/dist/cli/mcp/dispatch.js.map +1 -1
  171. package/dist/cli/registry.js +3 -0
  172. package/dist/cli/registry.js.map +1 -1
  173. package/dist/cli-delegate/{chunk-H4VIVD4C.js → chunk-236PNQZK.js} +413 -391
  174. package/dist/cli-delegate/{chunk-G23AT6GD.js → chunk-DMSZHXZS.js} +57 -1
  175. package/dist/cli-delegate/{chunk-77GR3VD4.js → chunk-FF7WAFMR.js} +58 -3
  176. package/dist/cli-delegate/{chunk-PLSG6UL5.js → chunk-K4FFODTS.js} +341 -204
  177. package/dist/cli-delegate/{chunk-YM4GZDJG.js → chunk-L43NCYPB.js} +5 -0
  178. package/dist/cli-delegate/{chunk-B2ERU2VA.js → chunk-WOKWX5PL.js} +1 -1
  179. package/dist/cli-delegate/cmd_brand_status.js +8 -6
  180. package/dist/cli-delegate/cmd_conformance.js +3 -3
  181. package/dist/cli-delegate/cmd_doctor.js +3 -3
  182. package/dist/cli-delegate/cmd_export.js +4 -4
  183. package/dist/cli-delegate/cmd_handoff.js +1 -1
  184. package/dist/cli-delegate/cmd_preflight.js +2 -2
  185. package/dist/cli-delegate/cmd_prune.js +4 -4
  186. package/dist/cli-delegate/cmd_session_recycle.js +70 -9
  187. package/dist/cli-delegate/cmd_settings_migrate.js +4 -4
  188. package/dist/cli-delegate/cmd_settings_set.js +1 -1
  189. package/dist/cli-delegate/cmd_sync.js +4 -4
  190. package/dist/cli-delegate/cmd_uninstall.js +4 -4
  191. package/dist/cli-delegate/cmd_validate.js +4 -4
  192. package/dist/discovery/deprecation-report.md +1 -1
  193. package/dist/discovery/discovery-manifest.json +359 -124
  194. package/dist/discovery/discovery-manifest.json.sha256 +1 -1
  195. package/dist/discovery/discovery-manifest.summary.md +4 -4
  196. package/dist/discovery/dormancy-report.md +1 -1
  197. package/dist/discovery/orphan-report.md +1 -1
  198. package/dist/discovery/packs.json +18 -8
  199. package/dist/discovery/trust-report.md +3 -3
  200. package/dist/discovery/workspaces.json +16 -6
  201. package/dist/hooks/dispatch.js +2337 -1436
  202. package/dist/install/install.mjs +795 -708
  203. package/dist/mcp/registry-manifest.json +3 -3
  204. package/dist/mcp/server.json +2 -2
  205. package/dist/mcp/server.mjs +1685 -1250
  206. package/dist/router.json +1 -1
  207. package/dist/scripts/_lib/lean_projection_mode.js +40 -0
  208. package/dist/scripts/_lib/lean_projection_mode.js.map +1 -0
  209. package/dist/scripts/_lib/scoped_projection.js +84 -0
  210. package/dist/scripts/_lib/scoped_projection.js.map +1 -1
  211. package/dist/scripts/_lib/ui_surface.js +89 -0
  212. package/dist/scripts/_lib/ui_surface.js.map +1 -0
  213. package/dist/scripts/condense.js +6 -10
  214. package/dist/scripts/condense.js.map +1 -1
  215. package/dist/scripts/project_thin_rules.js +40 -2
  216. package/dist/scripts/project_thin_rules.js.map +1 -1
  217. package/dist/server/schemas/settings.js +3 -0
  218. package/dist/server/schemas/settings.js.map +1 -1
  219. package/dist/shared/skillRanking.js +159 -0
  220. package/dist/shared/skillRanking.js.map +1 -0
  221. package/docs/contracts/provider-lifecycle.md +47 -18
  222. package/docs/contracts/settings-classes.md +14 -4
  223. package/docs/guidelines/agent-infra/context-hygiene-mechanics.md +49 -0
  224. package/docs/guidelines/agent-infra/evaluator-independence-mechanics.md +92 -0
  225. package/docs/guidelines/agent-infra/minimal-safe-diff-mechanics.md +45 -1
  226. package/docs/guidelines/agent-infra/roadmap-deferred-resolution-provenance.md +54 -0
  227. package/docs/guidelines/design-antipatterns.md +4 -2
  228. package/docs/guidelines/design-asset-discipline.md +38 -0
  229. package/docs/guidelines/design-fidelity-mechanics.md +45 -29
  230. package/docs/guidelines/design-handover-extraction.md +35 -5
  231. package/docs/guidelines/design-modes.md +41 -1
  232. package/docs/guidelines/monorepo-antipatterns.md +141 -0
  233. package/llms.txt +50 -39
  234. package/package.json +1 -1
  235. package/src/agent-src/templates/scripts/check_playbook_invokes.ts +231 -0
  236. package/src/agent-src/templates/scripts/work_engine/directives/ui/apply.ts +24 -0
  237. package/src/agent-src/templates/scripts/work_engine/directives/ui/polish.ts +2 -0
  238. package/src/agent-src/templates/scripts/work_engine/directives/ui/review.ts +216 -0
  239. package/src/agent-src/templates/scripts/work_engine/directives/ui/scaffold.ts +159 -0
  240. package/src/agent-src/templates/scripts/work_engine/directives/ui/stack_bundles.ts +73 -4
  241. package/src/agent-src/templates/scripts/work_engine/stack/detect.ts +325 -40
  242. package/src/config/agent-settings.template.yml +28 -0
  243. package/src/config/assurance-capability-registry.json +223 -0
  244. package/src/config/assurance-threshold-budget.json +65 -0
  245. package/src/config/ci-local-parity.yml +14 -0
  246. package/src/config/discovery/unassigned-artefacts.yml +2 -0
  247. package/src/config/dispatch-economy-metrics.json +4 -2
  248. package/src/config/evaluator-budgets.json +14 -14
  249. package/src/config/gate-coverage.yml +207 -8
  250. package/src/config/gate-violation-baselines.json +76 -72
  251. package/src/config/hook-latency-budget.json +1 -0
  252. package/src/config/hook-token-budget.json +137 -125
  253. package/src/config/pack-size-budget.json +4 -2
  254. package/src/config/quorum-attendance-budget.json +12 -4
  255. package/src/config/rule-activation-census.json +7 -3
  256. package/src/config/rule-enforcement-baseline.json +0 -1
  257. package/src/config/rule-stub-ceilings.json +112 -91
  258. package/src/scripts/_cli/cmd_doctor.ts +15 -16
  259. package/src/scripts/_cli/doctor_install_mode.ts +49 -0
  260. package/src/scripts/_cli/doctor_overrides.ts +154 -0
  261. package/src/scripts/_dispatch.bash +17 -0
  262. package/src/scripts/_lib/as_of.ts +412 -0
  263. package/src/scripts/_lib/exec_evidence.ts +7 -0
  264. package/src/scripts/_lib/hook_settings.ts +33 -0
  265. package/src/scripts/_lib/host_listing_model.ts +192 -0
  266. package/src/scripts/_lib/lean_projection_mode.ts +44 -0
  267. package/src/scripts/_lib/mcp_bridge.ts +199 -0
  268. package/src/scripts/_lib/review_independence.ts +62 -10
  269. package/src/scripts/_lib/rule_injection.ts +239 -0
  270. package/src/scripts/_lib/run_checkpoint.ts +54 -1
  271. package/src/scripts/_lib/scoped_projection.ts +96 -0
  272. package/src/scripts/_lib/session_register.ts +44 -2
  273. package/src/scripts/_lib/skill_catalogue.ts +38 -2
  274. package/src/scripts/_lib/transcript_reads.ts +207 -0
  275. package/src/scripts/_lib/ui_authority.test.ts +251 -0
  276. package/src/scripts/_lib/ui_authority.ts +343 -0
  277. package/src/scripts/ai-video/adapters/fal.sh +8 -3
  278. package/src/scripts/ai-video/adapters/gemini-veo.sh +10 -0
  279. package/src/scripts/ai-video/adapters/higgsfield.sh +10 -2
  280. package/src/scripts/ai-video/adapters/kling.sh +10 -0
  281. package/src/scripts/ai-video/adapters/sora.sh +10 -0
  282. package/src/scripts/ai-video/lib/calibrate-cost.sh +145 -0
  283. package/src/scripts/ai-video/lib/model-capabilities/README.md +53 -7
  284. package/src/scripts/ai-video/lib/model-capabilities/comfyui.json +15 -3
  285. package/src/scripts/ai-video/lib/model-capabilities/fal.json +36 -6
  286. package/src/scripts/ai-video/lib/model-capabilities/gemini-veo.json +23 -0
  287. package/src/scripts/ai-video/lib/model-capabilities/higgsfield.json +23 -0
  288. package/src/scripts/ai-video/lib/model-capabilities/kling.json +23 -0
  289. package/src/scripts/ai-video/lib/model-capabilities/musetalk.json +8 -2
  290. package/src/scripts/ai-video/lib/model-capabilities/replicate.json +36 -6
  291. package/src/scripts/ai-video/lib/model-capabilities/sora.json +45 -0
  292. package/src/scripts/ai-video/lib/model-capabilities/syncso.json +8 -2
  293. package/src/scripts/ai-video/lib/parse-blueprint.sh +52 -5
  294. package/src/scripts/ai-video/lib/resume-scan.sh +92 -3
  295. package/src/scripts/ai-video/lib/seam-plan.sh +212 -0
  296. package/src/scripts/ai-video/smoke-trace.sh +450 -2
  297. package/src/scripts/ai-video/stitch.sh +191 -10
  298. package/src/scripts/ai-video/test-pipeline.sh +84 -6
  299. package/src/scripts/ai_council/cli_agency_bounds.ts +139 -0
  300. package/src/scripts/ai_council/cli_least_agency_canary.ts +347 -0
  301. package/src/scripts/ai_council/clients.ts +3 -2
  302. package/src/scripts/ai_council/consensus.ts +63 -6
  303. package/src/scripts/ai_council/events_log.ts +46 -1
  304. package/src/scripts/ai_council/orchestrator.ts +103 -108
  305. package/src/scripts/ai_council/orchestrator_results.ts +166 -0
  306. package/src/scripts/ai_council/prompts.ts +12 -5
  307. package/src/scripts/ai_council/quorum.ts +82 -1
  308. package/src/scripts/ai_council/quorum_wiring.ts +82 -5
  309. package/src/scripts/ai_council/stance_tally.ts +22 -0
  310. package/src/scripts/bench_hook_latency.ts +62 -0
  311. package/src/scripts/build_proof.ts +12 -1
  312. package/src/scripts/capture_skill_catalogue.ts +21 -0
  313. package/src/scripts/check_always_budget.ts +2 -1
  314. package/src/scripts/check_augmentignore.ts +2 -1
  315. package/src/scripts/check_beta_review_markers.ts +2 -1
  316. package/src/scripts/check_composite_arming.ts +364 -0
  317. package/src/scripts/check_corpus_staleness.ts +2 -1
  318. package/src/scripts/check_council_pin_staleness.ts +3 -1
  319. package/src/scripts/check_enforcement_coverage.ts +116 -3
  320. package/src/scripts/check_enforcement_denominator.ts +365 -0
  321. package/src/scripts/check_gate_coverage.ts +2 -1
  322. package/src/scripts/check_hook_bundle_freshness.ts +13 -1
  323. package/src/scripts/check_knowledge_cards.ts +2 -1
  324. package/src/scripts/check_knowledge_pages.ts +3 -2
  325. package/src/scripts/check_memory.ts +2 -1
  326. package/src/scripts/check_no_automerge_key.ts +287 -0
  327. package/src/scripts/check_pack_conformance_fixture.ts +565 -0
  328. package/src/scripts/check_proposal.ts +2 -1
  329. package/src/scripts/check_reach_staleness.ts +2 -1
  330. package/src/scripts/check_release_adjacent_health.ts +2 -1
  331. package/src/scripts/check_release_pr_shape.ts +5 -0
  332. package/src/scripts/check_review_schema.ts +34 -1
  333. package/src/scripts/check_roadmap_trackable.ts +48 -3
  334. package/src/scripts/check_source_size_budget.ts +2 -1
  335. package/src/scripts/check_standing_payload_delta.ts +505 -0
  336. package/src/scripts/check_trigger_evals.ts +2 -1
  337. package/src/scripts/classify_change_risk.ts +281 -0
  338. package/src/scripts/compute_skill_tiers.ts +186 -0
  339. package/src/scripts/condense.ts +8 -13
  340. package/src/scripts/council_attendance_metrics.ts +183 -0
  341. package/src/scripts/council_cli.ts +10 -8
  342. package/src/scripts/council_parse_rate.ts +116 -0
  343. package/src/scripts/derive_playbooks.ts +406 -0
  344. package/src/scripts/design_slop_rules.test.ts +7 -0
  345. package/src/scripts/design_slop_rules.ts +56 -2
  346. package/src/scripts/dispatch_r2_reviewer.ts +16 -0
  347. package/src/scripts/frontend_corpus_hash.ts +116 -0
  348. package/src/scripts/grade_target_readiness.ts +478 -0
  349. package/src/scripts/hook_manifest.json +1 -1
  350. package/src/scripts/hook_manifest.yaml +97 -16
  351. package/src/scripts/hooks/concern_registry.ts +4 -0
  352. package/src/scripts/hooks/design_pass_hook.ts +356 -0
  353. package/src/scripts/hooks/rtk_wrap_hook.ts +30 -7
  354. package/src/scripts/hooks/rule_inject_hook.ts +318 -0
  355. package/src/scripts/hot_context_hook.ts +74 -7
  356. package/src/scripts/install.ts +40 -89
  357. package/src/scripts/lint_adapter_tier.ts +663 -0
  358. package/src/scripts/lint_archived_skills.ts +93 -0
  359. package/src/scripts/lint_budget_ownership.ts +2 -1
  360. package/src/scripts/lint_deterministic_time.ts +470 -0
  361. package/src/scripts/lint_framework_leakage.ts +5 -0
  362. package/src/scripts/lint_handoffs.ts +525 -1
  363. package/src/scripts/lint_judge_prompt_expectation.ts +155 -0
  364. package/src/scripts/lint_marketplace.ts +88 -0
  365. package/src/scripts/lint_media_policy_linkage.ts +140 -1
  366. package/src/scripts/lint_one_off_age.ts +6 -1
  367. package/src/scripts/lint_override_kernel_guard.ts +87 -5
  368. package/src/scripts/lint_roadmap_complexity.ts +56 -0
  369. package/src/scripts/lint_rule_enforcement_declaration.ts +24 -7
  370. package/src/scripts/lint_rule_norm_pin.ts +321 -0
  371. package/src/scripts/lint_spawn_payload.ts +42 -5
  372. package/src/scripts/lint_symptom_intake.ts +2 -1
  373. package/src/scripts/mcp_parity_smoke.ts +30 -4
  374. package/src/scripts/mcp_render.ts +66 -1
  375. package/src/scripts/mcp_tool_fingerprint.ts +241 -0
  376. package/src/scripts/measure_risk_class_drift.ts +140 -0
  377. package/src/scripts/measure_skill_ranker_baseline.ts +212 -0
  378. package/src/scripts/media/lib/adapter-common.sh +211 -1
  379. package/src/scripts/media/lib/adapter-contract.md +74 -6
  380. package/src/scripts/model_rule_injection.ts +907 -0
  381. package/src/scripts/project_thin_rules.ts +45 -2
  382. package/src/scripts/release.ts +66 -860
  383. package/src/scripts/release_drill.ts +59 -3
  384. package/src/scripts/release_env.ts +298 -0
  385. package/src/scripts/release_publication.ts +720 -0
  386. package/src/scripts/roadmap_context.ts +778 -0
  387. package/src/scripts/schemas/fidelity-measurement-sheet.schema.json +169 -0
  388. package/src/scripts/schemas/rule.schema.json +24 -2
  389. package/src/scripts/schemas/skill.schema.json +39 -0
  390. package/src/scripts/schemas/ui-authority.schema.json +114 -0
  391. package/src/scripts/session_register_hook.ts +29 -3
  392. package/src/scripts/sessions_cli.ts +67 -3
  393. package/src/scripts/skill_tools/score_skill_relevance.ts +36 -53
  394. package/src/scripts/token_sink_report.ts +239 -0
  395. package/src/scripts/trigger_coverage.ts +122 -3
  396. package/src/scripts/update_counts.ts +7 -3
  397. package/src/scripts/validate_frontmatter.ts +66 -0
  398. package/src/server/schemas/settings.ts +5 -0
  399. package/src/shared/skillRanking.ts +183 -0
@@ -11,10 +11,30 @@
11
11
  # parse-blueprint.sh < prompt.txt > blueprint.json
12
12
  # parse-blueprint.sh prompt.txt > blueprint.json
13
13
  #
14
+ # Optional CONTINUITY block — how this scene joins the PREVIOUS one:
15
+ #
16
+ # CONTINUITY: cut hard cut (default; the value assumed when the
17
+ # block is absent, so every existing blueprint
18
+ # keeps its exact meaning)
19
+ # CONTINUITY: handoff this scene's ref_images[0] is the extracted last
20
+ # frame of the PREVIOUS scene's rendered clip, not
21
+ # its own still — so the two clips must render
22
+ # sequentially
23
+ # CONTINUITY: connector handoff plus one extra generated clip bridging the
24
+ # two, which needs a probed end_frame:true on both
25
+ # adjacent models (seam-plan.sh gates it)
26
+ #
27
+ # The value is emitted as the top-level `continuity` key. An unknown value is
28
+ # a parse error naming the value — never a silent downgrade to `cut`, because a
29
+ # caller who asked for continuity and got a cut has no way to see it. The seam
30
+ # plan (which boundaries hand off, the generation count, the sequential trade)
31
+ # is printed by the sibling `seam-plan.sh` over an ordered list of these JSONs;
32
+ # this script parses ONE scene and knows nothing about its neighbours.
33
+ #
14
34
  # Exit codes:
15
35
  # 0 valid blueprint, JSON emitted on stdout
16
36
  # 2 missing required block — name on stderr
17
- # 3 parse error (unknown block, malformed DURATION, etc.)
37
+ # 3 parse error (unknown block, malformed DURATION, unknown CONTINUITY)
18
38
 
19
39
  set -euo pipefail
20
40
 
@@ -23,12 +43,24 @@ command -v jq >/dev/null 2>&1 || {
23
43
  exit 3
24
44
  }
25
45
 
26
- input="${1:-/dev/stdin}"
27
- [ -r "$input" ] || { echo "parse-blueprint: cannot read $input" >&2; exit 3; }
46
+ # A file argument is opened; with no argument the ALREADY-OPEN stdin is
47
+ # inherited rather than re-opened through /dev/stdin. Re-opening it is what the
48
+ # documented `parse-blueprint.sh < prompt.txt` form used to do, and it is not
49
+ # portable: on a Linux CI runner whose stdin is a pipe supplied by the test
50
+ # harness, `/dev/stdin` is not openable and the script died with
51
+ # "No such device or address" — the documented interface was broken on the one
52
+ # platform nothing had exercised it on. `exec` keeps the readable-path check
53
+ # meaningful for the argument form while leaving fd 0 untouched otherwise.
54
+ input="${1:-}"
55
+ if [ -n "$input" ]; then
56
+ [ -r "$input" ] || { echo "parse-blueprint: cannot read $input" >&2; exit 3; }
57
+ exec < "$input"
58
+ fi
28
59
 
29
60
  V_STYLE=""; V_SUBJECT=""; V_ENVIRONMENT=""; V_ACTION=""
30
61
  V_CAMERA=""; V_LENS=""; V_LIGHTING=""; V_MOOD=""
31
62
  V_DIALOGUE=""; V_AMBIENT_SOUND=""; V_DURATION=""; V_NEGATIVE=""
63
+ V_CONTINUITY=""
32
64
 
33
65
  append_to() {
34
66
  local name="$1"; local line="$2"
@@ -52,7 +84,7 @@ while IFS= read -r line || [ -n "$line" ]; do
52
84
  if [ -n "$label" ]; then
53
85
  key="$(printf '%s' "$label" | tr ' ' '_' | tr '[:lower:]' '[:upper:]')"
54
86
  case "$key" in
55
- STYLE|SUBJECT|ENVIRONMENT|ACTION|CAMERA|LENS|LIGHTING|MOOD|DIALOGUE|AMBIENT_SOUND|DURATION|NEGATIVE)
87
+ STYLE|SUBJECT|ENVIRONMENT|ACTION|CAMERA|LENS|LIGHTING|MOOD|DIALOGUE|AMBIENT_SOUND|DURATION|NEGATIVE|CONTINUITY)
56
88
  current="V_$key"
57
89
  rest="$(printf '%s' "$stripped" | sed -E "s/^${label}[[:space:]]*:[[:space:]]*//")"
58
90
  set_var "$current" "$rest"
@@ -63,7 +95,7 @@ while IFS= read -r line || [ -n "$line" ]; do
63
95
  if [ -n "$current" ] && [ -n "$line" ]; then
64
96
  append_to "$current" "$line"
65
97
  fi
66
- done < "$input"
98
+ done
67
99
 
68
100
  for short in STYLE SUBJECT ENVIRONMENT ACTION CAMERA LENS LIGHTING MOOD DURATION NEGATIVE; do
69
101
  eval "v=\$V_$short"
@@ -78,6 +110,19 @@ if ! printf '%s' "$V_DURATION" | grep -Eq '^[0-9]+(\.[0-9])?$'; then
78
110
  exit 3
79
111
  fi
80
112
 
113
+ # CONTINUITY is optional; absent means `cut`, which is what every blueprint
114
+ # written before this block existed meant. An unknown value is refused with the
115
+ # value named rather than downgraded to `cut`.
116
+ V_CONTINUITY="$(printf '%s' "$V_CONTINUITY" | sed -E 's/^[[:space:]]*//; s/[[:space:]]*$//' | tr '[:upper:]' '[:lower:]')"
117
+ [ -n "$V_CONTINUITY" ] || V_CONTINUITY="cut"
118
+ case "$V_CONTINUITY" in
119
+ cut|handoff|connector) ;;
120
+ *)
121
+ echo "parse-blueprint: unknown CONTINUITY value: $V_CONTINUITY (expected cut|handoff|connector)" >&2
122
+ exit 3
123
+ ;;
124
+ esac
125
+
81
126
  negative_json="$(printf '%s' "$V_NEGATIVE" | tr ',\n' '\n\n' | sed '/^[[:space:]]*$/d' | sed -E 's/^[[:space:]]*//; s/[[:space:]]*$//' | jq -R . | jq -s .)"
82
127
 
83
128
  to_array_or_null() {
@@ -109,6 +154,7 @@ jq -n \
109
154
  --argjson duration "$V_DURATION" \
110
155
  --argjson negative "$negative_json" \
111
156
  --argjson native "$audio_native" \
157
+ --arg continuity "$V_CONTINUITY" \
112
158
  '{
113
159
  prompt: {
114
160
  style: $style, subject: $subject, environment: $environment,
@@ -118,5 +164,6 @@ jq -n \
118
164
  audio: { dialogue: $dialogue, ambient: $ambient, enable_native_audio: $native },
119
165
  duration: $duration,
120
166
  negative: $negative,
167
+ continuity: $continuity,
121
168
  requires: { audio_native: $native }
122
169
  }'
@@ -22,12 +22,33 @@
22
22
  # failed error.json present.
23
23
  # missing in the plan but no green artifact on disk.
24
24
  #
25
+ # Seam sentinels (handoff chains) — same filesystem-as-state idiom:
26
+ #
27
+ # <project>/seams/<from>__<to>.json
28
+ # {"from","to","mode":"handoff|connector",
29
+ # "from_input_sha256","to_input_sha256"}
30
+ #
31
+ # A seam is DECLARED when scene <to>'s prompt.json carries
32
+ # `continuity: handoff|connector` — the value parse-blueprint.sh emits — and
33
+ # <from> is its immediate predecessor in scene-id order. Clip <to> was
34
+ # conditioned on the RENDERED last frame of clip <from>, so the join is a fact
35
+ # about a pair, which no per-scene sentinel can express. Classification:
36
+ #
37
+ # green sentinel present, both hashes match what is on disk now, and both
38
+ # adjacent scenes are green
39
+ # stale either adjacent scene is not green, or a recorded hash no longer
40
+ # matches — i.e. a failed or re-rolled clip invalidates exactly the
41
+ # seams it touches, and no others
42
+ # missing the seam is declared but no sentinel exists
43
+ #
25
44
  # Usage:
26
45
  # resume-scan.sh scan <project-dir> [--plan <plan.json>]
27
46
  # plan.json: [{"scene_id":"0001","input_sha256":"<hex>"}, …]
28
47
  # stdout: {"scenes":[{scene_id,state,reason?,charged_usd?}],
29
48
  # "green":N,"stale":N,"failed":N,"missing":N,
30
- # "spent_usd":X.YZ}
49
+ # "spent_usd":X.YZ,
50
+ # "seams":[{from,to,mode,state,reason?}],
51
+ # "seams_green":N,"seams_stale":N,"seams_missing":N}
31
52
  #
32
53
  # resume-scan.sh hash [< prompt.json]
33
54
  # Canonical input hash: jq -S over prompt.json with the
@@ -172,13 +193,81 @@ _rs_scan() {
172
193
  else . end)' "${plan}")"
173
194
  fi
174
195
 
175
- printf '%s' "${rows}" | jq '{
196
+ # --- seam pass ------------------------------------------------------------
197
+ # Walks the scene dirs in id order; a seam exists between consecutive scenes
198
+ # when the LATER one declares a handoff continuity. Scene states come from
199
+ # ${rows} above, so a seam can never disagree with its own scenes.
200
+ local seam_rows="[]" prev_id="" prev_state="" cur_id cur_state cont sentinel
201
+ local seam_state seam_reason rec_from rec_to cur_hash prev_hash seam_mode
202
+ if [ -d "${project_abs}/scenes" ]; then
203
+ for scene_dir in "${project_abs}"/scenes/*/; do
204
+ [ -d "${scene_dir}" ] || continue
205
+ cur_id="$(basename "${scene_dir}")"
206
+ case "${cur_id}" in
207
+ *[!A-Za-z0-9._-]*|..|.) continue ;;
208
+ esac
209
+ cur_state="$(printf '%s' "${rows}" | jq -r --arg id "${cur_id}" \
210
+ 'map(select(.scene_id == $id)) | (.[0].state // "")')"
211
+
212
+ cont="cut"
213
+ if [ -f "${scene_dir}prompt.json" ]; then
214
+ cont="$(jq -r '.continuity // "cut"' "${scene_dir}prompt.json" 2>/dev/null || printf 'cut')"
215
+ fi
216
+
217
+ if [ -n "${prev_id}" ] && { [ "${cont}" = "handoff" ] || [ "${cont}" = "connector" ]; }; then
218
+ seam_mode="${cont}"
219
+ sentinel="${project_abs}/seams/${prev_id}__${cur_id}.json"
220
+ seam_state="" seam_reason=""
221
+ if [ ! -f "${sentinel}" ]; then
222
+ seam_state="missing"
223
+ seam_reason="declared ${seam_mode} seam with no sentinel at seams/${prev_id}__${cur_id}.json"
224
+ else
225
+ rec_from="$(jq -r '.from_input_sha256 // empty' "${sentinel}" 2>/dev/null || true)"
226
+ rec_to="$(jq -r '.to_input_sha256 // empty' "${sentinel}" 2>/dev/null || true)"
227
+ prev_hash="$(jq -r '.input_sha256 // empty' "${project_abs}/scenes/${prev_id}/prompt.json" 2>/dev/null || true)"
228
+ cur_hash="$(jq -r '.input_sha256 // empty' "${scene_dir}prompt.json" 2>/dev/null || true)"
229
+ if [ "${prev_state}" != "green" ]; then
230
+ seam_state="stale"
231
+ seam_reason="scene ${prev_id} is ${prev_state:-unknown} — the handoff frame it supplies is not a rendered frame"
232
+ elif [ "${cur_state}" != "green" ]; then
233
+ seam_state="stale"
234
+ seam_reason="scene ${cur_id} is ${cur_state:-unknown} — re-render before the seam can be trusted"
235
+ elif [ -z "${rec_from}" ] || [ -z "${rec_to}" ]; then
236
+ seam_state="stale"
237
+ seam_reason="sentinel records no input hashes — never reuse unverifiable state (ADR-059)"
238
+ elif [ "${rec_from}" != "${prev_hash}" ]; then
239
+ seam_state="stale"
240
+ seam_reason="scene ${prev_id} was re-rolled after the seam was built (input hash changed)"
241
+ elif [ "${rec_to}" != "${cur_hash}" ]; then
242
+ seam_state="stale"
243
+ seam_reason="scene ${cur_id} was re-rolled after the seam was built (input hash changed)"
244
+ else
245
+ seam_state="green"
246
+ fi
247
+ fi
248
+ seam_rows="$(printf '%s' "${seam_rows}" | jq \
249
+ --arg from "${prev_id}" --arg to "${cur_id}" --arg mode "${seam_mode}" \
250
+ --arg st "${seam_state}" --arg rs "${seam_reason}" \
251
+ '. + [{from:$from, to:$to, mode:$mode, state:$st}
252
+ + (if $rs == "" then {} else {reason:$rs} end)]')"
253
+ fi
254
+
255
+ prev_id="${cur_id}"
256
+ prev_state="${cur_state}"
257
+ done
258
+ fi
259
+
260
+ printf '%s' "${rows}" | jq --argjson seams "${seam_rows}" '{
176
261
  scenes: .,
177
262
  green: (map(select(.state == "green")) | length),
178
263
  stale: (map(select(.state == "stale")) | length),
179
264
  failed: (map(select(.state == "failed")) | length),
180
265
  missing: (map(select(.state == "missing")) | length),
181
- spent_usd: (map(.charged_usd // 0) | add // 0)
266
+ spent_usd: (map(.charged_usd // 0) | add // 0),
267
+ seams: $seams,
268
+ seams_green: ($seams | map(select(.state == "green")) | length),
269
+ seams_stale: ($seams | map(select(.state == "stale")) | length),
270
+ seams_missing: ($seams | map(select(.state == "missing")) | length)
182
271
  }'
183
272
  }
184
273
 
@@ -0,0 +1,212 @@
1
+ #!/usr/bin/env bash
2
+ # seam-plan.sh — print the seam plan for an ordered chain of scene JSONs.
3
+ #
4
+ # `parse-blueprint.sh` parses ONE scene and emits its `continuity` value (how
5
+ # that scene joins the PREVIOUS one). Nothing there can see a chain, so nothing
6
+ # there can answer the two questions an operator needs BEFORE any spend:
7
+ #
8
+ # - which boundaries hand off and which cut (a handoff forces the two clips
9
+ # to render sequentially — the chain loses all parallelism);
10
+ # - how many generations the chain costs (N, or up to 2N-1 with connectors).
11
+ #
12
+ # This script answers both, reads nothing but local files, and calls no
13
+ # provider. Pure POSIX-compatible bash (no associative arrays, runs on macOS
14
+ # bash 3.2); jq required.
15
+ #
16
+ # Usage:
17
+ # seam-plan.sh <scene-1.json> <scene-2.json> [...]
18
+ # [--capabilities-dir <dir>]
19
+ # [--json]
20
+ #
21
+ # Scene JSONs are given in RENDER ORDER — the argument order IS the chain.
22
+ # `--capabilities-dir` defaults to this script's `model-capabilities/`
23
+ # sibling; it is a flag so a fixture tree can be planned without touching
24
+ # the shipped manifests.
25
+ # `--json` emits the machine shape instead of the human plan.
26
+ #
27
+ # The connector gate (`null` is never `true`):
28
+ # A `connector` boundary generates an extra clip conditioned on an end frame,
29
+ # so BOTH adjacent models must report a probed `end_frame: true` in their
30
+ # capability manifest. Anything else — `false`, `null`, a missing `end_frame`
31
+ # key, a missing model entry, a missing manifest, or a scene that does not
32
+ # name its adapter/model at all — REFUSES, naming the model. An unknown
33
+ # capability is not a usable capability, and a connector silently downgraded
34
+ # to a handoff is a generation the operator did not approve.
35
+ #
36
+ # Exit codes:
37
+ # 0 plan printed
38
+ # 2 usage error, or a refused plan (first-scene continuity, connector gate)
39
+ # 3 tool missing
40
+ # 7 unreadable / invalid scene JSON
41
+ set -euo pipefail
42
+
43
+ _sp_die() { local code="$1"; shift; printf 'seam-plan: %s\n' "$*" >&2; exit "${code}"; }
44
+
45
+ command -v jq >/dev/null 2>&1 || _sp_die 3 "jq required"
46
+
47
+ HERE="$(cd "$(dirname "$0")" && pwd)"
48
+ CAP_DIR="${HERE}/model-capabilities"
49
+ AS_JSON=0
50
+ # Scene paths go to a line-delimited temp file rather than into one
51
+ # space-separated string: re-splitting a string on IFS would break the moment a
52
+ # project path contains a space, which on macOS it routinely does.
53
+ SCENE_LIST="$(mktemp -t aiv-seam-plan-XXXXXX)"
54
+ trap 'rm -f "${SCENE_LIST}"' EXIT
55
+
56
+ while [ "$#" -gt 0 ]; do
57
+ case "$1" in
58
+ --capabilities-dir) CAP_DIR="${2:-}"; shift 2 ;;
59
+ --json) AS_JSON=1; shift ;;
60
+ -h|--help)
61
+ sed -n '2,40p' "$0" | sed 's/^# \{0,1\}//'
62
+ exit 0 ;;
63
+ --*) _sp_die 2 "unknown flag '$1'" ;;
64
+ *) printf '%s\n' "$1" >> "${SCENE_LIST}"; shift ;;
65
+ esac
66
+ done
67
+
68
+ N="$(wc -l < "${SCENE_LIST}" | tr -d ' ')"
69
+ [ "${N}" -ge 1 ] || _sp_die 2 "usage: seam-plan.sh <scene-1.json> <scene-2.json> [...] [--capabilities-dir <dir>] [--json]"
70
+
71
+ # --- read the chain -----------------------------------------------------------
72
+ # Parallel positional lists (bash 3.2 has no associative arrays): one
73
+ # newline-separated record per scene, `label<TAB>continuity<TAB>adapter<TAB>model`.
74
+ CHAIN=""
75
+ while IFS= read -r scene_file; do
76
+ [ -n "${scene_file}" ] || continue
77
+ [ -r "${scene_file}" ] || _sp_die 7 "scene JSON not readable: ${scene_file}"
78
+ jq -e 'type == "object"' "${scene_file}" >/dev/null 2>&1 \
79
+ || _sp_die 7 "scene JSON must be an object: ${scene_file}"
80
+ label="$(basename "${scene_file}")"
81
+ label="${label%.json}"
82
+ # A missing `continuity` means `cut` — the value every blueprint written
83
+ # before the block existed meant.
84
+ cont="$(jq -r '.continuity // "cut"' "${scene_file}")"
85
+ case "${cont}" in
86
+ cut|handoff|connector) ;;
87
+ *) _sp_die 7 "scene ${label}: unknown continuity value '${cont}' (expected cut|handoff|connector)" ;;
88
+ esac
89
+ adapter="$(jq -r '.adapter // ""' "${scene_file}")"
90
+ model="$(jq -r '.model_id // ""' "${scene_file}")"
91
+ CHAIN="${CHAIN}${label} ${cont} ${adapter} ${model}
92
+ "
93
+ done < "${SCENE_LIST}"
94
+
95
+ _sp_field() { # _sp_field <index-1-based> <field-1-based>
96
+ printf '%s' "${CHAIN}" | sed -n "$1p" | cut -f"$2"
97
+ }
98
+
99
+ # --- refusal: a non-cut continuity on the first scene -------------------------
100
+ first_label="$(_sp_field 1 1)"
101
+ first_cont="$(_sp_field 1 2)"
102
+ if [ "${first_cont}" != "cut" ]; then
103
+ _sp_die 2 "scene ${first_label} declares continuity=${first_cont} but has no previous scene to hand off from — the first scene of a chain is always a cut"
104
+ fi
105
+
106
+ # --- end_frame lookup ---------------------------------------------------------
107
+ # Returns the literal manifest value, or `null` for every kind of not-knowing:
108
+ # missing manifest, missing model entry, missing key, unnamed model. Phase 1's
109
+ # schema keys may not exist yet, so a missing key is read defensively — it is
110
+ # indistinguishable from `null` on purpose.
111
+ _sp_end_frame() { # _sp_end_frame <adapter> <model>
112
+ local adapter="$1" model="$2" file
113
+ if [ -z "${adapter}" ] || [ -z "${model}" ]; then printf 'null'; return 0; fi
114
+ case "${adapter}" in
115
+ */*|..|.|"") printf 'null'; return 0 ;;
116
+ esac
117
+ file="${CAP_DIR}/${adapter}.json"
118
+ [ -r "${file}" ] || { printf 'null'; return 0; }
119
+ # `// null` would be WRONG here: jq's alternative operator treats `false` as
120
+ # absent, so a probed `end_frame: false` would be reported as `null` and the
121
+ # refusal message would name the wrong reason. `has` distinguishes them.
122
+ jq -r --arg m "${model}" \
123
+ '(.models[$m] // {}) | (if has("end_frame") then .end_frame else null end) | tostring' \
124
+ "${file}" 2>/dev/null || printf 'null'
125
+ }
126
+
127
+ # --- walk the seams -----------------------------------------------------------
128
+ handoff_count=0
129
+ connector_count=0
130
+ cut_count=0
131
+ PLAN_LINES=""
132
+ SEAM_JSON="[]"
133
+ refusals=""
134
+
135
+ i=2
136
+ while [ "${i}" -le "${N}" ]; do
137
+ prev=$((i - 1))
138
+ from_label="$(_sp_field "${prev}" 1)"
139
+ to_label="$(_sp_field "${i}" 1)"
140
+ cont="$(_sp_field "${i}" 2)"
141
+
142
+ case "${cont}" in
143
+ cut) cut_count=$((cut_count + 1)) ;;
144
+ handoff) handoff_count=$((handoff_count + 1)) ;;
145
+ connector)
146
+ connector_count=$((connector_count + 1))
147
+ from_adapter="$(_sp_field "${prev}" 3)"; from_model="$(_sp_field "${prev}" 4)"
148
+ to_adapter="$(_sp_field "${i}" 3)"; to_model="$(_sp_field "${i}" 4)"
149
+ from_ef="$(_sp_end_frame "${from_adapter}" "${from_model}")"
150
+ to_ef="$(_sp_end_frame "${to_adapter}" "${to_model}")"
151
+ for side in from to; do
152
+ if [ "${side}" = "from" ]; then
153
+ ef="${from_ef}"; m="${from_model}"; a="${from_adapter}"; s="${from_label}"
154
+ else
155
+ ef="${to_ef}"; m="${to_model}"; a="${to_adapter}"; s="${to_label}"
156
+ fi
157
+ if [ "${ef}" != "true" ]; then
158
+ [ -n "${m}" ] || m="<unnamed model>"
159
+ [ -n "${a}" ] || a="<unnamed adapter>"
160
+ refusals="${refusals}connector refused at seam ${prev}->${i} (${from_label} -> ${to_label}): scene ${s} model '${m}' (adapter ${a}) reports end_frame=${ef} — a connector needs a probed end_frame:true on both sides, and null is not true
161
+ "
162
+ fi
163
+ done
164
+ ;;
165
+ esac
166
+
167
+ PLAN_LINES="${PLAN_LINES} seam ${prev}->${i} (${from_label} -> ${to_label}): ${cont}
168
+ "
169
+ SEAM_JSON="$(printf '%s' "${SEAM_JSON}" | jq \
170
+ --arg from "${from_label}" --arg to "${to_label}" --arg mode "${cont}" \
171
+ --argjson index "${prev}" \
172
+ '. + [{index: $index, from: $from, to: $to, mode: $mode}]')"
173
+ i=$((i + 1))
174
+ done
175
+
176
+ if [ -n "${refusals}" ]; then
177
+ printf '%s' "${refusals}" | while IFS= read -r line; do
178
+ [ -n "${line}" ] && printf 'seam-plan: %s\n' "${line}" >&2
179
+ done
180
+ exit 2
181
+ fi
182
+
183
+ # --- generation count ---------------------------------------------------------
184
+ # Each scene is one generation; each connector seam adds one bridging clip. A
185
+ # chain where EVERY boundary is a connector costs 2N-1, which is the number the
186
+ # operator has to see before approving spend.
187
+ GENS=$((N + connector_count))
188
+ GENS_NOTE=""
189
+ if [ "${N}" -gt 1 ] && [ "${connector_count}" -eq $((N - 1)) ]; then
190
+ GENS_NOTE=" (2N-1)"
191
+ fi
192
+
193
+ SEQUENTIAL=false
194
+ if [ $((handoff_count + connector_count)) -gt 0 ]; then SEQUENTIAL=true; fi
195
+
196
+ if [ "${AS_JSON}" -eq 1 ]; then
197
+ printf '%s' "${SEAM_JSON}" | jq \
198
+ --argjson scenes "${N}" --argjson gens "${GENS}" \
199
+ --argjson handoff "${handoff_count}" --argjson connector "${connector_count}" \
200
+ --argjson cut "${cut_count}" --argjson sequential "${SEQUENTIAL}" \
201
+ '{scenes: $scenes, seams: ., handoff: $handoff, connector: $connector,
202
+ cut: $cut, sequential: $sequential, gens: $gens}'
203
+ exit 0
204
+ fi
205
+
206
+ printf 'seam-plan: scenes=%d seams=%d cut=%d handoff=%d connector=%d sequential=%s\n' \
207
+ "${N}" "$((N > 0 ? N - 1 : 0))" "${cut_count}" "${handoff_count}" "${connector_count}" "${SEQUENTIAL}"
208
+ printf '%s' "${PLAN_LINES}"
209
+ if [ "${SEQUENTIAL}" = "true" ]; then
210
+ printf 'seam-plan: handoff/connector seams render SEQUENTIALLY — the chain loses parallelism\n'
211
+ fi
212
+ printf 'gens: %d%s\n' "${GENS}" "${GENS_NOTE}"