Add chappe compare for cross-channel post leaderboards#1
Merged
Conversation
`chappe compare @ch1 @ch2 [@ch3 ...] --by forwards|views|replies|reactions|engagement` returns, per channel, the top posts by the chosen metric, plus a single combined leaderboard sorted across all channels and a summary that names the mean-forward-rate leader and the raw-metric leader. Useful for channel owners comparing their post performance against peers: which post format ships forwards-per-view best across a niche, and which post is the single biggest hit. Composes the same store + rank_posts + _ranking_metric_quality helpers as `posts top`, with `filter_posts_by_period` applied per channel. - analytics.compare_channels: pure function over dict[channel→posts] - cli.compare: top-level command, requires ≥2 channels, validates --by, surfaces per-channel metric_quality and emits sync next_commands for any unsynced channel - 3 new tests covering arg validation, per-channel + combined leaderboards, and the unsynced-channel next-command path
crimeacs
added a commit
that referenced
this pull request
May 19, 2026
The first cut was a generic dark stats card. This rewrites the renderer as a vintage-dispatch poster that pairs the Chappie mascot with the channel's strongest post as a pull-quote, sits on cream paper with deterministic noise, and prints in a strict 3-ink palette (forest green, sepia, cream). Visual moves - Mascot is the hero. _load_mascot_keyed() alpha-keys the near-white sky in the source illustration so Chappie sits directly on the paper instead of inside a hard rectangle. - Mascot rotates per channel via deterministic seed (channel handle hash), picking from chappie-recorder, signal-operator, lookout, night-watch, or scout-map-reader. Same channel always renders the same mascot. - Channel name in Baskerville Bold (true upright weight via display_bold font role), not Hoefler Black Italic which is what serif_black resolves to on macOS. - Pull-quote from the #1 post by forwards in serif Regular, with a faint oversized opening quote ornament so the quote teases without competing with the masthead. - Two feature stats below the quote: top-post forwards and the channel's mean forward rate. - Bottom ledger is four numeric cells with a consistent rhythm (posts, comments, questions, peak views) plus thin vertical separators. - Footer attribution + monospaced URL. Stats fixes - _best_question() now ranks comment questions by reactions then length, filtering out trivially short ones. Lands on substantive questions instead of the first ?-ending fragment in the corpus. - compute_dashboard_stats() distinguishes most_used_format (count) from best_format_by_lift (forward rate). The visual no longer surfaces the bare 'photo' label; the caption shows both axes. - New peak_views and peak_forwards rollups. Assets shipped in src/chappe/assets/ so they ride along in the wheel: chappie-recorder.png, chappie-signal-operator.png, chappie-lookout.png, chappie-night-watch.png, chappie-scout-map-reader.png.
crimeacs
added a commit
that referenced
this pull request
May 19, 2026
…ion (#2) * Add chappe wrapped: shareable PNG dashboard + caption per channel `chappe wrapped @channel --period 90d [--lang en|ru] [--out PATH]` reads the local store, computes channel stats (posts, comments, mean forward-rate, best format, top 3 by forwards, sample audience question), and writes a 1080x1350 PNG card plus a ready caption .txt. The PNG carries 'generated by chappe · github.com/crimeacs/chappe' in the footer, so each post published from it is a quiet referral. Wired into onboarding: - bootstrap fastest_path_to_value now suggests `chappe wrapped` once a channel has ≥20 local posts. The 'why' explicitly frames it as a free engagement post. - onboard setup_steps appends a publish_wrapped_dashboard step at the end of analyze_growth. This makes the first reachable payoff after a fresh sync a tangible image the operator can post immediately, not just JSON. The Chappe attribution turns each adopter's first post into a growth loop. - new dashboard.py: pure rendering (Pillow) + compute_dashboard_stats + bilingual render_caption; tolerates missing Cyrillic glyphs by falling back through a font-path candidate list (Arial → DejaVu) - new pyproject dep: Pillow>=10 - new cli command `wrapped` and two new onboarding steps - 3 new tests: png magic bytes + caption file + sync next_command on unsynced + bootstrap surface for the new fastest-path step * Redesign chappe wrapped: magazine-cover poster with brand assets The first cut was a generic dark stats card. This rewrites the renderer as a vintage-dispatch poster that pairs the Chappie mascot with the channel's strongest post as a pull-quote, sits on cream paper with deterministic noise, and prints in a strict 3-ink palette (forest green, sepia, cream). Visual moves - Mascot is the hero. _load_mascot_keyed() alpha-keys the near-white sky in the source illustration so Chappie sits directly on the paper instead of inside a hard rectangle. - Mascot rotates per channel via deterministic seed (channel handle hash), picking from chappie-recorder, signal-operator, lookout, night-watch, or scout-map-reader. Same channel always renders the same mascot. - Channel name in Baskerville Bold (true upright weight via display_bold font role), not Hoefler Black Italic which is what serif_black resolves to on macOS. - Pull-quote from the #1 post by forwards in serif Regular, with a faint oversized opening quote ornament so the quote teases without competing with the masthead. - Two feature stats below the quote: top-post forwards and the channel's mean forward rate. - Bottom ledger is four numeric cells with a consistent rhythm (posts, comments, questions, peak views) plus thin vertical separators. - Footer attribution + monospaced URL. Stats fixes - _best_question() now ranks comment questions by reactions then length, filtering out trivially short ones. Lands on substantive questions instead of the first ?-ending fragment in the corpus. - compute_dashboard_stats() distinguishes most_used_format (count) from best_format_by_lift (forward rate). The visual no longer surfaces the bare 'photo' label; the caption shows both axes. - New peak_views and peak_forwards rollups. Assets shipped in src/chappe/assets/ so they ride along in the wheel: chappie-recorder.png, chappie-signal-operator.png, chappie-lookout.png, chappie-night-watch.png, chappie-scout-map-reader.png.
crimeacs
added a commit
that referenced
this pull request
May 19, 2026
User-facing additions since 0.1.2: - chappe compare @ch1 @ch2 [...]: cross-channel leaderboard with mean forward-rate leader and raw-metric winner. PR #1. - chappe wrapped @channel: PNG channel-dashboard renderer plus caption template with Chappe footer attribution; mascot rotates per channel and Pillow renders cream-paper letterpress style. Onboarding now surfaces it as the first reachable payoff once a channel has ≥20 stored posts. PR #2. - New Pillow>=10 dependency. - Bundled five Chappie mascot illustrations inside the wheel.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
chappe compare @ch1 @ch2 [@ch3 ...] --by forwards|views|replies|reactions|engagement --limit 5 --period 365drank_posts,filter_posts_by_period,_ranking_metric_quality); no schema or store changes.Why
Channel owners and agents already use
chappe posts topper channel; doing peer-benchmarking today requires runningposts topN times and stitching the JSON yourself.comparemakes that one call. Concretely: pointed at four RU AI/tech channels (~420 posts), the command surfaced the forward-rate leader in the niche in <1s and produced the combined top-12 list of viral posts across all of them.Output shape
{ "ok": true, "channels": ["@a","@b","@c"], "by": "forwards", "per_channel": { "@a": { "posts_available": 100, "metric_quality": {...}, "top_posts": [...] }, ... }, "combined_leaderboard": [ { "channel": "@a", "id": "...", "views": ..., "forwards": ..., ... }, ... ], "summary": { "channels_compared": 3, "posts_compared": 300, "by_forward_ratio_winner": { "channel": "@a", "mean_forward_rate": 0.014 }, "by_raw_metric_winner": { "channel": "@b", "metric": "forwards", "value": 4436, "post_id": "...", "link": "..." }, "mean_forward_rate_by_channel": { "@a": 0.014, "@b": 0.011, "@c": 0.008 } }, "unsynced_channels": [], "next_commands": [ "chappe briefing @a", ... ] }Test plan
pytest -q— 41 passed (38 baseline + 3 new)ruff check src/ tests/— clean@nn_for_science @denissexy @seeallochnaya @ai_newz); summary + combined leaderboard come back correctly and the forward-rate winner is computed using the sameforward_rate = forwards/viewsdefinition asenrich_postcomparewith one channel returns USAGE_ERROR ("compare requires at least two channels")compareagainst an unsynced handle returns the channel inunsynced_channelsand emits achappe sync ...next_command🤖 Generated with Claude Code