Skip to content

HLL Encoding

The HLL encoding phase transforms the approved corpus into formal Halachic Logic Language (HLL) rules. This is where source texts become executable logic that the Mistaber reasoning engine can process. The hll-encode skill guides this transformation and produces artifacts for human review at Checkpoint 2.

Purpose

The hll-encode skill accomplishes:

  1. Statement Transformation: Convert atomic statements to formal rules
  2. World Scoping: Assign rules to appropriate worlds (base, mechaber, rema)
  3. Machloket Encoding: Represent disputes with opposing rules and override mechanism
  4. Makor Attachment: Ensure every rule has complete source attribution
  5. Pre-compile Validation: Catch errors before full compilation

Prerequisites

Before invoking this skill:

  1. Corpus-prep checkpoint MUST be approved
  2. Session state shows corpus-prep.status: approved
  3. Corpus artifacts are available in .mistaber-artifacts/

Invoking the Skill

After corpus approval:

User: "Encode the rules"

The skill automatically:

  1. Loads approved corpus and ontology context
  2. Transforms statements to rules
  3. Generates world-scoped rules
  4. Runs pre-compile validation
  5. Requests checkpoint approval

Phase A: Encoding Context Initialization

Step 1: Load Approved Corpus

The skill reads the approved corpus files:

# Load sources YAML
corpus = yaml.safe_load(
    open(".mistaber-artifacts/corpus-sources-YD-87-1.yaml")
)

# Load resolved questions
questions = yaml.safe_load(
    open(".mistaber-artifacts/corpus-questions-YD-87-1.yaml")
)

It extracts:

  • Atomic statements with types
  • Commentary classifications
  • Machloket entries
  • Derivation chains
  • Human-resolved questions

Step 2: Load Ontology Context

The skill reads the current ontology state:

# Read predicate registry
predicates = read_file("mistaber/ontology/schema/sorts.lp")

# Read existing worlds
worlds = read_file("mistaber/ontology/worlds/kripke_rules.lp")

# Read existing corpus rules for context
existing = glob("mistaber/ontology/corpus/yd_87/*.lp")

This ensures:

  • Predicates are used consistently
  • World names match existing definitions
  • No duplicate rule IDs

Step 3: Initialize Rule ID Generator

Rule IDs follow a topic-based pattern (NOT siman-seif based):

r_{topic}_{specific}

Common Topic Prefixes:

Prefix Topic Example
r_bb_* basar bechalav (meat and milk) r_bb_beheima_achiila
r_bb_dag_* fish-related rules within basar bechalav r_bb_dag_no_bb
r_rema_* Rema-specific rules r_rema_dag_chalav_mutar
r_yo_* Yalkut Yosef rules r_yo_dag_sakana

Rule ID Examples:

Rule ID Meaning
r_bb_beheima_achiila Basar bechalav prohibition for eating beheima
r_bb_bishul_doraita Basar bechalav cooking prohibition (d'oraita)
r_bb_dag_no_bb Fish has no basar bechalav issur
r_rema_dag_chalav_mutar Rema's permission for fish with dairy

Step 4: Load Encoding Templates

The skill references encoding patterns from the plugin's reference files for consistent rule generation.

Phase B: Statement-to-Rule Transformation

For each atomic statement from the corpus, the skill performs a structured transformation.

Step 1: Statement Classification

Map statement type to rule category:

Statement Type Rule Category Primary Predicate
ISSUR Prohibition asserts(W, issur(action, M, level))
ISSUR_SAKANA Health danger asserts(W, sakana(M))
HETER Permission asserts(W, heter(action, M))
CHIYUV Obligation asserts(W, chiyuv(action, M, level))
DEFINITION Category is_X(entity) predicate
CONDITION Prerequisite Part of rule body
EXCEPTION Override override/3 or NAF

Step 2: Predicate Selection

The skill matches statements to predicates in the ontology:

Example mapping:

# Statement: "Meat and milk is forbidden to eat"
predicate: issur
arity: 3
arguments:
  - action: achiila
  - mixture: M (variable)
  - level: d_oraita

The skill validates predicate existence:

assert predicate_exists("issur", 3), f"Predicate issur/3 not in registry"

Refer to Predicate Registry for all available predicates.

Step 3: Argument Mapping

Map statement entities to ASP variables/constants:

Entity Type Mapping Example
Generic mixture Variable M mixture(M)
Specific food Constant food(salmon)
Action type Constant achiila, bishul, hanaah
Level Constant d_oraita, d_rabanan

Variable Naming Conventions:

Variable Represents
M Mixture
F Food
W World
V Vessel
A Action
L Level (madrega)

Step 4: Condition Extraction

Parse conditional language into rule body:

Natural Language ASP Body
"If X contains Y" contains(X, Y)
"When cooked together" mixture(M), cooked(M)
"Unless nullified" not batel(M)
"In case of X" context(X)
"Only if taste transfers" noten_taam(M)

Step 5: Madrega Assignment

Determine the normative level based on:

  1. Derivation chain terminus - Torah source = d_oraita
  2. Explicit statement - "d'rabanan" in source text
  3. Commentary classification - How commentators describe it
% D'oraita - has Torah source
madrega(r_bb_beheima_achiila, d_oraita).

% D'rabanan - rabbinic extension
madrega(r_bb_of_achiila, d_rabanan).

% Minhag - custom
madrega(r_waiting_six_hours, minhag).

% Chumra - stringency
madrega(r_separate_ovens, chumra).

Phase C: World-Scoped Rule Generation

Scope Decision Tree

The skill uses this decision tree to determine world scope:

flowchart TD
    A[Statement] --> B{Universal ruling?<br/>All poskim agree?}
    B -->|Yes| C[base world]
    B -->|No| D{Mechaber/Rema split?}
    D -->|Yes| E[mechaber + rema worlds]
    D -->|No| F{Commentary dispute?}
    F -->|Yes| G[interpretation layer<br/>shach/taz worlds]
    F -->|No| H{Modern authority ruling?}
    H -->|Yes| I[tier 3 world<br/>sefardi_yo/ashk_mb]
    H -->|No| C

Base World Rules

For universally agreed rulings, place in the base world:

% mistaber/ontology/corpus/yd_87/base.lp
% Shared definitions for YD 87 - Basar Bechalav

#include "../../schema/sorts.lp".

% === FOOD TYPE DEFINITIONS ===
basar_type(beheima).
basar_type(of).
basar_type(dag).

% === MIXTURE PREDICATES ===
is_beheima_chalav_mixture(M) :-
    mixture(M),
    mixture_has_basar(M, beheima),
    mixture_has_chalav(M).

is_dag_chalav_mixture(M) :-
    mixture(M),
    mixture_has_basar(M, dag),
    mixture_has_chalav(M).

% === UNIVERSAL RULES (base world) ===
% All authorities agree: beheima + chalav is forbidden d'oraita

rule(r_bb_beheima_achiila).
makor(r_bb_beheima_achiila, sa("yd:87:1")).
makor(r_bb_beheima_achiila, torah("shemot:23:19")).
madrega(r_bb_beheima_achiila, d_oraita).
scope(r_bb_beheima_achiila, base).

asserts(base, issur(achiila, M, d_oraita)) :-
    is_beheima_chalav_mixture(M).

Mechaber World Rules

For Sefardi-specific rulings:

% mistaber/ontology/worlds/mechaber.lp
#include "../corpus/yd_87/base.lp".

% === MECHABER-SPECIFIC: DAG + CHALAV SAKANA ===
% Mechaber holds: Fish + dairy has SAKANA (health danger)

rule(r_bb_dag_sakana).
makor(r_bb_dag_sakana, sa("yd:87:3")).
makor(r_bb_dag_sakana, beit_yosef("yd:87")).
scope(r_bb_dag_sakana, mechaber).

% Assert sakana for fish-dairy mixture
asserts(mechaber, sakana(M)) :-
    is_dag_chalav_mixture(M).

% Sakana creates an issur
asserts(mechaber, issur(achiila, M, sakana)) :-
    is_dag_chalav_mixture(M).

Rema World Rules

For Ashkenazi-specific rulings with overrides:

% mistaber/ontology/worlds/rema.lp
#include "../corpus/yd_87/base.lp".

% === REMA-SPECIFIC: DAG + CHALAV MUTAR ===
% Rema DISAGREES with Mechaber - no sakana for fish + dairy

rule(r_rema_dag_chalav_mutar).
makor(r_rema_dag_chalav_mutar, rema("yd:87:3")).
makor(r_rema_dag_chalav_mutar, taz("yd:87:3")).
makor(r_rema_dag_chalav_mutar, shach("yd:87:5")).
scope(r_rema_dag_chalav_mutar, rema).

% Override Mechaber's sakana ruling
% IMPORTANT: Third argument is the NEW VALUE (descriptive), not 'invalid'
override(rema, sakana(M), no_sakana) :-
    is_dag_chalav_mixture(M).

% Explicitly assert permission
asserts(rema, heter(achiila, M)) :-
    is_dag_chalav_mixture(M).

% Assert the positive: no sakana
asserts(rema, no_sakana(M)) :-
    is_dag_chalav_mixture(M).

Tier 3 World Rules

For modern authorities that follow earlier positions:

% mistaber/ontology/worlds/sefardi_yo.lp
#include "../corpus/yd_87/base.lp".

% === SEFARDI_YO (Yalkut Yosef) ===
% Follows Mechaber - maintains dag sakana

rule(r_yo_dag_sakana).
makor(r_yo_dag_sakana, yalkut_yosef("yd:87:3")).
scope(r_yo_dag_sakana, sefardi_yo).

% Inherits mechaber's sakana via accessible/2
% No need to redefine - accessible(sefardi_yo, mechaber)

Phase D: Machloket Encoding

Step 1: Structure the Dispute

From the corpus machloket entry:

machloket:
  topic: dag_bechalav
  positions:
    - authority: mechaber
      ruling: sakana
    - authority: rema
      ruling: mutar
  practical_difference: "Fish with dairy dishes"

Step 2: Generate Opposing Rules

Each position gets rules in its world (already generated in Phase C).

Step 3: Generate Machloket Marker

Create a detection predicate:

% Machloket marker for detection and comparison queries
machloket(dag_chalav, mechaber, rema, M) :-
    is_dag_chalav_mixture(M).

This allows queries like:

# Find all disputes for a scenario
engine.query("machloket(Topic, A, B, M)")

Step 4: Documentation Comments

Add explanatory comment blocks:

% ============================================================================
% MACHLOKET: Fish and Dairy (Dag Bechalav)
% ============================================================================
% Mechaber: Forbidden due to sakana (health danger)
%   Source: Beit Yosef citing medical sources
%   Practical: Sefardim avoid fish cooked/served with dairy
%
% Rema: Permitted (Ashkenazi practice)
%   Source: Rema's silence + explicit Taz/Shach clarification
%   Practical: Ashkenazim permit lox with cream cheese, fish in cream sauce
%
% Cross-ref: YD 116 for general sakana rules
% ============================================================================

Phase E: Context and Exception Handling

Context-Sensitive Rules

Encode lechatchila/bedieved distinctions:

% Lechatchila (ideally): Do not mix
asserts(W, issur(achiila, M, L)) :-
    world(W),
    is_basar_chalav_mixture(M),
    context(lechatchila).

% Bedieved (after the fact): May be permitted if unintentional
asserts(W, heter(achiila, M)) :-
    world(W),
    is_basar_chalav_mixture(M),
    context(bedieved),
    batel_b_shishim(M),
    not intentional_mixture(M).

Exception Encoding with NAF

Use negation-as-failure for "unless" clauses:

% "Forbidden UNLESS nullified in 60:1"
asserts(W, issur(achiila, M, L)) :-
    world(W),
    is_basar_chalav_mixture(M),
    not batel_b_shishim(M).

% Nullification rule
batel_b_shishim(M) :-
    mixture(M),
    ratio(M, heter, issur, R),
    R >= 60.

Safek Handling

Encode doubt resolution based on madrega:

% Safek d'oraita l'chumra (default)
safek_resolution(W, Query, chumra) :-
    world(W),
    query_madrega(Query, d_oraita),
    safek_policy(W, d_oraita, l_chumra).

% Safek d'rabanan l'kula
safek_resolution(W, Query, kula) :-
    world(W),
    query_madrega(Query, d_rabanan),
    safek_policy(W, d_rabanan, l_kula).

Phase F: Makor Chain Attachment

Primary Makor

Every normative rule MUST have at least one makor:

% Required: SA citation
makor(r_bb_beheima_achiila, sa("yd:87:1")).

Chain Makor

For d'oraita rules, add full derivation chain:

% Full chain for beheima achiila
makor(r_bb_beheima_achiila, sa("yd:87:1")).
makor(r_bb_beheima_achiila, tur("yd:87")).
makor(r_bb_beheima_achiila, rambam("maachalot:9:1")).
makor(r_bb_beheima_achiila, gemara("chullin:104b")).
makor(r_bb_beheima_achiila, mishnah("chullin:8:1")).
makor(r_bb_beheima_achiila, torah("shemot:23:19")).

Source Type Reference

Source Type Format Example
sa Shulchan Aruch sa("yd:87:1")
rema Rema gloss rema("yd:87:3")
tur Arba'ah Turim tur("yd:87")
rambam Mishneh Torah rambam("maachalot:9:1")
beit_yosef Beit Yosef beit_yosef("yd:87")
shach Siftei Kohen shach("yd:87:5")
taz Turei Zahav taz("yd:87:3")
gemara Talmud Bavli gemara("chullin:104b")
mishnah Mishnah mishnah("chullin:8:1")
torah Chumash torah("shemot:23:19")
yalkut_yosef Yalkut Yosef yalkut_yosef("yd:87:3")

Completeness Verification

Every rule must have:

  • [ ] At least one makor/2 fact
  • [ ] For normative rules: madrega/2 fact
  • [ ] For scoped rules: scope/2 fact

Phase G: Static Validation (Pre-Compile)

Step 1: Syntax Validation

Check all rules for:

  • Correct ASP syntax (. terminator)
  • Balanced parentheses
  • Valid variable names (uppercase start)
  • Valid constant names (lowercase start)

Step 2: Predicate Validation

For each used predicate:

for pred, arity in used_predicates:
    assert predicate_in_registry(pred, arity), \
        f"Unknown predicate: {pred}/{arity}"

Step 3: Directive Validation

Verify HLL directives:

Directive Validation
@world Must be valid world name
@makor Must have valid source format
@madrega Must use valid level
@rule Must have unique ID

Step 4: World Consistency

Check world references:

valid_worlds = ["base", "mechaber", "rema", "shach", "taz",
                "sefardi_yo", "ashk_mb", "ashk_ah", "gra"]

for world in referenced_worlds:
    assert world in valid_worlds, f"Unknown world: {world}"

Step 5: Cross-Reference Validation

Verify referenced predicates are defined:

# If rule uses is_beheima_chalav_mixture/1
# Verify it's defined in base.lp or included file

Phase H: Output Generation

Output 1: HLL Rules Files

File Organization (CRITICAL):

  • Shared definitions: mistaber/ontology/corpus/yd_{siman}/base.lp
  • World-specific rules: mistaber/ontology/worlds/{world}.lp

World files use #include to incorporate shared definitions:

% mistaber/ontology/worlds/mechaber.lp
#include "../corpus/yd_87/base.lp".

Example File Structure After Encoding:

mistaber/ontology/
├── corpus/
│   └── yd_87/
│       ├── base.lp           # Shared definitions (new/updated)
│       └── manifest.yaml     # Siman metadata
├── worlds/
│   ├── mechaber.lp           # Mechaber rules (updated)
│   ├── rema.lp               # Rema rules (updated)
│   └── ...
└── schema/
    └── sorts.lp              # Predicate definitions

Output 2: Encoding Report

encoding-report-YD-{siman}-{seif}.md

# Encoding Report: YD 87:1

## Summary
- **Reference:** YD 87:1
- **Encoded at:** 2026-01-25T14:00:00Z
- **Rules Created:** 8
- **Worlds Affected:** base, mechaber, rema

## Rules Generated

### Base World (2 rules)
1. `r_bb_beheima_achiila` - Beheima eating prohibition
2. `r_bb_beheima_bishul` - Beheima cooking prohibition

### Mechaber World (3 rules)
3. `r_bb_dag_sakana` - Fish-dairy sakana
4. `r_bb_dag_issur` - Fish-dairy prohibition
5. `r_bb_hanaah` - Benefit prohibition

### Rema World (3 rules)
6. `r_rema_dag_chalav_mutar` - Fish-dairy permission
7. `r_rema_no_sakana` - No sakana assertion
8. `r_rema_dag_heter` - Explicit heter

## Statement-Rule Mapping
[Traceability table]

## Machloket Encoding
[Dispute details]

## Pre-Compile Results
[Validation output]

Output 3: Statement-Rule Mapping

encoding-mapping-YD-{siman}-{seif}.yaml

reference: "YD:87:3"
encoded_at: "2026-01-25T14:00:00Z"

mappings:
  - statement_id: s1
    rule_ids:
      - r_bb_dag_no_bb
    predicate: "definition"
    notes: "Definition - no BB prohibition for fish"

  - statement_id: s2
    rule_ids:
      - r_bb_dag_bishul_mutar
      - r_bb_dag_achiila_mutar
    predicate: "heter"
    notes: "Permission to cook and eat"

  - statement_id: s3
    rule_ids:
      - r_bb_dag_sakana
    predicate: "sakana/issur"
    world: mechaber
    machloket: true
    notes: "Mechaber's sakana position - disputed by Rema"

  - statement_id: s3_rema
    rule_ids:
      - r_rema_dag_chalav_mutar
    predicate: "heter"
    world: rema
    machloket: true
    notes: "Rema's opposing position"

Output 4: Pre-Compile Results

encoding-validation-YD-{siman}-{seif}.yaml

reference: "YD:87:3"
validated_at: "2026-01-25T14:30:00Z"

syntax_check:
  status: passed
  issues: []

predicate_check:
  status: passed
  predicates_used: 12
  all_registered: true
  list:
    - issur/3
    - heter/2
    - sakana/1
    - is_dag_chalav_mixture/1
    # ...

directive_check:
  status: passed
  rules_with_makor: 8
  rules_with_madrega: 8
  missing_makor: []

world_check:
  status: passed
  worlds_referenced: [base, mechaber, rema]
  all_exist: true

summary:
  total_rules: 8
  base_rules: 2
  world_specific: 6
  machloket_markers: 1
  ready_for_compilation: true

Checkpoint Criteria

Before requesting human approval, verify:

  • [ ] All atomic statements have corresponding rules
  • [ ] Predicates correctly chosen and validated against registry
  • [ ] World scoping accurate (base vs. specific)
  • [ ] Machloket properly encoded with both positions
  • [ ] Makor chain complete for all rules
  • [ ] Madrega levels correct (d_oraita/d_rabanan/etc.)
  • [ ] Pre-compile validation passes
  • [ ] All four outputs generated

Session State Update

After completing encoding:

current_phase: hll-encode
checkpoints:
  hll-encode:
    status: pending_review
    artifacts:
      # Shared definitions
      - path: mistaber/ontology/corpus/yd_87/base.lp
        type: shared_definitions
        new_content: true
      # World-specific rules
      - path: mistaber/ontology/worlds/mechaber.lp
        rules_added: 3
        world: mechaber
      - path: mistaber/ontology/worlds/rema.lp
        rules_added: 3
        world: rema
      # Reports
      - encoding-report-YD-87-1.md
      - encoding-mapping-YD-87-1.yaml
      - encoding-validation-YD-87-1.yaml
    rules_count: 8
    worlds_affected: [base, mechaber, rema]

Common Patterns

Pattern 1: Simple Prohibition

rule(r_simple_issur).
makor(r_simple_issur, sa("yd:XX:Y")).
madrega(r_simple_issur, d_oraita).
scope(r_simple_issur, base).

asserts(base, issur(achiila, M, d_oraita)) :-
    matching_condition(M).

Pattern 2: Machloket with Override

% Position A (in mechaber.lp)
rule(r_position_a).
asserts(mechaber, ruling_a(M)) :- condition(M).

% Position B (in rema.lp)
rule(r_position_b).
override(rema, ruling_a(M), ruling_b) :- condition(M).
asserts(rema, ruling_b(M)) :- condition(M).

% Marker
machloket(topic, mechaber, rema, M) :- condition(M).

Pattern 3: Conditional Ruling

rule(r_conditional).
% Applies only when context is bedieved
asserts(W, heter(achiila, M)) :-
    world(W),
    condition(M),
    context(bedieved).

Pattern 4: Definition with Classification

% Food is considered basar
is_basar(F) :- food(F), food_type(F, beheima).
is_basar(F) :- food(F), food_type(F, chaya).
is_basar(F) :- food(F), food_type(F, of).

Troubleshooting

"Unknown predicate X/N"

  1. Check Predicate Registry
  2. If predicate should exist, check spelling
  3. If new predicate needed, document and add to sorts.lp

"Rule ID already exists"

  1. Use topic-based naming: r_{topic}_{specific}
  2. Avoid sequential numbers: r_1, r_2
  3. Be specific: r_bb_beheima_achiila not r_bb_1

"World inheritance not working"

  1. Verify #include statements
  2. Check accessible/2 rules in kripke_rules.lp
  3. Ensure base rules use asserts(base, ...) not asserts(mechaber, ...)

"Override not taking effect"

  1. Third argument must be descriptive value, not 'invalid'
  2. Ensure condition in override matches original rule
  3. Check that override world is accessible from base

Best Practices

  1. Use topic-based rule IDs - r_bb_achiila not r_87_1_1
  2. Document machloket thoroughly - Include sources for both positions
  3. Keep shared definitions in base.lp - World files only add specific rules
  4. Test override mechanism - Ensure both positions are derivable
  5. Validate before checkpoint - Catch errors early

Next Phase

After Checkpoint 2 approval, proceed to Validation and Testing.