invar-tools 1.17.8__py3-none-any.whl → 1.17.10__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/mcp/handlers.py +5 -3
- invar/shell/commands/guard.py +32 -32
- {invar_tools-1.17.8.dist-info → invar_tools-1.17.10.dist-info}/METADATA +1 -1
- {invar_tools-1.17.8.dist-info → invar_tools-1.17.10.dist-info}/RECORD +9 -9
- {invar_tools-1.17.8.dist-info → invar_tools-1.17.10.dist-info}/WHEEL +0 -0
- {invar_tools-1.17.8.dist-info → invar_tools-1.17.10.dist-info}/entry_points.txt +0 -0
- {invar_tools-1.17.8.dist-info → invar_tools-1.17.10.dist-info}/licenses/LICENSE +0 -0
- {invar_tools-1.17.8.dist-info → invar_tools-1.17.10.dist-info}/licenses/LICENSE-GPL +0 -0
- {invar_tools-1.17.8.dist-info → invar_tools-1.17.10.dist-info}/licenses/NOTICE +0 -0
invar/mcp/handlers.py
CHANGED
|
@@ -11,12 +11,14 @@ import json
|
|
|
11
11
|
import subprocess
|
|
12
12
|
import sys
|
|
13
13
|
from pathlib import Path
|
|
14
|
-
from typing import Any, Literal
|
|
14
|
+
from typing import TYPE_CHECKING, Any, Literal
|
|
15
15
|
|
|
16
|
-
from mcp.server.lowlevel.server import StructuredContent, CombinationContent
|
|
17
16
|
from mcp.types import TextContent
|
|
18
17
|
from returns.result import Success
|
|
19
18
|
|
|
19
|
+
if TYPE_CHECKING:
|
|
20
|
+
from mcp.server.lowlevel.server import CombinationContent
|
|
21
|
+
|
|
20
22
|
|
|
21
23
|
# @invar:allow shell_result: Pure validation helper, no I/O, returns tuple not Result
|
|
22
24
|
# @shell_complexity: Security validation requires multiple checks
|
|
@@ -435,6 +437,6 @@ async def _execute_command(
|
|
|
435
437
|
return [TextContent(type="text", text=output)]
|
|
436
438
|
|
|
437
439
|
except subprocess.TimeoutExpired:
|
|
438
|
-
return [TextContent(type="text", text=f"Error: Command timed out ({timeout}s")]
|
|
440
|
+
return [TextContent(type="text", text=f"Error: Command timed out ({timeout}s)")]
|
|
439
441
|
except Exception as e:
|
|
440
442
|
return [TextContent(type="text", text=f"Error: {e}")]
|
invar/shell/commands/guard.py
CHANGED
|
@@ -6,7 +6,6 @@ Shell module: handles user interaction and file I/O.
|
|
|
6
6
|
|
|
7
7
|
from __future__ import annotations
|
|
8
8
|
|
|
9
|
-
import os
|
|
10
9
|
from pathlib import Path
|
|
11
10
|
|
|
12
11
|
import typer
|
|
@@ -14,7 +13,6 @@ from returns.result import Failure, Result, Success
|
|
|
14
13
|
from rich.console import Console
|
|
15
14
|
from rich.table import Table
|
|
16
15
|
|
|
17
|
-
|
|
18
16
|
from invar import __version__
|
|
19
17
|
from invar.core.models import GuardReport, RuleConfig
|
|
20
18
|
from invar.core.rules import check_all_rules
|
|
@@ -111,6 +109,10 @@ def _scan_and_check(
|
|
|
111
109
|
return Success(report)
|
|
112
110
|
|
|
113
111
|
|
|
112
|
+
def _determine_output_mode(human: bool, agent: bool = False, json_output: bool = False) -> bool:
|
|
113
|
+
return not human
|
|
114
|
+
|
|
115
|
+
|
|
114
116
|
# @invar:allow entry_point_too_thick: Main CLI entry point, orchestrates all verification phases
|
|
115
117
|
@app.command()
|
|
116
118
|
def guard(
|
|
@@ -259,7 +261,34 @@ def guard(
|
|
|
259
261
|
changed_result = handle_changed_mode(path)
|
|
260
262
|
if isinstance(changed_result, Failure):
|
|
261
263
|
if changed_result.failure() == "NO_CHANGES":
|
|
262
|
-
|
|
264
|
+
use_agent_output = _determine_output_mode(human, agent, json_output)
|
|
265
|
+
if use_agent_output:
|
|
266
|
+
import json
|
|
267
|
+
|
|
268
|
+
console.print(
|
|
269
|
+
json.dumps(
|
|
270
|
+
{
|
|
271
|
+
"status": "passed",
|
|
272
|
+
"static": {"passed": True, "errors": 0, "warnings": 0, "infos": 0},
|
|
273
|
+
"summary": {
|
|
274
|
+
"files_checked": 0,
|
|
275
|
+
"errors": 0,
|
|
276
|
+
"warnings": 0,
|
|
277
|
+
"infos": 0,
|
|
278
|
+
},
|
|
279
|
+
"fixes": [],
|
|
280
|
+
"verification_level": "STANDARD",
|
|
281
|
+
"doctest": {"passed": True, "output": ""},
|
|
282
|
+
"crosshair": {"status": "skipped", "reason": "no changed files"},
|
|
283
|
+
"property_tests": {
|
|
284
|
+
"status": "skipped",
|
|
285
|
+
"reason": "no changed files",
|
|
286
|
+
},
|
|
287
|
+
}
|
|
288
|
+
)
|
|
289
|
+
)
|
|
290
|
+
else:
|
|
291
|
+
console.print("[green]No changed files to verify.[/green]")
|
|
263
292
|
raise typer.Exit(0)
|
|
264
293
|
console.print(f"[red]Error:[/red] {changed_result.failure()}")
|
|
265
294
|
raise typer.Exit(1)
|
|
@@ -420,27 +449,6 @@ def guard(
|
|
|
420
449
|
raise typer.Exit(final_exit)
|
|
421
450
|
|
|
422
451
|
|
|
423
|
-
# @shell_orchestration: Output mode decision helper for CLI
|
|
424
|
-
def _determine_output_mode(human: bool, agent: bool = False, json_output: bool = False) -> bool:
|
|
425
|
-
"""Determine if agent JSON output should be used (Agent First).
|
|
426
|
-
|
|
427
|
-
Agent First principle: Machine-readable JSON is the default output format.
|
|
428
|
-
Human-readable Rich output is opt-in via --human flag.
|
|
429
|
-
|
|
430
|
-
Priority:
|
|
431
|
-
- --human flag → human output (Rich, colored)
|
|
432
|
-
- Default → JSON output (machine-readable, Agent Native)
|
|
433
|
-
- --agent/--json flags → no-op (already default, kept for backward compat)
|
|
434
|
-
"""
|
|
435
|
-
# --human flag forces human output (priority highest)
|
|
436
|
-
if human:
|
|
437
|
-
return False # use_agent = False
|
|
438
|
-
|
|
439
|
-
# Default to JSON output (Agent First)
|
|
440
|
-
# --agent/--json are now no-ops but kept for backward compatibility
|
|
441
|
-
return True
|
|
442
|
-
|
|
443
|
-
|
|
444
452
|
def _show_verification_level(verification_level) -> None:
|
|
445
453
|
"""Show verification level in human-readable format.
|
|
446
454
|
|
|
@@ -470,8 +478,6 @@ def map_command(
|
|
|
470
478
|
"""Generate symbol map with reference counts."""
|
|
471
479
|
from invar.shell.commands.perception import run_map
|
|
472
480
|
|
|
473
|
-
# Agent First: Default to JSON output
|
|
474
|
-
# --json is now a no-op (kept for backward compat)
|
|
475
481
|
use_json = True
|
|
476
482
|
result = run_map(path, top, use_json)
|
|
477
483
|
if isinstance(result, Failure):
|
|
@@ -487,8 +493,6 @@ def sig_command(
|
|
|
487
493
|
"""Extract signatures from a file or symbol."""
|
|
488
494
|
from invar.shell.commands.perception import run_sig
|
|
489
495
|
|
|
490
|
-
# Agent First: Default to JSON output
|
|
491
|
-
# --json is now a no-op (kept for backward compat)
|
|
492
496
|
use_json = True
|
|
493
497
|
result = run_sig(target, use_json)
|
|
494
498
|
if isinstance(result, Failure):
|
|
@@ -512,8 +516,6 @@ def refs_command(
|
|
|
512
516
|
"""
|
|
513
517
|
from invar.shell.commands.perception import run_refs
|
|
514
518
|
|
|
515
|
-
# Agent First: Default to JSON output
|
|
516
|
-
# --json is now a no-op (kept for backward compat)
|
|
517
519
|
use_json = True
|
|
518
520
|
result = run_refs(target, use_json)
|
|
519
521
|
if isinstance(result, Failure):
|
|
@@ -538,8 +540,6 @@ def rules(
|
|
|
538
540
|
|
|
539
541
|
from invar.core.rule_meta import RULE_META, RuleCategory, get_rules_by_category
|
|
540
542
|
|
|
541
|
-
# Agent First: Default to JSON output
|
|
542
|
-
# --json is now a no-op (kept for backward compat)
|
|
543
543
|
use_json = True
|
|
544
544
|
|
|
545
545
|
# Filter by category if specified
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: invar-tools
|
|
3
|
-
Version: 1.17.
|
|
3
|
+
Version: 1.17.10
|
|
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
|
|
@@ -50,7 +50,7 @@ invar/core/patterns/registry.py,sha256=2rz0wWDRarMkuHN-qM_ZrT3qeGFDSKMABvRvPNZxQ
|
|
|
50
50
|
invar/core/patterns/types.py,sha256=ULAlWuAdmO6CFcEDjTrWBfzNTBsnomAl2d25tR11ihU,5506
|
|
51
51
|
invar/mcp/__init__.py,sha256=n3S7QwMjSMqOMT8cI2jf9E0yZPjKmBOJyIYhq4WZ8TQ,226
|
|
52
52
|
invar/mcp/__main__.py,sha256=ZcIT2U6xUyGOWucl4jq422BDE3lRLjqyxb9pFylRBdk,219
|
|
53
|
-
invar/mcp/handlers.py,sha256=
|
|
53
|
+
invar/mcp/handlers.py,sha256=3khWBATWxV4TwHPm6Gnr9pWfGaPyxf5p8yR-pnJhDtg,16756
|
|
54
54
|
invar/mcp/server.py,sha256=zSpY9bCFuq4mWe7XfolTnwHffhdmoyN40aFL4L7dFrE,20407
|
|
55
55
|
invar/node_tools/.gitignore,sha256=M2kz8Iw7Kzmi44mKo1r7_HOZMh79a7dFDdRrqXyaEhI,530
|
|
56
56
|
invar/node_tools/MANIFEST,sha256=2Z2at-27MK8K7DSjOjjtR4faTbt6eCiKQuEfvP_lwH8,145
|
|
@@ -2681,7 +2681,7 @@ invar/shell/ts_compiler.py,sha256=nA8brnOhThj9J_J3vAEGjDsM4NjbWQ_eX8Yf4pHPOgk,66
|
|
|
2681
2681
|
invar/shell/commands/__init__.py,sha256=MEkKwVyjI9DmkvBpJcuumXo2Pg_FFkfEr-Rr3nrAt7A,284
|
|
2682
2682
|
invar/shell/commands/doc.py,sha256=SOLDoCXXGxx_JU0PKXlAIGEF36PzconHmmAtL-rM6D4,13819
|
|
2683
2683
|
invar/shell/commands/feedback.py,sha256=lLxEeWW_71US_vlmorFrGXS8IARB9nbV6D0zruLs660,7640
|
|
2684
|
-
invar/shell/commands/guard.py,sha256=
|
|
2684
|
+
invar/shell/commands/guard.py,sha256=WXkeJ74N711p0uF042UWb7Ef9xm5sr0g7YSnqWcLY7w,24554
|
|
2685
2685
|
invar/shell/commands/hooks.py,sha256=W-SOnT4VQyUvXwipozkJwgEYfiOJGz7wksrbcdWegUg,2356
|
|
2686
2686
|
invar/shell/commands/init.py,sha256=rtoPFsfq7xRZ6lfTipWT1OejNK5wfzqu1ncXi1kizU0,23634
|
|
2687
2687
|
invar/shell/commands/merge.py,sha256=nuvKo8m32-OL-SCQlS4SLKmOZxQ3qj-1nGCx1Pgzifw,8183
|
|
@@ -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.10.dist-info/METADATA,sha256=vrPyr-dwQzhiioYZ6zpfN6UV94cftLiuFD8c2V2AEmg,28596
|
|
2782
|
+
invar_tools-1.17.10.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
2783
|
+
invar_tools-1.17.10.dist-info/entry_points.txt,sha256=RwH_EhqgtFPsnO6RcrwrAb70Zyfb8Mh6uUtztWnUxGk,102
|
|
2784
|
+
invar_tools-1.17.10.dist-info/licenses/LICENSE,sha256=qeFksp4H4kfTgQxPCIu3OdagXyiZcgBlVfsQ6M5oFyk,10767
|
|
2785
|
+
invar_tools-1.17.10.dist-info/licenses/LICENSE-GPL,sha256=IvZfC6ZbP7CLjytoHVzvpDZpD-Z3R_qa1GdMdWlWQ6Q,35157
|
|
2786
|
+
invar_tools-1.17.10.dist-info/licenses/NOTICE,sha256=joEyMyFhFY8Vd8tTJ-a3SirI0m2Sd0WjzqYt3sdcglc,2561
|
|
2787
|
+
invar_tools-1.17.10.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|