v1.0.0

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:

  1. Declarative
    Describe what must be true, not how to execute an algorithm.

  2. Source-linked
    Every formal rule should cite the source clause, regulation, policy, or interpretation it comes from.

  3. Typed
    Durations, times, dates, counts, roles, locations, and money should be explicit types.

  4. Auditable
    Every pass, failure, warning, exception, and generated compliance task should be explainable.

  5. Composable
    Airline-specific rule files should import regulatory baselines and overlay CBA/company-specific rules.

  6. 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:

text
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.mrdn

Jurisdiction files should compose regulatory baselines for a legal environment:

meridian
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_117

The airline-level file should compose the active ruleset for a specific airline and define the applicable legal/contractual stack:

meridian
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: true

4. Jurisdiction Stacks, Authority, and Conflict Resolution

Airline rules rarely exist in isolation. A complete airline ruleset is usually built from several layers:

text
supranational law
national or federal law
state, regional, or local law
CBA / industrial agreement
company policy
operational policy
Pleiades defaults

Meridian 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:

meridian
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

EU plus national example:

meridian
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_cba

The 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.

meridian
authority_model:
  hierarchy:
    - supranational_law
    - federal_law
    - national_law
    - state_law
    - regional_law
    - local_law
    - cba
    - company_policy
    - operational_policy
    - pleiades_default

Rules may declare authority directly, or inherit it from the imported module or jurisdiction stack entry.

meridian
rule "Maximum FDP"
id: EXAMPLE_MAX_FDP
source: "Example regulation"
jurisdiction: eu
authority: supranational_law
layer: supranational_law
severity: hard
capability: constraint_safe

Conflict Resolution

Precedence and restrictiveness are related but not identical.

If two rules define numeric legality limits, the most restrictive value usually controls:

text
EU max FDP: 13h
Spain max FDP: 12h30m
CBA max FDP: 12h

Effective max FDP: 12h

If two rules define a derived fact, the higher-authority interpretation may need to control:

text
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:

meridian
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: true

You can also define explicit conflict rules:

meridian
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: merge

Legacy precedence

The older precedence block is still acceptable for simple single-jurisdiction files:

meridian
precedence:
  federal_law > cba > company_policy
  most_restrictive_controls = true

For production airline rulesets, prefer jurisdiction_stack, authority_model, and conflict_resolution.


5. Top-Level Blocks

Meridian v0.1 supports these top-level blocks:

BlockPurpose
moduleDeclares the namespace of the file.
versionDeclares the version of the ruleset.
importImports another Meridian module.
jurisdiction_stackDeclares applicable legal, contractual, and policy modules.
authority_modelDefines authority layers and hierarchy.
conflict_resolutionDefines how conflicts between applicable rules are resolved.
active_rulesDeclares which imported modules are active for each crew group or domain.
constantDefines reusable constants.
tableDefines a decision table or lookup table.
deriveDefines facts inferred from operational data.
ruleDefines a legality, policy, entitlement, or warning rule.
preferenceDefines optimisation penalties or scoring preferences.
priority_orderDefines ordered assignment logic.
eventDefines compliance or workflow events emitted by rules.
external_checkReferences a registered backend check for exceptional cases.

6. Rule Anatomy

A typical rule looks like this:

meridian
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.

FieldMeaning
idStable machine-readable identifier.
sourceSource clause, regulation, policy, or interpretation.
jurisdictionLegal or organisational jurisdiction, such as us, eu, es, or airline. May be inherited from the module.
authorityAuthority level, such as federal_law, national_law, cba, or company_policy. May be inherited from the module.
layerRule origin/category. Usually the same as authority, but may be more specific, such as interpretation or pleiades_default.
severityHow strongly the rule applies.
capabilityHow 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:

text
supranational_law
federal_law
national_law
state_law
regional_law
local_law
cba
company_policy
operational_policy
interpretation
pleiades_default

Example:

meridian
jurisdiction: us
authority: federal_law
layer: federal_law

or:

meridian
jurisdiction: airline
authority: cba
layer: cba

When 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.

SeverityMeaning
hardMust not be violated. Illegal/infeasible if failed.
softShould be avoided but may be allowed. Usually becomes an optimisation penalty.
waiverableCan be allowed only if specific waiver/consent/certification facts are present.
advisoryProduces a warning but does not block the option.
manual_reviewRequires human review before acceptance.
pay_triggerDoes not block the assignment but creates a pay or entitlement consequence.
reporting_obligationCreates a compliance task or workflow event.

Example:

meridian
severity: hard

9. Capabilities

capability tells the compiler how the rule can be used.

CapabilityMeaning
constraint_safeCan be compiled directly into the optimisation model.
evaluation_onlyChecked during or after simulation, but not necessarily used as a solver constraint.
derived_factProduces facts used by later rules.
objective_termProduces costs, penalties, or preferences.
priority_policyDefines ordering among candidates.
workflow_eventEmits a compliance or operational task.
externalCalls a registered backend plugin/check.

Example:

meridian
capability: constraint_safe

10. Basic Expressions

Meridian expressions should remain simple and deterministic.

Supported operators:

text
==
!=
<
<=
>
>=
and
or
not
in

Examples:

meridian
duty.fdp <= 12h
crew.role == Captain
disruption.type in [weather, atc, mechanical]
reserve.available == true and reserve.legal_for(assignment) == true

11. Types

Durations

meridian
30m
2h
11h30m
7d
168h
672h
365d

Times

meridian
0030
04:30
0000-0359
1700-2359

Booleans

meridian
true
false

Strings

meridian
"CBA 25.D.4"
"Captain must receive post-extension rest."

Enums

Enums are bare words:

meridian
pilot
Captain
FO
LCR
SCR
APR
unaugmented
augmented

Lists

meridian
[inflight_weather, atc, inflight_mechanical]

12. Common Functions

Meridian v0.1 should support the following built-in functions.

FunctionPurpose
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:

meridian
count(duty.legs where leg.type in [flight, deadhead]) <= 6
meridian
sum(crew.fdp within rolling_window(168h, ending_at=duty.end)) <= 60h
meridian
exists(day_off where location == crew.domicile and duration >= 24h)

13. Decision Tables

Use table when a rule depends on a lookup matrix.

Example:

meridian
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: 10h30m

A rule can then use the table:

meridian
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:

meridian
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.

meridian
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.

meridian
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.

meridian
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:

meridian
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:

meridian
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:

meridian
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:

meridian
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:

meridian
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:

meridian
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.

meridian
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 descending

A 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.

meridian
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:

meridian
emit:
  compliance_task(type: FAA_EXTENSION_REPORT, due_within: 10d)

Standalone event example:

meridian
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.

meridian
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: string

Rules may consume external check outputs:

meridian
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:

meridian
explain:
  pass: "..."
  fail: "..."
  warn: "..."

Explanations can interpolate facts:

meridian
explain:
  fail: "FDP is {duty.fdp}, exceeding the allowed limit of {limit}."

The simulation engine should return structured rule outcomes:

json
{
  "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:

text
.mrdn source files
  -> Meridian parser
  -> semantic validator
  -> typed Rule IR
  -> compiled rule bundle
  -> simulation engine

The compiled rule bundle should classify each rule as one of:

text
solver constraint
objective term
derived fact
post-solve evaluator
priority policy
workflow event
external check
manual-review trigger

The 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, and capability.
  • 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:

  1. Pass case
    Rule clearly satisfied.

  2. Fail case
    Rule clearly violated.

  3. Boundary case
    Exactly at the limit.

  4. Exception case
    Rule would fail unless a valid exception applies.

  5. Missing-data case
    Required fact is unavailable.

Example:

meridian
test "Max legs boundary: exactly 6 legs is legal"
rule: CBA_25_D_4
facts:
  duty.legs.count_including_deadheads = 6
expect:
  status = pass
meridian
test "Max legs fail: 7 legs is illegal"
rule: CBA_25_D_4
facts:
  duty.legs.count_including_deadheads = 7
expect:
  status = fail
  severity = hard

Test 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:

meridian
function check_legality(crew, duty) { ... }

Meridian should not support arbitrary user-defined functions in v0.1.

Hidden assumptions

Bad:

meridian
require:
  rest.duration >= 8h

Better:

meridian
let:
  sleep_opportunity = rest.duration - rest.transport_to_facility - rest.transport_from_facility

require:
  sleep_opportunity >= 8h

Hard rules as penalties

Bad:

meridian
penalize:
  5000 points if duty.fdp > limit

Better:

meridian
require:
  duty.fdp <= limit

Unsourced rules

Bad:

meridian
rule "Crew should not work too long"

Better:

meridian
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 .mrdn files
  • Unbounded recursion
  • General-purpose computation

30. Example Full File

meridian
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:

  1. Store .mrdn source files in a versioned rules repository.
  2. Compile them into typed Rule IR during deployment or ruleset publication.
  3. Validate source references, types, units, table coverage, and rule capabilities.
  4. Resolve jurisdiction stacks, authority hierarchy, and conflict rules into an effective ruleset.
  5. Cache compiled rule bundles by airline, crew group, jurisdiction stack, version, and hash.
  6. During simulation, load the relevant compiled bundle.
  7. Apply constraint_safe rules to the optimiser.
  8. Apply derived_fact rules before legality evaluation.
  9. Apply objective_term rules during scoring.
  10. Apply evaluation_only rules during or after candidate generation.
  11. 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?