Skip to content

HLL Encoding Skill

The hll-encode skill transforms approved corpus preparation artifacts into HLL (Halachic Logic Language) rules with proper world scoping, makor attribution, madrega levels, and ASP-compatible syntax.

Overview

Attribute Value
Skill Name hll-encode
Phase 2 of 5
Checkpoint 2: Rule Review
Prerequisites Checkpoint 1 (corpus-prep) approved
Outputs base.lp, world-specific .lp files, encoding-report.md, encoding-mapping.yaml
Trigger Phrases "encode rules", "write HLL", "create ASP rules", "encode seif", "translate to HLL", "encode machloket"

Prerequisites

Before this skill can execute:

  1. Corpus-prep checkpoint MUST be approved
  2. Corpus artifacts must exist:
  3. corpus-sources-YD-{siman}-{seif}.yaml
  4. corpus-questions-YD-{siman}-{seif}.yaml (with resolved answers)
  5. Session state shows corpus-prep.status: approved

Phase A: Encoding Context Initialization

Step 1: Load Approved Corpus

The skill loads the approved corpus files:

# From corpus-sources-YD-87-3.yaml
statements:
  - id: s1
    type: DEFINITION
    text_en: "Fish and locusts have no basar bechalav prohibition"
    world_context: base

  - id: s2
    type: HETER
    text_en: "Permitted to cook them with milk"
    world_context: base

  - id: s3
    type: ISSUR_SAKANA
    text_en: "But forbidden to eat together due to danger"
    world_context: mechaber  # Disputed

machloket:
  - id: m1
    topic: dag_bechalav
    position_a:
      authority: mechaber
      ruling: sakana
    position_b:
      authority: rema
      ruling: mutar

Step 2: Load Ontology Context

The skill reads 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 this siman
existing = glob("mistaber/ontology/corpus/yd_{siman}/*.lp")

Step 3: Initialize Rule ID Generator

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

r_{topic}_{specific}

Topic Prefixes:

Prefix Topic
r_bb_* Basar bechalav (meat and milk)
r_bb_dag_* Fish-related rules within basar bechalav
r_rema_* Rema-specific (authority prefix)
r_yo_* Yalkut Yosef rules
r_mb_* Mishnah Berurah rules

Examples:

Rule ID Meaning
r_bb_beheima_achiila Basar bechalav beheima eating
r_bb_dag_no_bb Fish has no BB issur
r_rema_dag_chalav_mutar Rema's fish-dairy permission
r_yo_dag_sakana Yalkut Yosef's fish sakana

Phase B: Statement-to-Rule Transformation

Step 1: Statement Classification

Each statement type maps to a rule category:

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

Step 2: Predicate Selection

Statements are mapped to predicates in the ontology:

# Statement: "Fish + dairy is forbidden to eat due to sakana"
# Maps to:
predicate: sakana
arity: 1
arguments:
  - mixture: M (variable)
secondary_predicate: issur
secondary_arguments:
  - action: achiila
  - mixture: M
  - level: sakana

The skill validates predicates exist:

assert predicate_exists("sakana", 1), "Predicate sakana/1 not in registry"

Step 3: Argument Mapping

Statement entities map 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, sakana

Step 4: Condition Extraction

Conditional language parses to 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)

Step 5: Madrega Assignment

Normative level is determined from:

  • Derivation chain terminus (Torah = d_oraita)
  • Explicit statement in SA ("d'rabanan")
  • Commentary classification
% D'oraita - has Torah source
madrega(r_bb_achiila, d_oraita).

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

% Sakana - health danger (special level)
madrega(r_bb_dag_sakana, sakana).

% Minhag - custom
madrega(r_minhag_rule, minhag).

% Chumra - stringency
madrega(r_strict_rule, chumra).

Phase C: World-Scoped Rule Generation

Scope Decision Tree

graph TD
    A[Statement] --> B{Universal?}
    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]
    F -->|No| H{Modern Authority?}
    H -->|Yes| I[Tier 3 World]
    H -->|No| C

Base World Rules

For universally agreed rulings, rules go in corpus/yd_{siman}/base.lp:

% mistaber/ontology/corpus/yd_87/base.lp
% Yoreh Deah Siman 87: Basar Bechalav - Shared Definitions
%
% This file contains definitions and rules that ALL authorities agree upon.
% World-specific rules go in worlds/*.lp files.

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

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

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

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

% === SEIF 1: UNIVERSAL RULES ===
% All 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).

% === SEIF 3: FISH HAS NO BB ISSUR (UNIVERSAL) ===
% All agree: Fish has no basar bechalav prohibition
rule(r_bb_dag_no_bb).
makor(r_bb_dag_no_bb, sa("yd:87:3")).
scope(r_bb_dag_no_bb, base).

asserts(base, no_bb_issur(M)) :-
    is_dag_chalav_mixture(M).

Mechaber World Rules

For Sefardi-specific rulings, rules go in worlds/mechaber.lp:

% mistaber/ontology/worlds/mechaber.lp
% Mechaber (Sefardi) World-Specific Rules

#include "../corpus/yd_87/base.lp".

% === YD 87:3 - DAG + CHALAV SAKANA (MECHABER ONLY) ===
rule(r_bb_dag_sakana).
makor(r_bb_dag_sakana, sa("yd:87:3")).
makor(r_bb_dag_sakana, beit_yosef("yd:87")).
madrega(r_bb_dag_sakana, sakana).
scope(r_bb_dag_sakana, mechaber).

% Fish + dairy triggers sakana
asserts(mechaber, sakana(M)) :-
    is_dag_chalav_mixture(M).

% Sakana implies issur achiila
asserts(mechaber, issur(achiila, M, sakana)) :-
    is_dag_chalav_mixture(M),
    holds(sakana(M), mechaber).

Rema World Rules

For Ashkenazi-specific rulings with overrides, rules go in worlds/rema.lp:

% mistaber/ontology/worlds/rema.lp
% Rema (Ashkenazi) World-Specific Rules

#include "../corpus/yd_87/base.lp".

% === YD 87:3 - DAG + CHALAV MUTAR (REMA) ===
% Rema disagrees with Mechaber on 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
% CRITICAL: Third argument is DESCRIPTIVE VALUE, 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 no sakana in this world
asserts(rema, no_sakana(M)) :-
    is_dag_chalav_mixture(M).

Tier 3 World Rules

For modern authorities (e.g., in worlds/sefardi_yo.lp):

% mistaber/ontology/worlds/sefardi_yo.lp
% Sefardi (Yalkut Yosef) World-Specific Rules

#include "../corpus/yd_87/base.lp".

% === SEFARDI_YO (Yalkut Yosef) ===
% Inherits from mechaber, follows 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 - no override needed
% World inheritance handles this automatically

Phase D: Machloket Encoding

Step 1: Structure the Dispute

From the corpus machloket data:

machloket:
  topic: dag_bechalav
  positions:
    - authority: mechaber
      ruling: sakana
      world: mechaber
    - authority: rema
      ruling: mutar
      world: rema
  practical_difference: "Fish with dairy dishes (lox + cream cheese)"

Step 2: Generate Opposing Rules

(Already generated in Phase C world-specific rules)

Step 3: Generate Machloket Marker

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

Step 4: Documentation Comments

% ============================================================================
% MACHLOKET: Fish and Dairy (Dag Bechalav)
% ============================================================================
% Mechaber: Forbidden due to sakana (health danger)
%   Source: Beit Yosef citing medical sources
%   Worlds: mechaber, sefardi_yo
%
% Rema: Permitted (Ashkenazi practice)
%   Source: Rema's silence + explicit Taz/Shach clarification
%   Worlds: rema, ashk_mb, ashk_ah
%
% Practical: Lox with cream cheese, fish in cream sauce, gefillte fish + butter
% ============================================================================

Phase E: Context & Exception Handling

Lechatchila/Bedieved Distinctions

% Lechatchila: Ideally, Sefardim avoid fish + dairy
asserts(mechaber, issur(achiila, M, sakana)) :-
    is_dag_chalav_mixture(M),
    context(lechatchila).

% Bedieved: If already mixed, some poskim are lenient
% (Encode if commentary supports)
asserts(mechaber, heter(achiila, M)) :-
    is_dag_chalav_mixture(M),
    context(bedieved),
    hefsed_merubeh.  % Significant financial loss

Exception Encoding with NAF

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

% "Permitted IF already mixed AND not intentional"
asserts(W, heter(achiila, M)) :-
    is_basar_chalav_mixture(M),
    batel_b_shishim(M),
    not intentional_mixture(M).

Override Semantics

CRITICAL: Always use descriptive values for override/3

% CORRECT: Third argument describes the new state
override(rema, sakana(M), no_sakana) :- ...
override(gra, strict_ruling(X), lenient_ruling) :- ...

% WRONG: Never use 'invalid' as third argument
% override(rema, sakana(M), invalid) :- ...  % DO NOT DO THIS

Phase F: Makor Chain Attachment

Primary Makor

Every normative rule MUST have at least one makor:

% Required: SA citation
makor(r_bb_dag_sakana, sa("yd:87:3")).

Full Chain for D'oraita Rules

% 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")).

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: Pre-Compile Validation

Syntax Validation

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

Predicate Validation

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

World Validation

VALID_WORLDS = {"base", "mechaber", "rema", "gra", "sefardi_yo", "ashk_mb", "ashk_ah"}

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

Phase H: Output Generation

Output 1: Shared Definitions File

mistaber/ontology/corpus/yd_{siman}/base.lp

Contains: - Sort definitions shared across worlds - Mixture predicate definitions - Universal rules (no machloket)

Output 2: World-Specific Files

mistaber/ontology/worlds/{world}.lp

Contains: - #include of shared definitions - World-specific rules - Override declarations - Machloket markers

Output 3: Encoding Report

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

Uses template from templates/encoding-report.md:

  • Statement-to-rule mapping table
  • World distribution summary
  • Rule details with encoding
  • Machloket documentation
  • Pre-compile validation results

Output 4: Encoding 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"

Checkpoint Criteria

Before requesting human approval:

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

Session State Update

After completing encoding:

current_phase: hll-encode
checkpoints:
  hll-encode:
    status: pending_review
    artifacts:
      - path: mistaber/ontology/corpus/yd_87/base.lp
        type: shared_definitions
      - path: mistaber/ontology/worlds/mechaber.lp
        rules_count: 4
        world: mechaber
      - path: mistaber/ontology/worlds/rema.lp
        rules_count: 4
        world: rema
      - encoding-report-YD-87-3.md
      - encoding-mapping-YD-87-3.yaml

Common Issues

Missing Makor Attribution

The encoding-guard hook will block writes if rules lack makor:

BLOCKED: Rule 'r_bb_dag_sakana' uses normative predicate but has no makor

Solution: Add makor facts for all normative rules.

Unknown World Reference

BLOCKED: Unknown world referenced: 'mechaver' (typo)

Solution: Check spelling against VALID_WORLDS.

Override Third Argument

BLOCKED: Override uses 'invalid' - use descriptive value

Solution: Use descriptive new value, e.g., no_sakana instead of invalid.