From 354e223384a502073182ad1652c9e2d9a4db73ed Mon Sep 17 00:00:00 2001 From: Scott Karp Date: Wed, 21 Oct 2026 18:32:35 +0000 Subject: [PATCH] housekeeping: the inventory a stranger reads first MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit From a reading of the gate's documents (2026-10-21): - AGENTS.md: Steps 14 and 15 shown Pending while the Port and both sockets have carried live traffic since the gate was built → Done, with what carries them; "next build task" now points at the open items, the phase tables being complete. - README.md: the repository tree omitted azazel_processor, kushya_generator, mesorah, src/tools and scripts → listed, each in a line. - deploy/ARCHITECTURE.md: the judgment path holds no model, said in writing — the examination is Python patterns and Prolog rules, the judges consult that Prolog; kushya_generator (a fine-tuned model in this repo, not deployed, not wired) is an OFFERER whose output is examined, never a component the bedikah, the engine or a judge consults. The kohen is not the offerer. azazel_processor listed. - The map: the repository is public; eleven files named the ingress NLB's literal address and five the kohen's kubeconfig path. Docs now use the domains (git.bikoret.ch, bikoret.ch) or "" with the kubectl query that answers it; the kubeconfig is "$KUBECONFIG" / "$HOME/.kube/.yaml". gitea-public-apply.sh takes NLB from the environment. None of it was a secret; all of it was a map. - OTP pin: checked, not changed — the segfault in the build log was a source-built OTP 26.2.1 on macOS; the image is hexpm's 26.2.1 with ERL_FLAGS +JMsingle. Co-Authored-By: Claude Fable 5.1 --- AGENTS.md | 12 ++++++------ KOHEN.md | 14 +++++++------- KOHEN_PROMPT.md | 2 +- README.md | 5 +++++ deploy/ARCHITECTURE.md | 6 +++++- deploy/k8s/gitea-ingress.yaml | 2 +- deploy/k8s/gitea-mcp-ingress.yaml | 2 +- deploy/k8s/gitea-mcp-secret.yaml | 4 ++-- deploy/k8s/gitea-public-apply.sh | 4 ++-- deploy/k8s/gitea-public-patch.yaml | 2 +- deploy/k8s/gitea-public-verify.sh | 2 +- deploy/k8s/ingress-tcp-services.yaml | 6 +++--- deploy/k8s/secrets.yaml | 2 +- deploy/k8s/service.yaml | 2 +- deploy/k8s/shorashim-ch-takedown.sh | 2 +- 15 files changed, 38 insertions(+), 29 deletions(-) diff --git a/AGENTS.md b/AGENTS.md index 09c99183..f89676d3 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -53,10 +53,10 @@ before writing code. Do not summarize from memory. Read fresh. | 11. Manna provision infrastructure | Done | Provision file validation, expiry, anti-hoarding, double portion | | 12. Sanhedrin framework (Erlang) | Done | `sanhedrin/` — 8 modules, 41 tests, all passing | | 13. Korban Processor (Python) | Done | `korban_processor/` — 7 modules, 181 tests, all passing | -| 14. Connect components | Pending | Elixir → Haskell port, Elixir → Prolog socket | -| 15. Integration verification | Pending | | +| 14. Connect components | Done | Elixir → Haskell Port (`ShoreshEngineClient`), Elixir → Prolog socket (`TalmudicEngineSocket`), Elixir → Korban socket (`KorbanProcessorSocket`); line-framed replies (tablet 50) | +| 15. Integration verification | Done | Live round trips proven on the cluster: pe'ah cycle, bedikah, the gate with a real model (2026-10-13), the Sanhedrin's full dialectic (2026-10-20) | -**Next build task:** Step 14 — Connect components. Read Architecture §4 Step 14. +**Next build task:** none from the phase tables — all six steps of `specs/bishearecha.md` are built. Build from the open items in the builder's memory and the Broken Tablets; a spec row is a claim to test. ## Broken Tablets (Build Log) @@ -104,10 +104,10 @@ approve decisions, or supervise work. The specification does all of this. | Service | Location | Access | |---------|----------|--------| -| Gitea | `http://185.19.28.170:3000` (SSH :22) — behind the shared ingress NLB | User: heaviness510 | -| Bikoret | `https://bikoret.ch` (also `http://185.19.28.170`, the catch-all; `shorashim.ch` retired 2026-10-20) | keys: KOHEN.md "Issuing a key" | +| Gitea | `https://git.bikoret.ch` (git over HTTPS; SSH on the ingress NLB :22) | User: heaviness510 | +| Bikoret | `https://bikoret.ch` (the ingress catch-all also answers on the NLB's bare IP; `shorashim.ch` retired 2026-10-20) | keys: KOHEN.md "Issuing a key" | | PostgreSQL | Exoscale DBaaS ch-gva-2 | `temple-council-db` | -| Kubernetes | Exoscale SKS ch-gva-2 | `~/.kube/exoscale-temple-council.yaml` | +| Kubernetes | Exoscale SKS ch-gva-2 | the kohen's `$KUBECONFIG`, outside the repo | ## Principles diff --git a/KOHEN.md b/KOHEN.md index 0f27853d..4451b5fa 100644 --- a/KOHEN.md +++ b/KOHEN.md @@ -53,7 +53,7 @@ You inherit infrastructure that has been provisioned and verified: | Container registry `the-recognition-protocol` | All 4 bikoret images pushed and tagged `:latest`. | | Block Storage CSI driver | Installed. StorageClass `exoscale-sbs` available. | | cert-manager + nginx-ingress | Running. ClusterIssuer `letsencrypt-prod` working. | -| Gitea (persistent storage) | Running. Public HTTPS at `https://git.bikoret.ch` (ROOT_URL) since 2026-10-19; git also over `http://185.19.28.170:3000` and SSH :22. The web UI needs the https door (Secure cookie). | +| Gitea (persistent storage) | Running. Public HTTPS at `https://git.bikoret.ch` (ROOT_URL) since 2026-10-19; git also over `http://:3000` and SSH :22. The web UI needs the https door (Secure cookie). | | Gitea MCP server | `https://mcp.bikoret.ch/mcp`, MCP OAuth mode: each user authorizes with their own Gitea account (Gitea OAuth2 app "Claude", PKCE, client ID in the claude.ai connector's Advanced settings). Apply: `bash ~/.local/bin/gitea-public-apply`; check: `gitea-public-verify`. The old `mcp.shorashim.ch` and the shared static token are retired. | | L1 Torah filesystem | In the `bikoret` repo at `l1/torah/`. SHA-256 `9e1abe4e…3c3086` (full hash in `l1/integrity.sha256`; verified at Day 1). | | Image pull secret `shorashim-registry` | **Verify before assuming.** A prior partial setup may have created it. `kubectl get secrets -n shorashim` is the source of truth. | @@ -73,8 +73,8 @@ You inherit infrastructure that has been provisioned and verified: | Item | Where | |------|-------| -| Repo | `git clone http://185.19.28.170:3000/heaviness510/shorashim.git` | -| Kubeconfig | `~/.kube/exoscale-temple-council.yaml` | +| Repo | `git clone https://git.bikoret.ch/heaviness510/bikoret.git` | +| Kubeconfig | `$KUBECONFIG` — the kohen's own file, outside the repo | | `kubectl` | already installed | | `exo` CLI | already installed | | Docker daemon | only for image rebuilds (not needed for inauguration) | @@ -84,7 +84,7 @@ If the kubeconfig has expired: ```bash exo compute sks kubeconfig temple-council kube-admin --zone ch-gva-2 -g system:masters \ - > ~/.kube/exoscale-temple-council.yaml + > "$KUBECONFIG" ``` --- @@ -146,7 +146,7 @@ ecto://avnadmin:@temple-council-db-exoscale-66fffc16-59ac-4a62-9c19-f3 #### 2b. Apply the secrets ```bash -export KUBECONFIG=~/.kube/exoscale-temple-council.yaml +export KUBECONFIG="$HOME/.kube/.yaml" # DATABASE_URL secret kubectl create secret generic shorashim-secrets \ @@ -463,7 +463,7 @@ kubectl logs -n shorashim deploy/bikoret -c vav-pipeline -f If the seven days passed without halt events, without Shabbat violations, without manna exhaustion, without any pod restarts: -1. **Point DNS** — at the registrar, A records to the ingress IP (`kubectl get svc -n ingress-nginx ingress-nginx-controller`; `185.19.28.170`): `bikoret.ch`, `www.bikoret.ch`, and for the redirect `bikoret.org`, `www.bikoret.org`. Wait until `dig +short A bikoret.ch` answers the IP — only then `kubectl apply -f deploy/k8s/service.yaml`: it carries the TLS blocks (cert-manager, `letsencrypt-prod`, HTTP-01), and a certificate asked for before the name resolves burns Let's Encrypt's failed-validation limit. Then `kubectl -n shorashim get certificate` until both are Ready, and callers use `https://bikoret.ch`; `shorashim.ch` still answers over plain HTTP until its callers have moved +1. **Point DNS** — at the registrar, A records to the ingress IP (`kubectl get svc -n ingress-nginx ingress-nginx-controller`): `bikoret.ch`, `www.bikoret.ch`, and for the redirect `bikoret.org`, `www.bikoret.org`. Wait until `dig +short A bikoret.ch` answers the IP — only then `kubectl apply -f deploy/k8s/service.yaml`: it carries the TLS blocks (cert-manager, `letsencrypt-prod`, HTTP-01), and a certificate asked for before the name resolves burns Let's Encrypt's failed-validation limit. Then `kubectl -n shorashim get certificate` until both are Ready, and callers use `https://bikoret.ch`; `shorashim.ch` still answers over plain HTTP until its callers have moved 2. **Open the pe'ah endpoint to the world** — the stranger approaches first 3. **Observe the first real interaction** — a question from outside 4. If *ki tov*: open courtyard and chatzer endpoints. The system is consecrated. @@ -813,7 +813,7 @@ Three things are kept outside the mishkan repository, each for a Torah-grounded | Repo / directory | Where | Why | |---|---|---| -| `bikoret-readings` | `http://185.19.28.170:3000/heaviness510/shorashim-readings` | The book — Torah parshiyot read as AI specification. Companion to the mishkan. Lives beside the aron, not inside (Devarim 31:26). | +| `bikoret-readings` | `https://git.bikoret.ch/heaviness510/shorashim-readings` | The book — Torah parshiyot read as AI specification. Companion to the mishkan. Lives beside the aron, not inside (Devarim 31:26). | | `~/shorashim-source-data/morphhb` | local only | The quarry — raw WLC source. The carved tablets go in the aron; the quarry does not. | | `~/shorashim-operator-notes` | local only / private | The kohen's runbook — environment-specific details, hostnames, account names. Private operator notes. Not part of the system's specification. | diff --git a/KOHEN_PROMPT.md b/KOHEN_PROMPT.md index cb00a46f..0a0b3800 100644 --- a/KOHEN_PROMPT.md +++ b/KOHEN_PROMPT.md @@ -65,7 +65,7 @@ The runbook lists what should already exist. Verify it. Do **not** trust the tab ```bash # 0a. Cluster reachable -export KUBECONFIG=~/.kube/exoscale-temple-council.yaml +export KUBECONFIG="$HOME/.kube/.yaml" kubectl version kubectl get nodes diff --git a/README.md b/README.md index 8bf180a9..e07f2459 100644 --- a/README.md +++ b/README.md @@ -184,6 +184,11 @@ bikoret/ ├── vav_pipeline/ # Elixir — Bereishit cycle, Shema, Cloud, Manna, HTTP API ├── talmudic_engine/ # SWI-Prolog — 613 mitzvot, 13 middot, kushya ├── korban_processor/ # Python — offering protocol, eish zarah validation +├── azazel_processor/ # Python — the goat for Azazel: disposal records, vidui, L3 ingest +├── kushya_generator/ # Fine-tuned model (NOT deployed) — an offerer, never a judge; see deploy/ARCHITECTURE.md +├── mesorah/ # The second scroll — 128 works from the Sefaria export, pinned (Devarim 17:18) +├── src/tools/ # Specimen corpus, hakhel, evaluation (the kohen's measuring tools) +├── scripts/ # Build and operate: L1/mesorah/engine-verse builders, Doorpost check, rollout, watchdog │ ├── deploy/ # Infrastructure │ ├── ARCHITECTURE.md # Generic deployment shape (no account specifics) diff --git a/deploy/ARCHITECTURE.md b/deploy/ARCHITECTURE.md index 0acf9038..587ec32d 100644 --- a/deploy/ARCHITECTURE.md +++ b/deploy/ARCHITECTURE.md @@ -11,10 +11,14 @@ One Kubernetes namespace runs the following: | `vav-pipeline` | Elixir/OTP release | Bereishit cycle, ShemaContext, Cloud, Manna, HTTP API (pe'ah, courtyard, chatzer, kodesh) | | `shoresh-engine` | Haskell binary, spawned by vav-pipeline as an Erlang Port (staged into the pod by the `shoresh-engine-install` init container — NOT a sidecar container; a Port is a child process of the BEAM and cannot cross a container boundary) | Root activation, te'amim parsing, gematria | | `talmudic-engine` | SWI-Prolog (sidecar via Unix socket) | 613 mitzvot, 13 middot, kushya generation, teiku | -| `korban-processor` | Python 3.12 (sidecar) | Offering protocol, eish zarah validation | +| `korban-processor` | Python 3.12 (sidecar) | Offering protocol, eish zarah validation, the bedikah's readings (pattern-based: `korban_processor/bedikah.py`) | +| `kushya_generator/` | Fine-tuned model — **not deployed, not wired** | An OFFERER, if it is ever run: its output arrives at the gate like any model's and is examined. It is never a component the bedikah, the Talmudic Engine or the Sanhedrin consults. | +| `azazel_processor/` | Python — run by the kohen, not in the pod | Disposal records (the goat for Azazel); `VavPipeline.AzazelIngest` reads its files into L3 | All four run in the same pod. vav-pipeline is the main container; talmudic-engine and korban-processor are sidecars; shoresh-engine runs inside vav-pipeline as an Erlang Port child process, staged in by an init container. +**No model stands on the judgment path.** The examination of an output — the offering protocol, the seven readings, the halt rules — is Python pattern extraction and Prolog rules, and the Sanhedrin's judges consult that same Prolog. Nothing that examines is a model, and nothing a model produces is consulted as a rule. The kohen is not the offerer. A fine-tuned model in this repository (`kushya_generator/`) is an offerer or a tool whose output is itself examined; wiring it into the bedikah, the engine or a judge would put the offerer on the altar, and is refused by this document before anyone does it for convenience. + ## External dependencies | Dependency | Purpose | Contract | diff --git a/deploy/k8s/gitea-ingress.yaml b/deploy/k8s/gitea-ingress.yaml index 48a3c802..2e659f92 100644 --- a/deploy/k8s/gitea-ingress.yaml +++ b/deploy/k8s/gitea-ingress.yaml @@ -10,7 +10,7 @@ # (ingress-tcp-services.yaml) stay as they are; this adds a third door. # # Prerequisites: -# 1. DNS: git.bikoret.ch → 185.19.28.170 (Infomaniak zone) +# 1. DNS: git.bikoret.ch → (Infomaniak zone) # 2. ClusterIssuer letsencrypt-prod --- apiVersion: networking.k8s.io/v1 diff --git a/deploy/k8s/gitea-mcp-ingress.yaml b/deploy/k8s/gitea-mcp-ingress.yaml index 283a043e..51077fcc 100644 --- a/deploy/k8s/gitea-mcp-ingress.yaml +++ b/deploy/k8s/gitea-mcp-ingress.yaml @@ -8,7 +8,7 @@ # 1. nginx-ingress controller installed # 2. cert-manager installed # 3. ClusterIssuer letsencrypt-prod applied -# 4. DNS: mcp.bikoret.ch → 185.19.28.170 (the one NLB; Infomaniak zone) +# 4. DNS: mcp.bikoret.ch → (the one NLB; Infomaniak zone) --- apiVersion: networking.k8s.io/v1 kind: Ingress diff --git a/deploy/k8s/gitea-mcp-secret.yaml b/deploy/k8s/gitea-mcp-secret.yaml index a47a2c12..5fb8ebba 100644 --- a/deploy/k8s/gitea-mcp-secret.yaml +++ b/deploy/k8s/gitea-mcp-secret.yaml @@ -7,11 +7,11 @@ # # Two secrets needed (static-token mode): # 1. GITEA_TOKEN: Personal Access Token from Gitea -# Create at: http://185.19.28.170:3000/user/settings/applications +# Create at: https://git.bikoret.ch/user/settings/applications # Permissions: repo (read/write) # # 2. OAuth Client ID/Secret: Registered OAuth app in Gitea -# Create at: http://185.19.28.170:3000/user/settings/applications +# Create at: https://git.bikoret.ch/user/settings/applications # Redirect URIs: https://claude.ai/api/mcp/auth_callback # http://127.0.0.1/callback (Claude Code) # Confidential Client: UNCHECKED (PKCE). Only the Client ID is needed; diff --git a/deploy/k8s/gitea-public-apply.sh b/deploy/k8s/gitea-public-apply.sh index 394b6b20..cab5e104 100755 --- a/deploy/k8s/gitea-public-apply.sh +++ b/deploy/k8s/gitea-public-apply.sh @@ -2,7 +2,7 @@ # Move Gitea and its MCP server to public HTTPS on bikoret.ch and switch # the MCP server to MCP OAuth (2026-10-19). Run by the transmitter: # ! bash ~/.local/bin/gitea-public-apply -# Idempotent. Needs DNS first: git.bikoret.ch and mcp.bikoret.ch → 185.19.28.170. +# Idempotent. Needs DNS first: git.bikoret.ch and mcp.bikoret.ch → . # # Rollback (static-token mode on mcp.shorashim.ch, as before 2026-10-19): # kubectl -n temple-council set env deploy/gitea \ @@ -12,7 +12,7 @@ set -euo pipefail REPO="${REPO:-$HOME/bikoret}" cd "$REPO" -NLB=185.19.28.170 +NLB="${NLB:?set NLB to the ingress address: kubectl get svc -n ingress-nginx ingress-nginx-controller}" for h in git.bikoret.ch mcp.bikoret.ch; do ip=$(dig +short "$h" | tail -1 || true) if [ "$ip" != "$NLB" ]; then diff --git a/deploy/k8s/gitea-public-patch.yaml b/deploy/k8s/gitea-public-patch.yaml index da1bc328..0e5521f4 100644 --- a/deploy/k8s/gitea-public-patch.yaml +++ b/deploy/k8s/gitea-public-patch.yaml @@ -10,7 +10,7 @@ # name that never resolved) and SSH_DOMAIN (was 185.19.29.94, an NLB IP # released on 2026-10-06). Clone URLs shown by Gitea become # https://git.bikoret.ch/... and git@git.bikoret.ch:...; the old -# http://185.19.28.170:3000 remote keeps working for push/pull. +# http://:3000 remote keeps working for push/pull. # Side effect: with an https ROOT_URL Gitea marks its session cookie # Secure, so the WEB UI must be used at https://git.bikoret.ch, not on # the plain-HTTP :3000 door (git over :3000 is unaffected). diff --git a/deploy/k8s/gitea-public-verify.sh b/deploy/k8s/gitea-public-verify.sh index 6584d8c5..f118b247 100755 --- a/deploy/k8s/gitea-public-verify.sh +++ b/deploy/k8s/gitea-public-verify.sh @@ -13,6 +13,6 @@ chk "mcp /healthz" 200 "$(curl -sS -m 15 -o /dev/null -w '%{http_code}' https:// prm=$(curl -sS -m 15 https://mcp.bikoret.ch/.well-known/oauth-protected-resource || echo err) chk "protected-resource names Gitea" yes "$(printf '%s' "$prm" | grep -q 'git.bikoret.ch' && echo yes || echo no)" chk "POST /mcp without token → 401" 401 "$(curl -sS -m 15 -o /dev/null -w '%{http_code}' -X POST https://mcp.bikoret.ch/mcp -H 'Content-Type: application/json' -H 'Accept: application/json, text/event-stream' -d "$INIT" || echo err)" -chk "git over :3000 still answers" 200 "$(curl -sS -m 15 -o /dev/null -w '%{http_code}' http://185.19.28.170:3000/api/v1/version || echo err)" +chk "git over :3000 still answers" 200 "$(curl -sS -m 15 -o /dev/null -w '%{http_code}' http://:3000/api/v1/version || echo err)" echo "protected-resource: $prm" exit $fail diff --git a/deploy/k8s/ingress-tcp-services.yaml b/deploy/k8s/ingress-tcp-services.yaml index a50172d2..53bfbce3 100644 --- a/deploy/k8s/ingress-tcp-services.yaml +++ b/deploy/k8s/ingress-tcp-services.yaml @@ -1,14 +1,14 @@ # Gitea behind the shared ingress — TCP passthrough # -# One NLB for the cluster (185.19.28.170, the ingress-nginx Service) +# One NLB for the cluster (, the ingress-nginx Service) # instead of one per Service. Bikoret is an HTTP Ingress # (service.yaml). Gitea has no hostname that resolves # (gitea.temple-council.ch is configured in Gitea and exists nowhere), # and host-based routing needs a name — so Gitea rides the ingress # controller's TCP passthrough on two ports of the same NLB: # -# 185.19.28.170:3000 → temple-council/gitea:80 (HTTP — git, web UI) -# 185.19.28.170:22 → temple-council/gitea:22 (SSH) +# :3000 → temple-council/gitea:80 (HTTP — git, web UI) +# :22 → temple-council/gitea:22 (SSH) # # Three live objects carry this; only the first is a whole manifest: # diff --git a/deploy/k8s/secrets.yaml b/deploy/k8s/secrets.yaml index e890561f..9f30c0c0 100644 --- a/deploy/k8s/secrets.yaml +++ b/deploy/k8s/secrets.yaml @@ -42,7 +42,7 @@ stringData: # THIS FILE IS A TEMPLATE. Never commit a real value. Create the secret # from the live database credential instead: # -# export KUBECONFIG=~/.kube/exoscale-temple-council.yaml +# export KUBECONFIG="$HOME/.kube/.yaml" # umask 077 # TMP=$(mktemp) # diff --git a/deploy/k8s/service.yaml b/deploy/k8s/service.yaml index b3726dc1..2959e5fa 100644 --- a/deploy/k8s/service.yaml +++ b/deploy/k8s/service.yaml @@ -42,7 +42,7 @@ spec: # below) only redirects. The old shorashim.ch rule was taken down on # 2026-10-20 (the domain is retired). TLS from Let's Encrypt through cert-manager's # letsencrypt-prod ClusterIssuer, HTTP-01 — so apply this ONLY after -# `dig +short A bikoret.ch` answers 185.19.28.170: a certificate asked +# `dig +short A bikoret.ch` answers : a certificate asked # for before the name resolves only burns the failed-validation limit. # The no-host catch-all stays, so http:///... keeps working # with no DNS; with ssl-redirect on, named hosts go to https. diff --git a/deploy/k8s/shorashim-ch-takedown.sh b/deploy/k8s/shorashim-ch-takedown.sh index b9cbbc1a..aa4a5fbc 100755 --- a/deploy/k8s/shorashim-ch-takedown.sh +++ b/deploy/k8s/shorashim-ch-takedown.sh @@ -4,7 +4,7 @@ # ! bash ~/.local/bin/shorashim-ch-takedown # Idempotent. # 1. Ingress `shorashim`: the shorashim.ch host rule is gone (service.yaml). -# The no-host catch-all stays, so http://185.19.28.170/ still answers — +# The no-host catch-all stays, so http:/// still answers — # the name itself dies when its A record is removed at Infomaniak. # 2. The orphan TLS secret for mcp.shorashim.ch is deleted. # 3. Gitea APP_NAME "Shorashim" → "Bikoret" (gitea-public-patch.yaml; one restart).