feat(formal/tla): TLA+ model of Invoker — isolation + classification coverage#253
Merged
Conversation
…coverage Adds Invoker.tla: formal model of BojRest.Invoker (Phase 2 fork-per-request dispatcher). Invoker is stateless and synchronous — System.cmd blocks until boj-invoke exits, with no shared state between concurrent calls. Properties verified: - DoneOnce: each invocation resolves at most once (subprocess exits once; no race on resolution) - Consistent: running ↔ no result yet; done ↔ exactly one result - EventuallyDone [ASSUMED]: running ~> done under well-behaved CLI (noted gap: Phase 2 has no per-invocation timeout; ADR-0005 specifies 5 s for the future pool, not yet implemented) Non-vacuity: all 7 result kinds refuted by TLC (ReachOk through ReachInitFailed), proving every exit-code branch is reachable. Documents the known gap (no timeout in Phase 2 Invoker) and the future work (model the ADR-0005 GenServer pool checkout/backpressure when it lands). Formal coverage is now complete for all three Phase 2 Elixir components: - JsWorker.tla — single GenServer slot (ReplyOnce, EventuallyReplied) - JsWorkerPool.tla — N-slot pool (RouteConsistency, CrashIsolation) - Invoker.tla — stateless Zig-FFI dispatcher (DoneOnce, classification) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01F8pqMfJViUaKabWKNQ9wUg
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/Invoker.tla— TLA+ model ofBojRest.Invoker(Phase 2 fork-per-request Zig FFI dispatcher)specs/elixir-harness/Invoker.cfg— TLC config: 3 requests, 8 possible result kindsspecs/elixir-harness/README.adoc— adds Invoker section, moves it out of "Not yet modelled"; updates sanity-control shell loopWhat the model covers
Invokeris stateless and synchronous:System.cmd/3blocks untilboj-invokeexits; there is no pool, no GenServer, no shared mailbox. The interesting formal question is not a state machine but an isolation guarantee: N concurrent callers cannot interfere with each other's result.State variables:
status[r](new/running/done),result[r](one of 8 terminal kinds),doneCount[r](double-resolution detector).Actions:
Invoke(r)— CLI found, subprocess spawned (new → running)CliMissing(r)—cli_path()returns nil, short-circuits immediately (new → done)RespondOk / RespondCliCrashed / RespondArgs / RespondOpen / RespondMissingSym / RespondInitFailed— subprocess exits (running → done)Properties verified:
DoneOnce— each invocation resolves at most once; no race can deliver two results for the same call (sinceSystem.cmdis blocking, the subprocess exits exactly once)Consistent— running ↔ no result yet; done ↔ exactly one resultEventuallyDone[ASSUMED] — running ~> done, under the assumption that the subprocess exits on its ownKnown gap documented: Phase 2 has no per-invocation timeout.
System.cmdblocks indefinitely ifboj-invokehangs. ADR-0005 specifies 5 s for the future pool (not yet implemented).EventuallyDonerests on an [ASSUMED] liveness condition.Non-vacuity: all 7 result kinds refuted by TLC with witness traces.
Formal coverage after this PR
JsWorker(single slot)JsWorker.tlaReplyOnce,EventuallyRepliedJsWorkerPool(N slots)JsWorkerPool.tlaRouteConsistency, crash isolationInvoker(Zig-FFI, Phase 2)Invoker.tlaDoneOnce, classification coverageabi_axioms.zig+abi_verify.zigSafetyLemmas.idrcharEqSymdischargedTest plan
java -cp tla2tools.jar tlc2.TLC Invoker.tla— no invariant violation,EventuallyDoneholdsReachOk…ReachInitFailed) each refuted by TLC with a short witness traceJsWorker.tlaandJsWorkerPool.tlastill pass (no regression)🤖 Generated with Claude Code
https://claude.ai/code/session_01F8pqMfJViUaKabWKNQ9wUg
Generated by Claude Code