clauz3 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- clauz3-0.1.0/.github/workflows/docs.yaml +54 -0
- clauz3-0.1.0/.github/workflows/main.yaml +55 -0
- clauz3-0.1.0/.github/workflows/release.yaml +50 -0
- clauz3-0.1.0/.gitignore +10 -0
- clauz3-0.1.0/.python-version +1 -0
- clauz3-0.1.0/AGENTS.md +51 -0
- clauz3-0.1.0/Justfile +32 -0
- clauz3-0.1.0/PKG-INFO +260 -0
- clauz3-0.1.0/README.md +248 -0
- clauz3-0.1.0/docs/examples/bank-all-cases.md +9 -0
- clauz3-0.1.0/docs/examples/bank.md +39 -0
- clauz3-0.1.0/docs/examples/email-all-cases.md +9 -0
- clauz3-0.1.0/docs/examples/email-from-db-all-cases.md +9 -0
- clauz3-0.1.0/docs/examples/email-from-db.md +55 -0
- clauz3-0.1.0/docs/examples/email.md +47 -0
- clauz3-0.1.0/docs/explanation/background.md +193 -0
- clauz3-0.1.0/docs/explanation/concepts.md +179 -0
- clauz3-0.1.0/docs/explanation/faq.md +83 -0
- clauz3-0.1.0/docs/explanation/symbolic-iteration.md +117 -0
- clauz3-0.1.0/docs/how-to/approval-service.md +263 -0
- clauz3-0.1.0/docs/how-to/install-layers.md +85 -0
- clauz3-0.1.0/docs/how-to/integration-testing.md +168 -0
- clauz3-0.1.0/docs/how-to/pi-harness.md +315 -0
- clauz3-0.1.0/docs/index.md +76 -0
- clauz3-0.1.0/docs/macros.py +119 -0
- clauz3-0.1.0/docs/quickstart.md +103 -0
- clauz3-0.1.0/docs/reference/cli.md +124 -0
- clauz3-0.1.0/docs/reference/coverage-policies.md +124 -0
- clauz3-0.1.0/docs/reference/effect-specs.md +294 -0
- clauz3-0.1.0/docs/reference/python-subset.md +404 -0
- clauz3-0.1.0/docs/reference/stdlib.md +103 -0
- clauz3-0.1.0/docs/slides/index.html +749 -0
- clauz3-0.1.0/docs/superpowers/plans/2026-05-25-symbolic-iteration.md +3666 -0
- clauz3-0.1.0/docs/superpowers/specs/2026-05-25-symbolic-iteration-design.md +544 -0
- clauz3-0.1.0/docs/todos/effect-ir.md +180 -0
- clauz3-0.1.0/docs/todos/ideas.md +119 -0
- clauz3-0.1.0/docs/todos/owl-dl-mapping.md +150 -0
- clauz3-0.1.0/docs/todos/quantified-aggregates.md +44 -0
- clauz3-0.1.0/docs/todos/quantified-shares-value.md +30 -0
- clauz3-0.1.0/docs/todos/user-approval-dialog.md +362 -0
- clauz3-0.1.0/examples/bank/Justfile +35 -0
- clauz3-0.1.0/examples/bank/cases/for_loop_sum_fail.py +11 -0
- clauz3-0.1.0/examples/bank/cases/for_loop_sum_pass.py +11 -0
- clauz3-0.1.0/examples/bank/cases/max_spend_branch_pass.py +13 -0
- clauz3-0.1.0/examples/bank/cases/max_spend_fail.py +11 -0
- clauz3-0.1.0/examples/bank/cases/max_spend_pass.py +11 -0
- clauz3-0.1.0/examples/bank/cases/negative_amount_fail.py +10 -0
- clauz3-0.1.0/examples/bank/cases/only_account_fail.py +10 -0
- clauz3-0.1.0/examples/bank/cases/only_account_pass.py +11 -0
- clauz3-0.1.0/examples/bank/tools/bank/trusted/contracts.py +17 -0
- clauz3-0.1.0/examples/bank/tools/bank/trusted/effects.py +11 -0
- clauz3-0.1.0/examples/email/.claude/settings.json +11 -0
- clauz3-0.1.0/examples/email/AGENTS.md +92 -0
- clauz3-0.1.0/examples/email/CLAUDE.md +1 -0
- clauz3-0.1.0/examples/email/Justfile +87 -0
- clauz3-0.1.0/examples/email/cases/at_most_two_fail.py +12 -0
- clauz3-0.1.0/examples/email/cases/at_most_two_pass.py +11 -0
- clauz3-0.1.0/examples/email/cases/bob_at_most_two_branch_pass.py +15 -0
- clauz3-0.1.0/examples/email/cases/bob_at_most_two_fail.py +13 -0
- clauz3-0.1.0/examples/email/cases/bob_at_most_two_pass.py +12 -0
- clauz3-0.1.0/examples/email/cases/content_length_branch_pass.py +13 -0
- clauz3-0.1.0/examples/email/cases/content_length_fail.py +10 -0
- clauz3-0.1.0/examples/email/cases/content_length_pass.py +11 -0
- clauz3-0.1.0/examples/email/cases/dead_branch_pass.py +11 -0
- clauz3-0.1.0/examples/email/cases/helper_fail.py +14 -0
- clauz3-0.1.0/examples/email/cases/helper_pass.py +14 -0
- clauz3-0.1.0/examples/email/cases/no_guarantees_pass.py +12 -0
- clauz3-0.1.0/examples/email/cases/nobody_emailed_twice_fail.py +15 -0
- clauz3-0.1.0/examples/email/cases/none_fail.py +10 -0
- clauz3-0.1.0/examples/email/cases/none_pass.py +9 -0
- clauz3-0.1.0/examples/email/cases/only_bob_fail.py +10 -0
- clauz3-0.1.0/examples/email/cases/only_bob_pass.py +10 -0
- clauz3-0.1.0/examples/email/cases/precondition_fail.py +10 -0
- clauz3-0.1.0/examples/email/cases/same_content_branch_pass.py +15 -0
- clauz3-0.1.0/examples/email/cases/same_content_fail.py +11 -0
- clauz3-0.1.0/examples/email/cases/same_content_pass.py +11 -0
- clauz3-0.1.0/examples/email/cases/unique_recipients_branch_pass.py +13 -0
- clauz3-0.1.0/examples/email/cases/unique_recipients_fail.py +11 -0
- clauz3-0.1.0/examples/email/cases/unique_recipients_pass.py +11 -0
- clauz3-0.1.0/examples/email/tools/email/trusted/contracts.py +56 -0
- clauz3-0.1.0/examples/email/tools/email/trusted/effects.py +15 -0
- clauz3-0.1.0/examples/email/tools/email/trusted/policy.py +7 -0
- clauz3-0.1.0/examples/email-from-db/.claude/settings.json +11 -0
- clauz3-0.1.0/examples/email-from-db/AGENTS.md +50 -0
- clauz3-0.1.0/examples/email-from-db/CLAUDE.md +1 -0
- clauz3-0.1.0/examples/email-from-db/Justfile +28 -0
- clauz3-0.1.0/examples/email-from-db/cases/all_trivial_loop_pass.py +10 -0
- clauz3-0.1.0/examples/email-from-db/cases/count_pass.py +10 -0
- clauz3-0.1.0/examples/email-from-db/cases/count_too_tight_fail.py +12 -0
- clauz3-0.1.0/examples/email-from-db/cases/email_loop_fail.py +10 -0
- clauz3-0.1.0/examples/email-from-db/cases/literal_address_fail.py +10 -0
- clauz3-0.1.0/examples/email-from-db/cases/mixed_source_fail.py +12 -0
- clauz3-0.1.0/examples/email-from-db/cases/newsletter_pass.py +12 -0
- clauz3-0.1.0/examples/email-from-db/cases/no_emails_with_loop_pass.py +9 -0
- clauz3-0.1.0/examples/email-from-db/cases/unique_recipients_loop_fail.py +10 -0
- clauz3-0.1.0/examples/email-from-db/cases/wrong_column_fail.py +11 -0
- clauz3-0.1.0/examples/email-from-db/tools/db/trusted/contracts.py +71 -0
- clauz3-0.1.0/examples/email-from-db/tools/db/trusted/effects.py +19 -0
- clauz3-0.1.0/examples/email-from-db/tools/db/trusted/schemas.py +8 -0
- clauz3-0.1.0/examples/email-from-db/users.csv +5 -0
- clauz3-0.1.0/extensions/clauz3/index.ts +319 -0
- clauz3-0.1.0/extensions/clauz3/package.json +9 -0
- clauz3-0.1.0/mkdocs.yml +113 -0
- clauz3-0.1.0/pyproject.toml +64 -0
- clauz3-0.1.0/skills/clauz3/SKILL.md +32 -0
- clauz3-0.1.0/src/clauz3/__init__.py +42 -0
- clauz3-0.1.0/src/clauz3/_vendor/__init__.py +1 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/LICENSE +19 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/__init__.py +20 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_annotations.py +144 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_ast.py +46 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_cached_property.py +28 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_context/__init__.py +14 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_context/_context.py +118 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_context/_layer.py +69 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_context/_quantifier.py +23 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_context/_scope.py +43 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_context/_trace.py +30 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_eval_contracts.py +105 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_eval_expr.py +420 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_eval_stmt.py +340 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_exceptions.py +10 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_funcs/__init__.py +7 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_funcs/_builtins.py +173 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_funcs/_math.py +120 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_funcs/_os_path.py +29 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_funcs/_random.py +49 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_funcs/_re.py +38 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_funcs/_registry.py +23 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_goal.py +18 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_model.py +61 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/__init__.py +49 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_bool.py +130 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_dict.py +257 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_float.py +361 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_func.py +303 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_funcs.py +53 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_int.py +269 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_lambda.py +32 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_list.py +148 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_method.py +58 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_methods.py +57 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_pattern.py +140 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_proxy.py +346 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_registry.py +54 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_row.py +188 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_set.py +291 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_str.py +222 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_type_factory.py +36 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_proxies/_var_tuple.py +250 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_registry.py +37 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_theorem.py +290 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/_types.py +6 -0
- clauz3-0.1.0/src/clauz3/_vendor/deal_solver/py.typed +0 -0
- clauz3-0.1.0/src/clauz3/approval.py +261 -0
- clauz3-0.1.0/src/clauz3/approval_service.py +550 -0
- clauz3-0.1.0/src/clauz3/cli.py +387 -0
- clauz3-0.1.0/src/clauz3/install.py +314 -0
- clauz3-0.1.0/src/clauz3/policy.py +210 -0
- clauz3-0.1.0/src/clauz3/prove.py +13 -0
- clauz3-0.1.0/src/clauz3/prover.py +287 -0
- clauz3-0.1.0/src/clauz3/row.py +142 -0
- clauz3-0.1.0/src/clauz3/runner.py +362 -0
- clauz3-0.1.0/src/clauz3/spec.py +788 -0
- clauz3-0.1.0/src/clauz3/stdlib/README.md +48 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/README.md +75 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/Justfile +47 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/never_read_under_fail.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/never_read_under_pass.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/never_write_under_fail.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/never_write_under_pass.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/only_read_under_pass.py +11 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/only_write_under_branch_pass.py +13 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/only_write_under_fail.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/only_write_under_pass.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/read_only_fail.py +11 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/read_only_pass.py +11 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/writes_at_most_fail.py +11 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tests/cases/writes_at_most_pass.py +11 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tools/filesystem/trusted/contracts.py +61 -0
- clauz3-0.1.0/src/clauz3/stdlib/filesystem/tools/filesystem/trusted/effects.py +31 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/README.md +73 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/Justfile +36 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/cases/never_read_under_fail.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/cases/never_read_under_pass.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/cases/only_pattern_fail.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/cases/only_pattern_pass.py +11 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/cases/only_read_under_fail.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/cases/only_read_under_pass.py +10 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/cases/searches_at_most_fail.py +11 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tests/cases/searches_at_most_pass.py +11 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tools/grep/trusted/contracts.py +46 -0
- clauz3-0.1.0/src/clauz3/stdlib/grep/tools/grep/trusted/effects.py +22 -0
- clauz3-0.1.0/tests/conftest.py +13 -0
- clauz3-0.1.0/tests/fixtures/loop_email/__init__.py +0 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/addresses_from_literal_fail.py +10 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/addresses_from_mixed_source_fail.py +12 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/addresses_from_users_email_pass.py +11 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/addresses_from_wrong_column_fail.py +11 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/all_trivial_loop_pass.py +11 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/count_too_tight_fail.py +13 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/count_under_branch_fail.py +11 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/count_under_pass.py +11 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/distinct_over_loop_fail.py +11 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/empty_loop_fail.py +11 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/empty_no_send_pass.py +10 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/precondition_over_loop_fail.py +9 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/shares_value_over_loop_fail.py +10 -0
- clauz3-0.1.0/tests/fixtures/loop_email/cases/sum_selector_depends_on_row_fail.py +11 -0
- clauz3-0.1.0/tests/fixtures/loop_email/qtrusted/__init__.py +0 -0
- clauz3-0.1.0/tests/fixtures/loop_email/qtrusted/contracts.py +51 -0
- clauz3-0.1.0/tests/fixtures/loop_email/qtrusted/effects.py +45 -0
- clauz3-0.1.0/tests/fixtures/loop_email/qtrusted/rows.py +11 -0
- clauz3-0.1.0/tests/test_approval_service.py +288 -0
- clauz3-0.1.0/tests/test_bank_prover.py +40 -0
- clauz3-0.1.0/tests/test_cli.py +123 -0
- clauz3-0.1.0/tests/test_column_ref.py +83 -0
- clauz3-0.1.0/tests/test_coverage.py +103 -0
- clauz3-0.1.0/tests/test_email_prover.py +64 -0
- clauz3-0.1.0/tests/test_for_loop.py +268 -0
- clauz3-0.1.0/tests/test_import.py +5 -0
- clauz3-0.1.0/tests/test_install.py +116 -0
- clauz3-0.1.0/tests/test_model.py +75 -0
- clauz3-0.1.0/tests/test_quantified_facts.py +100 -0
- clauz3-0.1.0/tests/test_quantified_relations.py +119 -0
- clauz3-0.1.0/tests/test_relation_lambdas.py +51 -0
- clauz3-0.1.0/tests/test_required.py +101 -0
- clauz3-0.1.0/tests/test_row_proxy.py +216 -0
- clauz3-0.1.0/tests/test_run.py +231 -0
- clauz3-0.1.0/tests/test_stdlib.py +114 -0
- clauz3-0.1.0/uv.lock +1180 -0
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Deploy docs
|
|
3
|
+
|
|
4
|
+
on: # yamllint disable-line rule:truthy
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
contents: read
|
|
11
|
+
pages: write
|
|
12
|
+
id-token: write
|
|
13
|
+
|
|
14
|
+
concurrency:
|
|
15
|
+
group: pages
|
|
16
|
+
cancel-in-progress: false
|
|
17
|
+
|
|
18
|
+
jobs:
|
|
19
|
+
build:
|
|
20
|
+
runs-on: ubuntu-latest
|
|
21
|
+
steps:
|
|
22
|
+
- name: Check out repository
|
|
23
|
+
uses: actions/checkout@v4.2.2
|
|
24
|
+
with:
|
|
25
|
+
persist-credentials: false
|
|
26
|
+
|
|
27
|
+
- name: Install uv
|
|
28
|
+
uses: astral-sh/setup-uv@v6.4.3
|
|
29
|
+
with:
|
|
30
|
+
python-version: "3.12"
|
|
31
|
+
enable-cache: true
|
|
32
|
+
cache-dependency-glob: "uv.lock"
|
|
33
|
+
|
|
34
|
+
- name: Install docs dependencies
|
|
35
|
+
run: uv sync --group docs
|
|
36
|
+
|
|
37
|
+
- name: Build site
|
|
38
|
+
run: uv run --group docs mkdocs build --strict
|
|
39
|
+
|
|
40
|
+
- name: Upload Pages artifact
|
|
41
|
+
uses: actions/upload-pages-artifact@v3
|
|
42
|
+
with:
|
|
43
|
+
path: site
|
|
44
|
+
|
|
45
|
+
deploy:
|
|
46
|
+
needs: build
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
environment:
|
|
49
|
+
name: github-pages
|
|
50
|
+
url: ${{ steps.deployment.outputs.page_url }}
|
|
51
|
+
steps:
|
|
52
|
+
- name: Deploy to GitHub Pages
|
|
53
|
+
id: deployment
|
|
54
|
+
uses: actions/deploy-pages@v4
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# Built from:
|
|
2
|
+
# https://docs.github.com/en/actions/guides/building-and-testing-python
|
|
3
|
+
---
|
|
4
|
+
name: Build and test
|
|
5
|
+
|
|
6
|
+
on: # yamllint disable-line rule:truthy
|
|
7
|
+
push:
|
|
8
|
+
branches: [main]
|
|
9
|
+
pull_request:
|
|
10
|
+
|
|
11
|
+
env:
|
|
12
|
+
FORCE_COLOR: "1" # Make tools pretty.
|
|
13
|
+
|
|
14
|
+
#permissions: {}
|
|
15
|
+
|
|
16
|
+
jobs:
|
|
17
|
+
test:
|
|
18
|
+
|
|
19
|
+
runs-on: ubuntu-latest
|
|
20
|
+
strategy:
|
|
21
|
+
matrix:
|
|
22
|
+
python-version: ["3.11", "3.14"]
|
|
23
|
+
fail-fast: false
|
|
24
|
+
|
|
25
|
+
steps:
|
|
26
|
+
|
|
27
|
+
# https://github.com/actions/checkout
|
|
28
|
+
- name: Check out repository
|
|
29
|
+
uses: actions/checkout@v4.2.2
|
|
30
|
+
with:
|
|
31
|
+
persist-credentials: false
|
|
32
|
+
|
|
33
|
+
# https://github.com/astral-sh/setup-uv
|
|
34
|
+
- name: Install uv
|
|
35
|
+
uses: astral-sh/setup-uv@v6.4.3
|
|
36
|
+
with:
|
|
37
|
+
python-version: ${{ matrix.python-version }}
|
|
38
|
+
enable-cache: true
|
|
39
|
+
cache-dependency-glob: "uv.lock"
|
|
40
|
+
|
|
41
|
+
# https://github.com/actions/setup-python
|
|
42
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
43
|
+
uses: actions/setup-python@v5.6.0
|
|
44
|
+
with:
|
|
45
|
+
python-version: ${{ matrix.python-version }}
|
|
46
|
+
|
|
47
|
+
- name: Install just
|
|
48
|
+
run: |
|
|
49
|
+
uv tool install rust-just
|
|
50
|
+
|
|
51
|
+
- name: Install project
|
|
52
|
+
run: uv sync --dev
|
|
53
|
+
|
|
54
|
+
- name: Run test suite
|
|
55
|
+
run: just test
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: Release to PyPI
|
|
3
|
+
|
|
4
|
+
on: # yamllint disable-line rule:truthy
|
|
5
|
+
push:
|
|
6
|
+
tags: ['v*']
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
build:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- name: Check out repository
|
|
14
|
+
uses: actions/checkout@v4.2.2
|
|
15
|
+
with:
|
|
16
|
+
persist-credentials: false
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v6.4.3
|
|
20
|
+
with:
|
|
21
|
+
python-version: "3.12"
|
|
22
|
+
enable-cache: true
|
|
23
|
+
cache-dependency-glob: "uv.lock"
|
|
24
|
+
|
|
25
|
+
- name: Build distributions
|
|
26
|
+
run: uv build
|
|
27
|
+
|
|
28
|
+
- name: Upload dist artifacts
|
|
29
|
+
uses: actions/upload-artifact@v4
|
|
30
|
+
with:
|
|
31
|
+
name: dist
|
|
32
|
+
path: dist/
|
|
33
|
+
|
|
34
|
+
publish:
|
|
35
|
+
needs: build
|
|
36
|
+
runs-on: ubuntu-latest
|
|
37
|
+
environment:
|
|
38
|
+
name: pypi
|
|
39
|
+
url: https://pypi.org/p/clauz3
|
|
40
|
+
permissions:
|
|
41
|
+
id-token: write
|
|
42
|
+
steps:
|
|
43
|
+
- name: Download dist artifacts
|
|
44
|
+
uses: actions/download-artifact@v4
|
|
45
|
+
with:
|
|
46
|
+
name: dist
|
|
47
|
+
path: dist/
|
|
48
|
+
|
|
49
|
+
- name: Publish to PyPI (trusted publishing)
|
|
50
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
clauz3-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.11
|
clauz3-0.1.0/AGENTS.md
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
# Repository Guidelines
|
|
2
|
+
|
|
3
|
+
## Project Structure & Module Organization
|
|
4
|
+
|
|
5
|
+
`src/clauz3/` contains the CLI, prover, contract-spec DSL, and vendored
|
|
6
|
+
`deal_solver` code under `_vendor/`. Tests live in `tests/`. Worked examples
|
|
7
|
+
live in `examples/<domain>/`: each has `cases/` for agent-authored proof
|
|
8
|
+
fixtures and `tools/<domain>/trusted/` for trusted effects and contracts.
|
|
9
|
+
Design notes are in `docs/` and `docs/todos/`. CI is defined in
|
|
10
|
+
`.github/workflows/main.yaml`.
|
|
11
|
+
|
|
12
|
+
## Build, Test, and Development Commands
|
|
13
|
+
|
|
14
|
+
- `uv sync --dev`: install the project and development tools.
|
|
15
|
+
- `just test`: run pytest, ruff, mypy, and every example Justfile.
|
|
16
|
+
- `just check`: run ruff formatting/linting and strict mypy.
|
|
17
|
+
- `just pytest`: run only the pytest suite.
|
|
18
|
+
- `just examples`: run example proofs only.
|
|
19
|
+
- `uv run clauz3 prove --trusted-root tools/email/trusted cases/only_bob_pass.py`
|
|
20
|
+
from an example directory: prove one entry file against a trusted root.
|
|
21
|
+
|
|
22
|
+
## Coding Style & Naming Conventions
|
|
23
|
+
|
|
24
|
+
Use Python 3.11+ syntax and 4-space indentation. Ruff enforces linting,
|
|
25
|
+
formatting, import order, and selected modernization rules. Mypy runs in strict
|
|
26
|
+
mode for `src`, `tests`, and `examples`; `_vendor` is excluded for now. Keep
|
|
27
|
+
public package imports as `clauz3`, not the repository name. Trusted example
|
|
28
|
+
modules should use `tools/<domain>/trusted/{effects.py,contracts.py}`.
|
|
29
|
+
|
|
30
|
+
## Testing Guidelines
|
|
31
|
+
|
|
32
|
+
Tests use pytest and are named `tests/test_*.py`. Add focused pytest cases for
|
|
33
|
+
core behavior and example case files for proof behavior. Cases under
|
|
34
|
+
`examples/*/cases/` should be valid Python and remain mypy-clean. Example
|
|
35
|
+
Justfiles should include both expected-pass and expected-fail proof commands.
|
|
36
|
+
Run `just test` before pushing.
|
|
37
|
+
|
|
38
|
+
## Commit & Pull Request Guidelines
|
|
39
|
+
|
|
40
|
+
Recent commits use short imperative subjects, for example `Add CI and scalable
|
|
41
|
+
mypy roots` or `Rename package to clauz3`. Keep commits scoped. PRs should
|
|
42
|
+
include a concise summary, user-visible impact, and validation results such as
|
|
43
|
+
`just test`. Link issues when applicable. Screenshots are not needed unless a
|
|
44
|
+
future change adds UI.
|
|
45
|
+
|
|
46
|
+
## Trust Boundary Notes
|
|
47
|
+
|
|
48
|
+
Only code under trusted roots should define `@deal.has(...)` effects or
|
|
49
|
+
`@contract` helpers. Agent-authored entry files should import trusted tools and
|
|
50
|
+
state guarantees with `@clauz3.guarantee(...)`. Do not make untrusted code a
|
|
51
|
+
trusted boundary just to satisfy a proof.
|
clauz3-0.1.0/Justfile
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
set shell := ["bash", "-cu"]
|
|
2
|
+
|
|
3
|
+
example-justfiles := `find examples -mindepth 2 -maxdepth 2 -name Justfile | sort | paste -sd' ' -`
|
|
4
|
+
example-roots := `find examples -mindepth 1 -maxdepth 1 -type d | sort | paste -sd: -`
|
|
5
|
+
fixture-roots := `find tests/fixtures -mindepth 1 -maxdepth 1 -type d | sort | paste -sd: -`
|
|
6
|
+
stdlib-justfiles := `find src/clauz3/stdlib -name Justfile | sort | paste -sd' ' -`
|
|
7
|
+
|
|
8
|
+
test: pytest check examples stdlib
|
|
9
|
+
|
|
10
|
+
pytest:
|
|
11
|
+
uv run pytest
|
|
12
|
+
|
|
13
|
+
check:
|
|
14
|
+
uv run ruff check .
|
|
15
|
+
uv run ruff format --check .
|
|
16
|
+
MYPYPATH="src:{{example-roots}}:{{fixture-roots}}" uv run mypy src tests examples
|
|
17
|
+
|
|
18
|
+
examples:
|
|
19
|
+
for justfile in {{example-justfiles}}; do \
|
|
20
|
+
just -f "$justfile" test; \
|
|
21
|
+
done
|
|
22
|
+
|
|
23
|
+
stdlib:
|
|
24
|
+
for justfile in {{stdlib-justfiles}}; do \
|
|
25
|
+
just -f "$justfile" test; \
|
|
26
|
+
done
|
|
27
|
+
|
|
28
|
+
docs:
|
|
29
|
+
uv run --group docs mkdocs build --strict
|
|
30
|
+
|
|
31
|
+
serve-docs port="8077":
|
|
32
|
+
uv run --group docs mkdocs serve --dev-addr 127.0.0.1:{{port}}
|
clauz3-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: clauz3
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Static contract experiments for agent-authored Python
|
|
5
|
+
Requires-Python: >=3.11
|
|
6
|
+
Requires-Dist: astroid>=4.1.2
|
|
7
|
+
Requires-Dist: deal>=4.24.6
|
|
8
|
+
Requires-Dist: fastapi>=0.136.3
|
|
9
|
+
Requires-Dist: uvicorn>=0.48.0
|
|
10
|
+
Requires-Dist: z3-solver>=4.16.0.0
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# clauz3
|
|
14
|
+
|
|
15
|
+
Static contracts for agent-authored Python.
|
|
16
|
+
|
|
17
|
+
`clauz3` experiments with a different permission surface for agents: the
|
|
18
|
+
agent writes a small Python program, attaches a contract describing its trusted
|
|
19
|
+
side effects, and a static prover checks the contract before anything runs.
|
|
20
|
+
|
|
21
|
+
The contract is the thing the user should be asked to accept. The program is
|
|
22
|
+
still available for inspection, but a user should not have to read every branch
|
|
23
|
+
to answer questions like:
|
|
24
|
+
|
|
25
|
+
- Will this email anyone other than Bob?
|
|
26
|
+
- Will this email the same person twice?
|
|
27
|
+
- Will this withdraw more than $5 total?
|
|
28
|
+
- Will this write outside a sandbox?
|
|
29
|
+
|
|
30
|
+
## Current Shape
|
|
31
|
+
|
|
32
|
+
Projects are split into three layers:
|
|
33
|
+
|
|
34
|
+
- trusted roots such as `tools/email/trusted/`: small audited modules
|
|
35
|
+
containing both side-effecting functions and reusable domain contracts. These
|
|
36
|
+
are the environment contract: the prover trusts their signatures,
|
|
37
|
+
`@deal.has(...)` markers, `@deal.pre(...)` preconditions, and `@contract`
|
|
38
|
+
helper definitions.
|
|
39
|
+
- agent-authored code: ordinary Python that imports trusted functions and adds
|
|
40
|
+
`@clauz3.guarantee(...)` decorators to the function being proved.
|
|
41
|
+
|
|
42
|
+
Trusted calls bottom out into symbolic effect facts. For example:
|
|
43
|
+
|
|
44
|
+
```python
|
|
45
|
+
@deal.pre(lambda addr, msg: "@" in addr)
|
|
46
|
+
@deal.has("trusted")
|
|
47
|
+
def send_email(addr: str, msg: str) -> None:
|
|
48
|
+
...
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
A call to `send_email("bob@example.com", "hi")` creates a fact whose relation
|
|
52
|
+
name is `send_email`, whose fields are `addr` and `msg`, and whose condition is
|
|
53
|
+
the branch condition under which the call is reachable.
|
|
54
|
+
|
|
55
|
+
Domain logic can query those generated facts:
|
|
56
|
+
|
|
57
|
+
```python
|
|
58
|
+
from clauz3.spec import ContractSpec, contract, effect
|
|
59
|
+
from clauz3.spec import no_guarantees as core_no_guarantees
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
Email = effect("send_email")
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
@contract
|
|
66
|
+
def only(addresses: list[str]) -> ContractSpec:
|
|
67
|
+
return Email.all(lambda e: e.addr in addresses)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
@contract
|
|
71
|
+
def no_guarantees() -> ContractSpec:
|
|
72
|
+
return core_no_guarantees()
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
@contract
|
|
76
|
+
def unique_recipients() -> ContractSpec:
|
|
77
|
+
return Email.distinct(lambda e: e.addr)
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
Agent code then states guarantees in terms of that vocabulary:
|
|
81
|
+
|
|
82
|
+
```python
|
|
83
|
+
import clauz3
|
|
84
|
+
from tools.email.trusted import contracts as emails
|
|
85
|
+
from tools.email.trusted.effects import send_email
|
|
86
|
+
|
|
87
|
+
|
|
88
|
+
@clauz3.guarantee(emails.only(["bob@example.com"]))
|
|
89
|
+
@clauz3.guarantee(emails.unique_recipients())
|
|
90
|
+
def main() -> None:
|
|
91
|
+
send_email("bob@example.com", "hi")
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Run the prover:
|
|
95
|
+
|
|
96
|
+
```bash
|
|
97
|
+
cd examples/email
|
|
98
|
+
uv run clauz3 prove \
|
|
99
|
+
--trusted-root tools/email/trusted \
|
|
100
|
+
cases/only_bob_pass.py
|
|
101
|
+
```
|
|
102
|
+
|
|
103
|
+
For programs that combine domains, either repeat `--trusted-root` or pass
|
|
104
|
+
several roots with `--trusted-roots`:
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
uv run clauz3 prove plan.py \
|
|
108
|
+
--trusted-roots tools/email/trusted tools/db/trusted
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Installing a trusted layer
|
|
112
|
+
|
|
113
|
+
To start a new project from an existing one, copy its trusted `tools/` layer
|
|
114
|
+
with `clauz3 install`. It takes a local path to a project (or directly to a
|
|
115
|
+
`tools/` folder) and copies each `tools/<domain>/` into the current directory:
|
|
116
|
+
|
|
117
|
+
```bash
|
|
118
|
+
clauz3 install /path/to/repo/examples/email
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
Pass `--into <dir>` to target a different destination, `--force` to overwrite an
|
|
122
|
+
existing layer, and `--skills` to also generate
|
|
123
|
+
`agents/skills/<domain>/SKILL.md` describing the installed effects and
|
|
124
|
+
contracts:
|
|
125
|
+
|
|
126
|
+
```bash
|
|
127
|
+
clauz3 install /path/to/repo/examples/email --into my-project --skills
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
For now this is a trivial filesystem copy. Future work will add signing so a
|
|
131
|
+
user has guarantees that the installed layer is untouched.
|
|
132
|
+
|
|
133
|
+
## Standard library tools
|
|
134
|
+
|
|
135
|
+
`clauz3` ships a small set of **real (non-mock) tools** under
|
|
136
|
+
[`src/clauz3/stdlib`](src/clauz3/stdlib). After `pip install clauz3`, install
|
|
137
|
+
one into the current repo with the `stdlib:` scheme:
|
|
138
|
+
|
|
139
|
+
```bash
|
|
140
|
+
clauz3 install stdlib:filesystem
|
|
141
|
+
clauz3 install stdlib:grep
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
The bundled tools are located with `importlib.resources`, so this works the
|
|
145
|
+
same from a source checkout or an installed wheel. (A bare `clauz3 install
|
|
146
|
+
filesystem` also works as a shorthand.)
|
|
147
|
+
|
|
148
|
+
| Tool | Effects | Headline contracts |
|
|
149
|
+
| --- | --- | --- |
|
|
150
|
+
| [`filesystem`](src/clauz3/stdlib/filesystem) | `read_file`, `write_file` | `read_only`, `only_write_under`, `never_read_under`, `writes_at_most` |
|
|
151
|
+
| [`grep`](src/clauz3/stdlib/grep) | `grep` (imports `filesystem`) | `only_read_under`, `never_read_under`, `searches_at_most`, `only_pattern` |
|
|
152
|
+
|
|
153
|
+
These differ from the `examples/` layers in two ways: their effect bodies do
|
|
154
|
+
real work (so the prover skips them but `clauz3 run` executes them), and their
|
|
155
|
+
proof cases live under `tests/cases/` with a `tests/Justfile` rather than at the
|
|
156
|
+
top level. `just stdlib` proves them all.
|
|
157
|
+
|
|
158
|
+
## Examples
|
|
159
|
+
|
|
160
|
+
The repo currently has three worked examples:
|
|
161
|
+
|
|
162
|
+
| Example | Contracts | What it demonstrates |
|
|
163
|
+
| --- | --- | --- |
|
|
164
|
+
| [`examples/email`](examples/email) | `emails.only`, `emails.none`, `emails.no_guarantees`, `emails.unique_recipients`, `emails.content_length_at_most` | allowlists, explicit absence of guarantees, absence of effects, pairwise uniqueness, string length bounds |
|
|
165
|
+
| [`examples/bank`](examples/bank) | `bank.max_spend`, `bank.only_account` | numeric aggregation, field equality, and fixed-bound loop unrolling over trusted calls |
|
|
166
|
+
| [`examples/email-from-db`](examples/email-from-db) | `emails.addresses_from`, `db.only_table`, `db.only_where` | for-loops over trusted query returns, column-binding constraints |
|
|
167
|
+
|
|
168
|
+
All examples use generic effect relations inferred from trusted function
|
|
169
|
+
signatures. There is no email-specific, bank-specific, or database-specific logic in the core.
|
|
170
|
+
|
|
171
|
+
## Status
|
|
172
|
+
|
|
173
|
+
This is experimental. The current prover vendors and extends `deal-solver`.
|
|
174
|
+
Implemented pieces include:
|
|
175
|
+
|
|
176
|
+
- `clauz3.guarantee(...)`, a no-op runtime decorator consumed by the prover.
|
|
177
|
+
- trusted-call fact recording at `@deal.has(...)` boundaries.
|
|
178
|
+
- `clauz3.spec.effect(...)` for relation-style queries over trusted facts.
|
|
179
|
+
- relation primitives: `no_guarantees`, `all`, `empty`, `where`, `count`,
|
|
180
|
+
`distinct`, numeric `sum`, and `shares_value`.
|
|
181
|
+
- `clauz3 prove` for proving examples from the CLI.
|
|
182
|
+
- `clauz3 install` for copying a trusted `tools/` layer from a local path or a
|
|
183
|
+
bundled stdlib tool (`stdlib:filesystem`, `stdlib:grep`), optionally
|
|
184
|
+
generating `agents/skills/<domain>/SKILL.md` stubs.
|
|
185
|
+
- `clauz3 run` for proving a complete inline program, submitting an approval
|
|
186
|
+
request to an externally configured approval service, and executing `main`
|
|
187
|
+
only after an approval receipt is returned.
|
|
188
|
+
- `clauz3 approval-service` for starting a simple localhost FastAPI approval
|
|
189
|
+
service with REST endpoints and a browser UI for user decisions.
|
|
190
|
+
- `clauz3 mock-approval-service` for config-driven tests and local demos.
|
|
191
|
+
- For-loops over `list[Row]`-returning trusted calls, with column-binding
|
|
192
|
+
contracts via `UserRow.email` markers. See
|
|
193
|
+
[docs/explanation/symbolic-iteration.md](docs/explanation/symbolic-iteration.md).
|
|
194
|
+
- Domain coverage policies declared in a trusted-root `policy.py`: contracts a
|
|
195
|
+
domain `recommended`s are flagged in the approval UI when a used domain is
|
|
196
|
+
under-constrained, and contracts it marks `required` are conjoined into the
|
|
197
|
+
proof and rejected if unmet. See
|
|
198
|
+
[docs/reference/coverage-policies.md](docs/reference/coverage-policies.md).
|
|
199
|
+
|
|
200
|
+
Important limitations:
|
|
201
|
+
|
|
202
|
+
- Contract helper functions are still executed as builder functions. Their
|
|
203
|
+
lambda bodies are parsed as a small expression subset, but the helper body
|
|
204
|
+
itself is not yet fully AST-validated.
|
|
205
|
+
- Runtime receipt enforcement in trusted functions is not implemented yet; the
|
|
206
|
+
first `run` slice requires a receipt before execution and exposes it to the
|
|
207
|
+
process as `CLAUZ3_APPROVAL_RECEIPT`.
|
|
208
|
+
- `clauz3 run` includes source checks and reduced builtins, but it is not a
|
|
209
|
+
hardened Python or OS sandbox. The agent harness must still restrict execution
|
|
210
|
+
to the `clauz3` command path.
|
|
211
|
+
- The relation language is intentionally small. Richer string predicates,
|
|
212
|
+
richer aggregates, Datalog-style rules, and deterministic
|
|
213
|
+
natural language summaries are future work.
|
|
214
|
+
|
|
215
|
+
More detail:
|
|
216
|
+
|
|
217
|
+
- [FAQ and terminology](docs/explanation/faq.md)
|
|
218
|
+
- [Concepts](docs/explanation/concepts.md)
|
|
219
|
+
- [Background and related work](docs/explanation/background.md)
|
|
220
|
+
- [Effect specs](docs/reference/effect-specs.md)
|
|
221
|
+
- [Coverage policies](docs/reference/coverage-policies.md)
|
|
222
|
+
- [Symbolic iteration](docs/explanation/symbolic-iteration.md)
|
|
223
|
+
- [ClauZ3 Python subset](docs/reference/python-subset.md)
|
|
224
|
+
- [Approval service](docs/how-to/approval-service.md)
|
|
225
|
+
- [User approval dialog design](docs/todos/user-approval-dialog.md)
|
|
226
|
+
- [Ideas](docs/todos/ideas.md)
|
|
227
|
+
|
|
228
|
+
## Development
|
|
229
|
+
|
|
230
|
+
```bash
|
|
231
|
+
uv sync --dev
|
|
232
|
+
just test
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
## Built on
|
|
236
|
+
|
|
237
|
+
<p>
|
|
238
|
+
<a href="https://deal.readthedocs.io/">
|
|
239
|
+
<img src="https://raw.githubusercontent.com/life4/deal/master/logo.png"
|
|
240
|
+
alt="deal logo" height="48" align="middle">
|
|
241
|
+
</a>
|
|
242
|
+
|
|
243
|
+
<a href="https://github.com/Z3Prover/z3">
|
|
244
|
+
<img src="https://github.com/Z3Prover.png" alt="Z3 logo" height="48"
|
|
245
|
+
align="middle" style="border-radius: 8px;">
|
|
246
|
+
</a>
|
|
247
|
+
</p>
|
|
248
|
+
|
|
249
|
+
ClauZ3 layers on two upstream projects and would not exist without them:
|
|
250
|
+
|
|
251
|
+
- **[deal](https://deal.readthedocs.io/)** — the Python runtime contract
|
|
252
|
+
engine whose `@deal.pre`, `@deal.post`, and `@deal.has` decorators define
|
|
253
|
+
the trusted-layer vocabulary. ClauZ3 reads the same decorators and
|
|
254
|
+
discharges them statically; in runtime-only mode, deal enforces them at
|
|
255
|
+
execution. See
|
|
256
|
+
[Static proof vs runtime](docs/explanation/concepts.md#static-proof-vs-runtime)
|
|
257
|
+
for how the two layers relate.
|
|
258
|
+
- **[Z3](https://github.com/Z3Prover/z3)** — Microsoft Research's SMT solver,
|
|
259
|
+
the back-end the prover compiles every guarantee into. The vendored
|
|
260
|
+
`deal-solver` machinery is what bridges Python AST and Z3 constraints.
|