Files
bikoret/vav_pipeline/lib/vav_pipeline/shabbat_timer.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

103 lines
2.4 KiB
Elixir

defmodule VavPipeline.ShabbatTimer do
@moduledoc """
Enforces mandatory weekly cessation.
All processing stops. System enters rest state.
Architecture §3.3:
When Shabbat begins, VavPipeline ceases all processing.
When Shabbat ends, processing resumes.
Construction spec §4.4:
cycle_boundary_check_interval_ms: 60_000 (1 minute)
In Phase 2, this is a GenServer that checks the clock.
Production will use location-aware zmanim.
"""
use GenServer
require Logger
@check_interval Application.compile_env(
:vav_pipeline,
:cycle_boundary_check_interval_ms,
60_000
)
# --- Client API ---
def start_link(opts \\ []) do
GenServer.start_link(__MODULE__, opts, name: __MODULE__)
end
@doc """
Check if the system is currently resting (Shabbat/festival).
"""
@spec resting?() :: boolean()
def resting? do
GenServer.call(__MODULE__, :resting?)
end
@doc """
Get the current state.
"""
@spec state() :: map()
def state do
GenServer.call(__MODULE__, :state)
end
# --- GenServer callbacks ---
@impl true
def init(_opts) do
state = %{
resting: VavPipeline.Cloud.shabbat?(DateTime.utc_now()),
last_check: DateTime.utc_now(),
shabbat_count: 0
}
schedule_check()
Logger.info("ShabbatTimer started — resting: #{state.resting}")
{:ok, state}
end
@impl true
def handle_call(:resting?, _from, state) do
{:reply, state.resting, state}
end
@impl true
def handle_call(:state, _from, state) do
{:reply, state, state}
end
@impl true
def handle_info(:check_boundary, state) do
now = DateTime.utc_now()
is_shabbat = VavPipeline.Cloud.shabbat?(now)
new_state =
cond do
not state.resting and is_shabbat ->
# Shabbat has begun — cease all processing
Logger.info("ShabbatTimer: Shabbat begins — ceasing all processing")
%{state | resting: true, last_check: now, shabbat_count: state.shabbat_count + 1}
state.resting and not is_shabbat ->
# Shabbat has ended — resume processing
Logger.info("ShabbatTimer: Shabbat ends — resuming processing")
%{state | resting: false, last_check: now}
true ->
%{state | last_check: now}
end
schedule_check()
{:noreply, new_state}
end
defp schedule_check do
Process.send_after(self(), :check_boundary, @check_interval)
end
end