Skip to content

Commit b0697cb

Browse files
ArghDA M9: Isabelle/HOL adapter — second heavy-tail backend (foundation-first) (#45)
## What The second heavy-tail backend. arghda is now an **eight-backend** prover-parametric workspace (agda, agda-cubical, idris2, lean4, coq, **isabelle** as Assistants; z3, cvc5 as Solvers). Foundation-first again: **provisioned Isabelle2025** (1.08 GB tarball, HOL heap ships prebuilt), **ground-truthed the invocation** against the real tool, then built and dogfooded the adapter. ## How **Adapter — `src/prover/isabelle.rs` (`Isabelle`)** - Assistant kind, extensions `[thy]`, command `isabelle`. - Isabelle is session-based (no single-file `--check`), so `check_file` generates a throwaway session: copies the target `.thy` + sibling `.thy` files into a temp dir, writes a `ROOT` (`session ArghdaCheck = HOL + theories <T>`), and runs `isabelle build -o quick_and_dirty -d <dir> ArghdaCheck`. Heaps land in `~/.isabelle`, so the source tree stays clean (~6 s/theory). - Verdict, ground-truthed vs Isabelle2025 — honest, never fabricated: exit ≠ 0 → `Error`; exit 0 + `sorry`/`oops` → `Admitted` (`sorry` compiles under `quick_and_dirty`, so it is caught at the source, not hidden by the exit code); exit 0 + `axiomatization` → `Postulated`; exit 0 clean → `Proven`. - Imports: the header `imports … begin` clause (bare names + quoted-path final segment; stdlib `Main` dropped as external). Roots: a `ROOT` file's `theories` section — the genuine Isabelle entry-point convention (analogue of `All.agda`), parsed tolerantly. - `probe()` overridden to `isabelle version` (not `--version`, which errors `Unknown Isabelle tool` — `doctor` caught this); added a `pub(crate) probe_tool_arg` helper for the custom version query. **Lint — `src/lint/isabelle.rs` (`IsabelleEscapeHatch`)**: warn under the shared `escape-hatch` name (amber cap); flags `sorry`/`oops`/`axiomatization`. **Provisioning fix at source**: the script's Isabelle URL was stale (`/dist/Isabelle2024…` 404s once a newer release is current) — switched to the archived `/website-<VER>/dist/` path and bumped to Isabelle2025. **Wired**: `backend_for "isabelle"`, `KNOWN_BACKENDS`, all four `--backend` help strings, the CLI about line. ## Verification (actually run) - `cargo fmt --check` — clean - `cargo clippy --all-targets -- -D warnings` — clean - `cargo test` — **159 pass** (+6 isabelle unit, +4 isabelle lint unit, +3 isabelle integration; the graph tests are hermetic — text/ROOT only, run tool-less) - `bash scripts/check-spdx.sh .` — OK **Dogfooded against real Isabelle2025:** | fixture | `arghda check --backend isabelle` | |---|---| | `Good.thy` (`by simp`) | `proven` | | `Admits.thy` (`sorry`) | `admitted` | | `Postulate.thy` (`axiomatization`) | `postulated` | | `Broken.thy` (false lemma) | `error` | - `reason --check --backend isabelle` reproduces those verdicts - imports `All → Base` / `All → Util` / `Util → Base` parsed; `ROOT` `theories = All` → `crt_root` `All`; `Base`+`Util` wired; `Orphan` unwired - `arghda doctor` → `[OK] isabelle assistant Isabelle2025` ## Scope M9 at 90%. Remaining: session-qualified / relative-path imports + dependency-ordered multi-session builds. 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_012MpYSh6Wy8YMBH2E3qVyT7 --- _Generated by [Claude Code](https://claude.ai/code/session_012MpYSh6Wy8YMBH2E3qVyT7)_ Co-authored-by: Claude <noreply@anthropic.com>
1 parent 402f663 commit b0697cb

14 files changed

Lines changed: 749 additions & 26 deletions

File tree

.machine_readable/6a2/STATE.a2ml

Lines changed: 49 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ status = "active" # active | paused | archived
1111

1212
[project-context]
1313
name = "arghda-core"
14-
purpose = "Multi-backend proof-workspace manager — the 'Flying Logic for provers/solvers' engine. A four-state triage workspace (inbox/working/proven/rejected) as file moves, per-backend lint packs targeting the silent-failure class, a backend-parametric import-graph DAG, a demote-only status-propagating reasoning graph, and a JSON + event-stream contract a visual layer (arghda-studio) consumes. Seven backends across both interaction models (Agda, Cubical-Agda, Idris2, Lean4, Coq/Rocq assistants; Z3, CVC5 solvers). It never proves anything itself; the tools do."
14+
purpose = "Multi-backend proof-workspace manager — the 'Flying Logic for provers/solvers' engine. A four-state triage workspace (inbox/working/proven/rejected) as file moves, per-backend lint packs targeting the silent-failure class, a backend-parametric import-graph DAG, a demote-only status-propagating reasoning graph, and a JSON + event-stream contract a visual layer (arghda-studio) consumes. Eight backends across both interaction models (Agda, Cubical-Agda, Idris2, Lean4, Coq/Rocq, Isabelle/HOL assistants; Z3, CVC5 solvers). It never proves anything itself; the tools do."
1515
completion-percentage = 92
1616

1717
[position]
@@ -49,7 +49,7 @@ milestones = [
4949
{ name = "M6: Lean4 adapter (lake build + #print axioms audit)", completion = 92 },
5050
{ name = "M7: Echidna dispatch seam (optional route to orchestrator :8090, same Outcome)", completion = 70 },
5151
{ name = "M8: Coq/Rocq adapter (--heavy provisioning; Section-aware postulate classifier)", completion = 90 },
52-
{ name = "M9: Isabelle adapter (--heavy; dogfood tropical-resource-typing .thy)", completion = 0 },
52+
{ name = "M9: Isabelle adapter (--heavy; dogfood tropical-resource-typing .thy)", completion = 90 },
5353
{ name = "M10: Mizar adapter (detect-only first; highest uncertainty)", completion = 0 },
5454
{ name = "M11: studio JSON freeze (reason/0.1) + Groove manifest", completion = 100 },
5555
]
@@ -58,8 +58,13 @@ milestones = [
5858
# real --version. idris2 v0.7.0 builds via chez bootstrap. COQ NOW INSTALLED
5959
# (2026-07-01, heavy-tail foundation): opam 2.1.5 via apt → `opam install
6060
# coq.8.18.0` → coqc reports real --version; symlinked to /usr/local/bin/coqc
61-
# so `arghda doctor` probes it ([OK] coq assistant). Isabelle/Mizar remain
62-
# scripted (behind --heavy/--mizar) but not installed this session.
61+
# so `arghda doctor` probes it ([OK] coq assistant). ISABELLE NOW INSTALLED
62+
# (2026-07-01): Isabelle2025 tarball (1.08 GB, HOL heap prebuilt) unpacked to
63+
# /opt, symlinked to /usr/local/bin/isabelle; `isabelle version` → Isabelle2025;
64+
# doctor [OK] isabelle. NB the provision script's Isabelle URL was stale
65+
# (/dist/Isabelle2024… 404s once a newer release is current) — FIXED at source
66+
# to the archived /website-<VER>/dist/ path + bumped to Isabelle2025. Mizar
67+
# remains scripted (behind --mizar) but not installed (distribution manual).
6368
# Remaining M0: `arghda doctor` Rust subcommand (interim: `just doctor` shells
6469
# the script's --verify-only table).
6570
#
@@ -149,6 +154,36 @@ milestones = [
149154
# Error when an uncompiled dependency is Required — documented limitation, same
150155
# class as Lean's lake-env gap).
151156
#
157+
# M9 landed 2026-07-01 (90%, second heavy-tail backend): the Isabelle/HOL
158+
# adapter. Foundation-first again — provisioned Isabelle2025 (1.08 GB tarball,
159+
# HOL heap prebuilt) BEFORE the adapter; ground-truthed the invocation, then
160+
# built + dogfooded vs the REAL tool. Isabelle is session-based (no single-file
161+
# --check), so src/prover/isabelle.rs (`Isabelle`) check_file generates a
162+
# throwaway session: copies the target .thy + sibling .thy files into a temp
163+
# dir, writes `ROOT` (session ArghdaCheck = HOL + theories <T>), runs
164+
# `isabelle build -o quick_and_dirty -d <dir> ArghdaCheck` (heaps land in
165+
# ~/.isabelle, tree stays clean; ~6 s/theory). Verdict, ground-truthed vs
166+
# Isabelle2025: exit≠0 → Error; exit 0 + sorry/oops → Admitted (sorry compiles
167+
# under quick_and_dirty, so caught at source); exit 0 + axiomatization →
168+
# Postulated; exit 0 clean → Proven. Imports: the header `imports … begin`
169+
# clause (bare names + quoted-path final segment; stdlib Main dropped as
170+
# external). Roots: a `ROOT` file's `theories` section (the genuine Isabelle
171+
# entry-point convention — analogue of All.agda; parsed tolerantly, option
172+
# groups skipped). Lint: src/lint/isabelle.rs `IsabelleEscapeHatch` (warn,
173+
# shared name escape-hatch) flags sorry/oops/axiomatization. probe() overridden
174+
# to `isabelle version` (NOT --version, which errors "Unknown Isabelle tool" —
175+
# doctor caught this; added pub(crate) probe_tool_arg for the custom query).
176+
# Wired: backend_for "isabelle" + KNOWN_BACKENDS + all four --backend help
177+
# strings + about line. Also fixed the provision script's stale Isabelle URL at
178+
# source (/website-<VER>/dist/ + Isabelle2025). 159 tests (+6 isabelle unit +4
179+
# isabelle lint unit +3 isabelle integration; graph tests hermetic — text/ROOT
180+
# only, run tool-less). DOGFOODED vs real Isabelle2025: check → Good=proven /
181+
# Admits=admitted / Postulate=postulated / Broken=error; `reason --check
182+
# --backend isabelle` reproduces those; imports All→Base/All→Util/Util→Base
183+
# parsed, ROOT theories=All → crt_root All, Base+Util wired, Orphan unwired;
184+
# doctor → [OK] isabelle assistant Isabelle2025. Remaining 10%: session-
185+
# qualified / relative-path imports + dependency-ordered multi-session builds.
186+
#
152187
# M7 landed 2026-07-01 (70%): the Echidna dispatch seam — completes the
153188
# engine-spine deliverable (M0-M7 + M11). src/dispatch.rs: `Dispatch { Local,
154189
# Echidna { base_url } }` + `run(backend, file, include_root) -> Outcome`
@@ -311,7 +346,8 @@ actions = [
311346
"M4 follow-on: .ipkg-declared roots DONE; remaining = totality-hole (?name) + per-def `partial` lint.",
312347
"M3 follow-on: DONE — `reason --workspace <ws>` sources real verdicts from a `proven/` state (workspace_verdicts) + demotes stale-proven via the content-hash closure. Refinement follow-ons bucket now complete.",
313348
"M8 (Coq/Rocq): DONE (90%) — coqc 8.18.0 provisioned + adapter built + dogfooded (proven/admitted/postulated/error) with Section-aware postulate classifier. Remaining: _CoqProject logical paths + dependency-ordered compilation.",
314-
"M9-M10 heavy tail (Isabelle, Mizar) — next, foundation-first: Isabelle ~4GB tarball then adapter; Mizar niche/detect-only. Then climb to M6 lake-env, M4 totality lint, M7 Echidna client.",
349+
"M9 (Isabelle): DONE (90%) — Isabelle2025 provisioned + adapter built + dogfooded (proven/admitted/postulated/error) via session-build; ROOT-based roots, imports-clause edges. Remaining: session-qualified imports + dependency-ordered multi-session builds.",
350+
"M10 (Mizar): next, foundation-first — detect-only first (distribution is manual/niche via mizar.org; provision honestly, check_file → Unavailable until a real toolchain confirms invocation). Then climb to M6 lake-env, M4 totality lint, M7 Echidna client.",
315351
]
316352

317353
[maintenance-status]
@@ -320,13 +356,14 @@ last-result = "pass" # unknown | pass | warn | fail
320356
open-warnings = 0
321357
open-failures = 0
322358
# `just check` (fmt-check + clippy -D warnings + build + test + SPDX) green
323-
# post-M8: 108 lib + 38 integration = 146 tests pass. codeql.yml added
324-
# (code-scanning gate fix). M8 Coq adapter dogfooded vs real coqc 8.18.0
325-
# (proven/admitted/postulated/error; reason --check; import edges; roots; wired;
326-
# doctor [OK] coq). reason --workspace verdicts+staleness dogfooded. Lean
327-
# #print axioms audit dogfooded. doctor/groove/dispatch dogfooded. SEVEN
328-
# backends now: agda + agda-cubical + idris2 + lean4 + coq (Assistant), z3 +
329-
# cvc5 (Solver). Dogfooded historically vs echo-types + agda-unused.
359+
# post-M9: 118 lib + 41 integration = 159 tests pass. codeql.yml added
360+
# (code-scanning gate fix). M9 Isabelle adapter dogfooded vs real Isabelle2025
361+
# (proven/admitted/postulated/error; reason --check; imports edges; ROOT roots;
362+
# wired; doctor [OK] isabelle). M8 Coq adapter dogfooded vs real coqc 8.18.0.
363+
# reason --workspace verdicts+staleness dogfooded. Lean #print axioms audit
364+
# dogfooded. doctor/groove/dispatch dogfooded. EIGHT backends now: agda +
365+
# agda-cubical + idris2 + lean4 + coq + isabelle (Assistant), z3 + cvc5
366+
# (Solver). Dogfooded historically vs echo-types + agda-unused.
330367

331368
[ecosystem]
332369
part-of = ["arghda"]

scripts/provision-provers.sh

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ IDRIS2_TAG="v0.7.0" # standards/a2ml CI pin
3535
LEAN_VER="v4.13.0" # tropical-resource-typing lean-toolchain
3636
CVC5_VER="1.2.0" # cvc5 static-binary release
3737
COQ_VER="8.18.0" # opam (with --heavy)
38-
ISABELLE_VER="Isabelle2024" # TUM tarball (with --heavy)
38+
ISABELLE_VER="Isabelle2025" # TUM tarball (with --heavy)
3939

4040
STDLIB_DIR=/opt/agda-stdlib
4141
CUBICAL_DIR=/opt/agda-cubical
@@ -203,8 +203,11 @@ install_coq() {
203203

204204
install_isabelle() {
205205
have isabelle && { log "isabelle present"; return; }
206-
log "installing ${ISABELLE_VER} (heavy, ~4 GB)…"
207-
local url="https://isabelle.in.tum.de/dist/${ISABELLE_VER}_linux.tar.gz"
206+
log "installing ${ISABELLE_VER} (heavy, ~1.1 GB download, HOL heap ships prebuilt)…"
207+
# Only the *current* release lives under /dist/; older ones move to the
208+
# archived /website-<VER>/dist/ path (the /dist/ form 404s). The archived
209+
# path is stable and works for the current release too, so use it uniformly.
210+
local url="https://isabelle.in.tum.de/website-${ISABELLE_VER}/dist/${ISABELLE_VER}_linux.tar.gz"
208211
if curl -fsSL "$url" -o /tmp/isabelle.tar.gz 2>/dev/null && [ -s /tmp/isabelle.tar.gz ]; then
209212
tar -xzf /tmp/isabelle.tar.gz -C /opt \
210213
&& ln -sf "/opt/${ISABELLE_VER}/bin/isabelle" /usr/local/bin/isabelle \

src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,8 +35,8 @@ pub use graph::{build as build_graph, ImportGraph};
3535
pub use groove::{manifest as groove_manifest, GrooveManifest};
3636
pub use lint::{default_rules, rules_with_config, run_lints, LintRule, RuleConfig};
3737
pub use prover::{
38-
default_backend, Agda, AgdaCubical, Backend, BackendKind, Coq, Idris2, Lean, Outcome, Probe,
39-
Smt, Verdict,
38+
default_backend, Agda, AgdaCubical, Backend, BackendKind, Coq, Idris2, Isabelle, Lean, Outcome,
39+
Probe, Smt, Verdict,
4040
};
4141
pub use reason::{
4242
build as build_reason, workspace_verdicts, Junct, ReasonDocument, ReasonEdge, ReasonNode,

src/lint/isabelle.rs

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
// SPDX-License-Identifier: MPL-2.0
2+
// Copyright (c) 2026 Jonathan D.A. Jewell (hyperpolymath) <j.d.a.jewell@open.ac.uk>
3+
4+
//! Isabelle/HOL `escape-hatch` (warn) — surface soundness escape hatches.
5+
//!
6+
//! The Isabelle analogue of the Agda/Idris2/Lean/Coq escape-hatch rules;
7+
//! shares the rule *name* `escape-hatch` so the reasoning graph caps any hit
8+
//! at amber.
9+
//!
10+
//! Flags `sorry` (admits a proposition without proof), `oops` (abandons a
11+
//! proof mid-attempt) and `axiomatization` (introduces unverified axioms).
12+
//! `isabelle build -o quick_and_dirty` compiles a theory containing `sorry`
13+
//! with exit 0, so without this warn — and without the backend's source-level
14+
//! classification — such gaps ride along invisibly. Block comments `(* … *)`
15+
//! are stripped so a "no sorry here" comment does not match; prose blocks
16+
//! (`text ‹…›`) are a documented minor false-positive risk.
17+
18+
use super::{LintContext, LintRule};
19+
use crate::diagnostic::{Diagnostic, LintReport, Severity};
20+
use anyhow::{Context, Result};
21+
use std::fs;
22+
use std::path::Path;
23+
24+
pub struct IsabelleEscapeHatch;
25+
26+
const ESCAPE_TOKENS: &[&str] = &["sorry", "oops", "axiomatization"];
27+
28+
impl LintRule for IsabelleEscapeHatch {
29+
fn name(&self) -> &'static str {
30+
"escape-hatch"
31+
}
32+
33+
fn run(&self, file: &Path, _ctx: &LintContext<'_>, report: &mut LintReport) -> Result<()> {
34+
let contents =
35+
fs::read_to_string(file).with_context(|| format!("reading {}", file.display()))?;
36+
for (i, raw) in contents.lines().enumerate() {
37+
let trimmed = raw.trim_start();
38+
if trimmed.starts_with("(*") {
39+
continue; // whole-line comment (common case)
40+
}
41+
let code = strip_line_comments(raw);
42+
for tok in ESCAPE_TOKENS {
43+
if has_token(&code, tok) {
44+
report.push(warn(
45+
self.name(),
46+
file,
47+
i + 1,
48+
format!("escape primitive `{tok}`"),
49+
));
50+
}
51+
}
52+
}
53+
Ok(())
54+
}
55+
}
56+
57+
fn warn(rule: &str, file: &Path, line: usize, message: String) -> Diagnostic {
58+
Diagnostic {
59+
rule: rule.to_string(),
60+
severity: Severity::Warn,
61+
file: file.to_path_buf(),
62+
message,
63+
line: Some(line),
64+
}
65+
}
66+
67+
/// Remove balanced `(* … *)` spans; an unmatched `(*` truncates the rest of
68+
/// the line.
69+
fn strip_line_comments(line: &str) -> String {
70+
let mut out = String::with_capacity(line.len());
71+
let bytes = line.as_bytes();
72+
let mut i = 0;
73+
let mut depth = 0u32;
74+
while i < bytes.len() {
75+
if i + 1 < bytes.len() && bytes[i] == b'(' && bytes[i + 1] == b'*' {
76+
depth += 1;
77+
i += 2;
78+
continue;
79+
}
80+
if depth > 0 && i + 1 < bytes.len() && bytes[i] == b'*' && bytes[i + 1] == b')' {
81+
depth -= 1;
82+
i += 2;
83+
continue;
84+
}
85+
if depth == 0 {
86+
out.push(bytes[i] as char);
87+
}
88+
i += 1;
89+
}
90+
out
91+
}
92+
93+
/// `tok` appears in `s` as a delimited token (so `sorryish` does not match).
94+
fn has_token(s: &str, tok: &str) -> bool {
95+
s.split(|c: char| c.is_whitespace() || "(){}[];,.".contains(c))
96+
.any(|w| w == tok)
97+
}
98+
99+
#[cfg(test)]
100+
mod tests {
101+
use super::*;
102+
use crate::lint::run_lints;
103+
use std::path::PathBuf;
104+
105+
fn lint_str(body: &str) -> LintReport {
106+
let tmp = tempfile::NamedTempFile::new().unwrap();
107+
std::fs::write(tmp.path(), body).unwrap();
108+
let roots: [PathBuf; 0] = [];
109+
let ctx = LintContext {
110+
include_root: tmp.path().parent().unwrap(),
111+
entry_modules: &roots,
112+
};
113+
let rules: Vec<Box<dyn LintRule>> = vec![Box::new(IsabelleEscapeHatch)];
114+
run_lints(tmp.path(), &ctx, &rules).unwrap()
115+
}
116+
117+
#[test]
118+
fn sorry_is_warned() {
119+
let r = lint_str("theory T imports Main begin\nlemma l: \"True\" sorry\nend\n");
120+
assert_eq!(r.warns().count(), 1);
121+
assert_eq!(r.diagnostics[0].rule, "escape-hatch");
122+
assert!(r.diagnostics[0].message.contains("sorry"));
123+
}
124+
125+
#[test]
126+
fn oops_and_axiomatization_are_warned() {
127+
let r = lint_str(
128+
"theory T imports Main begin\naxiomatization where foo: \"P\"\nlemma l: \"Q\" oops\nend\n",
129+
);
130+
assert_eq!(r.warns().count(), 2);
131+
}
132+
133+
#[test]
134+
fn escape_token_in_comment_is_ignored() {
135+
let r = lint_str(
136+
"theory T imports Main begin\ndefinition x where \"x = 0\" (* no sorry *)\nend\n",
137+
);
138+
assert!(r.diagnostics.is_empty());
139+
}
140+
141+
#[test]
142+
fn clean_theory_is_silent() {
143+
let r = lint_str("theory T imports Main begin\nlemma l: \"True\" by simp\nend\n");
144+
assert!(r.diagnostics.is_empty());
145+
}
146+
}

src/lint/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ use std::path::{Path, PathBuf};
88
pub mod coq;
99
pub mod escape_hatch;
1010
pub mod idris2;
11+
pub mod isabelle;
1112
pub mod lean;
1213
pub mod orphan_module;
1314
pub mod postulate;

src/main.rs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ use anyhow::{Context, Result};
55
use arghda_core::lint::LintContext;
66
use arghda_core::{
77
build_dag, build_reason, event, groove_manifest, run_lints, unused, watcher, Agda, AgdaCubical,
8-
Backend, BackendKind, Coq, Dispatch, Idris2, Lean, LintRule, Probe, RuleConfig, Smt, State,
9-
Verdict, Workspace,
8+
Backend, BackendKind, Coq, Dispatch, Idris2, Isabelle, Lean, LintRule, Probe, RuleConfig, Smt,
9+
State, Verdict, Workspace,
1010
};
1111
use clap::{Parser, Subcommand};
1212
use std::path::{Path, PathBuf};
@@ -23,6 +23,7 @@ const KNOWN_BACKENDS: &[&str] = &[
2323
"idris2",
2424
"lean4",
2525
"coq",
26+
"isabelle",
2627
"z3",
2728
"cvc5",
2829
];
@@ -36,10 +37,11 @@ fn backend_for(name: &str) -> Result<Box<dyn Backend>> {
3637
"idris2" => Ok(Box::new(Idris2)),
3738
"lean4" => Ok(Box::new(Lean)),
3839
"coq" => Ok(Box::new(Coq)),
40+
"isabelle" => Ok(Box::new(Isabelle)),
3941
"z3" => Ok(Box::new(Smt::z3())),
4042
"cvc5" => Ok(Box::new(Smt::cvc5())),
4143
other => anyhow::bail!(
42-
"unknown backend `{other}` (known: agda, agda-cubical, idris2, lean4, coq, z3, cvc5)"
44+
"unknown backend `{other}` (known: agda, agda-cubical, idris2, lean4, coq, isabelle, z3, cvc5)"
4345
),
4446
}
4547
}
@@ -48,7 +50,7 @@ fn backend_for(name: &str) -> Result<Box<dyn Backend>> {
4850
#[command(
4951
name = "arghda",
5052
version,
51-
about = "Proof-workspace manager for provers/solvers (Agda, Cubical, Idris2, Lean4, Coq, Z3, CVC5)"
53+
about = "Proof-workspace manager for provers/solvers (Agda, Cubical, Idris2, Lean4, Coq, Isabelle, Z3, CVC5)"
5254
)]
5355
struct Cli {
5456
#[command(subcommand)]
@@ -76,7 +78,7 @@ enum Cmd {
7678
#[arg(long)]
7779
config: Option<PathBuf>,
7880
/// Backend: `agda` (default), `agda-cubical`, `idris2`, `lean4`,
79-
/// `coq`, `z3`, `cvc5`.
81+
/// `coq`, `isabelle`, `z3`, `cvc5`.
8082
#[arg(long, default_value = "agda")]
8183
backend: String,
8284
/// Also run the external `agda-unused` analyser and re-emit its
@@ -96,7 +98,7 @@ enum Cmd {
9698
#[arg(long)]
9799
include_root: Option<PathBuf>,
98100
/// Backend: `agda` (default), `agda-cubical`, `idris2`, `lean4`,
99-
/// `coq`, `z3`, `cvc5`.
101+
/// `coq`, `isabelle`, `z3`, `cvc5`.
100102
#[arg(long, default_value = "agda")]
101103
backend: String,
102104
/// Where the check runs: `local` (default) or `echidna[=<url>]`
@@ -124,7 +126,7 @@ enum Cmd {
124126
#[arg(long)]
125127
config: Option<PathBuf>,
126128
/// Backend: `agda` (default), `agda-cubical`, `idris2`, `lean4`,
127-
/// `coq`, `z3`, `cvc5`.
129+
/// `coq`, `isabelle`, `z3`, `cvc5`.
128130
#[arg(long, default_value = "agda")]
129131
backend: String,
130132
},
@@ -148,7 +150,7 @@ enum Cmd {
148150
#[arg(long)]
149151
config: Option<PathBuf>,
150152
/// Backend: `agda` (default), `agda-cubical`, `idris2`, `lean4`,
151-
/// `coq`, `z3`, `cvc5`.
153+
/// `coq`, `isabelle`, `z3`, `cvc5`.
152154
#[arg(long, default_value = "agda")]
153155
backend: String,
154156
/// Run the backend on every node to populate REAL prover verdicts

0 commit comments

Comments
 (0)