You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Problem (umbrella; spawn sub-issues as scoped). Report 12 cross-cutting items:
A1/S2 Per-provider Go modules (providers/{aws,azure,gcp}/go.mod) share only pkg/, forcing copy-paste of provider-agnostic helpers. Decide: collapse provider modules into root, or add a shared module they all depend on. (Note: PR chore(dev): add go.work for gopls multi-module workspace (closes #516) #858 added go.work for gopls — does not resolve the import barrier.)
D5 Savings-% formula copy-pasted across ~10 clients with inconsistent divide-by-zero guards (NaN flows into scorer) → common.SavingsPct(onDemandTotal, committedTotal) returning 0 when onDemandTotal <= 0. (Pairs with I-09.)
S1pkg/errors has zero importers — adopt (recommended; helps 4xx/5xx consistency) or remove. No-delete: explicit decision.
A2 Logging split stdlib log vs pkg/logging (~50/50, sometimes same file) — standardize library/provider on pkg/logging.
A3internal/api god files (handler_purchases 1787, router 825, handler_accounts 1490, handler_ri_exchange 844) + direct providers/* reach-through — route via a use-case layer, split by resource.
A4 Frontend god files (recommendations.ts 4312, settings.ts 3222) — decompose into frontend/src/modules/.
A5 FE/BE validation mirrored without cross-reference comments.
Evidence. Report 12 D1-D5, A1-A5, S1-S3, with exact file lists.
Suggested fix. Land the no-barrier ones first (D3, D4, D5, A2, S1 decision); make the A1 module decision and document the rationale; treat god-file splits (A3, A4) as incremental.
References. Source: report 12. The savings-formula guard (D5) is a prerequisite for I-09's clean fix. PR #858 (go.work).
Filed from automated adversarial code review (see docs/code-review/). Source finding(s): 12 A1-A5, D1-D5, S1.
Staged refactor plan (approved direction: full refactor incl. module collapse)
Full execution-ready plan: docs/code-review/14-refactor-plan.md (file:line call sites, tests, CI/Docker/Makefile implications, verification per stage).
HARD precondition — sequencing
Do not start until the in-flight PRs against feat/multicloud-web-frontend that touch the refactor's target files have merged. They rewrite the exact files this refactor rewrites (all provider clients, internal/api, internal/server/app.go, the frontend god files). Blocking set captured 2026-06-07: #1036#1037#1038#1039#1040#1041#1042#1043#1044#1045#1046#1047#1049 (+ PR #858 go.work, obsoleted by Stage 2). Land the refactor on its own branch off the shared branch and rebase before each stage (base keeps moving).
#1045/#1047 removed the fabricated-price fallbacks, not the savings-% formula — all 11 D5 sites still exist; SavingsPct DRYs what remains.
Dependency graph: GATE → Stage 1 → Stage 2 → Stage 3 (3 hard-depends on the unified module). Stage 4 runs in parallel with 2/3 once Stage 1 lands (it touches internal/api/frontend, not the provider module graph). A4 also waits on #1046/#1049.
Proposed sub-issues (for owner approval — NOT yet created)
refactor(common): centralise savings-% into common.SavingsPct, guard zero denominator (D5) — p1/severity:high/this-sprint/many/effort:m/type:bug
Problem (umbrella; spawn sub-issues as scoped). Report 12 cross-cutting items:
providers/{aws,azure,gcp}/go.mod) share onlypkg/, forcing copy-paste of provider-agnostic helpers. Decide: collapse provider modules into root, or add a shared module they all depend on. (Note: PR chore(dev): add go.work for gopls multi-module workspace (closes #516) #858 addedgo.workfor gopls — does not resolve the import barrier.)serviceResult/mergeServiceResultstriplicated → one genericCollectConcurrently[T].shouldIncludeServiceduplicated — can move topkg/commontoday (no barrier).concurrency.MaxParallelismFromEnv,execution.ConcurrencyFromEnv,gcpRegionConcurrency) →common.PositiveIntFromEnv.common.SavingsPct(onDemandTotal, committedTotal)returning 0 whenonDemandTotal <= 0. (Pairs with I-09.)pkg/errorshas zero importers — adopt (recommended; helps 4xx/5xx consistency) or remove. No-delete: explicit decision.logvspkg/logging(~50/50, sometimes same file) — standardize library/provider onpkg/logging.internal/apigod files (handler_purchases 1787, router 825, handler_accounts 1490, handler_ri_exchange 844) + directproviders/*reach-through — route via a use-case layer, split by resource.frontend/src/modules/.Evidence. Report 12 D1-D5, A1-A5, S1-S3, with exact file lists.
Suggested fix. Land the no-barrier ones first (D3, D4, D5, A2, S1 decision); make the A1 module decision and document the rationale; treat god-file splits (A3, A4) as incremental.
References. Source: report 12. The savings-formula guard (D5) is a prerequisite for I-09's clean fix. PR #858 (go.work).
Filed from automated adversarial code review (see docs/code-review/). Source finding(s): 12 A1-A5, D1-D5, S1.
Staged refactor plan (approved direction: full refactor incl. module collapse)
Full execution-ready plan:
docs/code-review/14-refactor-plan.md(file:line call sites, tests, CI/Docker/Makefile implications, verification per stage).HARD precondition — sequencing
Do not start until the in-flight PRs against
feat/multicloud-web-frontendthat touch the refactor's target files have merged. They rewrite the exact files this refactor rewrites (all provider clients,internal/api,internal/server/app.go, the frontend god files). Blocking set captured 2026-06-07: #1036 #1037 #1038 #1039 #1040 #1041 #1042 #1043 #1044 #1045 #1046 #1047 #1049 (+ PR #858 go.work, obsoleted by Stage 2). Land the refactor on its own branch off the shared branch and rebase before each stage (base keeps moving).Stages (ordered by risk/value)
common.SavingsPct(fixes NaN-into-scorer), D4common.PositiveIntFromEnv, D3 moveshouldIncludeService, A2 logging standardize, S1 adoptpkg/errorsproviders/{aws,azure,gcp}(+ optionallypkg/) into root module; drop 4replacedirectives; no import-path rewrites (paths preserved); fix CI govulncheck loop, Dockerfile per-module COPYs, Makefile, go.work dispositionCollectConcurrently[T]inpkg/concurrency; rewrite the 3 provider fan-outs; ctx.Err-after-Wait + semaphore-at-call + deterministic-merge invariant testsinternal/apisplit (cutproviders/*reach-through first); A4 decomposerecommendations.ts/settings.tsintofrontend/src/modules/; A5 FE/BE cross-ref commentsDependency graph: GATE → Stage 1 → Stage 2 → Stage 3 (3 hard-depends on the unified module). Stage 4 runs in parallel with 2/3 once Stage 1 lands (it touches
internal/api/frontend, not the provider module graph). A4 also waits on #1046/#1049.Proposed sub-issues (for owner approval — NOT yet created)
refactor(common): centralise savings-% into common.SavingsPct, guard zero denominator (D5)— p1/severity:high/this-sprint/many/effort:m/type:bugrefactor(common): common.PositiveIntFromEnv, delegate 3 env readers (D4)— p2/low/this-quarter/internal/effort:s/chorerefactor(common): move shouldIncludeService to pkg/common (D3)— p2/low/this-quarter/internal/effort:s/chorerefactor(logging): standardise provider/library layers on pkg/logging (A2)— p2/low/this-quarter/internal/effort:m/chorerefactor(errors): adopt pkg/errors for api 4xx/5xx mapping (S1 decision: adopt)— p2/medium/this-quarter/many/effort:m/chorerefactor(build): collapse provider Go modules into root module, drop replace directives (A1/S2)— p1/medium/this-quarter/internal/effort:l/chorerefactor(concurrency): generic CollectConcurrently[T], dedup 3 provider fan-outs (D1/D2/S3)— p2/medium/this-quarter/internal/effort:m/chorerefactor(api): route provider access via use-case layer + split god handlers (A3)— p2/medium/eventually/internal/effort:l/chorerefactor(frontend): decompose recommendations.ts into modules/ (A4)— p2/low/eventually/internal/effort:l/chorerefactor(frontend): decompose settings.ts into modules/ (A4)— p3/low/eventually/internal/effort:m/chorechore(validation): add FE/BE cross-reference comments for mirrored validation (A5)— p3/low/eventually/internal/effort:s/chore