3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-07-04 06:16:09 +00:00

Add Copilot skill architecture with 10 skills, 2 agents, and shared infra

Introduce .github/skills/ with solve, prove, optimize, simplify,
encode, explain, benchmark, memory-safety, static-analysis, and
deeptest skills. Each skill follows a SKILL.md + scripts/ pattern
with Python scripts backed by a shared SQLite logging library
(z3db.py). Two orchestrator agents (z3-solver, z3-verifier) route
requests to the appropriate skills.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Angelica Moreira 2026-03-11 17:41:29 +00:00
parent 1cba7cb5ee
commit d349b93d1d
25 changed files with 2784 additions and 0 deletions

54
.github/skills/prove/SKILL.md vendored Normal file
View file

@ -0,0 +1,54 @@
---
name: prove
description: Prove validity of logical statements by negation and satisfiability checking. If the negation is unsatisfiable, the original statement is valid. Otherwise a counterexample is returned.
---
Given a conjecture (an SMT-LIB2 assertion or a natural language claim), determine whether it holds universally. The method is standard: negate the conjecture and check satisfiability. If the negation is unsatisfiable, the original is valid. If satisfiable, the model is a counterexample.
# Step 1: Prepare the negated formula
Wrap the conjecture in `(assert (not ...))` and append `(check-sat)(get-model)`.
Example: to prove that `(> x 3)` implies `(> x 1)`:
```smtlib
(declare-const x Int)
(assert (not (=> (> x 3) (> x 1))))
(check-sat)
(get-model)
```
# Step 2: Run the prover
```bash
python3 scripts/prove.py --conjecture "(=> (> x 3) (> x 1))" --vars "x:Int"
```
For file input where the file contains the full negated formula:
```bash
python3 scripts/prove.py --file negated.smt2
```
With debug tracing:
```bash
python3 scripts/prove.py --conjecture "(=> (> x 3) (> x 1))" --vars "x:Int" --debug
```
# Step 3: Interpret the output
- `valid`: the negation was unsat, so the conjecture holds for all inputs.
- `invalid` followed by a counterexample: the negation was sat; the model shows a concrete assignment where the conjecture fails.
- `unknown` or `timeout`: Z3 could not decide. The conjecture may require auxiliary lemmas or induction.
# Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| conjecture | string | no | | the assertion to prove (without negation) |
| vars | string | no | | variable declarations as "name:sort" pairs, comma-separated |
| file | path | no | | .smt2 file with the negated formula |
| timeout | int | no | 30 | seconds |
| z3 | path | no | auto | path to z3 binary |
| debug | flag | no | off | verbose tracing |
| db | path | no | .z3-agent/z3agent.db | logging database |
Either `conjecture` (with `vars`) or `file` must be provided.

82
.github/skills/prove/scripts/prove.py vendored Normal file
View file

@ -0,0 +1,82 @@
#!/usr/bin/env python3
"""
prove.py: prove validity by negation + satisfiability check.
Usage:
python prove.py --conjecture "(=> (> x 3) (> x 1))" --vars "x:Int"
python prove.py --file negated.smt2
"""
import argparse
import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).resolve().parent.parent.parent / "shared"))
from z3db import Z3DB, run_z3, parse_model, setup_logging
def build_formula(conjecture: str, vars_str: str) -> str:
lines = []
if vars_str:
for v in vars_str.split(","):
v = v.strip()
name, sort = v.split(":")
lines.append(f"(declare-const {name.strip()} {sort.strip()})")
lines.append(f"(assert (not {conjecture}))")
lines.append("(check-sat)")
lines.append("(get-model)")
return "\n".join(lines)
def main():
parser = argparse.ArgumentParser(prog="prove")
parser.add_argument("--conjecture", help="assertion to prove")
parser.add_argument("--vars", help="variable declarations, e.g. 'x:Int,y:Bool'")
parser.add_argument("--file", help="path to .smt2 file with negated formula")
parser.add_argument("--timeout", type=int, default=30)
parser.add_argument("--z3", default=None)
parser.add_argument("--db", default=None)
parser.add_argument("--debug", action="store_true")
args = parser.parse_args()
setup_logging(args.debug)
if args.file:
formula = Path(args.file).read_text()
elif args.conjecture:
formula = build_formula(args.conjecture, args.vars or "")
else:
parser.error("provide --conjecture or --file")
return
db = Z3DB(args.db)
run_id = db.start_run("prove", formula)
result = run_z3(formula, z3_bin=args.z3, timeout=args.timeout, debug=args.debug)
if result["result"] == "unsat":
verdict = "valid"
elif result["result"] == "sat":
verdict = "invalid"
else:
verdict = result["result"]
model = parse_model(result["stdout"]) if verdict == "invalid" else None
db.log_formula(run_id, formula, verdict, str(model) if model else None)
db.finish_run(run_id, verdict, result["duration_ms"], result["exit_code"])
print(verdict)
if model:
print("counterexample:")
for name, val in model.items():
print(f" {name} = {val}")
db.close()
# Exit 0 when we successfully determined validity or invalidity;
# exit 1 only for errors/timeouts.
sys.exit(0 if verdict in ("valid", "invalid") else 1)
if __name__ == "__main__":
main()