limn-review 0.1.123
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +110 -0
- package/README.md +133 -0
- package/dist/ai/runtime.js +535 -0
- package/dist/api/plugins/auth.js +169 -0
- package/dist/api/plugins/error-handler.js +114 -0
- package/dist/api/plugins/rate-limit.js +855 -0
- package/dist/api/plugins/security.js +321 -0
- package/dist/api/routes/activity.js +103 -0
- package/dist/api/routes/ai-runtime.js +67 -0
- package/dist/api/routes/auth.js +194 -0
- package/dist/api/routes/billing.js +209 -0
- package/dist/api/routes/bot-triage.js +1289 -0
- package/dist/api/routes/conflicts.js +730 -0
- package/dist/api/routes/contact.js +318 -0
- package/dist/api/routes/daily-brief.js +58 -0
- package/dist/api/routes/flow.js +71 -0
- package/dist/api/routes/health.js +7 -0
- package/dist/api/routes/insights.js +200 -0
- package/dist/api/routes/me.js +458 -0
- package/dist/api/routes/mentions.js +22 -0
- package/dist/api/routes/mergers.js +8 -0
- package/dist/api/routes/ml-labels.js +109 -0
- package/dist/api/routes/open-prs.js +35 -0
- package/dist/api/routes/prs.js +1633 -0
- package/dist/api/routes/reactions.js +217 -0
- package/dist/api/routes/repos.js +563 -0
- package/dist/api/routes/search.js +41 -0
- package/dist/api/routes/threads.js +118 -0
- package/dist/api/routes/timeline.js +150 -0
- package/dist/api/routes/users.js +67 -0
- package/dist/api/routes/webhooks.js +181 -0
- package/dist/api/routes/workspaces.js +322 -0
- package/dist/app.js +274 -0
- package/dist/ascii.js +19 -0
- package/dist/auth/account.js +482 -0
- package/dist/auth/crypto.js +46 -0
- package/dist/bot-triage/resolve.js +59 -0
- package/dist/cli.js +388 -0
- package/dist/coding/activity.js +80 -0
- package/dist/coding/agent.js +288 -0
- package/dist/coding/ai-fix/auto-fix.js +212 -0
- package/dist/coding/ai-fix/manager.js +370 -0
- package/dist/coding/ai-fix/persist.js +213 -0
- package/dist/coding/ai-fix/pr-context.js +58 -0
- package/dist/coding/ai-fix/prompts.js +138 -0
- package/dist/coding/ai-fix/review-seed.js +357 -0
- package/dist/coding/ai-fix/routes.js +425 -0
- package/dist/coding/git-ops.js +321 -0
- package/dist/coding/git.js +184 -0
- package/dist/coding/merge.js +262 -0
- package/dist/coding/safe-path.js +75 -0
- package/dist/coding/schema.js +43 -0
- package/dist/config.js +648 -0
- package/dist/conflict/diff.js +304 -0
- package/dist/conflict/git.js +118 -0
- package/dist/conflict/hash.js +73 -0
- package/dist/conflict/janitor.js +218 -0
- package/dist/conflict/land.js +675 -0
- package/dist/conflict/model-types.js +2 -0
- package/dist/conflict/model.js +1081 -0
- package/dist/conflict/parse.js +142 -0
- package/dist/conflict/seam.js +136 -0
- package/dist/conflict/session.js +532 -0
- package/dist/conflict/suggestion.js +398 -0
- package/dist/conflict/tokens.js +72 -0
- package/dist/data-dir.js +112 -0
- package/dist/db/actor-lanes.js +213 -0
- package/dist/db/automation-ids.js +97 -0
- package/dist/db/automation-output.js +349 -0
- package/dist/db/blast-radius-query.js +36 -0
- package/dist/db/blast-radius.js +226 -0
- package/dist/db/bot-dormancy.js +115 -0
- package/dist/db/bot-overlap.js +579 -0
- package/dist/db/bot-volume.js +722 -0
- package/dist/db/bot-window.js +35 -0
- package/dist/db/branch-queries.js +310 -0
- package/dist/db/change-shape.js +243 -0
- package/dist/db/changepoint.js +75 -0
- package/dist/db/cleanup.js +36 -0
- package/dist/db/client.js +102 -0
- package/dist/db/code-loc.js +388 -0
- package/dist/db/credits.js +79 -0
- package/dist/db/daily-brief.js +406 -0
- package/dist/db/dependency-cards.js +145 -0
- package/dist/db/erase-account.js +255 -0
- package/dist/db/export-account.js +189 -0
- package/dist/db/failing-checks.js +124 -0
- package/dist/db/file-coupling.js +197 -0
- package/dist/db/flow-detail.js +661 -0
- package/dist/db/flow-pointers.js +197 -0
- package/dist/db/flow-settings.js +67 -0
- package/dist/db/forecast.js +114 -0
- package/dist/db/line-overlap.js +81 -0
- package/dist/db/merge-queue.js +189 -0
- package/dist/db/migrate.js +17 -0
- package/dist/db/migrations/0000_purple_ben_grimm.sql +155 -0
- package/dist/db/migrations/0001_colorful_ozymandias.sql +31 -0
- package/dist/db/migrations/0002_famous_sersi.sql +9 -0
- package/dist/db/migrations/0003_clever_shinobi_shaw.sql +3 -0
- package/dist/db/migrations/0004_pale_scalphunter.sql +1 -0
- package/dist/db/migrations/0005_daffy_guardian.sql +2 -0
- package/dist/db/migrations/0006_cute_violations.sql +45 -0
- package/dist/db/migrations/0007_dark_anthem.sql +2 -0
- package/dist/db/migrations/0008_multitenant_accounts.sql +44 -0
- package/dist/db/migrations/0009_lean_bodies.sql +13 -0
- package/dist/db/migrations/0010_lean_bodies_nullable.sql +56 -0
- package/dist/db/migrations/0011_pr_diff_size.sql +10 -0
- package/dist/db/migrations/0012_findings_included_default.sql +7 -0
- package/dist/db/migrations/0013_review_routing.sql +9 -0
- package/dist/db/migrations/0014_account_last_active.sql +6 -0
- package/dist/db/migrations/0015_repos_inbox_watch.sql +9 -0
- package/dist/db/migrations/0016_repo_viewer_permission.sql +7 -0
- package/dist/db/migrations/0017_account_display_name.sql +7 -0
- package/dist/db/migrations/0018_finding_comment_kind.sql +7 -0
- package/dist/db/migrations/0019_finding_file_in_diff.sql +7 -0
- package/dist/db/migrations/0020_claude_review_cost_telemetry.sql +11 -0
- package/dist/db/migrations/0021_account_feed_last_seen.sql +7 -0
- package/dist/db/migrations/0022_ci_status_events.sql +21 -0
- package/dist/db/migrations/0023_ai_usage.sql +21 -0
- package/dist/db/migrations/0024_pr_head_ref_name.sql +6 -0
- package/dist/db/migrations/0025_account_billing.sql +7 -0
- package/dist/db/migrations/0026_ai_credit_allowance.sql +5 -0
- package/dist/db/migrations/0027_user_github_type.sql +6 -0
- package/dist/db/migrations/0028_bot_review_classification.sql +21 -0
- package/dist/db/migrations/0029_bot_mute_rules.sql +19 -0
- package/dist/db/migrations/0030_teams.sql +32 -0
- package/dist/db/migrations/0031_events_pr_idx.sql +7 -0
- package/dist/db/migrations/0032_benchmark_contributions.sql +29 -0
- package/dist/db/migrations/0033_thread_addressed_confidence.sql +9 -0
- package/dist/db/migrations/0034_thread_resolved_at.sql +6 -0
- package/dist/db/migrations/0035_pr_first_review_requested_at.sql +5 -0
- package/dist/db/migrations/0036_search_index.sql +25 -0
- package/dist/db/migrations/0037_author_indexes.sql +15 -0
- package/dist/db/migrations/0038_auto_merge_requests.sql +37 -0
- package/dist/db/migrations/0039_branch_status.sql +44 -0
- package/dist/db/migrations/0040_pr_review_decision.sql +10 -0
- package/dist/db/migrations/0041_branch_commit_detail.sql +38 -0
- package/dist/db/migrations/0042_repo_reviewers.sql +176 -0
- package/dist/db/migrations/0043_account_reviewers.sql +131 -0
- package/dist/db/migrations/0044_workspaces.sql +138 -0
- package/dist/db/migrations/0045_workspace_reviewers.sql +180 -0
- package/dist/db/migrations/0046_drop_inbox_watch.sql +25 -0
- package/dist/db/migrations/0047_ml_comment_labels.sql +40 -0
- package/dist/db/migrations/0048_ml_vendor_severity.sql +31 -0
- package/dist/db/migrations/0049_seat_pricing_repo_description.sql +21 -0
- package/dist/db/migrations/0050_users_app_slug.sql +12 -0
- package/dist/db/migrations/0051_auto_merge_queue.sql +17 -0
- package/dist/db/migrations/0052_trunk_ci_status_events.sql +43 -0
- package/dist/db/migrations/0053_automation_roles.sql +79 -0
- package/dist/db/migrations/0054_automation_vendor_kinds.sql +514 -0
- package/dist/db/migrations/0055_auto_merge_phase.sql +12 -0
- package/dist/db/migrations/0056_pr_mentions.sql +22 -0
- package/dist/db/migrations/0057_large_pr_threshold.sql +14 -0
- package/dist/db/migrations/0058_pending_mute.sql +53 -0
- package/dist/db/migrations/0059_merge_queue_state.sql +33 -0
- package/dist/db/migrations/0060_drop_my_turn_dismissals.sql +33 -0
- package/dist/db/migrations/0061_auto_merge_durable_anchors.sql +27 -0
- package/dist/db/migrations/0062_blast_radius_config.sql +21 -0
- package/dist/db/migrations/0063_repo_file_coupling.sql +33 -0
- package/dist/db/migrations/0064_pr_content_kind.sql +21 -0
- package/dist/db/migrations/0065_workspace_flow_settings.sql +13 -0
- package/dist/db/migrations/0066_review_request_events.sql +31 -0
- package/dist/db/migrations/0067_pr_security_signals.sql +86 -0
- package/dist/db/migrations/0068_my_turn_settings.sql +18 -0
- package/dist/db/migrations/0069_my_turn_dismissals.sql +41 -0
- package/dist/db/migrations/0070_claude_review_follow_up_ticket.sql +22 -0
- package/dist/db/migrations/0071_claude_review_trigger.sql +11 -0
- package/dist/db/migrations/0072_commit_message_headline.sql +13 -0
- package/dist/db/migrations/0073_claude_review_chat.sql +31 -0
- package/dist/db/migrations/0074_adopt_agentic_tables.sql +98 -0
- package/dist/db/migrations/0075_review_lens_drop_learnings.sql +15 -0
- package/dist/db/migrations/0076_claude_review_threads.sql +17 -0
- package/dist/db/migrations/0077_claude_review_ci_failures.sql +10 -0
- package/dist/db/migrations/0078_ai_fix_change_report.sql +17 -0
- package/dist/db/migrations/0079_claude_finding_story.sql +16 -0
- package/dist/db/migrations/meta/0000_snapshot.json +1116 -0
- package/dist/db/migrations/meta/0001_snapshot.json +1321 -0
- package/dist/db/migrations/meta/0002_snapshot.json +1375 -0
- package/dist/db/migrations/meta/0003_snapshot.json +1396 -0
- package/dist/db/migrations/meta/0004_snapshot.json +1416 -0
- package/dist/db/migrations/meta/0005_snapshot.json +1430 -0
- package/dist/db/migrations/meta/0006_snapshot.json +1745 -0
- package/dist/db/migrations/meta/0007_snapshot.json +1759 -0
- package/dist/db/migrations/meta/_journal.json +566 -0
- package/dist/db/migrations-pg/0000_tired_alex_power.sql +268 -0
- package/dist/db/migrations-pg/0001_dizzy_mockingbird.sql +3 -0
- package/dist/db/migrations-pg/0002_glorious_ikaris.sql +4 -0
- package/dist/db/migrations-pg/0003_melted_secret_warriors.sql +2 -0
- package/dist/db/migrations-pg/0004_numerous_triton.sql +1 -0
- package/dist/db/migrations-pg/0005_thick_blockbuster.sql +2 -0
- package/dist/db/migrations-pg/0006_majestic_dracula.sql +1 -0
- package/dist/db/migrations-pg/0007_same_human_torch.sql +2 -0
- package/dist/db/migrations-pg/0008_slimy_toxin.sql +1 -0
- package/dist/db/migrations-pg/0009_fuzzy_jubilee.sql +4 -0
- package/dist/db/migrations-pg/0010_late_hammerhead.sql +1 -0
- package/dist/db/migrations-pg/0011_happy_leech.sql +16 -0
- package/dist/db/migrations-pg/0012_woozy_captain_midlands.sql +16 -0
- package/dist/db/migrations-pg/0013_yielding_nicolaos.sql +1 -0
- package/dist/db/migrations-pg/0014_wakeful_bill_hollister.sql +2 -0
- package/dist/db/migrations-pg/0015_aspiring_black_tom.sql +1 -0
- package/dist/db/migrations-pg/0016_cute_ghost_rider.sql +30 -0
- package/dist/db/migrations-pg/0017_far_changeling.sql +24 -0
- package/dist/db/migrations-pg/0018_fancy_miss_america.sql +1 -0
- package/dist/db/migrations-pg/0019_benchmark_contributions.sql +22 -0
- package/dist/db/migrations-pg/0020_majestic_edwin_jarvis.sql +3 -0
- package/dist/db/migrations-pg/0021_green_salo.sql +1 -0
- package/dist/db/migrations-pg/0022_wise_baron_strucker.sql +1 -0
- package/dist/db/migrations-pg/0023_search_index.sql +19 -0
- package/dist/db/migrations-pg/0024_author_indexes.sql +9 -0
- package/dist/db/migrations-pg/0025_auto_merge_requests.sql +26 -0
- package/dist/db/migrations-pg/0026_branch_status.sql +32 -0
- package/dist/db/migrations-pg/0027_pr_review_decision.sql +5 -0
- package/dist/db/migrations-pg/0028_branch_commit_detail.sql +9 -0
- package/dist/db/migrations-pg/0029_repo_reviewers.sql +127 -0
- package/dist/db/migrations-pg/0030_account_reviewers.sql +77 -0
- package/dist/db/migrations-pg/0031_workspaces.sql +131 -0
- package/dist/db/migrations-pg/0032_workspace_reviewers.sql +165 -0
- package/dist/db/migrations-pg/0033_drop_inbox_watch.sql +14 -0
- package/dist/db/migrations-pg/0034_ml_comment_labels.sql +33 -0
- package/dist/db/migrations-pg/0035_ml_vendor_severity.sql +16 -0
- package/dist/db/migrations-pg/0036_seat_pricing_repo_description.sql +12 -0
- package/dist/db/migrations-pg/0037_users_app_slug.sql +9 -0
- package/dist/db/migrations-pg/0038_auto_merge_queue.sql +10 -0
- package/dist/db/migrations-pg/0039_trunk_ci_status_events.sql +27 -0
- package/dist/db/migrations-pg/0040_automation_roles.sql +63 -0
- package/dist/db/migrations-pg/0041_automation_vendor_kinds.sql +488 -0
- package/dist/db/migrations-pg/0042_auto_merge_phase.sql +8 -0
- package/dist/db/migrations-pg/0043_pr_mentions.sql +19 -0
- package/dist/db/migrations-pg/0044_large_pr_threshold.sql +6 -0
- package/dist/db/migrations-pg/0045_pending_mute.sql +26 -0
- package/dist/db/migrations-pg/0046_merge_queue_state.sql +18 -0
- package/dist/db/migrations-pg/0047_drop_my_turn_dismissals.sql +21 -0
- package/dist/db/migrations-pg/0048_auto_merge_durable_anchors.sql +27 -0
- package/dist/db/migrations-pg/0049_blast_radius_config.sql +8 -0
- package/dist/db/migrations-pg/0050_repo_file_coupling.sql +13 -0
- package/dist/db/migrations-pg/0051_pr_content_kind.sql +6 -0
- package/dist/db/migrations-pg/0052_workspace_flow_settings.sql +4 -0
- package/dist/db/migrations-pg/0053_review_request_events.sql +18 -0
- package/dist/db/migrations-pg/0054_pr_security_signals.sql +59 -0
- package/dist/db/migrations-pg/0055_my_turn_settings.sql +6 -0
- package/dist/db/migrations-pg/0056_my_turn_dismissals.sql +21 -0
- package/dist/db/migrations-pg/0057_claude_review_follow_up_ticket.sql +8 -0
- package/dist/db/migrations-pg/0058_claude_review_trigger.sql +4 -0
- package/dist/db/migrations-pg/0059_commit_message_headline.sql +3 -0
- package/dist/db/migrations-pg/0060_claude_review_chat.sql +24 -0
- package/dist/db/migrations-pg/0061_adopt_agentic_tables.sql +79 -0
- package/dist/db/migrations-pg/0062_review_lens_drop_learnings.sql +5 -0
- package/dist/db/migrations-pg/0063_claude_review_threads.sql +7 -0
- package/dist/db/migrations-pg/0064_claude_review_ci_failures.sql +4 -0
- package/dist/db/migrations-pg/0065_ai_fix_change_report.sql +9 -0
- package/dist/db/migrations-pg/0066_claude_finding_story.sql +7 -0
- package/dist/db/migrations-pg/meta/0000_snapshot.json +2137 -0
- package/dist/db/migrations-pg/meta/0001_snapshot.json +2143 -0
- package/dist/db/migrations-pg/meta/0002_snapshot.json +2170 -0
- package/dist/db/migrations-pg/meta/0003_snapshot.json +2182 -0
- package/dist/db/migrations-pg/meta/0004_snapshot.json +2188 -0
- package/dist/db/migrations-pg/meta/0005_snapshot.json +2201 -0
- package/dist/db/migrations-pg/meta/0006_snapshot.json +2207 -0
- package/dist/db/migrations-pg/meta/0007_snapshot.json +2219 -0
- package/dist/db/migrations-pg/meta/0008_snapshot.json +2226 -0
- package/dist/db/migrations-pg/meta/0009_snapshot.json +2250 -0
- package/dist/db/migrations-pg/meta/0010_snapshot.json +2256 -0
- package/dist/db/migrations-pg/meta/0011_snapshot.json +2412 -0
- package/dist/db/migrations-pg/meta/0012_snapshot.json +2528 -0
- package/dist/db/migrations-pg/meta/0013_snapshot.json +2534 -0
- package/dist/db/migrations-pg/meta/0014_snapshot.json +2547 -0
- package/dist/db/migrations-pg/meta/0015_snapshot.json +2553 -0
- package/dist/db/migrations-pg/meta/0016_snapshot.json +2774 -0
- package/dist/db/migrations-pg/meta/0017_snapshot.json +2999 -0
- package/dist/db/migrations-pg/meta/0018_snapshot.json +3020 -0
- package/dist/db/migrations-pg/meta/0020_snapshot.json +3228 -0
- package/dist/db/migrations-pg/meta/0021_snapshot.json +3234 -0
- package/dist/db/migrations-pg/meta/0022_snapshot.json +3240 -0
- package/dist/db/migrations-pg/meta/_journal.json +475 -0
- package/dist/db/ml-labels.js +1666 -0
- package/dist/db/my-turn-dismissals.js +343 -0
- package/dist/db/my-turn-settings.js +34 -0
- package/dist/db/pending-classify.js +46 -0
- package/dist/db/pending-mute.js +171 -0
- package/dist/db/pending-tabs.js +238 -0
- package/dist/db/period-metrics.js +820 -0
- package/dist/db/person-period.js +763 -0
- package/dist/db/pr-intervals.js +930 -0
- package/dist/db/pr-liveness.js +240 -0
- package/dist/db/pr-mentions.js +279 -0
- package/dist/db/pr-merge-queue-stamp.js +91 -0
- package/dist/db/queries.js +14631 -0
- package/dist/db/reaction-targets.js +94 -0
- package/dist/db/repo-activity.js +171 -0
- package/dist/db/retention.js +138 -0
- package/dist/db/review-threads-for-review.js +240 -0
- package/dist/db/run-migrations.js +24 -0
- package/dist/db/schema.pg.js +1220 -0
- package/dist/db/schema.sqlite.js +1801 -0
- package/dist/db/search.js +317 -0
- package/dist/db/security-alerts.js +218 -0
- package/dist/db/synthesis-input.js +565 -0
- package/dist/db/triage.js +320 -0
- package/dist/db/usage.js +63 -0
- package/dist/db/work-plan.js +1086 -0
- package/dist/db/working-hours.js +161 -0
- package/dist/feed/my-turn.js +122 -0
- package/dist/github/actions-logs.js +397 -0
- package/dist/github/auth.js +86 -0
- package/dist/github/branch-queries.js +229 -0
- package/dist/github/client.js +454 -0
- package/dist/github/codeowners.js +221 -0
- package/dist/github/commit-checks.js +105 -0
- package/dist/github/compare.js +110 -0
- package/dist/github/diff-anchor.js +227 -0
- package/dist/github/mutations.js +706 -0
- package/dist/github/pr-file-content.js +254 -0
- package/dist/github/pr-liveness.js +161 -0
- package/dist/github/queries.js +875 -0
- package/dist/github/rate-budget.js +129 -0
- package/dist/github/reactions.js +161 -0
- package/dist/github/reviewer-suggest.js +104 -0
- package/dist/github/team-reviewers.js +96 -0
- package/dist/index.js +184 -0
- package/dist/merge/auto-merge-runner.js +960 -0
- package/dist/ml/severity-client.js +218 -0
- package/dist/pr/detail-enricher.js +26 -0
- package/dist/pro/bind.js +302 -0
- package/dist/pro/contract.js +37 -0
- package/dist/pro/migrate.js +64 -0
- package/dist/review/agent-context.js +127 -0
- package/dist/review/agent.js +385 -0
- package/dist/review/agentic.js +59 -0
- package/dist/review/auth.js +94 -0
- package/dist/review/chat-agent.js +179 -0
- package/dist/review/claude-review/ai-ready.js +16 -0
- package/dist/review/claude-review/auto-settings.js +139 -0
- package/dist/review/claude-review/auto.js +244 -0
- package/dist/review/claude-review/chat.js +489 -0
- package/dist/review/claude-review/ci-failures.js +350 -0
- package/dist/review/claude-review/follow-up.js +310 -0
- package/dist/review/claude-review/manager.js +686 -0
- package/dist/review/claude-review/persist.js +996 -0
- package/dist/review/claude-review/prompts.js +357 -0
- package/dist/review/claude-review/routes.js +518 -0
- package/dist/review/claude-review/routing.js +61 -0
- package/dist/review/claude-review/specialists.js +190 -0
- package/dist/review/claude-review/threads.js +265 -0
- package/dist/review/claude-review/ticket.js +282 -0
- package/dist/review/clone-hygiene.js +380 -0
- package/dist/review/clone-manager.js +367 -0
- package/dist/review/llm.js +113 -0
- package/dist/review/model-options.js +48 -0
- package/dist/review/plugin-providers.js +12 -0
- package/dist/review/post-review.js +216 -0
- package/dist/review/post-seam.js +161 -0
- package/dist/review/prepare.js +168 -0
- package/dist/review/pricing.js +17 -0
- package/dist/review/schema.js +156 -0
- package/dist/review/submit-map.js +41 -0
- package/dist/review/usage.js +90 -0
- package/dist/shared/claude-review.js +335 -0
- package/dist/shared/conflict-fold.js +151 -0
- package/dist/shared/conflicts.js +30 -0
- package/dist/shared/flow-settings.js +191 -0
- package/dist/shared/index.js +8 -0
- package/dist/shared/my-turn-settings.js +238 -0
- package/dist/shared/pending-rules.js +281 -0
- package/dist/shared/product.js +54 -0
- package/dist/shared/types.js +896 -0
- package/dist/status.js +386 -0
- package/dist/sync/adaptive.js +185 -0
- package/dist/sync/app-attribution.js +66 -0
- package/dist/sync/auth-notices.js +36 -0
- package/dist/sync/backfill-ci-history.js +315 -0
- package/dist/sync/backfill-commit-headlines.js +136 -0
- package/dist/sync/backfill-pr-security.js +175 -0
- package/dist/sync/backfill-review-requests.js +97 -0
- package/dist/sync/benchmark-rollup.js +50 -0
- package/dist/sync/bot-detection.js +309 -0
- package/dist/sync/bot-resolution-markers.js +30 -0
- package/dist/sync/branch-status.js +634 -0
- package/dist/sync/classify-change-shape.js +150 -0
- package/dist/sync/commit-files.js +74 -0
- package/dist/sync/derive-thread-state.js +99 -0
- package/dist/sync/drain-review-threads.js +212 -0
- package/dist/sync/hydrate-detail.js +482 -0
- package/dist/sync/mention-scan.js +89 -0
- package/dist/sync/ml-enrichment.js +478 -0
- package/dist/sync/pr-change-signal.js +96 -0
- package/dist/sync/pr-liveness-sweep.js +139 -0
- package/dist/sync/pr-settle.js +381 -0
- package/dist/sync/refresh-pr.js +163 -0
- package/dist/sync/reparse-vendor-badges.js +495 -0
- package/dist/sync/resync-after-write.js +280 -0
- package/dist/sync/review-fingerprint.js +117 -0
- package/dist/sync/reviewer-behavior.js +103 -0
- package/dist/sync/reviewer-classify.js +503 -0
- package/dist/sync/routing-files.js +97 -0
- package/dist/sync/scheduled-jobs.js +12 -0
- package/dist/sync/scheduler.js +159 -0
- package/dist/sync/security-detect.js +521 -0
- package/dist/sync/sync-manager.js +750 -0
- package/dist/sync/sync-one-pr.js +205 -0
- package/dist/sync/sync-repo.js +400 -0
- package/dist/sync/unsettled-prs.js +506 -0
- package/dist/sync/upsert.js +1190 -0
- package/package.json +56 -0
- package/public/apple-touch-icon.png +0 -0
- package/public/assets/AiFixTab-CQP6PT5u.js +2 -0
- package/public/assets/ClaudeReviewTab-DQJ-58ZA.js +8 -0
- package/public/assets/PrBotBehaviourTab-CCnFrWbC.js +1 -0
- package/public/assets/archivo-latin-600-BN-JkNrl.woff2 +0 -0
- package/public/assets/highlight-BEHUn5zE.css +10 -0
- package/public/assets/highlight-CIIZLa6Z.js +12 -0
- package/public/assets/index-BDnYs6zg.js +73 -0
- package/public/assets/index-mCuI--RC.css +1 -0
- package/public/assets/markdown-I_JLLVAZ.js +32 -0
- package/public/assets/perfProbe-Da13EhTE.js +1 -0
- package/public/assets/tanstack-5qsxxaLe.js +17 -0
- package/public/assets/vis-C3BCkP5U.js +1280 -0
- package/public/assets/vis-ziCVehMy.css +1 -0
- package/public/favicon-16.png +0 -0
- package/public/favicon-32.png +0 -0
- package/public/favicon-48.png +0 -0
- package/public/favicon.svg +5 -0
- package/public/index.html +41 -0
- package/public-landing/apple-touch-icon.png +0 -0
- package/public-landing/assets/archivo-latin-500-BWmvx2Mg.woff2 +0 -0
- package/public-landing/assets/archivo-latin-600-BN-JkNrl.woff2 +0 -0
- package/public-landing/assets/index-CA3eEGXO.js +40 -0
- package/public-landing/assets/index-naQrQ6Fe.css +1 -0
- package/public-landing/assets/jetbrains-mono-latin-400-RruCX7RW.woff2 +0 -0
- package/public-landing/assets/newsreader-latin-400-DExrRRrN.woff2 +0 -0
- package/public-landing/assets/newsreader-latin-400-italic-b0I-AwbV.woff2 +0 -0
- package/public-landing/bots/index.html +156 -0
- package/public-landing/contact/index.html +156 -0
- package/public-landing/cookies/index.html +156 -0
- package/public-landing/demo/limn-walkthrough-poster.jpg +0 -0
- package/public-landing/demo/limn-walkthrough.cues.json +44 -0
- package/public-landing/demo/limn-walkthrough.mp4 +0 -0
- package/public-landing/favicon-16.png +0 -0
- package/public-landing/favicon-32.png +0 -0
- package/public-landing/favicon-48.png +0 -0
- package/public-landing/favicon.svg +5 -0
- package/public-landing/features/index.html +156 -0
- package/public-landing/for-developers/index.html +156 -0
- package/public-landing/for-managers/index.html +156 -0
- package/public-landing/how-it-works/index.html +156 -0
- package/public-landing/how-we-measure/index.html +156 -0
- package/public-landing/icon-192.png +0 -0
- package/public-landing/icon-512.png +0 -0
- package/public-landing/index.html +156 -0
- package/public-landing/insights/index.html +156 -0
- package/public-landing/og-image.png +0 -0
- package/public-landing/pricing/index.html +156 -0
- package/public-landing/privacy/index.html +156 -0
- package/public-landing/pro/index.html +156 -0
- package/public-landing/reviews/index.html +156 -0
- package/public-landing/robots.txt +8 -0
- package/public-landing/shots/benchmark.png +0 -0
- package/public-landing/shots/bot-roi.png +0 -0
- package/public-landing/shots/bot-settings.png +0 -0
- package/public-landing/shots/chronology.png +0 -0
- package/public-landing/shots/feed.png +0 -0
- package/public-landing/shots/flow-metrics.png +0 -0
- package/public-landing/shots/free-reports.png +0 -0
- package/public-landing/shots/pending-board.png +0 -0
- package/public-landing/shots/pending-card.png +0 -0
- package/public-landing/shots/period-report.png +0 -0
- package/public-landing/shots/pr-detail.png +0 -0
- package/public-landing/shots/pr-threads.png +0 -0
- package/public-landing/shots/reach.png +0 -0
- package/public-landing/shots/repo-rows.png +0 -0
- package/public-landing/shots/severity-findings.png +0 -0
- package/public-landing/shots/severity-strip.png +0 -0
- package/public-landing/site.webmanifest +14 -0
- package/public-landing/sitemap.xml +51 -0
- package/public-landing/terms/index.html +156 -0
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta name="theme-color" content="#FAFAF8" />
|
|
7
|
+
|
|
8
|
+
<!-- Primary SEO. Everything between the seo:start/seo:end markers is REPLACED
|
|
9
|
+
per route at build time by prerender.mjs, from the ROUTE_SEO table in
|
|
10
|
+
src/lib/routes.ts — so /pricing ships its own title, description and
|
|
11
|
+
canonical in the HTML rather than inheriting the home page's. What is
|
|
12
|
+
written here is the home-page copy and the dev-server fallback; keep the
|
|
13
|
+
markers, and keep the copy in sync with ROUTE_SEO['/']. -->
|
|
14
|
+
<title>How we measure — the two models, in plain English</title>
|
|
15
|
+
<meta name="description" content="Almost everything Limn shows you is counted, not predicted. Two questions resist counting and have a model each: how serious a review-bot comment is, and whether your bots are doing well compared with the same bots in comparable repositories. What each one is for, how it was built, and how we know it works." />
|
|
16
|
+
<meta name="robots" content="index, follow" />
|
|
17
|
+
<link rel="canonical" href="https://pierre-review.com/how-we-measure" />
|
|
18
|
+
<meta property="og:type" content="website" />
|
|
19
|
+
<meta property="og:site_name" content="Limn" />
|
|
20
|
+
<meta property="og:title" content="How we measure — the two models, in plain English" />
|
|
21
|
+
<meta property="og:description" content="Almost everything Limn shows you is counted, not predicted. Two questions resist counting and have a model each: how serious a review-bot comment is, and whether your bots are doing well compared with the same bots in comparable repositories. What each one is for, how it was built, and how we know it works." />
|
|
22
|
+
<meta property="og:url" content="https://pierre-review.com/how-we-measure" />
|
|
23
|
+
<meta property="og:image" content="https://pierre-review.com/og-image.png" />
|
|
24
|
+
<meta property="og:image:width" content="1200" />
|
|
25
|
+
<meta property="og:image:height" content="630" />
|
|
26
|
+
<meta property="og:image:alt" content="The Limn board showing everything waiting across a team’s repositories, ranked most actionable first." />
|
|
27
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
28
|
+
<meta name="twitter:title" content="How we measure — the two models, in plain English" />
|
|
29
|
+
<meta name="twitter:description" content="Almost everything Limn shows you is counted, not predicted. Two questions resist counting and have a model each: how serious a review-bot comment is, and whether your bots are doing well compared with the same bots in comparable repositories. What each one is for, how it was built, and how we know it works." />
|
|
30
|
+
<meta name="twitter:image" content="https://pierre-review.com/og-image.png" />
|
|
31
|
+
<meta name="twitter:image:alt" content="The Limn board showing everything waiting across a team’s repositories, ranked most actionable first." />
|
|
32
|
+
|
|
33
|
+
<!-- Favicons: the Limn mark, rendered from apps/landing/src/lib/sprites.ts by
|
|
34
|
+
`node scripts/make-favicons.mjs`. Regenerate there, never by hand. -->
|
|
35
|
+
<!-- ⚠ THE SVG MUST STAY FIRST AND KEEP ITS `type`. A tab slot is 16 CSS px — 32 device px
|
|
36
|
+
at DPR 2 — and Chrome picks ONE of these and scales it, so any pick but an exact 1:1
|
|
37
|
+
raster resamples a grid whose features are one pixel wide and reads as blur. Declared
|
|
38
|
+
this way Chrome takes the SVG and `shape-rendering: crispEdges` snaps it to the device
|
|
39
|
+
grid at every DPR. The PNGs remain for Safari < 16.4 and the big-raster surfaces. -->
|
|
40
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
41
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
|
|
42
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" />
|
|
43
|
+
<link rel="icon" type="image/png" sizes="48x48" href="/favicon-48.png" />
|
|
44
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
45
|
+
<link rel="manifest" href="/site.webmanifest" />
|
|
46
|
+
|
|
47
|
+
<!-- Structured data: helps search engines understand what Limn is.
|
|
48
|
+
LANDMINE: this block sits OUTSIDE the seo:start/end markers, so the
|
|
49
|
+
prerenderer copies it verbatim into EVERY route — /privacy and /terms ship
|
|
50
|
+
this price too. It is a second, site-wide copy of both the product name
|
|
51
|
+
and the price; when either changes it must change here as well as in
|
|
52
|
+
src/lib/routes.ts, src/lib/site.ts and src/components/feint/TierTable.tsx.
|
|
53
|
+
⚠ IT WENT STALE ONCE ALREADY: it advertised Pro at $15 and a Pro+ tier at
|
|
54
|
+
$29 for as long as those were true on a pricing page that no longer
|
|
55
|
+
exists, which is exactly the failure a second copy invites.
|
|
56
|
+
Claude Review and AI Fix are FREE and local-only — they belong in the Free
|
|
57
|
+
offer, never the Pro one (they were "Pro+" once; that tier is gone).
|
|
58
|
+
The $25 stays because it is the real LIST price and the tier table says so;
|
|
59
|
+
the free month is described in the offer text rather than by writing "0",
|
|
60
|
+
which would be a different and wrong claim about what Pro costs. -->
|
|
61
|
+
<script type="application/ld+json">
|
|
62
|
+
{
|
|
63
|
+
"@context": "https://schema.org",
|
|
64
|
+
"@graph": [
|
|
65
|
+
{
|
|
66
|
+
"@type": "Organization",
|
|
67
|
+
"@id": "https://pierre-review.com/#org",
|
|
68
|
+
"name": "Limn",
|
|
69
|
+
"url": "https://pierre-review.com/",
|
|
70
|
+
"logo": "https://pierre-review.com/icon-512.png",
|
|
71
|
+
"sameAs": ["https://github.com/alexwakeman/pierre-review"]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"@type": "WebSite",
|
|
75
|
+
"@id": "https://pierre-review.com/#site",
|
|
76
|
+
"name": "Limn",
|
|
77
|
+
"url": "https://pierre-review.com/",
|
|
78
|
+
"publisher": { "@id": "https://pierre-review.com/#org" }
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"@type": "SoftwareApplication",
|
|
82
|
+
"name": "Limn",
|
|
83
|
+
"applicationCategory": "DeveloperApplication",
|
|
84
|
+
"operatingSystem": "Web, macOS, Linux, Windows",
|
|
85
|
+
"description": "Plans your day across every repository a team works in: one ranked board of what is waiting and on whom, by rules each person sets — plus how the work moved over a sprint, and an independent grade on every AI review bot comment.",
|
|
86
|
+
"url": "https://pierre-review.com/",
|
|
87
|
+
"publisher": { "@id": "https://pierre-review.com/#org" },
|
|
88
|
+
"offers": {
|
|
89
|
+
"@type": "AggregateOffer",
|
|
90
|
+
"priceCurrency": "USD",
|
|
91
|
+
"lowPrice": "0",
|
|
92
|
+
"highPrice": "25",
|
|
93
|
+
"offerCount": "2",
|
|
94
|
+
"offers": [
|
|
95
|
+
{
|
|
96
|
+
"@type": "Offer",
|
|
97
|
+
"name": "Free",
|
|
98
|
+
"description": "The open-core product: the ranked cross-repo Pending board and every setting behind it, triaged review threads, merge and conflict resolution in place, flow metrics per workspace, an independent grade on every bot comment, and — run locally — Claude Review and AI Fix on your own Claude Code or Anthropic API key, with no charge from Limn. No repository limit, no user limit, no expiry.",
|
|
99
|
+
"price": "0",
|
|
100
|
+
"priceCurrency": "USD"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"@type": "Offer",
|
|
104
|
+
"name": "Pro",
|
|
105
|
+
"description": "The roll-up across repositories, people and periods: a forwardable report per sprint, Chronology, the per-bot keep / tune / noisy scoreboard and the peer benchmark, plus written summaries on pull requests, a read on a failed build and a written plan for the day. Claude Review and AI Fix are not part of it: they are free. Lists at $25 per user per month; currently free for a month to anyone who asks via the contact form.",
|
|
106
|
+
"price": "25",
|
|
107
|
+
"priceCurrency": "USD",
|
|
108
|
+
"priceSpecification": {
|
|
109
|
+
"@type": "UnitPriceSpecification",
|
|
110
|
+
"price": "25",
|
|
111
|
+
"priceCurrency": "USD",
|
|
112
|
+
"billingIncrement": 1,
|
|
113
|
+
"unitText": "MONTH"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
"softwareHelp": "https://github.com/alexwakeman/pierre-review"
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<!-- The three typefaces (Archivo, Newsreader, JetBrains Mono) are SELF-HOSTED:
|
|
125
|
+
the @font-face blocks live in src/index.css and the .woff2 files ship from
|
|
126
|
+
src/fonts/. They are never fetched from Google, for three independent
|
|
127
|
+
reasons — `font-src 'self'` in the landing CSP blocks fonts.gstatic.com,
|
|
128
|
+
`style-src 'self' 'unsafe-inline'` does not permit a <link> to
|
|
129
|
+
fonts.googleapis.com, and a test pins that directive so it fails CI before
|
|
130
|
+
a browser ever sees it. On top of that it is a GDPR requirement: a gstatic
|
|
131
|
+
request discloses every visitor's IP to Google before consent, and Google
|
|
132
|
+
Fonts' recommended <link ... onload="this.media='all'"> would force
|
|
133
|
+
script-src 'unsafe-inline'. Same-origin + font-display:swap keeps them off
|
|
134
|
+
the critical path with no inline handler.
|
|
135
|
+
See apps/backend/src/api/plugins/security.ts. -->
|
|
136
|
+
<script type="module" crossorigin src="/assets/index-CA3eEGXO.js"></script>
|
|
137
|
+
<link rel="stylesheet" crossorigin href="/assets/index-naQrQ6Fe.css">
|
|
138
|
+
</head>
|
|
139
|
+
<body>
|
|
140
|
+
<!-- Everything between app:start/app:end is REPLACED at build time by
|
|
141
|
+
prerender.mjs with the route's fully-rendered markup, so the page has real,
|
|
142
|
+
readable content before a single byte of JS executes — for no-JS visitors,
|
|
143
|
+
for AI agents and crawlers that do not run scripts, and as the first paint
|
|
144
|
+
for everyone else. React's createRoot() replaces it on mount exactly as it
|
|
145
|
+
replaced the splash below.
|
|
146
|
+
|
|
147
|
+
What survives here is the DEV-server fallback (prerender.mjs only rewrites
|
|
148
|
+
the built dist/): a plain wordmark on paper, so the first paint is already
|
|
149
|
+
the right colour instead of a white flash. It is set in system-ui rather
|
|
150
|
+
than Archivo because the bundled font has not loaded at this point — and it
|
|
151
|
+
carries no animation, because the site does not move. -->
|
|
152
|
+
<div id="root">
|
|
153
|
+
<div class="mx-auto min-h-screen max-w-canvas"><header class="border-b border-rule px-gutter py-[26px]"><nav aria-label="Primary" class="flex flex-wrap items-baseline justify-between gap-x-6 gap-y-4"><a href="/" aria-label="Home" class="focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink"><span class="inline-flex items-center gap-2.5 font-display font-semibold tracking-[-0.02em] text-ink text-[21px]"><svg width="22" height="18" viewBox="0 0 11 9" shape-rendering="crispEdges" aria-hidden="true" focusable="false" class="shrink-0"><rect x="0" y="0" width="6" height="1" fill="#16161A"></rect><rect x="0" y="1" width="1" height="1" fill="#16161A"></rect><rect x="2" y="1" width="2" height="1" fill="#16161A"></rect><rect x="5" y="1" width="1" height="1" fill="#16161A"></rect><rect x="0" y="2" width="6" height="1" fill="#16161A"></rect><rect x="1" y="3" width="1" height="1" fill="#16161A"></rect><rect x="3" y="4" width="7" height="1" fill="#16161A"></rect><rect x="3" y="5" width="1" height="1" fill="#16161A"></rect><rect x="9" y="5" width="1" height="1" fill="#16161A"></rect><rect x="3" y="6" width="1" height="1" fill="#16161A"></rect><rect x="5" y="6" width="3" height="1" fill="#C13A20"></rect><rect x="9" y="6" width="1" height="1" fill="#16161A"></rect><rect x="3" y="7" width="7" height="1" fill="#16161A"></rect><rect x="5" y="8" width="1" height="1" fill="#16161A"></rect></svg><span>Limn<span class="text-signal-text">.</span></span></span></a><div class="flex flex-wrap items-baseline gap-x-5 gap-y-2 font-mono text-mono-nav text-nav-idle type:gap-x-[30px]"><a href="/for-developers" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">For developers</a><a href="/for-managers" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">For managers</a><a href="/how-we-measure" aria-current="page" class="border-b-2 border-signal-fill pb-0.5 text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">How we measure</a><a href="/contact" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Contact</a><a href="/api/auth/login" class="text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Sign in</a></div></nav></header><main><header class="px-gutter pt-hero-y"><span class="block font-mono uppercase text-mono-label-wide mb-[26px] text-secondary">How we measure</span><h1 class="mb-7 max-w-[20ch] text-pretty font-display text-hero-sm font-semibold text-ink type:text-hero">Two models. One job each.</h1><p class="mb-[34px] max-w-lede text-pretty text-lede text-ink-soft">Almost everything Limn shows you is arithmetic — counted, not predicted. Two questions resist counting, and each has a model of its own built for it: how serious is this comment, and is that good compared to everybody else?</p><div class="mb-4 flex flex-wrap items-center gap-3.5"><a href="/api/auth/login" class="inline-block bg-ink px-6 py-[15px] font-display text-[16px] font-semibold text-paper hover:bg-[#08080A] transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink ">Sign in with GitHub</a><a href="/for-managers" class="inline-block border-b border-ink px-1.5 py-[15px] font-display text-[16px] font-medium text-ink hover:text-signal-text transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink ">See what it produces →</a></div><p class="mb-11 max-w-reassure font-mono text-mono-nav text-secondary">Both are built and run by us. Neither sends your code or your comments anywhere.</p></header><section class="px-gutter py-section-y border-t border-ink "><div class="grid items-start gap-grid-gutter rail:grid-cols-rail-1 "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]"><span class="rail:block">01<span class="rail:hidden"> / </span></span>The grader</div><div><h2 class="mb-6 max-w-[30ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2">How serious is this comment?</h2><div class="max-w-[68ch]"><p class="mb-6">A review bot leaves forty comments on a pull request. Two of them will change whether the code works. The rest are preferences, tidy-ups and things somebody already knew. Nothing in the comments themselves tells you which is which — and the vendor’s own labels are marking their own homework.</p><p class="mb-6">So the first model reads each comment and says how serious it is: a nit, something minor, something major, or something critical. It is the same judgement a senior engineer makes in a second and cannot make four hundred times a week.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">How it was built</h3><p class="mb-6">We collected millions of real review-bot comments from public repositories on GitHub — every major vendor, across projects of every size — and taught the model on those rather than on anything invented. Under the hood it is a fine-tuned ModernBERT, which is a language model small enough to run on the ordinary processor in a laptop or a server: no graphics card, no cloud, nothing sent out, and nothing metered.</p><p class="mb-6">It does one thing, and that is the point. It is not a general assistant being asked nicely to have an opinion; it was trained for this single question and does nothing else.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">How we know it works</h3><p class="mb-6">We took a batch of real bot comments, hid every label they already carried, and had them graded from scratch by a human expert. Then we compared.</p><p class="mb-6">The model chose the same severity as the expert <strong>seven times in ten</strong>. To know whether that is good, we needed something to compare it against — so we checked how often two human experts agreed with <em>each other</em> on the same comments. Also seven times in ten. The model is reading these comments about as well as the question can be answered.</p><p>On those same comments, CodeRabbit’s own severity labels matched the expert fewer than five times in ten. That gap is the whole reason we grade independently instead of passing the vendor’s label through.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">What it feeds</h3><ul class="flex flex-col gap-3.5"><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>The severity badge on every bot comment, wherever you read it.</span></li><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>The “needs a look” counts on a pull request, so a wall of forty threads has a top.</span></li><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>The keep / tune / noisy verdict on each vendor, and the over-calling line beside it.</span></li></ul><p class="mt-7 flex items-baseline gap-3.5 border-t border-rule pt-4 font-mono text-mono-nav text-secondary"><span aria-hidden="true" class="text-signal-text">—</span><span><span class="text-ink">Free on every tier</span> · the grade, everywhere it appears. The ruler is never the paid part.</span></p></div></div></div><div class="mt-10"><figure class="border border-rule"><figcaption class="flex items-center justify-between border-b border-rule px-4 py-[11px] font-mono text-mono-caption text-secondary"><span>limn · the grade, and the disagreement</span><button type="button" class="text-signal-text transition-colors duration-hover ease-standard hover:text-ink focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Enlarge</button></figcaption><button type="button" aria-label="Enlarge screenshot: The model's grades on real bot comments, beside a grid showing where the model and the vendor's own badge agreed and where they did not" class="block w-full cursor-zoom-in focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ink"><span style="height:640px" class="block w-full overflow-hidden bg-paper"><img src="/shots/severity-findings.png" alt="The model's grades on real bot comments, beside a grid showing where the model and the vendor's own badge agreed and where they did not" loading="lazy" decoding="async" class="h-full w-full object-cover object-top"/></span></button></figure></div></section><section class="px-gutter py-section-y border-t border-rule bg-paper-alt "><div class="grid items-start gap-grid-gutter rail:grid-cols-rail-1 "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]"><span class="rail:block">02<span class="rail:hidden"> / </span></span>The benchmark</div><div><h2 class="mb-6 max-w-[30ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2">And is that good, or normal?</h2><div class="max-w-[68ch]"><p class="mb-6">Say your team acts on half of what CodeRabbit tells it. Is that good? There is no way to know from inside your own repositories. Half might be excellent. Half might mean the bot is badly configured and everyone has quietly started ignoring it.</p><p class="mb-6">The second model answers that by building the missing half of the comparison: what the same bot does in <em>other people’s</em> repositories.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">How it was built</h3><p class="mb-6">Every public action on GitHub is published as a public event stream. We read it to find repositories running each review vendor, drew a sample of <strong>2,204 of them</strong> across seven vendors, and then visited each one to collect what actually happened: how much the bot said, how much of it people replied to, resolved, or left sitting.</p><p class="mb-6">Repositories are then grouped with others of a similar size and pace, because a quiet internal service and a busy monorepo are not the same test. Your repository is placed against its own group, never against the average of all of them.</p><p>Which repositories to sample was decided in code, with a fixed seed and a written record of every choice, so the cohort is reproducible rather than hand-picked. It is rebuilt as the corpus grows, and the page tells you how old the current one is.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">How we know it works</h3><p class="mb-6">By refusing. Some groups have plenty of comparable repositories behind them and some have a handful, and a comparison drawn from a handful is a number that will move on its own next month. Where a group is too thin, the panel says so in words instead of printing a figure.</p><p>There are fourteen different ways it can decline to answer, and each one names which comparison it is declining and why. Every figure it <em>does</em> print carries how many repositories are behind it and which group they were.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">What it feeds</h3><ul class="flex flex-col gap-3.5"><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>Where each of your bots sits against the same bot running in comparable repositories.</span></li><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>What a typical team gets out of that vendor, so your own rate has something to mean.</span></li><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>A written refusal wherever the comparison would not be honest.</span></li></ul><p class="mt-7 flex items-baseline gap-3.5 border-t border-rule pt-4 font-mono text-mono-nav text-secondary"><span aria-hidden="true" class="text-signal-text">—</span><span><span class="text-ink">Pro</span> · the comparison. The independent grade underneath it stays free.</span></p></div></div></div><div class="mt-10"><figure class="border border-rule-strong"><figcaption class="flex items-center justify-between border-b border-rule px-4 py-[11px] font-mono text-mono-caption text-secondary"><span>limn · the comparison</span><button type="button" class="text-signal-text transition-colors duration-hover ease-standard hover:text-ink focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Enlarge</button></figcaption><button type="button" aria-label="Enlarge screenshot: The peer benchmark placing each vendor against comparable repositories, with written refusals where the comparison would not be honest" class="block w-full cursor-zoom-in focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ink"><span style="height:620px" class="block w-full overflow-hidden bg-paper"><img src="/shots/benchmark.png" alt="The peer benchmark placing each vendor against comparable repositories, with written refusals where the comparison would not be honest" loading="lazy" decoding="async" class="h-full w-full object-cover object-top"/></span></button></figure></div></section><section class="px-gutter py-section-y border-t border-ink "><div class="grid items-start gap-grid-gutter rail:grid-cols-rail "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]"><span class="rail:block">03<span class="rail:hidden"> / </span></span>And nowhere else</div><div class="rail:col-span-2"><h2 class="mb-[30px] max-w-[32ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2-major">Everything else here is counting, and counting is better at it.</h2><div class="grid gap-grid-gutter rail:grid-cols-2"><div><p class="mb-6">Two models, on two questions, and that is the end of the list. How many pull requests merged, how long they waited, whose turn it is, what is stalled, what a change touches, who was holding it — all of that is arithmetic over your own data. It is exact, it is reproducible, and you can check it.</p><p>A model would make every one of those <em>worse</em>. It would turn a number you can verify into an estimate you have to trust, and estimates are how dashboards stop being believed.</p></div><div><p class="mb-6">There is a third place Limn uses AI, and it is separate from both models on this page: writing. Short summaries — a paragraph on a long pull request, a read on a red build, the reason beside an item in your queue — and, on your own machine, Claude’s review of a pull request and its fix for the comments you pick. Those are language, not measurement, and they are clearly marked wherever they appear.</p><p>No number on any screen comes from them, and nothing in the product acts on a model’s output on its own. A grade changes what a list is sorted by. It never resolves a thread, merges a pull request or closes anything. A review is posted, and a fix pushed, only when you press the button.</p></div></div></div></div></section><section id="pricing" class="px-gutter border-t border-ink py-14"><div class="grid items-start gap-grid-gutter rail:grid-cols-rail-1 "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]">Free vs Pro</div><div><h2 class="mb-6 max-w-[30ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2">Free answers one pull request. Pro answers the fortnight.</h2><p class="mb-10 max-w-[62ch] text-pretty text-lede text-ink-soft">Limn is open core. The free tier is the product, not a trial — it has no repository limit, no user limit and no expiry, and every action you take on a pull request lives in it. Pro is what happens when you need the same truth one grain up: across repositories, across people, across a period.</p><div class="border-t border-ink"><div class="hidden gap-grid-gutter border-b border-rule-strong py-3 rail:grid rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><span class="block font-mono uppercase text-mono-label text-secondary">Question</span><span class="block font-mono uppercase text-mono-label text-secondary">Free · open core</span><span class="block font-mono uppercase text-mono-label text-signal-text">Pro · free for a month</span></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">What should I work on today?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Pending: everything waiting on you or your workspace, across every repository, in six ranked tabs — the top five of each marked Do next.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Plan my day: a written headline, a line on what can wait, and a reason on each planned card. The order stays the free one.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Can I change what counts as my turn?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Yes. Switch card types on or off, move your own work into My turn, set the order, choose how every tab ranks, and mute a repository or a workspace.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does. Your rules are never the paid part.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">What happened on this pull request?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Every thread triaged — untouched, replied, likely addressed, resolved. Blast radius, blockers, merge verdict.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">A short written summary, a read on what a red build means, and a check on whether a comment was really addressed.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Can I act without leaving?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Reply, resolve, approve, merge, merge-when-ready, update from trunk, resolve conflicts hunk by hunk.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does. Acting on a pull request is never the paid part.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Can Claude review or fix this?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Yes, on your machine, on your own Claude: a review you tick and post, a chat on it, and a fix that is pushed only when you click.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does. The agents are never the paid part.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Which review bots are worth their seat?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Detect every bot, name it, set its role and record what it costs — and an independent severity grade on every comment it leaves.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">The per-bot scoreboard: keep / tune / noisy, dollars per comment your team acted on, over-calling as a weekly line.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">How does that compare to other teams?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">—</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Your bots placed against a 2,204-repository cohort, with a written refusal wherever the cohort is too thin to answer.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">How is the team doing?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Flow metrics for the workspace, activity and reach by repository, open pull requests and trunk health.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">A stored report per sprint or month, compared like-for-like against the last one, with the coverage stated.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Is a repository about to bite us?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Default-branch health across every repository, the checks failing on it, and the pull request that landed its latest commit.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does. Trunk health is never the paid part — it is the thing you need at the worst moment.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Where is the time actually going?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">—</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Chronology: every open hour attributed to a reviewer, an author, or waiting to land. Nobody is named.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">What do I take into a one-to-one?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">—</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">A report with a section per person you pick. Preparation, not a ranking — there is no leaderboard anywhere in it.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Can I keep the noise down?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Bots hidden by default, notifications only for work that is yours, and a mute per repository or per workspace.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does, plus a Slack digest per workspace if you would rather read it there.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Where does it run?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">npx limn-review on your machine, or the hosted service. No repository limit, no user limit. Claude review and fix run on your machine only.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">The same two places. Pro unlocks on whichever one you already use.</p></div></div></div><p class="mt-6 max-w-[62ch] font-mono text-mono-caption text-secondary">Pro lists at $25 per user, and is free for a month to anyone who asks for it. A user is someone who signs in — bots never count, and there is no per-repository charge.</p><p class="mt-2 max-w-[62ch] font-mono text-mono-caption text-secondary">Review and fix run locally only, on your own Claude Code or Anthropic API key. Limn stores no key and charges nothing for it.</p><div class="mt-10"><figure class="border border-rule"><figcaption class="flex items-center justify-between border-b border-rule px-4 py-[11px] font-mono text-mono-caption text-secondary"><span>limn · reports, free account</span><button type="button" class="text-signal-text transition-colors duration-hover ease-standard hover:text-ink focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Enlarge</button></figcaption><button type="button" aria-label="Enlarge screenshot: The Reports pane on a free account: the flow metrics render in full, and the paid period-report panel below them is listed, badged and locked rather than hidden" class="block w-full cursor-zoom-in focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ink"><span style="height:460px" class="block w-full overflow-hidden bg-paper"><img src="/shots/free-reports.png" alt="The Reports pane on a free account: the flow metrics render in full, and the paid period-report panel below them is listed, badged and locked rather than hidden" loading="lazy" decoding="async" class="h-full w-full object-cover object-top"/></span></button></figure><p class="mt-[18px] max-w-caption text-list text-muted">What a free account actually sees. The paid panes are listed and locked rather than hidden, so you can tell what you are not buying before you buy it — and the free metrics above them are the ones that moved here off another tab.</p></div></div></div></section><section class="px-gutter py-section-y-lg "><div class="grid items-start gap-grid-gutter rail:grid-cols-rail-1 "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]">Start</div><div><h2 class="mb-5 max-w-[24ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2-major">Start free. Every repository, nothing missed.</h2><p class="mb-9 max-w-[56ch] text-pretty text-lede text-ink-soft">Sign in with GitHub and the first repositories are on screen in a couple of minutes, or run the whole free tier on your own machine and keep the data there. For Pro, send a message — it is free for a month, for asking.</p><div class="mb-5 flex flex-wrap items-center gap-3.5"><a href="/api/auth/login" class="inline-block bg-ink px-6 py-[15px] font-display text-[16px] font-semibold text-paper hover:bg-[#08080A] transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink ">Sign in with GitHub</a><a href="/contact?topic=pro" class="inline-block bg-signal-text px-6 py-[15px] font-display text-[16px] font-semibold text-paper hover:bg-[#A6301A] transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink ">Ask for a free month of Pro</a></div><p class="max-w-reassure font-mono text-mono-nav text-secondary">Card payments are not switched on yet, so Pro is not sold from this page — it is given, a month at a time, to anyone who asks. No card, nothing to cancel. Or run the free tier locally: <span class="text-ink">npx limn-review</span></p></div></div></section></main><footer class="border-t border-rule px-gutter py-[26px] font-mono text-mono-caption text-secondary"><div class="flex flex-wrap items-baseline justify-between gap-x-8 gap-y-3"><span>© 2026 Limn. Built for sprint situational awareness.</span><span class="flex flex-wrap items-baseline gap-x-5 gap-y-2"><a href="/for-developers" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">For developers</a><a href="/for-managers" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">For managers</a><a href="/how-we-measure" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">How we measure</a><a href="/contact" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Contact</a><a href="https://github.com/alexwakeman/pierre-review" target="_blank" rel="noreferrer noopener" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">GitHub</a><a href="/privacy" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Privacy</a><a href="/cookies" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Cookies</a><a href="/terms" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Terms</a></span></div><p class="mt-4 max-w-caption">Limn is a desktop experience today. A phone-friendly build is planned.</p></footer></div>
|
|
154
|
+
</div>
|
|
155
|
+
</body>
|
|
156
|
+
</html>
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="UTF-8" />
|
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
|
6
|
+
<meta name="theme-color" content="#FAFAF8" />
|
|
7
|
+
|
|
8
|
+
<!-- Primary SEO. Everything between the seo:start/seo:end markers is REPLACED
|
|
9
|
+
per route at build time by prerender.mjs, from the ROUTE_SEO table in
|
|
10
|
+
src/lib/routes.ts — so /pricing ships its own title, description and
|
|
11
|
+
canonical in the HTML rather than inheriting the home page's. What is
|
|
12
|
+
written here is the home-page copy and the dev-server fallback; keep the
|
|
13
|
+
markers, and keep the copy in sync with ROUTE_SEO['/']. -->
|
|
14
|
+
<title>How we measure — the two models, in plain English</title>
|
|
15
|
+
<meta name="description" content="Almost everything Limn shows you is counted, not predicted. Two questions resist counting and have a model each: how serious a review-bot comment is, and whether your bots are doing well compared with the same bots in comparable repositories. What each one is for, how it was built, and how we know it works." />
|
|
16
|
+
<meta name="robots" content="index, follow" />
|
|
17
|
+
<link rel="canonical" href="https://pierre-review.com/how-we-measure" />
|
|
18
|
+
<meta property="og:type" content="website" />
|
|
19
|
+
<meta property="og:site_name" content="Limn" />
|
|
20
|
+
<meta property="og:title" content="How we measure — the two models, in plain English" />
|
|
21
|
+
<meta property="og:description" content="Almost everything Limn shows you is counted, not predicted. Two questions resist counting and have a model each: how serious a review-bot comment is, and whether your bots are doing well compared with the same bots in comparable repositories. What each one is for, how it was built, and how we know it works." />
|
|
22
|
+
<meta property="og:url" content="https://pierre-review.com/how-we-measure" />
|
|
23
|
+
<meta property="og:image" content="https://pierre-review.com/og-image.png" />
|
|
24
|
+
<meta property="og:image:width" content="1200" />
|
|
25
|
+
<meta property="og:image:height" content="630" />
|
|
26
|
+
<meta property="og:image:alt" content="The Limn board showing everything waiting across a team’s repositories, ranked most actionable first." />
|
|
27
|
+
<meta name="twitter:card" content="summary_large_image" />
|
|
28
|
+
<meta name="twitter:title" content="How we measure — the two models, in plain English" />
|
|
29
|
+
<meta name="twitter:description" content="Almost everything Limn shows you is counted, not predicted. Two questions resist counting and have a model each: how serious a review-bot comment is, and whether your bots are doing well compared with the same bots in comparable repositories. What each one is for, how it was built, and how we know it works." />
|
|
30
|
+
<meta name="twitter:image" content="https://pierre-review.com/og-image.png" />
|
|
31
|
+
<meta name="twitter:image:alt" content="The Limn board showing everything waiting across a team’s repositories, ranked most actionable first." />
|
|
32
|
+
|
|
33
|
+
<!-- Favicons: the Limn mark, rendered from apps/landing/src/lib/sprites.ts by
|
|
34
|
+
`node scripts/make-favicons.mjs`. Regenerate there, never by hand. -->
|
|
35
|
+
<!-- ⚠ THE SVG MUST STAY FIRST AND KEEP ITS `type`. A tab slot is 16 CSS px — 32 device px
|
|
36
|
+
at DPR 2 — and Chrome picks ONE of these and scales it, so any pick but an exact 1:1
|
|
37
|
+
raster resamples a grid whose features are one pixel wide and reads as blur. Declared
|
|
38
|
+
this way Chrome takes the SVG and `shape-rendering: crispEdges` snaps it to the device
|
|
39
|
+
grid at every DPR. The PNGs remain for Safari < 16.4 and the big-raster surfaces. -->
|
|
40
|
+
<link rel="icon" href="/favicon.svg" type="image/svg+xml" />
|
|
41
|
+
<link rel="icon" type="image/png" sizes="32x32" href="/favicon-32.png" />
|
|
42
|
+
<link rel="icon" type="image/png" sizes="16x16" href="/favicon-16.png" />
|
|
43
|
+
<link rel="icon" type="image/png" sizes="48x48" href="/favicon-48.png" />
|
|
44
|
+
<link rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png" />
|
|
45
|
+
<link rel="manifest" href="/site.webmanifest" />
|
|
46
|
+
|
|
47
|
+
<!-- Structured data: helps search engines understand what Limn is.
|
|
48
|
+
LANDMINE: this block sits OUTSIDE the seo:start/end markers, so the
|
|
49
|
+
prerenderer copies it verbatim into EVERY route — /privacy and /terms ship
|
|
50
|
+
this price too. It is a second, site-wide copy of both the product name
|
|
51
|
+
and the price; when either changes it must change here as well as in
|
|
52
|
+
src/lib/routes.ts, src/lib/site.ts and src/components/feint/TierTable.tsx.
|
|
53
|
+
⚠ IT WENT STALE ONCE ALREADY: it advertised Pro at $15 and a Pro+ tier at
|
|
54
|
+
$29 for as long as those were true on a pricing page that no longer
|
|
55
|
+
exists, which is exactly the failure a second copy invites.
|
|
56
|
+
Claude Review and AI Fix are FREE and local-only — they belong in the Free
|
|
57
|
+
offer, never the Pro one (they were "Pro+" once; that tier is gone).
|
|
58
|
+
The $25 stays because it is the real LIST price and the tier table says so;
|
|
59
|
+
the free month is described in the offer text rather than by writing "0",
|
|
60
|
+
which would be a different and wrong claim about what Pro costs. -->
|
|
61
|
+
<script type="application/ld+json">
|
|
62
|
+
{
|
|
63
|
+
"@context": "https://schema.org",
|
|
64
|
+
"@graph": [
|
|
65
|
+
{
|
|
66
|
+
"@type": "Organization",
|
|
67
|
+
"@id": "https://pierre-review.com/#org",
|
|
68
|
+
"name": "Limn",
|
|
69
|
+
"url": "https://pierre-review.com/",
|
|
70
|
+
"logo": "https://pierre-review.com/icon-512.png",
|
|
71
|
+
"sameAs": ["https://github.com/alexwakeman/pierre-review"]
|
|
72
|
+
},
|
|
73
|
+
{
|
|
74
|
+
"@type": "WebSite",
|
|
75
|
+
"@id": "https://pierre-review.com/#site",
|
|
76
|
+
"name": "Limn",
|
|
77
|
+
"url": "https://pierre-review.com/",
|
|
78
|
+
"publisher": { "@id": "https://pierre-review.com/#org" }
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
"@type": "SoftwareApplication",
|
|
82
|
+
"name": "Limn",
|
|
83
|
+
"applicationCategory": "DeveloperApplication",
|
|
84
|
+
"operatingSystem": "Web, macOS, Linux, Windows",
|
|
85
|
+
"description": "Plans your day across every repository a team works in: one ranked board of what is waiting and on whom, by rules each person sets — plus how the work moved over a sprint, and an independent grade on every AI review bot comment.",
|
|
86
|
+
"url": "https://pierre-review.com/",
|
|
87
|
+
"publisher": { "@id": "https://pierre-review.com/#org" },
|
|
88
|
+
"offers": {
|
|
89
|
+
"@type": "AggregateOffer",
|
|
90
|
+
"priceCurrency": "USD",
|
|
91
|
+
"lowPrice": "0",
|
|
92
|
+
"highPrice": "25",
|
|
93
|
+
"offerCount": "2",
|
|
94
|
+
"offers": [
|
|
95
|
+
{
|
|
96
|
+
"@type": "Offer",
|
|
97
|
+
"name": "Free",
|
|
98
|
+
"description": "The open-core product: the ranked cross-repo Pending board and every setting behind it, triaged review threads, merge and conflict resolution in place, flow metrics per workspace, an independent grade on every bot comment, and — run locally — Claude Review and AI Fix on your own Claude Code or Anthropic API key, with no charge from Limn. No repository limit, no user limit, no expiry.",
|
|
99
|
+
"price": "0",
|
|
100
|
+
"priceCurrency": "USD"
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
"@type": "Offer",
|
|
104
|
+
"name": "Pro",
|
|
105
|
+
"description": "The roll-up across repositories, people and periods: a forwardable report per sprint, Chronology, the per-bot keep / tune / noisy scoreboard and the peer benchmark, plus written summaries on pull requests, a read on a failed build and a written plan for the day. Claude Review and AI Fix are not part of it: they are free. Lists at $25 per user per month; currently free for a month to anyone who asks via the contact form.",
|
|
106
|
+
"price": "25",
|
|
107
|
+
"priceCurrency": "USD",
|
|
108
|
+
"priceSpecification": {
|
|
109
|
+
"@type": "UnitPriceSpecification",
|
|
110
|
+
"price": "25",
|
|
111
|
+
"priceCurrency": "USD",
|
|
112
|
+
"billingIncrement": 1,
|
|
113
|
+
"unitText": "MONTH"
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
]
|
|
117
|
+
},
|
|
118
|
+
"softwareHelp": "https://github.com/alexwakeman/pierre-review"
|
|
119
|
+
}
|
|
120
|
+
]
|
|
121
|
+
}
|
|
122
|
+
</script>
|
|
123
|
+
|
|
124
|
+
<!-- The three typefaces (Archivo, Newsreader, JetBrains Mono) are SELF-HOSTED:
|
|
125
|
+
the @font-face blocks live in src/index.css and the .woff2 files ship from
|
|
126
|
+
src/fonts/. They are never fetched from Google, for three independent
|
|
127
|
+
reasons — `font-src 'self'` in the landing CSP blocks fonts.gstatic.com,
|
|
128
|
+
`style-src 'self' 'unsafe-inline'` does not permit a <link> to
|
|
129
|
+
fonts.googleapis.com, and a test pins that directive so it fails CI before
|
|
130
|
+
a browser ever sees it. On top of that it is a GDPR requirement: a gstatic
|
|
131
|
+
request discloses every visitor's IP to Google before consent, and Google
|
|
132
|
+
Fonts' recommended <link ... onload="this.media='all'"> would force
|
|
133
|
+
script-src 'unsafe-inline'. Same-origin + font-display:swap keeps them off
|
|
134
|
+
the critical path with no inline handler.
|
|
135
|
+
See apps/backend/src/api/plugins/security.ts. -->
|
|
136
|
+
<script type="module" crossorigin src="/assets/index-CA3eEGXO.js"></script>
|
|
137
|
+
<link rel="stylesheet" crossorigin href="/assets/index-naQrQ6Fe.css">
|
|
138
|
+
</head>
|
|
139
|
+
<body>
|
|
140
|
+
<!-- Everything between app:start/app:end is REPLACED at build time by
|
|
141
|
+
prerender.mjs with the route's fully-rendered markup, so the page has real,
|
|
142
|
+
readable content before a single byte of JS executes — for no-JS visitors,
|
|
143
|
+
for AI agents and crawlers that do not run scripts, and as the first paint
|
|
144
|
+
for everyone else. React's createRoot() replaces it on mount exactly as it
|
|
145
|
+
replaced the splash below.
|
|
146
|
+
|
|
147
|
+
What survives here is the DEV-server fallback (prerender.mjs only rewrites
|
|
148
|
+
the built dist/): a plain wordmark on paper, so the first paint is already
|
|
149
|
+
the right colour instead of a white flash. It is set in system-ui rather
|
|
150
|
+
than Archivo because the bundled font has not loaded at this point — and it
|
|
151
|
+
carries no animation, because the site does not move. -->
|
|
152
|
+
<div id="root">
|
|
153
|
+
<div class="mx-auto min-h-screen max-w-canvas"><header class="border-b border-rule px-gutter py-[26px]"><nav aria-label="Primary" class="flex flex-wrap items-baseline justify-between gap-x-6 gap-y-4"><a href="/" aria-label="Home" class="focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink"><span class="inline-flex items-center gap-2.5 font-display font-semibold tracking-[-0.02em] text-ink text-[21px]"><svg width="22" height="18" viewBox="0 0 11 9" shape-rendering="crispEdges" aria-hidden="true" focusable="false" class="shrink-0"><rect x="0" y="0" width="6" height="1" fill="#16161A"></rect><rect x="0" y="1" width="1" height="1" fill="#16161A"></rect><rect x="2" y="1" width="2" height="1" fill="#16161A"></rect><rect x="5" y="1" width="1" height="1" fill="#16161A"></rect><rect x="0" y="2" width="6" height="1" fill="#16161A"></rect><rect x="1" y="3" width="1" height="1" fill="#16161A"></rect><rect x="3" y="4" width="7" height="1" fill="#16161A"></rect><rect x="3" y="5" width="1" height="1" fill="#16161A"></rect><rect x="9" y="5" width="1" height="1" fill="#16161A"></rect><rect x="3" y="6" width="1" height="1" fill="#16161A"></rect><rect x="5" y="6" width="3" height="1" fill="#C13A20"></rect><rect x="9" y="6" width="1" height="1" fill="#16161A"></rect><rect x="3" y="7" width="7" height="1" fill="#16161A"></rect><rect x="5" y="8" width="1" height="1" fill="#16161A"></rect></svg><span>Limn<span class="text-signal-text">.</span></span></span></a><div class="flex flex-wrap items-baseline gap-x-5 gap-y-2 font-mono text-mono-nav text-nav-idle type:gap-x-[30px]"><a href="/for-developers" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">For developers</a><a href="/for-managers" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">For managers</a><a href="/how-we-measure" aria-current="page" class="border-b-2 border-signal-fill pb-0.5 text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">How we measure</a><a href="/contact" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Contact</a><a href="/api/auth/login" class="text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Sign in</a></div></nav></header><main><header class="px-gutter pt-hero-y"><span class="block font-mono uppercase text-mono-label-wide mb-[26px] text-secondary">How we measure</span><h1 class="mb-7 max-w-[20ch] text-pretty font-display text-hero-sm font-semibold text-ink type:text-hero">Two models. One job each.</h1><p class="mb-[34px] max-w-lede text-pretty text-lede text-ink-soft">Almost everything Limn shows you is arithmetic — counted, not predicted. Two questions resist counting, and each has a model of its own built for it: how serious is this comment, and is that good compared to everybody else?</p><div class="mb-4 flex flex-wrap items-center gap-3.5"><a href="/api/auth/login" class="inline-block bg-ink px-6 py-[15px] font-display text-[16px] font-semibold text-paper hover:bg-[#08080A] transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink ">Sign in with GitHub</a><a href="/for-managers" class="inline-block border-b border-ink px-1.5 py-[15px] font-display text-[16px] font-medium text-ink hover:text-signal-text transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink ">See what it produces →</a></div><p class="mb-11 max-w-reassure font-mono text-mono-nav text-secondary">Both are built and run by us. Neither sends your code or your comments anywhere.</p></header><section class="px-gutter py-section-y border-t border-ink "><div class="grid items-start gap-grid-gutter rail:grid-cols-rail-1 "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]"><span class="rail:block">01<span class="rail:hidden"> / </span></span>The grader</div><div><h2 class="mb-6 max-w-[30ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2">How serious is this comment?</h2><div class="max-w-[68ch]"><p class="mb-6">A review bot leaves forty comments on a pull request. Two of them will change whether the code works. The rest are preferences, tidy-ups and things somebody already knew. Nothing in the comments themselves tells you which is which — and the vendor’s own labels are marking their own homework.</p><p class="mb-6">So the first model reads each comment and says how serious it is: a nit, something minor, something major, or something critical. It is the same judgement a senior engineer makes in a second and cannot make four hundred times a week.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">How it was built</h3><p class="mb-6">We collected millions of real review-bot comments from public repositories on GitHub — every major vendor, across projects of every size — and taught the model on those rather than on anything invented. Under the hood it is a fine-tuned ModernBERT, which is a language model small enough to run on the ordinary processor in a laptop or a server: no graphics card, no cloud, nothing sent out, and nothing metered.</p><p class="mb-6">It does one thing, and that is the point. It is not a general assistant being asked nicely to have an opinion; it was trained for this single question and does nothing else.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">How we know it works</h3><p class="mb-6">We took a batch of real bot comments, hid every label they already carried, and had them graded from scratch by a human expert. Then we compared.</p><p class="mb-6">The model chose the same severity as the expert <strong>seven times in ten</strong>. To know whether that is good, we needed something to compare it against — so we checked how often two human experts agreed with <em>each other</em> on the same comments. Also seven times in ten. The model is reading these comments about as well as the question can be answered.</p><p>On those same comments, CodeRabbit’s own severity labels matched the expert fewer than five times in ten. That gap is the whole reason we grade independently instead of passing the vendor’s label through.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">What it feeds</h3><ul class="flex flex-col gap-3.5"><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>The severity badge on every bot comment, wherever you read it.</span></li><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>The “needs a look” counts on a pull request, so a wall of forty threads has a top.</span></li><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>The keep / tune / noisy verdict on each vendor, and the over-calling line beside it.</span></li></ul><p class="mt-7 flex items-baseline gap-3.5 border-t border-rule pt-4 font-mono text-mono-nav text-secondary"><span aria-hidden="true" class="text-signal-text">—</span><span><span class="text-ink">Free on every tier</span> · the grade, everywhere it appears. The ruler is never the paid part.</span></p></div></div></div><div class="mt-10"><figure class="border border-rule"><figcaption class="flex items-center justify-between border-b border-rule px-4 py-[11px] font-mono text-mono-caption text-secondary"><span>limn · the grade, and the disagreement</span><button type="button" class="text-signal-text transition-colors duration-hover ease-standard hover:text-ink focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Enlarge</button></figcaption><button type="button" aria-label="Enlarge screenshot: The model's grades on real bot comments, beside a grid showing where the model and the vendor's own badge agreed and where they did not" class="block w-full cursor-zoom-in focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ink"><span style="height:640px" class="block w-full overflow-hidden bg-paper"><img src="/shots/severity-findings.png" alt="The model's grades on real bot comments, beside a grid showing where the model and the vendor's own badge agreed and where they did not" loading="lazy" decoding="async" class="h-full w-full object-cover object-top"/></span></button></figure></div></section><section class="px-gutter py-section-y border-t border-rule bg-paper-alt "><div class="grid items-start gap-grid-gutter rail:grid-cols-rail-1 "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]"><span class="rail:block">02<span class="rail:hidden"> / </span></span>The benchmark</div><div><h2 class="mb-6 max-w-[30ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2">And is that good, or normal?</h2><div class="max-w-[68ch]"><p class="mb-6">Say your team acts on half of what CodeRabbit tells it. Is that good? There is no way to know from inside your own repositories. Half might be excellent. Half might mean the bot is badly configured and everyone has quietly started ignoring it.</p><p class="mb-6">The second model answers that by building the missing half of the comparison: what the same bot does in <em>other people’s</em> repositories.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">How it was built</h3><p class="mb-6">Every public action on GitHub is published as a public event stream. We read it to find repositories running each review vendor, drew a sample of <strong>2,204 of them</strong> across seven vendors, and then visited each one to collect what actually happened: how much the bot said, how much of it people replied to, resolved, or left sitting.</p><p class="mb-6">Repositories are then grouped with others of a similar size and pace, because a quiet internal service and a busy monorepo are not the same test. Your repository is placed against its own group, never against the average of all of them.</p><p>Which repositories to sample was decided in code, with a fixed seed and a written record of every choice, so the cohort is reproducible rather than hand-picked. It is rebuilt as the corpus grows, and the page tells you how old the current one is.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">How we know it works</h3><p class="mb-6">By refusing. Some groups have plenty of comparable repositories behind them and some have a handful, and a comparison drawn from a handful is a number that will move on its own next month. Where a group is too thin, the panel says so in words instead of printing a figure.</p><p>There are fourteen different ways it can decline to answer, and each one names which comparison it is declining and why. Every figure it <em>does</em> print carries how many repositories are behind it and which group they were.</p><h3 class="mb-3 mt-10 font-display text-h4 font-semibold text-ink">What it feeds</h3><ul class="flex flex-col gap-3.5"><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>Where each of your bots sits against the same bot running in comparable repositories.</span></li><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>What a typical team gets out of that vendor, so your own rate has something to mean.</span></li><li class="flex gap-3.5 text-body-sm"><span aria-hidden="true" class="pt-1.5 font-mono text-mono-caption text-signal-text">—</span><span>A written refusal wherever the comparison would not be honest.</span></li></ul><p class="mt-7 flex items-baseline gap-3.5 border-t border-rule pt-4 font-mono text-mono-nav text-secondary"><span aria-hidden="true" class="text-signal-text">—</span><span><span class="text-ink">Pro</span> · the comparison. The independent grade underneath it stays free.</span></p></div></div></div><div class="mt-10"><figure class="border border-rule-strong"><figcaption class="flex items-center justify-between border-b border-rule px-4 py-[11px] font-mono text-mono-caption text-secondary"><span>limn · the comparison</span><button type="button" class="text-signal-text transition-colors duration-hover ease-standard hover:text-ink focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Enlarge</button></figcaption><button type="button" aria-label="Enlarge screenshot: The peer benchmark placing each vendor against comparable repositories, with written refusals where the comparison would not be honest" class="block w-full cursor-zoom-in focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ink"><span style="height:620px" class="block w-full overflow-hidden bg-paper"><img src="/shots/benchmark.png" alt="The peer benchmark placing each vendor against comparable repositories, with written refusals where the comparison would not be honest" loading="lazy" decoding="async" class="h-full w-full object-cover object-top"/></span></button></figure></div></section><section class="px-gutter py-section-y border-t border-ink "><div class="grid items-start gap-grid-gutter rail:grid-cols-rail "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]"><span class="rail:block">03<span class="rail:hidden"> / </span></span>And nowhere else</div><div class="rail:col-span-2"><h2 class="mb-[30px] max-w-[32ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2-major">Everything else here is counting, and counting is better at it.</h2><div class="grid gap-grid-gutter rail:grid-cols-2"><div><p class="mb-6">Two models, on two questions, and that is the end of the list. How many pull requests merged, how long they waited, whose turn it is, what is stalled, what a change touches, who was holding it — all of that is arithmetic over your own data. It is exact, it is reproducible, and you can check it.</p><p>A model would make every one of those <em>worse</em>. It would turn a number you can verify into an estimate you have to trust, and estimates are how dashboards stop being believed.</p></div><div><p class="mb-6">There is a third place Limn uses AI, and it is separate from both models on this page: writing. Short summaries — a paragraph on a long pull request, a read on a red build, the reason beside an item in your queue — and, on your own machine, Claude’s review of a pull request and its fix for the comments you pick. Those are language, not measurement, and they are clearly marked wherever they appear.</p><p>No number on any screen comes from them, and nothing in the product acts on a model’s output on its own. A grade changes what a list is sorted by. It never resolves a thread, merges a pull request or closes anything. A review is posted, and a fix pushed, only when you press the button.</p></div></div></div></div></section><section id="pricing" class="px-gutter border-t border-ink py-14"><div class="grid items-start gap-grid-gutter rail:grid-cols-rail-1 "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]">Free vs Pro</div><div><h2 class="mb-6 max-w-[30ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2">Free answers one pull request. Pro answers the fortnight.</h2><p class="mb-10 max-w-[62ch] text-pretty text-lede text-ink-soft">Limn is open core. The free tier is the product, not a trial — it has no repository limit, no user limit and no expiry, and every action you take on a pull request lives in it. Pro is what happens when you need the same truth one grain up: across repositories, across people, across a period.</p><div class="border-t border-ink"><div class="hidden gap-grid-gutter border-b border-rule-strong py-3 rail:grid rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><span class="block font-mono uppercase text-mono-label text-secondary">Question</span><span class="block font-mono uppercase text-mono-label text-secondary">Free · open core</span><span class="block font-mono uppercase text-mono-label text-signal-text">Pro · free for a month</span></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">What should I work on today?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Pending: everything waiting on you or your workspace, across every repository, in six ranked tabs — the top five of each marked Do next.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Plan my day: a written headline, a line on what can wait, and a reason on each planned card. The order stays the free one.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Can I change what counts as my turn?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Yes. Switch card types on or off, move your own work into My turn, set the order, choose how every tab ranks, and mute a repository or a workspace.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does. Your rules are never the paid part.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">What happened on this pull request?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Every thread triaged — untouched, replied, likely addressed, resolved. Blast radius, blockers, merge verdict.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">A short written summary, a read on what a red build means, and a check on whether a comment was really addressed.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Can I act without leaving?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Reply, resolve, approve, merge, merge-when-ready, update from trunk, resolve conflicts hunk by hunk.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does. Acting on a pull request is never the paid part.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Can Claude review or fix this?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Yes, on your machine, on your own Claude: a review you tick and post, a chat on it, and a fix that is pushed only when you click.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does. The agents are never the paid part.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Which review bots are worth their seat?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Detect every bot, name it, set its role and record what it costs — and an independent severity grade on every comment it leaves.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">The per-bot scoreboard: keep / tune / noisy, dollars per comment your team acted on, over-calling as a weekly line.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">How does that compare to other teams?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">—</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Your bots placed against a 2,204-repository cohort, with a written refusal wherever the cohort is too thin to answer.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">How is the team doing?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Flow metrics for the workspace, activity and reach by repository, open pull requests and trunk health.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">A stored report per sprint or month, compared like-for-like against the last one, with the coverage stated.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Is a repository about to bite us?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Default-branch health across every repository, the checks failing on it, and the pull request that landed its latest commit.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does. Trunk health is never the paid part — it is the thing you need at the worst moment.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Where is the time actually going?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">—</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Chronology: every open hour attributed to a reviewer, an author, or waiting to land. Nobody is named.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">What do I take into a one-to-one?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">—</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">A report with a section per person you pick. Preparation, not a ranking — there is no leaderboard anywhere in it.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Can I keep the noise down?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">Bots hidden by default, notifications only for work that is yours, and a mute per repository or per workspace.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">Everything free does, plus a Slack digest per workspace if you would rather read it there.</p></div></div><div class="grid gap-x-grid-gutter gap-y-2 border-b border-rule-hair py-[18px] rail:grid-cols-[1.1fr_1.3fr_1.3fr]"><p class="font-display text-list font-semibold text-ink">Where does it run?</p><div><span class="block font-mono uppercase text-mono-label mb-1 text-secondary rail:hidden">Free</span><p class="text-list text-ink-body">npx limn-review on your machine, or the hosted service. No repository limit, no user limit. Claude review and fix run on your machine only.</p></div><div><span class="block font-mono uppercase text-mono-label mb-1 text-signal-text rail:hidden">Pro</span><p class="text-list text-ink-body">The same two places. Pro unlocks on whichever one you already use.</p></div></div></div><p class="mt-6 max-w-[62ch] font-mono text-mono-caption text-secondary">Pro lists at $25 per user, and is free for a month to anyone who asks for it. A user is someone who signs in — bots never count, and there is no per-repository charge.</p><p class="mt-2 max-w-[62ch] font-mono text-mono-caption text-secondary">Review and fix run locally only, on your own Claude Code or Anthropic API key. Limn stores no key and charges nothing for it.</p><div class="mt-10"><figure class="border border-rule"><figcaption class="flex items-center justify-between border-b border-rule px-4 py-[11px] font-mono text-mono-caption text-secondary"><span>limn · reports, free account</span><button type="button" class="text-signal-text transition-colors duration-hover ease-standard hover:text-ink focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Enlarge</button></figcaption><button type="button" aria-label="Enlarge screenshot: The Reports pane on a free account: the flow metrics render in full, and the paid period-report panel below them is listed, badged and locked rather than hidden" class="block w-full cursor-zoom-in focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:-outline-offset-2 focus-visible:outline-ink"><span style="height:460px" class="block w-full overflow-hidden bg-paper"><img src="/shots/free-reports.png" alt="The Reports pane on a free account: the flow metrics render in full, and the paid period-report panel below them is listed, badged and locked rather than hidden" loading="lazy" decoding="async" class="h-full w-full object-cover object-top"/></span></button></figure><p class="mt-[18px] max-w-caption text-list text-muted">What a free account actually sees. The paid panes are listed and locked rather than hidden, so you can tell what you are not buying before you buy it — and the free metrics above them are the ones that moved here off another tab.</p></div></div></div></section><section class="px-gutter py-section-y-lg "><div class="grid items-start gap-grid-gutter rail:grid-cols-rail-1 "><div class="mb-6 font-mono text-mono-label uppercase text-secondary rail:mb-0 rail:pt-[10px]">Start</div><div><h2 class="mb-5 max-w-[24ch] text-pretty font-display text-h2-sm font-semibold text-ink type:text-h2-major">Start free. Every repository, nothing missed.</h2><p class="mb-9 max-w-[56ch] text-pretty text-lede text-ink-soft">Sign in with GitHub and the first repositories are on screen in a couple of minutes, or run the whole free tier on your own machine and keep the data there. For Pro, send a message — it is free for a month, for asking.</p><div class="mb-5 flex flex-wrap items-center gap-3.5"><a href="/api/auth/login" class="inline-block bg-ink px-6 py-[15px] font-display text-[16px] font-semibold text-paper hover:bg-[#08080A] transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink ">Sign in with GitHub</a><a href="/contact?topic=pro" class="inline-block bg-signal-text px-6 py-[15px] font-display text-[16px] font-semibold text-paper hover:bg-[#A6301A] transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink ">Ask for a free month of Pro</a></div><p class="max-w-reassure font-mono text-mono-nav text-secondary">Card payments are not switched on yet, so Pro is not sold from this page — it is given, a month at a time, to anyone who asks. No card, nothing to cancel. Or run the free tier locally: <span class="text-ink">npx limn-review</span></p></div></div></section></main><footer class="border-t border-rule px-gutter py-[26px] font-mono text-mono-caption text-secondary"><div class="flex flex-wrap items-baseline justify-between gap-x-8 gap-y-3"><span>© 2026 Limn. Built for sprint situational awareness.</span><span class="flex flex-wrap items-baseline gap-x-5 gap-y-2"><a href="/for-developers" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">For developers</a><a href="/for-managers" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">For managers</a><a href="/how-we-measure" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">How we measure</a><a href="/contact" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Contact</a><a href="https://github.com/alexwakeman/pierre-review" target="_blank" rel="noreferrer noopener" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">GitHub</a><a href="/privacy" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Privacy</a><a href="/cookies" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Cookies</a><a href="/terms" class="hover:text-ink transition-colors duration-hover ease-standard focus:outline-none focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-ink">Terms</a></span></div><p class="mt-4 max-w-caption">Limn is a desktop experience today. A phone-friendly build is planned.</p></footer></div>
|
|
154
|
+
</div>
|
|
155
|
+
</body>
|
|
156
|
+
</html>
|
|
Binary file
|
|
Binary file
|