ADR-0190: Navin Enterprise Production Planning Agent, industrial product layer above the Control Plane
- Status: proposed (2026-11-04)
- Deciders: Navin Enterprise lead, UC-08 session
- References:
agent_uses_cases/08_Industrie_Planification_Production.md, decisions of 2026-11-04 (.navin/continuity/DECISIONS.md: UC-06 to UC-10 identities, one shared frontend, backend derived by copy, template ids limited to 40 characters), ADR-0176 (Banking Back-Office, pattern of copied generic modules), ADR-0180 (shared frontend shell), ADR-0181 and ADR-0183 (sibling insurance agents used as copy reference), contractcontracts/v1/agent-product-manifest.schema.json, OPA packageeai.industrie_planification(deploy/policies/opa/industrie_planification.rego), contractscontracts/v1/industrie-planification-production-copilot-event.schema.jsonandcontracts/v1/industrie-planification-production-action-request.schema.json, Manager templatenavin-industrie-planification-agent(published: false).
Context
An industrial site wants to consolidate its demand (firm orders, forecasts, released production orders), know its
real capacity (machines, shifts, qualifications, maintenance), check material availability, produce finite-capacity
scheduling proposals, compare scenarios (rush order, breakdown, late material), have a plan approved and published
to the ERP and MES, and follow execution to replan the remainder. The brief imposes eight modules
(production-inputs, resource-calendars, material-feasibility, scheduling-models, schedule-runs,
production-scenarios, plan-publications, production-replanning), an explicit server-side state machine
(input_snapshot_ready, validated, simulation_running, feasible or infeasible, review_pending,
approved, published, acknowledged, superseded) with 409 on every forbidden transition, quantities and
amounts as Decimal carrying a unit or a currency, and absolute prohibitions: never relax a safety, qualification
or mandatory maintenance constraint for an economic objective; never present a merely feasible plan as optimal;
never turn a timeout without solution into a fictitious schedule; never overwrite a started production order; never
a local published status without the source system's acknowledgement.
The platform already provides identity, OpenFGA, OPA, the Action Gateway with maker-checker, durable jobs, the document pipeline (ClamAV, YARA-X, Docling behind the Control Plane), RAG, memory and observability (ADR-0176). No real ERP, MES, CMMS or WMS is connected in the repository: connectors run in a deterministic sandbox and declare their capabilities.
Decision
1. The solver proposes, the human approves, the ERP/MES confirms
A scheduling run (schedule_runs) is a versioned deterministic finite-capacity engine (engine_version,
ruleset_version, input_snapshot_id, as_of, parameters, time_limit, solver_status, objective, gap).
Its result is a PROPOSAL: feasible, feasible_time_limit (feasible solution under the limit, never announced
optimal), infeasible (explained conflicts, proposed resolution options) or unknown (timeout without solution, no
schedule produced). A validator independent from the solver re-checks resources, precedences, calendars and
materials on the produced solution. Approving a scenario requires a human other than its preparer (maker-checker in
the Action Gateway, OPA rule, OpenFGA relation). Publication to the ERP/MES goes through an action plan with an
expected version (If-Match), an idempotency key and the connector's confirmation: a send without acknowledgement
stays unknown_pending_confirmation and is re-read; acknowledgements are tracked per order and partial rejections
reconciled without duplicating already confirmed orders.
2. Generic modules copied, business modules written
As in ADR-0181 and ADR-0183: the generic modules of the reference backend (config, errors, i18n, authz,
audit, jobs, worker, controlplane, db/session, Action Gateway, connectors, observability, document
pipeline, copilot, ops, api/common, app) are copied into navin_planification with no change other than the
package name, the schema (planification), the prefix (/api/v1/industrie-planification-production) and the OPA
package. The eight business tables of section 18.1 (production_orders, routing_operations,
resource_calendars, material_requirements, planning_snapshots, schedule_scenarios, schedule_operations,
plan_publications) and the cross-cutting tables of section 18.2 are written in migration 0001_foundation with
tenant-then-project RLS, composite (tenant_id, parent_id) foreign keys and CHECK constraints on statuses, units
and quantities carrying their unit.
3. Non-relaxable hard constraints and materials never consumed
Safety, qualification and mandatory maintenance constraints are flagged hard and non_relaxable as data; no
objective weight can cancel them and relaxing another hard constraint requires an explicit scenario and an approval.
A stopped machine or an unqualified operator is never made available through a penalty. Material feasibility
(material_feasibility) logically reserves quantities per scenario without touching real stock; a planned receipt
carries its status and confidence and is never counted as physical stock; two orders consuming a material available
for only one produce an explicit conflict, never a double reservation.
4. Delegation matrix and separation of duties in OPA
The eai.industrie_planification package reuses the fail-closed pattern of the sibling products: operation types as
data (eai.config.industrie_planification), preparation and approval roles, second human mandatory for
scenario_approve, plan_publish, frozen_horizon_change, exceptional_priority, overtime_assumption,
subcontracting_assumption, maintenance_move, constraint_relaxation and rule_change,
safety_constraint_relax always denied, dated revocable delegations, rail always none, applies true only for
planification.* and document.* actions. Obligations announce proposal_not_decision and
unknown_pending_confirmation.
5. Reality prevails
The status of a production order is the one taken from the MES/ERP (execution_status), never inferred from a
scenario; already produced quantities are not rescheduled; if a structuring source changes after approval, the
publication is blocked and the scenario revalidated. The copilot only receives sourced facts and cites the snapshot
and the solver output; memory keeps neither secrets nor personal data.
Consequences
- Positive: a complete product without frontend (product manifest, backend, migrations, policies, contracts, acceptance through the real API, prepared template) sharing the sibling agents' foundation; a later extraction of the generic modules into a library stays mechanical.
- Negative and limits: no external solver (OR-Tools or other) is embedded, the delivered algorithm is a deterministic finite-capacity heuristic documented as such; ERP, MES, CMMS and WMS are only exercised in a deterministic sandbox; reports are csv and json only; no frontend is delivered by this mission (ADR-0180); the template is not published to the catalogue.