Skip to main content

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), contract contracts/v1/agent-product-manifest.schema.json, OPA package eai.industrie_planification (deploy/policies/opa/industrie_planification.rego), contracts contracts/v1/industrie-planification-production-copilot-event.schema.json and contracts/v1/industrie-planification-production-action-request.schema.json, Manager template navin-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.