feat(formal/tla): TLA+ pool model — JsWorkerPool crash-isolation + route-consistency#252
Merged
Merged
Conversation
…ute-consistency Adds JsWorkerPool.tla: the pool-level formal model over N JsWorker slots. Composes with JsWorker.tla (same status/reply/replyCount discipline) and lifts it to N workers by adding `assigned` (which slot) and `wup` (per-worker Deno-process liveness). New properties beyond the single-worker model: - CRASH-ISOLATION: Crash(w) is guarded on `assigned[r] = w`, so a crash at one slot is structurally incapable of touching requests at other slots. Verified by TLC under every interleaving (ReplyOnce still holds pool-wide). - ROUTE-CONSISTENCY: a pool request is always at Route[r] — the phash2 target — never a different slot. Enforces the consistent-hash invariant. - ArriveFallback: when the hashed slot is down, JsInvoker (fork-per-call) delivers "fallback" atomically; WF on ArriveFallback ensures a stranded "new" request is not stuck forever. Sanity controls: ReachOk/Timeout/Crashed/Fallback are expected violations — all four terminal outcomes are reachable (non-vacuity check). Updates README to document the pool model and removes JsWorkerPool from "Not yet modelled". Invoker (fork-per-request) remains future work. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F8pqMfJViUaKabWKNQ9wUg
hyperpolymath
marked this pull request as ready for review
June 24, 2026 18:32
hyperpolymath
added a commit
that referenced
this pull request
Jun 24, 2026
- STATE.a2ml: last-updated 2026-06-13→2026-06-24; new tla-elixir-harness quality entry; new 2026-06-24 session-history entry covering PRs #252 (JsWorkerPool.tla) and #253 (Invoker.tla) - docs/wikis/Developer-Guide.adoc: add specs/elixir-harness/ to project structure with per-file descriptions Formal-proof axis only; CRG readiness grade unchanged.
3 tasks
hyperpolymath
added a commit
that referenced
this pull request
Jun 24, 2026
#254) ## Summary - **`.machine_readable/6a2/STATE.a2ml`** — Updated `last-updated` to 2026-06-24; added `tla-elixir-harness` quality field documenting the three TLA+ models; added 2026-06-24 session-history entry covering PRs #252 (JsWorkerPool.tla) and #253 (Invoker.tla). - **`docs/wikis/Developer-Guide.adoc`** — Added `specs/elixir-harness/` to the project structure section with per-file descriptions for `JsWorker.tla`, `JsWorkerPool.tla`, `Invoker.tla`, and `README.adoc`. ## Background PRs #252 and #253 added TLA+ formal models for the Elixir REST harness BEAM-side concurrency layer. These documentation files were not updated at the time of those merges. This PR closes that gap: - **Bot/AI audience** — `STATE.a2ml` now carries a `tla-elixir-harness` quality entry and session-history record so any future agent reading the machine-readable state knows the formal coverage exists, what properties were verified, and the current assumptions (EventuallyDone is `[ASSUMED]` pending Phase 3 pool — see ADR-0005). - **Human audience** — `Developer-Guide.adoc` project structure now lists `specs/elixir-harness/` alongside the other top-level directories. Formal-proof axis only; CRG readiness grade is unchanged at C. ## Test plan - [ ] Verify `specs/elixir-harness/` block appears in Developer-Guide project structure - [ ] Verify `STATE.a2ml` `last-updated`, `tla-elixir-harness` quality field, and 2026-06-24 session-history entry are all present - [ ] CI passes (no code changes; doc/metadata only) --- _Generated by [Claude Code](https://claude.ai/code/session_01F8pqMfJViUaKabWKNQ9wUg)_
🔍 Hypatia Security ScanFindings: 219 issues detected
View findings[
{
"reason": "Action actions/checkout@v4 needs attention",
"type": "unpinned_action",
"file": "pages-deploy.yml",
"action": "pin_sha",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in pages-deploy.yml",
"type": "missing_timeout_minutes",
"file": "pages-deploy.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in push-email-notify.yml",
"type": "missing_timeout_minutes",
"file": "push-email-notify.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in scorecard-enforcer.yml",
"type": "missing_timeout_minutes",
"file": "scorecard-enforcer.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in scorecard-enforcer.yml",
"type": "scorecard_publish_with_run_step",
"file": "scorecard-enforcer.yml",
"action": "split_scorecard_publish_job",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in instant-sync.yml",
"type": "secret_action_without_presence_gate",
"file": "instant-sync.yml",
"action": "peter-evans/repository-dispatch",
"rule_module": "workflow_audit",
"severity": "high"
},
{
"reason": "Issue in codeql.yml",
"type": "codeql_missing_actions_language",
"file": "codeql.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/academic-workflow-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/ephapax-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
},
{
"reason": "TypeScript file detected -- banned language",
"type": "banned_language_file",
"file": "/home/runner/work/boj-server/boj-server/cartridges/bofig-mcp/adapter/mod.ts",
"action": "flag",
"rule_module": "cicd_rules",
"severity": "critical"
}
]Powered by Hypatia Neurosymbolic CI/CD Intelligence |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
specs/elixir-harness/JsWorkerPool.tla— pool-level TLA+ model composing with the existingJsWorker.tla(samestatus/reply/replyCountdiscipline, lifted to N workers)specs/elixir-harness/JsWorkerPool.cfg— TLC config: 2 workers ({w0,w1}), 3 requests ({r1,r2,r3}),Route = [r1 |-> w0, r2 |-> w1, r3 |-> w0]specs/elixir-harness/README.adoc— documents the pool model and removesJsWorkerPoolfrom "Not yet modelled"What the model covers
New state variables beyond
JsWorker.tla:assigned[r]— which pool slot a request was dispatched to (orNoWorkerfor fallback/new)wup[w]— whether workerw's Deno process is aliveNew actions:
ArrivePool(r)— phash2-routed dispatch when slot is up (js_worker_pool.ex pick_worker/1 → JsWorker)ArriveFallback(r)— atomic dispatch viaJsInvokerwhen slot is down (modelled as always-terminates)Crash(w)/Restart(w)— per-slot crash and:one_for_onerestart (only affects slotw)New properties:
RouteConsistency— a pool-dispatched request is always atRoute[r]; no request ever lands at the wrong slot. Enforces thephash2invariant.NoPendingWhileDown—Crash(w)atomically clears all requests atw; no pending request outlives its worker.ReplyOnceandEventuallyRepliedinherited fromJsWorker.tla, now verified pool-wide.CRASH-ISOLATION is enforced structurally:
Crash(w)touches onlyassigned[r] = w. WithRoute = [r1 |-> w0, r2 |-> w1, r3 |-> w0], aCrash(w0)terminates r1 and r3 but not r2 — TLC exhaustively verifies no interleaving of concurrent crashes at w0 and w1 can violateReplyOnce.Non-vacuity:
ReachOk/ReachTimeout/ReachCrashed/ReachFallbackare sanity controls (not in.cfg) — all four are expected violations, proving every terminal outcome is reachable.Test plan
java -cp tla2tools.jar tlc2.TLC JsWorkerPool.tla— no invariant violation,EventuallyRepliedholdsReachOk,ReachTimeout,ReachCrashed,ReachFallback) each refuted by TLC with a short witness trace (non-vacuity check)JsWorker.tlastill passes (no regression): 341 states, depth 8, no error🤖 Generated with Claude Code
https://claude.ai/code/session_01F8pqMfJViUaKabWKNQ9wUg
Generated by Claude Code