3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-04-26 05:43:33 +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

50
.github/skills/solve/SKILL.md vendored Normal file
View file

@ -0,0 +1,50 @@
---
name: solve
description: Check satisfiability of SMT-LIB2 formulas using Z3. Returns sat/unsat with models or unsat cores. Logs every invocation to z3agent.db for auditability.
---
Given an SMT-LIB2 formula (or a set of constraints described in natural language), determine whether the formula is satisfiable. If sat, extract a satisfying assignment. If unsat and tracking labels are present, extract the unsat core.
# Step 1: Prepare the formula
If the input is already valid SMT-LIB2, use it directly. If it is a natural language description, use the **encode** skill first to produce SMT-LIB2.
The formula must include `(check-sat)` at the end. Append `(get-model)` for satisfiable queries or `(get-unsat-core)` when named assertions are used.
# Step 2: Run Z3
```bash
python3 scripts/solve.py --formula "(declare-const x Int)(assert (> x 0))(check-sat)(get-model)"
```
For file input:
```bash
python3 scripts/solve.py --file problem.smt2
```
With debug tracing:
```bash
python3 scripts/solve.py --file problem.smt2 --debug
```
The script pipes the formula to `z3 -in` via subprocess (no shell expansion), logs the run to `.z3-agent/z3agent.db`, and prints the result.
# Step 3: Interpret the output
- `sat` followed by a model: the formula is satisfiable; the model assigns concrete values to each declared constant.
- `unsat`: no assignment exists. If `(get-unsat-core)` was used, the conflicting named assertions are listed.
- `unknown`: Z3 could not decide within the timeout. Consider increasing the timeout or simplifying the formula.
- `timeout`: the process was killed after the deadline. Try the **simplify** skill to reduce complexity.
# Parameters
| Parameter | Type | Required | Default | Description |
|-----------|------|----------|---------|-------------|
| formula | string | no | | SMT-LIB2 formula as a string |
| file | path | no | | path to an .smt2 file |
| timeout | int | no | 30 | seconds before killing z3 |
| z3 | path | no | auto | explicit path to z3 binary |
| debug | flag | no | off | print z3 command, stdin, stdout, stderr, timing |
| db | path | no | .z3-agent/z3agent.db | path to the logging database |
Either `formula` or `file` must be provided.

66
.github/skills/solve/scripts/solve.py vendored Normal file
View file

@ -0,0 +1,66 @@
#!/usr/bin/env python3
"""
solve.py: check satisfiability of an SMT-LIB2 formula via Z3.
Usage:
python solve.py --formula "(declare-const x Int)(assert (> x 0))(check-sat)(get-model)"
python solve.py --file problem.smt2
python solve.py --file problem.smt2 --debug --timeout 60
"""
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, parse_unsat_core, setup_logging
def main():
parser = argparse.ArgumentParser(prog="solve")
parser.add_argument("--formula", help="SMT-LIB2 formula string")
parser.add_argument("--file", help="path to .smt2 file")
parser.add_argument("--timeout", type=int, default=30)
parser.add_argument("--z3", default=None, help="path to z3 binary")
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.formula:
formula = args.formula
else:
parser.error("provide --formula or --file")
return
db = Z3DB(args.db)
run_id = db.start_run("solve", formula)
result = run_z3(formula, z3_bin=args.z3, timeout=args.timeout, debug=args.debug)
model = parse_model(result["stdout"]) if result["result"] == "sat" else None
core = parse_unsat_core(result["stdout"]) if result["result"] == "unsat" else None
db.log_formula(run_id, formula, result["result"],
str(model) if model else None)
db.finish_run(run_id, result["result"], result["duration_ms"],
result["exit_code"])
print(result["result"])
if model:
for name, val in model.items():
print(f" {name} = {val}")
if core:
print("unsat core:", " ".join(core))
if result["stderr"] and result["result"] == "error":
print(result["stderr"], file=sys.stderr)
db.close()
sys.exit(0 if result["exit_code"] == 0 else 1)
if __name__ == "__main__":
main()