conduct-cli 0.7.40__tar.gz → 0.7.41__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.40 → conduct_cli-0.7.41}/PKG-INFO +1 -1
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/pyproject.toml +1 -1
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/guard.py +56 -1
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli.egg-info/PKG-INFO +1 -1
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/README.md +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/setup.cfg +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/setup.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/__init__.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/api.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/guardmcp.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/__init__.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/base.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/posttooluse.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/precompact.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/pretooluse.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/session_parser.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/session_report_push.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/session_start.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/hooks/stop.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/log_util.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/main.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/mcp_server.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/memory.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/paxel.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli/tool_groups.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli.egg-info/entry_points.txt +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli.egg-info/requires.txt +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/src/conduct_cli.egg-info/top_level.txt +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_advisory_and_hook.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_api_client.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_bash_operator_signature.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_blast_radius.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_cmd_run.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_command_word_matcher.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_drain_daemon_health.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_guard_policy.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_guard_savings.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_hook_dispatch.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_journal_drain.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_log_util.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_proxy_coverage.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_proxy_env.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_signed_policy.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/tests/test_switch.py +0 -0
- {conduct_cli-0.7.40 → conduct_cli-0.7.41}/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.41"
|
|
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" }
|
|
@@ -441,6 +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_copilot_instructions()
|
|
444
445
|
|
|
445
446
|
|
|
446
447
|
def _patch_claude_desktop_proxy(api_url: str, agent_token: str) -> None:
|
|
@@ -540,6 +541,60 @@ def _patch_cursor_global_rules() -> None:
|
|
|
540
541
|
print(f" {GREEN}Cursor global rules updated with ConductGuard policy{RESET}")
|
|
541
542
|
|
|
542
543
|
|
|
544
|
+
def _patch_copilot_instructions() -> None:
|
|
545
|
+
"""Write ConductGuard enforcement instructions into .github/copilot-instructions.md.
|
|
546
|
+
|
|
547
|
+
Copilot injects this file into every conversation automatically — soft hooks
|
|
548
|
+
for tools that don't support PreToolUse/PostToolUse interception.
|
|
549
|
+
Written to the current repo root if a .github/ dir exists, and to ~/
|
|
550
|
+
as a global fallback.
|
|
551
|
+
"""
|
|
552
|
+
GUARD_BLOCK = (
|
|
553
|
+
"<!-- ConductGuard — managed by conduct guard sync, do not edit this block -->\n"
|
|
554
|
+
"## ConductGuard Policy\n"
|
|
555
|
+
"Before executing any shell command, file write, network request, API call, or code change:\n"
|
|
556
|
+
"- Call `guard_check` (conductguard MCP tool) with the action and parameters.\n"
|
|
557
|
+
"- If BLOCKED: stop immediately and explain the policy rule to the user.\n"
|
|
558
|
+
"- If WARNING: proceed but surface the warning.\n"
|
|
559
|
+
"- If ALLOWED: proceed normally.\n"
|
|
560
|
+
"Never write credentials, API keys, or secrets to files or output.\n"
|
|
561
|
+
"Never send PII (emails, names, payment data) to external endpoints.\n"
|
|
562
|
+
"<!-- /ConductGuard -->"
|
|
563
|
+
)
|
|
564
|
+
|
|
565
|
+
candidates: list[Path] = []
|
|
566
|
+
# Repo-level: walk up from cwd to find .github/
|
|
567
|
+
cwd = Path.cwd()
|
|
568
|
+
for parent in [cwd, *cwd.parents]:
|
|
569
|
+
gh = parent / ".github"
|
|
570
|
+
if gh.is_dir():
|
|
571
|
+
candidates.append(gh / "copilot-instructions.md")
|
|
572
|
+
break
|
|
573
|
+
# Global fallback
|
|
574
|
+
candidates.append(Path.home() / ".github" / "copilot-instructions.md")
|
|
575
|
+
|
|
576
|
+
wrote_any = False
|
|
577
|
+
for path in candidates:
|
|
578
|
+
path.parent.mkdir(parents=True, exist_ok=True)
|
|
579
|
+
existing = path.read_text() if path.exists() else ""
|
|
580
|
+
if "<!-- ConductGuard" in existing:
|
|
581
|
+
print(f" {GRAY}Copilot instructions already contain ConductGuard policy ({path}){RESET}")
|
|
582
|
+
wrote_any = True
|
|
583
|
+
continue
|
|
584
|
+
updated = (existing.rstrip() + "\n\n" + GUARD_BLOCK).lstrip()
|
|
585
|
+
path.write_text(updated)
|
|
586
|
+
print(f" {GREEN}Copilot instructions updated with ConductGuard policy ({path}){RESET}")
|
|
587
|
+
wrote_any = True
|
|
588
|
+
break # repo-level wins; skip global if repo found
|
|
589
|
+
|
|
590
|
+
if not wrote_any:
|
|
591
|
+
# No .github/ dir found anywhere — write global
|
|
592
|
+
global_path = Path.home() / ".github" / "copilot-instructions.md"
|
|
593
|
+
global_path.parent.mkdir(parents=True, exist_ok=True)
|
|
594
|
+
global_path.write_text(GUARD_BLOCK)
|
|
595
|
+
print(f" {GREEN}Copilot instructions written ({global_path}){RESET}")
|
|
596
|
+
|
|
597
|
+
|
|
543
598
|
def _install_codex_hook(hook_path: Path) -> None:
|
|
544
599
|
"""Register PreToolUse and PostToolUse hooks in ~/.codex/hooks.json."""
|
|
545
600
|
codex_hooks = Path.home() / ".codex" / "hooks.json"
|
|
@@ -1351,7 +1406,7 @@ def cmd_guard_sync(args):
|
|
|
1351
1406
|
for t in _tools:
|
|
1352
1407
|
routed = "✓ Routed" if t.get("proxy_routed") else ("— Partial" if t["name"] == "codex-desktop" else "✗ Not routed")
|
|
1353
1408
|
mcp = "✓" if t.get("mcp_registered") else "✗"
|
|
1354
|
-
hook = "✓" if t.get("hook_registered") else "—"
|
|
1409
|
+
hook = "✓" if t.get("hook_registered") else ("~ soft" if t["name"] in ("copilot", "cursor") else "—")
|
|
1355
1410
|
print(f" {t['name']:<20} {routed:<16} {mcp:<8} {hook}")
|
|
1356
1411
|
print()
|
|
1357
1412
|
|
|
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
|