Add proposal side-effect analysis with 7-category breakdown and reversibility window#1033
Add proposal side-effect analysis with 7-category breakdown and reversibility window#1033Chris0Jeky merged 12 commits intomainfrom
Conversation
Part of #1020: paper-review-backend-gap-side-effects
Part of #1020: paper-review-backend-gap-side-effects
Part of #1020: paper-review-backend-gap-side-effects
Part of #1020: paper-review-backend-gap-side-effects
Part of #1020: paper-review-backend-gap-side-effects
Analyzes proposal operations to produce 7-category side-effect breakdown (Cards, Subtasks, Comments, Activity log, Notifications, Webhooks, Calendar) with active/passive tone classification and risk-based reversibility window. Part of #1020: paper-review-backend-gap-side-effects
Wires ISideEffectAnalyzer into AutomationProposalsController with board-level authorization and registers the service in DI. Part of #1020: paper-review-backend-gap-side-effects
25 tests covering construction, validation, equality, and formatting. Part of #1020: paper-review-backend-gap-side-effects
34 tests covering tone classification for all 7 categories, webhook detection, reversibility window computation, risk-level-based window adjustment, and null/empty edge cases. Part of #1020: paper-review-backend-gap-side-effects
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
- Remove unused 'using Taskdeck.Domain.Entities' from SideEffectDtos.cs - Remove unused hasColumnMutation variable from BuildSideEffectRows Part of #1020: paper-review-backend-gap-side-effects
Adversarial Self-Review FindingsTone classification correctness (7 categories)
Reversibility window
Issues found and fixed (commit
|
There was a problem hiding this comment.
Code Review
This pull request introduces a side-effect analysis feature for automation proposals, adding a new API endpoint, the SideEffectAnalyzer service, and corresponding domain entities and DTOs. The analysis breaks down proposal impacts into seven categories and determines a reversibility posture based on risk levels. Feedback focuses on refining the analysis logic: specifically, utilizing the currently unused hasColumnMutation variable, tightening the hasCardMutation check to verify target types, and ensuring the Webhooks tone is only marked as active when operations actually exist to trigger them.
| bool hasCardMutation = operations.Any(op => CardMutatingActions.Contains(op.ActionType)); | ||
| bool hasAnyOperation = operations.Count > 0; | ||
|
|
||
| return new List<SideEffectRow> | ||
| { |
There was a problem hiding this comment.
The hasColumnMutation variable is calculated but never used in the 7-category breakdown. Additionally, hasCardMutation is overly broad as it checks action types without verifying the target type, which could lead to false positives if other entity types share action names like 'create' or 'update'. Since the 'Cards' category is the most appropriate place for board structure changes in this 7-row model, I suggest combining them into a hasBoardMutation flag and refining the target type checks.
bool hasCardMutation = operations.Any(op =>
string.Equals(op.TargetType, "card", StringComparison.OrdinalIgnoreCase) &&
CardMutatingActions.Contains(op.ActionType));
bool hasColumnMutation = operations.Any(op =>
string.Equals(op.TargetType, "column", StringComparison.OrdinalIgnoreCase) &&
string.Equals(op.ActionType, "create_column", StringComparison.OrdinalIgnoreCase));
bool hasAnyOperation = operations.Count > 0;
bool hasBoardMutation = hasCardMutation || hasColumnMutation;| ? "Creates, moves, or archives cards on the board" | ||
| : "No card mutations", | ||
| hasCardMutation ? SideEffectTone.Active : SideEffectTone.Passive), | ||
|
|
||
| new( | ||
| "Subtasks", |
There was a problem hiding this comment.
The 'Cards' row should reflect board structure changes like column creation if they are present, especially since hasColumnMutation was explicitly calculated. Updating the description and tone to account for both cards and columns ensures the analysis is comprehensive within the 7-category constraint.
new(
"Cards",
hasBoardMutation
? "Creates, moves, or archives cards or columns on the board"
: "No card or column mutations",
hasBoardMutation ? SideEffectTone.Active : SideEffectTone.Passive),| : "No outbound webhooks configured", | ||
| hasActiveWebhooks ? SideEffectTone.Active : SideEffectTone.Passive), | ||
|
|
||
| new( | ||
| "Calendar", |
There was a problem hiding this comment.
The 'Webhooks' tone is currently set to Active solely based on whether webhooks are configured for the board (hasActiveWebhooks). However, if the proposal contains no operations (hasAnyOperation is false), no webhooks will actually fire. The tone should reflect the actual impact of the proposal. I suggest updating the logic to ensure the tone is only Active when both webhooks are configured and operations exist to trigger them.
new(
"Webhooks",
hasActiveWebhooks && hasAnyOperation
? "Outbound webhooks configured for this board will fire"
: (hasActiveWebhooks ? "No operations to trigger webhooks" : "No outbound webhooks configured"),
hasActiveWebhooks && hasAnyOperation ? SideEffectTone.Active : SideEffectTone.Passive),
Adversarial Review -- SideEffectAnalyzer fixesIssues found and fixed1. Bug:
2. Bug: Cards row ignores column mutations (MEDIUM)
3. Bug: Webhooks show Active with no operations (MEDIUM)
4. Test bug: Wrong action type in column-only test
New test coverage
Verification
|
… no-op guard
- Add TargetType check to hasCardMutation so column operations are not
misclassified as card mutations
- Introduce hasColumnMutation and hasBoardMutation flags; Cards row now
shows context-appropriate descriptions for card-only, column-only,
or combined board mutations
- Webhooks tone is Active only when hasActiveWebhooks AND hasAnyOperation,
preventing misleading "will fire" on no-op proposals
- Fix test that used wrong action type ("create_column" vs real "create")
which masked the target-type bug
- Add 6 new tests covering column mutations, target type filtering,
and webhook no-ops edge case
Fresh Adversarial Review (Round 3)CRITICAL1. Double database fetch for proposal (Confidence: 92) Fix: Pass the already-loaded proposal entity into IMPORTANT2. Unused 3. 4. 5. No API integration test (Confidence: 84) — 66 unit tests but no HTTP pipeline test for the endpoint. 6. Verified Non-Issues
|
…num validation Drop the unused userId parameter from ISideEffectAnalyzer.AnalyzeAsync, its implementation, the controller call site, and all tests. Add Enum.IsDefined guard to SideEffectRow constructor to reject undefined SideEffectTone values.
Resolve conflicts from #1032 (streak), #1033 (side-effects), and #1038 (similar-past) merges into main. - AutomationProposalsController: keep provenance endpoint from this branch alongside side-effects and similar-past endpoints from main; inject both IProvenanceQueryService and ISideEffectAnalyzer. - ApplicationServiceRegistration: register both IProvenanceQueryService and ISideEffectAnalyzer in the DI container. - smoke.spec.ts: take main's improved addColumn helper that waits for the POST response and dialog close.
Resolve conflicts from #1032 (streak), #1033 (side-effects), #1038 (similar-past) merges: - AutomationProposalsController: keep conflicts endpoint alongside side-effects, diff, and similar-past endpoints; constructor accepts all services - ApplicationServiceRegistration: register both ProposalConflictDetector and SideEffectAnalyzer - WorkerResilienceTests: fake repo implements both GetPendingByOperationTargetAsync and GetTerminalByActionTypeAsync - smoke.spec.ts: take main's more robust addColumn helper (waits for API response and dialog close)
Summary
SideEffectTone,SideEffectRow,Reversibility,ProposalSideEffects) for the paper deep-review Section III side-effects breakdownISideEffectAnalyzer/SideEffectAnalyzerservice that analyzes a proposal's operations to produce a 7-category side-effect table (Cards, Subtasks, Comments, Activity log, Notifications, Webhooks, Calendar) with active/passive tone classificationGET /api/automation/proposals/{id}/side-effectsendpoint with board-level authorizationTest plan
dotnet build backend/Taskdeck.sln -c Releasepasses (0 errors)dotnet test --filter "FullyQualifiedName~SideEffect"-- 60 tests passdotnet test --filter "FullyQualifiedName~Reversibility"-- 31 tests passAuthorizeProposalAsyncpattern from controllerCloses #1020