OptiCat Catalog Assistant ReviewDelivery, evidence, and next steps
Library contents
All library documents

Current implementation and release gates

Contract 2026-09-16.1: behavior, architecture, verification, rollout and remaining live/domain gates.

mdCurrent139 lines · 9 min read
docs/implementation/2026-09-14-release.mdView source on GitHub

Contract: 2026-09-16.1. Status: local release candidate; live validation and promotion pending.

Architecture and decisions

flowchart LR
  UI[Open conversation and typed selections] --> Route[Validated query and shared request budget]
  Route --> Planner[Bounded language interpretation]
  Route --> MCP[Python MCP over Streamable HTTP]
  MCP --> Resolve[Catalog identity and reference caches]
  Resolve --> API[OptiCat HTTP adapter]
  API --> Verify[Completeness and verification policy]
  Verify --> UI
  Route --> Audit[Server-authored append-only evidence]
  Audit --> Admin[Authenticated evidence viewer]
Diagram source (Mermaid), shown as text.

The Python service is the sole production catalog executor. The legacy TypeScript adapter remains available as historical code but the query route never falls back to it. The application renders catalog claims deterministically. AI interpretation has an eight-second timeout and cannot supply catalog evidence. Models, provider configuration and hosting remain unchanged.

Pydantic defines the wire contract. scripts/export-tool-contracts.py exports JSON Schema and TypeScript wire types. The web client validates with the exported schema plus the domain invariant that incomplete evidence cannot support not_found. SDK tool errors retain their structured domain result. Both new tools use the same envelope.

State lasts only while the conversation is mounted. Legacy requests carry at most 12 dialogue messages of 2,000 characters each. The integrated upstream v2 feature also retains an open-thread archive (at most 1,000 turns / 2 MB request); recent dialogue, extractive older summaries and read-only history retrieval share a bounded model prompt. Cancelled or late responses cannot commit another turn’s state. Returned products are candidates, not automatic selections. Year/model/VIN changes invalidate dependent configuration. Latest explicit qualifiers replace prior qualifiers. Ordinals bind to returned candidates; ambiguous references ask for selection. Typed actions re-resolve the exact catalog identity. Signed continuations contain the original plan, query and session, and expire after 30 minutes.

Catalog capabilities

Ten tools cover readiness, vehicle search, applications, exact fitment, interchange, supersession, VIN, details, attribute search and comparison. Attribute search scans at most 200 candidates and returns at most 50 matches; continuation preserves unreturned matches. Missing/incomparable attributes remain unknown. Comparison accepts two to four identities, preserves independent failures and normalizes supported units with 1% relative tolerance. Neither attribute agreement nor interchange establishes fitment.

Missing makes resolve only from a complete, current catalog-derived index scoped to the credential and region. Without an index hit, bounded year-wide catalog facets provide the same complete-coverage check; incomplete or ambiguous coverage asks for the make. AI make hints cannot select one of several catalog matches. Abbreviated years are checked against catalog year facets. Reference caches expire after 15 minutes and are bounded. Incomplete make/model pages are not cached as complete.

OPTICAT_SUPERSESSION_TYPE_S_CONFIRMED defaults to false. Enable only after confirming the meaning and direction of S-coded relationships. Explicit replaces/replacedBy fields remain directional evidence. Fixture configuration that enables S semantics is not live validation.

Execution and evidence

A customer request has a 55-second execution deadline, at most 40 upstream attempts, at most 20 allocated attempts per tool and three concurrent tasks. Every retry consumes an attempt. Timeouts and Retry-After waits are clipped to remaining time. A lost response is charged its full allocation; known unused attempts can be reused. Browser cancellation reaches the MCP client and awaited Python HTTP work. Completed primary fitment evidence survives an interrupted alternative search.

Started and settled trace events are appended with distinct sequence numbers and a stable step ID. The browser and admin viewer project that same event model. Supporting evidence includes request parameters, bounded redacted response excerpts, retry attempts, retrieval times, contract/version metadata and evidence references. Excerpts are not a byte-for-byte archive of the entire catalog. Audit failure is visible separately from the catalog answer.

Only the server database writer can insert execution evidence. Existing rows retain legacy_client_capability; new rows are labeled server_v2. Browser feedback uses a distinct signed capability scoped to a run, expiring after one hour. Anonymous/authenticated roles cannot directly write feedback or execution records. Privileged admin reads continue under RLS.

Hosted request controls use atomic database leases: 60 requests/minute globally, eight active globally, 20 requests/minute per purpose/caller bucket, three active per bucket. Leases expire after 60 seconds. Missing hosted controls fail closed. Local development uses a bounded in-memory limiter. Hosted MCP authentication also fails closed when its internal token is absent.

Requirement → implementation → verification

Requirement Implementation Verification
Missing attributes are not false negatives Shared policy.py evaluation; search and VIN outcomes Python test_hardening.py
No implicit selection or stale configuration Planner context and typed actions conversation-state.test.ts, real planner route tests
Full grouped refinement Controlled form with expandable/searchable options Browser integration journey
All records and explicit comparison Result browser, typed product identities, compare tool Browser integration journey and Python unit conversion tests
Context across short replies Bounded dialogue and persistent pending questions Real route and browser Mustang journeys
One contract Generated JSON Schema/types; runtime validation Contract drift and protocol tests
Bounded retries/cancellation Shared allocation, SDK cancellation, clipped HTTP deadlines Client retry/deadline tests and request budget tests
Trustworthy audit Server writer, immutable event tables, feedback capabilities PostgreSQL role/policy tests and capability tests
Live-only production flow No direct fallback or simulated recommendations Route failure regression
Failure visibility Per-product/per-task states and audit status Comparison failure, route audit-outage tests

Reproduce local checks

npm ci
uv sync --project poc/opticat-mcp-v2
npm run check:tool-contracts
npm run typecheck
npm test
npm run lint
uv run --project poc/opticat-mcp-v2 pytest poc/opticat-mcp-v2/tests
npm run build
npx playwright install chromium
npm run test:integration

The integration configuration starts the real Next.js app, Python MCP and HTTP adapter. Only the upstream vendor data is replaced. It disables AI for deterministic browser regression and does not contact a production database or OptiCat. Screenshots are labeled local fixture verification and saved under .context/evidence/. Model-enabled live accuracy is a separate gate.

Database verification uses a fresh, isolated PostgreSQL cluster with Supabase auth helper stubs: apply tests/database/bootstrap.sql, all migrations in filename order, then tests/database/evidence-security.sql. The tests exercise real grants/RLS, admin metadata, immutable evidence and atomic lease limits. They do not validate Supabase login/session issuance.

Preview and deployment runbook

  1. Provision the preview app/server and use environment-specific credentials. Set server-only SUPABASE_SECRET_KEY, MCP_INTERNAL_TOKEN and CATALOG_CAPABILITY_SECRET (the latter can fall back to the server database secret). Do not install an OptiCat key on the web app.
  2. Apply the additive evidence migration in preview, then deploy the matching app and MCP contract together. The migration revokes the old browser writer grants, so the previous app cannot serve as a compatible writer after migration.
  3. Build an account-scoped vehicle index using the operator command below. Its default years come from the historical evaluation corpus. Keep the file private; package it with the MCP or set OPTICAT_VEHICLE_INDEX_PATH to its deployed location.
  4. Run npm run preflight -- --app-url <preview-app> --mcp-url <preview-mcp> with MCP_INTERNAL_TOKEN supplied by the environment. Retain the redacted report. Health/configuration alone are not proof of entitlement.
  5. Run the historical 50 journeys and ten-tool release matrix against the exact deployment pair. Repeat high-risk language cases three times with the configured model. Record each case as passed, product defect, catalog limitation, entitlement limitation, or awaiting domain confirmation.
  6. Obtain three positive and three negative supersession examples, S-code direction confirmation, paging/brand/VIN scope, an entitled image-bearing product and qualifier-rule sign-off. Cases without evidence remain qualified and are excluded from positive claims.
  7. Conduct the planned review with three parts staff, three catalog engineers and three executive/buyer participants. Record task completion and usefulness; no participant outcomes have been claimed by this implementation.
  8. Promote only after the release checklist passes. Keep the exact app/MCP deployment identifiers and migration state in the handoff.
uv run --project poc/opticat-mcp-v2 python -m opticat_mcp_v2.vehicle_index --output .context/vehicle-index.json
# Or bound index building to specific agreed years:
uv run --project poc/opticat-mcp-v2 python -m opticat_mcp_v2.vehicle_index --years 1997,2018,2020 --output .context/vehicle-index.json

Rollback

Roll back the application and MCP as a compatible pair. Keep the stronger evidence grants and immutable historical records. An older application requires a forward-compatible server-writer patch before reuse; do not restore anonymous evidence-writing privileges. A failed or unconfigured preview remains unavailable rather than claiming catalog success. No production migration or promotion is performed by local checks.

Presenter guide and release gates

Use discovery/eval/demo-journeys-v2.json for twelve live journeys. Begin with the problem and desired decision, run the query, refine the material detail, inspect a product, then open its evidence trace when the engineer asks. Use New chat between unrelated stories. On an outage, show the operational outcome and retry when ready; there is no replay mode.

Required release outcomes: no unsupported positive fitment/replacement claims, no evidence-induced false negatives, accessible records/options, inspectable supporting operations, and no critical correctness/audit defects. Target initial progress within one second and p95 completion within 15 seconds for simple queries or 30 seconds for composed queries; all requests stay within the execution deadline. These are acceptance targets, not a measured live performance claim. Usability targets are 90% completion of answerable entitled tasks and average usefulness of 4/5.

Outstanding external gates

Live index construction, account-entitlement confirmation, model-enabled live replay, domain approval, participant review, hosted migration and deployment promotion remain separate from fixture/local validation. Historical live results belong to the previous contract and remain labeled accordingly in the Tool Atlas.

Integrated upstream changes

This release includes main commits efc9901, 5d0dd05 and 0cf66fd: bounded legacy dialogue, the v2 archive/reducer, exact-subject provenance, make hints and year-wide facet inference. Their regression tests remain in the combined suite. The existing CONVERSATION_VERSION=2 flag is preserved. Catalog claims are now rendered deterministically rather than rewritten by the conversation model. The ten-tool public contract is 2026-09-16.1, with schema-hash compatibility checks described below.

Contract collision protection

The frozen integration baseline is main 1ced403 (vehicle intelligence, PR #34). Badge/model hints, catalog correction controls and their tests are preserved. The release uses 2026-09-16.1 plus a SHA-256 hash of the registered tool descriptions, annotations, inputs and shared output schema. Both the web health gate and preflight require the version and schema hash to match. A reused version label cannot make a different tool surface compatible. This protects interface compatibility; live correctness still requires the domain and deployment gates above.

Recorded local verification — 2026-09-15

Check Result
Web unit/integration tests 264 passed
Python service, client, resolver and protocol tests 138 passed
Main UI regression suite 33 passed; 4 v2-specific checks run in the dedicated suite
Dedicated conversation browser suite 7 passed
Browser → real Python MCP → HTTP adapter journeys 4 passed
Production build, TypeScript, ESLint, Python lint, contract drift Passed
Isolated PostgreSQL grants, RLS, immutable evidence and lease checks Passed

Suite counts overlap and are intentionally reported separately. Browser/adapter evidence uses clearly labeled catalog fixtures; this is not a live accuracy score. Local screenshots and detailed logs are under .context/evidence/ and .context/verification-summary.json. The temporary PostgreSQL VM and local test servers were removed after validation. No hosted migration, production deployment or stakeholder messages were performed by this implementation.

Review screenshots

Captured on /demo by npm run test:integration against the real local query route, Python MCP and HTTP adapter with synthetic upstream catalog data:

The fixture banner distinguishes these UI checks from live catalog acceptance; the audit warning is expected because this suite does not use a production database.

View Demo