Skip to content

feat(SOLSYS-71): Sol → TRAPPIST-1 cinematic - #72

Merged
ThomasAFink merged 20 commits into
mainfrom
feat/SOLSYS-71-sol-trappist-cinematic
Aug 9, 2026
Merged

feat(SOLSYS-71): Sol → TRAPPIST-1 cinematic#72
ThomasAFink merged 20 commits into
mainfrom
feat/SOLSYS-71-sol-trappist-cinematic

Conversation

@ThomasAFink

@ThomasAFink ThomasAFink commented Aug 9, 2026

Copy link
Copy Markdown
Owner

Summary

  • New --system sol_trappist destination chapter: Sol open → neighborhood cruise → TRAPPIST-1 at true Sol XYZ (~40.7 ly) → b–h finale
  • --blender-bodies composites Sol packs + TRAPPIST-1 b–h spin billboards (host stays a scatter marker)
  • Tests, README gallery row, roadmap update

Test plan

  • python -m unittest tests.test_sol_trappist_cinematic
  • Visual check light/dark blender GIFs under output/animate/sol_trappist/blender/
  • Confirm finale shows seven labeled worlds with textured disks when packs present

Closes #71

Summary by CodeRabbit

  • New Features

    • Added a Sol-to-TRAPPIST-1 cinematic with seven planets, travel sequences, orbital motion, captions, labels, and staged camera views.
    • Added CLI support for standard and optional Blender-rendered planet bodies.
    • Added light and dark output variants with dedicated render locations.
    • Added TRAPPIST-1 planet previews to the finale.
  • Documentation

    • Updated cinematic usage guidance, Blender output details, galleries, and roadmap information.
  • Tests

    • Added coverage for camera framing, planetary positions, star-field coverage, travel phases, and Blender rendering.

Destination chapter from Sol through the neighborhood to TRAPPIST-1 at true
Sol XYZ, finishing on the b–h resonant chain using the #69 spin packs.
@coderabbitai

coderabbitai Bot commented Aug 9, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

Added a Sol→TRAPPIST-1 cinematic animator with staged travel, seven-planet rendering, optional Blender billboards, CLI support, tests, and updated documentation.

Changes

Sol→TRAPPIST-1 cinematic

Layer / File(s) Summary
Shared cinematic animator
animate/scenes/sol_centauri_cinematic.py
Extracts reusable destination, camera-scale, billboard-scale, and label machinery while keeping Alpha Centauri setup in its subclass.
TRAPPIST-1 scene and rendering
animate/scenes/sol_trappist_cinematic.py
Adds staged Sol travel, TRAPPIST-1 arrival, seven-planet orbital rendering, Blender body support, captions, camera transitions, and light/dark GIF outputs.
CLI integration and outputs
render.py, README.md, animate/scenes/blender/README.md
Adds sol_trappist to animate and all, passes --blender-bodies, and documents output directories, gallery media, CLI behavior, and roadmap updates.
Cinematic validation
tests/test_sol_trappist_cinematic.py
Tests catalog coordinates, camera framing, orbital placement, field-star coverage, Blender scales, and arrival sequencing.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RenderCLI
  participant SolTrappistCinematicAnimator
  participant StarCatalog
  participant BlenderBodyRegistry
  RenderCLI->>SolTrappistCinematicAnimator: select sol_trappist
  SolTrappistCinematicAnimator->>StarCatalog: load TRAPPIST-1 data
  SolTrappistCinematicAnimator->>StarCatalog: calculate travel and orbital positions
  SolTrappistCinematicAnimator->>BlenderBodyRegistry: queue optional planet billboards
  SolTrappistCinematicAnimator-->>RenderCLI: write light and dark GIF outputs
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (2 warnings)

Check name Status Explanation Resolution
Out of Scope Changes check ⚠️ Warning The pull request adds and applies the reusable SolScaleCinematicAnimator, which is a generic multi-destination refactor excluded by issue #71. Limit the change to the Sol→TRAPPIST-1 scene, or justify and separately scope the shared animator refactor.
Docstring Coverage ⚠️ Warning Docstring coverage is 7.14% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly identifies the new Sol→TRAPPIST-1 cinematic, which is the primary change in the pull request.
Linked Issues check ✅ Passed The changes add the scene, CLI support, Blender billboard finale, extended travel view, tests, outputs, and README updates required by issue #71.
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/SOLSYS-71-sol-trappist-cinematic

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.

Comment thread animate/scenes/sol_trappist_cinematic.py Fixed

@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: 3

🧹 Nitpick comments (1)
animate/scenes/sol_trappist_cinematic.py (1)

88-216: 📐 Maintainability & Code Quality | 🔵 Trivial | 🏗️ Heavy lift

Parameterize SolCentauriCinematicAnimator instead of copying it into the subclass. Both sites copy base-class code verbatim and change only a few destination-specific values, so future edits to the base class will not reach SolTrappistCinematicAnimator.

  • animate/scenes/sol_trappist_cinematic.py#L88-L216: replace the copied initializer with super().__init__(...) plus overridable hooks for destination geometry and framing constants; this also clears the CodeQL missing-super finding at Line 85.
  • animate/scenes/sol_trappist_cinematic.py#L240-L271: delete this override and add class attributes for the field-star radius and the excluded system_id to the base _loadFieldStars.
🤖 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 `@animate/scenes/sol_trappist_cinematic.py` around lines 88 - 216, Refactor
SolTrappistCinematicAnimator.__init__
(animate/scenes/sol_trappist_cinematic.py#L88-L216) to call
SolCentauriCinematicAnimator’s initializer via super().__init__(...), moving
destination-specific geometry and framing values into overridable hooks or class
attributes while preserving TRAPPIST-1 validation and setup; this also resolves
the missing-super finding. Remove the _loadFieldStars override at
animate/scenes/sol_trappist_cinematic.py#L240-L271, and add class attributes
consumed by the base implementation for the field-star radius and excluded
system_id.

Source: Linters/SAST tools

🤖 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 `@tests/test_sol_trappist_cinematic.py`:
- Around line 140-143: Update the inner-arrival assertion in the test around
animator._cameraState to evaluate a frame at or after
ARRIVAL_TRAPPIST_INNER_ARRIVE, then assert that innerHalf reaches
TRAPPIST_INNER_HALF_AU rather than only satisfying the wide-framing upper bound.
Preserve the existing focus assertion and Blender timing coverage.
- Around line 101-107: Strengthen test_planets_orbit_host by validating each
planet’s radial distance against its semiMajorAxisAu and eccentricity rather
than only the broad host offset bound. Evaluate _trappistPlanetPositionSol at
two distinct frames and assert the positions differ appropriately, while
retaining the existing planet-count and planar-orbit checks.
- Around line 109-113: Update test_field_stars_reach_trappist_distance to
require a non-empty animator.fieldStars selection, then assert at least one
selected star has a distance in the intended 30–45 ly extended range. Keep the
trappist_1 exclusion assertion unconditional rather than guarding it with an
emptiness check, and retain the existing configuration-bound assertions.

---

Nitpick comments:
In `@animate/scenes/sol_trappist_cinematic.py`:
- Around line 88-216: Refactor SolTrappistCinematicAnimator.__init__
(animate/scenes/sol_trappist_cinematic.py#L88-L216) to call
SolCentauriCinematicAnimator’s initializer via super().__init__(...), moving
destination-specific geometry and framing values into overridable hooks or class
attributes while preserving TRAPPIST-1 validation and setup; this also resolves
the missing-super finding. Remove the _loadFieldStars override at
animate/scenes/sol_trappist_cinematic.py#L240-L271, and add class attributes
consumed by the base implementation for the field-star radius and excluded
system_id.
🪄 Autofix

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 Plus

Run ID: f0c8d2ad-7011-4e4b-9ce8-a229954a8cdb

📥 Commits

Reviewing files that changed from the base of the PR and between a0eadb3 and 5c870a6.

📒 Files selected for processing (6)
  • README.md
  • animate/scenes/blender/README.md
  • animate/scenes/sol_centauri_cinematic.py
  • animate/scenes/sol_trappist_cinematic.py
  • render.py
  • tests/test_sol_trappist_cinematic.py

Comment thread tests/test_sol_trappist_cinematic.py Outdated
Comment thread tests/test_sol_trappist_cinematic.py Outdated
Comment thread tests/test_sol_trappist_cinematic.py Outdated
Gallery light/dark destination-chapter renders with Sol + TRAPPIST b–h billboards.
Skip unsafe super().__init__ (parent requires α Cen) with an explicit CodeQL
annotation, and tighten orbit / field-star / inner-frame camera tests.
Extract SolScaleCinematicAnimator for Sol-open / billboard machinery; α Cen and
TRAPPIST both inherit it and call super, clearing CodeQL missing-init.
Dive waypoints were Proxima leftovers that zoomed out to ~8000 AU after the
2 AU arrive hold, and the draw path hid the star above 80 AU — a black gap.

@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 `@tests/test_sol_trappist_cinematic.py`:
- Around line 160-165: Update the dive-width assertions in the sampling loop
around animator._cameraState so they enforce strict non-increasing behavior
using a small absolute floating-point tolerance rather than multiplying holdHalf
and previous by 1.01. Preserve the existing comparisons and previous = halfWidth
tracking while allowing only negligible numerical error.
🪄 Autofix

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 Plus

Run ID: f4c4405b-7e97-479f-85c6-b4cfbd229088

📥 Commits

Reviewing files that changed from the base of the PR and between 5c870a6 and 240dc48.

⛔ Files ignored due to path filters (2)
  • output/animate/sol_trappist/blender/sol_trappist_cinematic_blender_dark.gif is excluded by !**/*.gif
  • output/animate/sol_trappist/blender/sol_trappist_cinematic_blender_light.gif is excluded by !**/*.gif
📒 Files selected for processing (3)
  • animate/scenes/sol_centauri_cinematic.py
  • animate/scenes/sol_trappist_cinematic.py
  • tests/test_sol_trappist_cinematic.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • animate/scenes/sol_trappist_cinematic.py

Comment thread tests/test_sol_trappist_cinematic.py
Re-render after the dive black-gap fix so gallery assets match the tighten-only camera.
Use absolute float epsilon instead of 1% slack so the camera cannot quietly zoom out.
After the wide chain hold, draw a schematic HZ band, zoom to temperate
candidates e/f, then ease out to the full b–h finale.
Filled annulus, dashed rims, screen-space label, and a steeper HZ camera so
the band does not collapse into a foreshortened line.
Filled HZ annulus and screen-space label in the Sol→TRAPPIST blender gallery assets.
After the HZ band overview, shift the look-at point off the host onto the
temperate candidates so the close-up reads as a planet beat, not a star frame.

@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 `@animate/scenes/sol_trappist_cinematic.py`:
- Around line 201-211: Update __init__ to validate that the catalog contains
TRAPPIST-1 b through TRAPPIST-1 h before rendering; collect all missing names
and raise ValueError listing them. Preserve _planetByName and _candidateFocusSol
behavior, and add a test covering a partial planet catalog.
🪄 Autofix

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 Plus

Run ID: 3d6ddef5-0b51-45dd-92bf-211cffd1c133

📥 Commits

Reviewing files that changed from the base of the PR and between 240dc48 and 3702463.

⛔ Files ignored due to path filters (2)
  • output/animate/sol_trappist/blender/sol_trappist_cinematic_blender_dark.gif is excluded by !**/*.gif
  • output/animate/sol_trappist/blender/sol_trappist_cinematic_blender_light.gif is excluded by !**/*.gif
📒 Files selected for processing (3)
  • README.md
  • animate/scenes/sol_trappist_cinematic.py
  • tests/test_sol_trappist_cinematic.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • tests/test_sol_trappist_cinematic.py
  • README.md

Comment on lines +201 to +211
def _planetByName(self, name: str) -> SystemPlanet:
for planet in self.trappistPlanets:
if planet.name == name:
return planet
raise KeyError(name)

def _candidateFocusSol(self, frame: int) -> np.ndarray:
"""Look-at point between e and f so both HZ candidates stay in frame."""
planetE = self._trappistPlanetPositionSol(self._planetByName('TRAPPIST-1 e'), frame)
planetF = self._trappistPlanetPositionSol(self._planetByName('TRAPPIST-1 f'), frame)
return 0.62 * planetE + 0.38 * planetF

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

Validate the required planet rows before rendering.

_cameraState() calls _candidateFocusSol() for every frame. A StarSystem that passes the current constructor checks but lacks TRAPPIST-1 e or TRAPPIST-1 f fails later with KeyError, including during the Sol opening.

Validate the required TRAPPIST-1 b through TRAPPIST-1 h names in __init__. Raise ValueError with the missing names. Add a test for a partial planet catalog.

🤖 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 `@animate/scenes/sol_trappist_cinematic.py` around lines 201 - 211, Update
__init__ to validate that the catalog contains TRAPPIST-1 b through TRAPPIST-1 h
before rendering; collect all missing names and raise ValueError listing them.
Preserve _planetByName and _candidateFocusSol behavior, and add a test covering
a partial planet catalog.

Queue Blender billboards as soon as the chain is readable, and never fall
back to catalog scatter markers when a spin pack is present.
Re-render light/dark gallery assets after textured billboards lead the dive.
Shrink planet disks vs the host on first reveal, let e/f grow through a
deeper HZ→candidate dive, and slow/extend those orbit holds.

@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 `@tests/test_sol_trappist_cinematic.py`:
- Around line 224-231: Update the assertions in the test covering the HZ and
candidate holds to compare each hold duration against its corresponding zoom-in
duration, using the existing arrival and hold boundary constants; retain the
current minimum frame-count checks if they remain required.
🪄 Autofix

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 Plus

Run ID: ef6fc882-9696-431a-baa4-91094ccb1902

📥 Commits

Reviewing files that changed from the base of the PR and between 3702463 and 1eaa269.

⛔ Files ignored due to path filters (2)
  • output/animate/sol_trappist/blender/sol_trappist_cinematic_blender_dark.gif is excluded by !**/*.gif
  • output/animate/sol_trappist/blender/sol_trappist_cinematic_blender_light.gif is excluded by !**/*.gif
📒 Files selected for processing (3)
  • animate/scenes/sol_centauri_cinematic.py
  • animate/scenes/sol_trappist_cinematic.py
  • tests/test_sol_trappist_cinematic.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • animate/scenes/sol_centauri_cinematic.py
  • animate/scenes/sol_trappist_cinematic.py

Comment thread tests/test_sol_trappist_cinematic.py Outdated
Accumulate motion days when slowing the finale, and stop culling e/f by
semi-major axis once the camera pans onto them.
Light/dark gallery assets with continuous TRAPPIST motion and e/f visible
through the candidate close-up.
Use the Earth blender half-width and an Earth-scale hero disk on e/f so the
final zoom fills the frame like the Sol opening.
…se-up

Gallery light/dark assets after matching the e/f beat to the Earth open frame.

@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: 2

🤖 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 `@tests/test_sol_trappist_cinematic.py`:
- Around line 319-332: Update the test around _drawOneTrappistPlanet so it does
not depend on the optional TRAPPIST-1 e spin pack: mock _queueBlenderBody to
capture the queued body and retain the existing scale assertion, or explicitly
skip the assertion when the pack is unavailable.
- Around line 274-281: Update the monotonicity assertion loop in the
motion-clock test around _trappistMotionDays to require each sampled current
value to be strictly greater than the previous value, preventing frozen frames
from passing.
🪄 Autofix

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 Plus

Run ID: ea0c3d2c-153d-43ea-a95a-70a280b24d4b

📥 Commits

Reviewing files that changed from the base of the PR and between 1eaa269 and e889ec1.

⛔ Files ignored due to path filters (2)
  • output/animate/sol_trappist/blender/sol_trappist_cinematic_blender_dark.gif is excluded by !**/*.gif
  • output/animate/sol_trappist/blender/sol_trappist_cinematic_blender_light.gif is excluded by !**/*.gif
📒 Files selected for processing (3)
  • animate/scenes/sol_centauri_cinematic.py
  • animate/scenes/sol_trappist_cinematic.py
  • tests/test_sol_trappist_cinematic.py
🚧 Files skipped from review as they are similar to previous changes (2)
  • animate/scenes/sol_centauri_cinematic.py
  • animate/scenes/sol_trappist_cinematic.py

Comment thread tests/test_sol_trappist_cinematic.py Outdated
Comment on lines +274 to +281
# Accumulated clock must keep advancing (no reverse) when the rate eases down.
days = [
animator._trappistMotionDays(frame)
for frame in range(hzHold - 2, min(frames, candHold + 3))
]
self.assertGreater(days[-1], days[0])
for previous, current in zip(days, days[1:], strict=False):
self.assertGreaterEqual(current, previous)

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 | 🟡 Minor | ⚡ Quick win

Require every sampled motion-clock step to advance.

Line 281 permits an unchanged motion-clock value. This passes when the finale freezes on one or more frames. Use a strict comparison so the test enforces continuous orbital motion.

Proposed fix
-                self.assertGreaterEqual(current, previous)
+                self.assertGreater(current, previous)
📝 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
# Accumulated clock must keep advancing (no reverse) when the rate eases down.
days = [
animator._trappistMotionDays(frame)
for frame in range(hzHold - 2, min(frames, candHold + 3))
]
self.assertGreater(days[-1], days[0])
for previous, current in zip(days, days[1:], strict=False):
self.assertGreaterEqual(current, previous)
# Accumulated clock must keep advancing (no reverse) when the rate eases down.
days = [
animator._trappistMotionDays(frame)
for frame in range(hzHold - 2, min(frames, candHold + 3))
]
self.assertGreater(days[-1], days[0])
for previous, current in zip(days, days[1:], strict=False):
self.assertGreater(current, previous)
🤖 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 `@tests/test_sol_trappist_cinematic.py` around lines 274 - 281, Update the
monotonicity assertion loop in the motion-clock test around _trappistMotionDays
to require each sampled current value to be strictly greater than the previous
value, preventing frozen frames from passing.

Comment thread tests/test_sol_trappist_cinematic.py Outdated
Drop the Earth-sized dual-hero disks; zoom onto one HZ world at a time with
disks that stay under orbital spacing, then pan to the next.
Gallery light/dark assets after one-planet-at-a-time HZ close-ups.
@ThomasAFink
ThomasAFink merged commit e985232 into main Aug 9, 2026
5 checks passed
@ThomasAFink
ThomasAFink deleted the feat/SOLSYS-71-sol-trappist-cinematic branch August 9, 2026 23:07
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.

Sol → TRAPPIST-1 cinematic (Blender billboards)

2 participants