Skip to content

feat(skills): recoup-content-clip-video — clip long-form video into shorts via the OpusClip API#76

Open
sweetmantech wants to merge 1 commit into
mainfrom
feat/recoup-content-clip-video
Open

feat(skills): recoup-content-clip-video — clip long-form video into shorts via the OpusClip API#76
sweetmantech wants to merge 1 commit into
mainfrom
feat/recoup-content-clip-video

Conversation

@sweetmantech

@sweetmantech sweetmantech commented Jul 5, 2026

Copy link
Copy Markdown
Contributor

What

Adds recoup-content-clip-video — a minimal first-pass skill for turning long-form video (podcast, interview, livestream, live set) into social-ready short clips via the OpusClip API.

Kept intentionally basic so we can layer on today's workflow (curation preferences, brand templates, social posting, webhooks) in follow-ups:

  • SKILL.md with auth (OPUS_PRO_API_KEY env var), base URL, and the core submit → wait → fetch flow
  • Links to the OpusClip docs, including the LLM-readable endpoint index (https://help.opus.pro/llms.txt — every doc page has a .md variant)
  • Resolver route + eval fixture, README row

Also: unblocks CI on main

check_resolvable.py / run_resolver_eval.py were failing on main: recoup-internal-video-grok-1.5-imagine-facetime (#74) has a dot in its slug, and the resolver slug regex (recoup-[a-z0-9-]+) can't parse dotted names — so the skill could never have a parseable route. Fixed by broadening the regex to [a-z0-9.-] and adding the missing route + fixture. (Alternative was renaming that skill; left that call to a follow-up if we'd rather enforce dot-free slugs.)

Validation

All five gates pass locally: portability_lint, check_vendored, validate_manifests, check_resolvable (36/36 reachable), run_resolver_eval (48 positives + 15 negatives, full coverage).

🤖 Generated with Claude Code


Summary by cubic

Adds recoup-content-clip-video to turn long-form video into social-ready clips via the OpusClip API. Also broadens resolver slug parsing to allow dots, making recoup-internal-video-grok-1.5-imagine-facetime resolvable and unblocking CI.

  • New Features

    • New skill: recoup-content-clip-video for clipping podcasts/streams/interviews into shorts.
    • SKILL.md with OPUS_PRO_API_KEY auth, base URL, and submit → wait/poll → fetch flow; linked OpusClip docs.
    • Added resolver route, README entry, and resolver eval fixture.
  • Bug Fixes

    • Updated resolver slug regex to [a-z0-9.-] in validation/eval scripts.
    • Added route and eval fixture for recoup-internal-video-grok-1.5-imagine-facetime, restoring CI checks.

Written for commit 57ebe8b. Summary will update on new commits.

Review in cubic

Summary by CodeRabbit

  • New Features

    • Added support for turning long-form videos into short clips for social sharing.
    • Added a new internal video-call ad routing option for eligible requests.
  • Documentation

    • Expanded skill documentation with setup, workflow, and usage guidance for the new video-clipping capability.
  • Bug Fixes

    • Improved recognition of skill identifiers so entries with dots are handled correctly during validation and evaluation.

…horts via the OpusClip API

Minimal first pass: SKILL.md with auth, base URL, the submit→wait→fetch
flow, and links to the OpusClip API docs (quickstart + llms.txt index).
Route + fixture added per resolver rules.

Also unblocks CI on main: recoup-internal-video-grok-1.5-imagine-facetime
(#74) was unreachable because the resolver slug regex disallowed dots —
broadened to [a-z0-9.-] in check_resolvable.py / run_resolver_eval.py and
added its missing route + fixture.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@cursor

cursor Bot commented Jul 5, 2026

Copy link
Copy Markdown

Bugbot is not enabled for your account, so this pull request was not reviewed.

Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs.

@coderabbitai

coderabbitai Bot commented Jul 5, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

This PR adds a new recoup-content-clip-video skill with documentation for OpusClip-based video clipping, registers it and a new internal Grok Imagine intent in README and RESOLVER.md routing tables, adds corresponding resolver-eval fixtures, and updates skill-slug regexes in two scripts to allow dots.

Changes

Clip-Video Skill and Resolver Routing

Layer / File(s) Summary
New skill documentation
skills/recoup-content-clip-video/SKILL.md
Adds front-matter and full operational docs for clipping long-form video into shorts via the OpusClip API, including auth setup, execution steps, and API references.
Routing registration and eval fixtures
README.md, RESOLVER.md, resolver-eval.jsonl
Registers recoup-content-clip-video in README and RESOLVER Tier 1 tables, adds a gated internal intent for recoup-internal-video-grok-1.5-imagine-facetime in Tier 3, and adds two resolver-eval fixture lines validating both routings against negative constraints.
Skill-slug regex updates
scripts/check_resolvable.py, scripts/run_resolver_eval.py
Broadens SKILL_TOKEN and SKILL_TOKEN_PLAIN regex patterns to allow dots in recoup-* slugs, affecting which routed skills are recognized during audits and evaluations.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • recoupable/skills#74: Adds resolver routing/fixtures referencing the same recoup-internal-video-grok-1.5-imagine-facetime skill introduced here.

Poem

A rabbit clips a long, long reel,
Into shorts with OpusClip's zeal,
New routes now bend,
For FaceTime and friend,
While dots in slugs now have appeal. 🐇✂️

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly and concisely summarizes the main change: adding the recoup-content-clip-video skill for clipping long-form video with OpusClip.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/recoup-content-clip-video

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@scripts/run_resolver_eval.py`:
- Line 85: The SKILL_TOKEN_PLAIN regex currently overmatches by allowing any dot
anywhere, which causes trailing sentence punctuation to be treated as part of
the token in run_resolver_eval.py. Update the pattern in SKILL_TOKEN_PLAIN to be
version-aware so it still accepts valid dotted version segments but stops before
terminal punctuation, and make sure the token parsing logic that relies on this
regex returns the correct skill name instead of falling back to none.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 35d8dc3d-5b06-45d6-9342-471e7b1b9aa3

📥 Commits

Reviewing files that changed from the base of the PR and between 70404b8 and 57ebe8b.

📒 Files selected for processing (6)
  • README.md
  • RESOLVER.md
  • resolver-eval.jsonl
  • scripts/check_resolvable.py
  • scripts/run_resolver_eval.py
  • skills/recoup-content-clip-video/SKILL.md

MIN_PASS = float(os.environ.get("RECOUP_RESOLVER_EVAL_MIN_PASS", "1.0"))
FRONTMATTER_KEY = re.compile(r"^([A-Za-z][\w-]*):\s?(.*)$")
SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9-]+")
SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9.-]+")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Keep dot support, but stop matching sentence punctuation.

recoup-[a-z0-9.-]+ will also absorb a trailing . in model replies, so a correct answer like recoup-internal-video-grok-1.5-imagine-facetime. falls through to none. Make the pattern version-aware instead of letting . match anywhere.

♻️ Proposed fix
-SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9.-]+")
+SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9-]+(?:\.[a-z0-9-]+)*")
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9.-]+")
SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9-]+(?:\.[a-z0-9-]+)*")
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/run_resolver_eval.py` at line 85, The SKILL_TOKEN_PLAIN regex
currently overmatches by allowing any dot anywhere, which causes trailing
sentence punctuation to be treated as part of the token in run_resolver_eval.py.
Update the pattern in SKILL_TOKEN_PLAIN to be version-aware so it still accepts
valid dotted version segments but stops before terminal punctuation, and make
sure the token parsing logic that relies on this regex returns the correct skill
name instead of falling back to none.

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

2 issues found across 6 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="skills/recoup-content-clip-video/SKILL.md">

<violation number="1" location="skills/recoup-content-clip-video/SKILL.md:13">
P2: For multi-org users, the GET `/exportable-clips` endpoint requires a `x-opus-org-id` header. The current Setup only documents `Authorization: Bearer $OPUS_PRO_API_KEY`, so users with multiple organizations will get a 400 error on step 3 (Fetch clips) with no guidance on how to resolve it. Consider adding a note that this header may be needed, referencing the Org ID from the OpusClip dashboard.</violation>
</file>

<file name="scripts/run_resolver_eval.py">

<violation number="1" location="scripts/run_resolver_eval.py:85">
P2: The broadened character class `[a-z0-9.-]+` will greedily absorb a trailing `.` when the skill slug appears at the end of a sentence in a model reply (e.g., `"…use recoup-internal-video-grok-1.5-imagine-facetime."`). The resulting match won't exist in `skill_dirs()`, turning a correct answer into a false negative. A version-segment-aware pattern avoids this while still supporting dotted slugs like `grok-1.5`.</violation>
</file>

Reply with feedback, questions, or to request a fix.

Re-trigger cubic


## Setup

- Auth: `Authorization: Bearer $OPUS_PRO_API_KEY` (never hardcode the key; get

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: For multi-org users, the GET /exportable-clips endpoint requires a x-opus-org-id header. The current Setup only documents Authorization: Bearer $OPUS_PRO_API_KEY, so users with multiple organizations will get a 400 error on step 3 (Fetch clips) with no guidance on how to resolve it. Consider adding a note that this header may be needed, referencing the Org ID from the OpusClip dashboard.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At skills/recoup-content-clip-video/SKILL.md, line 13:

<comment>For multi-org users, the GET `/exportable-clips` endpoint requires a `x-opus-org-id` header. The current Setup only documents `Authorization: Bearer $OPUS_PRO_API_KEY`, so users with multiple organizations will get a 400 error on step 3 (Fetch clips) with no guidance on how to resolve it. Consider adding a note that this header may be needed, referencing the Org ID from the OpusClip dashboard.</comment>

<file context>
@@ -0,0 +1,32 @@
+
+## Setup
+
+- Auth: `Authorization: Bearer $OPUS_PRO_API_KEY` (never hardcode the key; get
+  one at https://clip.opus.pro/dashboard).
+- Base URL: `https://api.opus.pro/api`
</file context>

MIN_PASS = float(os.environ.get("RECOUP_RESOLVER_EVAL_MIN_PASS", "1.0"))
FRONTMATTER_KEY = re.compile(r"^([A-Za-z][\w-]*):\s?(.*)$")
SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9-]+")
SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9.-]+")

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The broadened character class [a-z0-9.-]+ will greedily absorb a trailing . when the skill slug appears at the end of a sentence in a model reply (e.g., "…use recoup-internal-video-grok-1.5-imagine-facetime."). The resulting match won't exist in skill_dirs(), turning a correct answer into a false negative. A version-segment-aware pattern avoids this while still supporting dotted slugs like grok-1.5.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At scripts/run_resolver_eval.py, line 85:

<comment>The broadened character class `[a-z0-9.-]+` will greedily absorb a trailing `.` when the skill slug appears at the end of a sentence in a model reply (e.g., `"…use recoup-internal-video-grok-1.5-imagine-facetime."`). The resulting match won't exist in `skill_dirs()`, turning a correct answer into a false negative. A version-segment-aware pattern avoids this while still supporting dotted slugs like `grok-1.5`.</comment>

<file context>
@@ -82,7 +82,7 @@ def load_fixtures() -> list[dict]:
 MIN_PASS = float(os.environ.get("RECOUP_RESOLVER_EVAL_MIN_PASS", "1.0"))
 FRONTMATTER_KEY = re.compile(r"^([A-Za-z][\w-]*):\s?(.*)$")
-SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9-]+")
+SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9.-]+")
 
 
</file context>
Suggested change
SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9.-]+")
SKILL_TOKEN_PLAIN = re.compile(r"recoup-[a-z0-9-]+(?:\.[a-z0-9-]+)*")

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant