Skip to content

feat(formal/tla): TLA+ model of Invoker — isolation + classification coverage#253

Merged
hyperpolymath merged 1 commit into
mainfrom
feat/invoker-tla
Jun 24, 2026
Merged

feat(formal/tla): TLA+ model of Invoker — isolation + classification coverage#253
hyperpolymath merged 1 commit into
mainfrom
feat/invoker-tla

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

Summary

  • Adds specs/elixir-harness/Invoker.tla — TLA+ model of BojRest.Invoker (Phase 2 fork-per-request Zig FFI dispatcher)
  • Adds specs/elixir-harness/Invoker.cfg — TLC config: 3 requests, 8 possible result kinds
  • Updates specs/elixir-harness/README.adoc — adds Invoker section, moves it out of "Not yet modelled"; updates sanity-control shell loop

What the model covers

Invoker is stateless and synchronous: System.cmd/3 blocks until boj-invoke exits; 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 (since System.cmd is blocking, the subprocess exits exactly once)
  • Consistent — running ↔ no result yet; done ↔ exactly one result
  • EventuallyDone [ASSUMED] — running ~> done, under the assumption that the subprocess exits on its own

Known gap documented: Phase 2 has no per-invocation timeout. System.cmd blocks indefinitely if boj-invoke hangs. ADR-0005 specifies 5 s for the future pool (not yet implemented). EventuallyDone rests on an [ASSUMED] liveness condition.

Non-vacuity: all 7 result kinds refuted by TLC with witness traces.

Formal coverage after this PR

Component Model Headline properties
JsWorker (single slot) JsWorker.tla ReplyOnce, EventuallyReplied
JsWorkerPool (N slots) JsWorkerPool.tla + RouteConsistency, crash isolation
Invoker (Zig-FFI, Phase 2) Invoker.tla DoneOnce, classification coverage
Zig FFI ABI abi_axioms.zig + abi_verify.zig comptime proofs + 40 boundary tests
Idris2 ABI SafetyLemmas.idr 4 class-J axioms + charEqSym discharged

Test plan

  • java -cp tla2tools.jar tlc2.TLC Invoker.tla — no invariant violation, EventuallyDone holds
  • All 7 sanity controls (ReachOkReachInitFailed) each refuted by TLC with a short witness trace
  • JsWorker.tla and JsWorkerPool.tla still pass (no regression)

🤖 Generated with Claude Code

https://claude.ai/code/session_01F8pqMfJViUaKabWKNQ9wUg


Generated by Claude Code

…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 hyperpolymath marked this pull request as ready for review June 24, 2026 18:46
@hyperpolymath hyperpolymath merged commit da8db01 into main Jun 24, 2026
19 checks passed
@hyperpolymath hyperpolymath deleted the feat/invoker-tla branch June 24, 2026 18:46
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