## Why Second pass at the complexity report. After the trial-experiment code (deleted by #762) and the analytics controller (#766), the worst offenders were the MCP write tools: - `UpdateTransaction::write` — cyclomatic complexity **20** - `UpdateAutomationRule::write` — cyclomatic complexity **13** Both for the same reason: a long wall of `if ($request->has('x')) { $model->x = ...; }` blocks, one per optional field. ## What changed Two shapes moved into `WriteTool`: **`modelInSpace()`** — resolving a record in the space was written five times (account, transaction, category, label, plus a rule resolver that existed twice, once in `UpdateAutomationRule` and once in `DeleteAutomationRule`), each a copy of the same query + null check + message. The four public helpers are now one-liners over it, and `ruleInSpace()` is shared instead of duplicated. **`applyFields()`** — assigns only the fields the request actually carries, which is the "only what you pass changes" contract these tools document. Values are closures, so resolving a related model (`accountInSpace`, `categoryInSpace` — either can throw a validation error) still happens only when its field is present. ## Metrics | | before | after | |---|---|---| | methods over complexity 10 | 35 | 33 | | `UpdateTransaction::write` | 20 | 7 | | `UpdateAutomationRule::write` | 13 | 6 | | duplicated lines | 5.34% | 5.34% | Duplication does not move, and it's worth being straight about why: what jscpd still flags across `app/Mcp/Tools` is **file headers** — the `use` block, the `#[Description]` attribute, the class line and the opening of `schema()`. Nine near-identical lines per tool that no extraction can remove. Deleting the duplicated `ruleInSpace` shortened `DeleteAutomationRule` enough that its header became a clone pair with another tool's, so the counter stayed flat while the real duplication went away. ## Testing `tests/Feature/Mcp` — 46 tests green, plus a new one. Nothing asserted the resolver failure messages before, and this PR changes how they are built (a shared template plus an optional hint), so the new test pins both branches: the message that points at a listing tool (`Call search_transactions to find ids.`) and the one that has no hint to append. |
||
|---|---|---|
| .. | ||
| Ai | ||
| Api | ||
| Auth | ||
| Console | ||
| Events | ||
| Jobs | ||
| Listeners | ||
| Mcp | ||
| Onboarding | ||
| OpenBanking | ||
| Services | ||
| Settings | ||
| Spaces | ||
| Sync | ||
| AccountBalanceControllerTest.php | ||
| AccountControllerTest.php | ||
| AccountImportConfigTest.php | ||
| AccountUserCurrencyServiceTest.php | ||
| AiConsentSettingsTest.php | ||
| AiConsentTest.php | ||
| AlignAccountsEncryptedFlagMigrationTest.php | ||
| ApplyRealEstateRevaluationTest.php | ||
| AuthenticatedLayoutSafeAreaTest.php | ||
| AutomationRuleApplicationTest.php | ||
| AutomationRuleEvaluationTest.php | ||
| AutomationRuleTest.php | ||
| BackfillAccountIbansCommandTest.php | ||
| BackfillXxxAccountCurrenciesTest.php | ||
| BalanceLookupTest.php | ||
| BudgetHistoricalAssignmentTest.php | ||
| BudgetNotificationTest.php | ||
| BudgetPeriodDateTest.php | ||
| BudgetPeriodServiceTest.php | ||
| BudgetTest.php | ||
| BudgetTransactionServiceTest.php | ||
| BulkUpdateTransactionsTest.php | ||
| CancelFreeEnableBankingConnectionsCommandTest.php | ||
| CashflowAnalyticsTest.php | ||
| CashflowPageTest.php | ||
| CatchAllBudgetTest.php | ||
| CategoryMonthlyBreakdownTest.php | ||
| CrapCommandTest.php | ||
| CurrencyConversionServiceTest.php | ||
| DashboardAnalyticsTest.php | ||
| DashboardTest.php | ||
| DecryptTransactionsTest.php | ||
| DeleteUserCommandTest.php | ||
| DemoAccountRestrictionsTest.php | ||
| DisconnectBankingConnectionsCommandTest.php | ||
| DiscordReportEmbedLimitsTest.php | ||
| DiscordWebhookTest.php | ||
| EncryptionTest.php | ||
| ExampleTest.php | ||
| ExchangeRateServiceTest.php | ||
| GenerateStripePromotionCodesCommandTest.php | ||
| IdorVulnerabilityTest.php | ||
| ImportDataTest.php | ||
| InertiaSharedDataTest.php | ||
| IntegrationRequestTest.php | ||
| LabelTest.php | ||
| LoanTest.php | ||
| LocalizationTest.php | ||
| LoggingConfigTest.php | ||
| MailSenderTest.php | ||
| NewTransactionsMarkerTest.php | ||
| OpenAiAppsChallengeTest.php | ||
| PersistUpsellSourceFromStripeTest.php | ||
| PlaintextTransactionsTest.php | ||
| PlanFeatureTest.php | ||
| PopoverSafeAreaTest.php | ||
| PostStripeEventToDiscordTest.php | ||
| PurgeResidualEncryptionArtifactsJobTest.php | ||
| PwaTest.php | ||
| QueueConfigTest.php | ||
| ReEvaluateTransactionRulesTest.php | ||
| RealEstateAvailabilityTest.php | ||
| RealEstateTest.php | ||
| ResendSyncCommandTest.php | ||
| RouteNotificationForMailTest.php | ||
| RuleEngineParityTest.php | ||
| SavedFilterTest.php | ||
| SelfServeRefundTest.php | ||
| SendAiCohortReportCommandTest.php | ||
| SendAiConsentFollowUpEmailsCommandTest.php | ||
| SendDailyStatsReportCommandTest.php | ||
| SendExperimentFunnelReportCommandTest.php | ||
| SendStuckCohortReportCommandTest.php | ||
| SendSubscriptionFunnelReportCommandTest.php | ||
| SentryConfigTest.php | ||
| SentryUserMiddlewareTest.php | ||
| SetLocaleTest.php | ||
| SitemapTest.php | ||
| StrayHttpRequestGuardTest.php | ||
| StripeSubscriptionStatsCommandTest.php | ||
| SubscriptionExperimentTest.php | ||
| SubscriptionTest.php | ||
| SuggestionPersistenceTest.php | ||
| SyncBankingConnectionsCommandTest.php | ||
| SyncStripePricesCommandTest.php | ||
| TrackLastActiveAtTest.php | ||
| TransactionAnalysisTest.php | ||
| TransactionFilterTest.php | ||
| TransactionSideClassificationTest.php | ||
| TransactionTest.php | ||
| WelcomeBanksOrderingTest.php | ||