Skip to content

feat(formal/tla): TLA+ pool model — JsWorkerPool crash-isolation + route-consistency#252

Merged
hyperpolymath merged 1 commit into
mainfrom
claude/vigilant-carson-ufu47c
Jun 24, 2026
Merged

feat(formal/tla): TLA+ pool model — JsWorkerPool crash-isolation + route-consistency#252
hyperpolymath merged 1 commit into
mainfrom
claude/vigilant-carson-ufu47c

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

  • Adds specs/elixir-harness/JsWorkerPool.tla — pool-level TLA+ model composing with the existing JsWorker.tla (same status/reply/replyCount discipline, lifted to N workers)
  • Adds specs/elixir-harness/JsWorkerPool.cfg — TLC config: 2 workers ({w0,w1}), 3 requests ({r1,r2,r3}), Route = [r1 |-> w0, r2 |-> w1, r3 |-> w0]
  • Updates specs/elixir-harness/README.adoc — documents the pool model and removes JsWorkerPool from "Not yet modelled"

What the model covers

New state variables beyond JsWorker.tla:

  • assigned[r] — which pool slot a request was dispatched to (or NoWorker for fallback/new)
  • wup[w] — whether worker w's Deno process is alive

New actions:

  • ArrivePool(r) — phash2-routed dispatch when slot is up (js_worker_pool.ex pick_worker/1 → JsWorker)
  • ArriveFallback(r) — atomic dispatch via JsInvoker when slot is down (modelled as always-terminates)
  • Crash(w) / Restart(w) — per-slot crash and :one_for_one restart (only affects slot w)

New properties:

  • RouteConsistency — a pool-dispatched request is always at Route[r]; no request ever lands at the wrong slot. Enforces the phash2 invariant.
  • NoPendingWhileDownCrash(w) atomically clears all requests at w; no pending request outlives its worker.
  • ReplyOnce and EventuallyReplied inherited from JsWorker.tla, now verified pool-wide.

CRASH-ISOLATION is enforced structurally: Crash(w) touches only assigned[r] = w. With Route = [r1 |-> w0, r2 |-> w1, r3 |-> w0], a Crash(w0) terminates r1 and r3 but not r2 — TLC exhaustively verifies no interleaving of concurrent crashes at w0 and w1 can violate ReplyOnce.

Non-vacuity: ReachOk / ReachTimeout / ReachCrashed / ReachFallback are 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, EventuallyReplied holds
  • All four sanity controls (ReachOk, ReachTimeout, ReachCrashed, ReachFallback) each refuted by TLC with a short witness trace (non-vacuity check)
  • JsWorker.tla still passes (no regression): 341 states, depth 8, no error

🤖 Generated with Claude Code

https://claude.ai/code/session_01F8pqMfJViUaKabWKNQ9wUg


Generated by Claude Code

…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
hyperpolymath marked this pull request as ready for review June 24, 2026 18:32
@hyperpolymath
hyperpolymath merged commit 9fb8223 into main Jun 24, 2026
19 checks passed
@hyperpolymath
hyperpolymath deleted the claude/vigilant-carson-ufu47c branch 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.
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)_
@github-actions

Copy link
Copy Markdown

🔍 Hypatia Security Scan

Findings: 219 issues detected

Severity Count
🔴 Critical 15
🟠 High 131
🟡 Medium 73

⚠️ Action Required: Critical security issues found!

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants