TX-1
The Auto-Fix Loop

How it works

A full walkthrough of the Chicago Bottleneck scenario — from the user typingrun baselineto a confirmed optimal solution, using the real data values.

Context: This walkthrough runs inside a project tab connected to the Chicago network. TX-1 supports multiple projects with multiple tabs — each tab maintains its own solver session, stream history, and status. See Workspace & UI in the docs.
The Setup — Chicago Bottleneck
FACTORY_SHENZHEN (50,000 unit supply)
        │
        │  SEA — $4.20/unit — 21 days
        ▼
WH_CHICAGO_01 (capacity: 10,000 ← the bottleneck)
        │
   ┌────┼────┐
   │    │    │
   ▼    ▼    ▼
CUST_NAPERVILLE  CUST_EVANSTON  CUST_AURORA
   (4,800)          (3,600)        (3,000)

Total Q3 demand: 11,400 units  →  Deficit: 1,400 units  →  INFEASIBLE
1

User types the command

The user types run baseline into the TX-1 terminal prompt.

❯ run baseline

The CommandBar calls invoke("run_command") — this goes through the Tauri Rust layer to the FastAPI sidecar, which returns {"status":"accepted"} immediately. The graph runs asynchronously in a background thread. All progress comes back over WebSocket.

2

Intent Classification

Dispatcher · Haiku

The first LangGraph node sends the query to Claude Haiku with strict instructions: return one of four intent categories, no prose.

{ "intent": "SOLVE_REQUEST", "entities": { "network": "chicago" } }

The graph routes to solver_engine. The terminal streams: Intent → SOLVE_REQUEST · Network → CHICAGO

3

OR-Tools Solver Runs

Solver Engine

OR-Tools GLOP (linear programming) loads the Chicago network from SQLite and sets up the Transportation Problem:

  • Factory outflow ≤ 50,000 (supply cap)
  • Chicago warehouse outflow ≤ 10,000 (capacity cap) ← this binds
  • Each customer receives exactly their demand
  • Minimise: total transport cost

The solver returns INFEASIBLE. No combination of flows can route 11,400 units through a 10,000-unit bottleneck.

status: INFEASIBLE
violation: WH_CAPACITY violated at WH_CHICAGO_01. Deficit: 1,400 units.
4

Archivist Query

Archivist · ChromaDB

Before the Strategist reasons, the Archivist queries ChromaDB for semantically similar past violations. On first run the store is empty. After the first approved fix, subsequent runs surface the historical context — informing the Strategist's headroom choice.

Archivist: no prior history for this violation.
5

Strategist Reasons

Strategist · Sonnet

Claude Sonnet receives the violation and a minimal context payload — only the relevant rows from SQLite, never the full database:

  • node_capacities row for WH_CHICAGO_01
  • Total Q3 demand aggregated from demand_forecast
  • Historical context from Archivist (if any)

Sonnet reasons: the minimum viable fix is to raise capacity to at least 11,400. It proposes 12,000 — 5% headroom buffer.

6

Dry-Run Validation

Before the fix is ever shown to the user, the Strategist proves it works:

BEGIN; UPDATE node_capacities SET max_capacity_units = 12000 WHERE node_id = 'WH_CHICAGO_01'; -- Re-check: 11,400 ≤ 12,000 → PASSES ROLLBACK; ← database unchanged

Only if dry_run_passed = true does the proposal proceed. This is the primary defence against hallucination.

7

Sensitivity Explorer renders

Sensitivity Analysis Card

Before the action card, a Sensitivity Explorer appears showing five capacity scenarios:

Capacity Sensitivity — WH_CHICAGO_01
MINIMUM11,4000%$3,500/mo
RECOMMENDED12,0005%$5,000/mo
COMFORTABLE13,50018%$8,750/mo
STRATEGIC16,00040%$15,000/mo
MAXIMUM22,800100%$32,000/mo

↑↓ arrow keys navigate between scenarios. Context before action.

8

InfeasibilityCard renders

HITL Approval Gate

The action card appears below the explorer. The graph is now paused — the LangGraph Human Approval Gate is blocked on a threading.Event waiting for the user's decision. All older terminal entries dim to 30% opacity.

The user sees: violation details, Strategist rationale, before/after comparison table, the SQL patch, and dry-run confirmation.

Waiting for approval… (⌘↵ Approve · Esc Dismiss)
9

User approves

User presses ⌘↵. The frontend calls invoke("resolve_approval", {decision: "APPROVED"}). The buttons lock immediately — no double-trigger possible.

Rust posts to localhost:8765/approve/{card_id}, which sets the threading.Event in the Approval Registry. The graph unblocks.

10

DB patched + Archivist updated

The apply_fix node executes the real SQL patch and writes the audit log:

UPDATE node_capacities SET max_capacity_units = 12000 WHERE node_id = 'WH_CHICAGO_01'; INSERT INTO audit_log (agent_id, table_name, row_id, column_name, previous_value, new_value, user_approved) VALUES ('STRATEGIST_v1', 'node_capacities', 'WH_CHICAGO_01', 'max_capacity_units', '10000', '12000', 1);

The Archivist also stores the approved fix in ChromaDB — the system now has memory of this violation pattern for future sessions.

11

Solver reruns → SUCCESS

The graph loops back to solver_engine. OR-Tools runs again with the patched capacity. This time: OPTIMAL.

status: SUCCESS
total_cost: $47,880.00
units: 11,400 shipped

A green SolveSuccess card renders. The full loop — from run baseline to confirmed solution — completed with one human decision.

All terminal commands

check healthData quality scan → HealthArtifact card with readiness score
run baselineChicago Auto-Fix loop — triggers INFEASIBLE → Approve → SUCCESS
run amsterdamEU network Auto-Fix loop — Rotterdam → Amsterdam → Brussels/Frankfurt/Paris
resetRestore Chicago WH_CHICAGO_01 to 10,000 units (dirty data)
reset amsterdamRestore Amsterdam WH_AMSTERDAM_01 to 15,000 units (dirty data)
reset allRestore both networks simultaneously
historyShow what the Archivist has learned from past approved fixes