guard-cli 0.1.3__tar.gz → 0.1.5__tar.gz

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 (50) hide show
  1. {guard_cli-0.1.3 → guard_cli-0.1.5}/PKG-INFO +1 -1
  2. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/api.py +9 -6
  3. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/cli.py +1 -1
  4. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/db.py +3 -1
  5. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/hook.py +8 -18
  6. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli.egg-info/PKG-INFO +1 -1
  7. {guard_cli-0.1.3 → guard_cli-0.1.5}/pyproject.toml +1 -1
  8. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_api_and_hook.py +33 -5
  9. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_coverage.py +14 -5
  10. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_db.py +14 -5
  11. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_feedback.py +14 -5
  12. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_thin_slice.py +14 -5
  13. {guard_cli-0.1.3 → guard_cli-0.1.5}/LICENSE +0 -0
  14. {guard_cli-0.1.3 → guard_cli-0.1.5}/README.md +0 -0
  15. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/__init__.py +0 -0
  16. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/agent_integration.py +0 -0
  17. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/backend.py +0 -0
  18. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/decision.py +0 -0
  19. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/doctor_cmd.py +0 -0
  20. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/events.py +0 -0
  21. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/feedback.py +0 -0
  22. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/ingest/__init__.py +0 -0
  23. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/ingest/coverage.py +0 -0
  24. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/ingest/static.py +0 -0
  25. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/init_cmd.py +0 -0
  26. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/integrations/__init__.py +0 -0
  27. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/integrations/antigravity.py +0 -0
  28. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/integrations/claude.py +0 -0
  29. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/state.py +0 -0
  30. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli/thin_slice.py +0 -0
  31. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli.egg-info/SOURCES.txt +0 -0
  32. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli.egg-info/dependency_links.txt +0 -0
  33. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli.egg-info/entry_points.txt +0 -0
  34. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli.egg-info/requires.txt +0 -0
  35. {guard_cli-0.1.3 → guard_cli-0.1.5}/guard_cli.egg-info/top_level.txt +0 -0
  36. {guard_cli-0.1.3 → guard_cli-0.1.5}/setup.cfg +0 -0
  37. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_antigravity_integration.py +0 -0
  38. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_antigravity_pre_recording_fixes.py +0 -0
  39. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_backend.py +0 -0
  40. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_commit_bypass.py +0 -0
  41. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_commit_bypass_fresh_session.py +0 -0
  42. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_decision.py +0 -0
  43. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_doctor_cmd.py +0 -0
  44. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_embedded_platform.py +0 -0
  45. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_event_reasons.py +0 -0
  46. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_fingerprint_invalidation.py +0 -0
  47. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_hook_timeout.py +0 -0
  48. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_init_cmd.py +0 -0
  49. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_integration_init_doctor.py +0 -0
  50. {guard_cli-0.1.3 → guard_cli-0.1.5}/tests/test_static.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: guard-cli
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Graph-powered safety layer for AI coding agents built on FalkorDB
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/thisisvaishnav/guard
@@ -396,12 +396,13 @@ def run(
396
396
  def covering_tests(
397
397
  function_id: str,
398
398
  min_confidence: float = 0.0,
399
- graph_name: str = "guard",
399
+ graph_name: str | None = None,
400
+ repo_path: str | Path | None = None,
400
401
  strict: bool = False,
401
402
  ) -> list[dict[str, Any]]:
402
403
  """Find tests covering a given function, ordered by confidence."""
403
404
  try:
404
- g = db.get_graph(graph_name)
405
+ g = db.get_graph(graph_name, repo_path=repo_path)
405
406
  return db.get_covering_tests(g, function_id, min_confidence=min_confidence)
406
407
  except Exception as exc:
407
408
  if strict:
@@ -414,12 +415,13 @@ def callers(
414
415
  function_id: str,
415
416
  hops: int = 4,
416
417
  min_confidence: float = 0.0,
417
- graph_name: str = "guard",
418
+ graph_name: str | None = None,
419
+ repo_path: str | Path | None = None,
418
420
  strict: bool = False,
419
421
  ) -> list[dict[str, Any]]:
420
422
  """Traverse inbound CALLS edges up to N hops filtered by min_confidence."""
421
423
  try:
422
- g = db.get_graph(graph_name)
424
+ g = db.get_graph(graph_name, repo_path=repo_path)
423
425
  return db.get_callers(g, function_id, hops=hops, min_confidence=min_confidence)
424
426
  except Exception as exc:
425
427
  if strict:
@@ -432,12 +434,13 @@ def report_miss(
432
434
  function_id: str,
433
435
  test_id: str,
434
436
  new_confidence: float = 1.0,
435
- graph_name: str = "guard",
437
+ graph_name: str | None = None,
438
+ repo_path: str | Path | None = None,
436
439
  strict: bool = False,
437
440
  ) -> dict[str, Any]:
438
441
  """Records a missed failure by repairing the graph with a miss_repair edge."""
439
442
  try:
440
- g = db.get_graph(graph_name)
443
+ g = db.get_graph(graph_name, repo_path=repo_path)
441
444
  return feedback.record_miss(
442
445
  g,
443
446
  function_id=function_id,
@@ -239,7 +239,7 @@ def main(argv=None) -> int:
239
239
 
240
240
  p = argparse.ArgumentParser(prog="guard")
241
241
  p.add_argument("-v", "--version", action="version", version=f"guard {guard_cli.__version__}")
242
- p.add_argument("--graph", default="guard")
242
+ p.add_argument("--graph", default=None, help="FalkorDB graph name (defaults to repository graph from .guard/config.toml)")
243
243
  sub = p.add_subparsers(dest="cmd", required=True)
244
244
 
245
245
  ini = sub.add_parser("init", help="Initialize Guard for repository")
@@ -47,7 +47,9 @@ def get_graph(
47
47
  if backend is None:
48
48
  backend = get_backend(repo_path=repo_path)
49
49
  if name is None:
50
- name = os.getenv("GUARD_GRAPH", GRAPH_NAME)
50
+ from guard_cli.backend import load_config
51
+ cfg = load_config(repo_path)
52
+ name = cfg.get("backend", {}).get("graph_name") or os.getenv("GUARD_GRAPH", GRAPH_NAME)
51
53
  return backend.get_graph(name)
52
54
 
53
55
 
@@ -530,16 +530,11 @@ def run_stop_hook(
530
530
  if is_antigravity:
531
531
  resp: dict[str, Any] = {"decision": "stop", "reason": reason or ""}
532
532
  payload = json.dumps(resp) + "\n"
533
- if saved_stdout is not None:
533
+ target_out = real_out if real_out is not None else saved_stdout
534
+ if target_out is not None:
534
535
  try:
535
- saved_stdout.write(payload)
536
- saved_stdout.flush()
537
- except Exception:
538
- pass
539
- if real_out is not None and real_out is not saved_stdout:
540
- try:
541
- real_out.write(payload)
542
- real_out.flush()
536
+ target_out.write(payload)
537
+ target_out.flush()
543
538
  except Exception:
544
539
  pass
545
540
  return 0
@@ -548,16 +543,11 @@ def run_stop_hook(
548
543
  if is_antigravity:
549
544
  resp: dict[str, Any] = {"decision": "continue", "reason": reason_text}
550
545
  payload = json.dumps(resp) + "\n"
551
- if saved_stdout is not None:
552
- try:
553
- saved_stdout.write(payload)
554
- saved_stdout.flush()
555
- except Exception:
556
- pass
557
- if real_out is not None and real_out is not saved_stdout:
546
+ target_out = real_out if real_out is not None else saved_stdout
547
+ if target_out is not None:
558
548
  try:
559
- real_out.write(payload)
560
- real_out.flush()
549
+ target_out.write(payload)
550
+ target_out.flush()
561
551
  except Exception:
562
552
  pass
563
553
  sys.stderr.write(reason_text)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: guard-cli
3
- Version: 0.1.3
3
+ Version: 0.1.5
4
4
  Summary: Graph-powered safety layer for AI coding agents built on FalkorDB
5
5
  License-Expression: MIT
6
6
  Project-URL: Homepage, https://github.com/thisisvaishnav/guard
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "guard-cli"
7
- version = "0.1.3"
7
+ version = "0.1.5"
8
8
  description = "Graph-powered safety layer for AI coding agents built on FalkorDB"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -58,10 +58,16 @@ def seeded_guard_graph():
58
58
  """Seeds a dedicated graph so check() exercises the 'select' path without
59
59
  depending on an externally pre-populated 'guard' graph (which may lack
60
60
  COVERED_BY evidence and silently fall back to run-all)."""
61
- g = db.get_graph("guard_api_check_test")
62
- db.reset_graph(g)
63
- g = db.get_graph("guard_api_check_test")
64
- db.ensure_schema(g)
61
+ backend = db.get_backend()
62
+ if not backend.is_healthy():
63
+ pytest.skip("FalkorDB server is not reachable")
64
+ try:
65
+ g = db.get_graph("guard_api_check_test", backend=backend)
66
+ db.reset_graph(g)
67
+ g = db.get_graph("guard_api_check_test", backend=backend)
68
+ db.ensure_schema(g)
69
+ except Exception as exc:
70
+ pytest.skip(f"FalkorDB server error: {exc}")
65
71
  db.write_static(
66
72
  g,
67
73
  StaticResult(
@@ -74,7 +80,10 @@ def seeded_guard_graph():
74
80
  )
75
81
  db.write_coverage(g, {"tests/test_mod.py::test_calc": ["pkg/mod.py::calc"]}, confidence=0.9)
76
82
  yield g
77
- db.reset_graph(g)
83
+ try:
84
+ db.reset_graph(g)
85
+ except Exception:
86
+ pass
78
87
 
79
88
 
80
89
  def test_api_check_schema_version_and_keys(temp_repo, seeded_guard_graph):
@@ -452,3 +461,22 @@ def test_cli_hook_subcommands(temp_repo, capsys):
452
461
  ret = main(["hook", "uninstall", "--repo", str(temp_repo), "--antigravity"])
453
462
  assert ret == 0
454
463
 
464
+
465
+ def test_cli_default_graph_resolution(temp_repo):
466
+ """Verify that when graph name is omitted, db and api resolve graph_name from .guard/config.toml."""
467
+ from guard_cli.backend import save_config
468
+ save_config(temp_repo, {"backend": {"type": "server", "graph_name": "custom_repo_graph"}})
469
+
470
+ with patch("guard_cli.db.get_backend") as mock_get_backend:
471
+ mock_backend = MagicMock()
472
+ mock_get_backend.return_value = mock_backend
473
+ db.get_graph(name=None, repo_path=temp_repo)
474
+ mock_backend.get_graph.assert_called_with("custom_repo_graph")
475
+
476
+ with patch("guard_cli.db.get_backend") as mock_get_backend, patch("guard_cli.db.get_covering_tests") as mock_get_cov:
477
+ mock_backend = MagicMock()
478
+ mock_get_backend.return_value = mock_backend
479
+ mock_get_cov.return_value = []
480
+ api.covering_tests("pkg/mod.py::calc", repo_path=temp_repo)
481
+ mock_backend.get_graph.assert_called_with("custom_repo_graph")
482
+
@@ -51,12 +51,21 @@ def test_compute_flakiness():
51
51
 
52
52
  @pytest.fixture
53
53
  def clean_test_graph():
54
- g = db.get_graph("guard_cov_test")
55
- db.reset_graph(g)
56
- g = db.get_graph("guard_cov_test")
57
- db.ensure_schema(g)
54
+ backend = db.get_backend()
55
+ if not backend.is_healthy():
56
+ pytest.skip("FalkorDB server is not reachable")
57
+ try:
58
+ g = db.get_graph("guard_cov_test", backend=backend)
59
+ db.reset_graph(g)
60
+ g = db.get_graph("guard_cov_test", backend=backend)
61
+ db.ensure_schema(g)
62
+ except Exception as exc:
63
+ pytest.skip(f"FalkorDB server error: {exc}")
58
64
  yield g
59
- db.reset_graph(g)
65
+ try:
66
+ db.reset_graph(g)
67
+ except Exception:
68
+ pass
60
69
 
61
70
 
62
71
  def test_coverage_write_to_graph(clean_test_graph):
@@ -6,12 +6,21 @@ from guard.ingest.static import StaticResult, FuncDef
6
6
  @pytest.fixture
7
7
  def test_graph():
8
8
  """Provides a fresh test graph in FalkorDB."""
9
- g = db.get_graph("guard_test")
10
- db.reset_graph(g)
11
- g = db.get_graph("guard_test")
12
- db.ensure_schema(g)
9
+ backend = db.get_backend()
10
+ if not backend.is_healthy():
11
+ pytest.skip("FalkorDB server is not reachable")
12
+ try:
13
+ g = db.get_graph("guard_test", backend=backend)
14
+ db.reset_graph(g)
15
+ g = db.get_graph("guard_test", backend=backend)
16
+ db.ensure_schema(g)
17
+ except Exception as exc:
18
+ pytest.skip(f"FalkorDB server error: {exc}")
13
19
  yield g
14
- db.reset_graph(g)
20
+ try:
21
+ db.reset_graph(g)
22
+ except Exception:
23
+ pass
15
24
 
16
25
 
17
26
  def test_ensure_schema_creates_indexes(test_graph):
@@ -7,12 +7,21 @@ from guard.ingest.static import StaticResult, FuncDef
7
7
 
8
8
  @pytest.fixture
9
9
  def feedback_test_graph():
10
- g = db.get_graph("guard_feedback_test")
11
- db.reset_graph(g)
12
- g = db.get_graph("guard_feedback_test")
13
- db.ensure_schema(g)
10
+ backend = db.get_backend()
11
+ if not backend.is_healthy():
12
+ pytest.skip("FalkorDB server is not reachable")
13
+ try:
14
+ g = db.get_graph("guard_feedback_test", backend=backend)
15
+ db.reset_graph(g)
16
+ g = db.get_graph("guard_feedback_test", backend=backend)
17
+ db.ensure_schema(g)
18
+ except Exception as exc:
19
+ pytest.skip(f"FalkorDB server error: {exc}")
14
20
  yield g
15
- db.reset_graph(g)
21
+ try:
22
+ db.reset_graph(g)
23
+ except Exception:
24
+ pass
16
25
 
17
26
 
18
27
  def test_record_miss_creates_repair_edge(feedback_test_graph):
@@ -52,12 +52,21 @@ def test_thin_slice_decision_fallback_on_test_files_touched():
52
52
 
53
53
  @pytest.fixture
54
54
  def slice_test_graph():
55
- g = db.get_graph("guard_slice_test")
56
- db.reset_graph(g)
57
- g = db.get_graph("guard_slice_test")
58
- db.ensure_schema(g)
55
+ backend = db.get_backend()
56
+ if not backend.is_healthy():
57
+ pytest.skip("FalkorDB server is not reachable")
58
+ try:
59
+ g = db.get_graph("guard_slice_test", backend=backend)
60
+ db.reset_graph(g)
61
+ g = db.get_graph("guard_slice_test", backend=backend)
62
+ db.ensure_schema(g)
63
+ except Exception as exc:
64
+ pytest.skip(f"FalkorDB server error: {exc}")
59
65
  yield g
60
- db.reset_graph(g)
66
+ try:
67
+ db.reset_graph(g)
68
+ except Exception:
69
+ pass
61
70
 
62
71
 
63
72
  def test_thin_slice_selects_covering_tests(slice_test_graph):
File without changes
File without changes
File without changes
File without changes
File without changes