This document describes the design and implementation for a Soundiness Info Window in KeY, as implemented on July 3, 2026.
Soundiness refers to the practical trade-offs made in formal verification tools between complete soundness and usability. Unlike binary soundness (sound/unsound), soundiness acknowledges a spectrum of assumptions and simplifications that affect verification validity.
See: Soundiness - Communications of the ACM
In KeY's context, soundiness encompasses:
- Taclet options that disable certain checks for usability
- Platform limitations (memory, timeouts)
- Incomplete source code analysis
- Proof techniques that rely on unproved lemmas or assumptions
Provide non-expert KeY users with a comprehensive, understandable report explaining what assumptions and limitations affect their verification results.
| Question | Decision | Rationale |
|---|---|---|
| Q1: Aggregate risk score? | ❌ No aggregate level | Users should see individual warnings without oversimplification |
| Q2: Detail level? | ✅ Full detail in HTML format | Simple, readable format that works in Swing |
| Q3: Proof tree analysis depth? | ✅ Full traversal | Users need to find where assumptions are used |
| Q4: Batch analysis? | ❌ Not for v1 | Focus on single-proof experience first |
| Q5: Report persistence? | ❌ Compute fresh each time | Settings may change; always show current state |
| Q6: Memory warning thresholds? | ✅ Yes (<1GB critical, <2GB warning) | Concrete thresholds help users understand limits |
The soundiness report is organized into four distinct compartments:
"Platform and tool limitations that affect verification"
Data Sources:
Runtime.getRuntime().maxMemory()- JVM memory limitsChoiceSettings.getChoice("initialisation")- Static initialization settingStrategySettings.getMaxSteps()- Proof search limitsGeneralSettings.isUseJML()- JML enabled/disabledGeneralSettings.isEnsureSourceConsistency()- Source caching
Warning Examples:
| Category | Condition | User Message |
|---|---|---|
| Memory | < 1GB available | "Very limited memory available" |
| Memory | < 2GB available | "Limited memory available" |
| Static Initialization | disableStaticInitialisation |
"Static constructors are not analyzed" |
| JML Disabled | isUseJML() == false |
"JML specifications are ignored" |
| Source Caching | isEnsureSourceConsistency() == false |
"Source file changes may not be detected" |
"Semantic simplifications in the logical calculus"
Current KeY Classification:
// UNSOUND choices (TacletOptionsSettings.isUnsound())
- runtimeExceptions:ignore
- initialisation:disableStaticInitialisation
- intRules:arithmeticSemanticsIgnoringOF
// INCOMPLETE choices (isIncomplete())
- runtimeExceptions:ban
- Strings:off
- intRules:arithmeticSemanticsCheckingOF
- integerSimplificationRules:minimal
- programRules:None
// CONDITIONAL (getInformation())
- JavaCard:on/off (sound only for respective platform)
- assertions:on/off (depends on JVM startup flags)Enhanced Presentation:
| Choice | Plain English Impact | Severity |
|---|---|---|
runtimeExceptions:ignore |
"Assumes no null pointer, divide-by-zero, or array bounds errors occur" | 🔴 High |
intRules:arithmeticSemanticsIgnoringOF |
"Integer overflow is ignored; arithmetic wraps around like in Java" | 🔴 High |
initialisation:disableStaticInitialisation |
"Static field initializers and static blocks are skipped" | 🔴 High |
Strings:off |
"String operations are not analyzed" | 🟡 Medium |
programRules:None |
"Java language constructs are not processed" | 🔴 High |
runtimeExceptions:ban |
"Any implicit runtime exception is treated as program failure" | 🟢 Low |
"What was actually loaded and parsed"
Information Displayed:
- Count of loaded
.javaand.keyfiles - Parse warnings and errors
- Missing class dependencies
- JML contract coverage (% of methods with specifications)
- Unsupported Java features (lambdas, streams, etc.)
Note: Currently returns empty data; full implementation requires integration with KeYFile/InitConfig.
"What happened during this specific proof"
Analysis Components:
-
Goal Statistics
- Total goals, closed goals, open goals
- Cached goals (from proof cache)
-
User-Defined Lemmas
- Scan for taclets with "lemma" in name
- Track usage count
- Flag unproved lemmas
-
Assumptions
- Count of
assumecommands used - Location and formula for each assumption
- Count of
-
Rule Application Statistics
- Most frequently used rules (top 5)
- Interactive vs. automated steps ratio
The implementation uses a single HTML generation approach rather than separate data models and UI components:
Location: /opencode/key.ui/src/main/java/de/uka/ilkd/key/gui/soundiness/SoundinessAnalyzer.java
public final class SoundinessAnalyzer {
/**
* Generates an HTML soundiness report for the given proof.
*
* @param proof the proof to analyze
* @return HTML string containing the complete report
*/
public static String generateHTMLReport(Proof proof);
}Internal Data Records (encapsulated within analyzer):
GeneralKeYWarning- Warning with level, category, message, recommendationTacletOptionEntry- Taclet choice with impact descriptionSourceStats- Source file statisticsProofStats- Proof tree statisticsLemmaUsage- Lemma usage trackingAssumptionUsage- Assumption tracking
Location: /opencode/key.ui/src/main/java/de/uka/ilkd/key/gui/soundiness/SoundinessDialog.java
Simple modal JDialog with:
- HTML pane displaying the generated report
- Scroll pane with wheel scrolling enabled
- Copy HTML button
- Close button
UI Layout:
┌─────────────────────────────────────────────────────┐
│ Soundiness Report: [Proof Name] │
├─────────────────────────────────────────────────────┤
│ │
│ [Scrollable HTML Report] │
│ - 1. General KeY Settings │
│ - 2. Taclet Options │
│ - 3. Source Analysis │
│ - 4. Proof Tree Analysis │
│ │
│ [Copy HTML] [Close] │
└─────────────────────────────────────────────────────┘
File: TaskTree.java:TaskTreeIconCellRenderer.getTreeCellRendererComponent()
Add overlay icon when proof has unsound choices or assumptions:
- Icon: Use existing
IconFactory.WARNING_UNSOUND - Tooltip: Brief summary like "2 unsound choices, 1 assumption used"
File: ShowProofStatistics.java:Window.init()
Add button after line ~338:
JButton soundinessButton = new JButton("Show Soundiness Report");
soundinessButton.setIcon(IconFactory.WARNING_UNSOUND.get());
soundinessButton.addActionListener(e -> {
de.uka.ilkd.key.gui.soundiness.SoundinessDialog dialog =
new de.uka.ilkd.key.gui.soundiness.SoundinessDialog(mainWindow, proof);
dialog.setVisible(true);
});
buttonPane2.add(soundinessButton);File: ShowSoundinessAction.java
Register via KeY extension mechanism to add "Show Soundiness Report" to proof list right-click menu.
File: ProofClosedJTextPaneDisplay.java:execute()
After showing statistics, optionally add link: "⚠ This proof used unsound options. [View Details]"
- Use
Soundinessprefix consistently (notSoundness) - Private constructors for utility classes
- Internal records use descriptive names
- Javadoc for public APIs
- Include
@since 2.13tag - Link to this document in package-info.java
- Never fail silently - log warnings to SLF4J
- Handle null proofs gracefully
- Catch exceptions during analysis and show partial results
- Proof with all 3 unsound choices enabled
- Proof using
\lemmataclets without side proofs - Proof with multiple
assumecommands - Minimal proof (single goal, few steps)
- Proof closed via cache
- Large proof (>1000 nodes) - verify performance acceptable (<2s analysis)
- Single-pass analysis for all compartments
- HTML generated on-demand
- No caching (report computed fresh each time)
For very large proofs, consider:
- Background thread analysis
- Lazy loading of compartments
- Caching with invalidation on proof structure changes
| Risk | Impact | Mitigation |
|---|---|---|
| Proof tree traversal too slow | Poor UX for large proofs | Profile and optimize if needed |
| Too many false positives | Users ignore warnings | Careful calibration, user feedback loop |
| Technical jargon in messages | Confuses non-experts | Iterate on wording based on feedback |
| Integration conflicts with extensions | Broken functionality | Test with popular extensions |
- Batch analysis ("Analyze All Loaded Proofs")
- Persistent soundiness metadata in proof bundles
- Aggregate statistics across proof corpus
- Automatic recommendations ("Consider enabling X for more complete verification")
- Integration with SMT solver trust levels
- Historical tracking (how soundiness changed during proof development)
- Enhanced source analysis with real KeYFile data
- Proper lemma detection via \lemma annotation parsing
- Soundiness - CACM Paper
TacletOptionsSettings.java- existing taclet option handlingShowProofStatistics.java- similar dialog patternTaskTree.java- proof list rendering
For questions about this implementation, contact the KeY development team.
Document Version: 2.0
Created: 2026-07-03
Updated: 2026-07-03 (Simplified HTML generation approach)
Status: ✅ Implemented