conduct-cli 0.7.44__tar.gz → 0.7.45__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.
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/PKG-INFO +1 -1
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/pyproject.toml +1 -1
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/guard.py +65 -12
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli.egg-info/PKG-INFO +1 -1
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/README.md +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/setup.cfg +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/setup.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/__init__.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/api.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/guardmcp.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/__init__.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/base.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/posttooluse.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/precompact.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/pretooluse.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/session_parser.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/session_report_push.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/session_start.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/hooks/stop.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/log_util.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/main.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/mcp_server.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/memory.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/paxel.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli/tool_groups.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli.egg-info/entry_points.txt +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli.egg-info/requires.txt +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/src/conduct_cli.egg-info/top_level.txt +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_advisory_and_hook.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_api_client.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_bash_operator_signature.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_blast_radius.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_cmd_run.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_command_word_matcher.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_drain_daemon_health.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_guard_policy.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_guard_savings.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_hook_dispatch.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_journal_drain.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_log_util.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_proxy_coverage.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_proxy_env.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_signed_policy.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_switch.py +0 -0
- {conduct_cli-0.7.44 → conduct_cli-0.7.45}/tests/test_token_lifecycle.py +0 -0
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "conduct-cli"
|
|
7
|
-
version = "0.7.
|
|
7
|
+
version = "0.7.45"
|
|
8
8
|
description = "CLI for Conduct AI — secure, govern, install agents, manage projects, run tests"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -388,7 +388,7 @@ _MCP_TARGETS = [
|
|
|
388
388
|
]
|
|
389
389
|
|
|
390
390
|
|
|
391
|
-
def _register_mcp(workspace_id: str, agent_token: str, api_url: str) -> None:
|
|
391
|
+
def _register_mcp(workspace_id: str, agent_token: str, api_url: str, dry_run: bool = False) -> None:
|
|
392
392
|
"""Write conductguard + agent-booster MCP entries into every AI tool config found.
|
|
393
393
|
|
|
394
394
|
Credentials are NOT stored in the MCP config — the server reads them from
|
|
@@ -441,7 +441,7 @@ def _register_mcp(workspace_id: str, agent_token: str, api_url: str) -> None:
|
|
|
441
441
|
|
|
442
442
|
# Cursor global rules — write Guard policies as user rules so they apply across all projects.
|
|
443
443
|
_patch_cursor_global_rules()
|
|
444
|
-
_patch_tool_instruction_files(agent_token, api_url)
|
|
444
|
+
_patch_tool_instruction_files(agent_token, api_url, dry_run=dry_run)
|
|
445
445
|
|
|
446
446
|
|
|
447
447
|
def _patch_claude_desktop_proxy(api_url: str, agent_token: str) -> None:
|
|
@@ -542,7 +542,7 @@ def _patch_cursor_global_rules() -> None:
|
|
|
542
542
|
print(f" {GREEN}Cursor global rules updated with ConductGuard policy{RESET}")
|
|
543
543
|
|
|
544
544
|
|
|
545
|
-
def _patch_tool_instruction_files(agent_token: str, api_url: str) -> None:
|
|
545
|
+
def _patch_tool_instruction_files(agent_token: str, api_url: str, dry_run: bool = False) -> None:
|
|
546
546
|
"""Write ConductGuard policy block into instruction files for all AI tools.
|
|
547
547
|
|
|
548
548
|
Targets:
|
|
@@ -597,19 +597,64 @@ def _patch_tool_instruction_files(agent_token: str, api_url: str) -> None:
|
|
|
597
597
|
path = repo_path if (repo_path and repo_path.exists()) else global_path
|
|
598
598
|
if not path.exists() and repo_path:
|
|
599
599
|
path = repo_path
|
|
600
|
-
path.parent.mkdir(parents=True, exist_ok=True)
|
|
601
600
|
existing = path.read_text() if path.exists() else ""
|
|
602
601
|
if MARKER_START in existing:
|
|
603
602
|
updated = pattern.sub(guard_block, existing)
|
|
604
|
-
if
|
|
605
|
-
|
|
603
|
+
if dry_run:
|
|
604
|
+
if updated == existing:
|
|
605
|
+
print(f" [dry-run] No change: {path}")
|
|
606
|
+
else:
|
|
607
|
+
print(f" [dry-run] Would write: {path}")
|
|
606
608
|
else:
|
|
607
|
-
path.
|
|
608
|
-
|
|
609
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
610
|
+
if updated == existing:
|
|
611
|
+
print(f" {GRAY}{label} already up to date{RESET}")
|
|
612
|
+
else:
|
|
613
|
+
path.write_text(updated)
|
|
614
|
+
print(f" {GREEN}{label} updated{RESET}")
|
|
609
615
|
else:
|
|
610
|
-
|
|
611
|
-
|
|
612
|
-
|
|
616
|
+
new_content = (existing.rstrip() + ("\n\n" if existing.strip() else "") + guard_block + "\n").lstrip()
|
|
617
|
+
if dry_run:
|
|
618
|
+
if new_content == existing:
|
|
619
|
+
print(f" [dry-run] No change: {path}")
|
|
620
|
+
else:
|
|
621
|
+
print(f" [dry-run] Would write: {path}")
|
|
622
|
+
else:
|
|
623
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
624
|
+
path.write_text(new_content)
|
|
625
|
+
print(f" {GREEN}{label} — ConductGuard block added{RESET}")
|
|
626
|
+
|
|
627
|
+
|
|
628
|
+
def _reset_tool_instruction_files() -> None:
|
|
629
|
+
"""Remove ConductGuard blocks from all instruction files."""
|
|
630
|
+
import re as _re
|
|
631
|
+
MARKER_RE = _re.compile(
|
|
632
|
+
r"\n?<!-- ConductGuard -->\n.*?<!-- /ConductGuard -->\n?",
|
|
633
|
+
_re.DOTALL,
|
|
634
|
+
)
|
|
635
|
+
targets = [
|
|
636
|
+
Path.home() / "CLAUDE.md",
|
|
637
|
+
Path.cwd() / "CLAUDE.md",
|
|
638
|
+
Path.cwd() / ".github" / "copilot-instructions.md",
|
|
639
|
+
Path.cwd() / "AGENTS.md",
|
|
640
|
+
Path.cwd() / ".cursorrules",
|
|
641
|
+
Path.cwd() / ".windsurfrules",
|
|
642
|
+
]
|
|
643
|
+
removed = 0
|
|
644
|
+
for p in targets:
|
|
645
|
+
if not p.exists():
|
|
646
|
+
continue
|
|
647
|
+
original = p.read_text(encoding="utf-8")
|
|
648
|
+
cleaned = MARKER_RE.sub("", original).strip()
|
|
649
|
+
if cleaned != original.strip():
|
|
650
|
+
p.write_text(cleaned + "\n", encoding="utf-8")
|
|
651
|
+
print(f" {GREEN}Removed ConductGuard block: {p}{RESET}")
|
|
652
|
+
removed += 1
|
|
653
|
+
else:
|
|
654
|
+
print(f" {YELLOW}No ConductGuard block found: {p}{RESET}")
|
|
655
|
+
if removed == 0:
|
|
656
|
+
print(" No ConductGuard blocks found in any instruction files.")
|
|
657
|
+
|
|
613
658
|
|
|
614
659
|
def _install_codex_hook(hook_path: Path) -> None:
|
|
615
660
|
"""Register PreToolUse and PostToolUse hooks in ~/.codex/hooks.json."""
|
|
@@ -1319,6 +1364,12 @@ def cmd_guard_sync(args):
|
|
|
1319
1364
|
# Persona selection — prompt once, skip if already chosen
|
|
1320
1365
|
|
|
1321
1366
|
dry_run = getattr(args, "dry_run", False)
|
|
1367
|
+
|
|
1368
|
+
if getattr(args, "reset_instructions", False):
|
|
1369
|
+
print("Removing ConductGuard blocks from instruction files…")
|
|
1370
|
+
_reset_tool_instruction_files()
|
|
1371
|
+
return
|
|
1372
|
+
|
|
1322
1373
|
print(f"{'[dry-run] ' if dry_run else ''}Syncing policy…")
|
|
1323
1374
|
_check_and_upgrade_packages()
|
|
1324
1375
|
|
|
@@ -1463,7 +1514,7 @@ def cmd_guard_sync(args):
|
|
|
1463
1514
|
_install_claude_hook(hook_path)
|
|
1464
1515
|
_install_codex_hook(hook_path)
|
|
1465
1516
|
cfg2 = _load_guard_config()
|
|
1466
|
-
_register_mcp(workspace_id, cfg2.get("agent_token", ""), base_url)
|
|
1517
|
+
_register_mcp(workspace_id, cfg2.get("agent_token", ""), base_url, dry_run=dry_run)
|
|
1467
1518
|
try:
|
|
1468
1519
|
_install_session_hooks()
|
|
1469
1520
|
except Exception:
|
|
@@ -2176,6 +2227,8 @@ def register_guard_parser(sub):
|
|
|
2176
2227
|
sync_p = guard_sub.add_parser("sync", help="Refresh policy and re-scan for AI tools")
|
|
2177
2228
|
sync_p.add_argument("--cursor", action="store_true", help="Write active Guard policies to .cursorrules")
|
|
2178
2229
|
sync_p.add_argument("--dry-run", action="store_true", help="Preview policy changes without writing anything")
|
|
2230
|
+
sync_p.add_argument("--reset-instructions", action="store_true", dest="reset_instructions",
|
|
2231
|
+
help="Remove ConductGuard blocks from all instruction files")
|
|
2179
2232
|
sync_p.add_argument("--proxy-url", default=None,
|
|
2180
2233
|
help="Override the Guard proxy URL (default: https://api.conductai.ai/proxy/anthropic)")
|
|
2181
2234
|
sync_p.add_argument("--no-local-audit", action="store_true",
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|