@event4u/agent-config 2.23.0 → 2.25.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 (82) hide show
  1. package/.agent-src/commands/create-pr/description-only.md +39 -11
  2. package/.agent-src/commands/create-pr.md +59 -5
  3. package/.agent-src/commands/video/from-script.md +123 -0
  4. package/.agent-src/commands/video/scene.md +92 -0
  5. package/.agent-src/commands/video/stitch.md +83 -0
  6. package/.agent-src/commands/video/storyboard.md +95 -0
  7. package/.agent-src/commands/video.md +59 -0
  8. package/.agent-src/contexts/execution/roadmap-process-loop.md +69 -14
  9. package/.agent-src/personas/README.md +5 -1
  10. package/.agent-src/personas/ai-video-technical-director.md +81 -0
  11. package/.agent-src/personas/hollywood-director.md +99 -0
  12. package/.agent-src/profiles/content_creator.yml +5 -0
  13. package/.agent-src/rules/media-governance-routing.md +82 -0
  14. package/.agent-src/rules/persona-governance.md +90 -0
  15. package/.agent-src/rules/post-push-rewrite-discipline.md +70 -0
  16. package/.agent-src/rules/provider-lifecycle-discipline.md +75 -0
  17. package/.agent-src/rules/roadmap-ci-steps-policy.md +145 -0
  18. package/.agent-src/rules/roadmap-progress-sync.md +11 -5
  19. package/.agent-src/skills/character-consistency/SKILL.md +131 -0
  20. package/.agent-src/skills/git-workflow/SKILL.md +133 -0
  21. package/.agent-src/skills/motion-choreographer/SKILL.md +161 -0
  22. package/.agent-src/skills/pixar-storyteller/SKILL.md +120 -0
  23. package/.agent-src/skills/roadmap-writing/SKILL.md +10 -0
  24. package/.agent-src/skills/scene-expander/SKILL.md +137 -0
  25. package/.agent-src/skills/scene-expander/scene-blueprint.schema.yaml +108 -0
  26. package/.agent-src/skills/subagent-orchestration/SKILL.md +17 -15
  27. package/.agent-src/skills/video-director/SKILL.md +126 -0
  28. package/.agent-src/templates/agent-settings.md +19 -0
  29. package/.agent-src/templates/agents/agent-project-settings.example.yml +1 -1
  30. package/.agent-src/templates/roadmaps.md +16 -0
  31. package/.claude-plugin/marketplace.json +11 -1
  32. package/CHANGELOG.md +65 -0
  33. package/README.md +7 -5
  34. package/config/agent-settings.template.yml +54 -0
  35. package/docs/adrs/caveman/0001-default-off-until-bench.md +2 -2
  36. package/docs/adrs/cost/0001-hard-stop-hook.md +1 -1
  37. package/docs/adrs/smoke/0001-per-tier-smoke-scripts.md +2 -2
  38. package/docs/architecture.md +3 -3
  39. package/docs/catalog.md +18 -5
  40. package/docs/contracts/command-clusters.md +1 -0
  41. package/docs/contracts/compression-default-kill-criterion.md +1 -1
  42. package/docs/contracts/file-ownership-matrix.json +405 -0
  43. package/docs/contracts/provider-lifecycle.md +122 -0
  44. package/docs/decisions/ADR-011-domain-pack-readiness.md +213 -0
  45. package/docs/decisions/INDEX.md +1 -0
  46. package/docs/getting-started-by-role.md +10 -0
  47. package/docs/getting-started.md +2 -2
  48. package/docs/parity/ruflo.md +3 -3
  49. package/docs/personas.md +73 -26
  50. package/docs/profiles.md +9 -4
  51. package/package.json +1 -1
  52. package/scripts/_tmp_scan_framework_leakage.py +119 -0
  53. package/scripts/ai-video/adapters/gemini-veo.sh +62 -0
  54. package/scripts/ai-video/adapters/higgsfield.sh +88 -0
  55. package/scripts/ai-video/adapters/kling.sh +59 -0
  56. package/scripts/ai-video/adapters/openai-images.sh +57 -0
  57. package/scripts/ai-video/adapters/sora.sh +60 -0
  58. package/scripts/ai-video/lib/adapter-common.sh +116 -0
  59. package/scripts/ai-video/lib/adapter-contract.md +163 -0
  60. package/scripts/ai-video/lib/fixtures/gemini-veo/result.json +1 -0
  61. package/scripts/ai-video/lib/fixtures/gemini-veo/scene-0001.mp4 +1 -0
  62. package/scripts/ai-video/lib/fixtures/higgsfield/result.json +1 -0
  63. package/scripts/ai-video/lib/fixtures/higgsfield/scene-0001.mp4 +1 -0
  64. package/scripts/ai-video/lib/fixtures/kling/result.json +1 -0
  65. package/scripts/ai-video/lib/fixtures/kling/scene-0001.mp4 +1 -0
  66. package/scripts/ai-video/lib/fixtures/openai-images/result.json +1 -0
  67. package/scripts/ai-video/lib/fixtures/openai-images/scene-0001.png +3 -0
  68. package/scripts/ai-video/lib/fixtures/sora/result.json +1 -0
  69. package/scripts/ai-video/lib/fixtures/sora/scene-0001.mp4 +1 -0
  70. package/scripts/ai-video/lib/load-config.sh +140 -0
  71. package/scripts/ai-video/lib/operator-pick.sh +119 -0
  72. package/scripts/ai-video/lib/parse-blueprint.sh +122 -0
  73. package/scripts/ai-video/lib/redact.sh +85 -0
  74. package/scripts/ai-video/lib/validate-deps.sh +132 -0
  75. package/scripts/ai-video/stitch.sh +154 -0
  76. package/scripts/ai-video/test-pipeline.sh +169 -0
  77. package/scripts/check_portability.py +6 -0
  78. package/scripts/lint_media_policy_linkage.py +140 -0
  79. package/scripts/lint_persona_governance.py +164 -0
  80. package/scripts/lint_roadmap_ci_steps.py +182 -0
  81. package/scripts/schemas/command.schema.json +8 -0
  82. package/scripts/smoke/schema.sh +1 -1
@@ -0,0 +1,145 @@
1
+ ---
2
+ type: "auto"
3
+ tier: "2a"
4
+ description: "When authoring or executing roadmaps — forbid task ci / make test / npm run check steps when quality.local_auto_run is false; skip inline at execution"
5
+ source: package
6
+ triggers:
7
+ - path_prefix: "agents/roadmaps/"
8
+ - path_prefix: "app/Modules/"
9
+ - keyword: "task ci"
10
+ - keyword: "make test"
11
+ - keyword: "npm run check"
12
+ - keyword: "pnpm run check"
13
+ - keyword: "yarn check"
14
+ - keyword: "composer test"
15
+ - phrase: "run the quality pipeline"
16
+ - phrase: "run task ci"
17
+ - phrase: "run the full ci"
18
+ applies_to_user_types:
19
+ - "maintainer"
20
+ - "developer"
21
+ validator_ignore:
22
+ - type: "substring"
23
+ pattern: "agents/roadmaps/"
24
+ reason: "Rule's subject is roadmap files under agents/roadmaps/; every body link points there by design."
25
+ - type: "substring"
26
+ pattern: ".agent-settings.yml"
27
+ reason: "Rule reads quality.local_auto_run from .agent-settings.yml; naming the file is the contract."
28
+ ---
29
+
30
+ # Roadmap CI-Steps Policy
31
+
32
+ ## Iron Law
33
+
34
+ ```
35
+ WHEN quality.local_auto_run IS FALSE,
36
+ ROADMAPS MUST NOT SCHEDULE FULL-PIPELINE CI STEPS,
37
+ AND EXECUTION MUST SKIP THEM INLINE WITH [-] AND A REASON.
38
+ ```
39
+
40
+ When `quality.local_auto_run: false` in `.agent-settings.yml`, every
41
+ full-pipeline gate run during roadmap work is wasted wall-clock and
42
+ tokens — remote CI on the PR is the authoritative gate. Roadmaps
43
+ must neither schedule nor execute them locally. New CI gates and
44
+ smoke/test files added by the roadmap itself are exempt — they must
45
+ run once locally to count as verified evidence per
46
+ [`verify-before-complete`](verify-before-complete.md).
47
+
48
+ ## Forbidden step patterns (authoring + execution)
49
+
50
+ A step is **CI-shaped** when its text matches any pattern below.
51
+ Case-insensitive. Line-bounded — literal must appear inside the
52
+ step's `- [ ]` line or its immediate inline `<!-- … -->` / `(…)` note.
53
+
54
+ | Pattern | Example |
55
+ |---|---|
56
+ | `task ci` | `Run task ci before the boundary` |
57
+ | `task ci-strict` | `task ci-strict release gate` |
58
+ | `task ci-fast` | `task ci-fast smoke` |
59
+ | `make test` | `Run make test on phase boundary` |
60
+ | `make ci` | `make ci pre-merge` |
61
+ | `npm run check` / `pnpm run check` / `yarn check` | `npm run check before commit` |
62
+ | `composer test` | `composer test on every phase` |
63
+ | `vendor/bin/phpunit` (whole-suite, no path arg) | `vendor/bin/phpunit` |
64
+ | `php artisan test` (no `--filter`) | `php artisan test` |
65
+
66
+ Targeted commands (`vendor/bin/phpstan analyse app/Modules/X`,
67
+ `php artisan test --filter=…`, `npm run lint -- --fix path/`) are
68
+ **not** CI-shaped — narrow verifications, allowed regardless of the
69
+ setting.
70
+
71
+ ## Carve-outs — when CI-shaped steps are still allowed
72
+
73
+ 1. **New CI gate / smoke test / test file landed by this roadmap.**
74
+ Once-locally execution is mandatory under
75
+ [`verify-before-complete`](verify-before-complete.md) carve-out
76
+ (see `templates/agent-settings.md` § `quality.local_auto_run`).
77
+ Mark the step with `<!-- carve-out: new-gate-verification -->`
78
+ on the same line; linter and execution loop honour it and let the
79
+ step run.
80
+ 2. **`quality.local_auto_run: true`.** Opt-in restores pre-policy
81
+ behaviour — linter no-ops, execution loop runs CI steps unmodified.
82
+ 3. **Acceptance-criteria block at end of roadmap.** Final-gate prose
83
+ like "All quality gates pass (`task ci`)" inside an
84
+ `## Acceptance criteria` section is documentation, not an
85
+ executable step (no `- [ ]` checkbox in front). Linter ignores;
86
+ execution loop never reaches it as a step.
87
+
88
+ ## Authoring — linter blocks at write-time
89
+
90
+ `task lint-roadmap-ci-steps` (wired into `task ci-fast` /
91
+ `lint-roadmap-complexity` cadence) scans `agents/roadmaps/*.md` and
92
+ `app/Modules/*/agents/roadmaps/*.md`. Exit code:
93
+
94
+ - `0` — no CI-shaped steps, or setting is `true`, or every match is
95
+ carve-out-marked.
96
+ - `1` — at least one CI-shaped step in an active (non-archived,
97
+ non-skipped) roadmap with `quality.local_auto_run: false` and no
98
+ carve-out marker. Linter prints file, line, matched literal, and
99
+ suggested rewording.
100
+
101
+ Archive (`agents/roadmaps/archive/`) and skipped
102
+ (`agents/roadmaps/skipped/`) are out of scope — they record history,
103
+ not future work.
104
+
105
+ ## Execution — process-loop skips inline
106
+
107
+ Wrappers `/roadmap:process-step|phase|full` honour the policy at the
108
+ top of [`roadmap-process-loop § 5`](../contexts/execution/roadmap-process-loop.md#5-step-loop):
109
+
110
+ 1. Before running a step, match its text against the patterns above.
111
+ 2. CI-shaped **and** `quality.local_auto_run: false` **and** no
112
+ carve-out marker → flip checkbox to `[-]` (cancelled), append a
113
+ one-line reason as inline note, regenerate the dashboard, continue
114
+ to next step. **Never** run the gate.
115
+ 3. CI-shaped **and** `quality.local_auto_run: true` → run normally.
116
+ 4. Carve-out-marked → run regardless of the setting.
117
+
118
+ The `[-]` reason format is fixed:
119
+ `<!-- skipped: quality.local_auto_run=false → remote CI is the gate -->`.
120
+ Per [`roadmap-progress-sync`](roadmap-progress-sync.md) the flip and
121
+ dashboard regen happen in the **same reply** that decides to skip;
122
+ saving skips for the archive commit is a rule violation.
123
+
124
+ ## Failure modes
125
+
126
+ - Authoring `- [ ] Run task ci` while `local_auto_run: false` — linter
127
+ fails the PR.
128
+ - Executing a CI-shaped step without inline-skip flip — Iron Law
129
+ violation; loop never reaches the gate.
130
+ - Carve-out marker on an *existing* pipeline run — abuse; the marker
131
+ is reserved for **new** gates introduced by the same roadmap.
132
+ - Hiding the literal inside a fenced bash block to dodge the linter —
133
+ linter matches inside fenced blocks too (see
134
+ `scripts/lint_roadmap_ci_steps.py`).
135
+
136
+ ## See also
137
+
138
+ - [`verify-before-complete`](verify-before-complete.md) — Iron Law
139
+ this rule narrows; carve-out cites it.
140
+ - [`roadmap-progress-sync`](roadmap-progress-sync.md) — inline flip +
141
+ dashboard regen contract.
142
+ - `templates/agent-settings.md` § `quality.local_auto_run` — source
143
+ of the toggle and its carve-out wording.
144
+ - [`contexts/execution/roadmap-process-loop`](../contexts/execution/roadmap-process-loop.md)
145
+ — § 5 owns the inline-skip mechanics.
@@ -25,16 +25,17 @@ Roadmap touch = create / rename / delete / move file, add/rename/remove a phase,
25
25
  ```
26
26
  EVERY DONE STEP FLIPS [ ] → [x] IN THE SAME REPLY THAT LANDS THE WORK.
27
27
  NO "I UPDATE THE ROADMAP AT THE END OF THE PHASE."
28
- NO "FOUR STEPS DONE, ONE COMMIT, ONE REGEN."
29
28
  A REPLY THAT LANDS A VERIFIED STEP WITHOUT FLIPPING ITS CHECKBOX
30
29
  IS A RULE VIOLATION, NOT AN OVERSIGHT.
31
30
  ```
32
31
 
33
- `/roadmap:process-step`, `/roadmap:process-phase`, `/roadmap:process-full`, and any other multi-step autonomous run flip the box for step N **before** moving on to step N+1. The dashboard is a real-time monitor, not a post-hoc summary. Batched flips at the archive commit defeat the dashboard's purpose.
32
+ `/roadmap:process-step`, `/roadmap:process-phase`, `/roadmap:process-full`, and any other multi-step autonomous run flip the box for step N **before** moving on to step N+1. The checkbox itself is the real-time monitor the markdown file is the source of truth, the dashboard is a derived view.
34
33
 
35
34
  **Step counts as done** when its code/doc change is written and saved AND the verification cited in the step has passed (fresh output in this reply or an earlier one).
36
35
 
37
- **In-progress marker.** When a step takes more than one reply, mark it `[~]` the moment work starts and regen — the user sees one row move `[ ] → [~] → [x]` instead of silent rows. `[~]` stays open for `count_open` but advances the phase percentage.
36
+ **In-progress marker.** When a step takes more than one reply, mark it `[~]` the moment work starts — the user sees one row move `[ ] → [~] → [x]` instead of silent rows. `[~]` stays open for `count_open` but advances the phase percentage.
37
+
38
+ **Dashboard regen cadence — opt-in batching.** The checkbox flip is non-batchable. The **subprocess regen** (`./agent-config roadmap:progress`) is batchable per `roadmap.dashboard_regen_cadence` in `.agent-settings.yml` (`per_step` default · `every_5_steps` · `phase_boundary`). Run end, phase boundary, and any file-shape touch (rename / phase add / archive — Iron Law 1) always force an immediate regen regardless of cadence.
38
39
 
39
40
  ## Pre-send self-check — MANDATORY
40
41
 
@@ -42,10 +43,15 @@ Before sending any reply that landed roadmap work:
42
43
 
43
44
  1. Did this reply land a step (code/doc saved + verification passed)?
44
45
  2. Is its checkbox flipped to `[x]` / `[~]` / `[-]` in `agents/roadmaps/<file>.md`? If no → flip, then continue.
45
- 3. Did `./agent-config roadmap:progress` run after the flip? If no → run, then continue.
46
+ 3. Is regen due now per `roadmap.dashboard_regen_cadence`?
47
+ - `per_step` → yes, always.
48
+ - `every_5_steps` → yes when this is the 5th, 10th, … closed step in the run, or the last step of the reply.
49
+ - `phase_boundary` → only when this reply closes the phase or run.
50
+ - Any file-shape touch (rename / phase add / archive) → yes, regardless of cadence.
51
+ If yes and not run yet → run `./agent-config roadmap:progress`, then continue.
46
52
  4. Did `count_open` reach 0? If yes → `git mv` to `archive/` and regen again — same reply.
47
53
 
48
- Any "no" at step 2 or 3 → reply is incomplete. Do not send.
54
+ Any "no" at step 2 → reply is incomplete. Do not send. A skipped step 3 regen is fine when cadence permits — checkbox truth lives in the markdown file.
49
55
 
50
56
  Long-form mechanics (failure-mode catalog, Copilot fallback, `[~]` vs `[ ]` semantics, hook + CI defence-in-depth) live in `guideline:agent-infra/roadmap-progress-mechanics`.
51
57
  Trigger-set above activates this routing under the `balanced` and `full` profiles.
@@ -0,0 +1,131 @@
1
+ ---
2
+ name: character-consistency
3
+ description: "Use when a character must stay visually identical across AI video scenes — locks identity tokens (silhouette, palette, wardrobe, prop) in JSON. Triggers 'character lock', 'same character'."
4
+ personas:
5
+ - hollywood-director
6
+ source: package
7
+ domain: product
8
+ ---
9
+
10
+ # character-consistency
11
+
12
+ > Lock a character's visual identity into
13
+ > `agents/ai-video/<project>/characters/<id>.json` so every scene
14
+ > reuses the **exact same tokens** verbatim. Downstream skills
15
+ > ([`video-director`](../video-director/SKILL.md),
16
+ > [`pixar-storyteller`](../pixar-storyteller/SKILL.md),
17
+ > [`motion-choreographer`](../motion-choreographer/SKILL.md)) read
18
+ > this file and never paraphrase. Verified by visual regression
19
+ > (pixel similarity ≥ 95%, Phase 6 Step 3).
20
+
21
+ ## When to use
22
+
23
+ - A multi-scene run names the same character on screen more than
24
+ once — Character Lock is mandatory before the second scene drafts.
25
+ - A character drift bug landed (face / outfit / prop changed between
26
+ scenes) — re-lock and rerun the affected scenes.
27
+ - A series, episode, or recurring ad uses the same on-screen identity.
28
+
29
+ Do NOT use when:
30
+
31
+ - One-shot scene with no recurring character — overhead is wasted.
32
+ - The "character" is an object or environment, not a person /
33
+ creature — use a `style.json` lock pattern in the project's notes
34
+ instead.
35
+
36
+ ## Procedure
37
+
38
+ ### Step 0: Inspect
39
+
40
+ 1. Check `agents/ai-video/<project>/characters/` — if a lock already
41
+ exists for this id, **read it, do not redraft**. Edits require an
42
+ explicit revision note (Phase 6 visual regression must rerun).
43
+ 2. Confirm the character will appear in ≥ 2 scenes; one-shot → skip.
44
+
45
+ ### Step 1: Draft identity tokens
46
+
47
+ Emit a JSON file at
48
+ `agents/ai-video/<project>/characters/<character-id>.json` with the
49
+ following fields. Every field is mandatory; missing field → fail
50
+ the lock.
51
+
52
+ ```json
53
+ {
54
+ "id": "kebab-case-id",
55
+ "name": "Display Name",
56
+ "silhouette": "one-line read of the body shape from 30m",
57
+ "palette": ["#hex1", "#hex2", "#hex3"],
58
+ "wardrobe": "garment list, materials, era",
59
+ "signature_prop": "the one object that travels with them",
60
+ "posture_default": "how they stand when not acting",
61
+ "eye_behavior": "blink rhythm, glance habit",
62
+ "face": "age band, skin tone, hair (length / color / texture), distinguishing marks",
63
+ "voice_note": "timbre + cadence for native-audio adapters; null if N/A",
64
+ "reference_frame": "scenes/<id>/frames/<n>.png or null",
65
+ "version": 1
66
+ }
67
+ ```
68
+
69
+ ### Step 2: Reference frame
70
+
71
+ 1. After the first scene renders, copy the highest-quality frame
72
+ showing the character full-face and full-body to
73
+ `agents/ai-video/<project>/characters/<id>.ref.png`.
74
+ 2. Update `reference_frame` in the JSON to point at it.
75
+ 3. Phase 6 visual regression compares every subsequent scene's
76
+ character frame against this reference (ImageMagick `compare`
77
+ ≥ 95% similarity).
78
+
79
+ ### Step 3: Validate
80
+
81
+ 1. JSON parses (`jq . characters/<id>.json` exits 0).
82
+ 2. All mandatory fields present and non-empty.
83
+ 3. Palette has ≥ 2 and ≤ 5 hex values.
84
+ 4. Downstream skills cite this file by path, never paraphrase its
85
+ contents.
86
+
87
+ ## Output format
88
+
89
+ 1. **`agents/ai-video/<project>/characters/<id>.json`** — locked
90
+ identity tokens, schema above.
91
+ 2. **`agents/ai-video/<project>/characters/<id>.ref.png`** —
92
+ reference frame (added after first render).
93
+ 3. **`agents/ai-video/<project>/characters/CHANGELOG.md`** — one
94
+ line per revision: `v<n> · YYYY-MM-DD · reason · scenes-to-rerun`.
95
+
96
+ ## Gotcha
97
+
98
+ - The model wants to "improve" identity tokens on each scene —
99
+ this is the silent drift failure. Tokens are immutable until a
100
+ revision note bumps `version`.
101
+ - Palette without a count fails downstream — adapters need a small
102
+ closed set (2–5 hex).
103
+ - `voice_note: null` is explicit; missing the key entirely breaks
104
+ the schema validator.
105
+ - Reference frame is captured *after* the first successful render,
106
+ not before — bootstrap scenes have no reference and only the
107
+ JSON locks them.
108
+ - A revision (`version` bumped) requires Phase 6 visual regression
109
+ to rerun against every prior scene that used the old version.
110
+
111
+ ## Do NOT
112
+
113
+ - Do NOT paraphrase identity tokens when drafting scene prompts —
114
+ copy verbatim or break the lock.
115
+ - Do NOT edit a locked JSON in place without bumping `version` and
116
+ adding a CHANGELOG line.
117
+ - Do NOT skip the reference frame after the first render — visual
118
+ regression has nothing to compare against.
119
+ - Do NOT lock a character that appears in only one scene.
120
+
121
+ ## Policies
122
+
123
+ When a character lock would identify or render a real person, consult before emitting the JSON:
124
+
125
+ - [`agents/policies/media/likeness.md`](../../../agents/policies/media/likeness.md) — real-person identity tokens require a cited likeness release.
126
+ - [`agents/policies/media/public-figures.md`](../../../agents/policies/media/public-figures.md) — recognised public figures carry the harder gate (publicity rights + transformative-intent).
127
+ - [`agents/policies/media/voice-cloning.md`](../../../agents/policies/media/voice-cloning.md) — when `voice_note` references a real person's voice.
128
+ - [`agents/policies/media/disclosure.md`](../../../agents/policies/media/disclosure.md) — outputs carrying a real-person lock require the non-removable AI-generation disclosure downstream.
129
+
130
+ Refuse-and-surface the file path; do not silently sanitise the prompt.
131
+
@@ -77,6 +77,139 @@ The project uses `.github/pull_request_template.md`:
77
77
  - `main` is default/production branch.
78
78
  - Merge strategy: merge commits (not squash).
79
79
 
80
+ ## Procedure: Safe squash-after-push
81
+
82
+ Use ONLY when the user explicitly authorized a squash on a branch that
83
+ is already on origin. The whole sequence runs in **one turn** — never
84
+ end the session between rewrite and push.
85
+
86
+ Trigger context: `post-push-rewrite-discipline` rule routed here.
87
+
88
+ ### 1. Snapshot before touching anything
89
+
90
+ ```bash
91
+ BRANCH=$(git branch --show-current)
92
+ DATE=$(date +%F)
93
+ git fetch origin
94
+ git tag "safe-squash-pre/${BRANCH}/${DATE}" HEAD
95
+ git tag "safe-squash-origin/${BRANCH}/${DATE}" "@{u}"
96
+ ```
97
+
98
+ Two tags = two recoveries (local tip + origin tip). Do not skip the
99
+ tags — `git reflog` is TTL-bounded and unreliable across sessions.
100
+
101
+ ### 2. Verify aligned starting state
102
+
103
+ ```bash
104
+ git rev-list --left-right --count HEAD...@{u}
105
+ ```
106
+
107
+ - `0 0` → aligned, proceed.
108
+ - `N 0` (local ahead) → unpushed work, proceed.
109
+ - `0 N` (origin ahead) → `git pull --ff-only` first, then re-check.
110
+ - `M N` (both non-zero) → **divergent**. Abandon the squash and run
111
+ § Divergent-State Recovery below.
112
+
113
+ ### 3. Perform the squash
114
+
115
+ Default — soft-reset path (single token-cheap rewrite):
116
+
117
+ ```bash
118
+ git reset --soft "$(git merge-base HEAD <base>)"
119
+ git commit -m "<conventional commit message>"
120
+ ```
121
+
122
+ Interactive rebase only when the user wants per-commit control — it
123
+ replays derived files (`.compression-hashes.json`, router projections)
124
+ per commit and conflicts on every replay.
125
+
126
+ ### 4. Re-push in the SAME turn
127
+
128
+ ```bash
129
+ FETCHED_SHA=$(git rev-parse "@{u}")
130
+ git push --force-with-lease="${BRANCH}:${FETCHED_SHA}" origin "${BRANCH}"
131
+ git fetch origin
132
+ [ "$(git rev-parse HEAD)" = "$(git rev-parse @{u})" ] \
133
+ && echo "OK: origin matches HEAD" \
134
+ || echo "MISMATCH — do not end session"
135
+ ```
136
+
137
+ If the push fails (pre-push hook, network, token budget):
138
+ - Fix the underlying cause **now**.
139
+ - Re-push immediately.
140
+ - Do not commit new work on top of the squashed-but-unpushed tip.
141
+ - Do not end the session until `HEAD == @{u}`.
142
+
143
+ ### 5. Hand off only with verified parity
144
+
145
+ Report exactly:
146
+ - pre-squash tip SHA (from step 1)
147
+ - pre-squash tag name (for recovery)
148
+ - post-squash tip SHA == origin SHA (verified in step 4)
149
+ - PR number, if any, and confirm it picked up the new tip
150
+
151
+ ## Procedure: Divergent-State Recovery
152
+
153
+ Fires when `git rev-list --left-right --count HEAD...@{u}` shows
154
+ **both** sides non-zero on the current branch.
155
+
156
+ ### 1. Stop. Do not pull.
157
+
158
+ A blind `git pull --rebase` here replays remote commits on top of a
159
+ local history that may already represent the same work in a different
160
+ shape — guaranteed conflict storm in derived files, possible
161
+ double-application of the same change. This is the documented failure
162
+ mode behind `post-push-rewrite-discipline`.
163
+
164
+ ### 2. Tag both sides immediately
165
+
166
+ ```bash
167
+ TS=$(date +%FT%H%M)
168
+ git tag "diverged-local/${TS}" HEAD
169
+ git tag "diverged-origin/${TS}" "@{u}"
170
+ ```
171
+
172
+ ### 3. Diagnose: which side is the correct future?
173
+
174
+ ```bash
175
+ git log --oneline @{u}..HEAD # local-only commits
176
+ git log --oneline HEAD..@{u} # origin-only commits
177
+ git diff @{u}..HEAD --stat # shape of local-ahead work
178
+ ```
179
+
180
+ Decision matrix:
181
+
182
+ | Pattern | Future | Action |
183
+ |---|---|---|
184
+ | Local has the same logical work as origin, just reshaped (squash/rebase) | **Local** | After PR-review check (step 4), `git push --force-with-lease=<branch>:<origin-sha>` |
185
+ | Origin has commits local does not reflect (another contributor pushed) | **Origin** | Tag any local-ahead work for cherry-pick, then `git reset --hard @{u}` |
186
+ | Both sides have genuine independent work | **ask user** | Never decide silently — surface the two commit lists and let the user pick |
187
+
188
+ ### 4. PR review-comment check (mandatory before any force-push)
189
+
190
+ If a PR is open on this branch:
191
+ ```bash
192
+ gh pr view --json reviews,comments
193
+ # or via GitHub API: /repos/<owner>/<repo>/pulls/<num>/{reviews,comments}
194
+ ```
195
+
196
+ If review comments are anchored to commits that the force-push will
197
+ erase → STOP, ask the user how to preserve them. A force-push that
198
+ destroys live review feedback is unrecoverable from the agent side.
199
+
200
+ ### 5. Recover or proceed
201
+
202
+ Use the tags from step 2 to restore either side if step 4 surfaces a
203
+ problem. After resolution, verify `HEAD == @{u}` and report both
204
+ SHAs plus the tags created.
205
+
206
+ ## Hard prohibitions on a pushed branch
207
+
208
+ - No `git pull --rebase` after detecting divergent state.
209
+ - No `git push --force` without `--force-with-lease=<branch>:<sha>`.
210
+ - No squash-then-end-session — the push must complete in the same turn.
211
+ - No reflog-only recovery — always tag the state explicitly first.
212
+
80
213
  ## Output format
81
214
 
82
215
  1. Commits following conventional commit format
@@ -0,0 +1,161 @@
1
+ ---
2
+ name: motion-choreographer
3
+ description: "Use when turning a locked still + blueprint into a provider-tuned motion prompt — camera, primary + secondary motion, physics, native-audio sync. Triggers 'motion prompt for Veo/Kling/Sora'."
4
+ personas:
5
+ - ai-video-technical-director
6
+ source: package
7
+ domain: product
8
+ ---
9
+
10
+ # motion-choreographer
11
+
12
+ > Turn an approved still + the 12-block scene blueprint into a
13
+ > provider-tuned **motion prompt** that the target video adapter
14
+ > consumes. Camera choreography, primary subject motion, secondary
15
+ > environment motion, physics constraints, and — when the adapter
16
+ > declares `audio: native` — a synchronized audio direction block.
17
+ > Reads adapter capabilities from
18
+ > [`adapter-contract.md`](../../../scripts/ai-video/lib/adapter-contract.md);
19
+ > never speaks to a network API.
20
+
21
+ ## When to use
22
+
23
+ - An image is locked (operator picked one candidate via
24
+ `operator-pick.sh`) and the next step is motion + audio direction
25
+ for the video adapter.
26
+ - The blueprint exists in `scenes/<id>/blueprint.json` but the
27
+ motion prompt has not been emitted yet.
28
+ - A provider switch (Veo → Kling, Sora → Higgsfield) requires the
29
+ same scene retuned for the new adapter's capability profile.
30
+
31
+ Do NOT use when:
32
+
33
+ - The blueprint is still prose only — run
34
+ [`scene-expander`](../scene-expander/SKILL.md) → `parse-blueprint.sh`
35
+ first.
36
+ - No still has been locked — the operator-selection checkpoint
37
+ must complete first.
38
+ - The output is a still graphic — `canvas-design`.
39
+
40
+ ## Procedure
41
+
42
+ ### Step 0: Inspect
43
+
44
+ 1. Read `scenes/<id>/blueprint.json` — fail loud if missing.
45
+ 2. Read `scenes/<id>/selection.json` — fail loud if missing; the
46
+ locked image path is required as the motion anchor.
47
+ 3. Read the target adapter's capability via
48
+ `scripts/ai-video/adapters/<id>.sh capability`. Cache `audio=*`
49
+ for Step 3.
50
+ 4. If a `character.json` lock exists, load it verbatim — identity
51
+ tokens are immutable.
52
+
53
+ ### Step 1: Camera choreography
54
+
55
+ Emit a `CAMERA MOTION` block with the move type, distance, speed
56
+ in seconds, and start-end framing.
57
+
58
+ - Move types: lock-off, pan, tilt, dolly-in, dolly-out, truck,
59
+ pedestal, push, pull, handheld, gimbal-glide, crane, whip.
60
+ - Speed in seconds per beat (`0.4s push, hold 1.6s, 0.4s pull`).
61
+ - Start and end framing named (`MS → CU`, `WS → MS`).
62
+
63
+ Adapter quirks:
64
+
65
+ - **Veo** — accepts named moves; prefers ≤ 8s clips.
66
+ - **Kling** — motion intensity 0–1 token; map our speed to that.
67
+ - **Sora** — natural-language move + duration; no token.
68
+ - **Higgsfield** — preset-driven; pick the preset that matches the
69
+ move; record the preset id in the motion prompt.
70
+
71
+ ### Step 2: Primary + secondary motion
72
+
73
+ Two blocks:
74
+
75
+ 1. **PRIMARY MOTION** — what the subject does, beat-counted, with
76
+ physics anchors (mass, contact points, momentum). Reuse `ACTION`
77
+ from the blueprint; refine for the adapter's preferred verb
78
+ density.
79
+ 2. **SECONDARY MOTION** — what the world does (hair, fabric,
80
+ foliage, water, dust, particles, breath). One layer per line.
81
+
82
+ ### Step 3: Audio direction (conditional)
83
+
84
+ If adapter capability is `audio: native` AND the blueprint's
85
+ `audio.enable_native_audio` is `true`:
86
+
87
+ Emit an `AUDIO DIRECTION` block with:
88
+
89
+ - `DIALOGUE TIMING` — `speaker @ 0.4s: "line"` per dialogue entry.
90
+ - `AMBIENT LAYERS` — copy from blueprint; one layer per line.
91
+ - `SYNC CUES` — which action beat maps to which audio cue
92
+ (`footstep @ 1.2s`, `door close @ 2.1s`).
93
+
94
+ If adapter capability is `audio: none`:
95
+
96
+ - Emit a `# AUDIO: ffmpeg-mux fallback` comment with the
97
+ blueprint's audio paths queued for stitch-time mux.
98
+ - Set `enable_native_audio: false` in the motion-prompt JSON.
99
+
100
+ ### Step 4: Physics constraints
101
+
102
+ Emit `PHYSICS` — a short list of what the model must respect:
103
+ gravity direction, contact friction, fluid behavior, hair / cloth
104
+ inertia, lens parallax. Single line per constraint.
105
+
106
+ ### Step 5: Emit motion-prompt JSON
107
+
108
+ Write `scenes/<id>/motion-prompt.json` with the adapter-contract
109
+ stdin shape. The orchestrator pipes this into the video adapter's
110
+ `submit` subcommand.
111
+
112
+ ### Step 6: Validate
113
+
114
+ 1. JSON parses (`jq .`).
115
+ 2. `requires.audio_native` is consistent with the chosen adapter's
116
+ capability.
117
+ 3. Duration in the motion prompt matches blueprint duration ±0.
118
+ 4. Identity tokens (if `character.json` exists) are verbatim.
119
+
120
+ ## Output format
121
+
122
+ 1. **`scenes/<id>/motion-prompt.json`** — adapter-contract stdin.
123
+ 2. **`scenes/<id>/motion-prompt.txt`** — labeled prose blocks
124
+ (CAMERA MOTION · PRIMARY MOTION · SECONDARY MOTION · AUDIO
125
+ DIRECTION · PHYSICS) for operator review.
126
+ 3. **`scenes/<id>/adapter-notes.md`** — which adapter, which
127
+ capability, which preset / model, with rationale.
128
+
129
+ ## Gotcha
130
+
131
+ - The model wants to "improve" the blueprint's `SUBJECT` block —
132
+ identity tokens are immutable; refuse the temptation.
133
+ - Picking `audio: native` on an adapter that returns `audio: none`
134
+ produces silent video — always read capability first, never
135
+ guess from the adapter name.
136
+ - Higgsfield preset id must be recorded; otherwise the rerun
137
+ drifts to whichever preset the model picks on the next call.
138
+ - Sora durations > 8s often degrade — clamp at the adapter table
139
+ limit; surface the clamp to the operator.
140
+
141
+ ## Do NOT
142
+
143
+ - Do NOT emit motion prompts for an adapter whose capability you
144
+ did not query this turn.
145
+ - Do NOT skip the still-locked check — motion direction without an
146
+ anchored image diverges on every call.
147
+ - Do NOT paraphrase identity tokens from `character.json`.
148
+ - Do NOT call any network API — this skill is provider-tuning
149
+ prose only.
150
+
151
+ ## Policies
152
+
153
+ Motion prompts inherit upstream blueprint constraints. Before emitting provider-tuned prose:
154
+
155
+ - [`agents/policies/media/disclosure.md`](../../../agents/policies/media/disclosure.md) — every distributed clip → non-removable AI-generation disclosure; refuse adapter flags that suppress it.
156
+ - [`agents/policies/media/transparency.md`](../../../agents/policies/media/transparency.md) — provider provenance (C2PA / SynthID) preserved; refuse re-encode flags that strip provenance.
157
+ - [`agents/policies/media/voice-cloning.md`](../../../agents/policies/media/voice-cloning.md) — motion prompt requests `audio: native` in named voice.
158
+ - [`agents/policies/media/brand-impersonation.md`](../../../agents/policies/media/brand-impersonation.md) — copies recognised brand's chyron / mascot / signature transition.
159
+
160
+ Refuse-and-surface; motion prompt cannot launder upstream policy gap.
161
+