# HubSpot case catalog audit — 2026-08-26

## Bound evidence

- Imported acceptance base: `pingcap-inc/nexuscrm-hubspot-acceptance@8fb9d7c76e09e5373f5c3cf138a424b40447cd8e`.
- Runtime/L2 source readback: `pingcap-inc/nexuscrm-pingcap-pack@8fd9250076b6d8019e0f2361b9e0ff66c7f693fc`.
- Latest broad live evidence reviewed: GitHub Actions run `31876567043` (123 selected, 72 passed, 0 failed, 51 skipped).
- Latest targeted live evidence reviewed: GitHub Actions run `32687850218` (8 selected, 8 passed).
- Initial catalog: 132 cases. Current catalog: 88 cases. Retired/moved out: 52 cases. Added or restored with executable current contracts: 8 cases, including one post-audit provider-only harness smoke and the performance-suite-required 20- and 100-contact Set Campaign cases.

The live reports are evidence inputs, not blanket acceptance. A case was not
retired merely because an environment blocked or skipped it. The audit also
compared case behavior, assertions, current L2 registration, and the explicit
performance/pressure contracts.

## Current acceptance classes

| Class | Count | CI meaning |
| --- | ---: | --- |
| `release_required` | 64 | Routine functionality case; every case must pass. A failed, blocked, or skipped result fails the acceptance gate. |
| `targeted_required` | 12 | Narrow regression or provider-only harness smoke, excluded from routine full to avoid duplicate cost; must pass whenever explicitly selected. |
| `performance_required` | 2 | Dedicated 20- and 100-contact Set Campaign workloads, excluded from functionality; each must pass in the performance suite. |
| `performance_observation` | 1 | Optional dedicated `k-camp-10` 2,000-contact/action Set Campaign workload with exactly 2,000 attributed Leads and CampaignMembers inside the fixed 20-minute terminal poll and 43-minute case limit. A failed result stays failed without blocking the combined performance suite when its two required cases pass. Selecting only this case still exits nonzero on failure. All three cases share the workflow's 43-minute execution budget. |
| `pressure_required` | 2 | 8-worker × 2k and 8-worker × 4k matrix cells; must pass. |
| `pressure_should_pass` | 2 | 16-worker × 2k and 16-worker × 4k cells; tracked as a quality target, not a release blocker. |
| `pressure_diagnostic` | 5 | 8-worker × 6k, 16-worker × 6k, and all three 32-worker cells; diagnostic capacity observations. |

The complete 88-case list is generated from the case metadata rather than
copied into a second hand-maintained inventory:

```bash
node scripts/case-inventory.mjs
```

CI calls the same read path and rejects an optional case that has no supported
targeted, performance, or pressure contract.

## Retired cases

The files remain recoverable from the imported base commit above.

### Replaced by stronger or canonical coverage (21)

- `attr-01` — weaker than deterministic association case `k-assoc-01`.
- `en-02` — subset of default-enabled regression `fix-2752`.
- `in-cc-001` — duplicate of canonical contact/company routing `in-routing`.
- `in-rej-01` — generic invalid-picklist path covered by stricter `fix-2480`.
- `auto-sync-01` — explicit-enable subset of `fix-2752`.
- `rt-nx-01`, `rt-nx-02` — duplicate round-trip coverage; canonical case is `fix-2784`.
- `rt-nx-04` — weaker blocked variant of strict `rt-nx-05`.
- `out-001` — subset of `out-004`.
- `out-002` — split canonical coverage exists in `out-acct` and `fix-2790`.
- `in-owner-01` — weaker than owner regression `fix-2582`.
- `contact-lead-inbound-country-api`, `contact-lead-inbound-industry-case-api`, `contact-lead-inbound-smoke-api`, `contact-lead-inbound-status-api` — redundant API-shaped variants of retained inbound routing/mapping cases.
- `lead-contact-outbound-title-api` — redundant API-shaped variant of retained outbound field mapping coverage.
- `out-vm-miss-01`, `out-vm-miss-02`, `vm-miss-no-attempt` — overlapping value-map miss behavior retained in canonical strict cases.
- `out-err` — generic outbound error handling duplicated by retained rejection/retry regressions.
- `inf-ob` — generic observability assertion without a distinct executable acceptance contract.

### Stopped or unregistered product paths (7)

- `k-assoc-02`, `k-perm-01`, `merge-co`, `merge-deal` — depended on company/deal inbound flows that exist as legacy files but are not registered by the current L2 companion pack.
- `k-form-02`, `k-form-03`, `k-form-04` — depended on retired form-specific routing variants rather than the current generic inbound path.

### Invalid campaign/list implementations (8)

- `k-camp-01`, `k-camp-02`, `k-camp-03`, `k-camp-04`, `k-camp-06`, `k-camp-07`, `k-camp-08`, `k-camp-09` — stale campaign/list fixtures or assertions and no valid execution of the current list-trigger contract.

### Non-executable reliability claims (6)

- `k-conflict-01`, `bi-conflict` — did not execute or prove the declared conflict-winner/convergence policy.
- `k-resync-01`, `k-retry-01`, `k-retry-02` — described replay/retry behavior without exercising the required failure mechanism.
- `k-soak-01` — did not execute the declared two-hour soak workload.

### Misclassified or superseded performance claims (8)

- `acq-bulk-440`, `bulk-in`, `bulk-out`, `perf-flow`, `bi-lat-01`, `perf-in-01`, `perf-out-01`, `perf-out-03` — lacked an enforceable throughput/latency aggregation contract, or were superseded by the explicit pressure matrix and `k-camp-10` performance contract.

### No distinct acceptance value (1)

- `k-form-05` — obsolete form variant with no independent current product assertion.

### Outside the HubSpot synchronization boundary (1)

- `fix-3296-flowdef-pack-owned-tooling` — Salesforce Tooling/AppService error-projection parity (#5366), not HubSpot webhook, inbound, outbound, Campaign, form, owner, or convert behavior. It must live in the CRM administration/Tooling suite rather than consuming the HubSpot release gate.

## Added or restored executable coverage (5)

- `contact-propertychange-coalescing` — re-authored from closed-unmerged PR #3901; now covers sibling preservation, explicit clear/newer-value ordering, lifecycle source time, all three late attribution fields from #4405, numeric `portalId` from #5075, D3 terminal evidence, and a 60-second settled readback.
- `webhook-retry-receipt-idempotency` — attempt 0 and attempt 1 produce two verified receipts but one Event, one Runtime command, and one mapper effect (app-packs PR #551).
- `post-convert-contact-storm` — starts from a NexusCRM-native outbound-synced Lead (#3089), converts it, then proves a provider-backed ten-event storm converges the active Contact (#2829).
- `ai-vertical-en-dash` — exact U+2013 EN DASH Industry/Vertical mapping from #5220/#5301 survives an unrelated sparse delta and settle window.
- `suite-durable-health` — runs last and blocks uncertain outbound lanes, pending work behind a poisoned LinkKey, and run-created nonterminal/dead WorkItem or PlatformCommand residue (#5488).

## Strengthened retained coverage

- The four invalid D3 recovery oracles now follow WorkItem through `ConnectorRuntimeHandoffReceipt` to the Runtime-owned PlatformCommand; the history-sequence fixture also uses the TiDB-compatible explicit derived-table alias.
- `k-form-01` now reads back settled HubSpot firstname/lastname/company/email, guarding the #3398 placeholder echo.
- `out-owner` now proves an unbound owner clears the local shadow and is suppressed from the provider payload while a simultaneous business update still lands (#2591/#2593).
- `out-contact` now pins Contact owner-shadow serialization as `hubspot_owner_id` without expanding its provider-free acceptance boundary.
- `in-c-019` and `in-c-fields` now retain delayed settled Industry/Country oracles; the old duplicate #3016 files remain retired.

## Open acceptance gaps, not silently closed

The audit retires invalid case implementations; it does not declare these
requirements passed:

- real SC400 list-trigger acceptance against the current active list/flow;
- an actual two-hour soak workload with time-bound assertions;
- deterministic provider 429/5xx, ambiguous-effect/manual-compensation, restart-idempotency, and resync fault injection;
- live V2 legacy-RemoteLink finalization and second-same-link liveness proof after the restoration candidate is published through the normal release tuple.

These should return only as executable cases with current fixtures, an explicit
acceptance contract, and a CI lane capable of producing the claimed evidence.
