From e9eae7fb2d20aabd2024b54bd8deee073aa92caa Mon Sep 17 00:00:00 2001 From: Tony Balascio Date: Fri, 14 Aug 2026 16:30:56 +0000 Subject: [PATCH] =?UTF-8?q?docs(architecture):=20findings-to-cbr=20mapping?= =?UTF-8?q?=20for=20audit=5Fengine=20=E2=86=92=20Canonical=20Business=20Re?= =?UTF-8?q?cord=20v0.1.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- docs/architecture/findings-to-cbr-mapping.md | 165 +++++++++++++++++++ 1 file changed, 165 insertions(+) create mode 100644 docs/architecture/findings-to-cbr-mapping.md diff --git a/docs/architecture/findings-to-cbr-mapping.md b/docs/architecture/findings-to-cbr-mapping.md new file mode 100644 index 0000000..9d77519 --- /dev/null +++ b/docs/architecture/findings-to-cbr-mapping.md @@ -0,0 +1,165 @@ +# Audit Engine Findings → Canonical Business Record Mapping + +**Date:** 2026-08-14 +**Status:** Draft +**Owner:** Tony / VeriPath +**Scope:** Architecture + +Contract between `audit_engine.py` output (findings) and `canonical-business-record-v0.1.1.md` field states. + +--- + +## 1. Direct Field Mappings + +Each audit finding maps to one or more CBR domains. The finding's evidence drives the field's `status`, `evidence_tier`, and `action_risk`. + +| Finding ID | CBR Domain | CBR Field(s) Updated | +|------------|-----------|----------------------| +| `nap_phone_mismatch` | Contact | `phone` | +| `nap_address_mismatch` | Location | `street_address` | +| `nap_website_mismatch` | Contact | `website` | +| `hours_mismatch` | Hours | `regular_hours` | +| `rating_delta_high` | Proof & Reputation | `review_count`, `review_sources` | +| `rating_below_threshold` | Proof & Reputation | `review_count`, `review_sources` | +| `review_count_delta` | Proof & Reputation | `review_count`, `review_sources` | +| `reviews_stale` | Proof & Reputation | `review_sources` | +| `reviews_low_specificity` | Proof & Reputation | `review_sources`, `differentiators` | +| `category_fragmentation` | Identity | `industry` | +| `gbp_permanently_closed` | Identity | `industry` (closed status flag) | +| `gbp_temporarily_closed` | Identity | `industry` (closed status flag) | +| `no_description` | Proof & Reputation | (description field — not yet in CBR) | +| `no_price_level` | Services and Pricing | `price_point` | +| `no_photos` | Proof & Reputation | (photos field — not yet in CBR) | +| `low_photos` | Proof & Reputation | (photos field — not yet in CBR) | +| `missing_jsonld_schema` | Identity | (schema field — not yet in CBR) | +| `schema_wrong_type` | Identity | (schema field — not yet in CBR) | +| `missing_canonical` | Identity | (schema field — not yet in CBR) | +| `missing_og_tags` | Identity | (schema field — not yet in CBR) | +| `website_unreachable` | Contact | `website` | +| `no_gmaps_url` | Location | `geo_coordinates` (GBP claim URL) | +| `low_coordinate_precision` | Location | `geo_coordinates` | + +--- + +## 2. Provenance Rules + +### Status Assignment + +| Engine Finding Severity | CBR Field `status` | When | +|------------------------|-------------------|------| +| Finding detected, 1 source | `observed` | Single surface has data but no corroboration | +| Finding detected, 2+ independent sources agree | `verified` | GBP + Apple Maps match, or website + GBP match | +| Finding detected, sources contradict | `disputed` | GBP says one thing, Apple says another | +| Previous audit had value, window expired | `stale` | Freshness policy exceeded without re-check | + +### Evidence Tier Assignment + +| Source Combination | `evidence_tier` | `source_independence` | +|--------------------|----------------|-----------------------| +| GBP only | `tier_3` | `unknown` | +| Apple Maps only | `tier_3` | `unknown` | +| Bing Places only | `tier_3` | `unknown` | +| GBP + Apple Maps | `tier_2` | `independent` (different data pipelines) | +| GBP + Bing Places | `tier_2` | `independent` | +| Apple Maps + Bing Places | `tier_2` | `independent` | +| GBP + Apple + Bing | `tier_2` | `independent` | +| Website schema + GBP | `tier_2` | `independent` | +| Owner confirmation | `tier_1` | `independent` | +| Website footer + website schema | `tier_3` | `same_origin` | + +**Rule:** Multiple extractions from the same website (footer text, JSON-LD, meta tags) count as `same_origin`, not independent. Only cross-platform matches upgrade tier. + +### Freshness Policy Alignment + +Each field inherits the freshness window from `evidence-freshness-policy-v0.1.md`: + +| CBR Domain | Freshness Window | `fresh_until` calculation | +|-----------|------------------|--------------------------| +| Hours | 7 days | `audit_timestamp + 7d` | +| Services/Pricing | 14 days | `audit_timestamp + 14d` | +| Booking | 7 days | `audit_timestamp + 7d` | +| All other fields | 30 days | `audit_timestamp + 30d` | + +If a finding detects a mismatch on a field whose freshness has expired, set `fresh_until` to the audit timestamp + that domain's window. + +--- + +## 3. Severity → action_risk Translation + +| Engine Severity | CBR `action_risk` | Rationale | +|----------------|------------------|-----------| +| `immediate` | `high` | Data is actively harmful (wrong address, closed status, phone mismatch). Downstream agents must not act on stale values without re-check. | +| `high` | `high` | Significant credibility signal loss (no photos, rating below 4.0, no website). Display only; block transactions. | +| `medium` | `medium` | Optimization gap (category misalignment, low review specificity, missing price level). Display with timestamp and recheck notice. | +| `enhancement` | `low` | Nice-to-have (OG tags, additional photos). Informational display. | + +--- + +## 4. Gaps and Open Questions + +The following audit findings have **no clean home** in the current CBR v0.1.1 schema: + +| Finding | Gap | Proposed Resolution | +|---------|-----|-------------------| +| `no_photos` / `low_photos` | No `photos` field in CBR | Add `photos: { count, sources, last_updated }` to Proof & Reputation | +| `no_description` | No `description` field in CBR | Add `description` to Identity domain | +| `missing_jsonld_schema` / `schema_wrong_type` / `missing_canonical` / `missing_og_tags` | No technical schema fields in CBR | Add `technical_seo: { jsonld, canonical, og_tags }` as metadata domain | +| `website_unreachable` | Website status is boolean but CBR only stores URL | Add `website: { url, reachable, last_checked }` sub-object | +| `reviews_low_specificity` | CBR has `differentiators` but no structured review quality score | Add `review_quality: { specific_ratio, sample_size }` to Proof & Reputation | + +**Decision needed:** Do we extend CBR v0.1.2 to include these fields, or keep the engine findings separate from the canonical record until v1.0? + +--- + +## 5. Example: Phoenix Salon+Spa Address Mismatch + +**Finding:** +```json +{ + "id": "nap_address_mismatch", + "severity": "immediate", + "title": "Address inconsistent across 2 surface(s)", + "sub_score": "Digital Identity", + "evidence": { + "google": "1234 Main St, Ste 4, Los Angeles, CA 90012", + "apple": "1234 Main St, Los Angeles, CA 90012" + }, + "recommendation": "Standardize exact address format. GBP address is authoritative." +} +``` + +**Resulting CBR field state:** +```json +{ + "street_address": { + "value": "1234 Main St, Ste 4, Los Angeles, CA 90012", + "status": "disputed", + "evidence_tier": "tier_2", + "observed_at": "2026-08-14T00:00:00Z", + "verified_at": null, + "fresh_until": "2026-09-13T00:00:00Z", + "source_independence": "independent", + "sources": ["google_business_profile", "apple_maps"], + "action_risk": "high", + "conflict_detail": { + "google": "1234 Main St, Ste 4, Los Angeles, CA 90012", + "apple": "1234 Main St, Los Angeles, CA 90012" + } + } +} +``` + +**Decision logic:** +- GBP is authoritative → GBP value is the canonical `value` +- Apple disagrees → `status` is `disputed`, not `verified` +- Two independent sources → `evidence_tier` is `tier_2` +- Severity `immediate` → `action_risk` is `high` +- Domain is Location (regular field) → `fresh_until` is `audit + 30d` + +--- + +## Related Documents + +- `docs/architecture/canonical-business-record-v0.1.1.md` +- `docs/architecture/evidence-freshness-policy-v0.1.md` +- `implementation/auditing/audit_engine.py`