Meridian Language Guide
Declarative rules language for airline legality, CBA provisions, operational policy, optimisation preferences, and compliance triggers.
1. What Meridian Is
Meridian is a declarative rule language for encoding airline operating rules in a format that Pleiades systems can validate, compile, and execute.
A Meridian file should answer questions like:
- Is this crew assignment legal?
- Which CBA or regulatory clause makes it legal or illegal?
- What limits apply to this duty period?
- Which rules are hard constraints versus soft preferences?
- What facts must be derived before simulation?
- What compliance tasks are triggered by a recovery option?
- Why did the solver reject, penalise, or warn about an option?
Meridian is not intended to be a general-purpose programming language. It should be deterministic, auditable, source-linked, and safe to compile into the MDMS simulation engine.
2. Core Design Principles
Meridian files should be:
-
Declarative
Describe what must be true, not how to execute an algorithm. -
Source-linked
Every formal rule should cite the source clause, regulation, policy, or interpretation it comes from. -
Typed
Durations, times, dates, counts, roles, locations, and money should be explicit types. -
Auditable
Every pass, failure, warning, exception, and generated compliance task should be explainable. -
Composable
Airline-specific rule files should import regulatory baselines and overlay CBA/company-specific rules. -
Compiler-friendly
Rules should be classifiable as solver constraints, derived facts, objective terms, post-solve evaluators, or manual-review triggers.
3. File Structure
Recommended directory structure:
rules/
jurisdictions/
us/
usa.mrdn
faa/
part_117.mrdn
part_121.mrdn
eu/
easa_ftl.mrdn
es/
spain_aviation_rules.mrdn
airlines/
commuteair/
airline.mrdn
pilot_cba_section_25.mrdn
fa_cba.mrdn
company_policy.mrdn
objective_weights.mrdn
iberia/
airline.mrdn
pilot_cba.mrdn
company_policy.mrdnJurisdiction files should compose regulatory baselines for a legal environment:
module jurisdictions.us.usa
version "2026.05.01"
import jurisdictions.us.faa.part_117
import jurisdictions.us.faa.part_121
jurisdiction "US"
authority: federal_law
active_rules:
crew_group pilot:
- jurisdictions.us.faa.part_117The airline-level file should compose the active ruleset for a specific airline and define the applicable legal/contractual stack:
module airlines.commuteair.airline
version "2026.05.01"
import jurisdictions.us.usa
import airlines.commuteair.pilot_cba_section_25
import airlines.commuteair.company_policy
import airlines.commuteair.objective_weights
airline "CommuteAir"
iata "C5"
jurisdiction_stack:
- jurisdiction: us
authority: federal_law
source: jurisdictions.us.usa
- jurisdiction: airline
authority: cba
source: airlines.commuteair.pilot_cba_section_25
- jurisdiction: airline
authority: company_policy
source: airlines.commuteair.company_policy
active_rules:
crew_group pilot:
- jurisdictions.us.usa
- airlines.commuteair.pilot_cba_section_25
- airlines.commuteair.company_policy
- airlines.commuteair.objective_weights
authority_model:
hierarchy:
- federal_law
- cba
- company_policy
- operational_policy
- pleiades_default
conflict_resolution:
default: most_restrictive
legality_limits: most_restrictive
permissions: most_restrictive
derived_facts: highest_authority
decision_tables: compose_or_highest_authority
objective_terms: merge
lower_authority_may_not_relax_higher_authority: true4. Jurisdiction Stacks, Authority, and Conflict Resolution
Airline rules rarely exist in isolation. A complete airline ruleset is usually built from several layers:
supranational law
national or federal law
state, regional, or local law
CBA / industrial agreement
company policy
operational policy
Pleiades defaultsMeridian represents this using jurisdiction_stack, authority_model, and conflict_resolution.
Jurisdiction Stack
Use jurisdiction_stack to declare which legal, contractual, and policy modules apply to the airline.
US example:
jurisdiction_stack:
- jurisdiction: us
authority: federal_law
source: jurisdictions.us.usa
- jurisdiction: airline
authority: cba
source: airlines.commuteair.pilot_cba_section_25
- jurisdiction: airline
authority: company_policy
source: airlines.commuteair.company_policyEU plus national example:
module airlines.iberia.airline
version "2026.05.01"
import jurisdictions.eu.easa_ftl
import jurisdictions.es.spain_aviation_rules
import airlines.iberia.pilot_cba
airline "Iberia"
iata "IB"
country "ES"
jurisdiction_stack:
- jurisdiction: eu
authority: supranational_law
source: jurisdictions.eu.easa_ftl
- jurisdiction: es
authority: national_law
source: jurisdictions.es.spain_aviation_rules
- jurisdiction: airline
authority: cba
source: airlines.iberia.pilot_cbaThe stack does not mean that lower layers always replace higher layers. In most legality cases, all applicable rules are evaluated and the most restrictive result controls.
Authority Model
Use authority_model to define the recognised authority layers and their order for a ruleset.
authority_model:
hierarchy:
- supranational_law
- federal_law
- national_law
- state_law
- regional_law
- local_law
- cba
- company_policy
- operational_policy
- pleiades_defaultRules may declare authority directly, or inherit it from the imported module or jurisdiction stack entry.
rule "Maximum FDP"
id: EXAMPLE_MAX_FDP
source: "Example regulation"
jurisdiction: eu
authority: supranational_law
layer: supranational_law
severity: hard
capability: constraint_safeConflict Resolution
Precedence and restrictiveness are related but not identical.
If two rules define numeric legality limits, the most restrictive value usually controls:
EU max FDP: 13h
Spain max FDP: 12h30m
CBA max FDP: 12h
Effective max FDP: 12hIf two rules define a derived fact, the higher-authority interpretation may need to control:
EU rule derives report time one way.
National rule derives report time differently for a specific local case.
Effective derived fact: resolved by authority or an explicit conflict rule.Recommended conflict resolution block:
conflict_resolution:
default: most_restrictive
legality_limits: most_restrictive
permissions: most_restrictive
prohibitions: most_restrictive
derived_facts: highest_authority
decision_tables: compose_or_highest_authority
objective_terms: merge
workflow_events: merge
lower_authority_may_not_relax_higher_authority: trueYou can also define explicit conflict rules:
conflict_resolution:
rules:
- when: conflict.type == legality_limit
resolve: most_restrictive
- when: conflict.type == permission
resolve: most_restrictive
- when: conflict.type == derived_fact
resolve: highest_authority
- when: conflict.type == objective_term
resolve: mergeLegacy precedence
The older precedence block is still acceptable for simple single-jurisdiction files:
precedence:
federal_law > cba > company_policy
most_restrictive_controls = trueFor production airline rulesets, prefer jurisdiction_stack, authority_model, and conflict_resolution.
5. Top-Level Blocks
Meridian v0.1 supports these top-level blocks:
| Block | Purpose |
|---|---|
module | Declares the namespace of the file. |
version | Declares the version of the ruleset. |
import | Imports another Meridian module. |
jurisdiction_stack | Declares applicable legal, contractual, and policy modules. |
authority_model | Defines authority layers and hierarchy. |
conflict_resolution | Defines how conflicts between applicable rules are resolved. |
active_rules | Declares which imported modules are active for each crew group or domain. |
constant | Defines reusable constants. |
table | Defines a decision table or lookup table. |
derive | Defines facts inferred from operational data. |
rule | Defines a legality, policy, entitlement, or warning rule. |
preference | Defines optimisation penalties or scoring preferences. |
priority_order | Defines ordered assignment logic. |
event | Defines compliance or workflow events emitted by rules. |
external_check | References a registered backend check for exceptional cases. |
6. Rule Anatomy
A typical rule looks like this:
rule "Max legs per duty period"
id: CBA_25_D_4
source: "CBA 25.D.4"
layer: cba
severity: hard
capability: constraint_safe
when:
duty.crew_group == pilot
require:
duty.legs.count_including_deadheads <= 6
explain:
pass: "Duty period has {duty.legs.count_including_deadheads} legs, within the 6-leg limit."
fail: "Duty period has {duty.legs.count_including_deadheads} legs including deadheads. Maximum allowed is 6."Required Effective Rule Fields
Rules may either declare these fields directly or inherit them from their module, jurisdiction stack entry, or surrounding block.
| Field | Meaning |
|---|---|
id | Stable machine-readable identifier. |
source | Source clause, regulation, policy, or interpretation. |
jurisdiction | Legal or organisational jurisdiction, such as us, eu, es, or airline. May be inherited from the module. |
authority | Authority level, such as federal_law, national_law, cba, or company_policy. May be inherited from the module. |
layer | Rule origin/category. Usually the same as authority, but may be more specific, such as interpretation or pleiades_default. |
severity | How strongly the rule applies. |
capability | How the compiler/sim engine should execute the rule. |
7. Layers and Authority Values
layer describes where the rule comes from. authority describes the legal or contractual authority level used for conflict resolution.
Recommended authority values:
supranational_law
federal_law
national_law
state_law
regional_law
local_law
cba
company_policy
operational_policy
interpretation
pleiades_defaultExample:
jurisdiction: us
authority: federal_law
layer: federal_lawor:
jurisdiction: airline
authority: cba
layer: cbaWhen multiple layers apply, the ruleset should define jurisdiction_stack, authority_model, and conflict_resolution explicitly.
8. Severity Levels
severity tells the system how to treat a rule outcome.
| Severity | Meaning |
|---|---|
hard | Must not be violated. Illegal/infeasible if failed. |
soft | Should be avoided but may be allowed. Usually becomes an optimisation penalty. |
waiverable | Can be allowed only if specific waiver/consent/certification facts are present. |
advisory | Produces a warning but does not block the option. |
manual_review | Requires human review before acceptance. |
pay_trigger | Does not block the assignment but creates a pay or entitlement consequence. |
reporting_obligation | Creates a compliance task or workflow event. |
Example:
severity: hard9. Capabilities
capability tells the compiler how the rule can be used.
| Capability | Meaning |
|---|---|
constraint_safe | Can be compiled directly into the optimisation model. |
evaluation_only | Checked during or after simulation, but not necessarily used as a solver constraint. |
derived_fact | Produces facts used by later rules. |
objective_term | Produces costs, penalties, or preferences. |
priority_policy | Defines ordering among candidates. |
workflow_event | Emits a compliance or operational task. |
external | Calls a registered backend plugin/check. |
Example:
capability: constraint_safe10. Basic Expressions
Meridian expressions should remain simple and deterministic.
Supported operators:
==
!=
<
<=
>
>=
and
or
not
inExamples:
duty.fdp <= 12h
crew.role == Captain
disruption.type in [weather, atc, mechanical]
reserve.available == true and reserve.legal_for(assignment) == true11. Types
Durations
30m
2h
11h30m
7d
168h
672h
365dTimes
0030
04:30
0000-0359
1700-2359Booleans
true
falseStrings
"CBA 25.D.4"
"Captain must receive post-extension rest."Enums
Enums are bare words:
pilot
Captain
FO
LCR
SCR
APR
unaugmented
augmentedLists
[inflight_weather, atc, inflight_mechanical]12. Common Functions
Meridian v0.1 should support the following built-in functions.
| Function | Purpose |
|---|---|
count(...) | Counts matching objects. |
sum(...) | Sums durations, costs, counts, or other numeric values. |
min(...) | Returns the minimum value. |
max(...) | Returns the maximum value. |
exists(...) | Returns true if at least one matching object exists. |
rolling_window(...) | Defines a rolling time window. |
consecutive_count(...) | Counts consecutive matching periods/days/events. |
lookup(...) | Looks up a value in a table. |
band(...) | Converts a value into a table band. |
between(...) | Tests whether a value lies between two boundaries. |
within(...) | Tests whether a value is inside a time period/window. |
Examples:
count(duty.legs where leg.type in [flight, deadhead]) <= 6sum(crew.fdp within rolling_window(168h, ending_at=duty.end)) <= 60hexists(day_off where location == crew.domicile and duration >= 24h)13. Decision Tables
Use table when a rule depends on a lookup matrix.
Example:
table "FAR Table B FDP Limit"
id: FAR_117_13_TABLE_B
source: "14 CFR 117.13 Table B"
layer: federal_law
inputs:
report_band: time_band
segments: segment_band
output:
max_fdp: duration
rows:
- report_band: 0000-0359
segments: 1+
max_fdp: 9h
- report_band: 0400-0459
segments: 1..4
max_fdp: 10h
- report_band: 0400-0459
segments: 5+
max_fdp: 9h
- report_band: 0500-0559
segments: 1..2
max_fdp: 13h
- report_band: 0500-0559
segments: 3..4
max_fdp: 12h
- report_band: 0500-0559
segments: 5
max_fdp: 11h30m
- report_band: 0500-0559
segments: 6
max_fdp: 11h
- report_band: 0500-0559
segments: 7+
max_fdp: 10h30mA rule can then use the table:
rule "Unaugmented FDP must not exceed FAR Table B"
id: FAR_117_13_UNAUGMENTED_FDP
source: "14 CFR 117.13"
layer: federal_law
severity: hard
capability: constraint_safe
when:
duty.operation == unaugmented
let:
report_band = band(duty.effective_report_time, "FAR Table B FDP Limit.report_band")
segments = duty.flight_segments.count
limit = lookup("FAR Table B FDP Limit", report_band, segments).max_fdp
require:
duty.fdp <= limit
explain:
fail: "FDP is {duty.fdp}, exceeding the {limit} Table B limit for report time {report_band} and {segments} segments."14. Derived Facts
Use derive when Meridian needs to define how operational facts should be interpreted before rules are evaluated.
Example:
derive "APR report time starts FDP clock"
id: FAR_117_APR_FDP_START
source: "14 CFR 117.3 / FAA guidance"
layer: interpretation
capability: derived_fact
when:
reserve.type == APR
reserve.location == assigned_airport
reserve.free_to_rest == false
set:
duty.fdp_start = reserve.report_time
explain:
"APR time is treated as FDP because the pilot is at an assigned location and not free to rest."Derived facts should be evaluated before legality rules that depend on them.
15. Hard Rules
Use require for conditions that must be true.
rule "FDP limit in 168 consecutive hours"
id: FAR_117_23_A_168
source: "14 CFR 117.23(a)"
layer: federal_law
severity: hard
capability: evaluation_only
require:
sum(crew.fdp within rolling_window(168h, ending_at=duty.end)) <= 60h
explain:
fail: "Crew member would exceed 60 FDP hours in 168 consecutive hours."Use forbid for conditions that must not be true.
rule "Do not extend line holder when legal reserve is available"
id: CBA_25_H_3_A
source: "CBA 25.H.3.a"
layer: cba
severity: hard
capability: evaluation_only
when:
assignment.extends_line_holder == true
forbid:
exists(reserve in crew_pool where
reserve.available == true
and reserve.legal_for(assignment) == true
and reserve.able_to_cover(assignment) == true
)
explain:
fail: "Line holder extension is not permitted because a reserve pilot is available, legal, and able to cover the assignment."16. Waiverable or Conditional Rules
Use allow and only_if for rules that can be permitted only under specific conditions.
rule "Unforeseen circumstances FDP extension"
id: FAR_117_19_EXTENSION
source: "14 CFR 117.19"
layer: federal_law
severity: waiverable
capability: evaluation_only
when:
duty.fdp > duty.base_fdp_limit
allow:
duty.fdp <= duty.base_fdp_limit + 2h
only_if:
disruption.arose_after_takeoff_of_last_segment == true
disruption.type in [inflight_weather, atc, inflight_mechanical]
pic.certifies_safe_extension == true
emit:
compliance_task(type: FAA_EXTENSION_REPORT, due_within: 10d)
explain:
fail: "FDP exceeds the base limit and does not qualify for a 117.19 unforeseen circumstances extension."The system should never infer human certification. It must be present as an explicit fact.
17. Rest Rules
Example:
rule "Minimum rest sleep opportunity"
id: FAR_117_25_A
source: "14 CFR 117.25(a)"
layer: federal_law
severity: hard
capability: evaluation_only
let:
sleep_opportunity = rest.duration - rest.transport_to_facility - rest.transport_from_facility
require:
sleep_opportunity >= 8h
explain:
fail: "Rest period does not provide at least 8 consecutive hours of sleep opportunity after transport time."Post-extension rest:
rule "Post 117.19 extension rest"
id: FAR_117_25_C
source: "14 CFR 117.25(c)"
layer: federal_law
severity: hard
capability: constraint_safe
when:
previous_duty.extended_under == FAR_117_19
require:
rest.duration >= 10h
rest.reducible == false
explain:
fail: "Following a 117.19 FDP extension, rest must be at least 10 hours and cannot be reduced."18. Days-Off Rules
Example:
rule "Two domicile days off in any seven consecutive days"
id: CBA_25_C_8
source: "CBA 25.C.8"
layer: cba
severity: hard
capability: evaluation_only
require:
count(days_off where location == crew.domicile within rolling_window(7d)) >= 2
explain:
fail: "Pilot does not have at least 2 days off at domicile in a 7-consecutive-day window."Example:
rule "Monthly three-day domicile block"
id: CBA_25_C_9
source: "CBA 25.C.9"
layer: cba
severity: hard
capability: evaluation_only
require:
exists(block of days_off where
length >= 3d
and location == crew.domicile
and block.month == bid_period.month
)
explain:
fail: "Pilot does not have a block of at least 3 consecutive domicile days off in the bid period month."19. Split-Duty Rules
Example:
rule "Max consecutive split-duty periods"
id: CBA_25_D_6_C
source: "CBA 25.D.6.c"
layer: cba
severity: hard
capability: evaluation_only
require:
consecutive_count(duty_periods where type == split_duty) <= 4
explain:
fail: "Pilot is assigned more than 4 consecutive split-duty periods."Example:
rule "Day off after four consecutive split-duty periods"
id: CBA_25_D_6_D
source: "CBA 25.D.6.d"
layer: cba
severity: hard
capability: evaluation_only
when:
previous_sequence(type == split_duty).consecutive_count == 4
next_trip.type != split_duty
require:
exists(day_off where
location == crew.domicile
and duration >= 1 full_domicile_day
and day_off between previous_duty.end and next_trip.start
)
explain:
fail: "Pilot completed 4 consecutive split-duty periods and requires 1 full domicile day off before a non-split trip."20. Priority Orders
Use priority_order when the rules define how candidates should be selected or ranked.
priority_order "Reserve assignment priority"
id: CBA_25_G_5_C
source: "CBA 25.G.5.c"
layer: cba
capability: priority_policy
candidates:
reserve_pilots where reserve.available == true and reserve.legal_for(assignment) == true
order:
1: reserve.type == LCR and reserve.preference == CallFirst by seniority ascending
2: reserve.type == LCR and reserve.preference == NoPreference by company_discretion
3: reserve.type == LCR and reserve.preference == CallLast by seniority descending
4: reserve.type == SCR and reserve.preference == CallFirst by seniority ascending
5: reserve.type == SCR and reserve.preference == NoPreference by company_discretion
6: reserve.type == SCR and reserve.preference == CallLast by seniority descending
7: reserve.type == APR and reserve.preference == CallFirst by seniority ascending
8: reserve.type == APR and reserve.preference == NoPreference by company_discretion
9: reserve.type == APR and reserve.preference == CallLast by seniority descendingA priority order may be used by the optimiser, a candidate generator, or a post-solve evaluator.
21. Preferences and Objective Terms
Use preference for rules that influence ranking but do not define legality.
preference "Avoid minimum-rest turns"
id: PREF_AVOID_MIN_REST
source: "Pleiades default optimisation policy"
layer: pleiades_default
severity: soft
capability: objective_term
when:
rest.duration < 13h
penalize:
500 points
explain:
"Option is penalised because it creates a minimum-rest turn."Hard FAR/CBA rules should not be expressed as penalties unless they are explicitly waiverable or advisory.
22. Events and Compliance Tasks
Use event or emit when a rule creates a workflow obligation.
Inline emit example:
emit:
compliance_task(type: FAA_EXTENSION_REPORT, due_within: 10d)Standalone event example:
event "FAA report required after FDP extension"
id: FAA_EXTENSION_REPORT_REQUIRED
source: "14 CFR 117.19(c)"
layer: federal_law
severity: reporting_obligation
capability: workflow_event
when:
duty.extended_under == FAR_117_19
emit:
compliance_task(type: FAA_EXTENSION_REPORT, due_within: 10d)
explain:
"FDP extension under FAR 117.19 requires FAA reporting within 10 days."23. External Checks
Use external_check only when the rule cannot be safely expressed in Meridian v0.1.
external_check "Fatigue risk model"
id: EXT_FATIGUE_RISK_MODEL
source: "Company fatigue risk policy"
layer: company_policy
capability: external
inputs:
crew_member
duty_sequence
timezone_history
rest_history
returns:
fatigue_risk_score: number
explanation: stringRules may consume external check outputs:
rule "High fatigue risk requires manual review"
id: FATIGUE_MANUAL_REVIEW
source: "Company fatigue risk policy"
layer: company_policy
severity: manual_review
capability: evaluation_only
when:
external.EXT_FATIGUE_RISK_MODEL.fatigue_risk_score >= 0.8
require:
operations_manager.approval == true
explain:
fail: "Fatigue risk score is high and requires operations manager approval."External checks must be registered, typed, versioned, and sandboxed outside the .mrdn file.
24. Explanations
Every rule should include explanations.
Recommended format:
explain:
pass: "..."
fail: "..."
warn: "..."Explanations can interpolate facts:
explain:
fail: "FDP is {duty.fdp}, exceeding the allowed limit of {limit}."The simulation engine should return structured rule outcomes:
{
"rule_id": "CBA_25_D_4",
"source": "CBA 25.D.4",
"status": "failed",
"severity": "hard",
"message": "Duty period has 7 legs including deadheads. Maximum allowed is 6.",
"inputs": {
"actual_legs": 7,
"limit": 6
}
}25. Compilation Model
Meridian source files should not be interpreted directly on every simulation request.
Recommended flow:
.mrdn source files
-> Meridian parser
-> semantic validator
-> typed Rule IR
-> compiled rule bundle
-> simulation engineThe compiled rule bundle should classify each rule as one of:
solver constraint
objective term
derived fact
post-solve evaluator
priority policy
workflow event
external check
manual-review triggerThe sim engine should consume the compiled bundle, not raw text.
26. Minimal Authoring Checklist
Before merging an .mrdn file, check:
- Every rule has a stable
id. - Every formal rule has a
source. - Every rule has
layer,severity, andcapability. - Every hard rule has an explanation.
- No hard legality rule is accidentally encoded as a soft preference.
- No human judgement is inferred automatically.
- Decision tables have complete, non-overlapping rows.
- Units are explicit for all durations, times, and counts.
- Imported modules, jurisdiction stack, authority model, and conflict resolution are clear.
- The file compiles into Rule IR without semantic errors.
- Test scenarios cover pass, fail, boundary, and exception cases.
27. Boundary Tests
Every rule should have examples that test:
-
Pass case
Rule clearly satisfied. -
Fail case
Rule clearly violated. -
Boundary case
Exactly at the limit. -
Exception case
Rule would fail unless a valid exception applies. -
Missing-data case
Required fact is unavailable.
Example:
test "Max legs boundary: exactly 6 legs is legal"
rule: CBA_25_D_4
facts:
duty.legs.count_including_deadheads = 6
expect:
status = passtest "Max legs fail: 7 legs is illegal"
rule: CBA_25_D_4
facts:
duty.legs.count_including_deadheads = 7
expect:
status = fail
severity = hardTest syntax is optional in v0.1, but the compiler/test harness should eventually support it.
28. Anti-Patterns
Avoid these patterns:
Procedural logic
Do not write rules like this:
function check_legality(crew, duty) { ... }Meridian should not support arbitrary user-defined functions in v0.1.
Hidden assumptions
Bad:
require:
rest.duration >= 8hBetter:
let:
sleep_opportunity = rest.duration - rest.transport_to_facility - rest.transport_from_facility
require:
sleep_opportunity >= 8hHard rules as penalties
Bad:
penalize:
5000 points if duty.fdp > limitBetter:
require:
duty.fdp <= limitUnsourced rules
Bad:
rule "Crew should not work too long"Better:
rule "FDP limit in 168 consecutive hours"
id: FAR_117_23_A_168
source: "14 CFR 117.23(a)"29. Meridian v0.1 Scope
In scope for v0.1:
- Rule metadata
- Jurisdiction stacks
- Authority models
- Conflict resolution rules
- Hard constraints
- Soft preferences
- Decision tables
- Derived facts
- Rolling-window expressions
- Consecutive-count expressions
- Priority orders
- Workflow events
- External check references
- Explanations
- Compilation to typed Rule IR
Out of scope for v0.1:
- Arbitrary loops
- User-defined functions
- Classes or inheritance
- Inline Python/JavaScript
- Network calls from
.mrdnfiles - Unbounded recursion
- General-purpose computation
30. Example Full File
module example_airline.pilot_rules
version "2026.05.01"
import jurisdictions.us.usa
import airlines.example_airline.pilot_cba
import airlines.example_airline.company_policy
airline "Example Airline"
iata "EX"
crew_group pilot
jurisdiction_stack:
- jurisdiction: us
authority: federal_law
source: jurisdictions.us.usa
- jurisdiction: airline
authority: cba
source: airlines.example_airline.pilot_cba
- jurisdiction: airline
authority: company_policy
source: airlines.example_airline.company_policy
authority_model:
hierarchy:
- federal_law
- cba
- company_policy
- pleiades_default
conflict_resolution:
default: most_restrictive
legality_limits: most_restrictive
permissions: most_restrictive
derived_facts: highest_authority
objective_terms: merge
lower_authority_may_not_relax_higher_authority: true
rule "Max legs per duty period"
id: CBA_25_D_4
source: "CBA 25.D.4"
jurisdiction: airline
authority: cba
layer: cba
severity: hard
capability: constraint_safe
when:
duty.crew_group == pilot
require:
duty.legs.count_including_deadheads <= 6
explain:
fail: "Duty period has {duty.legs.count_including_deadheads} legs including deadheads. Maximum allowed is 6."
rule "Post 117.19 extension rest"
id: FAR_117_25_C
source: "14 CFR 117.25(c)"
jurisdiction: us
authority: federal_law
layer: federal_law
severity: hard
capability: constraint_safe
when:
previous_duty.extended_under == FAR_117_19
require:
rest.duration >= 10h
rest.reducible == false
explain:
fail: "Following a 117.19 FDP extension, rest must be at least 10 hours and cannot be reduced."
preference "Avoid minimum-rest turns"
id: PREF_AVOID_MIN_REST
source: "Pleiades default optimisation policy"
jurisdiction: airline
authority: pleiades_default
layer: pleiades_default
severity: soft
capability: objective_term
when:
rest.duration < 13h
penalize:
500 points
explain:
"Option is penalised because it creates a minimum-rest turn."31. Practical Implementation Notes
For the MDMS backend, the recommended integration pattern is:
- Store
.mrdnsource files in a versioned rules repository. - Compile them into typed Rule IR during deployment or ruleset publication.
- Validate source references, types, units, table coverage, and rule capabilities.
- Resolve jurisdiction stacks, authority hierarchy, and conflict rules into an effective ruleset.
- Cache compiled rule bundles by airline, crew group, jurisdiction stack, version, and hash.
- During simulation, load the relevant compiled bundle.
- Apply
constraint_saferules to the optimiser. - Apply
derived_factrules before legality evaluation. - Apply
objective_termrules during scoring. - Apply
evaluation_onlyrules during or after candidate generation. - Return structured explanations for every failed, warning, waiver, or manual-review rule.
32. Summary
Meridian should be powerful enough to encode messy airline crew rules, but constrained enough to remain safe, explainable, and optimisable.
The goal is not to create a general-purpose programming language. The goal is to create an auditable rules layer that allows Pleiades to turn CBAs, regulations, and operational policies into executable simulation constraints.
A well-authored .mrdn file should let the MDMS answer not only:
Is this option legal?
but also:
Why is it legal or illegal, which clause controls, what exception applies, and what operational action follows?