Files
bikoret/vav_pipeline/lib/vav_pipeline/cycle_log.ex
T
Scott KarpandClaude Sonnet 4.6 80ec364da6 Phase 1-2 build: Steps 5-6, 8-13
Shoresh Engine (Haskell, Step 5)
- 12 modules: Types, Lexicon, Binyanim, Teamim, Gematria, Graph,
  KetivQere, Smikhut, Havdalah, Kriah, KiTov, Firmware
- 33 EUnit tests, 0 failures
- Firmware module verifies L1 SHA-256 hash at startup

Talmudic Engine (SWI-Prolog, Step 6)
- 15 modules: halt, reasoning, specification, interface
- 57 PlUnit tests, 0 failures
- Three cardinal halt conditions: avodah_zarah, shfichut_damim, gilui_arayot

Vav Pipeline (Elixir, Steps 8-11)
- 14 modules: BereishitCycle, Shema, Cloud, Manna, L1Reader,
  Specification, HaltConditions, ShabbatTimer, CycleLog, Chatzotzrot,
  ShoreshEngineClient, TalmudicEngineClient, Application
- 46 ExUnit tests, 0 failures
- Nishma-first architecture: hears before it speaks

Sanhedrin Framework (Erlang/OTP, Step 12)
- 8 modules: sanhedrin_app, sanhedrin_sup, escalation, panel_sup,
  panel, judge, clerk, halt_monitor
- 46 EUnit tests, 0 failures (includes fix: rejected outcome now reachable)
- Panel sizes: 1/3/23/71 — unanimous capital guilty → acquit (Sanhedrin 17a)
- Minority opinions append-only, never deleted

Korban Processor (Python, Step 13)
- 6 modules: korban, shechitah, semichah, zerikah, haktarah, router

Builder tooling: AGENTS.md, opencode.json, memory/, src/tools/

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-02-26 14:02:34 -05:00

67 lines
2.0 KiB
Elixir

defmodule VavPipeline.CycleLog do
@moduledoc """
Cycle boundary logging.
Records each Bereishit cycle completion.
Enforces erev/voker boundaries.
Every cycle is logged as an append-only record —
consistent with L3 write protocol (INSERT only, never UPDATE/DELETE).
"""
require Logger
@type cycle_record :: %{
cycle_id: String.t(),
scope: VavPipeline.scope(),
result: atom(),
started_at: DateTime.t(),
completed_at: DateTime.t(),
phase: atom()
}
@doc """
Record a cycle completion.
Phase is :erev (evening — input received) or :voker (morning — output produced).
The cycle boundary is the transition from voker back to erev.
"""
@spec record(VavPipeline.cycle_result(), atom()) :: cycle_record()
def record(result, phase) do
inner = extract_inner(result)
record = %{
cycle_id: generate_id(),
scope: if(is_map(inner), do: Map.get(inner, :scope, %{}), else: %{}),
result: classify_result(result),
started_at: if(is_map(inner), do: Map.get(inner, :started_at, DateTime.utc_now()), else: DateTime.utc_now()),
completed_at: DateTime.utc_now(),
phase: phase
}
Logger.info(
"Cycle #{record.cycle_id}: #{record.result} (#{record.phase}) — " <>
"scope: #{inspect(record.scope)}"
)
record
end
defp extract_inner({:ok, data}), do: data
defp extract_inner({:rejected, _reason}), do: %{}
defp extract_inner({:unresolved, data}), do: data
defp extract_inner({:halted, _, _}), do: %{}
defp extract_inner(other) when is_map(other), do: other
defp extract_inner(_), do: %{}
defp classify_result({:ok, _}), do: :tov
defp classify_result({:rejected, _}), do: :lo_tov
defp classify_result({:unresolved, _}), do: :teiku
defp classify_result(%{status: status}), do: status
defp classify_result(_), do: :unknown
defp generate_id do
:crypto.strong_rand_bytes(8) |> Base.hex_encode32(case: :lower, padding: false)
end
end