factory simulator

Free-text factory descriptions, parsed by LLM agents, scheduled and scored by a deterministic core.

Factory Simulator turns a paragraph of prose about a factory into a schedule. LLM agents parse the description into a typed config, a deterministic EDD job-shop simulator runs one to three scenarios over it, and a briefing explains the metrics. The use case is the planner's morning question: what will go wrong today, and which jobs are at risk.

It began as a fixed ten-stage pipeline. On 2025-12-03 I replaced it with a plan-then-execute agent: the model emits a typed plan, and a deterministic engine executes that plan against a tool registry under max-step and LLM-call budgets, returning a partial answer when a budget runs out. The alternative was adopting LangGraph; the in-repo demo script instead maps each hand-rolled piece to its LangGraph equivalent. The orchestrator shrank to a 31-line wrapper.

Two guards make the parsing checkable. Before any LLM call, regex extraction pulls the machine and job IDs the text states explicitly; the model's parse is then measured against that ground truth, so a dropped or invented machine is a number, not a suspicion. And every LLM response passes through one choke point: OpenAI JSON mode into a Pydantic schema. openai is imported inside that function, so the test suite monkeypatches the boundary and runs without an API key or the package installed.

Evaluation is a 13-case adversarial corpus of clean, messy, and hostile factory texts, checked against structural invariants rather than golden outputs: valid machine references, minimum durations, non-empty jobs. The React frontend renders the agent's plan, its data flow, and the LLM call log beside the answer.

Numbers, from git log and AST counts at HEAD: 93 commits from 2025-11-19 to 2025-12-06; 419 test functions across 20 backend files; zero frontend tests.

What is wrong with it is mostly what the rewrite left behind. The README documents the pre-rewrite system: it describes POST /api/simulate, and the server exposes only POST /api/agent. The CLI imports a function the rewrite deleted, so python -m backend.main raises ImportError. The backend has no dependency manifest, and there is no CI. Determinism holds only for the scheduler core — the LLM calls set no temperature and no seed. The fallback policy contradicts itself: a demo-factory tool coexists with a system prompt that forbids silently using it.

The core still cannot invent a schedule. Everything around it drifted in three weeks.