feat(api/graphql): add verifyProof + suggestTactics(prover/context/goalState) + proverStatus (closes #180)#188
Merged
Conversation
…alState) + proverStatus (closes #180) Closes the GraphQL contract mismatch surfaced in #180 by adding the three operations the echidnabot client expects, plus surfacing the typed REST `/api/verify` taxonomy (`outcome`, optional `mode`/`smtStatus`) so future clients no longer need to round-trip via REST to disambiguate Timeout vs NoProofFound. New operations -------------- - mutation `verifyProof(prover: String!, content: String!): VerifyProofResult!` - mutation `suggestTactics(prover: String!, context: String!, goalState: String!): [SuggestedTactic!]!` - query `proverStatus(prover: String!): ProverStatusInfo!` New types --------- - `VerifyOutcome` (enum: Proved / NoProofFound / InvalidInput / UnsupportedFeature / Timeout / InconsistentPremises / ProverError / SystemError) — mirrors REST `/api/verify` taxonomy - `VerifyProofResult` — status, message, proverOutput, durationMs, artifacts (matches echidnabot's existing `VerifyProofData`), plus `outcome` / `mode` / `smtStatus` (new typed fields) - `SuggestedTactic` — tactic, confidence, explanation (matches echidnabot's `TacticSuggestionData`) - `ProverStatusInfo` — available, message Breaking change --------------- The existing `suggestTactics(proofId, limit)` *query* has been renamed to `suggestTacticsByProofId(proofId, limit)` to free the `suggestTactics` name for the new *mutation* the echidnabot client expects. Other consumers must update the operation name; the argument shape and return type (`[Tactic!]!` with name/args/description/ confidence fields) are unchanged. DRY --- The new `verifyProof` mutation delegates to the same `ProverFactory::create` + `parse_string` + `verify_proof` chain that backs REST `/api/verify`, so behaviour matches by construction. `suggestTactics` for-goal tries the Julia ML coprocessor first and falls back to backend-native suggestions — same pattern as the existing session-based path, just without requiring a `proof_id`. Tests ----- +8 in `schema::tests` (covers outcome-taxon round-trip, loose-status backward-compat for echidnabot's `parse_proof_status`, end-to-end schema execution for all three new ops including a contract assertion via introspection that the issue body asked for). Baseline lib tests unchanged: 1070 passed. Notes ----- - `prover` arguments take a `String` (parsed via `CoreProverKind::from_str`) not the GraphQL `ProverKind` enum, because the echidnabot client sends lowercase string variants (`"coq"`, `"cvc5"`, etc.) and the REST API uses the same string set. - Unknown prover names on `verifyProof` / `proverStatus` return a structured `SystemError` / `available: false` response rather than a GraphQL error, so the client always gets contract-shaped data. `suggestTactics` (which returns `[SuggestedTactic!]!`, non-null list) has no field to encode "unknown prover", so it surfaces a top-level GraphQL error in that path. - No mock data introduced; all ops dispatch through real `ProverFactory` / ML-coprocessor paths. - GraphQL playground / introspection guards untouched. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
hyperpolymath
enabled auto-merge (squash)
June 1, 2026 18:39
🔍 Hypatia Security ScanFindings: 246 issues detected
View findings[
{
"reason": "Issue in agda-meta-checker.yml",
"type": "missing_timeout_minutes",
"file": "agda-meta-checker.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in boj-build.yml",
"type": "missing_timeout_minutes",
"file": "boj-build.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in cargo-audit.yml",
"type": "missing_timeout_minutes",
"file": "cargo-audit.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in cflite_batch.yml",
"type": "missing_timeout_minutes",
"file": "cflite_batch.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in cflite_pr.yml",
"type": "missing_timeout_minutes",
"file": "cflite_pr.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in chapel-ci.yml",
"type": "missing_timeout_minutes",
"file": "chapel-ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in chapel-ci.yml",
"type": "missing_timeout_minutes",
"file": "chapel-ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in chapel-ci.yml",
"type": "missing_timeout_minutes",
"file": "chapel-ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in chapel-ci.yml",
"type": "missing_timeout_minutes",
"file": "chapel-ci.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
},
{
"reason": "Issue in codeql.yml",
"type": "missing_timeout_minutes",
"file": "codeql.yml",
"action": "flag",
"rule_module": "workflow_audit",
"severity": "medium"
}
]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
Resolves the echidna ↔ echidnabot GraphQL contract mismatch surfaced in #180 by adding the three operations the echidnabot client expects, plus surfacing the typed REST
/api/verifytaxonomy (outcome, optionalmode/smtStatus) through GraphQL so future clients no longer need to round-trip via REST to disambiguate Timeout vs NoProofFound.New GraphQL operations
verifyProof(prover: String!, content: String!)VerifyProofResult!suggestTactics(prover: String!, context: String!, goalState: String!)[SuggestedTactic!]!proverStatus(prover: String!)ProverStatusInfo!New GraphQL types
VerifyOutcome(enum:PROVED/NO_PROOF_FOUND/INVALID_INPUT/UNSUPPORTED_FEATURE/TIMEOUT/INCONSISTENT_PREMISES/PROVER_ERROR/SYSTEM_ERROR) — mirrors the REST/api/verifyoutcomefieldVerifyProofResult—status+message+proverOutput+durationMs+artifacts(echidnabot client's existingVerifyProofDatashape), plusoutcome+mode+smtStatus(the typed REST taxonomy newly threaded through)SuggestedTactic—tactic+confidence+explanation(matches echidnabot'sTacticSuggestionData)ProverStatusInfo—available+messageBreaking change
The existing query
suggestTactics(proofId, limit)has been renamed tosuggestTacticsByProofId(proofId, limit)to free thesuggestTacticsname for the new mutation the echidnabot client expects.[Tactic!]!) are unchanged.query { suggestTactics(proofId: ..., limit: ...) }must update the operation name tosuggestTacticsByProofId. The newsuggestTactics(prover, context, goalState)onMutationRootis the onlysuggestTacticsfield after this PR.interfaces/README.mdupdated to reflect the new GraphQL surface.DRY
verifyProofdelegates to the sameProverFactory::create+parse_string+verify_proofchain that backs REST/api/verify, so behaviour matches by construction.suggestTactics(for-goal) tries the Julia ML coprocessor first and falls back to backend-native suggestions — same pattern as the existing session-basedsuggest_tacticspath, just without requiring aproof_id.Tests
+8insrc/interfaces/graphql/schema.rs::tests:verify_outcome_from_rest_str_covers_taxonomy— every REST taxon round-trips to a distinct enum variantverify_outcome_loose_status_matches_client—loose_status()aligns with echidnabot'sparse_proof_statusverify_proof_mutation_unknown_prover_returns_system_error— end-to-end execution; structuredSYSTEM_ERRORoutcomeprover_status_unknown_prover_reports_unavailable— query path;available: false+ populated messagesuggest_tactics_mutation_unknown_prover_errors— top-level GraphQL error (non-null list has no in-band error slot)suggest_tactics_is_a_mutation— guard against accidental kind drift;suggestTacticson QueryRoot must not resolvesuggest_tactics_by_proof_id_is_a_query— renamed legacy query still registered on QueryRootintrospection_exposes_all_three_new_operations— the contract assertion seam(echidnabot): GraphQL contract mismatch — client queries 3 ops that the server does not expose #180 asked forBaseline lib tests unchanged: 1070 passed (
cargo test --lib -p echidna).Don't-touched
submitProof/applyTactic/cancelProofprovers/proofState/listProofs/healthoutcome)Test plan
cargo build -p echidna-graphql— cleancargo test -p echidna-graphql— 8/8 new tests passcargo test --lib -p echidna— 1070 baseline tests still passverifyProof+suggestTactics+proverStatusfrom echidnabot client inEchidnaApiMode::Graphql(deferred — needs a follow-up in echidnabot for the typedoutcomeconsumption)🤖 Generated with Claude Code