invar-tools 1.7.1__py3-none-any.whl → 1.10.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 (113) hide show
  1. invar/__init__.py +8 -0
  2. invar/core/language.py +88 -0
  3. invar/core/models.py +106 -0
  4. invar/core/patterns/detector.py +6 -1
  5. invar/core/patterns/p0_exhaustive.py +15 -3
  6. invar/core/patterns/p0_literal.py +15 -3
  7. invar/core/patterns/p0_newtype.py +15 -3
  8. invar/core/patterns/p0_nonempty.py +15 -3
  9. invar/core/patterns/p0_validation.py +15 -3
  10. invar/core/patterns/registry.py +5 -1
  11. invar/core/patterns/types.py +5 -1
  12. invar/core/property_gen.py +4 -0
  13. invar/core/rules.py +84 -18
  14. invar/core/sync_helpers.py +27 -1
  15. invar/core/template_helpers.py +32 -0
  16. invar/core/ts_parsers.py +286 -0
  17. invar/core/ts_sig_parser.py +307 -0
  18. invar/node_tools/MANIFEST +7 -0
  19. invar/node_tools/__init__.py +51 -0
  20. invar/node_tools/fc-runner/cli.js +77 -0
  21. invar/node_tools/quick-check/cli.js +28 -0
  22. invar/node_tools/ts-analyzer/cli.js +480 -0
  23. invar/shell/claude_hooks.py +35 -12
  24. invar/shell/commands/guard.py +36 -1
  25. invar/shell/commands/init.py +133 -7
  26. invar/shell/commands/perception.py +157 -33
  27. invar/shell/commands/skill.py +187 -0
  28. invar/shell/commands/template_sync.py +65 -13
  29. invar/shell/commands/uninstall.py +77 -12
  30. invar/shell/commands/update.py +6 -14
  31. invar/shell/contract_coverage.py +1 -0
  32. invar/shell/fs.py +66 -13
  33. invar/shell/pi_hooks.py +213 -0
  34. invar/shell/prove/guard_ts.py +899 -0
  35. invar/shell/skill_manager.py +353 -0
  36. invar/shell/template_engine.py +28 -4
  37. invar/shell/templates.py +4 -4
  38. invar/templates/claude-md/python/critical-rules.md +33 -0
  39. invar/templates/claude-md/python/quick-reference.md +24 -0
  40. invar/templates/claude-md/typescript/critical-rules.md +40 -0
  41. invar/templates/claude-md/typescript/quick-reference.md +24 -0
  42. invar/templates/claude-md/universal/check-in.md +25 -0
  43. invar/templates/claude-md/universal/skills.md +73 -0
  44. invar/templates/claude-md/universal/workflow.md +55 -0
  45. invar/templates/commands/{audit.md → audit.md.jinja} +18 -1
  46. invar/templates/config/AGENT.md.jinja +256 -0
  47. invar/templates/config/CLAUDE.md.jinja +16 -209
  48. invar/templates/config/context.md.jinja +19 -0
  49. invar/templates/examples/{README.md → python/README.md} +2 -0
  50. invar/templates/examples/{conftest.py → python/conftest.py} +1 -1
  51. invar/templates/examples/{contracts.py → python/contracts.py} +81 -4
  52. invar/templates/examples/python/core_shell.py +227 -0
  53. invar/templates/examples/python/functional.py +613 -0
  54. invar/templates/examples/typescript/README.md +31 -0
  55. invar/templates/examples/typescript/contracts.ts +163 -0
  56. invar/templates/examples/typescript/core_shell.ts +374 -0
  57. invar/templates/examples/typescript/functional.ts +601 -0
  58. invar/templates/examples/typescript/workflow.md +95 -0
  59. invar/templates/hooks/PostToolUse.sh.jinja +10 -1
  60. invar/templates/hooks/PreToolUse.sh.jinja +38 -0
  61. invar/templates/hooks/Stop.sh.jinja +1 -1
  62. invar/templates/hooks/UserPromptSubmit.sh.jinja +7 -0
  63. invar/templates/hooks/pi/invar.ts.jinja +82 -0
  64. invar/templates/manifest.toml +8 -6
  65. invar/templates/onboard/assessment.md.jinja +214 -0
  66. invar/templates/onboard/patterns/python.md +347 -0
  67. invar/templates/onboard/patterns/typescript.md +452 -0
  68. invar/templates/onboard/roadmap.md.jinja +168 -0
  69. invar/templates/protocol/INVAR.md.jinja +51 -0
  70. invar/templates/protocol/python/architecture-examples.md +41 -0
  71. invar/templates/protocol/python/contracts-syntax.md +56 -0
  72. invar/templates/protocol/python/markers.md +44 -0
  73. invar/templates/protocol/python/tools.md +24 -0
  74. invar/templates/protocol/python/troubleshooting.md +38 -0
  75. invar/templates/protocol/typescript/architecture-examples.md +52 -0
  76. invar/templates/protocol/typescript/contracts-syntax.md +73 -0
  77. invar/templates/protocol/typescript/markers.md +48 -0
  78. invar/templates/protocol/typescript/tools.md +65 -0
  79. invar/templates/protocol/typescript/troubleshooting.md +104 -0
  80. invar/templates/protocol/universal/architecture.md +36 -0
  81. invar/templates/protocol/universal/completion.md +14 -0
  82. invar/templates/protocol/universal/contracts-concept.md +37 -0
  83. invar/templates/protocol/universal/header.md +17 -0
  84. invar/templates/protocol/universal/session.md +17 -0
  85. invar/templates/protocol/universal/six-laws.md +10 -0
  86. invar/templates/protocol/universal/usbv.md +14 -0
  87. invar/templates/protocol/universal/visible-workflow.md +25 -0
  88. invar/templates/skills/develop/SKILL.md.jinja +98 -3
  89. invar/templates/skills/extensions/_registry.yaml +93 -0
  90. invar/templates/skills/extensions/acceptance/SKILL.md +383 -0
  91. invar/templates/skills/extensions/invar-onboard/SKILL.md +448 -0
  92. invar/templates/skills/extensions/invar-onboard/patterns/python.md +347 -0
  93. invar/templates/skills/extensions/invar-onboard/patterns/typescript.md +452 -0
  94. invar/templates/skills/extensions/invar-onboard/templates/assessment.md.jinja +214 -0
  95. invar/templates/skills/extensions/invar-onboard/templates/roadmap.md.jinja +168 -0
  96. invar/templates/skills/extensions/security/SKILL.md +382 -0
  97. invar/templates/skills/extensions/security/patterns/_common.yaml +126 -0
  98. invar/templates/skills/extensions/security/patterns/python.yaml +155 -0
  99. invar/templates/skills/extensions/security/patterns/typescript.yaml +194 -0
  100. invar/templates/skills/investigate/SKILL.md.jinja +15 -0
  101. invar/templates/skills/propose/SKILL.md.jinja +33 -0
  102. invar/templates/skills/review/SKILL.md.jinja +346 -71
  103. {invar_tools-1.7.1.dist-info → invar_tools-1.10.0.dist-info}/METADATA +326 -19
  104. invar_tools-1.10.0.dist-info/RECORD +173 -0
  105. invar/templates/examples/core_shell.py +0 -127
  106. invar/templates/protocol/INVAR.md +0 -310
  107. invar_tools-1.7.1.dist-info/RECORD +0 -112
  108. /invar/templates/examples/{workflow.md → python/workflow.md} +0 -0
  109. {invar_tools-1.7.1.dist-info → invar_tools-1.10.0.dist-info}/WHEEL +0 -0
  110. {invar_tools-1.7.1.dist-info → invar_tools-1.10.0.dist-info}/entry_points.txt +0 -0
  111. {invar_tools-1.7.1.dist-info → invar_tools-1.10.0.dist-info}/licenses/LICENSE +0 -0
  112. {invar_tools-1.7.1.dist-info → invar_tools-1.10.0.dist-info}/licenses/LICENSE-GPL +0 -0
  113. {invar_tools-1.7.1.dist-info → invar_tools-1.10.0.dist-info}/licenses/NOTICE +0 -0
@@ -1,127 +0,0 @@
1
- """
2
- Invar Core/Shell Separation Examples
3
-
4
- Reference patterns for Core vs Shell architecture.
5
- Managed by Invar - do not edit directly.
6
- """
7
-
8
- from pathlib import Path
9
-
10
- # For lambda-based contracts, use deal directly
11
- # invar_runtime.pre/post are for Contract objects (NonEmpty, IsInstance, etc.)
12
- from deal import post, pre
13
- from returns.result import Failure, Result, Success
14
-
15
- # =============================================================================
16
- # CORE: Pure Logic (no I/O)
17
- # =============================================================================
18
- # Location: src/*/core/
19
- # Requirements: @pre/@post, doctests, no I/O imports
20
- # =============================================================================
21
-
22
-
23
- # @invar:allow shell_result: Example file - demonstrates Core pattern
24
- # @shell_orchestration: Example file - demonstrates Core pattern
25
- @pre(lambda content: content is not None) # Accepts any string including empty
26
- @post(lambda result: all(line.strip() == line and line for line in result)) # No whitespace, non-empty
27
- def parse_lines(content: str) -> list[str]:
28
- """
29
- Parse content into non-empty lines.
30
-
31
- >>> parse_lines("a\\nb\\nc")
32
- ['a', 'b', 'c']
33
- >>> parse_lines("")
34
- []
35
- >>> parse_lines(" \\n ") # Edge: whitespace only
36
- []
37
- """
38
- return [line.strip() for line in content.split("\n") if line.strip()]
39
-
40
-
41
- # @invar:allow shell_result: Example file - demonstrates Core pattern
42
- # @shell_orchestration: Example file - demonstrates Core pattern
43
- @pre(lambda items: all(isinstance(i, str) for i in items)) # All items must be strings
44
- @post(lambda result: all(v > 0 for v in result.values())) # All counts are positive
45
- def count_items(items: list[str]) -> dict[str, int]:
46
- """
47
- Count occurrences of each item.
48
-
49
- >>> sorted(count_items(['a', 'b', 'a']).items())
50
- [('a', 2), ('b', 1)]
51
- >>> count_items([])
52
- {}
53
- """
54
- counts: dict[str, int] = {}
55
- for item in items:
56
- counts[item] = counts.get(item, 0) + 1
57
- return counts
58
-
59
-
60
- # =============================================================================
61
- # SHELL: I/O Operations
62
- # =============================================================================
63
- # Location: src/*/shell/
64
- # Requirements: Result[T, E] return type, calls Core for logic
65
- # =============================================================================
66
-
67
-
68
- def read_file(path: Path) -> Result[str, str]:
69
- """
70
- Read file content.
71
-
72
- Shell handles I/O, returns Result for error handling.
73
- """
74
- try:
75
- return Success(path.read_text())
76
- except FileNotFoundError:
77
- return Failure(f"File not found: {path}")
78
- except PermissionError:
79
- return Failure(f"Permission denied: {path}")
80
-
81
-
82
- def count_lines_in_file(path: Path) -> Result[dict[str, int], str]:
83
- """
84
- Count lines in file - demonstrates Core/Shell integration.
85
-
86
- Shell reads file → Core parses content → Shell returns result.
87
- """
88
- # Shell: I/O operation
89
- content_result = read_file(path)
90
-
91
- if isinstance(content_result, Failure):
92
- return content_result
93
-
94
- content = content_result.unwrap()
95
-
96
- # Core: Pure logic (no I/O)
97
- lines = parse_lines(content)
98
- counts = count_items(lines)
99
-
100
- # Shell: Return result
101
- return Success(counts)
102
-
103
-
104
- # =============================================================================
105
- # ANTI-PATTERNS
106
- # =============================================================================
107
-
108
- # DON'T: I/O in Core
109
- # def parse_file(path: Path): # BAD: Path in Core
110
- # content = path.read_text() # BAD: I/O in Core # noqa: ERA001
111
- # return parse_lines(content) # noqa: ERA001
112
-
113
- # DO: Core receives content, not paths
114
- # def parse_content(content: str): # GOOD: receives data
115
- # return parse_lines(content) # noqa: ERA001
116
-
117
-
118
- # DON'T: Missing Result in Shell
119
- # def load_config(path: Path) -> dict: # BAD: no Result type
120
- # return json.loads(path.read_text()) # Exceptions not handled # noqa: ERA001
121
-
122
- # DO: Return Result[T, E]
123
- # def load_config(path: Path) -> Result[dict, str]: # GOOD
124
- # try: # noqa: ERA001
125
- # return Success(json.loads(path.read_text())) # noqa: ERA001
126
- # except Exception as e: # noqa: ERA001
127
- # return Failure(str(e)) # noqa: ERA001
@@ -1,310 +0,0 @@
1
- <!--
2
- ┌─────────────────────────────────────────────────────────────┐
3
- │ INVAR-MANAGED FILE - DO NOT EDIT DIRECTLY │
4
- │ │
5
- │ This file is managed by Invar. Changes may be lost on │
6
- │ `invar update`. Add project content to CLAUDE.md instead. │
7
- └─────────────────────────────────────────────────────────────┘
8
-
9
- License: CC-BY-4.0 (Creative Commons Attribution 4.0 International)
10
- https://creativecommons.org/licenses/by/4.0/
11
-
12
- You are free to share and adapt this document, provided you give
13
- appropriate credit to the Invar project.
14
- -->
15
- # The Invar Protocol v5.0
16
-
17
- > **"Trade structure for safety."**
18
-
19
- ## Six Laws
20
-
21
- | Law | Principle |
22
- |-----|-----------|
23
- | 1. Separation | Core (pure logic) / Shell (I/O) physically separate |
24
- | 2. Contract Complete | @pre/@post + doctests uniquely determine implementation |
25
- | 3. Context Economy | map → sig → code (only read what's needed) |
26
- | 4. Decompose First | Break into sub-functions before implementing |
27
- | 5. Verify Reflectively | Fail → Reflect (why?) → Fix → Verify |
28
- | 6. Integrate Fully | Local correct ≠ Global correct; verify all paths |
29
-
30
- ## Core/Shell Architecture
31
-
32
- | Zone | Location | Requirements |
33
- |------|----------|--------------|
34
- | Core | `**/core/**` | @pre/@post, pure (no I/O), doctests |
35
- | Shell | `**/shell/**` | `Result[T, E]` return type |
36
-
37
- **Forbidden in Core:** `os`, `sys`, `subprocess`, `pathlib`, `open`, `requests`, `datetime.now`
38
-
39
- ### Decision Tree: Core vs Shell
40
-
41
- ```
42
- Does this function...
43
-
44
- ├─ Read or write files? ──────────────────→ Shell
45
- ├─ Make network requests? ─────────────────→ Shell
46
- ├─ Access current time (datetime.now)? ────→ Shell OR inject as parameter
47
- ├─ Generate random values? ────────────────→ Shell OR inject as parameter
48
- ├─ Print to console? ──────────────────────→ Shell (return data, Shell logs)
49
- ├─ Access environment variables? ──────────→ Shell
50
-
51
- └─ None of the above? ─────────────────────→ Core
52
- ```
53
-
54
- **Pattern:** Inject impure values as parameters:
55
- ```python
56
- # Core: receives 'now' as parameter (pure)
57
- def is_expired(expiry: datetime, now: datetime) -> bool:
58
- return now > expiry
59
-
60
- # Shell calls with actual time
61
- expired = is_expired(token.expiry, datetime.now())
62
- ```
63
-
64
- ## Core Example (Pure Logic)
65
-
66
- ```python
67
- from deal import pre, post
68
-
69
- @pre(lambda price, discount: price > 0 and 0 <= discount <= 1)
70
- @post(lambda result: result >= 0)
71
- def discounted_price(price: float, discount: float) -> float:
72
- """
73
- >>> discounted_price(100, 0.2)
74
- 80.0
75
- >>> discounted_price(100, 0) # Edge: no discount
76
- 100.0
77
- """
78
- return price * (1 - discount)
79
- ```
80
-
81
- **Self-test:** Can someone else write the exact same function from just @pre/@post + doctests?
82
-
83
- ## Shell Example (I/O Operations)
84
-
85
- ```python
86
- from pathlib import Path
87
- from returns.result import Result, Success, Failure
88
-
89
- def read_config(path: Path) -> Result[dict, str]:
90
- """Shell: handles I/O, returns Result for error handling."""
91
- try:
92
- import json
93
- return Success(json.loads(path.read_text()))
94
- except FileNotFoundError:
95
- return Failure(f"File not found: {path}")
96
- except json.JSONDecodeError as e:
97
- return Failure(f"Invalid JSON: {e}")
98
- ```
99
-
100
- **Pattern:** Shell reads file → passes content to Core → returns Result.
101
-
102
- More examples: `.invar/examples/`
103
-
104
- ## Contract Rules
105
-
106
- ### Lambda Signature (Critical)
107
-
108
- ```python
109
- # WRONG: Lambda only takes first parameter
110
- @pre(lambda x: x >= 0)
111
- def calculate(x: int, y: int = 0): ...
112
-
113
- # CORRECT: Lambda must include ALL parameters (even defaults)
114
- @pre(lambda x, y=0: x >= 0)
115
- def calculate(x: int, y: int = 0): ...
116
- ```
117
-
118
- Guard's `param_mismatch` rule catches this as ERROR.
119
-
120
- ### Meaningful Contracts
121
-
122
- ```python
123
- # Redundant - type hints already check this
124
- @pre(lambda x: isinstance(x, int))
125
- def calc(x: int): ...
126
-
127
- # Meaningful - checks business logic
128
- @pre(lambda x: x > 0)
129
- def calc(x: int): ...
130
-
131
- # Meaningful - checks relationship between params
132
- @pre(lambda start, end: start < end)
133
- def process_range(start: int, end: int): ...
134
- ```
135
-
136
- ### @post Scope
137
-
138
- ```python
139
- # WRONG: @post cannot access function parameters
140
- @post(lambda result: result > x) # 'x' not available!
141
- def calc(x: int) -> int: ...
142
-
143
- # CORRECT: @post can only use 'result'
144
- @post(lambda result: result >= 0)
145
- def calc(x: int) -> int: ...
146
- ```
147
-
148
- ## Check-In (Required)
149
-
150
- Your first message MUST display:
151
-
152
- ```
153
- ✓ Check-In: [project] | [branch] | [clean/dirty]
154
- ```
155
-
156
- Actions:
157
- 1. Read `.invar/context.md` (Key Rules + Current State + Lessons Learned)
158
- 2. Show one-line status
159
-
160
- **Do NOT execute guard or map at Check-In.**
161
- Guard is for VALIDATE phase and Final only.
162
-
163
- This is your sign-in. The user sees it immediately.
164
- No visible check-in = Session not started.
165
-
166
- ## USBV Workflow (DX-32)
167
-
168
- **U**nderstand → **S**pecify → **B**uild → **V**alidate
169
-
170
- | Phase | Purpose | Activities |
171
- |-------|---------|------------|
172
- | UNDERSTAND | Know what and why | Intent, Inspect (invar sig/map), Constraints |
173
- | SPECIFY | Define boundaries | @pre/@post, Design decomposition, Doctests |
174
- | BUILD | Write code | Implement leaves, Compose |
175
- | VALIDATE | Confirm correctness | invar guard, Review Gate, Reflect |
176
-
177
- **Key:** Inspect before Contract. Depth varies naturally. Iterate when needed.
178
-
179
- **Review Gate:** When Guard triggers `review_suggested` (escape hatches ≥3, security paths, low coverage), invoke `/review` before completion.
180
-
181
- ## Visible Workflow (DX-30)
182
-
183
- For complex tasks (3+ functions), show 3 checkpoints in TodoList:
184
-
185
- ```
186
- □ [UNDERSTAND] Task description, codebase context, constraints
187
- □ [SPECIFY] Contracts (@pre/@post) and design decomposition
188
- □ [VALIDATE] Guard results, Review Gate if triggered, integration status
189
- ```
190
-
191
- **BUILD is internal work** — not shown in TodoList.
192
-
193
- **Show contracts before code.** Example:
194
-
195
- ```python
196
- [SPECIFY] calculate_discount:
197
- @pre(lambda price, rate: price > 0 and 0 <= rate <= 1)
198
- @post(lambda result: result >= 0)
199
- def calculate_discount(price: float, rate: float) -> float: ...
200
-
201
- [BUILD] Now coding...
202
- ```
203
-
204
- **When to use:** New features (3+ functions), architectural changes, Core modifications.
205
- **Skip for:** Single-line fixes, documentation, trivial refactoring.
206
-
207
- ## Task Completion
208
-
209
- A task is complete only when ALL conditions are met:
210
- - Check-In displayed: `✓ Check-In: [project] | [branch] | [clean/dirty]`
211
- - Intent explicitly stated
212
- - Contract written before implementation
213
- - Final displayed: `✓ Final: guard PASS | <errors>, <warnings>`
214
- - User requirement satisfied
215
-
216
- **Missing any = Task incomplete.**
217
-
218
- ## Markers
219
-
220
- ### Entry Points
221
-
222
- Entry points are framework callbacks (`@app.route`, `@app.command`) at Shell boundary.
223
- - **Exempt** from `Result[T, E]` — must match framework signature
224
- - **Keep thin** (max 15 lines) — delegate to Shell functions that return Result
225
-
226
- Auto-detected by decorators. For custom callbacks:
227
-
228
- ```python
229
- # @shell:entry
230
- def on_custom_event(data: dict) -> dict:
231
- result = handle_event(data)
232
- return result.unwrap_or({"error": "failed"})
233
- ```
234
-
235
- ### Shell Complexity
236
-
237
- When shell function complexity is justified:
238
-
239
- ```python
240
- # @shell_complexity: Subprocess with error classification
241
- def run_external_tool(...): ...
242
-
243
- # @shell_orchestration: Multi-step pipeline coordination
244
- def process_batch(...): ...
245
- ```
246
-
247
- ### Architecture Escape Hatch
248
-
249
- When rule violation has valid architectural justification:
250
-
251
- ```python
252
- # @invar:allow shell_result: Framework callback signature fixed
253
- def flask_handler(): ...
254
- ```
255
-
256
- **Valid rule names for @invar:allow:**
257
- - `shell_result` — Shell function without Result return type
258
- - `entry_point_too_thick` — Entry point exceeds 15 lines
259
- - `forbidden_import` — I/O import in Core (rare, justify carefully)
260
-
261
- Run `invar rules` for complete rule catalog with hints.
262
-
263
- ## Commands
264
-
265
- ```bash
266
- invar guard # Full: static + doctests + CrossHair + Hypothesis
267
- invar guard --static # Static only (quick debug, ~0.5s)
268
- invar guard --changed # Modified files only
269
- invar guard --coverage # Collect branch coverage
270
- invar guard -c # Contract coverage only (DX-63)
271
- invar sig <file> # Show contracts + signatures
272
- invar map --top 10 # Most-referenced symbols
273
- invar rules # List all rules with detection/hints (JSON)
274
- ```
275
-
276
- ## Configuration
277
-
278
- ```toml
279
- # pyproject.toml or invar.toml
280
- [tool.invar.guard]
281
- core_paths = ["src/myapp/core"] # Default: ["src/core", "core"]
282
- shell_paths = ["src/myapp/shell"] # Default: ["src/shell", "shell"]
283
- max_file_lines = 500 # Default: 500 (warning at 80%)
284
- max_function_lines = 50 # Default: 50
285
- # Doctest lines are excluded from size calculations
286
- ```
287
-
288
- ## Troubleshooting
289
-
290
- ### Size Limits (Agent Quick Reference)
291
-
292
- | Rule | Limit | Fix |
293
- |------|-------|-----|
294
- | `function_too_long` | **50 lines** | Extract helper: `_impl()` + main with docstring |
295
- | `file_too_long` | **500 lines** | Split by responsibility |
296
- | `entry_point_too_thick` | **15 lines** | Delegate to Shell functions |
297
-
298
- *Doctest lines excluded from counts. Limits configurable in `pyproject.toml`.*
299
-
300
- ### Common Errors
301
-
302
- | Symptom | Cause | Fix |
303
- |---------|-------|-----|
304
- | `param_mismatch` error | Lambda missing params | Include ALL params (even defaults) |
305
- | `shell_result` error | Shell func no Result | Add Result[T,E] or @invar:allow |
306
- | `is_failure()` not found | Wrong Result check | Use `isinstance(result, Failure)` |
307
-
308
- ---
309
-
310
- *Protocol v5.0 — USBV workflow (DX-32) | [Examples](.invar/examples/)*
@@ -1,112 +0,0 @@
1
- invar/__init__.py,sha256=HV5W2nywevBhAMgF7TIHdBoiFY4ETWVLBYAt_gZCPHU,1520
2
- invar/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
- invar/core/__init__.py,sha256=01TgQ2bqTFV4VFdksfqXYPa2WUqo-DpUWUkEcIUXFb4,218
4
- invar/core/contracts.py,sha256=SOyF1KeJ6hrEwfQ09UzMt881OJKDXRbPTslKA6HzdKg,19085
5
- invar/core/entry_points.py,sha256=1p6GRGTp9kA9spNkGKidFLlzLPheh6JO2XFb68Cr0sE,12209
6
- invar/core/extraction.py,sha256=mScqEMEEQdsd-Z0jx9g3scK6Z1vI9l-ESjggXPIWHZ4,6112
7
- invar/core/format_specs.py,sha256=P299aRHFMXyow8STwsvaT6Bg2ALPs2wSy7SByiRZZ-A,5610
8
- invar/core/format_strategies.py,sha256=LifL97JbsF8WEkVNmQpq2htyFUC3pW21myAjtRGpSxU,5774
9
- invar/core/formatter.py,sha256=rCGZhMpl4dPLrztgKDkNtAvnv2vKfomyIHl_6fThuno,11293
10
- invar/core/hypothesis_strategies.py,sha256=_MfjG7KxkmJvuPsczr_1JayR_YmiDzU2jJ8fQPoKGgs,16517
11
- invar/core/inspect.py,sha256=l1knohwpLRHSNySPUjyeBHJusnU0vYiQGj4dMVgQZIo,4381
12
- invar/core/lambda_helpers.py,sha256=Ap1y7N0wpgCgPHwrs2pd7zD9Qq4Ptfd2iTliprXIkME,6457
13
- invar/core/models.py,sha256=1bbhLijXHSe-o5SXQhbJgq8_EqPOOgsGKIrnWRwwtYM,13200
14
- invar/core/must_use.py,sha256=7HnnbT53lb4dOT-1mL64pz0JbQYytuw4eejNVe7iWKY,5496
15
- invar/core/parser.py,sha256=ucVpGziVzUvbkXT1n_SgOrYdStDEcNBqLuRGqK3_M5g,9205
16
- invar/core/postcondition_scope.py,sha256=ykjVNqZZ1zItBmI7ebgmLW5vFGE-vpaLRTvSgWaJMgM,5245
17
- invar/core/property_gen.py,sha256=_IvBJNUqd8pwu7wXuIProZn5RZksqFdmtXt3GnLU6Vo,14033
18
- invar/core/purity.py,sha256=dt5dFy5V8Ch93iBJF5OuKUr1jjfimfY3oHLQD8KmLHw,12036
19
- invar/core/purity_heuristics.py,sha256=vsgphC1XPIFtsoLB0xvp--AyaJHqlh83LyKXYda4pWc,4546
20
- invar/core/references.py,sha256=64yGIdj9vL72Y4uUhJsi9pztZkuMnLN-7OcOziyxYMo,6339
21
- invar/core/review_trigger.py,sha256=4GGHUmgbVsQJAob4OO6A8G7KrLcNMwNOuqHiT6Jc7cs,14085
22
- invar/core/rule_meta.py,sha256=il_KUTjSlW1MOVgLguuLDS9wEdyqUe3CDvUx4gQjACo,10180
23
- invar/core/rules.py,sha256=6MvqO4dQXYwYe3ICp1bT2s_33O7FkpGwUzOrgHL16X4,19962
24
- invar/core/shell_analysis.py,sha256=i2A9SMqBI3Rb4Ai0QNTM7awIkSJIY6yZJVWS72lv0bY,6457
25
- invar/core/shell_architecture.py,sha256=98EVdBFIs8tO-i9jKuzdmv7fLB4PKnyI-vKh5lxnB98,6538
26
- invar/core/strategies.py,sha256=2DPl0z2p_CBNd4RlSbZzTeAy6Dq6cpCiBCB2p5qHHkk,8798
27
- invar/core/suggestions.py,sha256=LCg2Dy9EHh_n1t9jATRZ0gTkgJkAEZk3vp2nuuCyr-s,15129
28
- invar/core/sync_helpers.py,sha256=kd6VyFAcpKfkVcbDk3GaBi2n0EWOGICz4VmdxwbshfI,7523
29
- invar/core/tautology.py,sha256=Pmn__a0Bt55W0lAQo1G5q8Ory9KuE23dRknKw45xxbs,9221
30
- invar/core/template_parser.py,sha256=vH3H8OX55scZ1hWh3xoA8oJMhgleKufCOhkTvsSuu_4,14730
31
- invar/core/timeout_inference.py,sha256=BS2fJGmwOrLpYZUku4qrizgNDSIXVLFBslW-6sRAvpc,3451
32
- invar/core/trivial_detection.py,sha256=KYP8jJb7QDeusAxFdX5NAML_H0NL5wLgMeBWDQmNqfU,6086
33
- invar/core/utils.py,sha256=PyW8dcTLUEFD81xcvkz-LNnCwjIQefn08OUh23fM_Po,14266
34
- invar/core/verification_routing.py,sha256=_jXi1txFCcUdnB3-Yavtuyk8N-XhEO_Vu_051Vuz27Y,5020
35
- invar/core/patterns/__init__.py,sha256=79a3ucN0BI54RnIOe49lngKASpADygs1hll9ROCrP6s,1429
36
- invar/core/patterns/detector.py,sha256=lZ2HPtDJDiGps8Y3e7jds3naZa1oGqDDscHRSX5Vv0s,8297
37
- invar/core/patterns/p0_exhaustive.py,sha256=yK51l4VkriOUA6i6ujeNY3SDlogArVSW2SqtnAaMl0Y,6905
38
- invar/core/patterns/p0_literal.py,sha256=eazGzNvTpDSeuZJZg9H4_1vukXREKO9GgzCQUSqAKVc,10705
39
- invar/core/patterns/p0_newtype.py,sha256=T9T6vxgtRXrt2Ym_KNWuHeLNOUKFoMfqu7oE1IUAhCo,7562
40
- invar/core/patterns/p0_nonempty.py,sha256=H5SXU0XNaW4H_gTw0NFN4cXckbPyTqAUl1KgGvVX9uM,10681
41
- invar/core/patterns/p0_validation.py,sha256=AuPI7j2MRqBulXPCnAGVbPO2p1DVPjrM1avrIrgyCwQ,9563
42
- invar/core/patterns/registry.py,sha256=XuwRBPnV5-5uMFsn66pjZV-qDkIVZezt3YH540Gi8Qs,7422
43
- invar/core/patterns/types.py,sha256=d5wqYJUVF3PHYL5lv6DZnB3PWcZ_MWn7q3-PxrToAEc,5385
44
- invar/mcp/__init__.py,sha256=n3S7QwMjSMqOMT8cI2jf9E0yZPjKmBOJyIYhq4WZ8TQ,226
45
- invar/mcp/__main__.py,sha256=ZcIT2U6xUyGOWucl4jq422BDE3lRLjqyxb9pFylRBdk,219
46
- invar/mcp/server.py,sha256=ay-w2YfSa1kTmBFx3x3jEgmNRC3NFEW0EYuZRt7M39w,12244
47
- invar/shell/__init__.py,sha256=FFw1mNbh_97PeKPcHIqQpQ7mw-JoIvyLM1yOdxLw5uk,204
48
- invar/shell/claude_hooks.py,sha256=KJAQ-a7-mvabJ2fgsC9wPMakvi7J43GCU6ZcpWwKYFg,16180
49
- invar/shell/config.py,sha256=6-kbo6--SxfROXoyU-v7InSLR8f_U1Mar_xEOdCXFkY,17633
50
- invar/shell/contract_coverage.py,sha256=UPn-lEqrAFu00fl7v9PnSvNwS7KX3_SV1K_GhynQ9cw,12023
51
- invar/shell/coverage.py,sha256=m01o898IFIdBztEBQLwwL1Vt5PWrpUntO4lv4nWEkls,11344
52
- invar/shell/fs.py,sha256=wVD7DPWsCIJXuTyY_pi-5_LS82mXRdn_grJCOLn9zpU,3699
53
- invar/shell/git.py,sha256=s6RQxEDQuLrmK3mru88EoYP8__4hiFW8AozlcxmY47E,2784
54
- invar/shell/guard_helpers.py,sha256=QeYgbW0lgUa9Z_RCjAMG7UJdiMzz5cW48Lb2u-qgQi8,15114
55
- invar/shell/guard_output.py,sha256=v3gG5P-_47nIFo8eAMKwdA_hLf2KZ0cQ-45Z6JjKp4w,12520
56
- invar/shell/mcp_config.py,sha256=-hC7Y5BGuVs285b6gBARk7ZyzVxHwPgXSyt_GoN0jfs,4580
57
- invar/shell/mutation.py,sha256=Lfyk2b8j8-hxAq-iwAgQeOhr7Ci6c5tRF1TXe3CxQCs,8914
58
- invar/shell/pattern_integration.py,sha256=pRcjfq3NvMW_tvQCnaXZnD1k5AVEWK8CYOE2jN6VTro,7842
59
- invar/shell/property_tests.py,sha256=N9JreyH5PqR89oF5yLcX7ZAV-Koyg5BKo-J05-GUPsA,9109
60
- invar/shell/subprocess_env.py,sha256=9oXl3eMEbzLsFEgMHqobEw6oW_wV0qMEP7pklwm58Pw,11453
61
- invar/shell/template_engine.py,sha256=IzOiGsKVFo0lDUdtg27wMzIJJKToclv151RDZuDnHHo,11027
62
- invar/shell/templates.py,sha256=30eT61HXPA6DmsgUyUqljZNGGtB9TSR-aAaI4fmKAco,13722
63
- invar/shell/testing.py,sha256=rTNBH0Okh2qtG9ohSXOz487baQ2gXrWT3s_WECW3HJs,11143
64
- invar/shell/commands/__init__.py,sha256=MEkKwVyjI9DmkvBpJcuumXo2Pg_FFkfEr-Rr3nrAt7A,284
65
- invar/shell/commands/guard.py,sha256=vDBGOFb9mQ1D8eXrMvQB505GpjO1XLeCLrv2ig9-6dU,21718
66
- invar/shell/commands/hooks.py,sha256=W-SOnT4VQyUvXwipozkJwgEYfiOJGz7wksrbcdWegUg,2356
67
- invar/shell/commands/init.py,sha256=wAPPIDpoJyNOhrD09LldRg8w76mWv0r5qTcqlPWc920,13411
68
- invar/shell/commands/merge.py,sha256=nuvKo8m32-OL-SCQlS4SLKmOZxQ3qj-1nGCx1Pgzifw,8183
69
- invar/shell/commands/mutate.py,sha256=GwemiO6LlbGCBEQsBFnzZuKhF-wIMEl79GAMnKUWc8U,5765
70
- invar/shell/commands/perception.py,sha256=TyH_HpqyKkmE3-zcU4YyBG8ghwJaSFeRC-OQMVBDTbQ,3837
71
- invar/shell/commands/sync_self.py,sha256=nmqBry7V2_enKwy2zzHg8UoedZNicLe3yKDhjmBeZ68,3880
72
- invar/shell/commands/template_sync.py,sha256=wVZ-UvJ1wpN2UBcWMfbei0n46XHYx-zRbMA2oX6FSi4,13723
73
- invar/shell/commands/test.py,sha256=goMf-ovvzEyWQMheq4YlJ-mwK5-w3lDj0cq0IA_1-_c,4205
74
- invar/shell/commands/uninstall.py,sha256=u1fqE2jCod2KxFMEYbtC4UFK1zuxzoaQKQzZdAjQcDE,17368
75
- invar/shell/commands/update.py,sha256=0V5F8vxQ6PHPHPVYDmxdRD7xXeQEFypiJMYpY5ryiek,1349
76
- invar/shell/prove/__init__.py,sha256=ZqlbmyMFJf6yAle8634jFuPRv8wNvHps8loMlOJyf8A,240
77
- invar/shell/prove/accept.py,sha256=cnY_6jzU1EBnpLF8-zWUWcXiSXtCwxPsXEYXsSVPG38,3717
78
- invar/shell/prove/cache.py,sha256=jbNdrvfLjvK7S0iqugErqeabb4YIbQuwIlcSRyCKbcg,4105
79
- invar/shell/prove/crosshair.py,sha256=4Z_iIYBlkp-I6FqSYZa89wWB09V4Ouw2PduYhTn6rfw,16525
80
- invar/shell/prove/hypothesis.py,sha256=QUclOOUg_VB6wbmHw8O2EPiL5qBOeBRqQeM04AVuLw0,9880
81
- invar/templates/CLAUDE.md.template,sha256=eaGU3SyRO_NEifw5b26k3srgQH4jyeujjCJ-HbM36_w,4913
82
- invar/templates/__init__.py,sha256=cb3ht8KPK5oBn5oG6HsTznujmo9WriJ_P--fVxJwycc,45
83
- invar/templates/context.md.template,sha256=FKyI1ghpqcf4wftyv9-auIFHor8Nm8lETN45Ja-L8Og,2386
84
- invar/templates/manifest.toml,sha256=cEe7yEOOeaLmOF-PrwZXxiPGjHhsSJYkWBKRHDmSbac,4268
85
- invar/templates/proposal.md.template,sha256=UP7SpQ7gk8jVlHGLQCSQ5c-kCj1DBQEz8M-vEStK77I,1573
86
- invar/templates/commands/audit.md,sha256=OrotO8420zTKnlNyAyL1Eos0VIaihzEU4AHdfDv68Oc,4162
87
- invar/templates/commands/guard.md,sha256=N_C_AXd9kI85W1B0aTEycjiDp_jdaP8eeq8O0FQ_WQ8,1227
88
- invar/templates/config/CLAUDE.md.jinja,sha256=VbtDWxn3H8qiE9-DV1hlG3DJ-GcBQU4ZiUHbFh6Bxxk,7814
89
- invar/templates/config/context.md.jinja,sha256=_kJ8erEQNJMLDCKrv4BXWkO6OaGzE-zW9biCf7144aY,3103
90
- invar/templates/config/pre-commit.yaml.jinja,sha256=nUPxLxkTHAgZwhFAuOMDbZ8v0NQV9FlQPbr2MDEOsoA,1778
91
- invar/templates/examples/README.md,sha256=xMcJZ1KEcfLJi5Ope_4FIbqDWKK3mRleAgllvgeNT6I,572
92
- invar/templates/examples/conftest.py,sha256=uKA4NR7nyZWeSzY0URdZtw5zCcJpU32jNcaSKrI1Mxc,152
93
- invar/templates/examples/contracts.py,sha256=uqJ6Y1GADo246MjFKoLY-_2E74cfBQsLO4vTqYcR81c,3241
94
- invar/templates/examples/core_shell.py,sha256=ckor-7ZoaF7n8gVjnIO0CXlBjKGcVwmOGSDJbaXCSrM,4247
95
- invar/templates/examples/workflow.md,sha256=jAopzQH1xE9_leJFdav4oj1AkI46-a2q4L8RQCkDknw,2334
96
- invar/templates/hooks/PostToolUse.sh.jinja,sha256=H-lzVaEMvlr0uoO2LxrGNpWrBtyUkHmYrhtWmCqdAjI,2967
97
- invar/templates/hooks/PreToolUse.sh.jinja,sha256=D39PaT1eFSjz_Av16xK1atoBZbhLI8tLp8L12zkG-3k,2334
98
- invar/templates/hooks/Stop.sh.jinja,sha256=3S6lLeAGIu5aPQVRz4jjFS9AfjCD9DdS_jagmkw-x8Q,960
99
- invar/templates/hooks/UserPromptSubmit.sh.jinja,sha256=eAQqQ-XdOCyhLpF5_1r1z7C-Ej9GQ5Isqbu_2LAtsno,2302
100
- invar/templates/hooks/__init__.py,sha256=RnnMoQA-8eqbr8Y_1Vu9B8h5vAz4C-vmo8wgdcGYrz0,43
101
- invar/templates/protocol/INVAR.md,sha256=ppQhb_-R5YaXAqW1WDMOcXptx-CrAQI_xYxld7YljK8,9998
102
- invar/templates/skills/develop/SKILL.md.jinja,sha256=3coPSZGh1-YKN9Xc_xcEkfEP3S0XiFMMGF0hJZEaAx8,10562
103
- invar/templates/skills/investigate/SKILL.md.jinja,sha256=bOLdLMH5WUVBYOo4NpsfyvI6xx7I1lCNr_X-8bMe_kg,2744
104
- invar/templates/skills/propose/SKILL.md.jinja,sha256=_iDLYN6-cfzA8n0_8sv-Dnpm1xq9IIpcDyM10mU2WUA,2420
105
- invar/templates/skills/review/SKILL.md.jinja,sha256=e7HULz1jjLOlk2LYejQMk2F-cu7dDIwvh6lWNjx3j-Q,14123
106
- invar_tools-1.7.1.dist-info/METADATA,sha256=dBk4N2qRISfYrc6Rr66eY08_me9Rqfyq34RDBCaEj1s,17600
107
- invar_tools-1.7.1.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
108
- invar_tools-1.7.1.dist-info/entry_points.txt,sha256=RwH_EhqgtFPsnO6RcrwrAb70Zyfb8Mh6uUtztWnUxGk,102
109
- invar_tools-1.7.1.dist-info/licenses/LICENSE,sha256=qeFksp4H4kfTgQxPCIu3OdagXyiZcgBlVfsQ6M5oFyk,10767
110
- invar_tools-1.7.1.dist-info/licenses/LICENSE-GPL,sha256=IvZfC6ZbP7CLjytoHVzvpDZpD-Z3R_qa1GdMdWlWQ6Q,35157
111
- invar_tools-1.7.1.dist-info/licenses/NOTICE,sha256=joEyMyFhFY8Vd8tTJ-a3SirI0m2Sd0WjzqYt3sdcglc,2561
112
- invar_tools-1.7.1.dist-info/RECORD,,