Add confidence breakdown API for proposal review UI#1036
Conversation
Immutable value object representing a single named component of a confidence breakdown (e.g. Pattern match, Reach). Validates key is non-empty and value is finite and in [0.0, 1.0]. Includes equality, hash code, and operator overloads. Closes part of #1021
Multi-component confidence breakdown with overall score, component list, optional note, and threshold. Validates all scores are finite and in [0.0, 1.0]. Defensive-copies component list. Exposes MeetsThreshold computed property. Closes part of #1021
Application-layer DTOs for the confidence breakdown API response. ConfidenceBreakdownDto includes overall, components, note, threshold, and a computed MeetsThreshold property. Closes part of #1021
Computes a 4-component confidence breakdown for proposals: - Pattern match: proportion of operations using well-known actions - Reach: inverse log of distinct affected entities - Reversibility: blend of risk level baseline and action-type risk - Recency: remaining fraction of the proposal expiry window Overall is a weighted average (Reversibility 0.35, Pattern match 0.30, Reach 0.20, Recency 0.15). Generates explanatory note when score is near the default 0.7 threshold. Closes part of #1021
Wire IConfidenceBreakdownService into AutomationProposalsController and register it in DI. Endpoint uses existing authorization flow to verify the caller has read access to the proposal's board. Closes part of #1021
30 tests covering value validation (0..1 range, NaN, Infinity, empty key, null components), boundary values, equality/hash code, MeetsThreshold, defensive copy, and ToString formatting. Closes part of #1021
33 tests covering breakdown computation, component logic (pattern match, reach, reversibility, recency), overall weighted average, note generation, and proposal-type integration scenarios. Closes #1021
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Adversarial review found that move, reorder, assign, attach, restore, unarchive, and unblock were in WellKnownActions but not classified as safe or destructive, causing them to fall through to a neutral 0.6 action factor. These are all reversible operations and should be classified as safe for the reversibility component.
Adversarial Self-ReviewChecked areas (per issue requirements)1. Value range validation -- PASS
2. NaN/Infinity handling -- PASS
3. Interaction with existing ConfidenceScore system -- PASS (no conflict)
4. Component weight normalization -- PASS
5. Floating-point comparison edge cases -- PASS
Found and fixed6. Missing action type classification -- FIXED in
Remaining notes (not bugs, design decisions)
|
There was a problem hiding this comment.
Code Review
This pull request implements a confidence breakdown system for automation proposals, adding a new API endpoint and a service to calculate scores based on pattern matching, reach, reversibility, and recency. The feedback identifies an unused parameter in the service method, a discrepancy between the reach score formula and its documentation, and a performance optimization to reduce allocations during score weighting.
Adversarial Review -- PR #1036Reviewed all 10 changed files. Confirming the 3 Gemini bot findings and fixing all of them: 1. MEDIUM: Unused
|
Authorization is handled at the controller level via AuthorizeProposalAsync before the service is called, so the userId parameter was dead code.
…tatic field - Fix ComputeReach formula from 1/(1+log2) to 2/(2+log2) to match documented examples (2 targets ~ 0.67, 4 ~ 0.5, 8 ~ 0.4) - Remove unused userId parameter from GetBreakdownAsync implementation - Promote per-call weights dictionary to static readonly ComponentWeights field to avoid allocation on every ComputeOverall call
Matches the updated IConfidenceBreakdownService signature that no longer accepts a userId parameter.
Remove Guid.NewGuid() userId arguments from all GetBreakdownAsync test call sites to match the updated interface signature.
Fresh Adversarial Review (Round 3)IMPORTANT1. Double database fetch for proposal (Confidence: 85) 2. Static mutable Fix: Use Verified Non-Issues
|
Wrap the static ComponentWeights field as IReadOnlyDictionary backed by ReadOnlyDictionary to prevent accidental mutation of weight values at runtime.
Resolve conflicts combining confidence-breakdown endpoint (branch) with side-effects, similar-past, and streak features (main). Take main's addColumn fix in smoke.spec.ts.
Summary
Implements the backend confidence breakdown system (#1021) so the paper deep-review header dial and right-rail bars can show a 4-component explanation of why a proposal is or isn't above the apply threshold.
ConfidenceComponentandConfidenceBreakdownvalue objects with full [0..1] range validation, NaN/Infinity rejection, equality, and defensive copy semanticsIConfidenceBreakdownService/ConfidenceBreakdownServicecomputing 4 components (Pattern match, Reach, Reversibility, Recency) from proposal metadata with weighted overall score and threshold-relative note generationGET /api/automation/proposals/{id}/confidenceendpoint with board-scoped authorizationComponent computation
Response shape
{ "overall": 0.82, "components": [ { "key": "Pattern match", "value": 1.0 }, { "key": "Reach", "value": 0.67 }, { "key": "Reversibility", "value": 0.9 }, { "key": "Recency", "value": 0.95 } ], "note": null, "threshold": 0.7, "meetsThreshold": true }Test plan
dotnet build backend/Taskdeck.sln -c ReleasepassesCloses #1021