diff --git a/.planning/phases/12-orders-invoices-company-matching/12-CONTEXT.md b/.planning/phases/12-orders-invoices-company-matching/12-CONTEXT.md
new file mode 100644
index 0000000..e6779e3
--- /dev/null
+++ b/.planning/phases/12-orders-invoices-company-matching/12-CONTEXT.md
@@ -0,0 +1,198 @@
+# Phase 12: Orders/Invoices & Company Matching - Context
+
+**Gathered:** 2026-07-11
+**Status:** Ready for planning
+
+
+## Phase Boundary
+
+Pulse gains historical PAX8 cost data for reconciliation over time (order/invoice
+line items into `pax8_orders`/`pax8_order_items`), and every PAX8 company is
+automatically linked to its Autotask counterpart by fuzzy name matching, or
+explicitly flagged for review rather than silently guessed. No `/pax8` UI (Phase
+14 — this phase only populates `pax8_company_match_review`), no scheduler/cron
+wiring (Phase 13), no manual-resolution admin flow (Phase 14 — PAX8-12).
+
+
+
+
+## Implementation Decisions
+
+### Match Confidence Threshold
+- **D-01:** Auto-link (no human review) only on a high-confidence fuzzy match
+ — not exact-string-only, but a high similarity bar (near-identical names:
+ punctuation/case/whitespace differences, minor typos). The user explicitly
+ chose "be conservative — fewer auto-matches" over a looser threshold or
+ deferring the number to the planner's judgment alone: bias toward flagging
+ borderline cases for review rather than risking a wrong auto-link, since
+ this data feeds cost/billing reconciliation. The planner should document
+ the exact numeric threshold chosen (and the library/approach) directly in
+ the plan so it's easy to find and tune later — this is an initial number,
+ not a permanently fixed one.
+- **D-02:** Even an otherwise-exact name match must be flagged for review
+ (not auto-linked) if it's ambiguous against more than one Autotask company
+ sharing that same/very-similar name (e.g. franchise locations, "Acme Inc"
+ vs "Acme Holdings Inc"). No silent tie-breaking — ever, even when the
+ string match itself looks perfect.
+
+### No-Match & Ambiguous-Candidate Handling
+- **D-03:** When a PAX8 company has zero reasonably-similar Autotask
+ candidates at all, still create a `pax8_company_match_review` row with an
+ empty `candidate_company_ids` array — never silently drop it (PAX8-11).
+ This flags it into the admin queue so Phase 14's UI can offer a manual
+ search/pick, or confirm there truly isn't a matching Autotask company yet.
+- **D-04:** Ambiguous-match review rows carry the **top 3** highest-scoring
+ Autotask candidates (matches the existing `device_link_review` precedent's
+ style of showing a small ranked list, not every plausible match).
+- **D-05:** PAX8 companies still sitting unresolved in the review queue are
+ **re-scored on every subsequent full sync**, not matched once and left
+ alone — candidates can improve over time (e.g. a renamed/newly-created
+ Autotask company scores better later) without requiring a manual
+ re-trigger. This does NOT apply to already-resolved matches: SC#4's
+ idempotency guarantee (a manually-confirmed match is never overwritten by
+ a later sync) still holds — only rows with `resolved_at IS NULL` are
+ eligible for re-scoring.
+
+### Claude's Discretion
+- **Exact threshold value / library choice** — user wants "conservative,"
+ not a specific number. The planner should research common fuzzy
+ name-matching approaches (e.g., trigram similarity via Postgres
+ `pg_trgm`, or a JS library) and pick/document a concrete high threshold,
+ erring toward fewer auto-matches per D-01.
+- **Company name normalization nuances** (legal suffixes like LLC/Inc/Corp,
+ punctuation, abbreviations) — not discussed in depth this session (user
+ deselected this gray area). Planner/researcher should investigate whether
+ Autotask company names in this instance commonly carry legal suffixes
+ PAX8 names don't (or vice versa) and decide normalization rules
+ accordingly; err toward the conservative stance (D-01/D-02) if uncertain.
+- **Orders/invoices historical lookback window** — not discussed in depth
+ this session (user deselected this gray area). `migrations/091`'s comment
+ states "sync pulls full order history on first sync in a later phase"
+ (this phase) — the planner should confirm this is still the intent (full
+ history, no bounded window) during research, and flag to the user if
+ PAX8's invoices API makes "full history" impractical (e.g., no
+ pagination limit safety, or a very large per-company invoice count).
+
+
+
+
+## Canonical References
+
+**Downstream agents MUST read these before planning or implementing.**
+
+### Project scope & requirements
+- `.planning/PROJECT.md` — Current Milestone: v2.0 PAX8 Integration section
+- `.planning/REQUIREMENTS.md` — PAX8-06, PAX8-10, PAX8-11 (this phase's
+ requirement IDs); note PAX8-12/13/14 (manual resolution, `/pax8` UI) are
+ Phase 14, not this phase
+- `.planning/ROADMAP.md` — Phase 12 section (goal, 4 success criteria,
+ depends on Phase 11)
+
+### Prior phase foundation this phase builds on
+- `migrations/091_pax8_tables.sql` — `pax8_orders` (header, Invoice-shaped
+ per its own inline comment: total/status/currency mirror PAX8's Invoice
+ object, sourced from PAX8's `/invoices` resource not `/orders` — confirm
+ exact field mapping against the live API during research),
+ `pax8_order_items` (line items, hard FK to `pax8_orders`, soft ref to
+ `pax8_products`), and `pax8_company_match_review` (copied field-for-field
+ from `device_link_review` — `candidate_company_ids BIGINT[]`,
+ `match_confidences TEXT[]`, partial unique index enforcing one open
+ review per PAX8 company). All three tables already exist — this phase
+ populates them, does not alter schema unless research finds a genuine gap
+ (e.g., no column yet exists on `pax8_companies` to record a confident
+ auto-match — the planner must decide where a non-reviewed, auto-linked
+ match gets stored)
+- `.planning/phases/11-company-catalog-subscription-sync/11-SUMMARY.md` /
+ `11-02-SUMMARY.md` — `Pax8SyncService.fullSync` shape, soft-delete
+ tombstone pattern (`id <> ALL($1::uuid[])`), `Pax8EntitySyncResult`/
+ `Pax8SyncResult` types this phase's new entity syncs should conform to
+- `lib/services/pax8-client.ts` — read-only pagination helpers
+ (`listAllCompanies`/`listAllSubscriptions`/`listAllProducts`); this phase
+ needs an equivalent for invoices (`listAllInvoices` or similar) following
+ the same `paginateAll()` shape
+- `lib/services/pax8-sync-service.ts` — existing `Pax8SyncService` class
+ this phase extends (or a sibling matching service) with orders/invoices
+ sync + company-matching logic
+
+### Existing patterns to follow
+- `lib/services/device-link-reconciler.ts` — direct precedent for the
+ match/review/confidence pattern this phase implements for companies:
+ cascading match strategies ranked by confidence, `LINK_CONFIDENCE_RANK`
+ ordering, `device_link_review` candidate storage shape. D-04's "top 3"
+ and D-02's tie-flagging should follow this file's structure/conventions
+ closely.
+- `migrations/080_device_xref_company_id.sql` — schema `device_link_review`
+ was copied from; useful for understanding the review-row lifecycle
+ (detected_at, resolved_at, resolved_by_user_id, resolved_to_company_id,
+ resolution_note) that `pax8_company_match_review` mirrors
+- Soft-delete / tombstone convention (`is_deleted`, `deleted_at`,
+ `id <> ALL($1::uuid[])`) — established in Phase 11, applies to
+ `pax8_orders`/`pax8_order_items` too
+
+
+
+
+## Existing Code Insights
+
+### Reusable Assets
+- `lib/services/device-link-reconciler.ts` — confidence-ranked matching
+ logic to adapt for company name fuzzy matching (different matching
+ criteria — name similarity instead of serial/MAC/hostname — but same
+ candidate-ranking and review-row-write shape)
+- `lib/services/pax8-sync-service.ts` — existing tombstone/upsert
+ primitives from Phase 11 to extend for orders/order_items
+- `postgresClient` singleton — parameterized queries, no ORM
+
+### Established Patterns
+- Sync services live at `lib/services/-sync-service.ts`; this phase
+ likely extends the existing `pax8-sync-service.ts` rather than creating a
+ new file, since it's the same integration's sync orchestration
+- `*_match_review` tables follow a detect → flag → admin-resolves lifecycle;
+ `resolved_at`/`resolved_to_company_id` gate re-scoring per D-05
+
+### Integration Points
+- Extends `lib/services/pax8-sync-service.ts` (or a new
+ `pax8-matching-service.ts` — planner's call) with orders/invoices sync +
+ company matching, invoked from the same `fullSync()` orchestration Phase
+ 11 built
+- No route/nav/UI integration in this phase (`UI hint: no` per ROADMAP.md)
+ — `pax8_company_match_review` rows are written here, consumed by Phase
+ 14's UI
+
+
+
+
+## Specific Ideas
+
+No specific UI or behavioral references beyond the discussed decisions.
+The five numbered decisions above (D-01 through D-05) are the concrete
+specifics: conservative high-confidence auto-match threshold (tune-able,
+not a fixed permanent number), always-flag-on-any-tie even for exact
+string matches, empty-candidate-list flagging for true no-match cases,
+top-3 candidate cap for ambiguous cases, and continuous re-scoring of
+unresolved (not yet human-confirmed) review rows on every sync.
+
+
+
+
+## Deferred Ideas
+
+Two gray areas were surfaced but not discussed this session (user chose to
+focus on match confidence and no-match/ambiguous handling instead) — not
+deferred to a future phase, just left as Claude's Discretion within this
+phase (see above):
+- Company name normalization nuances (legal suffixes, punctuation,
+ abbreviations)
+- Orders/invoices historical lookback window (full history vs. bounded)
+
+No capabilities were deferred outside this phase's boundary — discussion
+stayed within Phase 12's scope. (The `/pax8` UI, manual resolution flow, and
+scheduler cron wiring are already sequenced into Phases 13-14 per
+ROADMAP.md/REQUIREMENTS.md, not deferred from this discussion.)
+
+
+
+---
+
+*Phase: 12-orders-invoices-company-matching*
+*Context gathered: 2026-07-11*
diff --git a/.planning/phases/12-orders-invoices-company-matching/12-DISCUSSION-LOG.md b/.planning/phases/12-orders-invoices-company-matching/12-DISCUSSION-LOG.md
new file mode 100644
index 0000000..ba47eaa
--- /dev/null
+++ b/.planning/phases/12-orders-invoices-company-matching/12-DISCUSSION-LOG.md
@@ -0,0 +1,84 @@
+# Phase 12: Orders/Invoices & Company Matching - Discussion Log
+
+> **Audit trail only.** Do not use as input to planning, research, or execution agents.
+> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
+
+**Date:** 2026-07-11
+**Phase:** 12-orders-invoices-company-matching
+**Areas discussed:** Match confidence threshold, No-match & ambiguous-candidate handling
+
+---
+
+## Match Confidence Threshold
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Exact name match only | Only auto-link on byte-identical names (case/whitespace-insensitive). Safest but likely means most companies land in review. | |
+| High-confidence fuzzy match | Auto-link when similarity clears a high bar (e.g. ≥90-95%), covering near-identical names. | ✓ |
+| You decide | Planner picks a threshold based on research. | |
+
+**User's choice:** High-confidence fuzzy match
+
+**Follow-up: threshold tuning approach**
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Set an initial number, tune later | Planner picks ~90-95% as a starting point, documented for later adjustment. | |
+| Be conservative — fewer auto-matches | Bias toward flagging borderline cases; accept more manual review since this feeds cost/billing reconciliation. | ✓ |
+| You decide | No strong preference. | |
+
+**User's choice:** Be conservative — fewer auto-matches
+**Notes:** User explicitly prioritized avoiding wrong auto-links over reducing review burden, since this data feeds cost/billing reconciliation.
+
+**Follow-up: duplicate/tie edge case**
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Yes — always flag on any tie | Even an exact name match gets flagged if ambiguous against multiple same/similar-named Autotask companies. | ✓ |
+| No — exact match always wins | Exact string equality is strong enough signal on its own, even with a second similarly-named company present. | |
+
+**User's choice:** Yes — always flag on any tie
+**Notes:** Reinforces the conservative stance — never silently pick between look-alike companies (e.g. franchise locations).
+
+---
+
+## No-Match & Ambiguous-Candidate Handling
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Flag with an empty candidate list | Still create a review row with an empty candidate array for true no-match cases, so it surfaces in the admin queue. | ✓ |
+| You decide | Planner decides mechanics as long as PAX8-11 (never silently dropped) is satisfied. | |
+
+**User's choice:** Flag with an empty candidate list
+
+**Follow-up: ambiguous-candidate count**
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Top 3 | Cap review candidates at the 3 highest-scoring Autotask companies, matching `device_link_review` precedent. | ✓ |
+| All above a "plausible" floor | Show every candidate clearing a low relevance floor, regardless of count. | |
+| You decide | Planner picks a reasonable cap. | |
+
+**User's choice:** Top 3
+
+**Follow-up: re-scoring cadence for unresolved reviews**
+
+| Option | Description | Selected |
+|--------|-------------|----------|
+| Re-score every sync until resolved | Keep re-evaluating unresolved PAX8 companies each full sync; resolved matches still never overwritten. | ✓ |
+| Match once, don't re-touch until resolved | Leave flagged companies alone until an admin resolves them — simpler, stable candidate list between admin visits. | |
+
+**User's choice:** Re-score every sync until resolved
+**Notes:** Candidates can improve over time (e.g. a renamed/newly-created Autotask company scores better later) without requiring a manual re-trigger. Does not affect SC#4's idempotency guarantee for already-resolved matches.
+
+---
+
+## Claude's Discretion
+
+- Exact numeric fuzzy-match threshold and matching library/approach (e.g. Postgres `pg_trgm` vs. a JS similarity library) — user wants "conservative," not a specific number; planner researches and documents the chosen value.
+- Company name normalization nuances (legal suffixes like LLC/Inc/Corp, punctuation, abbreviations) — gray area was surfaced but not selected for discussion this session.
+- Orders/invoices historical lookback window (full history vs. bounded window) — gray area was surfaced but not selected for discussion this session; `migrations/091`'s inline comment indicates full history was the original intent, to be confirmed during research.
+
+## Deferred Ideas
+
+None — discussion stayed within Phase 12's scope. No new capabilities were proposed; the two undiscussed gray areas above were left to Claude's discretion within this phase, not deferred to a future phase.