4.2 KiB
Code review — NEO-136 (E7M3-04)
Date: 2026-06-15
Scope: Branch NEO-136-e7m3-reputation-operations-apply-delta — commits e9abc8b … 536f635 vs main
Follow-up: Review findings addressed in follow-up commit (applied-delta rollback, ops id normalization, AAA nit).
Base: main
Verdict
Approve with nits
Summary
This branch lands E7M3-04: server-internal ReputationOperations.TryApplyDelta orchestrates standing mutation via IFactionStandingStore, append-only audit via IReputationDeltaStore, and compensating standing rollback when audit append fails. Supporting types ReputationApplyOutcome and ReputationApplyReasonCodes cover ops-level pre-flight denies and store passthrough. Ten AAA unit tests plus host DI smoke exercise happy path, clamp, unknown faction, invalid delta/id/source, audit-append rollback, non-writable player, and factory resolution. 780 server tests pass locally. Risk is low — infrastructure-only, no HTTP or Godot wiring (NEO-138+). One non-blocking correctness gap: compensating rollback uses -deltaAmount rather than the actual applied delta when clamping occurred, which can leave wrong standing on rare audit-append failure after a clamped apply.
Documentation checked
| Path | Result |
|---|---|
docs/plans/NEO-136-implementation-plan.md |
Matches — shipped ops, types, tests, README, module/alignment updates reconcile with plan; AC checklist marked complete. Plan flow step 1 cites explicit FactionStandingIds normalization at ops layer; implementation delegates player/faction normalization to stores (see Suggestions). |
docs/plans/E7M3-pre-production-backlog.md |
Matches — E7M3-04 scope (auditable apply orchestration, no client counterpart, no HTTP) aligns with implementation. |
docs/decomposition/modules/E7_M3_FactionReputationLedger.md |
Matches — Status line notes E7M3-04 ReputationOperations landed (NEO-136). |
docs/decomposition/modules/documentation_and_implementation_alignment.md |
Matches — E7.M3 row updated for E7M3-04 / NEO-136. |
docs/decomposition/modules/module_dependency_register.md |
N/A change — register row already lists FactionStanding / ReputationDelta contracts. |
server/README.md |
Matches — new ReputationOperations section documents commit order, rollback policy, pre-flight denies, and “do not call standing store alone.” |
Blocking issues
None.
Suggestions
-
Compensating rollback delta when clamping — On audit append failure, rollback usesDone. Rollback now uses-deltaAmount:-appliedDeltawhereappliedDelta = mutation.NewStanding - mutation.PreviousStanding; audit row records applied delta. TestTryApplyDelta_ShouldRestoreClampedStanding_WhenAuditAppendFailsadded. -
Ops-layer id normalization (plan alignment) — Plan §2 step 1 says normalize viaDone.FactionStandingIdsbefore store calls.TryApplyDeltanormalizes player/faction ids at the ops boundary; audit row built from normalized values.
Nits
Nit:Done.TryApplyDelta_ShouldApplyStandingAndAppendAudit_WhenHappyPath—auditStore.GetDeltasForPlayer(PlayerId)runs in the Act phase; per csharp-style, verification reads belong in Assert.GetDeltasForPlayermoved to Assert.- Nit:
ReputationApplyOutcomeon store-boundary deny returns standings from the mutation outcome (good); pre-flightDeny()zeroes standings — callers must not treat0as “neutral read” oninvalid_delta/invalid_sourcedenies (documented implicitly by reason codes). - Nit: Telemetry hook comment for NEO-141 is correctly placed on the success path only — no action needed.
Verification
Commands run during review (passed):
dotnet test NeonSprawl.sln --filter "FullyQualifiedName~ReputationOperationsTests"
dotnet test NeonSprawl.sln
Author should confirm PR CI green before merge. No manual QA doc required (server engine only per plan). Intentional follow-on: reward bundle rep wiring (NEO-138), quest accept gate eval (NEO-137), HTTP GET standing (NEO-139), Godot HUD (NEO-142+).