Skip to content

fix(timeline): prefer exact segment clip matches - #241

Closed
arhxam wants to merge 2 commits into
getopenscreen:mainfrom
arhxam:codex/exact-segment-clip-resolution
Closed

fix(timeline): prefer exact segment clip matches#241
arhxam wants to merge 2 commits into
getopenscreen:mainfrom
arhxam:codex/exact-segment-clip-resolution

Conversation

@arhxam

@arhxam arhxam commented Aug 4, 2026

Copy link
Copy Markdown

Summary

  • resolve an exact raw clip ID before considering generated segment-prefix matches
  • use the longest matching raw ID for generated segments so nested _seg-like IDs remain unambiguous
  • add regression coverage for both exact and generated collision cases

Related issue

No linked issue; found while auditing segment-to-source identity handling.

Type of change

  • Bug fix
  • Feature
  • Enhancement
  • Documentation
  • Refactor / maintenance
  • Performance
  • Security

Release impact

  • Patch
  • Minor
  • Major / breaking change
  • No release note needed

Desktop impact

  • Windows
  • macOS
  • Linux
  • Installer / packaging
  • Not platform-specific

Screenshots / video

Not applicable; this fixes internal timeline identity resolution.

Testing

  • npm exec -- vitest run src/lib/ai-edition/timeline/virtual-preview.test.ts
  • npm exec -- biome check src/lib/ai-edition/timeline/virtual-preview.ts src/lib/ai-edition/timeline/virtual-preview.test.ts
  • npm run build-vite
  • npm run wb:typecheck

Summary by CodeRabbit

  • Bug Fixes
    • Improved timeline segment matching to select exact clip matches before partial matches.
    • Ensured split segments resolve to the most specific source clip.
    • Corrected virtual timeline start offsets for exact clip matches.

@arhxam
arhxam requested a review from EtienneLescot as a code owner August 4, 2026 00:15
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@arhxam, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 37 minutes

You've used all free OSS reviews for now. Wait for the free limit to reset to keep reviewing this public repository.

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 46bd9605-5b5f-4c3f-bef0-0c77c5d28910

📥 Commits

Reviewing files that changed from the base of the PR and between e1978c6 and feab5e9.

📒 Files selected for processing (1)
  • src/lib/ai-edition/timeline/virtual-preview.ts
📝 Walkthrough

Walkthrough

The raw clip lookup now prioritizes exact segment IDs, then matches derived segment IDs to the longest raw clip ID. Tests cover both cases and verify the resulting virtual start time.

Changes

Raw clip resolution

Layer / File(s) Summary
Lookup precedence and validation
src/lib/ai-edition/timeline/virtual-preview.ts, src/lib/ai-edition/timeline/virtual-preview.test.ts
findRawClipForSegment checks exact IDs first and uses the longest matching raw clip ID for _seg prefixes. Tests verify lookup precedence, base clip fallback, and virtual start time calculation.

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

Possibly related PRs

Suggested reviewers: etiennelescot

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and concisely describes the main change: preferring exact segment clip matches.
Description check ✅ Passed The description covers all template sections and includes the change summary, classifications, impact, and testing commands.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
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 unit tests (beta)
  • Create PR with unit tests

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.

🧹 Nitpick comments (1)
src/lib/ai-edition/timeline/virtual-preview.ts (1)

62-64: 🚀 Performance & Scalability | 🔵 Trivial | ⚡ Quick win

Avoid sorting rawClips on every lookup.

locateKeptSegment calls this helper once per playback segment. For each segment without an exact match, this code copies and sorts the full rawClips array. Scan once while retaining the longest matching ID, or build a sorted index once outside this helper.

Proposed O(n) lookup
 		rawClips.find((clip) => clip.id === segment.id) ??
-		[...rawClips]
-			.sort((a, b) => b.id.length - a.id.length)
-			.find((clip) => segment.id.startsWith(`${clip.id}_seg`)) ??
+		rawClips.reduce<AxcutClip | undefined>((longest, clip) => {
+			if (!segment.id.startsWith(`${clip.id}_seg`)) return longest;
+			return !longest || clip.id.length > longest.id.length ? clip : longest;
+		}, undefined) ??
🤖 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 `@src/lib/ai-edition/timeline/virtual-preview.ts` around lines 62 - 64, Update
locateKeptSegment to avoid copying and sorting rawClips for every segment
lookup. Replace the per-call [...rawClips].sort(...).find(...) logic with a
single scan that retains the longest clip ID matching
segment.id.startsWith(`${clip.id}_seg`), preserving the current match preference
without repeated sorting.
🤖 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.

Nitpick comments:
In `@src/lib/ai-edition/timeline/virtual-preview.ts`:
- Around line 62-64: Update locateKeptSegment to avoid copying and sorting
rawClips for every segment lookup. Replace the per-call
[...rawClips].sort(...).find(...) logic with a single scan that retains the
longest clip ID matching segment.id.startsWith(`${clip.id}_seg`), preserving the
current match preference without repeated sorting.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 76759673-7009-4438-bed8-252ff8746554

📥 Commits

Reviewing files that changed from the base of the PR and between 545043d and e1978c6.

📒 Files selected for processing (2)
  • src/lib/ai-edition/timeline/virtual-preview.test.ts
  • src/lib/ai-edition/timeline/virtual-preview.ts

@arhxam

arhxam commented Aug 4, 2026

Copy link
Copy Markdown
Author

Addressed the CodeRabbit performance nit in commit feab5e9: longest generated-segment parent selection is now a single O(n) scan with no copied/sorted array, while preserving exact-ID priority and longest-prefix behavior. Verified with 27/27 focused tests, both TypeScript configs, Biome, and diff checks.

@EtienneLescot

Copy link
Copy Markdown
Collaborator

Closing this one too, for a narrower reason than #240 — the code here is actually fine.

The precedence flaw is real at the function level. I reproduced it: given a clip clip and a clip clip_seg1, main's findRawClipForSegment returns clip for the segment id clip_seg1, because the prefix match wins before the exact one is considered. Preferring the exact id, then the longest prefix, is the right rule.

It just cannot happen. I enumerated every site that mints a clip id — five non-test sites — and they all produce clip_<n> or clip_<uuid>. The _segN ids come from resolvePlaybackSegments, which derives them for playback and never writes them back into document.timeline.clips. So no user action, no agent tool, and no document on disk can produce a timeline containing both X and X_segN. There is no user-visible symptom to fix.

That alone would not make me close it — defensive hardening of an internal helper is a reasonable thing to want. What tips it is the framing. The PR is titled fix:, ticks "Bug fix" and "Patch", and AGENTS.md says PR titles feed GitHub's auto-generated release notes. So this would ship a user-facing bug-fix line for a defect no user could hit. CodeRabbit's summary already reads "Corrected virtual timeline start time resolution", which is exactly the sentence I do not want in a changelog.

If you want to reopen it as test: or refactor: with the release-impact boxes unticked, and the test renamed to say it guards the id-convention invariant rather than a bug, I will take it. One thing that would make it genuinely more valuable: the near-miss the app can mint is clip_1 vs clip_10"clip_10_seg1".startsWith("clip_1_seg") is false only because index 6 is 0 and not _. That is the invariant a future change to the id scheme would actually break, and nothing currently covers it.

Six of the ten landed: #235, #236, #237, #238, #239, #242. Thanks for the batch — the hit rate on the ones that described a reachable bug was high.

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.

2 participants