invar-tools 1.2.0__py3-none-any.whl → 1.3.0__py3-none-any.whl

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.
Files changed (89) hide show
  1. invar/__init__.py +1 -0
  2. invar/core/contracts.py +10 -10
  3. invar/core/entry_points.py +105 -32
  4. invar/core/extraction.py +5 -6
  5. invar/core/format_specs.py +1 -2
  6. invar/core/formatter.py +6 -7
  7. invar/core/hypothesis_strategies.py +5 -7
  8. invar/core/inspect.py +1 -1
  9. invar/core/lambda_helpers.py +3 -3
  10. invar/core/models.py +7 -1
  11. invar/core/must_use.py +2 -1
  12. invar/core/parser.py +7 -4
  13. invar/core/postcondition_scope.py +128 -0
  14. invar/core/property_gen.py +8 -5
  15. invar/core/purity.py +3 -3
  16. invar/core/purity_heuristics.py +5 -9
  17. invar/core/references.py +8 -6
  18. invar/core/review_trigger.py +78 -6
  19. invar/core/rule_meta.py +8 -0
  20. invar/core/rules.py +18 -19
  21. invar/core/shell_analysis.py +5 -10
  22. invar/core/shell_architecture.py +2 -2
  23. invar/core/strategies.py +7 -14
  24. invar/core/suggestions.py +86 -0
  25. invar/core/sync_helpers.py +238 -0
  26. invar/core/tautology.py +102 -37
  27. invar/core/template_parser.py +467 -0
  28. invar/core/timeout_inference.py +4 -7
  29. invar/core/utils.py +13 -15
  30. invar/core/verification_routing.py +4 -7
  31. invar/mcp/server.py +100 -17
  32. invar/shell/commands/__init__.py +11 -0
  33. invar/shell/{cli.py → commands/guard.py} +94 -14
  34. invar/shell/{init_cmd.py → commands/init.py} +179 -27
  35. invar/shell/commands/merge.py +256 -0
  36. invar/shell/commands/sync_self.py +113 -0
  37. invar/shell/commands/template_sync.py +366 -0
  38. invar/shell/commands/update.py +48 -0
  39. invar/shell/config.py +12 -24
  40. invar/shell/coverage.py +351 -0
  41. invar/shell/guard_helpers.py +38 -17
  42. invar/shell/guard_output.py +7 -1
  43. invar/shell/property_tests.py +58 -22
  44. invar/shell/prove/__init__.py +9 -0
  45. invar/shell/{prove.py → prove/crosshair.py} +40 -33
  46. invar/shell/{prove_fallback.py → prove/hypothesis.py} +12 -4
  47. invar/shell/subprocess_env.py +393 -0
  48. invar/shell/template_engine.py +345 -0
  49. invar/shell/templates.py +19 -0
  50. invar/shell/testing.py +71 -20
  51. invar/templates/CLAUDE.md.template +38 -17
  52. invar/templates/aider.conf.yml.template +2 -2
  53. invar/templates/commands/{review.md → audit.md} +20 -82
  54. invar/templates/commands/guard.md +77 -0
  55. invar/templates/config/CLAUDE.md.jinja +206 -0
  56. invar/templates/config/context.md.jinja +92 -0
  57. invar/templates/config/pre-commit.yaml.jinja +44 -0
  58. invar/templates/context.md.template +33 -0
  59. invar/templates/cursorrules.template +7 -4
  60. invar/templates/examples/README.md +2 -0
  61. invar/templates/examples/conftest.py +3 -0
  62. invar/templates/examples/contracts.py +5 -5
  63. invar/templates/examples/core_shell.py +11 -7
  64. invar/templates/examples/workflow.md +81 -0
  65. invar/templates/manifest.toml +137 -0
  66. invar/templates/{INVAR.md → protocol/INVAR.md} +10 -7
  67. invar/templates/skills/develop/SKILL.md.jinja +318 -0
  68. invar/templates/skills/investigate/SKILL.md.jinja +106 -0
  69. invar/templates/skills/propose/SKILL.md.jinja +104 -0
  70. invar/templates/skills/review/SKILL.md.jinja +125 -0
  71. {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/METADATA +108 -118
  72. invar_tools-1.3.0.dist-info/RECORD +95 -0
  73. invar_tools-1.3.0.dist-info/entry_points.txt +2 -0
  74. invar/contracts.py +0 -152
  75. invar/decorators.py +0 -94
  76. invar/invariant.py +0 -58
  77. invar/resource.py +0 -99
  78. invar/shell/update_cmd.py +0 -193
  79. invar_tools-1.2.0.dist-info/RECORD +0 -77
  80. invar_tools-1.2.0.dist-info/entry_points.txt +0 -2
  81. /invar/shell/{mutate_cmd.py → commands/mutate.py} +0 -0
  82. /invar/shell/{perception.py → commands/perception.py} +0 -0
  83. /invar/shell/{test_cmd.py → commands/test.py} +0 -0
  84. /invar/shell/{prove_accept.py → prove/accept.py} +0 -0
  85. /invar/shell/{prove_cache.py → prove/cache.py} +0 -0
  86. {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/WHEEL +0 -0
  87. {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/licenses/LICENSE +0 -0
  88. {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/licenses/LICENSE-GPL +0 -0
  89. {invar_tools-1.2.0.dist-info → invar_tools-1.3.0.dist-info}/licenses/NOTICE +0 -0
invar/decorators.py DELETED
@@ -1,94 +0,0 @@
1
- """
2
- Invar contract decorators.
3
-
4
- Provides decorators that extend deal's contract system for additional
5
- static analysis by Guard.
6
-
7
- DX-12-B: Added @strategy for custom Hypothesis strategies.
8
- """
9
-
10
- from __future__ import annotations
11
-
12
- from collections.abc import Callable
13
- from typing import Any, TypeVar
14
-
15
- F = TypeVar("F", bound=Callable)
16
-
17
-
18
- def must_use(reason: str | None = None) -> Callable[[F], F]:
19
- """
20
- Mark a function's return value as must-use.
21
-
22
- Guard will warn if calls to this function discard the return value.
23
- Inspired by Move's lack of drop ability and Rust's #[must_use].
24
-
25
- Args:
26
- reason: Explanation of why the return value must be used.
27
-
28
- Returns:
29
- A decorator that marks the function.
30
-
31
- >>> @must_use("Error must be handled")
32
- ... def may_fail() -> int:
33
- ... return 42
34
- >>> may_fail.__invar_must_use__
35
- 'Error must be handled'
36
-
37
- >>> @must_use()
38
- ... def important() -> str:
39
- ... return "result"
40
- >>> important.__invar_must_use__
41
- 'Return value must be used'
42
- """
43
-
44
- def decorator(func: F) -> F:
45
- func.__invar_must_use__ = reason or "Return value must be used" # type: ignore[attr-defined]
46
- return func
47
-
48
- return decorator
49
-
50
-
51
- def strategy(**param_strategies: Any) -> Callable[[F], F]:
52
- """
53
- Specify custom Hypothesis strategies for function parameters.
54
-
55
- DX-12-B: Escape hatch when automatic strategy inference fails or
56
- when you need precise control over generated values.
57
-
58
- Args:
59
- **param_strategies: Mapping of parameter names to Hypothesis strategies.
60
-
61
- Returns:
62
- A decorator that attaches strategies to the function.
63
-
64
- Examples:
65
- >>> from hypothesis import strategies as st
66
- >>> @strategy(x=st.floats(min_value=1e-10, max_value=1e10))
67
- ... def sqrt(x: float) -> float:
68
- ... return x ** 0.5
69
- >>> hasattr(sqrt, '__invar_strategies__')
70
- True
71
- >>> 'x' in sqrt.__invar_strategies__
72
- True
73
-
74
- >>> # NumPy array with specific shape
75
- >>> @strategy(arr="arrays(dtype=float64, shape=(10,))")
76
- ... def normalize(arr):
77
- ... return arr / arr.sum()
78
- >>> 'arr' in normalize.__invar_strategies__
79
- True
80
-
81
- Note:
82
- Strategies can be either:
83
- - Hypothesis strategy objects (e.g., st.floats())
84
- - String representations (e.g., "floats(min_value=0)")
85
-
86
- String representations are useful when you don't want to import
87
- Hypothesis at module load time.
88
- """
89
-
90
- def decorator(func: F) -> F:
91
- func.__invar_strategies__ = param_strategies # type: ignore[attr-defined]
92
- return func
93
-
94
- return decorator
invar/invariant.py DELETED
@@ -1,58 +0,0 @@
1
- """
2
- Loop invariant support for Invar.
3
-
4
- Provides runtime-checked loop invariants inspired by Dafny.
5
- Checking controlled by INVAR_CHECK environment variable (default: ON).
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- import os
11
-
12
-
13
- class InvariantViolation(Exception):
14
- """Raised when a loop invariant is violated."""
15
-
16
- pass
17
-
18
-
19
- # Read once at module load time - effectively a constant
20
- _INVAR_CHECK = os.environ.get("INVAR_CHECK", "1") == "1"
21
-
22
-
23
- # @invar:allow entry_point_too_thick: False positive - .get() matches router.get pattern
24
- def invariant(condition: bool, message: str = "") -> None:
25
- """
26
- Assert loop invariant. Checked at runtime when INVAR_CHECK=1.
27
-
28
- Place at the START of loop body to check condition each iteration.
29
- Invariants document what must remain true throughout loop execution.
30
-
31
- Args:
32
- condition: Boolean condition that must hold
33
- message: Optional message describing the invariant
34
-
35
- Raises:
36
- InvariantViolation: When condition is False and INVAR_CHECK=1
37
-
38
- Examples:
39
- >>> invariant(True) # OK
40
-
41
- >>> invariant(True, "x is positive") # OK with message
42
-
43
- >>> try:
44
- ... invariant(False, "x must be positive")
45
- ... except InvariantViolation as e:
46
- ... print(str(e))
47
- Loop invariant violated: x must be positive
48
-
49
- Typical usage in a binary search:
50
-
51
- while lo < hi:
52
- invariant(0 <= lo <= hi <= len(arr))
53
- invariant(target not in arr[:lo]) # Already searched
54
- ...
55
- """
56
- if _INVAR_CHECK and not condition:
57
- msg = f"Loop invariant violated: {message}" if message else "Loop invariant violated"
58
- raise InvariantViolation(msg)
invar/resource.py DELETED
@@ -1,99 +0,0 @@
1
- """
2
- Resource management decorators for Invar.
3
-
4
- Provides @must_close for marking classes that require explicit cleanup.
5
- Inspired by Move language's resource semantics.
6
- """
7
-
8
- from __future__ import annotations
9
-
10
- from typing import Any, TypeVar
11
-
12
- T = TypeVar("T")
13
-
14
-
15
- class ResourceWarning(UserWarning):
16
- """Warning raised when a resource may not be properly closed."""
17
-
18
- pass
19
-
20
-
21
- class MustCloseViolation(Exception):
22
- """Raised when a @must_close resource is not properly managed."""
23
-
24
- pass
25
-
26
-
27
- def must_close(cls: type[T]) -> type[T]:
28
- """
29
- Mark a class as a resource that must be explicitly closed.
30
-
31
- The decorated class should have a `close()` method. The decorator:
32
- 1. Adds __invar_must_close__ marker for Guard detection
33
- 2. Adds context manager protocol if not present
34
-
35
- Examples:
36
- >>> @must_close
37
- ... class TempFile:
38
- ... def __init__(self, path: str):
39
- ... self.path = path
40
- ... self.closed = False
41
- ... def write(self, data: str) -> None:
42
- ... if self.closed:
43
- ... raise ValueError("File is closed")
44
- ... def close(self) -> None:
45
- ... self.closed = True
46
-
47
- >>> # Preferred: use as context manager
48
- >>> with TempFile("test.txt") as f:
49
- ... f.write("hello")
50
- >>> f.closed
51
- True
52
-
53
- >>> # Also works: explicit close
54
- >>> f2 = TempFile("test2.txt")
55
- >>> f2.write("world")
56
- >>> f2.close()
57
- >>> f2.closed
58
- True
59
- """
60
- # Mark for Guard detection
61
- cls.__invar_must_close__ = True # type: ignore[attr-defined]
62
-
63
- # Add context manager protocol if not present
64
- if not hasattr(cls, "__enter__"):
65
-
66
- def __enter__(self: Any) -> Any:
67
- return self
68
-
69
- cls.__enter__ = __enter__ # type: ignore[attr-defined]
70
-
71
- if not hasattr(cls, "__exit__"):
72
-
73
- def __exit__(self: Any, exc_type: Any, exc_val: Any, exc_tb: Any) -> None:
74
- if hasattr(self, "close") and callable(self.close):
75
- self.close()
76
-
77
- cls.__exit__ = __exit__ # type: ignore[attr-defined]
78
-
79
- return cls
80
-
81
-
82
- def is_must_close(cls_or_obj: Any) -> bool:
83
- """
84
- Check if a class or instance is marked with @must_close.
85
-
86
- >>> @must_close
87
- ... class Resource:
88
- ... def close(self): pass
89
- >>> is_must_close(Resource)
90
- True
91
- >>> is_must_close(Resource())
92
- True
93
- >>> class Plain: pass
94
- >>> is_must_close(Plain)
95
- False
96
- """
97
- if isinstance(cls_or_obj, type):
98
- return getattr(cls_or_obj, "__invar_must_close__", False)
99
- return getattr(type(cls_or_obj), "__invar_must_close__", False)
invar/shell/update_cmd.py DELETED
@@ -1,193 +0,0 @@
1
- """
2
- Update command for Invar.
3
-
4
- Shell module: handles updating Invar-managed files to latest version.
5
- """
6
-
7
- from __future__ import annotations
8
-
9
- import re
10
- from pathlib import Path
11
-
12
- import typer
13
- from returns.result import Failure, Result, Success
14
- from rich.console import Console
15
-
16
- from invar.shell.templates import copy_examples_directory, get_template_path
17
-
18
- console = Console()
19
-
20
- # Version pattern: matches "v3.23" or "v3.23.1"
21
- VERSION_PATTERN = re.compile(r"v(\d+)\.(\d+)(?:\.(\d+))?")
22
-
23
-
24
- # @shell_orchestration: Version parsing helper for update command
25
- def parse_version(text: str) -> tuple[int, int, int] | None:
26
- """
27
- Parse version string from text.
28
-
29
- >>> parse_version("Protocol v3.23")
30
- (3, 23, 0)
31
- >>> parse_version("v3.23.1")
32
- (3, 23, 1)
33
- >>> parse_version("no version here")
34
- """
35
- match = VERSION_PATTERN.search(text)
36
- if match:
37
- major = int(match.group(1))
38
- minor = int(match.group(2))
39
- patch = int(match.group(3)) if match.group(3) else 0
40
- return (major, minor, patch)
41
- return None
42
-
43
-
44
- def get_current_version(path: Path) -> Result[tuple[int, int, int], str]:
45
- """Get version from current INVAR.md file."""
46
- invar_md = path / "INVAR.md"
47
- if not invar_md.exists():
48
- return Failure("INVAR.md not found. Run 'invar init' first.")
49
-
50
- try:
51
- content = invar_md.read_text()
52
- version = parse_version(content)
53
- if version is None:
54
- return Failure("Could not parse version from INVAR.md")
55
- return Success(version)
56
- except OSError as e:
57
- return Failure(f"Failed to read INVAR.md: {e}")
58
-
59
-
60
- def get_template_version() -> Result[tuple[int, int, int], str]:
61
- """Get version from template INVAR.md."""
62
- template_result = get_template_path("INVAR.md")
63
- if isinstance(template_result, Failure):
64
- return template_result
65
-
66
- template_path = template_result.unwrap()
67
- try:
68
- content = template_path.read_text()
69
- version = parse_version(content)
70
- if version is None:
71
- return Failure("Could not parse version from template")
72
- return Success(version)
73
- except OSError as e:
74
- return Failure(f"Failed to read template: {e}")
75
-
76
-
77
- def format_version(version: tuple[int, int, int]) -> str:
78
- """Format version tuple as string."""
79
- if version[2] == 0:
80
- return f"v{version[0]}.{version[1]}"
81
- return f"v{version[0]}.{version[1]}.{version[2]}"
82
-
83
-
84
- def update_invar_md(path: Path, console: Console) -> Result[bool, str]:
85
- """Update INVAR.md by overwriting with template."""
86
- template_result = get_template_path("INVAR.md")
87
- if isinstance(template_result, Failure):
88
- return template_result
89
-
90
- template_path = template_result.unwrap()
91
- dest_file = path / "INVAR.md"
92
-
93
- try:
94
- dest_file.write_text(template_path.read_text())
95
- return Success(True)
96
- except OSError as e:
97
- return Failure(f"Failed to update INVAR.md: {e}")
98
-
99
-
100
- def update_examples(path: Path, console: Console) -> Result[bool, str]:
101
- """Update .invar/examples/ directory."""
102
- import shutil
103
-
104
- examples_dest = path / ".invar" / "examples"
105
-
106
- # Remove existing examples
107
- if examples_dest.exists():
108
- try:
109
- shutil.rmtree(examples_dest)
110
- except OSError as e:
111
- return Failure(f"Failed to remove old examples: {e}")
112
-
113
- # Copy new examples
114
- return copy_examples_directory(path, console)
115
-
116
-
117
- # @shell_complexity: Update command with template comparison
118
- def update(
119
- path: Path = typer.Argument(Path(), help="Project root directory"),
120
- force: bool = typer.Option(
121
- False, "--force", "-f", help="Update even if already at latest version"
122
- ),
123
- check: bool = typer.Option(
124
- False, "--check", help="Check for updates without applying"
125
- ),
126
- ) -> None:
127
- """
128
- Update Invar-managed files to latest version.
129
-
130
- Updates INVAR.md and .invar/examples/ from the installed python-invar package.
131
- User-managed files (CLAUDE.md, .invar/context.md) are never modified.
132
-
133
- Use --check to see if updates are available without applying them.
134
- Use --force to update even if already at latest version.
135
- """
136
- # Get current version
137
- current_result = get_current_version(path)
138
- if isinstance(current_result, Failure):
139
- console.print(f"[red]Error:[/red] {current_result.failure()}")
140
- raise typer.Exit(1)
141
- current_version = current_result.unwrap()
142
-
143
- # Get template version
144
- template_result = get_template_version()
145
- if isinstance(template_result, Failure):
146
- console.print(f"[red]Error:[/red] {template_result.failure()}")
147
- raise typer.Exit(1)
148
- template_version = template_result.unwrap()
149
-
150
- current_str = format_version(current_version)
151
- template_str = format_version(template_version)
152
-
153
- # Compare versions
154
- needs_update = template_version > current_version
155
-
156
- if check:
157
- # Check mode: just report status
158
- if needs_update:
159
- console.print(f"[yellow]Update available:[/yellow] {current_str} → {template_str}")
160
- else:
161
- console.print(f"[green]Up to date:[/green] {current_str}")
162
- return
163
-
164
- if not needs_update and not force:
165
- console.print(f"[green]Already at latest version:[/green] {current_str}")
166
- console.print("[dim]Use --force to update anyway[/dim]")
167
- return
168
-
169
- # Perform update
170
- console.print("\n[bold]Updating Invar files...[/bold]")
171
- console.print(f" Version: {current_str} → {template_str}")
172
- console.print()
173
-
174
- # Update INVAR.md
175
- result = update_invar_md(path, console)
176
- if isinstance(result, Failure):
177
- console.print(f"[red]Error:[/red] {result.failure()}")
178
- raise typer.Exit(1)
179
- console.print(f"[green]Updated[/green] INVAR.md ({template_str})")
180
-
181
- # Update examples
182
- result = update_examples(path, console)
183
- if isinstance(result, Failure):
184
- console.print(f"[yellow]Warning:[/yellow] {result.failure()}")
185
- else:
186
- console.print("[green]Updated[/green] .invar/examples/")
187
-
188
- # Remind about user-managed files
189
- console.print()
190
- console.print("[dim]User-managed files unchanged:[/dim]")
191
- console.print("[dim] ○ CLAUDE.md[/dim]")
192
- console.print("[dim] ○ .invar/context.md[/dim]")
193
- console.print("[dim] ○ pyproject.toml [tool.invar][/dim]")
@@ -1,77 +0,0 @@
1
- invar/__init__.py,sha256=gvCf_VzCH3gMfq6dvsvncxicAEv7_FhgBoQTBdbqcFM,1256
2
- invar/contracts.py,sha256=xAqk901hd3ep7ItxCln7Q0fID3rm47OROgEugmFnRY4,4631
3
- invar/decorators.py,sha256=EaZUgt4JzlhSgRTeRmKIEb-KgU8L5Npn8-oJuMuygRU,2677
4
- invar/invariant.py,sha256=V-qd2yMDmomz-eiTxvTaFbtsEwqNnNix1tpRfhSfsPo,1698
5
- invar/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
- invar/resource.py,sha256=uX3V8R8_e5uFRO6ksOt_RN62g6nmf_wzpjyr9JXNhoc,2680
7
- invar/core/__init__.py,sha256=01TgQ2bqTFV4VFdksfqXYPa2WUqo-DpUWUkEcIUXFb4,218
8
- invar/core/contracts.py,sha256=hdpMieO5I0BSuW4n5lLtiintTPqhutqB0UkdbkxB-Ao,19081
9
- invar/core/entry_points.py,sha256=6wqofuXOXWjOKX0aSl7WM8_R8rSGkfTSGRqMcS6UVDE,9082
10
- invar/core/extraction.py,sha256=NEGtpmPLIg0O_EnXGEDQcTRXudwJneysYCM3rpy0a2g,6058
11
- invar/core/format_specs.py,sha256=pjr_6zl81IAOJnptr5LuPTvCwfom-c5abQ95d_vdI_g,5640
12
- invar/core/format_strategies.py,sha256=LifL97JbsF8WEkVNmQpq2htyFUC3pW21myAjtRGpSxU,5774
13
- invar/core/formatter.py,sha256=wB4J9b-CMoooeYzPbRR2UTo5GuDueSzEXybyeVzdI14,10566
14
- invar/core/hypothesis_strategies.py,sha256=KTk0X_pJ-9AVduYm_xiv6AdGtIAd01VjOfk2Z4mXYKA,16468
15
- invar/core/inspect.py,sha256=5OX-c3BJ7GEiJWqIY77GYoP0Ox15cTcrmlNfjh9Hvfg,4380
16
- invar/core/lambda_helpers.py,sha256=pt_5GezT3kQoOiyJDAdLDLzRl-xEN1yWMQ7NYAVuWzI,6371
17
- invar/core/models.py,sha256=K6_-t7mOXa8k3TQK2aR-qm2G0lLHu3vmJpilGaTzTlc,9653
18
- invar/core/must_use.py,sha256=R8VsIIWqLXtVov1kf5RqiKfkvqI1o2Bn4rKKNo5KFSw,5376
19
- invar/core/parser.py,sha256=hlxLtqmS8eaXmcLO5BnD7HfTfRpxbpfTBmFSHGW2tzc,9079
20
- invar/core/property_gen.py,sha256=PpPYcKpPHqvx0XmCb8ktliigcFkxvKPbhAXm8qksokE,13990
21
- invar/core/purity.py,sha256=Wi_6wRLshSFLzaNxJfjoa0-4frCWJkQJliPpQfdUeq8,11980
22
- invar/core/purity_heuristics.py,sha256=dcdYqJJh-RLZHZR_G1j1gViH3Cqe37RfE3leaA2MU34,4748
23
- invar/core/references.py,sha256=iOIivmQ3Qcp38XiFpzaa7EZa01Ab75Q-G7KR2PRn-tI,6107
24
- invar/core/review_trigger.py,sha256=sCsBX9YOv9xnEhJqVJDhyAE5YzIC3p1MFrKbjCiD3Hk,11377
25
- invar/core/rule_meta.py,sha256=5bTrr6I7-Qi-ubqUQi-3Hva0E3mJBc-MadV0K77dwWs,9772
26
- invar/core/rules.py,sha256=3HY9A_9sVw72XNTA7CV8gWSG5xBqBqfS1v_agQzIj_s,19699
27
- invar/core/shell_analysis.py,sha256=IumoT0qjfZ4ElYBq6etwQL7ETSFS-a3sJnPKgOvUprg,6676
28
- invar/core/shell_architecture.py,sha256=41JE0hM8-PCSLyNlJB0fy6l1zPSnd9t_r3HxUTqZ4qQ,6521
29
- invar/core/strategies.py,sha256=AhiEJl-5SxXKSmprpeT4OdCmEk7dS3Di7Eb90I7QENQ,8797
30
- invar/core/suggestions.py,sha256=Y3b9hprG4M2fCNGgo2fNfMox4TDPKD9nyfmzCsBbF-Q,11500
31
- invar/core/tautology.py,sha256=Vk_FSP8q7uHeR5ZcyE28NWqxq1_WG-sJXwyKiClxdv4,5610
32
- invar/core/timeout_inference.py,sha256=NOLwNuadLAKvGTtAnd3qppZikVfKlo2ZPxHFVg4Vupk,3544
33
- invar/core/utils.py,sha256=aImcrQaiz1LkH_eJIgPAgl0HSPI3UBeE-tdUu92bIFc,14481
34
- invar/core/verification_routing.py,sha256=09qqOac3DjOWACmRAY4CJiOuri7J2cN2kXztBJ9ch0I,5126
35
- invar/mcp/__init__.py,sha256=n3S7QwMjSMqOMT8cI2jf9E0yZPjKmBOJyIYhq4WZ8TQ,226
36
- invar/mcp/__main__.py,sha256=ZcIT2U6xUyGOWucl4jq422BDE3lRLjqyxb9pFylRBdk,219
37
- invar/mcp/server.py,sha256=EYXZZQ8IPLVer0Cv5vw8wHu4OuLQxqK6uRQo1byE45k,8832
38
- invar/shell/__init__.py,sha256=FFw1mNbh_97PeKPcHIqQpQ7mw-JoIvyLM1yOdxLw5uk,204
39
- invar/shell/cli.py,sha256=wDFQsLnO--S1Au4AKo3ayNXEJY6JJhv-DdIWnk9tcOk,13674
40
- invar/shell/config.py,sha256=TxCuEQIjKbutpSCU2SxY7H7jPA6CIWNL9QDCe2KjNqc,16163
41
- invar/shell/fs.py,sha256=wVD7DPWsCIJXuTyY_pi-5_LS82mXRdn_grJCOLn9zpU,3699
42
- invar/shell/git.py,sha256=s6RQxEDQuLrmK3mru88EoYP8__4hiFW8AozlcxmY47E,2784
43
- invar/shell/guard_helpers.py,sha256=XPWpWUovKDnD100WUop7PqdOzxODXvE84ALPng2ujHo,14007
44
- invar/shell/guard_output.py,sha256=pxOTp7jGfpjOwOX2FaATDcmM_rsaLQ8CrZDqEMa0zSQ,11523
45
- invar/shell/init_cmd.py,sha256=a0Lk45wP1RF71jyVFDSrBTJgPjIeSstrKWbpCJiPPw4,10622
46
- invar/shell/mcp_config.py,sha256=-hC7Y5BGuVs285b6gBARk7ZyzVxHwPgXSyt_GoN0jfs,4580
47
- invar/shell/mutate_cmd.py,sha256=GwemiO6LlbGCBEQsBFnzZuKhF-wIMEl79GAMnKUWc8U,5765
48
- invar/shell/mutation.py,sha256=Lfyk2b8j8-hxAq-iwAgQeOhr7Ci6c5tRF1TXe3CxQCs,8914
49
- invar/shell/perception.py,sha256=TyH_HpqyKkmE3-zcU4YyBG8ghwJaSFeRC-OQMVBDTbQ,3837
50
- invar/shell/property_tests.py,sha256=1ycvPXA0_2cnJP5lIP4HukL8VQshWcc7xJ3Md-iacLQ,7408
51
- invar/shell/prove.py,sha256=jPxLKgxAjako2dqgcxwe2bcfdbZA_Cj1acayTWRVtrg,15644
52
- invar/shell/prove_accept.py,sha256=cnY_6jzU1EBnpLF8-zWUWcXiSXtCwxPsXEYXsSVPG38,3717
53
- invar/shell/prove_cache.py,sha256=jbNdrvfLjvK7S0iqugErqeabb4YIbQuwIlcSRyCKbcg,4105
54
- invar/shell/prove_fallback.py,sha256=UOhD6c6YIVcR1Q3wG6W9ySMnuJXZ6x8hTL6O1HG5zrU,9628
55
- invar/shell/templates.py,sha256=joJA6ASSCGi8GcApPY6kxoSbrFElpsxVhHVzJGAnsXc,15083
56
- invar/shell/test_cmd.py,sha256=DKnlSbUydKq6skHLLKhZGg42qTAKtiLxrTU3oyFDmAo,4189
57
- invar/shell/testing.py,sha256=2aG_4-VTRmvFKGz7IOdY_o0QqP29fs5yUgV00QUL0Js,8766
58
- invar/shell/update_cmd.py,sha256=PbXN0UwmUcFmy0IKFmyO9oBXEjwy77gZG3j7gFJA8lA,6317
59
- invar/templates/CLAUDE.md.template,sha256=dBZkhmBQhSZ-uEDWozlZsrrt4Qo8xhzx4XYJiJ9gi8A,2943
60
- invar/templates/INVAR.md,sha256=BDihvntGUXHeaSlwVNA8HSTidfQFH4dCqmzZtEIPPWo,6635
61
- invar/templates/__init__.py,sha256=cb3ht8KPK5oBn5oG6HsTznujmo9WriJ_P--fVxJwycc,45
62
- invar/templates/aider.conf.yml.template,sha256=hPWt5-_q53Ex00v-fNL-80db8wNdxT2q8PLbpbO6GQw,842
63
- invar/templates/context.md.template,sha256=D4mIAbj33io5_xe0uTcZh5JuSfpzXpv_t5h6k0B6UIA,1168
64
- invar/templates/cursorrules.template,sha256=AYZumL5oSXuvfs3HZ6fziDvbaAWaDCvGf-CFSXmFHsg,987
65
- invar/templates/pre-commit-config.yaml.template,sha256=2qWY3E8iDUqi85jE_X7y0atE88YOlL5IZ93wkjCgQGo,1737
66
- invar/templates/proposal.md.template,sha256=UP7SpQ7gk8jVlHGLQCSQ5c-kCj1DBQEz8M-vEStK77I,1573
67
- invar/templates/commands/review.md,sha256=fIOt_aFxn5KlDptJmE1USlmNbJs-_5sZgn6_ABl-S6w,6037
68
- invar/templates/examples/README.md,sha256=dkS5QI1mzDsQp23dJGCoTZzM_1SQg1vos37sZAS-Wsc,485
69
- invar/templates/examples/contracts.py,sha256=VFlu9N1Zg8YcTO3UYeSvh1HCBPGZWFktpQN_jtE8ue0,3204
70
- invar/templates/examples/core_shell.py,sha256=HhTAxo3M7MhiQn05I3BClx43pshtxOnEjtVh974PFXc,3820
71
- invar_tools-1.2.0.dist-info/METADATA,sha256=WbedCOQ1a6lN9Px4qJScVlzd5xLnnvzHDdC7Stymg1g,11534
72
- invar_tools-1.2.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
73
- invar_tools-1.2.0.dist-info/entry_points.txt,sha256=C7R-M4tvNd6UHDOcG98RQVS9plLyJ-c939z8qLLzTj8,46
74
- invar_tools-1.2.0.dist-info/licenses/LICENSE,sha256=qeFksp4H4kfTgQxPCIu3OdagXyiZcgBlVfsQ6M5oFyk,10767
75
- invar_tools-1.2.0.dist-info/licenses/LICENSE-GPL,sha256=IvZfC6ZbP7CLjytoHVzvpDZpD-Z3R_qa1GdMdWlWQ6Q,35157
76
- invar_tools-1.2.0.dist-info/licenses/NOTICE,sha256=joEyMyFhFY8Vd8tTJ-a3SirI0m2Sd0WjzqYt3sdcglc,2561
77
- invar_tools-1.2.0.dist-info/RECORD,,
@@ -1,2 +0,0 @@
1
- [console_scripts]
2
- invar = invar.shell.cli:app
File without changes
File without changes
File without changes
File without changes
File without changes