conduct-cli 0.14.0__tar.gz → 0.14.1__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 (57) hide show
  1. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/PKG-INFO +1 -1
  2. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/pyproject.toml +1 -1
  3. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/guard.py +28 -15
  4. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli.egg-info/PKG-INFO +1 -1
  5. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_proxy_env.py +34 -0
  6. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/LICENSE +0 -0
  7. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/README.md +0 -0
  8. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/setup.cfg +0 -0
  9. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/setup.py +0 -0
  10. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/__init__.py +0 -0
  11. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/api.py +0 -0
  12. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/guard_policy.md +0 -0
  13. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/__init__.py +0 -0
  14. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/base.py +0 -0
  15. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/posttooluse.py +0 -0
  16. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/precompact.py +0 -0
  17. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/pretooluse.py +0 -0
  18. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/session_parser.py +0 -0
  19. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/session_report_push.py +0 -0
  20. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/session_start.py +0 -0
  21. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/hooks/stop.py +0 -0
  22. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/log_util.py +0 -0
  23. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/main.py +0 -0
  24. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/memory.py +0 -0
  25. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/paxel.py +0 -0
  26. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli/tool_groups.py +0 -0
  27. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
  28. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
  29. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli.egg-info/entry_points.txt +0 -0
  30. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli.egg-info/requires.txt +0 -0
  31. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/src/conduct_cli.egg-info/top_level.txt +0 -0
  32. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_advisory_and_hook.py +0 -0
  33. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_api_client.py +0 -0
  34. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_bash_operator_signature.py +0 -0
  35. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_bash_scan_target.py +0 -0
  36. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_blast_radius.py +0 -0
  37. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_cli_matrix.py +0 -0
  38. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_cmd_run.py +0 -0
  39. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_command_word_matcher.py +0 -0
  40. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_drain_daemon_health.py +0 -0
  41. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_guard_approvals.py +0 -0
  42. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_guard_policy.py +0 -0
  43. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_guard_savings.py +0 -0
  44. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_hook_dispatch.py +0 -0
  45. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_hook_journal.py +0 -0
  46. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_hook_receipt.py +0 -0
  47. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_install_all.py +0 -0
  48. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_instruction_files.py +0 -0
  49. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_journal_drain.py +0 -0
  50. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_log_util.py +0 -0
  51. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_pretooluse_approval_e2e.py +0 -0
  52. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_pretooluse_check_policy.py +0 -0
  53. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_proxy_coverage.py +0 -0
  54. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_report_tool_coverage.py +0 -0
  55. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_signed_policy.py +0 -0
  56. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_switch.py +0 -0
  57. {conduct_cli-0.14.0 → conduct_cli-0.14.1}/tests/test_token_lifecycle.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.14.0
3
+ Version: 0.14.1
4
4
  Summary: Runtime governance for AI agents. CLI for Conduct AI — secure, govern, install agents, manage projects, run tests
5
5
  Author-email: Conduct AI <hello@conductai.ai>
6
6
  License: Apache-2.0
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "conduct-cli"
7
- version = "0.14.0"
7
+ version = "0.14.1"
8
8
  description = "Runtime governance for AI agents. CLI for Conduct AI — secure, govern, install agents, manage projects, run tests"
9
9
  readme = "README.md"
10
10
  license = { text = "Apache-2.0" }
@@ -1781,6 +1781,24 @@ def _post_local_findings(cfg: dict, base_url: str, findings: list[dict]) -> None
1781
1781
  print(f" {YELLOW}Audit upload skipped: {e}{RESET}")
1782
1782
 
1783
1783
 
1784
+ _LEGACY_CLAUDE_BYPASSES = {
1785
+ "alias claude='env -u ANTHROPIC_BASE_URL claude'",
1786
+ (
1787
+ "function claude { "
1788
+ "$prev=$env:ANTHROPIC_BASE_URL; $env:ANTHROPIC_BASE_URL=$null; "
1789
+ "try { & claude @args } finally { $env:ANTHROPIC_BASE_URL=$prev } }"
1790
+ ),
1791
+ }
1792
+
1793
+
1794
+ def _remove_legacy_claude_bypass(content: str) -> str:
1795
+ """Remove only proxy-bypass aliases previously generated by Conduct."""
1796
+ return "".join(
1797
+ line for line in content.splitlines(keepends=True)
1798
+ if line.strip() not in _LEGACY_CLAUDE_BYPASSES
1799
+ )
1800
+
1801
+
1784
1802
  def _write_proxy_env_windows(agent_token: str, proxy_url: str) -> tuple[Path, bool]:
1785
1803
  """Windows equivalent of _write_proxy_env — PowerShell profile + env.ps1."""
1786
1804
  CONDUCT_DIR.mkdir(parents=True, exist_ok=True)
@@ -1814,16 +1832,14 @@ def _write_proxy_env_windows(agent_token: str, proxy_url: str) -> tuple[Path, bo
1814
1832
  rc = wps5_profile
1815
1833
 
1816
1834
  existing = rc.read_text() if rc.exists() else ""
1817
- CLAUDE_ALIAS = (
1818
- "function claude { "
1819
- "$prev=$env:ANTHROPIC_BASE_URL; $env:ANTHROPIC_BASE_URL=$null; "
1820
- "try { & claude @args } finally { $env:ANTHROPIC_BASE_URL=$prev } }"
1821
- )
1835
+ cleaned = _remove_legacy_claude_bypass(existing)
1836
+ bypass_removed = cleaned != existing
1837
+ existing = cleaned
1822
1838
  PS_SOURCE_LINE = 'if (Test-Path "$HOME/.conduct/env.ps1") { . "$HOME/.conduct/env.ps1" }'
1823
1839
 
1824
1840
  if SHELL_RC_MARKER in existing:
1825
- if CLAUDE_ALIAS not in existing:
1826
- rc.write_text(existing.rstrip() + f"\n{CLAUDE_ALIAS}\n")
1841
+ if bypass_removed:
1842
+ rc.write_text(existing)
1827
1843
  return rc, True
1828
1844
  return rc, False
1829
1845
 
@@ -1831,7 +1847,6 @@ def _write_proxy_env_windows(agent_token: str, proxy_url: str) -> tuple[Path, bo
1831
1847
  addition = (
1832
1848
  f"\n\n{SHELL_RC_MARKER}\n"
1833
1849
  f"{PS_SOURCE_LINE}\n"
1834
- f"{CLAUDE_ALIAS}\n"
1835
1850
  )
1836
1851
  rc.write_text(existing.rstrip() + addition if existing else addition.lstrip())
1837
1852
  return rc, True
@@ -1889,22 +1904,20 @@ def _write_proxy_env(agent_token: str, proxy_url: str) -> tuple[Path, bool]:
1889
1904
  return Path(), False
1890
1905
 
1891
1906
  existing = rc.read_text() if rc.exists() else ""
1892
- CLAUDE_ALIAS = "alias claude='env -u ANTHROPIC_BASE_URL claude'"
1907
+ cleaned = _remove_legacy_claude_bypass(existing)
1908
+ bypass_removed = cleaned != existing
1909
+ existing = cleaned
1893
1910
 
1894
1911
  if SHELL_RC_MARKER in existing:
1895
- # Already installed — patch in the alias if missing (upgrade path)
1896
- if CLAUDE_ALIAS not in existing:
1897
- rc.write_text(existing.rstrip() + f"\n{CLAUDE_ALIAS}\n")
1912
+ if bypass_removed:
1913
+ rc.write_text(existing)
1898
1914
  return rc, True
1899
1915
  return rc, False
1900
1916
 
1901
1917
  rc.parent.mkdir(parents=True, exist_ok=True)
1902
- # ponytail: alias strips ANTHROPIC_BASE_URL so Claude Code auth isn't routed
1903
- # through the Guard proxy (Claude Code governs agents; it isn't one)
1904
1918
  addition = (
1905
1919
  f"\n\n{SHELL_RC_MARKER}\n"
1906
1920
  f"{SHELL_SOURCE_LINE}\n"
1907
- f"{CLAUDE_ALIAS}\n"
1908
1921
  )
1909
1922
  rc.write_text(existing.rstrip() + addition if existing else addition.lstrip())
1910
1923
  return rc, True
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: conduct-cli
3
- Version: 0.14.0
3
+ Version: 0.14.1
4
4
  Summary: Runtime governance for AI agents. CLI for Conduct AI — secure, govern, install agents, manage projects, run tests
5
5
  Author-email: Conduct AI <hello@conductai.ai>
6
6
  License: Apache-2.0
@@ -61,6 +61,26 @@ def test_shell_rc_source_line_added_once_across_multiple_syncs(tmp_path, monkeyp
61
61
  rc_text = (tmp_path / ".zshrc").read_text()
62
62
  assert rc_text.count(guard.SHELL_RC_MARKER) == 1
63
63
  assert rc_text.count(guard.SHELL_SOURCE_LINE) == 1
64
+ assert "env -u ANTHROPIC_BASE_URL" not in rc_text
65
+
66
+
67
+ @pytestmark_posix
68
+ def test_sync_removes_generated_claude_proxy_bypass(tmp_path, monkeypatch):
69
+ _redirect_home(tmp_path, monkeypatch)
70
+ monkeypatch.setenv("SHELL", "/bin/zsh")
71
+ zshrc = tmp_path / ".zshrc"
72
+ custom_alias = "alias claude-work='claude --worktree'"
73
+ zshrc.write_text(
74
+ f"{custom_alias}\n{guard.SHELL_RC_MARKER}\n{guard.SHELL_SOURCE_LINE}\n"
75
+ "alias claude='env -u ANTHROPIC_BASE_URL claude'\n"
76
+ )
77
+
78
+ _, changed = guard._write_proxy_env("abc", "https://api.conductai.ai/gateway/v1")
79
+
80
+ content = zshrc.read_text()
81
+ assert changed is True
82
+ assert "env -u ANTHROPIC_BASE_URL" not in content
83
+ assert custom_alias in content
64
84
 
65
85
 
66
86
  @pytestmark_posix
@@ -212,6 +232,20 @@ def test_windows_appends_source_line_to_powershell_profile_once(tmp_path, monkey
212
232
  text = profile.read_text()
213
233
  assert text.count(guard.SHELL_RC_MARKER) == 1
214
234
  assert text.count('. "$HOME/.conduct/env.ps1"') == 1
235
+ assert "$env:ANTHROPIC_BASE_URL=$null" not in text
236
+
237
+
238
+ def test_windows_sync_removes_generated_claude_proxy_bypass(tmp_path, monkeypatch):
239
+ _redirect_home_windows(tmp_path, monkeypatch)
240
+ profile = tmp_path / "Documents" / "PowerShell" / "Microsoft.PowerShell_profile.ps1"
241
+ profile.parent.mkdir(parents=True)
242
+ bypass = next(value for value in guard._LEGACY_CLAUDE_BYPASSES if value.startswith("function claude"))
243
+ profile.write_text(f"{guard.SHELL_RC_MARKER}\n{bypass}\n")
244
+
245
+ _, changed = guard._write_proxy_env("abc", "https://api.conductai.ai/gateway/v1")
246
+
247
+ assert changed is True
248
+ assert "$env:ANTHROPIC_BASE_URL=$null" not in profile.read_text()
215
249
 
216
250
 
217
251
  def test_windows_prefers_ps7_profile_when_no_wps5_exists(tmp_path, monkeypatch):
File without changes
File without changes
File without changes
File without changes