conduct-cli 0.4.78__tar.gz → 0.4.80__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.4.78 → conduct_cli-0.4.80}/PKG-INFO +1 -1
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/pyproject.toml +2 -2
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/guard.py +19 -2
- conduct_cli-0.4.80/src/conduct_cli/hook_stop_template.py +42 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/memory.py +11 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli.egg-info/PKG-INFO +1 -1
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli.egg-info/SOURCES.txt +1 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/README.md +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/setup.cfg +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/setup.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/__init__.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/api.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/guardmcp.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/hook_precompact_template.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/hook_session_start_template.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/hook_template.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/main.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli/mcp_server.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli.egg-info/entry_points.txt +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli.egg-info/requires.txt +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/src/conduct_cli.egg-info/top_level.txt +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/tests/test_guard_policy.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/tests/test_guard_savings.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/tests/test_hook_syntax.py +0 -0
- {conduct_cli-0.4.78 → conduct_cli-0.4.80}/tests/test_switch.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.4.
|
|
7
|
+
version = "0.4.80"
|
|
8
8
|
description = "CLI for Conduct AI — install agents, manage projects, run tests"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -43,4 +43,4 @@ conductguard-post = "conduct_cli.guard:post_usage_main"
|
|
|
43
43
|
where = ["src"]
|
|
44
44
|
|
|
45
45
|
[tool.setuptools.package-data]
|
|
46
|
-
conduct_cli = ["hook_template.py", "hook_precompact_template.py", "hook_session_start_template.py"]
|
|
46
|
+
conduct_cli = ["hook_template.py", "hook_precompact_template.py", "hook_session_start_template.py", "hook_stop_template.py"]
|
|
@@ -119,16 +119,19 @@ def _write_hook(path: Path) -> None:
|
|
|
119
119
|
|
|
120
120
|
|
|
121
121
|
def _install_session_hooks() -> None:
|
|
122
|
-
"""Write PreCompact + SessionStart hook scripts and register them in ~/.claude/settings.json."""
|
|
122
|
+
"""Write PreCompact + SessionStart + Stop hook scripts and register them in ~/.claude/settings.json."""
|
|
123
123
|
python = _best_python()
|
|
124
124
|
|
|
125
125
|
precompact_path = GUARD_DIR / "guard-precompact.py"
|
|
126
126
|
session_start_path = GUARD_DIR / "guard-session-start.py"
|
|
127
|
+
stop_path = GUARD_DIR / "guard-stop.py"
|
|
127
128
|
|
|
128
129
|
precompact_path.write_text(_read_template("hook_precompact_template.py"))
|
|
129
130
|
precompact_path.chmod(0o755)
|
|
130
131
|
session_start_path.write_text(_read_template("hook_session_start_template.py"))
|
|
131
132
|
session_start_path.chmod(0o755)
|
|
133
|
+
stop_path.write_text(_read_template("hook_stop_template.py"))
|
|
134
|
+
stop_path.chmod(0o755)
|
|
132
135
|
|
|
133
136
|
claude_settings = Path.home() / ".claude" / "settings.json"
|
|
134
137
|
settings: dict = {}
|
|
@@ -396,7 +399,7 @@ def _install_claude_hook(hook_path: Path) -> None:
|
|
|
396
399
|
if cleaned:
|
|
397
400
|
changed = True
|
|
398
401
|
|
|
399
|
-
# Stop — auto-sync
|
|
402
|
+
# Stop — (1) auto-sync savings, (2) capture session for team memory
|
|
400
403
|
stop = hooks.setdefault("Stop", [])
|
|
401
404
|
stop_cmd = "conduct guard sync"
|
|
402
405
|
stop_already = any(
|
|
@@ -408,6 +411,18 @@ def _install_claude_hook(hook_path: Path) -> None:
|
|
|
408
411
|
stop.append({"hooks": [{"type": "command", "command": stop_cmd}]})
|
|
409
412
|
changed = True
|
|
410
413
|
|
|
414
|
+
python = _best_python()
|
|
415
|
+
stop_path = GUARD_DIR / "guard-stop.py"
|
|
416
|
+
mem_cmd = f"{python} {stop_path}"
|
|
417
|
+
mem_already = any(
|
|
418
|
+
"guard-stop" in e.get("command", "")
|
|
419
|
+
for h in stop
|
|
420
|
+
for e in h.get("hooks", [])
|
|
421
|
+
)
|
|
422
|
+
if not mem_already and stop_path.exists():
|
|
423
|
+
stop.append({"hooks": [{"type": "command", "command": mem_cmd}]})
|
|
424
|
+
changed = True
|
|
425
|
+
|
|
411
426
|
if changed:
|
|
412
427
|
claude_settings.parent.mkdir(parents=True, exist_ok=True)
|
|
413
428
|
claude_settings.write_text(json.dumps(settings, indent=2))
|
|
@@ -417,6 +432,8 @@ def _install_claude_hook(hook_path: Path) -> None:
|
|
|
417
432
|
print(f" {GREEN}Claude Code PostToolUse hook registered{RESET}")
|
|
418
433
|
if not stop_already:
|
|
419
434
|
print(f" {GREEN}Claude Code Stop hook registered (auto-sync savings){RESET}")
|
|
435
|
+
if not mem_already:
|
|
436
|
+
print(f" {GREEN}Claude Code Stop hook registered (team memory capture){RESET}")
|
|
420
437
|
else:
|
|
421
438
|
print(f" {GRAY}Claude Code hooks already registered{RESET}")
|
|
422
439
|
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""ConductGuard Stop hook — captures session transcript for team memory."""
|
|
3
|
+
import json
|
|
4
|
+
import subprocess
|
|
5
|
+
import sys
|
|
6
|
+
from pathlib import Path
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def _detect_repo():
|
|
10
|
+
try:
|
|
11
|
+
out = subprocess.check_output(
|
|
12
|
+
["git", "remote", "get-url", "origin"],
|
|
13
|
+
stderr=subprocess.DEVNULL, text=True,
|
|
14
|
+
).strip()
|
|
15
|
+
if "github.com" in out:
|
|
16
|
+
return out.split("github.com")[-1].lstrip("/:").rstrip(".git")
|
|
17
|
+
except Exception:
|
|
18
|
+
pass
|
|
19
|
+
return None
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
def main():
|
|
23
|
+
try:
|
|
24
|
+
raw = sys.stdin.read()
|
|
25
|
+
data = json.loads(raw) if raw.strip() else {}
|
|
26
|
+
except Exception:
|
|
27
|
+
data = {}
|
|
28
|
+
|
|
29
|
+
session_id = data.get("session_id", "")
|
|
30
|
+
transcript_path = data.get("transcript_path") or data.get("transcriptPath")
|
|
31
|
+
|
|
32
|
+
try:
|
|
33
|
+
from conduct_cli.memory import post_session_to_api
|
|
34
|
+
post_session_to_api(session_id, transcript_path, _detect_repo())
|
|
35
|
+
except Exception:
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
sys.exit(0)
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
if __name__ == "__main__":
|
|
42
|
+
main()
|
|
@@ -36,12 +36,23 @@ def post_session_to_api(session_id: str, transcript_path: str | None, repo: str
|
|
|
36
36
|
except Exception:
|
|
37
37
|
pass
|
|
38
38
|
|
|
39
|
+
developer_id = cfg.get("user_id") or cfg.get("email") or cfg.get("member_email")
|
|
40
|
+
if not developer_id:
|
|
41
|
+
try:
|
|
42
|
+
import subprocess as _sp
|
|
43
|
+
developer_id = _sp.check_output(
|
|
44
|
+
["git", "config", "user.email"], stderr=_sp.DEVNULL, text=True
|
|
45
|
+
).strip() or None
|
|
46
|
+
except Exception:
|
|
47
|
+
pass
|
|
48
|
+
|
|
39
49
|
payload = json.dumps({
|
|
40
50
|
"session_id": session_id,
|
|
41
51
|
"tool": "claude_code",
|
|
42
52
|
"repo_full_name": repo,
|
|
43
53
|
"raw_transcript": raw_transcript,
|
|
44
54
|
"files_touched": [],
|
|
55
|
+
"developer_id": developer_id,
|
|
45
56
|
}).encode()
|
|
46
57
|
|
|
47
58
|
def _send():
|
|
@@ -7,6 +7,7 @@ src/conduct_cli/guard.py
|
|
|
7
7
|
src/conduct_cli/guardmcp.py
|
|
8
8
|
src/conduct_cli/hook_precompact_template.py
|
|
9
9
|
src/conduct_cli/hook_session_start_template.py
|
|
10
|
+
src/conduct_cli/hook_stop_template.py
|
|
10
11
|
src/conduct_cli/hook_template.py
|
|
11
12
|
src/conduct_cli/main.py
|
|
12
13
|
src/conduct_cli/mcp_server.py
|
|
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
|