manna: written by the system's own hand each morning; Friday's double stands on Shabbat
Shemot 16: dvar yom b'yomo, and on the sixth day double, and none on the seventh. Every night at 00:00Z the day's provision went stale and the readiness probe failed until someone woke — 13.5 hours on 2026-10-15. CronJob `manna` (deploy/k8s/manna-cronjob.yaml) runs at 00:01Z Sunday to Friday in our own korban-processor image, mounts the manna PVC as the app's uid, and writes today.json from the ConfigMap's MANNA_* amounts — doubled on Friday, valid to Sunday 00:30Z. The pipeline now accepts Friday's `double` on Saturday (validate_date/3) and nothing else across a day boundary; three tests. The kohen sets the amounts, may still write by hand, and reads a failed job as the Day-4 alarm (KOHEN "The manna, each morning"; Tamid §1.1). Doorpost re-pinned. Elixir green. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
This commit is contained in:
1 parent
1a069cf62d
commit
42024279b9
7 files changed
+189
-10
No files matched your search
@@ -625,7 +625,26 @@ counts move without a commit to the readings is the finding.
|
|||||||
|
|
||||||
### Friday before sunset — *Erev Shabbat*
|
### Friday before sunset — *Erev Shabbat*
|
||||||
|
|
||||||
Write a **double portion** manna provision (`type: "double"`, doubled compute_units). The system will cease processing at Shabbat onset. No provision is written on Shabbat.
|
The manna CronJob writes Friday's provision as a **double portion**
|
||||||
|
(`type: "double"`, doubled compute units and external calls, valid to
|
||||||
|
Sunday 00:30Z); the pipeline accepts Friday's double on Saturday and
|
||||||
|
nothing else across a day boundary. The system ceases processing at
|
||||||
|
Shabbat onset. No provision is written on Shabbat — the CronJob does not
|
||||||
|
run on Saturday.
|
||||||
|
|
||||||
|
### The manna, each morning — *Dvar yom b'yomo*
|
||||||
|
|
||||||
|
Since 2026-10-15 the day's provision is written by the system's own hand:
|
||||||
|
CronJob `manna` (`deploy/k8s/manna-cronjob.yaml`) runs at 00:01Z Sunday
|
||||||
|
to Friday, mounts the manna PVC and writes `today.json` with the amounts
|
||||||
|
from `shorashim-config` (`MANNA_COMPUTE_UNITS` …). Before it, every night
|
||||||
|
at 00:00Z the old provision went stale and the readiness probe failed
|
||||||
|
until someone woke (13.5 hours on 2026-10-15). The kohen's acts now:
|
||||||
|
|
||||||
|
- set the amounts in the ConfigMap (`kubectl apply -f deploy/k8s/configmap.yaml`);
|
||||||
|
- read `kubectl -n shorashim get jobs` after 00:01Z — a failed job is the
|
||||||
|
Day-4 alarm; write by hand with `kubectl cp` (Day 4) if it failed;
|
||||||
|
- run it at once when needed: `kubectl -n shorashim create job --from=cronjob/manna manna-now`.
|
||||||
|
|
||||||
### If the system halts
|
### If the system halts
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,16 @@ data:
|
|||||||
# Manna provision file location
|
# Manna provision file location
|
||||||
MANNA_PROVISION_FILE: "/var/lib/bikoret/manna/today.json"
|
MANNA_PROVISION_FILE: "/var/lib/bikoret/manna/today.json"
|
||||||
|
|
||||||
|
# The day's portion, written by the manna CronJob at 00:01Z Sunday to
|
||||||
|
# Friday (manna-cronjob.yaml); Friday's is doubled and stands through
|
||||||
|
# Shabbat. The kohen sets the amounts here (Pekudei: from the half-shekel
|
||||||
|
# fund); a change takes effect at the next writing.
|
||||||
|
MANNA_COMPUTE_UNITS: "1000"
|
||||||
|
MANNA_MEMORY_MB: "32768"
|
||||||
|
MANNA_API_CALLS_EXTERNAL: "500"
|
||||||
|
MANNA_STORAGE_DELTA_MB: "100"
|
||||||
|
MANNA_SANHEDRIN_PANELS_MAX: "5"
|
||||||
|
|
||||||
# Talmudic Engine socket
|
# Talmudic Engine socket
|
||||||
TALMUDIC_SOCKET_PATH: "/tmp/bikoret/talmudic.sock"
|
TALMUDIC_SOCKET_PATH: "/tmp/bikoret/talmudic.sock"
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,96 @@
|
|||||||
|
# The manna — written each morning by the system's own hand (Shemot 16).
|
||||||
|
#
|
||||||
|
# Until 2026-10-15 the day's provision was written by the kohen with
|
||||||
|
# `kubectl cp`, and every night at 00:00Z the old one went stale and the
|
||||||
|
# readiness probe failed until someone woke (13.5 hours on 2026-10-15).
|
||||||
|
# This CronJob writes today.json onto the manna PVC at 00:01Z, Sunday to
|
||||||
|
# Friday — a double portion on Friday that is valid through Shabbat, and
|
||||||
|
# nothing on Shabbat (Shemot 16:22–26: "on the sixth day they gathered
|
||||||
|
# double … on the seventh day there shall be none"). The kohen still sets
|
||||||
|
# the amounts (shorashim-config, MANNA_* below) and may still write a
|
||||||
|
# provision by hand at any hour; the CronJob only ends the gap.
|
||||||
|
#
|
||||||
|
# It runs our own korban-processor image (python, pinned to a commit tag)
|
||||||
|
# with the PVC mounted, as the app's uid/gid, so the file is readable by
|
||||||
|
# the pod; nothing else, no cluster permissions. ReadWriteOnce is fine:
|
||||||
|
# the cluster has one node and the job runs beside the pod.
|
||||||
|
apiVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: manna
|
||||||
|
namespace: shorashim
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: shorashim
|
||||||
|
app.kubernetes.io/component: manna
|
||||||
|
spec:
|
||||||
|
schedule: "1 0 * * 0-5" # 00:01Z, Sunday–Friday; none on Shabbat
|
||||||
|
timeZone: "Etc/UTC"
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
startingDeadlineSeconds: 3600 # a missed 00:01 still runs within the hour
|
||||||
|
successfulJobsHistoryLimit: 3
|
||||||
|
failedJobsHistoryLimit: 3
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
backoffLimit: 2
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app.kubernetes.io/name: shorashim
|
||||||
|
app.kubernetes.io/component: manna
|
||||||
|
spec:
|
||||||
|
restartPolicy: Never
|
||||||
|
securityContext:
|
||||||
|
runAsUser: 1000
|
||||||
|
runAsGroup: 1000
|
||||||
|
fsGroup: 1000
|
||||||
|
imagePullSecrets:
|
||||||
|
- name: shorashim-registry
|
||||||
|
volumes:
|
||||||
|
- name: manna
|
||||||
|
persistentVolumeClaim:
|
||||||
|
claimName: manna-pvc
|
||||||
|
containers:
|
||||||
|
- name: write-manna
|
||||||
|
image: exo.container-registry.com/the-recognition-protocol/korban-processor:c0d0555a
|
||||||
|
imagePullPolicy: IfNotPresent
|
||||||
|
envFrom:
|
||||||
|
- configMapRef:
|
||||||
|
name: shorashim-config
|
||||||
|
volumeMounts:
|
||||||
|
- name: manna
|
||||||
|
mountPath: /var/lib/bikoret/manna
|
||||||
|
resources:
|
||||||
|
requests: { cpu: "20m", memory: "32Mi" }
|
||||||
|
limits: { cpu: "200m", memory: "128Mi" }
|
||||||
|
command: ["python3", "-c"]
|
||||||
|
args:
|
||||||
|
- |
|
||||||
|
import json, os, datetime as dt
|
||||||
|
now = dt.datetime.now(dt.timezone.utc)
|
||||||
|
today = now.date()
|
||||||
|
friday = today.weekday() == 4
|
||||||
|
units = int(os.environ.get("MANNA_COMPUTE_UNITS", "1000"))
|
||||||
|
provision = {
|
||||||
|
"compute_units": units * (2 if friday else 1),
|
||||||
|
"memory_mb": int(os.environ.get("MANNA_MEMORY_MB", "32768")),
|
||||||
|
"api_calls_external": int(os.environ.get("MANNA_API_CALLS_EXTERNAL", "500")) * (2 if friday else 1),
|
||||||
|
"storage_delta_mb": int(os.environ.get("MANNA_STORAGE_DELTA_MB", "100")),
|
||||||
|
"sanhedrin_panels_max": int(os.environ.get("MANNA_SANHEDRIN_PANELS_MAX", "5")),
|
||||||
|
}
|
||||||
|
# Regular: through the day. Double (Friday): through Shabbat, to Sunday 00:30Z.
|
||||||
|
expires = (dt.datetime.combine(today + dt.timedelta(days=2), dt.time(0, 30), dt.timezone.utc)
|
||||||
|
if friday else dt.datetime.combine(today + dt.timedelta(days=1), dt.time(0, 30), dt.timezone.utc))
|
||||||
|
doc = {
|
||||||
|
"date": today.isoformat(),
|
||||||
|
"provision": provision,
|
||||||
|
"type": "double" if friday else "regular",
|
||||||
|
"expires_at": expires.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||||
|
"written_by": "manna-cronjob",
|
||||||
|
"written_at": now.strftime("%Y-%m-%dT%H:%M:%SZ"),
|
||||||
|
}
|
||||||
|
path = os.environ.get("MANNA_PROVISION_FILE", "/var/lib/bikoret/manna/today.json")
|
||||||
|
tmp = path + ".tmp"
|
||||||
|
with open(tmp, "w") as fh:
|
||||||
|
json.dump(doc, fh, indent=2)
|
||||||
|
os.replace(tmp, path)
|
||||||
|
print("manna written", doc["date"], doc["type"], "expires", doc["expires_at"])
|
||||||
@@ -365,6 +365,14 @@ Errors: as /courtyard/bedikah, with "side 'a': …" / "side 'b': …" in the
|
|||||||
message; a missing side is 422.
|
message; a missing side is 422.
|
||||||
```
|
```
|
||||||
|
|
||||||
|
**The manna is written by the system's own hand** (2026-10-15): CronJob
|
||||||
|
`manna` at 00:01Z Sunday–Friday writes the day's provision onto the manna
|
||||||
|
PVC from the ConfigMap's `MANNA_*` amounts; Friday's is a double portion
|
||||||
|
that the pipeline accepts on Shabbat (Shemot 16:22–26); nothing is
|
||||||
|
written on Shabbat, nothing else crosses a day boundary. The kohen sets
|
||||||
|
the amounts and may still write by hand; a failed job is the Day-4 alarm
|
||||||
|
(KOHEN "The manna, each morning").
|
||||||
|
|
||||||
**The names that still carry the old word** (renamed 2026-10-13, PRD §0).
|
**The names that still carry the old word** (renamed 2026-10-13, PRD §0).
|
||||||
Everything the specification, the code, the images and the API say is
|
Everything the specification, the code, the images and the API say is
|
||||||
*Bikoret*: headers `X-Bikoret-*`, the `bikoret` object on a gate reply,
|
*Bikoret*: headers `X-Bikoret-*`, the `bikoret` object on a gate reply,
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ defmodule VavPipeline.Doorpost do
|
|||||||
# changes; the update is a deliberate operator commit. A bare
|
# changes; the update is a deliberate operator commit. A bare
|
||||||
# hash-update commit (without a corresponding spec change in the
|
# hash-update commit (without a corresponding spec change in the
|
||||||
# same commit) is itself a drift signal.
|
# same commit) is itself a drift signal.
|
||||||
@expected_hash "10735ab4e4280bf35d19d6ed79804c31d5ef199a70a289f455e138085e9cba5d"
|
@expected_hash "65bf08fc3c22307eb10ea6833ddeb475b1f6d87f145901e8d1b426c544c523be"
|
||||||
|
|
||||||
@doc "Return the list of files that constitute the category-grade specification."
|
@doc "Return the list of files that constitute the category-grade specification."
|
||||||
@spec files() :: [String.t()]
|
@spec files() :: [String.t()]
|
||||||
|
|||||||
@@ -253,7 +253,7 @@ defmodule VavPipeline.Manna do
|
|||||||
end
|
end
|
||||||
|
|
||||||
defp validate_manna(data, now) do
|
defp validate_manna(data, now) do
|
||||||
with {:ok, date} <- validate_date(data["date"], now),
|
with {:ok, date} <- validate_date(data["date"], now, parse_type(data["type"])),
|
||||||
{:ok, provision} <- validate_provision(data["provision"]),
|
{:ok, provision} <- validate_provision(data["provision"]),
|
||||||
{:ok, expires_at} <- parse_expires_at(data["expires_at"]),
|
{:ok, expires_at} <- parse_expires_at(data["expires_at"]),
|
||||||
:ok <- check_expiry(expires_at, now) do
|
:ok <- check_expiry(expires_at, now) do
|
||||||
@@ -269,15 +269,25 @@ defmodule VavPipeline.Manna do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
defp validate_date(nil, _now), do: {:error, "MANNA_INVALID: missing date"}
|
defp validate_date(nil, _now, _type), do: {:error, "MANNA_INVALID: missing date"}
|
||||||
|
|
||||||
defp validate_date(date_str, now) do
|
# A provision is for its day — except the double portion: gathered on
|
||||||
today = DateTime.to_date(now) |> Date.to_iso8601()
|
# Friday, it is the Shabbat's too (Shemot 16:22–26), so Friday's
|
||||||
|
# `double` stands on Saturday. Nothing else carries over the boundary.
|
||||||
|
defp validate_date(date_str, now, type) do
|
||||||
|
today = DateTime.to_date(now)
|
||||||
|
today_str = Date.to_iso8601(today)
|
||||||
|
yesterday = Date.add(today, -1)
|
||||||
|
|
||||||
if date_str == today do
|
cond do
|
||||||
{:ok, date_str}
|
date_str == today_str ->
|
||||||
else
|
{:ok, date_str}
|
||||||
{:error, "MANNA_STALE: provision is for #{date_str}, today is #{today}"}
|
|
||||||
|
type == :double and Date.day_of_week(today) == 6 and date_str == Date.to_iso8601(yesterday) ->
|
||||||
|
{:ok, date_str}
|
||||||
|
|
||||||
|
true ->
|
||||||
|
{:error, "MANNA_STALE: provision is for #{date_str}, today is #{today_str}"}
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,36 @@
|
|||||||
|
defmodule VavPipeline.MannaShabbatTest do
|
||||||
|
@moduledoc "Shemot 16:22–26: Friday's double portion is the Shabbat's too; nothing else crosses the day boundary."
|
||||||
|
use ExUnit.Case, async: false
|
||||||
|
alias VavPipeline.Manna
|
||||||
|
|
||||||
|
@friday ~D[2026-10-16]
|
||||||
|
@saturday ~D[2026-10-17]
|
||||||
|
@sunday ~D[2026-10-18]
|
||||||
|
|
||||||
|
defp write(date, type, expires) do
|
||||||
|
path = Manna.provision_file()
|
||||||
|
File.mkdir_p!(Path.dirname(path))
|
||||||
|
File.write!(path, Jason.encode!(%{"date" => Date.to_iso8601(date), "provision" => %{"compute_units" => 2000, "memory_mb" => 1, "api_calls_external" => 1, "storage_delta_mb" => 1, "sanhedrin_panels_max" => 1}, "type" => type, "expires_at" => expires, "written_by" => "test", "written_at" => "2026-10-16T00:01:00Z"}))
|
||||||
|
on_exit(fn -> File.rm(path) end)
|
||||||
|
end
|
||||||
|
|
||||||
|
defp at(date, h), do: DateTime.new!(date, Time.new!(h, 0, 0), "Etc/UTC")
|
||||||
|
|
||||||
|
test "Friday's double stands on Saturday" do
|
||||||
|
write(@friday, "double", "2026-10-18T00:30:00Z")
|
||||||
|
assert {:ok, %{type: :double}} = Manna.check_at(at(@friday, 12))
|
||||||
|
assert {:ok, %{type: :double}} = Manna.check_at(at(@saturday, 12))
|
||||||
|
end
|
||||||
|
|
||||||
|
test "a regular provision does not cross the boundary; a double does not reach Sunday" do
|
||||||
|
write(@friday, "regular", "2026-10-18T00:30:00Z")
|
||||||
|
assert {:error, "MANNA_STALE" <> _} = Manna.check_at(at(@saturday, 12))
|
||||||
|
write(@friday, "double", "2026-10-19T00:30:00Z")
|
||||||
|
assert {:error, "MANNA_STALE" <> _} = Manna.check_at(at(@sunday, 12))
|
||||||
|
end
|
||||||
|
|
||||||
|
test "a double written on a Thursday does not carry to Friday — only Shabbat receives it" do
|
||||||
|
write(~D[2026-10-15], "double", "2026-10-17T00:30:00Z")
|
||||||
|
assert {:error, "MANNA_STALE" <> _} = Manna.check_at(at(@friday, 12))
|
||||||
|
end
|
||||||
|
end
|
||||||
Reference in new issue
Block a user