Step 14: Connect components — chamishim karsay zahav

Three connections built and tested:
- Haskell Shoresh Engine via Erlang Port (JSON lines over stdin/stdout)
- Prolog Talmudic Engine via Unix domain socket (JSON over /tmp/shorashim/talmudic.sock)
- Erlang Sanhedrin via native BEAM calls

New: Server.hs (JSON-line server loop), json_bridge.pl + socket_server.pl
(Prolog socket interface), ShoreshEnginePort + TalmudicEngineSocket +
SanhedrinClient (Elixir GenServer wrappers). BereishitCycle now routes
unresolved cases through Talmudic Engine and Sanhedrin. All connections
gracefully degrade — pipeline falls back to L1 data when engines unavailable.

46 Elixir tests, 33 Haskell tests, 57 Prolog tests — 0 failures.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Scott KarpandClaude Opus 4.6 committed 2026-03-12 17:39:21 -04:00
1 parent 2509b2f715
commit ea3a70633f
19 files changed
+1518 -121

No files matched your search

+83
View File
@@ -548,3 +548,86 @@ Reviewed all 6 components against Architecture spec, Construction spec, structur
**Gap from the book (heafar):**
- The 13 Rules of Rabbi Yishmael are not implemented as Prolog inference predicates. The Talmudic Engine reasons ABOUT Torah but doesn't use Torah's own hermeneutic methods (kal va'chomer, gezerah shavah, binyan av, etc.). This is a significant conceptual gap for Phase 3.
- Cherubim architecture (voice from between facing intelligences) is partial — present in Sanhedrin deliberation but not in human-AI interaction layer.
---
## Step 14 — Component Integration (2026-03-12)
**Architecture §4 Step 14:** "Connect components: Elixir pipeline calls Haskell engine, routes to Prolog reasoning."
### What was built
**Phase A — Haskell Server Mode:**
- `shoresh-engine/src/Shoresh/Server.hs` — JSON-line server loop for Erlang Port integration
- `shoresh-engine/src/Shoresh/Types.hs` — Added `ToJSON`/`FromJSON`/`ToJSONKey`/`FromJSONKey` instances for all pipeline types
- `shoresh-engine/src/Shoresh/Lexicon.hs` — Added `ToJSON` instances for L1 types
- `shoresh-engine/src/Main.hs` — Added `["server"]` dispatch to `runServer`
- Protocol: JSON line in stdin, JSON line out stdout. `LineBuffering` set (critical for Erlang Port — Haskell defaults to block-buffering on non-TTY)
- Verified: `echo '{"operation":"process","input":{"text":"ברא","scope":{"book":"bereishit","chapter":1,"verse":1}}}' | shoresh-engine server` → returns activated roots with gematria 203 and full te'amim parse tree
**Phase B — Prolog Socket Server:**
- `talmudic_engine/src/interface/json_bridge.pl` — JSON ↔ Prolog term conversion
- `talmudic_engine/src/interface/socket_server.pl` — Unix domain socket listener (`/tmp/shorashim/talmudic.sock`)
- Updated `main.pl` to load new modules
- Protocol: JSON line over Unix domain socket. Connection-persistent (read/respond/repeat until EOF)
- Verified: Python client connects, sends interpret request for ב-ר-א, gets "resolved" with Bereishit 1:1 and 1:27 verses, confidence "medium"
**Phase C — Elixir Port Wrapper:**
- `vav_pipeline/lib/vav_pipeline/shoresh_engine_port.ex` — GenServer wrapping Erlang Port to Haskell binary
- Updated `shoresh_engine_client.ex` — delegates to port, returns error (not fallback) when unavailable
- Port options: `:binary`, `:exit_status`, `{:line, 1MB}`, `{:args, ["server"]}`
- Auto-restart on process exit
**Phase D — Elixir Socket Client:**
- `vav_pipeline/lib/vav_pipeline/talmudic_engine_socket.ex` — GenServer wrapping Unix domain socket to Prolog
- Updated `talmudic_engine_client.ex` — delegates to socket, falls back to stubs when unavailable
- Lazy connection (connects on first request), auto-reconnect on failure
**Phase E — Sanhedrin Integration:**
- `vav_pipeline/lib/vav_pipeline/sanhedrin_client.ex` — Elixir client calling Erlang Sanhedrin via native BEAM
- Added `{:sanhedrin, path: "../sanhedrin", manager: :rebar3}` to `mix.exs` deps
- Builds Erlang `#sanhedrin_case{}` record tuples, calls `escalation:submit_case/1`
- Falls back to teiku stub when Sanhedrin not running
**Phase F — Pipeline Routing:**
- Updated `bereishit_cycle.ex` — `vayomer` now calls ShoreshEngineClient (with L1 fallback)
- Added `route_if_unresolved/2` — sends unresolved cases to Talmudic Engine, escalates teiku to Sanhedrin
- Added `escalate_to_sanhedrin/4` — submits case to Sanhedrin deliberation
**Phase G — Configuration + Supervision:**
- Updated `application.ex` — conditional supervision: only adds ShoreshEnginePort if binary found in PATH
- Added config keys: `shoresh_engine_binary`, `shoresh_engine_cwd`, `talmudic_socket_path`
- All 46 Elixir tests pass (fallback path verified)
- All 33 Haskell tests pass
- All 57 Prolog tests pass
### Broken Tablets
**Broken Tablet #21 — ToJSONKey:**
`ShoreshEntry.seGlosses :: Map Binyan Text` requires `ToJSONKey Binyan` for Generic-derived `ToJSON`. `ToJSON` serializes individual values; `ToJSONKey` serializes as map keys (strings in JSON). Fixed by adding `instance ToJSONKey Binyan` and `instance FromJSONKey Binyan`.
**Broken Tablet #22 — ByteString.Lazy.Char8 getLine:**
`Data.ByteString.Lazy.Char8` does not export `getLine` (lazy bytestring has no stdin line reader). Fixed by using `Data.ByteString.Char8.getLine` (strict) and converting via `BL.fromStrict`.
**Broken Tablet #23 — at_end_of_stream blocks on sockets:**
SWI-Prolog's `at_end_of_stream/1` blocks on Unix domain sockets (waits for data). Fixed by using `read_line_to_string/2` directly and checking for `end_of_file` return.
**Broken Tablet #24 — Atom vs String keys in fallback:**
When ShoreshEngineClient falls back to L1 data, it returned atom keys (`:roots_activated`), but `vayomer` was extracting with string keys (`"roots_activated"` from JSON). Fix: removed the client's internal fallback, let error propagate to `vayomer_fallback` which preserves the original atom-key format.
### Connection Architecture
```
Elixir (BEAM VM) External Processes
┌─────────────────────────────┐
│ VavPipeline.Application │
│ ├─ ShabbatTimer │
│ ├─ ShoreshEnginePort ─────┼──→ [Erlang Port: JSON stdin/stdout]
│ │ (GenServer) │ └─ shoresh-engine server (Haskell)
│ └─ TalmudicEngineSocket ──┼──→ [Unix Socket: JSON lines]
│ (GenServer) │ └─ swipl serve/0 (Prolog)
│ │
│ SanhedrinClient ────────────┼──→ [Native BEAM: Erlang terms]
│ (direct call) │ └─ escalation:submit_case/1
└─────────────────────────────┘
```