> ## Documentation Index
> Fetch the complete documentation index at: https://docs.prodexlabs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Configurator

> Walk a configurable product's option tree with Dexter, confirm each gated decision, and land a per-order parts list.

## Overview

The Configurator handles **configure-to-order** products: walk an option tree, make selections, pin material attributes, and land a concrete parts list for one real-world order. [Dexter](/product/ai-assistant) drives the walk — reading the order document, mapping it onto the template, and proposing each decision one at a time for you to confirm. You can override any decision at any point.

It operates on three layers:

| Layer                                                          | What it is                                                                                                                     |
| -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------ |
| **[Configuration Template](/product/configuration-templates)** | The possibility space for a product — every option class, material, and valid nested decision. Authored once per product line. |
| **[Configuration](/product/configurations)**                   | An identity-only container (name, description) grouping all the revisions for one real-world order, quote, or build slot.      |
| **Revision**                                                   | An immutable snapshot: the selections, material assignments, and notes that resolve the template to a concrete parts list.     |

The configuration row holds no state — every fact lives on a revision, and the revision with the highest `revision_number` is the active state. Reconfiguration writes a **new** revision; existing revisions are never edited. For how this group of artifacts fits together, see the [BOMs & Configuration overview](/product/bom-overview).

<Note>
  A **configuration template** here is its own artifact type, distinct from a Data [Pipeline](/product/templates) — they are separate entries in the product's artifact catalog. This page never means a pipeline when it says "template."
</Note>

## The Decision Model

A template presents decisions as **option classes**, each with a `selection_type`:

* `select_one` — exactly one option must be chosen
* `select_many` — zero or more options may be chosen
* `select_at_least_one` — one or more options must be chosen

Options can carry their own nested materials and option classes. Nested classes only become reachable once the containing option is selected — picking `diesel-engine` can expose a nested `turbo-configuration` class that was invisible until then.

Once options are decided, each reachable material needs its attributes pinned. Each **attribute value** is a `VariantCondition` — the same typed union [BOM variant conditions](/product/bom#variant-conditions) use (`boolean`, `discrete_text`, `discrete_number`, `range`).

<Tip>
  At revision time, prefer **fully-pinned** conditions: a single-element values list, or a concrete boolean. A range on a revision usually means a decision is unresolved — treat it as the trigger to ask, not something to leave in place.
</Tip>

## Phases and the State Script

A revision moves through four phases:

| Phase                 | Meaning                                                                             |
| --------------------- | ----------------------------------------------------------------------------------- |
| `pending`             | No decisions yet                                                                    |
| `selecting_options`   | Some, not all, reachable option classes are decided                                 |
| `assigning_materials` | Every reachable option class is decided; some materials still need attribute values |
| `completed`           | Every option class decided, every material pinned, no errors, no stale entries      |

Picking an option that unlocks nested classes returns the run to `selecting_options` until the new decisions land.

The **state script** is the single source of truth for where a run stands. Given the template and the current revision, it computes:

* `phase` — one of the four above
* `next` — the **frontier** of next decisions, each tagged by `kind` (`option_class` or `material`) alongside the reference it points at
* `stale` — selections or assignments whose addressing key is no longer reachable given current upstream selections
* `errors` — structural problems: unknown option-class or material IDs, cardinality violations, unknown entity slugs
* `resolved_materials` — the flat parts list implied by the current selections

Dexter re-calls the state script at the start of every turn and after every write — the chat transcript is not a substitute, because the projection shifts as decisions land.

<Note>
  Stale entries and errors must both be resolved before a revision can reach `completed`. Dropping stale entries is deterministic; error repairs apply directly only when there is exactly one valid fix (an obvious typo) — anything ambiguous becomes a user decision, gated through the same ask-confirm loop.
</Note>

## Creating a Configuration

1. **Pick the template.** One template per product line.
2. **Gather the order source.** Assemble the order document(s) you'll ground selections against — a PDF, spec sheet, customer email, or an ERP extract. These are cited on the `source` field of each assignment, not attached to the configuration itself.
3. **Selecting options.** Dexter proposes one option-class decision per round-trip — ask, then write. On confirmation it records the selection, re-calls the state script, and moves to the next class. Newly reachable nested classes appear as they unlock.
4. **Assigning materials.** For each reachable material, Dexter pins the attribute values. **Source-batching:** when one grounded source (an ERP extract, an order PDF, a mapping CSV) supplies values for many materials, a single confirmation authorizes the batch and one write lands them all — each assignment citing the same `source`. When a value can't be grounded in a shared source, Dexter falls back to asking per material.
5. **Complete.** When the phase reports `completed`, the resolved parts list is final for this revision.

<Note>
  Every selection, every material assignment, and every mid-run template edit is gated by an ask-confirm turn. Nothing is written without your confirmation — and once written to a revision, decisions only change by creating a new revision.
</Note>

### Provenance: `source`, `notes`, `revision_notes`

Three fields carry three different kinds of provenance:

| Field            | Lives on                | Answers                                                                                                         |
| ---------------- | ----------------------- | --------------------------------------------------------------------------------------------------------------- |
| `source`         | Material assignment     | *Where did the value come from?* — e.g. an ERP part reference, "customer order PDF, line 3", a mapping-file row |
| `notes`          | Selection or assignment | *Why was the decision made?* — justification, edge cases, what was considered and discarded                     |
| `revision_notes` | Revision                | *What changed in this revision vs. the prior one?* — empty on revision 1                                        |

<Warning>
  An empty `source` field is an audit-trail gap — not enforced by the state script, which won't block on it. But the whole point of the field is downstream traceability: an assignment no one can trace can't be evaluated at reconfiguration time. Fill it anyway.
</Warning>

## Reconfiguring

When a completed revision needs to change — the customer revised the order, a sourced value turned out wrong, a template edit cascaded — fork a new revision:

1. Read the latest revision.
2. Create a new revision with a descriptive slug (e.g. `rev-3-hardtop-swap`), `revision_number + 1`, and a `revision_notes` line naming the delta.
3. Carry forward every unchanged selection and assignment. Remove the entries that are changing — they become the open frontier the state script surfaces.
4. Resolve any new stale entries or errors, then walk the frontier to `completed` exactly like an initial run.

`revision_number` is immutable and the revision chain is the audit trail; the version chain is implicit in the numbering — there is no parent pointer, and there is no in-place edit.

<Tip>
  Prune more rather than less when carrying state forward — remove anything the change might cascade into, even if it's "probably still right," and let the ask-confirm loop bring values back with fresh verification. The fork is cheap, and the revision chain is the audit trail, so keep reconfiguring within it rather than starting over.
</Tip>

## Mid-Run Template Edits

When an order doesn't fit the current option set, the template can be edited during the run: the structural change is gated through ask-confirm, written to the [template](/product/configuration-templates), and a one-line entry is appended to the template's `revision_log`. The per-turn loop then resumes against the updated template. Flag known gaps at the start of a run — mid-run edits are supported, but they slow the walk.

## Relationship to BOMs, Planning, and Simulation

* Configuration Templates are **not [BOMs](/product/bom)** — they can't be used directly in planning or simulation. If something needs to feed the optimizer, build a BOM.
* Templates produce revisions; each revision carries a per-order parts list.
* [Planning](/product/planning-overview) consumes BOMs; [simulation](/product/simulation-overview) references entities directly through model nodes. Neither reads templates or revisions.
* Feeding a completed revision's resolved parts list into [planning demand](/product/demand-and-supply) is a manual or [pipeline-mediated](/product/templates) step — completing a revision does not auto-create demand orders.

## Best Practices

* **Shape the option tree around the customer's decision sequence**, not the manufacturing BOM structure.
* **Keep nesting shallow** (2–3 levels). Deep trees are hard to walk and hard to reconfigure.
* **Use `select_one` only when a "none" option is genuinely invalid** — otherwise `select_many` is more forgiving.
* **Correct early, not late.** A wrong selection near the top of the tree cascades through every nested class beneath it.
* **Structured order documents make runs faster.** Include part numbers in the order document or a companion file when the ERP can't be queried live.
* **Let source-batching do its job** during material assignment; don't confirm per material when one source covers many.
* **Fill `notes` and `source` diligently** — they are the audit trail.
* **Name revision slugs for what changed**, not for sequence: `rev-3-hardtop-swap`, not `rev-3`. Write `revision_notes` as the delta, not the final state.
* **Keep entity definitions in sync with templates** — especially the `part_number` attribute on every referenced entity (see [template authoring](/product/configuration-templates)).
