Deterministic Admin Agent product file actions

This PR moves uploaded product CSV rename/import work from model-reconstructed mutations to fingerprinted server-owned preflight, approval, execution, and verification.

Author @mehulshinde PR #6365 State open draft Branch main ← mehul/dealops-jyz3-recovery Area apps/server/src/dealops3/configAgent Files 44 Diff +9259 / -150 Note diff supplied truncated

What it adds

Typed server executors for product CSV work: catalogFileAction for file-backed renames/updates and catalogCsvImport for create/import workflows.

What it changes

Preflight now persists bounded approval evidence and fingerprints the file, catalog snapshot, operation spec, and derived plan before any write.

What it fixes

Two-column rename files no longer fall into generic import logic, LLM-authored projections, or retry loops after terminal preflight failures.

What it preserves

Actual catalog writes still stage drafts through existing catalog product staging paths; the PR changes ownership and verification around those writes.

Uploaded file
Conversation state
Deterministic planner
Catalog snapshot
Server executor
Catalog drafts

1. Why this exists

Before
  • Uploaded files were treated like generic imports too early.
  • The model had to infer mappings and catalog fields before deterministic preflight.
  • A rename could invent unsupported fields such as productName and never persist an executable plan.
  • Currency was copied into custom attributes instead of structural listPriceCurrencies.
After
  • The user states the operation; the server binds it to the current uploaded file.
  • Preflight produces one concrete plan with bounded examples and a typed executor.
  • Approval runs the exact fingerprinted plan after re-reading file and catalog state.
  • CSV currency remains structural and passes product attribute validation.
Verified fixture
100Xendit source rows pass deterministic import validation

Rows keep USD in listPriceCurrencies, not attributes.currency.

Verified rename
57Merge Test Org products matched

14 change, 43 are already correct, and 16 unmatched rows are reported/skipped.

Validation
85focused/router tests called out in PR description

Plus typecheck, types build, Prettier, and git diff --check.

Input visibility: the user-supplied diff is truncated. This explainer reflects the PR description, full file list, and the visible diff excerpts; it does not claim to cover unseen hunks line-by-line.

2. What changes

New protocol boundary
catalogFileActionProtocol.ts
Shared fingerprint helpers for file content, catalog snapshots, and derived file-action plans.
catalogFileActionPreflight.ts
Read-only preflight that persists approvable state or blocked diagnostics.
catalogFileActionExecution.ts
Server-side approval execution for exact catalogFileAction executors.
Deterministic file planning
catalogProductFileAction.ts
Plans rename/update actions from CSV rows plus current catalog coverage.
catalogProductFileToolPolicy.ts
Selects safe tool capabilities based on typed operation: read, file rename/update, file import, or approved direct mutation.
tools/catalogProductFileActionTool.ts
Exposes read-only preflight to the Product Catalog Agent.
CSV import recovery
catalogProductCsvImport.ts
Adds structured mapping recovery, indexed mappings, compact Xendit pricing/COGS parsing, and structural currency handling.
catalogProductCsvImportExecution.ts
Executes approved CSV imports using persisted mappings and exact draft readback checks.
csvImportClarification.ts
Builds bounded clarification state for unresolved CSV core fields.
Router + state
conversationStore.ts
Adds catalog file action state, CSV import state compare-and-set, execution leases, pending-plan clearing by executor, and intent generation guards.
router.ts
Routes typed approvals directly to server execution instead of back through the orchestrator.
agents/*.ts
Requires operation-first Product Catalog delegation and restricts mutation tools until server-owned approval.

Behavior matrix

Scenario Old failure mode New behavior Primary guard
Single attached two-column rename file LLM tries generic import fields or asks for product category/channel/currency. Bypasses LLM-authored catalog projection and preflights rename from catalog value coverage. preflightAttachedCatalogProductRename
Ambiguous or missing source matches Could partially invent or retry. Persists blocked diagnostics; only preflightPassed or preflightPartial can create an approval. blockingIssues
Approved file changed after preflight Execution could trust stale model payload. Re-reads R2 file and rejects drift before catalog reads/writes. CATALOG_FILE_DRIFT
Catalog changed after preflight Approval could write against a different matching set. Re-plans against the current catalog and blocks on drift/truncation. CATALOG_DRIFT
Duplicate approval click Could stage twice or re-enter the agent. Returns stored terminal result without new reads or writes. terminalResult
CSV import execution reports success without exact drafts Could claim complete with missing or wrong drafts. Fails closed unless verified draft skuIds/write fingerprints match expected output. readStagedCatalogWriteFingerprints

3. How it works

1. Operation classification

askProductCatalogAgent now receives an explicit operation such as fileRename, fileImport, read, or directMutation.

Tool availability follows that operation, not the model’s interpretation of CSV columns.

2. Read-only preflight

Preflight reads the current-turn file and a bounded catalog snapshot, infers or applies an operation spec, and returns awaitingApproval only when the plan is executable.

Blocked plans persist issues, not approval executors.

3. Fingerprinted approval

The pending action plan carries an executor with kind, runId, and planFingerprint.

Approval dispatch is typed; the router does not classify by English summary text.

4. Verification

Execution re-reads file/catalog, re-plans, writes drafts, then verifies exact staged SKU IDs or write fingerprints before reporting success.

Duplicate approvals return stored terminal evidence.

File-action planner rules

Rule Why it matters Visible tests
Infer rename direction from catalog value coverage. A two-column file can be a complete rename without import-only fields. catalogProductFileAction.spec.ts
Use indexed column refs: { header, index }. Duplicate headers and reordered columns are detected instead of silently misread. STALE_COLUMN_REF, duplicate-header mapping tests
Collapse identical duplicate rows. Retried/exported rows do not create false conflicts. “collapses duplicate rows when they describe the exact same update”
Block contradictory duplicate source keys. No last-row-wins behavior for catalog writes. DUPLICATE_SOURCE_KEY
Support unmatchedPolicy: skip. Merge-style files can update matched products while reporting unmatched rows. preflightPartial

CSV import fixes

Old CSV import hazards
  • Alternate headers could throw or trigger LLM JSON fallback.
  • Duplicate headers were not safe if only header text identified mappings.
  • Currency became a custom attribute.
  • Terminal blockers could be summarized away and retried.
New CSV import behavior
  • needsMapping supports one deterministic same-tool retry.
  • needsUserInput bundles all unresolved core mappings into one form.
  • Currency populates listPriceCurrencies.
  • Terminal failures set terminal=true and doNotRetry=true.

4. What it does not change

Explicit non-goals

5. Risks / rollback / open questions

Primary risk: stricter blocking can expose previously hidden ambiguity. Files that used to “work” by model luck may now stop at needsUserInput, preflightBlocked, CATALOG_DRIFT, or CATALOG_TOO_LARGE_FOR_SAFE_PREFLIGHT. That is intentional for deterministic approval, but it changes user-facing behavior.
Rollback shape

Because the change is mostly server routing/state/tool policy, rollback is code-level: disable typed file-action routing and return to prior Product Catalog Agent tool exposure.

Be careful: rolling back also reopens the original retry-loop and unsupported projection failure modes.

Operational guardrails
  • Organization lock prevents concurrent approved catalog execution.
  • Compare-and-set prevents superseded runs from writing terminal state.
  • Execution leases prevent an in-progress action from being overwritten by a new user turn.
Open review focus
  • Confirm fingerprint canonicalization is stable across all plan shapes.
  • Check that approval summaries remain concise with bounded examples only.
  • Verify truncation thresholds are acceptable for large org catalogs.

Reviewer checklist

CorrectnessApproval executor must reject plan/file/catalog drift before writes.
IdempotencyDuplicate approval must return stored terminalResult.
SafetyModel must not receive mutation tools for unclear file intent.
UXBlocked CSV mapping should ask one bundled question, not repeated single-field prompts.