Repository navigation
Architecture
Published from the source document. Propose an edit through a pull request; direct wiki edits are replaced by the next publication.
This is the implementation map for agents changing APEX. Read it after repository conventions, then follow the source and test links below. The current scheduling problem and planning vocabulary ship with the application release and have no separate schema versions. There is no separate legacy scheduler in this checkout.
Use the data model for field semantics, the operating guide for commands, and the migration audit for historical v2 evidence. This directory documents implemented behavior.
Cargo.toml is the workspace root and the apex-scheduler package with the apex library and the apex binary. The scheduling core is the apex-engine crate in core/; the control platform crates build on it without changing this executable. lib.rs exposes the modules; main.rs selects CLI commands and transports. The scheduler does not depend on Python, an LLM or an external solver. Repository Python/Node scripts support fixtures and verification.
flowchart TD
Agent[Agent client] --> Transport[transport.rs: MCP stdio, MCP HTTP, JSON HTTP]
Viewer[ui/mcp-app/compat.html: embedded viewer] --> Transport
CLI[main.rs: CLI] --> Service[service.rs: scenarios and saved artifacts]
Transport --> Service
CLI --> Search[xh.rs, xt.rs, xe.rs, improve.rs]
CLI --> Engine[xg.rs: common evaluation]
Service --> Search
Service --> Engine
Search --> Engine
Engine --> Model[compile.rs, domain.rs, language.rs: active model]
Model --> Dispatch[dispatch.rs: admissible construction decisions]
Dispatch --> Decode[xg.rs and calendar.rs: placement]
Decode --> Validate[validate.rs: independent checks and replay]
Service --> Store[Local .apex artifact store]
The application has five responsibility boundaries. Cargo crates inside them keep dependencies explicit; they are not separate deployment services.
| Directory | Responsibility |
|---|---|
core/ |
apex-engine crate: in-memory scheduling semantics, algorithms and independent validation |
middleware/api/ |
HTTP/MCP, authentication, events, workers and CLI entry points |
middleware/control/ |
Scenarios, immutable revisions, runs, approvals, package configuration and core invocation |
middleware/data/ |
PostgreSQL store, migrations and compatibility file persistence |
ui/mcp-app/, ui/desktop/
|
MCP App and native display clients of the same middleware |
skills/ |
General agent workflows |
customization/<id>/ |
Package manifest, adapters, domain model/knowledge, skills, tests and optional views |
lib.rs retains existing public module re-exports for library callers. The service
orchestrates persistence through data::FileStore; scheduling modules operate
on in-memory models. CLI plan, hypersearch, treesearch, improve and evolve also call those modules directly. Search changes candidate decisions or ranking parameters and uses the same evaluation path as quick planning.
flowchart LR
Chat[Agent and MCP App] --> API[middleware/api]
Desktop[ui/desktop] --> API
API --> Control[middleware/control]
Control --> Core[core]
Control --> Store[Store contract]
Data[middleware/data] -. implements .-> Store
Packages[customization packages] --> Control
middleware/control/src/apex.rs is the optional built-in implementation of the
engine contract. It is not a separate adapter service. Domain source adapters
belong in customization/<id>/adapter. The desktop depends on control contracts
without enabling the apex feature. The MCP App receives results.get or views.get through
its host bridge and does not persist authoritative planning state.
middleware/control/src/views.rs owns bounded read-only dashboards and the
provider registry. Providers inspect authorized revisions and matching results.
middleware/control/src/overview.rs builds the default APEX planning overview
from saved input, completion events and validated metrics. It owns presentation
thresholds and bounded summaries, without changing scheduling semantics.
Shared widgets render declarative data; domain providers/renderers live under
customization/<id>/ui/ with explicit registration. Source details uses optional
ScenarioContent.source_summary for adapter evidence, hashed/persisted but not
passed to the engine. See the insights contract.
The container deployment starts this central server with PostgreSQL; it does not start the compatibility executable or native desktop. Application container files are independent of the root demo. The root demo composes additional source services and selects a customization through config.
All module links below point into core unless stated otherwise.
| Responsibility | Entry points and related modules |
|---|---|
| Serialized input, options and output |
model.rs: Problem, Options, Schedule, activities, commitments and diagnostics. Additional typed contracts live beside their implementation in language, policy, queues and xe. |
| Production templates |
production.rs: ProductionInput, expand; expands orders, quantities and workplans into canonical tasks. It does not schedule them. |
| Readiness and indexes |
compile.rs: compile, Compiled; validates supported inputs, resolves IDs and builds dependency and dispatch graphs. urgency.rs derives upstream dispatch urgency. |
| Active problem |
domain.rs: resolve; selects routes, removes inactive work, expands quantity formulas and applies job/order defaults. language.rs lowers typed planning templates; conditionals.rs checks and applies conditional choices. |
| Material preparation | material.rs: existing-supply allocation, pegging and route/mode-aware preparation. Flexible allocation runs during active-model resolution; explicit preparation creates a separate scenario. |
| Construction stock reservations | material_ledger.rs: dated receipts, consumption and production during decoding. Previously reserved future work stays supplied when a later decision is placed earlier. Independent validation reconstructs balances separately. |
| Shared placement state | decoding.rs: calendar occupancy, predecessor readiness, execution continuation, material, fixed starts and phase placement. Probes roll back temporary calendar writes; only committed assignments update the prefix. Full decoding and eligible construction use this same implementation. |
| Construction and policy enforcement |
dispatch.rs: decisions_with, choices; common ready-pool selection. policy.rs: mandatory filters and replay. placement.rs: private exact-placement oracle for those filters. |
| Ranking and objectives | queues.rs: Q definitions, normalization and stage policies. rules.rs: bounds, rank, exact objectives and score. metrics.rs: KPI catalog and evaluation. |
| Schedule construction (XG) |
xg.rs: create, evaluate, decode, conditional_specs; orchestrates evaluation and places main/pre/post/restart work. activities.rs handles conditional DAGs; calendar.rs places phased work against resource calendars and occupancy. |
| Hypersearch (XH) | xh.rs: Q-policy mutation, crossover and population search. |
| Tree search (XT) | xt.rs: UCT tree, prefix expansion and rollouts. |
| Direct evolution (XE) | xe.rs: schedule chromosomes and genetic operators. |
| Shared search and portfolio | search.rs: budgets, workers, randomness, selection and reporting helpers. improve.rs: shared-budget XH/XT/optional XE portfolio. |
| Independent validation |
validate.rs: validate, validate_active, validate_customized; reconstructs expected semantics and checks output. Uses policy::verify for governed construction and extensions.rs for native validation and metrics. |
| Native customization |
rules::Customization declares the contract. extensions.rs registers, lowers and decorates models. customization/demo is the linked synthetic example. |
| Agent API and viewer |
service.rs: Service::call, package routing and tool orchestration. transport.rs: tool schemas, JSON-RPC, HTTP and OpenAPI. ui/mcp-app/compat.html: embedded schedule viewer and optional development workbench. |
Trace xg::create / create_internal when debugging a result. xg::evaluate is the shared entry used by search workers.
-
Check options and lower a native extension. If a customization is selected,
extensions::registeredresolves its version andextensions::lowerproduces typed input with declared native objectives, Qs and conditional choices. Unknown customizations fail. Validate requested strategies and decision options before constructing a schedule. -
Compile and resolve the active model.
compile::compilechecks the input.domain::resolvelowers the planning block, chooses workplan alternatives, applies quantities and conditional choices, and performs configured material allocation. Hard commitments constrain these choices. Compile the resolved problem when it differs from the original. -
Choose an admissible construction order.
dispatch::decisions_withtracks dependency readiness, mode/resource/order commitments and consecutive blocks. Mandatory policies filter eligible task/mode pairs before heuristic ranking. Qs, classic strategies and soft priority orders rank only the remaining choices. A forced prefix must survive the same checks. -
Decorate and decode. Native sequence hooks can add declared pre/post activities and setup charges. The decoder builds conditional graphs from task/mode activities, neighbor transitions, sequence patterns, terminal cleanup and running-work restart records.
calendar::placeplaces work and reservations; the engine enforces dependency timing and material availability. A placement failure rejects the candidate. - Evaluate the result. Compute actual KPIs, objective values and score; attach route/material choices, construction order, replay options and any policy witness. Native metric hooks run here. Non-finite values or objectives without an evaluator fail.
- Validate before accepting. The validator resolves saved choices, checks physical assignments and metrics, and verifies mandatory-policy witnesses. A customized result also passes native validation and independent native metric evaluation. Only an accepted result becomes a search candidate or saved schedule.
Validation does not trust success from the constructor. It shares typed semantics and some helpers with construction, so a new rule still needs negative and deliberately corrupted-output tests.
| Concept | Meaning when changing code |
|---|---|
Problem and Options
|
Problem contains model facts and persistent commitments. Options selects a run's search settings and requested decisions. Do not silently write search preferences back into business facts. |
Compiled |
Borrowed problem plus lookup tables, precedence graphs and derived urgency. Rebuild it after changing the active problem. |
Decisions and Schedule
|
Decisions select task order and modes. Decoding produces timed activities. Schedule.construction records actual decoder order; assignment array order is not a replacement for it. |
| Work segments and reservations | Segments describe productive work. Reservations describe resource occupancy, including retained pauses. Calendar breaks, rates and retention mean occupied time and work are different quantities. |
| Main end and product readiness |
Assignment.end is main completion; ready includes required post-processing. Product dependencies and completion metrics must use their declared event, not assume these timestamps coincide. |
| Dependency and resource order | A product dependency waits for the predecessor's release plus lag. A resource sequence lock constrains construction/resource order without automatically waiting for independent post-processing resources. Compiled keeps separate graphs for these meanings. |
| Constraint, policy and Q | A physical constraint applies to the final schedule. A dispatch policy restricts the next decision against its prospective prefix. A Q is a heuristic ranking value. One cannot substitute for another. |
| Hard prefix and soft order |
decision_prefix pins decisions. decision_order expresses task priorities for direct evolution; dependencies, locks and mandatory filters remain binding. Caller-supplied route/mode/conditional choices must also survive search. |
| Due date and urgency | Due dates remain business facts. Derived upstream urgency can prioritize predecessors without changing their original dates or completion metrics. Soft due dates do not become hard deadlines. |
See declarative scheduling for filter order, exact probes, the native prefix contract and bounded replay evidence.
| Entry point | What it varies |
|---|---|
schedule.create / xg::create
|
One constructive pass using the requested/default policy. The CLI and service default to queues; Options::default() in the library defaults to due. |
schedule.hypersearch / xh::search_with
|
Evolves Q-policy configurations, weights/normalization and supported choices; evaluates complete schedules. It is instance-specific search. |
schedule.treesearch / xt::search
|
Retains a bounded UCT prefix tree and completes branches with shared construction. It does not enumerate all feasible schedules. |
schedule.evolve / xe::evolve
|
Evolves task-priority chromosomes and route/main-mode/conditional genes. Native operators propose candidates; they cannot bypass evaluation. |
schedule.improve / improve::improve_from
|
Runs XH, then XT from retained policies, then optional GA, sharing one budget, incumbent and archive. Defaults are 40% XH, remaining allowance XT, zero reserved GA share. |
schedule.repair |
Uses the XH path on the current scenario, including its commitments. It reconstructs a schedule; it does not patch a cached schedule in place. |
Search evaluates candidates on worker threads when configured, while portfolio phases run sequentially. Time budgets are soft checks between evaluations/batches; a single expensive evaluation can overrun. Evaluation counts include rejected candidates. An exhausted constructor or search does not prove infeasibility.
The combined-improvement contract specifies budget division and incumbent handling. Search semantics and direct evolution define candidate spaces, reproducibility and operator evidence.
The central apex-control service owns immutable scenario revisions, queued runs,
validated results and approval/publication through the Store contract. Its
PostgreSQL implementation is in middleware/data; the in-memory store supports
tests and transient demonstrations. Both clients use this workflow; see the
control platform for deployment and authorization.
The following describes the retained file-backed apex compatibility interface.
It has separate records and does not automatically migrate them to PostgreSQL.
The default store is .apex under the configured workspace. middleware/data/files.rs stores separate JSON artifacts for imports, scenarios and schedules. Writes use a temporary file, flush/sync and rename. Service::call selects the request package and holds its exclusive store.lock across the entire tool call, including scheduling. Calls sharing a store therefore serialize; search workers provide parallel candidate evaluation inside a call. Chunked imports reduce request/context size, but the complete problem is still held in memory for planning.
With explicit configuration, package state is scoped by ID and version and input
files by package ID. Responses, saved records and viewer links retain package
context. Requests never change a global active package. Unconfigured flat stores
remain compatible. See server configuration for
selection, version changes and shared-trust limitations. Use apex-control for
active-plan lifecycle, tenant authorization and MCP Apps resources.
A scenario has a revision, problem and optional parent. Patches require expected_revision. A saved schedule contains its scenario identity/revision, the exact problem snapshot and the result. Improve/evolve can reuse an incumbent only for the same scenario and revision; after a patch or fork, create a result for that model. Validation and explanations use the saved problem, not the current mutable scenario.
service::tool_names and transport::tools expose the same 32 operations over MCP stdio, stateless MCP HTTP at /mcp, and JSON HTTP. Responses larger than 64 KiB are retained as local artifacts with a bounded reference; paging keeps routine tool output small. Transport/authentication and import contracts are in agent integration.
The viewer is compiled into the Rust binary with include_str!; HTML edits require a rebuild before browser verification. The default UI reads saved plans, KPIs and commitments. ?mode=workbench enables development controls. Keep ordinary planning and rule changes in the agent workflow; the UI does not run its own scheduling engine.
Server packages group adapter, model, skills, tests and optional UI by domain.
Package configuration validates manifests; it does not
execute code. Data storage owns persistence. Package selection
and Problem.customization have different meanings: the latter selects native
scheduling behavior. The optional demo source adapter
reads the public MES API and saved Excel file into canonical input and an import
report. It runs separately; package selection does not execute it. It uses the
existing input contract without changing core semantics. The HTTP server's
deployment-configurable request-size limit also applies to these imports.
rules::Customization covers typed lowering, sequence decorations, candidate filters/rank, Qs, objectives/metrics, validation and genetic proposals. Native implementations are deterministic, versioned, statically linked and Send + Sync. Registration is explicit in extensions::registered; demo@1 is the current bundled implementation.
Keep reusable physical semantics in the core and optional domain behavior in customization modules. New native code needs a build. Tool arguments, Markdown knowledge and skills/ guide the agent; they do not execute plugins or enforce rules. Sequence hooks used by exact dispatch policies must support meaningful prefix decoration, with tests for every affected interaction.
Read existing tests in the affected row before editing. Synthetic regression inputs are in tests/fixtures; the embedded production demo input belongs to customization/demo. Never turn customer exports into fixtures.
| Change | Update together | Verification starting points |
|---|---|---|
| Input field or physical rule | Typed model, readiness in compile/domain checks, lowering, decoder/calendar semantics, independent validator and schema/docs |
core, migration, parity |
| Material/order/workplan behavior |
production, material, domain, consumption/release handling in engine and validate
|
material, migration, material tool workflow |
| Mandatory next-choice rule |
language, policy, shared dispatch, exact placement where needed, replay/diagnostics |
dispatch, customization; include singleton, forced-prefix and beyond-Q-window cases |
| Objective or Q | Exact rules/metrics evaluator, direction/scale/priority, readiness, independent metric check, explicit queues mapping and search behavior |
search, improve, evolution; test actual fitness separately from the heuristic proxy |
| Search or genetic operator |
xh/xt/xe/search/improve, option types, budget accounting, commitment preservation, replay and evidence |
search, improve, evolution |
| Native domain rule |
Customization implementation, registry/version, typed lowering, metric/validation hooks and synthetic knowledge bundle |
customization, relevant dispatch/XE tests |
| Tool or persistence behavior | Service dispatch, tool_names, transport::tools schema/OpenAPI and saved-artifact revision semantics |
service, MCP smoke, HTTP/MCP |
| Viewer explanation |
ui/mcp-app/compat.html and bounded service fields needed to explain the decision |
viewer plan smoke, dispatch viewer, evolution viewer |
For Rust changes run the required checks from the application root (app/ in the development checkout):
cargo fmt --check
cargo clippy --all-targets -- -D warnings
cargo test
cargo build --release
When serialized types change, regenerate and review affected current schemas with the rebuilt binary using the schema directory instructions. The input-contract tests check snapshot consistency; the data-model release contract defines versioning and compatibility. Rebuild before MCP/browser verification; follow the operating guide for relevant smoke commands. Generated reports and .apex artifacts stay local. Documentation-only edits need link, example and source-reference checks rather than scheduler benchmarks.
- The decoder constructs append-based schedules with integer-second time and fixed resource identities within each phase. It has no completeness or optimality guarantee.
- Exact policy probes use a specialized independent-task fast path or reconstruct
prefix + candidate. There is no general transactional rollback or incremental cross-resource repair engine. - The
apexservice uses a local file store and serialized tool calls. Tenants, durable runs, approval and publication belong to the separate control platform. - There is no external solver backend, stochastic simulator, general simultaneous batch formation, arbitrary plugin hot-loading, automatic Q-formula generation or automatic operator synthesis.
- Passing current tests does not establish complete v2 parity. Keep measured comparisons in the migration audit and separate benchmark workstream.
APEX documentation
Use APEX
- APEX documentation
- Rust implementation and operating guide
- Chat-led scheduling
- Agent integration
- Server configuration and customization packages
- Start APEX with Docker Compose
- Control platform
- MCP App insights and customization views
Reference
- Executable scheduling data model
- Material preparation: scheduling, not MRP
- Search and objectives
- Combined improvement
- Direct schedule evolution
- Declarative scheduling
Development and evidence
- Current architecture
- Demo model boundary
- Migration audit: legacy v2 to Rust
- Source distribution
- Wiki publication
- Repository layout and distribution
Licensing