{
  "title": "Capture fee truncates instead of rounding half up",
  "severity": "P1",
  "relatedFeatures": "payments",
  "reproducibility": "always",
  "last_known_working": "Unknown at runtime; parent d08a680 uses applyRate, but was not tested.",
  "observed": "Capturing 200 minor units records a scheme fee of 2 and a merchant amount of 198. The RISK-02 fee assertion fails: actual 2, expected 3.",
  "expected": "TR4 requires half-up rounding. For a capture of 200 minor units, record a fee of 3 and a merchant amount of 197. RISK-02 also requires fee 149 and merchant amount 9850 for a capture of 9999. Fee plus merchant amount must equal the capture.",
  "reproduction": "1. From the 301-config fixture root, run:\n   node --experimental-strip-types --test --test-name-pattern '^\\[RISK-02\\]' test/service.test.ts\n2. Observe test/service.test.ts:112 fail: actual 2, expected 3.\n3. Inspect src/payments/service.ts:119-120: Math.floor gives fee 2; subtracting it from 200 gives merchant amount 198.",
  "environment": "301-config payments fixture; round-0 at aa7cebc with an uncommitted working tree; macOS (Darwin arm64); Node v26.9.0; node:test; TEST_CARDS.visa and EXPIRY from test/fixtures/cards.ts. Reproduced on 2026-09-29.",
  "error_output": "AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:\n\n2 !== 3\n\nactual: 2\nexpected: 3\noperator: 'strictEqual'\n\nFailing assertion: test/service.test.ts:112. Full output: docs/assets/lab-3-define/risk-02-output.txt",
  "context": "Impact: for the reproduced capture of 200, the fee account receives one minor unit too little and the merchant account one too much. The total remains 200.\n\nEvidence: the fee failure was reproduced separately from Task 1 Eval, which passed RETRY-01. Reproducibility 'always' refers to this capture case. Production exposure and frequency are unknown.\n\nDecision for payments-product: set repair priority and agree whether to investigate deployed versions and affected payments.\n\nRepair scope: use the existing applyRate helper in src/payments/service.ts; verify with the existing RISK-02 test. Keep retry coverage and refund policy separate.\n\nSelected evidence:\n- clean_review task 1: capture() now floors the scheme fee instead of rounding half up, contradicting TR4/RISK-02 and the RISK-02 test added in this same diff. (source: `.speed/features/payments/evidence/clean_review/1/467d7ec1-ef20-43ac-80c0-00ece22c69b3.json`)",
  "rationale": "The existing rounding requirement and failing RISK-02 test establish a fee regression. Track this bounded repair separately from retry-helper coverage and the unresolved refund-idempotency policy."
}
