invar-tools 1.8.0__py3-none-any.whl → 1.11.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 (117) hide show
  1. invar/__init__.py +8 -0
  2. invar/core/doc_edit.py +187 -0
  3. invar/core/doc_parser.py +563 -0
  4. invar/core/language.py +88 -0
  5. invar/core/models.py +106 -0
  6. invar/core/patterns/detector.py +6 -1
  7. invar/core/patterns/p0_exhaustive.py +15 -3
  8. invar/core/patterns/p0_literal.py +15 -3
  9. invar/core/patterns/p0_newtype.py +15 -3
  10. invar/core/patterns/p0_nonempty.py +15 -3
  11. invar/core/patterns/p0_validation.py +15 -3
  12. invar/core/patterns/registry.py +5 -1
  13. invar/core/patterns/types.py +5 -1
  14. invar/core/property_gen.py +4 -0
  15. invar/core/rules.py +84 -18
  16. invar/core/sync_helpers.py +27 -1
  17. invar/core/ts_parsers.py +286 -0
  18. invar/core/ts_sig_parser.py +310 -0
  19. invar/mcp/handlers.py +408 -0
  20. invar/mcp/server.py +288 -143
  21. invar/node_tools/MANIFEST +7 -0
  22. invar/node_tools/__init__.py +51 -0
  23. invar/node_tools/fc-runner/cli.js +77 -0
  24. invar/node_tools/quick-check/cli.js +28 -0
  25. invar/node_tools/ts-analyzer/cli.js +480 -0
  26. invar/shell/claude_hooks.py +35 -12
  27. invar/shell/commands/doc.py +409 -0
  28. invar/shell/commands/guard.py +41 -1
  29. invar/shell/commands/init.py +154 -16
  30. invar/shell/commands/perception.py +157 -33
  31. invar/shell/commands/skill.py +187 -0
  32. invar/shell/commands/template_sync.py +65 -13
  33. invar/shell/commands/uninstall.py +60 -12
  34. invar/shell/commands/update.py +6 -14
  35. invar/shell/contract_coverage.py +1 -0
  36. invar/shell/doc_tools.py +459 -0
  37. invar/shell/fs.py +67 -13
  38. invar/shell/pi_hooks.py +6 -0
  39. invar/shell/prove/crosshair.py +3 -0
  40. invar/shell/prove/guard_ts.py +902 -0
  41. invar/shell/skill_manager.py +355 -0
  42. invar/shell/template_engine.py +28 -4
  43. invar/shell/templates.py +4 -4
  44. invar/templates/claude-md/python/critical-rules.md +33 -0
  45. invar/templates/claude-md/python/quick-reference.md +24 -0
  46. invar/templates/claude-md/typescript/critical-rules.md +40 -0
  47. invar/templates/claude-md/typescript/quick-reference.md +24 -0
  48. invar/templates/claude-md/universal/check-in.md +25 -0
  49. invar/templates/claude-md/universal/skills.md +73 -0
  50. invar/templates/claude-md/universal/workflow.md +55 -0
  51. invar/templates/commands/{audit.md → audit.md.jinja} +18 -1
  52. invar/templates/config/AGENT.md.jinja +58 -0
  53. invar/templates/config/CLAUDE.md.jinja +16 -209
  54. invar/templates/config/context.md.jinja +19 -0
  55. invar/templates/examples/{README.md → python/README.md} +2 -0
  56. invar/templates/examples/{conftest.py → python/conftest.py} +1 -1
  57. invar/templates/examples/{contracts.py → python/contracts.py} +81 -4
  58. invar/templates/examples/python/core_shell.py +227 -0
  59. invar/templates/examples/python/functional.py +613 -0
  60. invar/templates/examples/typescript/README.md +31 -0
  61. invar/templates/examples/typescript/contracts.ts +163 -0
  62. invar/templates/examples/typescript/core_shell.ts +374 -0
  63. invar/templates/examples/typescript/functional.ts +601 -0
  64. invar/templates/examples/typescript/workflow.md +95 -0
  65. invar/templates/hooks/PostToolUse.sh.jinja +10 -1
  66. invar/templates/hooks/PreToolUse.sh.jinja +38 -0
  67. invar/templates/hooks/Stop.sh.jinja +1 -1
  68. invar/templates/hooks/UserPromptSubmit.sh.jinja +7 -0
  69. invar/templates/hooks/pi/invar.ts.jinja +9 -0
  70. invar/templates/manifest.toml +7 -6
  71. invar/templates/onboard/assessment.md.jinja +214 -0
  72. invar/templates/onboard/patterns/python.md +347 -0
  73. invar/templates/onboard/patterns/typescript.md +452 -0
  74. invar/templates/onboard/roadmap.md.jinja +168 -0
  75. invar/templates/protocol/INVAR.md.jinja +51 -0
  76. invar/templates/protocol/python/architecture-examples.md +41 -0
  77. invar/templates/protocol/python/contracts-syntax.md +56 -0
  78. invar/templates/protocol/python/markers.md +44 -0
  79. invar/templates/protocol/python/tools.md +24 -0
  80. invar/templates/protocol/python/troubleshooting.md +38 -0
  81. invar/templates/protocol/typescript/architecture-examples.md +52 -0
  82. invar/templates/protocol/typescript/contracts-syntax.md +73 -0
  83. invar/templates/protocol/typescript/markers.md +48 -0
  84. invar/templates/protocol/typescript/tools.md +65 -0
  85. invar/templates/protocol/typescript/troubleshooting.md +104 -0
  86. invar/templates/protocol/universal/architecture.md +36 -0
  87. invar/templates/protocol/universal/completion.md +14 -0
  88. invar/templates/protocol/universal/contracts-concept.md +37 -0
  89. invar/templates/protocol/universal/header.md +17 -0
  90. invar/templates/protocol/universal/session.md +17 -0
  91. invar/templates/protocol/universal/six-laws.md +10 -0
  92. invar/templates/protocol/universal/usbv.md +14 -0
  93. invar/templates/protocol/universal/visible-workflow.md +25 -0
  94. invar/templates/skills/develop/SKILL.md.jinja +85 -3
  95. invar/templates/skills/extensions/_registry.yaml +93 -0
  96. invar/templates/skills/extensions/acceptance/SKILL.md +383 -0
  97. invar/templates/skills/extensions/invar-onboard/SKILL.md +448 -0
  98. invar/templates/skills/extensions/invar-onboard/patterns/python.md +347 -0
  99. invar/templates/skills/extensions/invar-onboard/patterns/typescript.md +452 -0
  100. invar/templates/skills/extensions/invar-onboard/templates/assessment.md.jinja +214 -0
  101. invar/templates/skills/extensions/invar-onboard/templates/roadmap.md.jinja +168 -0
  102. invar/templates/skills/extensions/security/SKILL.md +382 -0
  103. invar/templates/skills/extensions/security/patterns/_common.yaml +126 -0
  104. invar/templates/skills/extensions/security/patterns/python.yaml +155 -0
  105. invar/templates/skills/extensions/security/patterns/typescript.yaml +194 -0
  106. invar/templates/skills/review/SKILL.md.jinja +220 -248
  107. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/METADATA +336 -12
  108. invar_tools-1.11.0.dist-info/RECORD +178 -0
  109. invar/templates/examples/core_shell.py +0 -127
  110. invar/templates/protocol/INVAR.md +0 -310
  111. invar_tools-1.8.0.dist-info/RECORD +0 -116
  112. /invar/templates/examples/{workflow.md → python/workflow.md} +0 -0
  113. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/WHEEL +0 -0
  114. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/entry_points.txt +0 -0
  115. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/licenses/LICENSE +0 -0
  116. {invar_tools-1.8.0.dist-info → invar_tools-1.11.0.dist-info}/licenses/LICENSE-GPL +0 -0
  117. {invar_tools-1.8.0.dist-info → invar_tools-1.11.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,116 +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_helpers.py,sha256=E1UT7ct0DaUFlfHr9oTBvW4xfxAiS81rbmZHSucPw4c,881
31
- invar/core/template_parser.py,sha256=vH3H8OX55scZ1hWh3xoA8oJMhgleKufCOhkTvsSuu_4,14730
32
- invar/core/timeout_inference.py,sha256=BS2fJGmwOrLpYZUku4qrizgNDSIXVLFBslW-6sRAvpc,3451
33
- invar/core/trivial_detection.py,sha256=KYP8jJb7QDeusAxFdX5NAML_H0NL5wLgMeBWDQmNqfU,6086
34
- invar/core/utils.py,sha256=PyW8dcTLUEFD81xcvkz-LNnCwjIQefn08OUh23fM_Po,14266
35
- invar/core/verification_routing.py,sha256=_jXi1txFCcUdnB3-Yavtuyk8N-XhEO_Vu_051Vuz27Y,5020
36
- invar/core/patterns/__init__.py,sha256=79a3ucN0BI54RnIOe49lngKASpADygs1hll9ROCrP6s,1429
37
- invar/core/patterns/detector.py,sha256=lZ2HPtDJDiGps8Y3e7jds3naZa1oGqDDscHRSX5Vv0s,8297
38
- invar/core/patterns/p0_exhaustive.py,sha256=yK51l4VkriOUA6i6ujeNY3SDlogArVSW2SqtnAaMl0Y,6905
39
- invar/core/patterns/p0_literal.py,sha256=eazGzNvTpDSeuZJZg9H4_1vukXREKO9GgzCQUSqAKVc,10705
40
- invar/core/patterns/p0_newtype.py,sha256=T9T6vxgtRXrt2Ym_KNWuHeLNOUKFoMfqu7oE1IUAhCo,7562
41
- invar/core/patterns/p0_nonempty.py,sha256=H5SXU0XNaW4H_gTw0NFN4cXckbPyTqAUl1KgGvVX9uM,10681
42
- invar/core/patterns/p0_validation.py,sha256=AuPI7j2MRqBulXPCnAGVbPO2p1DVPjrM1avrIrgyCwQ,9563
43
- invar/core/patterns/registry.py,sha256=XuwRBPnV5-5uMFsn66pjZV-qDkIVZezt3YH540Gi8Qs,7422
44
- invar/core/patterns/types.py,sha256=d5wqYJUVF3PHYL5lv6DZnB3PWcZ_MWn7q3-PxrToAEc,5385
45
- invar/mcp/__init__.py,sha256=n3S7QwMjSMqOMT8cI2jf9E0yZPjKmBOJyIYhq4WZ8TQ,226
46
- invar/mcp/__main__.py,sha256=ZcIT2U6xUyGOWucl4jq422BDE3lRLjqyxb9pFylRBdk,219
47
- invar/mcp/server.py,sha256=ay-w2YfSa1kTmBFx3x3jEgmNRC3NFEW0EYuZRt7M39w,12244
48
- invar/shell/__init__.py,sha256=FFw1mNbh_97PeKPcHIqQpQ7mw-JoIvyLM1yOdxLw5uk,204
49
- invar/shell/claude_hooks.py,sha256=KJAQ-a7-mvabJ2fgsC9wPMakvi7J43GCU6ZcpWwKYFg,16180
50
- invar/shell/config.py,sha256=6-kbo6--SxfROXoyU-v7InSLR8f_U1Mar_xEOdCXFkY,17633
51
- invar/shell/contract_coverage.py,sha256=UPn-lEqrAFu00fl7v9PnSvNwS7KX3_SV1K_GhynQ9cw,12023
52
- invar/shell/coverage.py,sha256=m01o898IFIdBztEBQLwwL1Vt5PWrpUntO4lv4nWEkls,11344
53
- invar/shell/fs.py,sha256=wVD7DPWsCIJXuTyY_pi-5_LS82mXRdn_grJCOLn9zpU,3699
54
- invar/shell/git.py,sha256=s6RQxEDQuLrmK3mru88EoYP8__4hiFW8AozlcxmY47E,2784
55
- invar/shell/guard_helpers.py,sha256=QeYgbW0lgUa9Z_RCjAMG7UJdiMzz5cW48Lb2u-qgQi8,15114
56
- invar/shell/guard_output.py,sha256=v3gG5P-_47nIFo8eAMKwdA_hLf2KZ0cQ-45Z6JjKp4w,12520
57
- invar/shell/mcp_config.py,sha256=-hC7Y5BGuVs285b6gBARk7ZyzVxHwPgXSyt_GoN0jfs,4580
58
- invar/shell/mutation.py,sha256=Lfyk2b8j8-hxAq-iwAgQeOhr7Ci6c5tRF1TXe3CxQCs,8914
59
- invar/shell/pattern_integration.py,sha256=pRcjfq3NvMW_tvQCnaXZnD1k5AVEWK8CYOE2jN6VTro,7842
60
- invar/shell/pi_hooks.py,sha256=ln71f6SkjQ_7pMt6_udzeqgRaRIk3Y11XobLURBP2v0,6597
61
- invar/shell/property_tests.py,sha256=N9JreyH5PqR89oF5yLcX7ZAV-Koyg5BKo-J05-GUPsA,9109
62
- invar/shell/subprocess_env.py,sha256=9oXl3eMEbzLsFEgMHqobEw6oW_wV0qMEP7pklwm58Pw,11453
63
- invar/shell/template_engine.py,sha256=IzOiGsKVFo0lDUdtg27wMzIJJKToclv151RDZuDnHHo,11027
64
- invar/shell/templates.py,sha256=30eT61HXPA6DmsgUyUqljZNGGtB9TSR-aAaI4fmKAco,13722
65
- invar/shell/testing.py,sha256=rTNBH0Okh2qtG9ohSXOz487baQ2gXrWT3s_WECW3HJs,11143
66
- invar/shell/commands/__init__.py,sha256=MEkKwVyjI9DmkvBpJcuumXo2Pg_FFkfEr-Rr3nrAt7A,284
67
- invar/shell/commands/guard.py,sha256=vDBGOFb9mQ1D8eXrMvQB505GpjO1XLeCLrv2ig9-6dU,21718
68
- invar/shell/commands/hooks.py,sha256=W-SOnT4VQyUvXwipozkJwgEYfiOJGz7wksrbcdWegUg,2356
69
- invar/shell/commands/init.py,sha256=ASl01hIYW3Dt_d5XhYPwDfdRujbKvBGfK8B9Sf4eXq0,15117
70
- invar/shell/commands/merge.py,sha256=nuvKo8m32-OL-SCQlS4SLKmOZxQ3qj-1nGCx1Pgzifw,8183
71
- invar/shell/commands/mutate.py,sha256=GwemiO6LlbGCBEQsBFnzZuKhF-wIMEl79GAMnKUWc8U,5765
72
- invar/shell/commands/perception.py,sha256=TyH_HpqyKkmE3-zcU4YyBG8ghwJaSFeRC-OQMVBDTbQ,3837
73
- invar/shell/commands/sync_self.py,sha256=nmqBry7V2_enKwy2zzHg8UoedZNicLe3yKDhjmBeZ68,3880
74
- invar/shell/commands/template_sync.py,sha256=wVZ-UvJ1wpN2UBcWMfbei0n46XHYx-zRbMA2oX6FSi4,13723
75
- invar/shell/commands/test.py,sha256=goMf-ovvzEyWQMheq4YlJ-mwK5-w3lDj0cq0IA_1-_c,4205
76
- invar/shell/commands/uninstall.py,sha256=Q2tDbGLUf0PC2xxWqmuBYwfxX7IuSQ_SmyxvwYcDyPo,18102
77
- invar/shell/commands/update.py,sha256=0V5F8vxQ6PHPHPVYDmxdRD7xXeQEFypiJMYpY5ryiek,1349
78
- invar/shell/prove/__init__.py,sha256=ZqlbmyMFJf6yAle8634jFuPRv8wNvHps8loMlOJyf8A,240
79
- invar/shell/prove/accept.py,sha256=cnY_6jzU1EBnpLF8-zWUWcXiSXtCwxPsXEYXsSVPG38,3717
80
- invar/shell/prove/cache.py,sha256=jbNdrvfLjvK7S0iqugErqeabb4YIbQuwIlcSRyCKbcg,4105
81
- invar/shell/prove/crosshair.py,sha256=4Z_iIYBlkp-I6FqSYZa89wWB09V4Ouw2PduYhTn6rfw,16525
82
- invar/shell/prove/hypothesis.py,sha256=QUclOOUg_VB6wbmHw8O2EPiL5qBOeBRqQeM04AVuLw0,9880
83
- invar/templates/CLAUDE.md.template,sha256=eaGU3SyRO_NEifw5b26k3srgQH4jyeujjCJ-HbM36_w,4913
84
- invar/templates/__init__.py,sha256=cb3ht8KPK5oBn5oG6HsTznujmo9WriJ_P--fVxJwycc,45
85
- invar/templates/context.md.template,sha256=FKyI1ghpqcf4wftyv9-auIFHor8Nm8lETN45Ja-L8Og,2386
86
- invar/templates/manifest.toml,sha256=afovCokbqEh0nyDGdIp1LqTUslJdC8T2HY6MV-NvegY,4331
87
- invar/templates/proposal.md.template,sha256=UP7SpQ7gk8jVlHGLQCSQ5c-kCj1DBQEz8M-vEStK77I,1573
88
- invar/templates/commands/audit.md,sha256=OrotO8420zTKnlNyAyL1Eos0VIaihzEU4AHdfDv68Oc,4162
89
- invar/templates/commands/guard.md,sha256=N_C_AXd9kI85W1B0aTEycjiDp_jdaP8eeq8O0FQ_WQ8,1227
90
- invar/templates/config/AGENT.md.jinja,sha256=tadNeX5G_XLLdbLiG1JSQm_Xjmt1kAJ3IrTaw_sDU9g,5275
91
- invar/templates/config/CLAUDE.md.jinja,sha256=VbtDWxn3H8qiE9-DV1hlG3DJ-GcBQU4ZiUHbFh6Bxxk,7814
92
- invar/templates/config/context.md.jinja,sha256=_kJ8erEQNJMLDCKrv4BXWkO6OaGzE-zW9biCf7144aY,3103
93
- invar/templates/config/pre-commit.yaml.jinja,sha256=nUPxLxkTHAgZwhFAuOMDbZ8v0NQV9FlQPbr2MDEOsoA,1778
94
- invar/templates/examples/README.md,sha256=xMcJZ1KEcfLJi5Ope_4FIbqDWKK3mRleAgllvgeNT6I,572
95
- invar/templates/examples/conftest.py,sha256=uKA4NR7nyZWeSzY0URdZtw5zCcJpU32jNcaSKrI1Mxc,152
96
- invar/templates/examples/contracts.py,sha256=uqJ6Y1GADo246MjFKoLY-_2E74cfBQsLO4vTqYcR81c,3241
97
- invar/templates/examples/core_shell.py,sha256=ckor-7ZoaF7n8gVjnIO0CXlBjKGcVwmOGSDJbaXCSrM,4247
98
- invar/templates/examples/workflow.md,sha256=jAopzQH1xE9_leJFdav4oj1AkI46-a2q4L8RQCkDknw,2334
99
- invar/templates/hooks/PostToolUse.sh.jinja,sha256=H-lzVaEMvlr0uoO2LxrGNpWrBtyUkHmYrhtWmCqdAjI,2967
100
- invar/templates/hooks/PreToolUse.sh.jinja,sha256=D39PaT1eFSjz_Av16xK1atoBZbhLI8tLp8L12zkG-3k,2334
101
- invar/templates/hooks/Stop.sh.jinja,sha256=3S6lLeAGIu5aPQVRz4jjFS9AfjCD9DdS_jagmkw-x8Q,960
102
- invar/templates/hooks/UserPromptSubmit.sh.jinja,sha256=eAQqQ-XdOCyhLpF5_1r1z7C-Ej9GQ5Isqbu_2LAtsno,2302
103
- invar/templates/hooks/__init__.py,sha256=RnnMoQA-8eqbr8Y_1Vu9B8h5vAz4C-vmo8wgdcGYrz0,43
104
- invar/templates/hooks/pi/invar.ts.jinja,sha256=D1TRxHuNkmjhICPOxjcyoRUZryyz7MpfIvBLjm-krjA,2234
105
- invar/templates/protocol/INVAR.md,sha256=ppQhb_-R5YaXAqW1WDMOcXptx-CrAQI_xYxld7YljK8,9998
106
- invar/templates/skills/develop/SKILL.md.jinja,sha256=kCKXTgHtfqED__Udn3dM6OxG0FQZx1NsjFhHtDNExJA,12558
107
- invar/templates/skills/investigate/SKILL.md.jinja,sha256=cp6TBEixBYh1rLeeHOR1yqEnFqv1NZYePORMnavLkQI,3231
108
- invar/templates/skills/propose/SKILL.md.jinja,sha256=6BuKiCqO1AEu3VtzMHy1QWGqr_xqG9eJlhbsKT4jev4,3463
109
- invar/templates/skills/review/SKILL.md.jinja,sha256=OvKoomS4MJHYbTuWSZjmeS_q_Wh6uNHzjXaewj6ELEg,14596
110
- invar_tools-1.8.0.dist-info/METADATA,sha256=51-iej0SZ6ramV9uMvwlxBUZYbXTQAUc1Mi5GHJGvDw,18295
111
- invar_tools-1.8.0.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
112
- invar_tools-1.8.0.dist-info/entry_points.txt,sha256=RwH_EhqgtFPsnO6RcrwrAb70Zyfb8Mh6uUtztWnUxGk,102
113
- invar_tools-1.8.0.dist-info/licenses/LICENSE,sha256=qeFksp4H4kfTgQxPCIu3OdagXyiZcgBlVfsQ6M5oFyk,10767
114
- invar_tools-1.8.0.dist-info/licenses/LICENSE-GPL,sha256=IvZfC6ZbP7CLjytoHVzvpDZpD-Z3R_qa1GdMdWlWQ6Q,35157
115
- invar_tools-1.8.0.dist-info/licenses/NOTICE,sha256=joEyMyFhFY8Vd8tTJ-a3SirI0m2Sd0WjzqYt3sdcglc,2561
116
- invar_tools-1.8.0.dist-info/RECORD,,