Skip to content

feat(cli): add trip reports command#83

Merged
dreamiurg merged 11 commits into
mainfrom
feat-trip-reports
May 24, 2026
Merged

feat(cli): add trip reports command#83
dreamiurg merged 11 commits into
mainfrom
feat-trip-reports

Conversation

@dreamiurg

Copy link
Copy Markdown
Owner

Who's affected

CLI users and automation that need full PeakBagger trip report text for a peak.

What changed

Before this change, callers had to list peak ascents, pick ascent IDs with trip reports, call ascent show repeatedly, and filter short reports themselves.

This adds peakbagger trip-reports PEAK_ID, which returns detailed trip report records in one CLI invocation. The command supports --limit, --min-words, --within, --after, --before, --format, and --rate-limit. JSON output is a parseable list with ascent ID/URL, climber, date, full report text, word count, GPX availability, route, and external URL when present.

Invalid filter combinations and malformed filters are rejected before network work at both the CLI and collector boundaries. The collector applies summary filters before detail-page fetches and treats limit as the maximum returned reports after detail validation.

Refs #82 and dreamiurg/claude-mountaineering-skills#35.

Notable decisions

PeakBagger does not expose full report text from the ascent summary page, so this is one CLI call for callers but internally performs one summary request plus selected detail requests. That keeps the caller contract simple while still respecting the existing rate-limited client.

CodeRabbit CLI review was requested but could not run because agent-mode auth is not configured. coderabbit auth status --agent returned not_authenticated; coderabbit auth login --agent timed out waiting for browser authentication.

Agent context

  • Contracts changed: new top-level CLI command trip-reports; new JSON output contract for TripReport records.
  • Scope boundary: no changes to existing peak, peak ascents, peak stats, or ascent show command contracts.
  • Known gaps: no VCR cassette for the new command composition; unit coverage exercises collector, CLI wiring, validation, and formatter behavior.
  • Rollback risk: safe to revert; no schema, config, or persistence changes.

Verification

  • uv run pytest tests/test_trip_reports.py -v: 24 passed
  • uv run ruff format --check peakbagger tests: 23 files already formatted
  • uv run ruff check peakbagger tests: passed
  • uv run ty check: exit 0, with two pre-existing warnings in untouched files
  • uv run pytest: 203 passed, 3 skipped
  • uv run peakbagger trip-reports --help: rendered expected command help

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@dreamiurg, we couldn't start this review because you've used your available PR reviews for now.

Your plan currently allows 1 review/hour. Refill in 51 minutes and 15 seconds.

Your organization has run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

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

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than trial, open-source, and free plans. In all cases, review capacity refills continuously over time.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 26a34a95-25bc-456a-bb4c-47ca98dd7147

📥 Commits

Reviewing files that changed from the base of the PR and between 38ab146 and 116e350.

📒 Files selected for processing (3)
  • docs/superpowers/plans/2026-05-24-trip-reports-command.md
  • peakbagger/trip_reports.py
  • tests/test_trip_reports.py
📝 Walkthrough

Walkthrough

This PR implements the complete peakbagger trip-reports <peak_id> CLI feature, including the TripReport data model, a TripReportCollector that orchestrates fetching and filtering ascent details, formatters for JSON and text output, CLI command wiring with filter validation, comprehensive tests using deterministic test doubles, and documentation covering spec and usage examples.

Changes

Trip-Reports CLI Implementation

Layer / File(s) Summary
TripReport model and collection protocols
peakbagger/models.py, peakbagger/trip_reports.py
TripReport Pydantic model stores ascent/climber metadata, text, word count, and an optional external URL, plus a computed url property and JSON serializer. TripReportClient and TripReportScraper protocol abstractions define the fetching/parsing contracts, and count_report_words() validates report text.
TripReportCollector filtering and orchestration
peakbagger/trip_reports.py
TripReportCollector.collect() fetches peak summary, parses candidate ascents, applies summary-level filters (trip-report presence, date ranges), fetches ascent details, validates trip-report text and word count, and builds final TripReport objects. Includes validation of conflicting filters, date parsing (YYYY-MM-DD), relative/absolute date filtering, and summary fallbacks for missing detail fields.
Trip report formatting (JSON and text output)
peakbagger/formatters.py
format_trip_reports() routes between JSON serialization (using TripReport.to_dict()) and text rendering. _print_trip_reports() produces Rich-formatted output with numbered entries, metadata (date, word count, GPX, route, climber), ascent URLs, report text, separators, and empty-state messaging.
CLI command wiring and filter validation
peakbagger/cli.py
New trip-reports command accepts peak_id, format, limit, min-words, date filters, and rate-limit; validates filter combinations and date formats up front via _validate_trip_report_filters(); initializes client/scraper/formatter/collector; supports --dump-html early exit; collects and formats reports; ensures client cleanup via finally.
Comprehensive test coverage
tests/test_trip_reports.py
Test doubles (FakeClient, FakeScraper, DetailValidationScraper, stub collectors) simulate deterministic network/scraping behavior. Unit tests cover word counting, model JSON serialization, collector filtering order, filter/date/limit validation without network calls, formatter output (JSON structure, text rendering, empty state), and CLI wiring/error handling including --dump-html and client lifecycle.
Specification and user documentation
docs/superpowers/plans/2026-05-24-trip-reports-command.md, README.md
Spec plan defines command behavior, CLI options, validation rules, JSON contract, and filtering order, with step-by-step implementation tasks. README adds usage examples (basic, limit, min-words, date windows, JSON) and a jq snippet to extract text fields from JSON output.

Sequence Diagram

sequenceDiagram
  participant User
  participant CLI as trip-reports Command
  participant Collector as TripReportCollector
  participant Client as PeakBaggerClient
  participant Scraper as PeakBaggerScraper
  participant Formatter as PeakFormatter

  User->>CLI: peakbagger trip-reports <peak_id> --limit 5
  CLI->>CLI: validate filters & dates
  CLI->>Client: create connection
  CLI->>Collector: create with client/scraper
  CLI->>Collector: collect(peak_id, limit=5, ...)
  
  Collector->>Client: get(summary_url)
  Client-->>Collector: summary_html
  Collector->>Scraper: parse_peak_ascents(html)
  Scraper-->>Collector: list[Ascent]
  
  Collector->>Collector: filter summaries (date, trip-report presence)
  
  loop for each candidate ascent
    Collector->>Client: get(detail_url)
    Client-->>Collector: detail_html
    Collector->>Scraper: parse_ascent_detail(html)
    Scraper-->>Collector: Ascent with trip_report_text
    Collector->>Collector: validate text & word_count
    alt word_count >= min_words
      Collector->>Collector: build TripReport
    else skip
    end
  end
  
  Collector-->>CLI: list[TripReport]
  CLI->>Formatter: format_trip_reports(reports, format="text")
  Formatter-->>User: Rich formatted output
  CLI->>Client: close()
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Suggested labels

released

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 77.42% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title 'feat(cli): add trip reports command' clearly and concisely summarizes the main change: a new CLI command for trip reports.
Description check ✅ Passed The PR description is comprehensive and well-structured, covering who's affected, what changed, notable decisions, and verification results. However, it does not follow the provided template format with the Type checkboxes and structured Changes section.
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.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@codecov

codecov Bot commented May 24, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 97.69585% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 93.48%. Comparing base (541ff05) to head (116e350).

Files with missing lines Patch % Lines
peakbagger/cli.py 94.52% 4 Missing ⚠️
peakbagger/formatters.py 97.22% 0 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main      #83      +/-   ##
==========================================
+ Coverage   93.43%   93.48%   +0.05%     
==========================================
  Files          10       11       +1     
  Lines        1857     2026     +169     
  Branches      239      265      +26     
==========================================
+ Hits         1735     1894     +159     
  Misses         84       84              
- Partials       38       48      +10     

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

@dreamiurg dreamiurg marked this pull request as ready for review May 24, 2026 17:55

Copy link
Copy Markdown
Owner Author

@coderabbitai review

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown
✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

coderabbitai[bot]
coderabbitai Bot previously requested changes May 24, 2026

@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 `@docs/superpowers/plans/2026-05-24-trip-reports-command.md`:
- Line 943: The phrase "rate limiting reuse" in the document should be
hyphenated as a compound adjective; locate the occurrence of the text "rate
limiting reuse" (around the summary line containing "summary filtering, date
filters, word-count filters, rate limiting reuse, dump") and change it to
"rate-limiting reuse" to improve readability and maintain consistent technical
style.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8822d109-2f60-4d95-b38f-204568cf2d4a

📥 Commits

Reviewing files that changed from the base of the PR and between 541ff05 and 38ab146.

📒 Files selected for processing (7)
  • README.md
  • docs/superpowers/plans/2026-05-24-trip-reports-command.md
  • peakbagger/cli.py
  • peakbagger/formatters.py
  • peakbagger/models.py
  • peakbagger/trip_reports.py
  • tests/test_trip_reports.py

Comment thread docs/superpowers/plans/2026-05-24-trip-reports-command.md Outdated
@dreamiurg dreamiurg dismissed coderabbitai[bot]’s stale review May 24, 2026 18:06

Addressed in 116e350; latest CodeRabbit check is passing.

@dreamiurg

Copy link
Copy Markdown
Owner Author

Babysit PR summary

PR: #83

Required CI

Pass: Required Checks and dependency-review are green.

What changed

  • Added the trip-reports CLI command, report model, collector, formatter support, docs, and tests.
  • Added follow-up coverage tests and simplified unreachable collector branches so Codecov passes.
  • Addressed CodeRabbit's wording comment in the implementation plan.

Review feedback

  • CodeRabbit: addressed the single inline comment and dismissed the stale bot changes-requested review after the latest CodeRabbit check passed.

Remaining risk / notes

  • Local ty still reports two pre-existing warnings in untouched files: browser_transport.py unused ignore and client.py redundant cast.
  • I did not merge; the babysit-pr workflow keeps merge control with the human.

Ready for human merge?

Yes: PR is clean, all checks are passing, and reviewDecision is clear.

@dreamiurg dreamiurg merged commit 2219343 into main May 24, 2026
19 checks passed
@dreamiurg dreamiurg deleted the feat-trip-reports branch May 24, 2026 18:40
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant