# `ordering.toml` / Ordering Rule Files Spec

## Purpose

Ordering rule files define explicit authored ordering constraints that are applied on top of the base mod order.

Base mod order comes from:

1. file order in `layout.mod_files`
2. line order inside each `.list` file
3. enabled entries only

Ordering rule files are used only for additional constraints such as:

- this mod must load after another mod
- this mod must load before another mod

These files are intended for human authorship and should remain readable and maintainable.

---

## Design principles

1. Base ordering comes from `.list` files, not from rule files.
2. Ordering rules are exceptions and constraints, not the main ordering mechanism.
3. Rule files should be explicit and human-readable.
4. Multiple smaller rule files are preferred over one giant file.
5. The same mod reference syntax used in `.list` files should be used in rule files.

---

## File format

Ordering rule files should use TOML, not JSON.

Recommended extension:

```text
rules/00_core.toml
rules/20_ui.toml
rules/30_combat.toml
```

Reasons to prefer TOML:

- comments are supported
- repeated rule blocks are readable
- files are pleasant to edit manually
- Git diffs are cleaner than equivalent JSON

---

## Relationship to `pack.toml`

Rule files are declared explicitly in `pack.toml`.

Example:

```toml
[paths]
ordering_rule_files = [
  "rules/00_core.toml",
  "rules/20_ui.toml",
  "rules/30_combat.toml",
]
```

The order of files in `ordering_rule_files` is the order in which they are loaded.

The application should:

1. read files in listed order
2. parse all rules
3. merge them into one rule set
4. preserve source-file information for diagnostics

Rule files should not include other rule files directly.

Do not use nested include/import mechanisms inside rule files.

---

## Rule schema

Each rule is represented by a `[[rules]]` table.

### Required fields

#### `type`
Type: string

Supported values:

- `"before"`
- `"after"`

#### `mod`
Type: string

Reference to the mod being constrained.

Uses the same reference syntax as `.list` entries.

#### `target`
Type: string

Reference to the mod that acts as the ordering target.

Uses the same reference syntax as `.list` entries.

### Optional fields

#### `reason`
Type: string

Human-readable explanation for why the rule exists.

This is useful for maintenance and debugging.

#### `enabled`
Type: boolean

Optional explicit enable/disable flag for the rule.

This is not strictly required if authors are comfortable commenting out rules, but it may be supported.

---

## Supported reference syntax

Rule references use the same syntax as `.list` files.

Supported forms:

```text
steam:2009463077
packageid:brrainz.harmony
packageid:Ludeon.RimWorld
packageid:Ludeon.RimWorld.Royalty
packageid:Ludeon.RimWorld.Ideology
packageid:Ludeon.RimWorld.Biotech
packageid:Ludeon.RimWorld.Anomaly
local:MyFork
```

The rule system must not invent a second reference language.

---

## Examples

### Minimal example

```toml
[[rules]]
type = "after"
mod = "packageid:my.patch.mod"
target = "packageid:brrainz.harmony"
```

### Recommended example

```toml
# CE-related rules

[[rules]]
type = "after"
mod = "packageid:my.ce.patch"
target = "packageid:ceteam.combatextended"
reason = "Compatibility patch loads after CE"

[[rules]]
type = "before"
mod = "packageid:my.ui.mod"
target = "packageid:ceteam.combatextended"
reason = "UI tweaks should initialize before CE"
```

### Example with local mod

```toml
[[rules]]
type = "after"
mod = "local:MyFork"
target = "steam:2009463077"
reason = "Local fork depends on Harmony behavior"
```

### Example with multiple files

```text
rules/
  00_core.toml
  20_ui.toml
  30_combat.toml
  90_experimental.toml
```

---

## Resolution behavior

The resolver should apply ordering rules only after:

1. collecting base order from `layout.mod_files`
2. parsing enabled `.list` entries
3. resolving references to canonical mod identities

Then it should:

1. map each rule's `mod` and `target` to resolved entries
2. build ordering constraints
3. apply a stable topological sort
4. preserve original relative order wherever possible
5. emit diagnostics for failures or ambiguities

---

## Stability requirement

Ordering rule application must be stable.

That means:

- if no rule requires two mods to change relative order, their original authored order should remain unchanged
- rule application should disturb base order as little as possible

This is essential for predictability.

---

## Diagnostics

If rule application fails or cannot be fully resolved, the tool must emit diagnostics.

Examples:

- `mod` reference not found
- `target` reference not found
- unresolved reference
- cycle detected
- duplicate or contradictory rule intent

Diagnostics should include source-file information when possible.

Example:

- cycle detected between rules in `rules/30_combat.toml` and `rules/90_experimental.toml`

---

## Built-in constraints

Built-in resolver constraints, if any, should be documented separately.

Examples of possible built-in constraints:

- `packageid:Ludeon.RimWorld` loads first
- official DLC package IDs load after `packageid:Ludeon.RimWorld` in canonical order

These are resolver policy rules, not authored ordering rules, and should not be stored in ordering rule files.

---

## What ordering rule files should not do

Ordering rule files should not become the main source of pack structure.

They should not be used to:

- define the entire normal pack order
- replace sensible `.list` file organization
- store lock data
- store full mod metadata
- store UI state
- store large compatibility databases
- implement nested include systems
- introduce wildcard or regex targeting in v1

---

## Scaling guidance

If rules become too large, prefer splitting them into multiple files.

Good:

```toml
[paths]
ordering_rule_files = [
  "rules/00_core.toml",
  "rules/20_ui.toml",
  "rules/30_combat.toml",
  "rules/40_factions.toml",
  "rules/90_experimental.toml",
]
```

Less desirable:

- one giant `rules/ordering.toml` with hundreds of unrelated rules

Large rule counts may indicate a design smell:

- too much is being encoded as rules instead of `.list` order
- base pack structure may need improvement
- rule files may be compensating for weak grouping

---

## Suggested agent guidance

The agent should follow these rules:

1. Treat ordering rules as constraints layered on top of base `.list` order.
2. Use the same reference syntax as `.list` files.
3. Support multiple rule files declared in `pack.toml`.
4. Load rule files in declared order.
5. Preserve source-file information for diagnostics.
6. Apply a stable topological sort.
7. Minimize disruption to original authored order.
8. Do not invent nested include systems inside rule files.
9. Do not treat rule files as the primary source of pack structure.

---

## Compact machine-oriented summary

```text
ordering rule files:
- TOML files declared by [paths].ordering_rule_files in pack.toml
- each file contains repeated [[rules]] tables

rule schema:
- type = "before" | "after"
- mod = "<mod reference>"
- target = "<mod reference>"
- optional reason = "<human note>"
- optional enabled = true | false

reference syntax:
- same as .list files
- steam:<id>
- packageid:<id>
- local:<name>

behavior:
- base order comes from mod_files and line order
- rules are applied after resolution
- apply stable topological sort
- preserve original relative order where possible
- emit diagnostics for missing refs and cycles
```
