Files
wyndham-ARR/.project-docs/10-decisions/ADR-006-daily-price-review.md
2026-08-06 22:40:18 +08:00

2.5 KiB

ADR-006: PRICE_UNMATCHED uses a frozen, source-replayed manual review

Status

Accepted

Date

2026-08-06

Context

The fixed price table can legitimately lack an exact normalized price key. Treating every such result as a permanent failure makes staff re-upload unchanged XML after a separate price decision, while accepting edited spreadsheets or mutable price-table changes would create a second intake path and weaken provenance.

Decision

Only a non-empty error set entirely composed of PRICE_UNMATCHED becomes review_required. ARR stores one privacy-minimized review case per run, grouped missing keys, revisioned actor/price history and candidate comparisons. It creates no Finance version, daily download, rejected Finance version, arr.processing_failed, or monthly event.

After every key has a non-negative integer value, ARR freezes canonical JSON bound to the job, case, original XML SHA-256, business date, processor version, rule hash and complete issue set. The operator/API surface uses integer text (including explicit 0); ARR normalizes that value to exact numeric(18,2) and canonical .00 manifest text before replay. Finalization re-materializes the registered source XML and replays it with the fixed price table plus that manifest. Independent validation must accept the same manifest before one atomic Finance-version activation, case completion and arr.daily_version_committed event.

Consequences

  • POST /api/jobs remains XML-only; there is no Excel draft/download/upload-back workflow.
  • Staff can change only a reviewed missing key's non-negative integer price, including explicit 0; fixed pricing rules and XML fields remain immutable.
  • Review mutations require session authentication, CSRF and optimistic revision checks. Frozen item/manifest facts are immutable and permanently audited without free-form notes or guest detail.
  • Infrastructure failures after freeze become generation_failed and may retry with the identical manifest. A deterministic final replay failure closes the review and run as failed. Processor/rule identity drift requires cancel then fresh upload.
  • The legacy direct_mcp path uses an isolated v3 success/failure projection: it rejects manual overrides and maps price misses to normal v3 failures, so it cannot gain review behavior from the active v4 processor.
  • database/017_daily_price_review.sql
  • database/018_daily_review_manual_override_artifact.sql
  • arr_web/programmatic.py
  • arr_ingestion/postgres.py
  • arr-opera-daily-ingest/scripts/process_daily.py