the name: Shorashim → Bikoret (בִּקֹּרֶת) — the specification
Vayikra 19:20 bikoret tihyeh — "there shall be an examination" — the one
noun Torah gives this function; its root ב-ק-ר is the priest's examining
of a mark by its signs (13:36) and the examining between good and bad
(27:33). The judges' form is v'darashta heitev … v'hineh emet nachon
hadavar / ed-sheker ha'ed (Devarim 13:15, 17:4, 19:18); the question
answered is eichah neda et hadavar asher lo dibro (18:21).
The system was named Shorashim ("roots") for the first thing built. Its
function became the examination of a model's output with the sources in
hand, and Torah re-cuts a name when the function is fixed, with its ki,
never for reach (Bereishit 2:19; 17:5; 32:29; 11:4). Nothing was changed
to fit the name; the root engine stays the pe'ah's reading cycle.
Spec files renamed bikoret_*.md; PRD §0 "The Name"; architecture §1.1;
README's Vayishlach row marked done; Tamid lists what still carries the
old word (Kubernetes resource names, the DB role, the domain, local
paths) and why, for the kohen's cut-over.
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
b1c8358f8b
commit
017a9b89d4
22 files changed
+293
-251
No files matched your search
+5
-5
@@ -25,7 +25,7 @@ The two-goat architecture says these paths are provisioned together, from the sa
|
||||
|
||||
## What this is for
|
||||
|
||||
In Shorashim today there are at least four classes of input the system encounters but cannot fully metabolize:
|
||||
In Bikoret today there are at least four classes of input the system encounters but cannot fully metabolize:
|
||||
|
||||
1. **Empty-vital korban.** Zerikah returns no vital content from a model response. Currently the offering is "rejected, not processed into empty propositions" (per `BUILD_KORBAN.md` test 5) — but rejection just discards. There is no permanent record naming what was rejected and why.
|
||||
2. **Halt-tripping content.** A response that triggers `avodah_zarah` / `gilui_arayot` / `shfichut_damim` halts the system. The halt is recorded; the *content that caused it* is not preserved with a structured commit.
|
||||
@@ -85,7 +85,7 @@ From `azazel_engineering_reading.md §14`. Each property gets a specific code-le
|
||||
| 2 | **Blind routing (the goral)** — operator cannot bias | `goral.cast_lot(input_id)` returns `:la_shem` or `:la_azazel` using `secrets.randbits(1)`. Commit-then-reveal: caller MUST submit a commitment hash BEFORE seeing the outcome. The operator chooses to invoke the lot; they do not choose its result. |
|
||||
| 3 | **Enumerative commit (vidui)** — operator-produced, comprehensive, three-fold | `vidui.confess(disposal_input) -> Vidui` produces a structured commit with three required fields: `avonot` (categorical errors — halt-trips), `peshaim` (boundary violations — distinction collapses), `chatot` (target errors — what was offered but unprocessable). All three must be enumerated; an empty list in any slot is acceptable but absence of the slot is not. The vidui is what becomes permanent in the L3 azazel_record. |
|
||||
| 4 | **Role-separated operator (ish itti)** — disposal handler distinct from kohen | `shaliach.py` defines an `IshItti` class. The Korban Processor's `stages.py` enforces owner/kohen separation. Azazel adds a third role: `IshItti`. Functions in `azazel_processor` requiring shaliach context check `IshItti.is_active()`; if a kohen-role caller invokes a shaliach function, refuse. After disposal, `IshItti.tevilah()` must be called — clears any state the handler accumulated (memoized payload references, intermediate tags) before the same process continues. |
|
||||
| 5 | **Provisioned infrastructure (sukkot)** — pre-surveyed route with waystations | `azazel.dispatch_for_disposal()` runs through named checkpoints: `STAGED → CONFESSED → ROUTED → DESTROYED → ACKNOWLEDGED → RECORDED`. Each checkpoint is a recoverable point if the disposal halts mid-route (e.g. L3 write fails after destruction). Implementation: `dispatch_for_disposal` is a state machine, not a linear function. State is persisted at each checkpoint to a process-local file (`/tmp/shorashim/azazel/in_flight/<id>.json`); on restart, half-completed disposals resume from their last checkpoint. |
|
||||
| 5 | **Provisioned infrastructure (sukkot)** — pre-surveyed route with waystations | `azazel.dispatch_for_disposal()` runs through named checkpoints: `STAGED → CONFESSED → ROUTED → DESTROYED → ACKNOWLEDGED → RECORDED`. Each checkpoint is a recoverable point if the disposal halts mid-route (e.g. L3 write fails after destruction). Implementation: `dispatch_for_disposal` is a state machine, not a linear function. State is persisted at each checkpoint to a process-local file (`/tmp/bikoret/azazel/in_flight/<id>.json`); on restart, half-completed disposals resume from their last checkpoint. |
|
||||
| 6 | **Out-of-band acknowledgment (scarlet thread)** — confirmation via side channel | When `RECORDED` checkpoint is reached, fire `Chatzotzrot.signal(:moadim, reason: "Azazel disposal completed: <vidui_summary>")`. The chatzotzrot is the side channel; the disposal flow itself does not return acknowledgment to the caller (the caller already knows they handed the input to disposal — they don't need a return value confirming it). |
|
||||
| 7 | **Authorized routing (Ramban)** — destination unowned, routing decision owned | The Vidui object includes `authorized_by: <kohen_gadol_id>`. The L3 azazel_record records this. The destination is the symbol `:eretz_gezerah` only — no URL, no queue name, no recipient handle. The routing decision is owned and traceable; the destination is not. |
|
||||
| 8 | **Protocol-restricted access** — legitimate only under the full envelope | `azazel.dispatch_for_disposal()` asserts `azazel.is_yom_kippur_protocol_active() or azazel.has_explicit_disposal_authorization()`. Outside that envelope, raise `ProtocolViolation` — invoking the Azazel channel privately is the avodah zarah shape from `specs/eish_zarah_reading.md`. The Yom Kippur predicate currently returns True only when set by the operator; `has_explicit_disposal_authorization` is a flag that allows event-driven disposals during the year (e.g. the empty-vital case from external_offering). |
|
||||
@@ -157,7 +157,7 @@ These are the questions the engineering reading does NOT decide. Each needs an a
|
||||
|
||||
### Q1. When is the goral actually invoked?
|
||||
|
||||
The Mishkan goral routes between two pre-provisioned goats. In Shorashim, most disposal candidates are ALREADY classified (empty vital, halt-tripping, malformed). For those, classification determines routing — there is no goral.
|
||||
The Mishkan goral routes between two pre-provisioned goats. In Bikoret, most disposal candidates are ALREADY classified (empty vital, halt-tripping, malformed). For those, classification determines routing — there is no goral.
|
||||
|
||||
**Where the goral applies:** borderline inputs that *could* be processed with low confidence OR disposed safely. Concretely: zerikah returns vital content with confidence below some threshold. Currently those go through with the low confidence tag. After Azazel: run the goral. Heads → through with low confidence. Tails → disposal.
|
||||
|
||||
@@ -185,7 +185,7 @@ The Mishkan high priest draws both lots simultaneously without seeing them; the
|
||||
|
||||
The Azazel Processor is Python; L3 is Elixir/Postgres. Cross-language write requires a bridge.
|
||||
|
||||
**Proposal:** the Python orchestrator writes the AzazelRecord to a structured JSON file in `/tmp/shorashim/azazel/pending/`. An Elixir GenServer (`VavPipeline.AzazelIngest`) watches the directory, reads each file, calls `L3.Store.record_disposal/1`, and on success deletes the file. This is the same pattern Shorashim uses elsewhere for cross-language state transfer (the manna provision file). Recoverable if either side crashes mid-write.
|
||||
**Proposal:** the Python orchestrator writes the AzazelRecord to a structured JSON file in `/tmp/bikoret/azazel/pending/`. An Elixir GenServer (`VavPipeline.AzazelIngest`) watches the directory, reads each file, calls `L3.Store.record_disposal/1`, and on success deletes the file. This is the same pattern Bikoret uses elsewhere for cross-language state transfer (the manna provision file). Recoverable if either side crashes mid-write.
|
||||
|
||||
### Q6. Should the disposal log endpoint expose vidui details, or only counts?
|
||||
|
||||
@@ -231,7 +231,7 @@ Each commit is independently testable and reviewable. Staging chosen so each com
|
||||
|
||||
### Commit 5 — Orchestrator with full state machine
|
||||
|
||||
- `azazel.py`: `dispatch_for_disposal()` state machine with the 6 named checkpoints, in-flight persistence to `/tmp/shorashim/azazel/in_flight/`, recovery on restart
|
||||
- `azazel.py`: `dispatch_for_disposal()` state machine with the 6 named checkpoints, in-flight persistence to `/tmp/bikoret/azazel/in_flight/`, recovery on restart
|
||||
- `azazel_record.py`: the data type
|
||||
- `test/test_azazel.py`: full happy-path integration; mid-route halt + restart recovery; double-disposal idempotency
|
||||
|
||||
|
||||
Reference in new issue
Block a user