Repository navigation
Feat: added Deployment Summary UX for the previous PR #114 - #115
Conversation
|
Warning Review limit reached
More reviews will be available in 53 minutes and 8 seconds. Learn how PR review limits work. Your organization has run out of usage credits. Purchase more in the billing tab. ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the We recommend that you space out your commits to avoid hitting the rate limit. 🚦 How do rate limits work?CodeRabbit enforces hourly rate limits for each developer per organization. Our paid plans include higher PR review limits than trial, open-source, and free plans. In all cases, reviews become available again over time. During sustained high-volume PR review activity, CodeRabbit may temporarily slow when the next review becomes available. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Run ID: 📒 Files selected for processing (2)
📝 WalkthroughWalkthroughDeployment recommendations are now automatically displayed across all ChangesDeployment Recommendation Display
Estimated code review effort🎯 2 (Simple) | ⏱️ ~10 minutes Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
Auto Pull Request Review from LlamaPReview
Large PR Notification
Dear contributor,
Thank you for your substantial contribution to this project. LlamaPReview has detected that this Pull Request contains a large volume of changes, which exceeds our current processing capacity.
Details:
- PR and related contents total size: Approximately 1,495,976 characters
- Current limit: 256,000 characters
Next steps:
- Consider breaking this PR into smaller, more focused changes if possible.
- For manual review, please reach out to your team members or maintainers.
We appreciate your understanding and commitment to improving this project. Your contributions are valuable, and we want to ensure they receive the attention they deserve.
LlamaPReview is continuously evolving to better serve the community. Share your thoughts on handling large PRs in our GitHub Discussions - your feedback helps us improve and expand our capabilities.
If you have any questions or need assistance, our community and support team are here to help.
Best regards,
LlamaPReview Team
There was a problem hiding this comment.
Actionable comments posted: 1
🧹 Nitpick comments (1)
tests/test_deployment_explanation.py (1)
155-157: ⚡ Quick winStrengthen assertions to enforce placement contract, not just presence.
On Line 155 and Line 170 (and similarly in the HTML test on Line 189-191), these checks only verify substring existence. They can still pass if the deployment block moves to the wrong section or if
"Fairness"appears elsewhere. Add relative-position assertions (and a more specific HTML marker) so tests enforce the intended UX sequence from the PR objective.Suggested test hardening
def test_show_contains_deployment_summary(mock_report, capsys): @@ mock_report.show() captured = capsys.readouterr() - assert "Deployment Verdict: CAUTION" in captured.out - assert "Primary Risk:" in captured.out + out = captured.out + assert "Deployment Verdict: CAUTION" in out + assert "Primary Risk:" in out assert "Investigate subgroup performance disparities" in captured.out + # Contract: deployment summary should appear before key observations + assert out.index("Deployment Verdict:") < out.index("Key Observations") @@ def test_deployment_summary_in_text_report(mock_report): @@ - assert "Deployment Verdict: CAUTION" in text - assert "Primary Risk:" in text + assert "Deployment Verdict: CAUTION" in text + assert "Primary Risk:" in text assert "Investigate subgroup performance disparities" in text + assert text.index("Deployment Verdict:") < text.index("Key Observations") @@ def test_deployment_summary_in_html_report(mock_report): @@ html = mock_report._repr_html_() assert "Deployment Verdict:" in html - assert "Fairness" in html + assert "Primary Risk" in html + assert "Fairness" in html assert "Investigate subgroup performance disparities" in htmlAlso applies to: 170-172, 189-191
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@tests/test_deployment_explanation.py` around lines 155 - 157, The current assertions only check for substrings and can pass if the deployment block appears in the wrong place; update the tests around the captured output checks that reference "Deployment Verdict: CAUTION", "Primary Risk:", and "Investigate subgroup performance disparities" to enforce relative ordering (e.g., assert captured.out.index("Fairness") < captured.out.index("Deployment Verdict: CAUTION") and that "Primary Risk:" and the specific investigation line appear after the verdict) and in the HTML assertions replace generic substring checks with a specific structural marker (for example assert the deployment block occurs inside the intended container by checking an HTML id/class or the relative index of "<div id=\"deployment-verdict\">" vs "<section class=\"fairness\">") so the test validates placement, not just presence.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@trustlens/report.py`:
- Around line 1511-1539: The deployment card interpolates unescaped dynamic
content from self.deployment_explanation (used in reasons_html, pr_html,
recs_html and the verdict line) which can lead to HTML/script injection; fix by
HTML-escaping all dynamic values before building the strings (escape
exp["verdict"], each r["message"] in reasons_html, exp["primary_risk"]["metric"]
in pr_html, and each recommendation in recs_html) — e.g., import and use a safe
escaper (html.escape or markupsafe.escape) when constructing reasons_html,
pr_html, recs_html and then concatenate into html.
---
Nitpick comments:
In `@tests/test_deployment_explanation.py`:
- Around line 155-157: The current assertions only check for substrings and can
pass if the deployment block appears in the wrong place; update the tests around
the captured output checks that reference "Deployment Verdict: CAUTION",
"Primary Risk:", and "Investigate subgroup performance disparities" to enforce
relative ordering (e.g., assert captured.out.index("Fairness") <
captured.out.index("Deployment Verdict: CAUTION") and that "Primary Risk:" and
the specific investigation line appear after the verdict) and in the HTML
assertions replace generic substring checks with a specific structural marker
(for example assert the deployment block occurs inside the intended container by
checking an HTML id/class or the relative index of "<div
id=\"deployment-verdict\">" vs "<section class=\"fairness\">") so the test
validates placement, not just presence.
🪄 Autofix (Beta)
❌ Autofix failed (check again to retry)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: e97448cd-5472-4bc8-ad87-db4e78202876
📒 Files selected for processing (4)
CHANGELOG.mdexamples/trustlens_demo.ipynbtests/test_deployment_explanation.pytrustlens/report.py
|
Note Autofix is a beta feature. Expect some limitations and changes as we gather feedback and continue to improve it. Autofix skipped. No unresolved CodeRabbit review comments with fix instructions found. |
…COLORS Merging upstream/main (Khanz9664#115, Deployment Summary UX) reintroduced references to summary_plot._C in report.py, which was removed in this branch's style migration. Repoint them to the canonical BRAND_COLORS so the merged tree type-checks. Color values unchanged. Refs Khanz9664#57
… (#102) * feat(visualization): add centralized style module Introduce trustlens/visualization/style.py as the single source of truth for visual constants across plotting functions: - BRAND_COLORS dict for named colors (blue/orange/green/red/amber/...) - PALETTE list for categorical plots, drawn from BRAND_COLORS - SEMANTIC_COLORS for severity (acceptable/moderate/severe/unknown), verdict (deploy/caution/do_not_deploy), grade (A/B/C/D), direction, and neutral references - TYPOGRAPHY, GRID, FIG_DEFAULTS, SPACING for non-color constants - Frozen Theme dataclass with DEFAULT_THEME, leaving room for future named themes (dark, colorblind, publication) without API changes - apply_style() context manager that scopes matplotlib.rcParams mutations to a `with` block, preventing global state leakage in notebooks and larger ML pipelines - styled_figure() and get_categorical_colors() helpers The module is internal (no __all__) - the surface may evolve before being promoted to a supported public API. Relates to #57 * test(visualization): add tests for centralized style module Add tests/test_visualization_style.py covering: - Hex validity and uniqueness of palette / brand / semantic colors - Required keys for severity, verdict, and grade scales - Theme dataclass frozen-ness and instance independence - apply_style context manager: rcParams restoration on normal exit, on exception, and through nested usage - styled_figure: default and custom figsize, multi-subplot support, facecolor application - get_categorical_colors: cyclic behavior, empty / negative inputs - Module surface completeness Relates to #57 * refactor(calibration): use centralized style module Replace inline styling in plot_reliability_diagram() with the centralized style module introduced in the previous commits: - Remove function-local BLUE / ORANGE / GRAY constants - Replace plt.style.use("seaborn-v0_8-whitegrid") with apply_style() context manager - rcParams are now scoped and restored on exit - Source colors from theme.brand and theme.semantic["neutral"] - Source grid alpha and savefig DPI from theme Visual output is preserved (same hex values, same figsize, same alpha and linewidth values). No public API changes. Update CHANGELOG.md with an entry under [Unreleased] / Added. Closes #57 (calibration_plots only; remaining visualization modules to follow in subsequent commits on this branch). * fix(visualization): address review feedback from automated bots Address feedback from CodeRabbit and LlamaPReview on PR #102: - CHANGELOG.md: change `(closes #57)` to `(refs #57)` since this is an incremental migration; the issue should not auto-close until all visualization modules are migrated on this branch. - style.py: guard `get_categorical_colors()` against an empty theme palette to fail fast with a ValueError instead of a ZeroDivisionError. - tests: add a regression test for the empty palette guard. - calibration_plots.py: remove the faulty `"agg" not in get_backend()` check that incorrectly skipped `plt.show()` on interactive backends whose names also contain "agg" (e.g. QtAgg, TkAgg). This bug pre-dated this PR but was surfaced by the review. Relates to #57 * fix(visualization): add base-style warning and validate n_bins Address remaining review feedback from PR #102: - style.py: emit a UserWarning when apply_style() cannot load the theme's base_style sheet, instead of silently falling through to rcParams-only styling. Custom themes with typos or missing styles are now visible during debugging without becoming hard failures (per LlamaPReview and @Khanz9664). - calibration_plots.py: validate n_bins >= 1 up front with a clear ValueError instead of letting an invalid value reach the bar width calculation (per CodeRabbit and @Khanz9664). - tests: add coverage for the new warning path and the n_bins guard in a new tests/test_calibration_visualization.py file, following the repo's per-module visualization test convention. Relates to #57 * refactor(failure): use centralized style module Migrate failure_plots.py to use apply_style() context manager and theme references from trustlens.visualization.style, removing the inline GREEN/RED constants and direct plt.style.use() call. Color values are preserved bit-for-bit: - GREEN "#34C759" -> theme.brand["green"] - RED "#FF3B30" -> theme.brand["red"] - edgecolor="white" -> theme.semantic["neutral"]["edge"] - edgecolor="#CCCCCC" -> theme.semantic["neutral"]["annotation_edge"] - facecolor="white" -> theme.semantic["neutral"]["annotation_face"] - dpi=150 (savefig) -> theme.fig_defaults["savefig_dpi"] Magic numbers (alpha, figsize, fontsize, bar width factor) are intentionally left as-is, per the migration plan agreed in PR #102. Visual parity verified: full test suite (301 passed) runs unchanged. Refs #57 * refactor(bias): use centralized style module Migrate bias_plots.py to use apply_style() context manager and theme references from trustlens.visualization.style, removing the inline PALETTE definition (which exactly duplicated style.PALETTE) and the direct plt.style.use() call. Color values are preserved bit-for-bit: - PALETTE (8 colors) -> get_categorical_colors(n) from style module (identical hex values, identical mod cycling) - edgecolor="white" -> theme.semantic["neutral"]["edge"] - edgecolor="#CCCCCC" -> theme.semantic["neutral"]["annotation_edge"] - facecolor="white" -> theme.semantic["neutral"]["annotation_face"] - dpi=150 (savefig) -> theme.fig_defaults["savefig_dpi"] Magic numbers (linewidth, alpha, figsize, fontsize, percentage offset factor) are intentionally left as-is, per the migration plan agreed in PR #102. Visual parity verified: full test suite (301 passed) runs unchanged. Refs #57 * refactor(representation): use centralized style module Migrate representation_plots.py to use apply_style() context manager and theme references from trustlens.visualization.style, removing the inline hex color literals and the direct plt.style.use() call. Color values are preserved bit-for-bit: - "#34C759" (silhouette / separability good) -> theme.brand["green"] - "#FF9F0A" (silhouette / separability warn) -> theme.brand["amber"] - "#FF3B30" (silhouette / separability bad) -> theme.brand["red"] - "#4B8BF5" (Within-Class card) -> theme.brand["blue"] - "#AF52DE" (Between-Class card) -> theme.brand["purple"] - "#666666" (subtitle text) -> theme.brand["text_muted"] - "#444444" (card label / ratio label text) -> theme.brand["text_dark"] - "#888888" (guidance footer text) -> theme.brand["text_subtle"] - dpi=150 (savefig in both functions) -> theme.fig_defaults["savefig_dpi"] The matplotlib `tab10` cmap used in plot_embedding_2d() is intentionally left untouched, since it is a separate color system from BRAND_COLORS and substituting get_categorical_colors() would change the per-class scatter colors (visual parity violation). Magic numbers (alpha, figsize, fontsize, linewidth, marker size, ...) are intentionally left as-is, per the migration plan agreed in PR #102. Also restores the "Centralized Visualization Styling" CHANGELOG entry that was inadvertently dropped during the recent merge from main (commit 53ea795), and extends its "so far:" list to include representation_plots.py. Visual parity verified: full test suite (302 passed) runs unchanged. Refs #57 * refactor(fairness): use centralized style module Migrate fairness.py to use apply_style() context manager and theme references from trustlens.visualization.style, removing the inline PALETTE list, the violation_colors dict, and the direct plt.style.use() calls. Color values are preserved bit-for-bit: - PALETTE (8 colors) -> get_categorical_colors() (mod-cycling) - bar edgecolor "white" -> theme.semantic["neutral"]["edge"] - annotation facecolor "white" -> theme.semantic["neutral"]["annotation_face"] - annotation edgecolor "#CCCCCC" -> theme.semantic["neutral"]["annotation_edge"] - TPR/gap bar "#4B8BF5" -> theme.brand["blue"] - FPR/gap bar "#F5784B" -> theme.brand["orange"] - violation_colors {severe/moderate/acceptable} -> theme.semantic["severity"] - violation fallback "#CCCCCC" -> theme.semantic["severity"]["unknown"] (same hex) - savefig dpi=150 -> theme.fig_defaults["savefig_dpi"] The grid alpha is left as the literal 0.35; it intentionally differs from theme.grid["alpha"] (0.4), so theming it would change visual output. Other magic numbers (alpha=0.85, figsize, fontsize) are left as-is per the migration plan agreed in PR #102. The *_multi wrappers delegate to the single-feature functions and are unchanged. Also updates the CHANGELOG "so far" list to include fairness.py. Visual parity verified: full test suite (312 passed) runs unchanged. Refs #57 * refactor(summary): use centralized style module Migrate summary_plot.py to source colors from the centralized trustlens.visualization.style module and to scope its matplotlib.rcParams mutations inside apply_style(), removing the inline _C palette and _GRADE_COLORS dict and the global plt.rcParams.update() call. Color values are preserved bit-for-bit: - _C[...] (blue/orange/green/red/amber/purple/gray/light/white/dark) -> BRAND_COLORS[...] - _GRADE_COLORS {A/B/C/D} -> SEMANTIC_COLORS["grade"] - class-distribution palette -> built from BRAND_COLORS in the same order (NOT get_categorical_colors, which is a different 8-color palette) - savefig dpi=150 -> FIG_DEFAULTS["savefig_dpi"] The previously global rcParams.update() leaked styling into the user's matplotlib session; it is now scoped to the apply_style() context, which is the core goal of #57. apply_style() already sets font, spines, and white figure/axes facecolors via the base theme, so only "axes.grid": False is re-applied inside the context (the base style seaborn-v0_8-whitegrid enables the grid; the dashboard draws its own per-panel grids). Left as literals (no brand equivalent, parity-preserving): the "#DDD" annotation-box edges, the per-panel grid alphas (0.2/0.25) with dashed linestyle, and the bar edgecolor "white". Magic numbers (alpha, figsize, fontsize) are unchanged per the migration plan agreed in PR #102. Also updates the CHANGELOG "so far" list to include summary_plot.py. Visual parity verified: full test suite (312 passed) runs unchanged, and an rcParams leak check confirms no global state leaks after rendering. Also repoints the cross-module references to summary_plot._C in trust_score.py and report.py (used in their _repr_html_ output) to the canonical BRAND_COLORS via a top-level import, since _C was removed from summary_plot. Color strings are unchanged (gray #8E8E93, dark #1C1C1E both exist in BRAND_COLORS), so the rendered HTML is identical. Refs #57 * ci: re-trigger checks for centralized style migration * ci: re-trigger checks * fix(report): repoint _C references introduced by main merge to BRAND_COLORS Merging upstream/main (#115, Deployment Summary UX) reintroduced references to summary_plot._C in report.py, which was removed in this branch's style migration. Repoint them to the canonical BRAND_COLORS so the merged tree type-checks. Color values unchanged. Refs #57 --------- Co-authored-by: Shahid Ul Islam <65996596+Khanz9664@users.noreply.github.com>
Summary
The Deployment Summary has been successfully integrated natively into the core TrustReport user experience, drastically improving the discoverability of deployment recommendations without breaking any existing API surfaces or logic.
1. Architectural Changes
The deployment summary string (and its rich HTML equivalent) is now systematically embedded into the three primary report generation endpoints:
TrustReport.show()The core CLI output now features the deployment summary printed immediately after the
Score Summary / Penalty Explanationsection and beforeKey Observations. This establishes a highly natural reading flow:TrustReport._generate_text_report()The plain-text export (used when saving to
.txtfiles) mirrors the structure ofshow(), ensuring the deployment summary is persisted when sharing analysis logs in CI/CD pipelines or text archives.TrustReport._repr_html_()The Jupyter Notebook output now renders a visually distinct, rich HTML block. It utilizes the structured
deployment_explanationdictionary rather than the plain text string, converting thereasonsinto a clean bulleted list with color-coded success/failure icons (✓/✗), and therecommendationsinto a formatted checklist.Note
Backward Compatibility Maintained:
As intended,
_format_score_explanation()was left completely intact. No existing trust score mechanics, blocking logic, or visualization endpoints were altered. This is a 100% additive UX enhancement.2. Test Coverage
The test suite in
tests/test_deployment_explanation.pywas expanded to rigorously verify the UX changes:test_show_contains_deployment_summary: Captures stdout usingcapsysto assert thatreport.show()successfully prints the "Deployment Verdict:" string and subsequent recommendations.test_deployment_summary_in_text_report: Asserts the output of_generate_text_report().test_deployment_summary_in_html_report: Mocks out thematplotlibsummary plot to independently assert the presence of the new HTML deployment block in_repr_html_().All 9 tests pass successfully.
3. Changelog Documentation
The
CHANGELOG.mdfile was updated to formally record this UX improvement, explicitly stating:Summary by CodeRabbit
New Features
Tests