ADR 0014: Direct Evaluator as First Runtime Engine
ADR 0014: Direct Evaluator as First Runtime Engine
Status: Accepted for architectural direction.
Date: 2026-05-11.
Context
The solver layer will eventually support several engine styles.
The first runtime implementation still needs a small, auditable, deterministic core.
Most early user-facing queries are fixed-state evaluations:
- can I take this course;
- which prerequisites are satisfied;
- which prerequisite branches remain open;
- how much of this credential is completed;
- what changed if I add this completed course or grade;
- which parts are unknown because the source or student state is incomplete.
These queries should not require CP search, SAT encodings, or SMT integration in version 1.
They require correct structured evaluation and honest unknown propagation.
Decision
Implement a deterministic direct evaluator as the first runtime engine.
The direct evaluator will consume a normalized evaluation_problem.
It will produce an engine_result that the result normalizer maps into an academic_result.
The direct evaluator must support:
all_of;any_of;choose;- course completion;
- course credit completion;
- grade thresholds;
- unit counts over explicit indexed sets;
- academic progress predicates;
- academic standing predicates when modeled;
- program enrollment predicates;
- antirequisite conflict checks when indexed;
- equivalence and cross-listing facts when indexed;
- opaque source text as conservative unknown.
The direct evaluator is also the validation baseline for later planning outputs.
A future CP or resolver-style adapter may propose a plan.
The direct evaluator should validate the final planned state against credential requirements when possible.
Consequences
Version 1 can ship useful academic answers without waiting for external solver integration.
The direct evaluator becomes the clearest implementation of basic requirement semantics.
Fixture coverage must be strong because later adapters will be compared against it.
The evaluator must not grow into an ad hoc planning engine.
The evaluator must return structured explanations, not only booleans.
The evaluator must preserve source references and unknown reasons.
Alternatives Considered
Alternative 1: Start With SMT
SMT can express many Boolean and numeric constraints.
SMT-LIB provides a standard language context: SMT-LIB.
However, starting with SMT would put an external encoding between the project and the basic semantics of all_of, any_of, choose, and opaque source propagation.
It would make early debugging harder.
This alternative is rejected for the first runtime engine.
Alternative 2: Start With Datalog
Datalog is a strong fit for relation closure.
Souffle and Z3 fixedpoint are useful references: Souffle program documentation, Z3 basic Datalog.
However, direct prerequisite and credential progress evaluation needs requirement tree status, grade thresholds, and unknown propagation.
Datalog can support related closure queries later.
It should not be the first fixed-state evaluator.
This alternative is rejected.
Alternative 3: Start With CP Planning
CP is appropriate for bounded term planning.
OR-Tools CP-SAT is a useful reference: OR-Tools CP-SAT.
However, planning is a later feature.
The direct evaluator is needed before planning results can be trusted.
This alternative is rejected.
Follow-Up
Write a direct evaluator implementation spec.
Define direct evaluator fixtures.
Define exact status mapping for direct evaluator tree results.