conduct-cli 0.4.59__tar.gz → 0.4.60__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 (20) hide show
  1. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/PKG-INFO +1 -1
  2. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/pyproject.toml +1 -1
  3. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli/guard.py +17 -12
  4. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli.egg-info/PKG-INFO +1 -1
  5. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/README.md +0 -0
  6. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/setup.cfg +0 -0
  7. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/setup.py +0 -0
  8. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli/__init__.py +0 -0
  9. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli/api.py +0 -0
  10. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli/guardmcp.py +0 -0
  11. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli/main.py +0 -0
  12. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli/mcp_server.py +0 -0
  13. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
  14. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
  15. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli.egg-info/entry_points.txt +0 -0
  16. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli.egg-info/requires.txt +0 -0
  17. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/src/conduct_cli.egg-info/top_level.txt +0 -0
  18. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/tests/test_guard_policy.py +0 -0
  19. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/tests/test_guard_savings.py +0 -0
  20. {conduct_cli-0.4.59 → conduct_cli-0.4.60}/tests/test_switch.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.4.59
3
+ Version: 0.4.60
4
4
  Summary: CLI for Conduct AI — install agents, manage projects, run tests
5
5
  Author-email: Conduct AI <hello@conductai.ai>
6
6
  License: MIT
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "conduct-cli"
7
- version = "0.4.59"
7
+ version = "0.4.60"
8
8
  description = "CLI for Conduct AI — install agents, manage projects, run tests"
9
9
  readme = "README.md"
10
10
  license = { text = "MIT" }
@@ -282,17 +282,14 @@ def _classify_text(text):
282
282
 
283
283
  def _line_number_from_text(text, matched_pattern):
284
284
  """Extract line number where pattern matched.
285
-
286
- Handles two formats:
287
- - Read tool output: ' N\\tcode line' (cat -n style)
288
- - Plain text: count newlines before match offset
285
+ Uses splitlines() and chr(10) — no backslash-n literals (safe inside _HOOK_SCRIPT).
289
286
  """
290
287
  import re as _re
291
288
  if not matched_pattern:
292
289
  return None
293
290
  try:
294
- # Try cat-n format first (Read tool)
295
- for raw_line in text.split("\n"):
291
+ # Try cat-n format first (Read tool outputs ' N<TAB>code line')
292
+ for raw_line in text.splitlines():
296
293
  m = _re.match(r"^\s*(\d+)\t(.*)$", raw_line)
297
294
  if m:
298
295
  lineno, content = int(m.group(1)), m.group(2)
@@ -302,10 +299,10 @@ def _line_number_from_text(text, matched_pattern):
302
299
  except Exception:
303
300
  if matched_pattern.lower() in content.lower():
304
301
  return lineno
305
- # Fallback: count newlines before the first match
302
+ # Fallback: count lines before the first match offset
306
303
  m = _re.search(matched_pattern, text, _re.IGNORECASE)
307
304
  if m:
308
- return text[:m.start()].count("\n") + 1
305
+ return text[:m.start()].count(chr(10)) + 1
309
306
  except Exception:
310
307
  pass
311
308
  return None
@@ -813,17 +810,25 @@ def _best_python() -> str:
813
810
 
814
811
  def _write_hook(path: Path) -> None:
815
812
  """Write _HOOK_SCRIPT to path, then py_compile-validate it.
816
- Raises RuntimeError if the written file fails to compile prevents
817
- silently deploying a syntactically broken hook."""
813
+ On syntax failure: restores previous hook (or writes a safe stub) so the
814
+ system is never left without a working hook file."""
818
815
  import py_compile, tempfile, os
816
+ # Stash existing hook so we can restore on failure
817
+ backup = None
818
+ if path.exists():
819
+ backup = path.read_text()
820
+ path.parent.mkdir(parents=True, exist_ok=True)
819
821
  path.write_text(_HOOK_SCRIPT)
820
822
  path.chmod(0o755)
821
823
  try:
822
824
  py_compile.compile(str(path), doraise=True)
823
825
  except py_compile.PyCompileError as exc:
824
- path.unlink(missing_ok=True)
826
+ if backup is not None:
827
+ path.write_text(backup)
828
+ else:
829
+ path.write_text("#!/usr/bin/env python3\nimport sys\nsys.exit(0)\n")
825
830
  raise RuntimeError(
826
- f"hook.py failed syntax check after write hook NOT installed.\n{exc}"
831
+ f"hook.py failed syntax check previous hook restored.\n{exc}"
827
832
  ) from exc
828
833
 
829
834
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.4.59
3
+ Version: 0.4.60
4
4
  Summary: CLI for Conduct AI — install agents, manage projects, run tests
5
5
  Author-email: Conduct AI <hello@conductai.ai>
6
6
  License: MIT
File without changes
File without changes
File without changes