analint 0.0.1__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.
- analint-0.0.1/.gitignore +14 -0
- analint-0.0.1/CHANGELOG.md +45 -0
- analint-0.0.1/CONTRIBUTING.md +83 -0
- analint-0.0.1/LICENSE +21 -0
- analint-0.0.1/PKG-INFO +752 -0
- analint-0.0.1/README.md +723 -0
- analint-0.0.1/examples/branch_protection/README.md +40 -0
- analint-0.0.1/examples/branch_protection/spec.py +454 -0
- analint-0.0.1/examples/cloak/README.md +33 -0
- analint-0.0.1/examples/cloak/spec.py +264 -0
- analint-0.0.1/examples/coin/README.md +33 -0
- analint-0.0.1/examples/coin/spec.py +199 -0
- analint-0.0.1/examples/ecommerce/README.md +28 -0
- analint-0.0.1/examples/ecommerce/spec.py +164 -0
- analint-0.0.1/examples/expectations.toml +156 -0
- analint-0.0.1/examples/fulfillment/README.md +33 -0
- analint-0.0.1/examples/fulfillment/__init__.py +0 -0
- analint-0.0.1/examples/fulfillment/actions.py +171 -0
- analint-0.0.1/examples/fulfillment/entities.py +90 -0
- analint-0.0.1/examples/fulfillment/events.py +23 -0
- analint-0.0.1/examples/fulfillment/invariants.py +34 -0
- analint-0.0.1/examples/fulfillment/queries.py +76 -0
- analint-0.0.1/examples/fulfillment/scenarios.py +224 -0
- analint-0.0.1/examples/fulfillment/spec.py +13 -0
- analint-0.0.1/examples/k8s_replicaset/README.md +58 -0
- analint-0.0.1/examples/k8s_replicaset/spec.py +342 -0
- analint-0.0.1/examples/mafia/README.md +31 -0
- analint-0.0.1/examples/mafia/spec.py +441 -0
- analint-0.0.1/examples/oauth/README.md +46 -0
- analint-0.0.1/examples/oauth/__init__.py +1 -0
- analint-0.0.1/examples/oauth/assurance.py +378 -0
- analint-0.0.1/examples/oauth/oauth.qnt +293 -0
- analint-0.0.1/examples/oauth/protocol.py +172 -0
- analint-0.0.1/examples/oauth/spec.py +25 -0
- analint-0.0.1/examples/play.py +134 -0
- analint-0.0.1/examples/sunless_crypt/README.md +34 -0
- analint-0.0.1/examples/sunless_crypt/spec.py +324 -0
- analint-0.0.1/examples/taskboard/README.md +31 -0
- analint-0.0.1/examples/taskboard/__init__.py +0 -0
- analint-0.0.1/examples/taskboard/actions.py +140 -0
- analint-0.0.1/examples/taskboard/entities.py +95 -0
- analint-0.0.1/examples/taskboard/events.py +36 -0
- analint-0.0.1/examples/taskboard/flows.py +39 -0
- analint-0.0.1/examples/taskboard/invariants.py +30 -0
- analint-0.0.1/examples/taskboard/scenarios.py +289 -0
- analint-0.0.1/examples/taskboard/spec.py +12 -0
- analint-0.0.1/examples/trollbridge/README.md +33 -0
- analint-0.0.1/examples/trollbridge/spec.py +165 -0
- analint-0.0.1/pyproject.toml +128 -0
- analint-0.0.1/src/analint/__init__.py +94 -0
- analint-0.0.1/src/analint/cli.py +273 -0
- analint-0.0.1/src/analint/loader/__init__.py +15 -0
- analint-0.0.1/src/analint/loader/discovery.py +17 -0
- analint-0.0.1/src/analint/loader/python_loader.py +242 -0
- analint-0.0.1/src/analint/mcp_server.py +171 -0
- analint-0.0.1/src/analint/models/__init__.py +72 -0
- analint-0.0.1/src/analint/models/action.py +89 -0
- analint-0.0.1/src/analint/models/contract.py +61 -0
- analint-0.0.1/src/analint/models/effect.py +75 -0
- analint-0.0.1/src/analint/models/entity.py +282 -0
- analint-0.0.1/src/analint/models/event.py +35 -0
- analint-0.0.1/src/analint/models/expr.py +108 -0
- analint-0.0.1/src/analint/models/flow.py +59 -0
- analint-0.0.1/src/analint/models/initial.py +30 -0
- analint-0.0.1/src/analint/models/invariant.py +26 -0
- analint-0.0.1/src/analint/models/lifecycle.py +85 -0
- analint-0.0.1/src/analint/models/param.py +402 -0
- analint-0.0.1/src/analint/models/predicate.py +152 -0
- analint-0.0.1/src/analint/models/quantifier.py +280 -0
- analint-0.0.1/src/analint/models/query.py +104 -0
- analint-0.0.1/src/analint/models/root.py +104 -0
- analint-0.0.1/src/analint/models/scenario.py +40 -0
- analint-0.0.1/src/analint/models/scope.py +254 -0
- analint-0.0.1/src/analint/py.typed +0 -0
- analint-0.0.1/src/analint/query.py +438 -0
- analint-0.0.1/src/analint/reporter/__init__.py +12 -0
- analint-0.0.1/src/analint/reporter/base.py +192 -0
- analint-0.0.1/src/analint/reporter/exploration_artifact.py +122 -0
- analint-0.0.1/src/analint/reporter/json_reporter.py +101 -0
- analint-0.0.1/src/analint/reporter/terminal.py +178 -0
- analint-0.0.1/src/analint/validator/__init__.py +3 -0
- analint-0.0.1/src/analint/validator/artifact_builder.py +207 -0
- analint-0.0.1/src/analint/validator/engine.py +333 -0
- analint-0.0.1/src/analint/validator/exploration_service.py +193 -0
- analint-0.0.1/src/analint/validator/explorer.py +1048 -0
- analint-0.0.1/src/analint/validator/flow_runner.py +99 -0
- analint-0.0.1/src/analint/validator/kernel.py +441 -0
- analint-0.0.1/src/analint/validator/rule_checker.py +157 -0
- analint-0.0.1/src/analint/validator/scenario_runner.py +133 -0
- analint-0.0.1/src/analint/validator/state_checks.py +78 -0
- analint-0.0.1/src/analint/validator/structural.py +1057 -0
- analint-0.0.1/tests/__init__.py +0 -0
- analint-0.0.1/tests/fixtures/__init__.py +0 -0
- analint-0.0.1/tests/fixtures/broken_spec.py +45 -0
- analint-0.0.1/tests/fixtures/composed/__init__.py +1 -0
- analint-0.0.1/tests/fixtures/composed/component.py +28 -0
- analint-0.0.1/tests/fixtures/composed/spec.py +16 -0
- analint-0.0.1/tests/fixtures/inconclusive/spec.py +16 -0
- analint-0.0.1/tests/fixtures/multiple_specs.py +4 -0
- analint-0.0.1/tests/fixtures/simple_spec.py +47 -0
- analint-0.0.1/tests/fixtures/warns/spec.py +14 -0
- analint-0.0.1/tests/snapshots/README.md +60 -0
- analint-0.0.1/tests/snapshots/examples.json +1617 -0
- analint-0.0.1/tests/test_characterization.py +156 -0
- analint-0.0.1/tests/test_composition.py +104 -0
- analint-0.0.1/tests/test_create_delete.py +236 -0
- analint-0.0.1/tests/test_example_expectations.py +89 -0
- analint-0.0.1/tests/test_exploration_artifact.py +213 -0
- analint-0.0.1/tests/test_exploration_service.py +156 -0
- analint-0.0.1/tests/test_explorer.py +809 -0
- analint-0.0.1/tests/test_expressions.py +127 -0
- analint-0.0.1/tests/test_flow.py +214 -0
- analint-0.0.1/tests/test_kernel.py +182 -0
- analint-0.0.1/tests/test_loader.py +29 -0
- analint-0.0.1/tests/test_models.py +916 -0
- analint-0.0.1/tests/test_multiplicity.py +268 -0
- analint-0.0.1/tests/test_params.py +167 -0
- analint-0.0.1/tests/test_play_runner.py +70 -0
- analint-0.0.1/tests/test_presence.py +235 -0
- analint-0.0.1/tests/test_quantifiers.py +356 -0
- analint-0.0.1/tests/test_query.py +278 -0
- analint-0.0.1/tests/test_scaling_models.py +41 -0
- analint-0.0.1/tests/test_soundness.py +198 -0
- analint-0.0.1/tests/test_trace.py +139 -0
- analint-0.0.1/tests/test_transition_conformance.py +433 -0
- analint-0.0.1/tests/test_typecheck_probes.py +67 -0
- analint-0.0.1/tests/test_validator.py +86 -0
- analint-0.0.1/tests/test_verdict.py +110 -0
- analint-0.0.1/tests/typecheck_probes/authoring_forms.py +53 -0
- analint-0.0.1/tests/typecheck_probes/negative_forms.py +24 -0
analint-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and the project follows
|
|
5
|
+
[Semantic Versioning](https://semver.org/spec/v2.0.0.html). While the version is
|
|
6
|
+
`0.x` the public API may change between minor releases.
|
|
7
|
+
|
|
8
|
+
## [0.0.1] — 2026-06-21
|
|
9
|
+
|
|
10
|
+
First public release. The engine and CLI are mature and covered by an extensive
|
|
11
|
+
test suite; this release makes them installable and documents their scope.
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- **DSL** for declaring system behaviour in Python: `Entity` with field
|
|
16
|
+
constraints, `Invariant`, `Action` (`pre` / `effect` / `post` / `emits`),
|
|
17
|
+
`Event`, `Lifecycle`, `Scenario`, `Flow`, parameterized actions
|
|
18
|
+
(`Param`), finite quantifiers/aggregates, `Scope` multiplicity, and `Spec` as
|
|
19
|
+
the top-level aggregate.
|
|
20
|
+
- **Validator** with a single transition kernel shared by scenarios, flows, and
|
|
21
|
+
the explorer; structural validation; scenario execution; executable multi-step
|
|
22
|
+
flows.
|
|
23
|
+
- **Bounded reachability engine**: BFS over a finite state graph with reachability
|
|
24
|
+
queries (`Reachable`, `Unreachable`, `AlwaysHolds`, `NoDeadEnd`, `DeadActions`),
|
|
25
|
+
state-diff witness/counterexample traces, and a deterministic
|
|
26
|
+
`analint.exploration/v1` artifact.
|
|
27
|
+
- **CLI** `analint`: `check`, `show`, `affects`, `explore`, `trace`, with
|
|
28
|
+
`--what-if` hypothesis testing, terminal and JSON output, and meaningful exit
|
|
29
|
+
codes.
|
|
30
|
+
- **MCP server** (`analint-mcp`, optional `mcp` extra) exposing the same surface
|
|
31
|
+
to AI agents.
|
|
32
|
+
- **Examples** spanning business analytics, game/narrative rules, and two external
|
|
33
|
+
evidence models (GitHub branch protection, OAuth 2.0 auth-code + PKCE), plus a
|
|
34
|
+
project-sized Kubernetes ReplicaSet dogfood.
|
|
35
|
+
|
|
36
|
+
### Scope and honesty
|
|
37
|
+
|
|
38
|
+
- Verification is **bounded reachability** over a finite state space: it checks
|
|
39
|
+
safety and reachability and reports a three-valued verdict
|
|
40
|
+
(`PASS` / `FAIL` / `INCONCLUSIVE`), preferring `INCONCLUSIVE` / `NOT_CHECKED`
|
|
41
|
+
over a silent pass.
|
|
42
|
+
- It deliberately does **not** model liveness or temporal "eventually"
|
|
43
|
+
properties. This is a scope boundary, not a defect.
|
|
44
|
+
|
|
45
|
+
[0.0.1]: https://github.com/angru/analint/releases/tag/v0.0.1
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# Contributing to analint
|
|
2
|
+
|
|
3
|
+
Thanks for your interest in analint. This is an early public release (`0.0.1`):
|
|
4
|
+
issues, reproductions, and example specs are especially welcome.
|
|
5
|
+
|
|
6
|
+
All new repository content — code, comments, docs, commit messages — is written in
|
|
7
|
+
**English**. (Some historical research notes are in Russian; leave them as-is.)
|
|
8
|
+
|
|
9
|
+
## Development setup
|
|
10
|
+
|
|
11
|
+
analint uses [uv](https://docs.astral.sh/uv/) and targets **Python 3.12+**.
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
git clone https://github.com/angru/analint
|
|
15
|
+
cd analint
|
|
16
|
+
uv sync # create the env and install dev dependencies
|
|
17
|
+
uv run analint examples/ecommerce/ # smoke test
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
## Running the checks
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
uv run pytest # full test suite
|
|
24
|
+
uv run ruff check . # lint
|
|
25
|
+
uv run ruff format --check . # formatting
|
|
26
|
+
uv run ty check # type check (src/)
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
A few specific things to know about the test suite:
|
|
30
|
+
|
|
31
|
+
- `tests/test_characterization.py` is the behavioural regression oracle: a
|
|
32
|
+
committed golden snapshot (`tests/snapshots/examples.json`) of every example's
|
|
33
|
+
verdict, per-scenario results, and per-query graph hashes/traces. If you
|
|
34
|
+
**intentionally** change behaviour, regenerate it — never mechanically, always
|
|
35
|
+
after confirming the new snapshot is correct:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
UPDATE_SNAPSHOT=1 uv run pytest tests/test_characterization.py
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
See `tests/snapshots/README.md` for the regen rule and expected deltas.
|
|
42
|
+
- `tests/test_transition_conformance.py` is the fine-grained kernel gate. Agreed
|
|
43
|
+
semantics stay green; known target changes are `xfail(strict=True)`, so fixing
|
|
44
|
+
one produces an XPASS until its marker is deliberately removed.
|
|
45
|
+
|
|
46
|
+
## Trying the CLI
|
|
47
|
+
|
|
48
|
+
```bash
|
|
49
|
+
uv run analint check . # validate the spec in the cwd
|
|
50
|
+
uv run analint show action <id> -p <spec> # inspect one action
|
|
51
|
+
uv run analint affects <Entity.field> -p <spec> # blast radius of a field
|
|
52
|
+
uv run analint explore -p <spec> # bounded reachability exploration
|
|
53
|
+
uv run analint check . --what-if file.py # test a hypothesis without editing files
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Exit codes: `0` ok · `1` findings · `2` usage · `3` spec failed to load · `4`
|
|
57
|
+
inconclusive (a query exhausted its exploration budget — it proved nothing). JSON
|
|
58
|
+
output carries a three-valued `verdict` (`PASS`/`FAIL`/`INCONCLUSIVE`).
|
|
59
|
+
|
|
60
|
+
## How the project works
|
|
61
|
+
|
|
62
|
+
- **`ROADMAP.md` is the single source of truth** for status and priorities.
|
|
63
|
+
`research/` holds dated design rationale that the roadmap links to;
|
|
64
|
+
`AGENTS.md` is a detailed map of the codebase.
|
|
65
|
+
- The project is **review-gated and fail-closed by design**: a verification
|
|
66
|
+
feature that hides a defect is the worst possible outcome here. Prefer
|
|
67
|
+
`INCONCLUSIVE` / `NOT_CHECKED` over a silent pass. When you add or change a
|
|
68
|
+
verification path, adversarially self-probe it — plant a defect the new path
|
|
69
|
+
should catch and confirm the overall verdict actually goes `FAIL`.
|
|
70
|
+
- Keep changes semantically focused: one behavioural change per commit, with the
|
|
71
|
+
characterization snapshot updated deliberately in the same commit.
|
|
72
|
+
|
|
73
|
+
## Pull requests
|
|
74
|
+
|
|
75
|
+
1. Branch from `main`.
|
|
76
|
+
2. Make the change; add or update tests and (if behaviour changed) the snapshot.
|
|
77
|
+
3. Ensure `pytest`, `ruff`, and `ty` are green.
|
|
78
|
+
4. Open a PR describing **what guarantee changed**, not just the diff.
|
|
79
|
+
|
|
80
|
+
## License
|
|
81
|
+
|
|
82
|
+
By contributing, you agree that your contributions are licensed under the
|
|
83
|
+
project's [MIT License](LICENSE).
|
analint-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 angru
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|