invar-tools 1.17.24__py3-none-any.whl → 1.17.26__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.
- invar/core/utils.py +18 -3
- invar/shell/config.py +31 -13
- invar/shell/property_tests.py +176 -48
- {invar_tools-1.17.24.dist-info → invar_tools-1.17.26.dist-info}/METADATA +1 -1
- {invar_tools-1.17.24.dist-info → invar_tools-1.17.26.dist-info}/RECORD +10 -10
- {invar_tools-1.17.24.dist-info → invar_tools-1.17.26.dist-info}/WHEEL +0 -0
- {invar_tools-1.17.24.dist-info → invar_tools-1.17.26.dist-info}/entry_points.txt +0 -0
- {invar_tools-1.17.24.dist-info → invar_tools-1.17.26.dist-info}/licenses/LICENSE +0 -0
- {invar_tools-1.17.24.dist-info → invar_tools-1.17.26.dist-info}/licenses/LICENSE-GPL +0 -0
- {invar_tools-1.17.24.dist-info → invar_tools-1.17.26.dist-info}/licenses/NOTICE +0 -0
invar/core/utils.py
CHANGED
|
@@ -37,7 +37,13 @@ def get_exit_code(report: GuardReport, strict: bool) -> int:
|
|
|
37
37
|
return 0
|
|
38
38
|
|
|
39
39
|
|
|
40
|
-
@pre(
|
|
40
|
+
@pre(
|
|
41
|
+
lambda report,
|
|
42
|
+
strict,
|
|
43
|
+
doctest_passed=True,
|
|
44
|
+
crosshair_passed=True,
|
|
45
|
+
property_passed=True: report.files_checked >= 0
|
|
46
|
+
)
|
|
41
47
|
@post(lambda result: result in ("passed", "failed"))
|
|
42
48
|
def get_combined_status(
|
|
43
49
|
report: GuardReport,
|
|
@@ -204,7 +210,9 @@ def _parse_rule_exclusions(config: dict[str, Any]) -> list[RuleExclusion] | None
|
|
|
204
210
|
if isinstance(excl, dict) and "pattern" in excl and "rules" in excl:
|
|
205
211
|
pattern, rules = excl["pattern"], excl["rules"]
|
|
206
212
|
if isinstance(pattern, str) and isinstance(rules, list):
|
|
207
|
-
exclusions.append(
|
|
213
|
+
exclusions.append(
|
|
214
|
+
RuleExclusion(pattern=str(pattern), rules=[str(r) for r in rules])
|
|
215
|
+
)
|
|
208
216
|
return exclusions if exclusions else None
|
|
209
217
|
|
|
210
218
|
|
|
@@ -253,7 +261,14 @@ def parse_guard_config(guard_config: dict[str, Any]) -> RuleConfig:
|
|
|
253
261
|
kwargs: dict[str, Any] = {}
|
|
254
262
|
|
|
255
263
|
# Int fields
|
|
256
|
-
for key in (
|
|
264
|
+
for key in (
|
|
265
|
+
"max_file_lines",
|
|
266
|
+
"max_function_lines",
|
|
267
|
+
"timeout_doctest",
|
|
268
|
+
"timeout_hypothesis",
|
|
269
|
+
"timeout_crosshair",
|
|
270
|
+
"timeout_crosshair_per_condition",
|
|
271
|
+
):
|
|
257
272
|
if (val := _get_int(guard_config, key)) is not None:
|
|
258
273
|
kwargs[key] = val
|
|
259
274
|
|
invar/shell/config.py
CHANGED
|
@@ -435,24 +435,42 @@ _DEFAULT_EXCLUDE_PATHS = [
|
|
|
435
435
|
]
|
|
436
436
|
|
|
437
437
|
|
|
438
|
+
# @shell_complexity: Config fallthrough requires checking multiple sources
|
|
438
439
|
def _get_classification_config(project_root: Path) -> Result[dict[str, Any], str]:
|
|
439
|
-
"""Get classification-related config (paths and patterns).
|
|
440
|
-
find_result = _find_config_source(project_root)
|
|
441
|
-
if isinstance(find_result, Failure):
|
|
442
|
-
return Success({}) # Return empty on error
|
|
443
|
-
config_path, source = find_result.unwrap()
|
|
440
|
+
"""Get classification-related config (paths and patterns).
|
|
444
441
|
|
|
445
|
-
if
|
|
446
|
-
|
|
442
|
+
Uses fallthrough logic: if pyproject.toml exists but has no [tool.invar.guard],
|
|
443
|
+
continues to check invar.toml and .invar/config.toml.
|
|
444
|
+
"""
|
|
445
|
+
# Build list of config sources to try (same order as load_config)
|
|
446
|
+
sources_to_try: list[tuple[Path, ConfigSource]] = []
|
|
447
|
+
|
|
448
|
+
pyproject = project_root / "pyproject.toml"
|
|
449
|
+
if pyproject.exists():
|
|
450
|
+
sources_to_try.append((pyproject, "pyproject"))
|
|
447
451
|
|
|
448
|
-
|
|
449
|
-
|
|
452
|
+
invar_toml = project_root / "invar.toml"
|
|
453
|
+
if invar_toml.exists():
|
|
454
|
+
sources_to_try.append((invar_toml, "invar"))
|
|
450
455
|
|
|
451
|
-
|
|
452
|
-
|
|
456
|
+
invar_config = project_root / ".invar" / "config.toml"
|
|
457
|
+
if invar_config.exists():
|
|
458
|
+
sources_to_try.append((invar_config, "invar_dir"))
|
|
459
|
+
|
|
460
|
+
# Try each source, fallback if no guard config found
|
|
461
|
+
for config_path, source in sources_to_try:
|
|
462
|
+
result = _read_toml(config_path)
|
|
463
|
+
if isinstance(result, Failure):
|
|
464
|
+
continue # Skip unreadable files
|
|
465
|
+
|
|
466
|
+
data = result.unwrap()
|
|
467
|
+
guard_config = extract_guard_section(data, source)
|
|
468
|
+
|
|
469
|
+
if guard_config: # Found valid guard config
|
|
470
|
+
return Success(guard_config)
|
|
453
471
|
|
|
454
|
-
|
|
455
|
-
return Success(
|
|
472
|
+
# No config found in any source, return empty dict
|
|
473
|
+
return Success({})
|
|
456
474
|
|
|
457
475
|
|
|
458
476
|
def get_path_classification(project_root: Path) -> Result[tuple[list[str], list[str]], str]:
|
invar/shell/property_tests.py
CHANGED
|
@@ -7,13 +7,10 @@ Handles I/O and file scanning, returns Result[T, E].
|
|
|
7
7
|
|
|
8
8
|
from __future__ import annotations
|
|
9
9
|
|
|
10
|
-
import importlib.util
|
|
11
10
|
import sys
|
|
11
|
+
import tomllib
|
|
12
12
|
from contextlib import contextmanager, suppress
|
|
13
|
-
from
|
|
14
|
-
|
|
15
|
-
if TYPE_CHECKING:
|
|
16
|
-
from pathlib import Path
|
|
13
|
+
from pathlib import Path
|
|
17
14
|
|
|
18
15
|
from returns.result import Failure, Result, Success
|
|
19
16
|
from rich.console import Console
|
|
@@ -24,9 +21,98 @@ from invar.shell.subprocess_env import detect_project_venv, find_site_packages
|
|
|
24
21
|
console = Console()
|
|
25
22
|
|
|
26
23
|
|
|
24
|
+
def _extract_src_dirs_from_paths(project_root: Path, paths: list[str]) -> set[str]:
|
|
25
|
+
"""
|
|
26
|
+
Extract unique src directories from configured paths.
|
|
27
|
+
|
|
28
|
+
For monorepo structures like 'packages/pkg-a/src/pkg_a/core',
|
|
29
|
+
extracts 'packages/pkg-a/src' as the directory to add to sys.path.
|
|
30
|
+
|
|
31
|
+
Examples:
|
|
32
|
+
>>> from pathlib import Path
|
|
33
|
+
>>> root = Path("/project")
|
|
34
|
+
>>> paths = ["packages/a/src/pkg/core", "packages/b/src/pkg/shell"]
|
|
35
|
+
>>> # Returns src dirs (would check existence in real use)
|
|
36
|
+
>>> sorted(_extract_src_dirs_from_paths(root, paths)) # doctest: +SKIP
|
|
37
|
+
['/project/packages/a/src', '/project/packages/b/src']
|
|
38
|
+
"""
|
|
39
|
+
src_dirs: set[str] = set()
|
|
40
|
+
for p in paths:
|
|
41
|
+
parts = Path(p).parts
|
|
42
|
+
if "src" in parts:
|
|
43
|
+
idx = parts.index("src")
|
|
44
|
+
src_dir = project_root / Path(*parts[: idx + 1])
|
|
45
|
+
if src_dir.exists():
|
|
46
|
+
src_dirs.add(str(src_dir))
|
|
47
|
+
return src_dirs
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
# @shell_complexity: Config fallthrough requires checking 3 sources with error handling
|
|
51
|
+
def _get_invar_paths_from_config(project_root: Path) -> list[str]:
|
|
52
|
+
"""
|
|
53
|
+
Get 'paths' from [tool.invar] config across all config locations.
|
|
54
|
+
|
|
55
|
+
Checks in priority order:
|
|
56
|
+
1. pyproject.toml [tool.invar].paths
|
|
57
|
+
2. invar.toml [invar].paths (root level)
|
|
58
|
+
3. .invar/config.toml [invar].paths (root level)
|
|
59
|
+
|
|
60
|
+
Returns first found, or empty list.
|
|
61
|
+
"""
|
|
62
|
+
# 1. pyproject.toml [tool.invar].paths
|
|
63
|
+
pyproject = project_root / "pyproject.toml"
|
|
64
|
+
if pyproject.exists():
|
|
65
|
+
try:
|
|
66
|
+
with pyproject.open("rb") as f:
|
|
67
|
+
data = tomllib.load(f)
|
|
68
|
+
paths = data.get("tool", {}).get("invar", {}).get("paths", [])
|
|
69
|
+
if paths:
|
|
70
|
+
return paths
|
|
71
|
+
except Exception:
|
|
72
|
+
pass
|
|
73
|
+
|
|
74
|
+
# 2. invar.toml [invar].paths (root level, since no [tool] wrapper)
|
|
75
|
+
invar_toml = project_root / "invar.toml"
|
|
76
|
+
if invar_toml.exists():
|
|
77
|
+
try:
|
|
78
|
+
with invar_toml.open("rb") as f:
|
|
79
|
+
data = tomllib.load(f)
|
|
80
|
+
# In invar.toml, paths could be at root or under [invar]
|
|
81
|
+
paths = data.get("paths", []) or data.get("invar", {}).get("paths", [])
|
|
82
|
+
if paths:
|
|
83
|
+
return paths
|
|
84
|
+
except Exception:
|
|
85
|
+
pass
|
|
86
|
+
|
|
87
|
+
# 3. .invar/config.toml
|
|
88
|
+
invar_config = project_root / ".invar" / "config.toml"
|
|
89
|
+
if invar_config.exists():
|
|
90
|
+
try:
|
|
91
|
+
with invar_config.open("rb") as f:
|
|
92
|
+
data = tomllib.load(f)
|
|
93
|
+
paths = data.get("paths", []) or data.get("invar", {}).get("paths", [])
|
|
94
|
+
if paths:
|
|
95
|
+
return paths
|
|
96
|
+
except Exception:
|
|
97
|
+
pass
|
|
98
|
+
|
|
99
|
+
return []
|
|
100
|
+
|
|
101
|
+
|
|
27
102
|
# @shell_orchestration: Temporarily inject venv site-packages for module imports
|
|
103
|
+
# @shell_complexity: Monorepo support requires reading config and extracting src dirs
|
|
28
104
|
@contextmanager
|
|
29
105
|
def _inject_project_site_packages(project_root: Path):
|
|
106
|
+
"""
|
|
107
|
+
Context manager that temporarily injects project dependencies into sys.path.
|
|
108
|
+
|
|
109
|
+
Supports:
|
|
110
|
+
- Standard layout: project_root/src
|
|
111
|
+
- Monorepo layout: paths from config (pyproject.toml, invar.toml, .invar/config.toml)
|
|
112
|
+
- Configured paths: extracted from core_paths/shell_paths in [tool.invar.guard]
|
|
113
|
+
"""
|
|
114
|
+
from invar.shell.config import get_path_classification
|
|
115
|
+
|
|
30
116
|
venv = detect_project_venv(project_root)
|
|
31
117
|
site_packages = find_site_packages(venv) if venv is not None else None
|
|
32
118
|
|
|
@@ -34,13 +120,35 @@ def _inject_project_site_packages(project_root: Path):
|
|
|
34
120
|
yield
|
|
35
121
|
return
|
|
36
122
|
|
|
37
|
-
src_dir = project_root / "src"
|
|
38
|
-
|
|
39
123
|
added: list[str] = []
|
|
124
|
+
|
|
125
|
+
# 1. Read 'paths' from config (supports pyproject.toml, invar.toml, .invar/config.toml)
|
|
126
|
+
invar_paths = _get_invar_paths_from_config(project_root)
|
|
127
|
+
for p in invar_paths:
|
|
128
|
+
src_dir = project_root / p
|
|
129
|
+
if src_dir.exists():
|
|
130
|
+
src_dir_str = str(src_dir)
|
|
131
|
+
if src_dir_str not in added:
|
|
132
|
+
sys.path.insert(0, src_dir_str)
|
|
133
|
+
added.append(src_dir_str)
|
|
134
|
+
|
|
135
|
+
# 2. Extract src dirs from core_paths and shell_paths config
|
|
136
|
+
path_result = get_path_classification(project_root)
|
|
137
|
+
if isinstance(path_result, Success):
|
|
138
|
+
core_paths, shell_paths = path_result.unwrap()
|
|
139
|
+
src_dirs = _extract_src_dirs_from_paths(project_root, core_paths + shell_paths)
|
|
140
|
+
for src_dir_str in src_dirs:
|
|
141
|
+
if src_dir_str not in added:
|
|
142
|
+
sys.path.insert(0, src_dir_str)
|
|
143
|
+
added.append(src_dir_str)
|
|
144
|
+
|
|
145
|
+
# 3. Fallback to project_root/src (standard layout)
|
|
146
|
+
src_dir = project_root / "src"
|
|
40
147
|
if src_dir.exists():
|
|
41
148
|
src_dir_str = str(src_dir)
|
|
42
|
-
|
|
43
|
-
|
|
149
|
+
if src_dir_str not in added:
|
|
150
|
+
sys.path.insert(0, src_dir_str)
|
|
151
|
+
added.append(src_dir_str)
|
|
44
152
|
|
|
45
153
|
site_packages_str = str(site_packages)
|
|
46
154
|
sys.path.insert(0, site_packages_str)
|
|
@@ -218,64 +326,84 @@ def _accumulate_report(
|
|
|
218
326
|
combined_report.errors.extend(file_report.errors)
|
|
219
327
|
|
|
220
328
|
|
|
329
|
+
# @shell_complexity: Path traversal logic for monorepo src detection
|
|
330
|
+
def _find_module_root(file_path: Path, project_root: Path | None) -> Path | None:
|
|
331
|
+
"""
|
|
332
|
+
Find the module root directory (the directory that should be in sys.path).
|
|
333
|
+
|
|
334
|
+
For monorepo structures, finds the 'src' directory containing the file.
|
|
335
|
+
Falls back to project_root for standard layouts.
|
|
336
|
+
|
|
337
|
+
Examples:
|
|
338
|
+
>>> from pathlib import Path
|
|
339
|
+
>>> # Standard layout: project/src/pkg/module.py -> project/src
|
|
340
|
+
>>> # Monorepo: project/packages/a/src/pkg/module.py -> project/packages/a/src
|
|
341
|
+
"""
|
|
342
|
+
if project_root is None:
|
|
343
|
+
return None
|
|
344
|
+
|
|
345
|
+
# Check if file is under a 'src' directory
|
|
346
|
+
try:
|
|
347
|
+
relative = file_path.relative_to(project_root)
|
|
348
|
+
parts = relative.parts
|
|
349
|
+
|
|
350
|
+
if "src" in parts:
|
|
351
|
+
idx = parts.index("src")
|
|
352
|
+
# Return the src directory itself
|
|
353
|
+
return project_root / Path(*parts[: idx + 1])
|
|
354
|
+
except ValueError:
|
|
355
|
+
pass
|
|
356
|
+
|
|
357
|
+
# Fallback: check if project_root/src exists and contains the file
|
|
358
|
+
src_dir = project_root / "src"
|
|
359
|
+
if src_dir.exists():
|
|
360
|
+
try:
|
|
361
|
+
file_path.relative_to(src_dir)
|
|
362
|
+
return src_dir
|
|
363
|
+
except ValueError:
|
|
364
|
+
pass
|
|
365
|
+
|
|
366
|
+
return project_root
|
|
367
|
+
|
|
368
|
+
|
|
221
369
|
# @shell_complexity: BUG-57 fix requires package hierarchy setup for relative imports
|
|
222
370
|
def _import_module_from_path(file_path: Path, project_root: Path | None = None) -> object | None:
|
|
223
371
|
"""
|
|
224
372
|
Import a Python module from a file path.
|
|
225
373
|
|
|
226
374
|
BUG-57: Properly handles relative imports by setting up package context.
|
|
375
|
+
Monorepo fix: Calculates module name relative to src directory, not project root.
|
|
227
376
|
|
|
228
377
|
Returns None if import fails.
|
|
229
378
|
"""
|
|
379
|
+
import importlib
|
|
380
|
+
|
|
230
381
|
try:
|
|
231
|
-
#
|
|
232
|
-
|
|
233
|
-
|
|
382
|
+
# Find the module root (src directory) for this file
|
|
383
|
+
module_root = _find_module_root(file_path, project_root)
|
|
384
|
+
|
|
385
|
+
# Calculate module name relative to module_root (not project_root!)
|
|
386
|
+
if module_root and file_path.is_relative_to(module_root):
|
|
387
|
+
relative = file_path.relative_to(module_root)
|
|
388
|
+
parts = list(relative.with_suffix("").parts)
|
|
389
|
+
module_name = ".".join(parts)
|
|
390
|
+
elif project_root and file_path.is_relative_to(project_root):
|
|
391
|
+
# Fallback to project_root relative path
|
|
234
392
|
relative = file_path.relative_to(project_root)
|
|
235
393
|
parts = list(relative.with_suffix("").parts)
|
|
236
394
|
module_name = ".".join(parts)
|
|
237
395
|
else:
|
|
238
396
|
module_name = file_path.stem
|
|
239
397
|
|
|
240
|
-
# Ensure
|
|
241
|
-
if
|
|
242
|
-
root_str = str(
|
|
398
|
+
# Ensure module root is in sys.path
|
|
399
|
+
if module_root:
|
|
400
|
+
root_str = str(module_root)
|
|
243
401
|
if root_str not in sys.path:
|
|
244
402
|
sys.path.insert(0, root_str)
|
|
245
403
|
|
|
246
|
-
#
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
parts = module_name.split(".")
|
|
250
|
-
for i in range(1, len(parts)):
|
|
251
|
-
parent_name = ".".join(parts[:i])
|
|
252
|
-
if parent_name not in sys.modules:
|
|
253
|
-
parent_path = project_root / "/".join(parts[:i]) if project_root else None
|
|
254
|
-
if parent_path and (parent_path / "__init__.py").exists():
|
|
255
|
-
parent_spec = importlib.util.spec_from_file_location(
|
|
256
|
-
parent_name,
|
|
257
|
-
parent_path / "__init__.py",
|
|
258
|
-
submodule_search_locations=[str(parent_path)],
|
|
259
|
-
)
|
|
260
|
-
if parent_spec and parent_spec.loader:
|
|
261
|
-
parent_module = importlib.util.module_from_spec(parent_spec)
|
|
262
|
-
sys.modules[parent_name] = parent_module
|
|
263
|
-
parent_spec.loader.exec_module(parent_module)
|
|
264
|
-
|
|
265
|
-
# Now import the target module
|
|
266
|
-
spec = importlib.util.spec_from_file_location(
|
|
267
|
-
module_name,
|
|
268
|
-
file_path,
|
|
269
|
-
submodule_search_locations=[str(file_path.parent)],
|
|
270
|
-
)
|
|
271
|
-
if spec is None or spec.loader is None:
|
|
272
|
-
return None
|
|
273
|
-
|
|
274
|
-
module = importlib.util.module_from_spec(spec)
|
|
275
|
-
sys.modules[module_name] = module
|
|
276
|
-
|
|
277
|
-
# Suppress output during import
|
|
278
|
-
spec.loader.exec_module(module)
|
|
404
|
+
# Use importlib.import_module which correctly handles relative imports
|
|
405
|
+
# This is simpler and more reliable than manual spec loading
|
|
406
|
+
module = importlib.import_module(module_name)
|
|
279
407
|
return module
|
|
280
408
|
|
|
281
409
|
except Exception:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: invar-tools
|
|
3
|
-
Version: 1.17.
|
|
3
|
+
Version: 1.17.26
|
|
4
4
|
Summary: AI-native software engineering tools with design-by-contract verification
|
|
5
5
|
Project-URL: Homepage, https://github.com/tefx/invar
|
|
6
6
|
Project-URL: Documentation, https://github.com/tefx/invar#readme
|
|
@@ -37,7 +37,7 @@ invar/core/timeout_inference.py,sha256=BS2fJGmwOrLpYZUku4qrizgNDSIXVLFBslW-6sRAv
|
|
|
37
37
|
invar/core/trivial_detection.py,sha256=KYP8jJb7QDeusAxFdX5NAML_H0NL5wLgMeBWDQmNqfU,6086
|
|
38
38
|
invar/core/ts_parsers.py,sha256=gXvLgb141gD8VAtiW4T1aaRnaSv10BEm0XYqArYIN00,8743
|
|
39
39
|
invar/core/ts_sig_parser.py,sha256=_lUNfArFPILpENo-1dqmPY1qoVmcfAehv2Tva3r6dzw,9931
|
|
40
|
-
invar/core/utils.py,sha256=
|
|
40
|
+
invar/core/utils.py,sha256=BMzMOJuCZ7I74AdM0PImzHypnIMO5OqsO9ms84x-fH0,14478
|
|
41
41
|
invar/core/verification_routing.py,sha256=_jXi1txFCcUdnB3-Yavtuyk8N-XhEO_Vu_051Vuz27Y,5020
|
|
42
42
|
invar/core/patterns/__init__.py,sha256=79a3ucN0BI54RnIOe49lngKASpADygs1hll9ROCrP6s,1429
|
|
43
43
|
invar/core/patterns/detector.py,sha256=lUfED7qk2VWOAjHoGWgSqll5ynhhdzd6CjCiol-7kV8,8690
|
|
@@ -2657,7 +2657,7 @@ invar/node_tools/quick-check/cli.js,sha256=dwV3hdJleFQga2cKUn3PPfQDvvujhzKdjQcIv
|
|
|
2657
2657
|
invar/node_tools/ts-analyzer/cli.js,sha256=SvZ6HyjmobpP8NAZqXFiy8BwH_t5Hb17Ytar_18udaQ,4092887
|
|
2658
2658
|
invar/shell/__init__.py,sha256=FFw1mNbh_97PeKPcHIqQpQ7mw-JoIvyLM1yOdxLw5uk,204
|
|
2659
2659
|
invar/shell/claude_hooks.py,sha256=hV4DfG3cVng32f0Rxoo070tliVlYFC5v9slIWEbAD7E,18899
|
|
2660
|
-
invar/shell/config.py,sha256=
|
|
2660
|
+
invar/shell/config.py,sha256=fPKY1AAqM28vcIIasvitYqqCv3g5VAjCdS8M7dNbQWA,19331
|
|
2661
2661
|
invar/shell/contract_coverage.py,sha256=81OQkQqUVYUKytG5aiJyRK62gwh9UzbSG926vkvFTc8,12088
|
|
2662
2662
|
invar/shell/coverage.py,sha256=m01o898IFIdBztEBQLwwL1Vt5PWrpUntO4lv4nWEkls,11344
|
|
2663
2663
|
invar/shell/doc_tools.py,sha256=16gvo_ay9-_EK6lX16WkiRGg4OfTAKK_i0ucQkE7lbI,15149
|
|
@@ -2670,7 +2670,7 @@ invar/shell/mutation.py,sha256=Lfyk2b8j8-hxAq-iwAgQeOhr7Ci6c5tRF1TXe3CxQCs,8914
|
|
|
2670
2670
|
invar/shell/pattern_integration.py,sha256=pRcjfq3NvMW_tvQCnaXZnD1k5AVEWK8CYOE2jN6VTro,7842
|
|
2671
2671
|
invar/shell/pi_hooks.py,sha256=ulZc1sP8mTRJTBsjwFHQzUgg-h8ajRIMp7iF1Y4UUtw,6885
|
|
2672
2672
|
invar/shell/pi_tools.py,sha256=a3ACDDXykFV8fUB5UpBmgMvppwkmLvT1k_BWm0IY47k,4068
|
|
2673
|
-
invar/shell/property_tests.py,sha256=
|
|
2673
|
+
invar/shell/property_tests.py,sha256=zKkCh03MaWTLnz_gfdTMeCGb2RMK_sz0L8PAcD8-iVU,17031
|
|
2674
2674
|
invar/shell/py_refs.py,sha256=Vjz50lmt9prDBcBv4nkkODdiJ7_DKu5zO4UPZBjAfmM,4638
|
|
2675
2675
|
invar/shell/skill_manager.py,sha256=Mr7Mh9rxPSKSAOTJCAM5ZHiG5nfUf6KQVCuD4LBNHSI,12440
|
|
2676
2676
|
invar/shell/subprocess_env.py,sha256=hendEERSyAG4a8UFhYfPtOAlfspVRB03aVCYpj3uqk4,12745
|
|
@@ -2778,10 +2778,10 @@ invar/templates/skills/invar-reflect/template.md,sha256=Rr5hvbllvmd8jSLf_0ZjyKt6
|
|
|
2778
2778
|
invar/templates/skills/investigate/SKILL.md.jinja,sha256=cp6TBEixBYh1rLeeHOR1yqEnFqv1NZYePORMnavLkQI,3231
|
|
2779
2779
|
invar/templates/skills/propose/SKILL.md.jinja,sha256=6BuKiCqO1AEu3VtzMHy1QWGqr_xqG9eJlhbsKT4jev4,3463
|
|
2780
2780
|
invar/templates/skills/review/SKILL.md.jinja,sha256=ET5mbdSe_eKgJbi2LbgFC-z1aviKcHOBw7J5Q28fr4U,14105
|
|
2781
|
-
invar_tools-1.17.
|
|
2782
|
-
invar_tools-1.17.
|
|
2783
|
-
invar_tools-1.17.
|
|
2784
|
-
invar_tools-1.17.
|
|
2785
|
-
invar_tools-1.17.
|
|
2786
|
-
invar_tools-1.17.
|
|
2787
|
-
invar_tools-1.17.
|
|
2781
|
+
invar_tools-1.17.26.dist-info/METADATA,sha256=3iy3Ed3UYlIp66dIVkA4DvQZbADVG_IzGkYrmgLu7dI,28582
|
|
2782
|
+
invar_tools-1.17.26.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
2783
|
+
invar_tools-1.17.26.dist-info/entry_points.txt,sha256=RwH_EhqgtFPsnO6RcrwrAb70Zyfb8Mh6uUtztWnUxGk,102
|
|
2784
|
+
invar_tools-1.17.26.dist-info/licenses/LICENSE,sha256=qeFksp4H4kfTgQxPCIu3OdagXyiZcgBlVfsQ6M5oFyk,10767
|
|
2785
|
+
invar_tools-1.17.26.dist-info/licenses/LICENSE-GPL,sha256=IvZfC6ZbP7CLjytoHVzvpDZpD-Z3R_qa1GdMdWlWQ6Q,35157
|
|
2786
|
+
invar_tools-1.17.26.dist-info/licenses/NOTICE,sha256=joEyMyFhFY8Vd8tTJ-a3SirI0m2Sd0WjzqYt3sdcglc,2561
|
|
2787
|
+
invar_tools-1.17.26.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|