conduct-cli 0.6.25__tar.gz → 0.6.27__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.6.25 → conduct_cli-0.6.27}/PKG-INFO +2 -2
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/pyproject.toml +3 -3
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/guard.py +21 -26
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli.egg-info/PKG-INFO +2 -2
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli.egg-info/SOURCES.txt +0 -4
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli.egg-info/requires.txt +1 -1
- conduct_cli-0.6.25/src/conduct_cli/hook_precompact_template.py +0 -78
- conduct_cli-0.6.25/src/conduct_cli/hook_session_start_template.py +0 -161
- conduct_cli-0.6.25/src/conduct_cli/hook_stop_template.py +0 -42
- conduct_cli-0.6.25/src/conduct_cli/hook_template.py +0 -987
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/README.md +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/setup.cfg +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/setup.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/__init__.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/api.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/guardmcp.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/hooks/__init__.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/hooks/base.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/hooks/posttooluse.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/hooks/precompact.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/hooks/pretooluse.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/hooks/session_parser.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/hooks/session_start.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/hooks/stop.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/log_util.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/main.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/mcp_server.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/memory.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli/paxel.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli.egg-info/entry_points.txt +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/src/conduct_cli.egg-info/top_level.txt +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_bash_operator_signature.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_command_word_matcher.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_guard_policy.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_guard_savings.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_hook_syntax.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_journal_drain.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_log_util.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_proxy_env.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_signed_policy.py +0 -0
- {conduct_cli-0.6.25 → conduct_cli-0.6.27}/tests/test_switch.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conduct-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.27
|
|
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
|
|
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
Requires-Dist: pyyaml>=6.0
|
|
24
24
|
Requires-Dist: rich>=13.0
|
|
25
25
|
Provides-Extra: booster
|
|
26
|
-
Requires-Dist: agent-booster[watch]>=0.
|
|
26
|
+
Requires-Dist: agent-booster[watch]>=0.6.6; extra == "booster"
|
|
27
27
|
|
|
28
28
|
<!-- mcp-name: io.github.sseshachala/conduct-cli -->
|
|
29
29
|
# conduct-cli
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "conduct-cli"
|
|
7
|
-
version = "0.6.
|
|
7
|
+
version = "0.6.27"
|
|
8
8
|
description = "CLI for Conduct AI — install agents, manage projects, run tests"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = { text = "MIT" }
|
|
@@ -26,7 +26,7 @@ classifiers = [
|
|
|
26
26
|
dependencies = ["pyyaml>=6.0", "rich>=13.0"]
|
|
27
27
|
|
|
28
28
|
[project.optional-dependencies]
|
|
29
|
-
booster = ["agent-booster[watch]>=0.
|
|
29
|
+
booster = ["agent-booster[watch]>=0.6.6"]
|
|
30
30
|
|
|
31
31
|
[project.urls]
|
|
32
32
|
Homepage = "https://conductai.ai"
|
|
@@ -44,4 +44,4 @@ where = ["src"]
|
|
|
44
44
|
include = ["conduct_cli*"]
|
|
45
45
|
|
|
46
46
|
[tool.setuptools.package-data]
|
|
47
|
-
conduct_cli = ["
|
|
47
|
+
conduct_cli = ["paxel.py"]
|
|
@@ -22,11 +22,6 @@ CONFIG_PATH = GUARD_DIR / "config.json"
|
|
|
22
22
|
POLICY_PATH = GUARD_DIR / "policy.json"
|
|
23
23
|
|
|
24
24
|
# ── Hook templates — loaded from real .py files (no string embedding) ─────────
|
|
25
|
-
_TEMPLATES_DIR = Path(__file__).parent
|
|
26
|
-
|
|
27
|
-
def _read_template(name: str) -> str:
|
|
28
|
-
return (_TEMPLATES_DIR / name).read_text()
|
|
29
|
-
|
|
30
25
|
|
|
31
26
|
# ── Thin launcher content ─────────────────────────────────────────────────────
|
|
32
27
|
|
|
@@ -195,12 +190,7 @@ def _write_hook(path: Path) -> None:
|
|
|
195
190
|
backup = path.read_text()
|
|
196
191
|
path.parent.mkdir(parents=True, exist_ok=True)
|
|
197
192
|
|
|
198
|
-
|
|
199
|
-
try:
|
|
200
|
-
import conduct_cli.hooks.pretooluse # noqa: F401
|
|
201
|
-
content = _THIN_LAUNCHERS["pretooluse"]
|
|
202
|
-
except ImportError:
|
|
203
|
-
content = _read_template("hook_template.py")
|
|
193
|
+
content = _THIN_LAUNCHERS["pretooluse"]
|
|
204
194
|
|
|
205
195
|
path.write_text(content)
|
|
206
196
|
path.chmod(0o755)
|
|
@@ -216,18 +206,8 @@ def _write_hook(path: Path) -> None:
|
|
|
216
206
|
) from exc
|
|
217
207
|
|
|
218
208
|
|
|
219
|
-
def _write_session_hook(path: Path, launcher_key: str
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
If conduct_cli.hooks is importable, writes the thin launcher.
|
|
223
|
-
Falls back to the full template so old installs continue to work.
|
|
224
|
-
Also rewrites old-style (non-thin) hooks to thin launchers on sync.
|
|
225
|
-
"""
|
|
226
|
-
try:
|
|
227
|
-
import conduct_cli.hooks # noqa: F401
|
|
228
|
-
content = _THIN_LAUNCHERS[launcher_key]
|
|
229
|
-
except ImportError:
|
|
230
|
-
content = _read_template(template_name)
|
|
209
|
+
def _write_session_hook(path: Path, launcher_key: str) -> None:
|
|
210
|
+
content = _THIN_LAUNCHERS[launcher_key]
|
|
231
211
|
path.write_text(content)
|
|
232
212
|
path.chmod(0o755)
|
|
233
213
|
|
|
@@ -240,9 +220,9 @@ def _install_session_hooks() -> None:
|
|
|
240
220
|
session_start_path = GUARD_DIR / "guard-session-start.py"
|
|
241
221
|
stop_path = GUARD_DIR / "guard-stop.py"
|
|
242
222
|
|
|
243
|
-
_write_session_hook(precompact_path, "precompact"
|
|
244
|
-
_write_session_hook(session_start_path, "session-start"
|
|
245
|
-
_write_session_hook(stop_path, "stop"
|
|
223
|
+
_write_session_hook(precompact_path, "precompact")
|
|
224
|
+
_write_session_hook(session_start_path, "session-start")
|
|
225
|
+
_write_session_hook(stop_path, "stop")
|
|
246
226
|
|
|
247
227
|
claude_settings = Path.home() / ".claude" / "settings.json"
|
|
248
228
|
settings: dict = {}
|
|
@@ -1508,6 +1488,21 @@ def _ensure_booster(root: Path) -> None:
|
|
|
1508
1488
|
pass
|
|
1509
1489
|
print(f" {GREEN}Agent Booster:{RESET} {symbols_count} symbols indexed — Read/Grep intercept active")
|
|
1510
1490
|
|
|
1491
|
+
# Keep BOOSTER_SECRET in .mcp.json in sync with ~/.booster/.secret
|
|
1492
|
+
secret_file = Path.home() / ".booster" / ".secret"
|
|
1493
|
+
mcp_json = root / ".mcp.json"
|
|
1494
|
+
if secret_file.exists() and mcp_json.exists():
|
|
1495
|
+
try:
|
|
1496
|
+
expected = secret_file.read_text().strip()
|
|
1497
|
+
data = json.loads(mcp_json.read_text())
|
|
1498
|
+
server = data.get("mcpServers", {}).get("agent-booster", {})
|
|
1499
|
+
if server.get("env", {}).get("BOOSTER_SECRET") != expected:
|
|
1500
|
+
server.setdefault("env", {})["BOOSTER_SECRET"] = expected
|
|
1501
|
+
mcp_json.write_text(json.dumps(data, indent=2) + "\n")
|
|
1502
|
+
print(f" {GREEN}Agent Booster:{RESET} refreshed BOOSTER_SECRET in .mcp.json")
|
|
1503
|
+
except Exception:
|
|
1504
|
+
pass
|
|
1505
|
+
|
|
1511
1506
|
|
|
1512
1507
|
def _report_savings(cfg: dict, base_url: str, api_key: str) -> None:
|
|
1513
1508
|
import subprocess
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: conduct-cli
|
|
3
|
-
Version: 0.6.
|
|
3
|
+
Version: 0.6.27
|
|
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
|
|
@@ -23,7 +23,7 @@ Description-Content-Type: text/markdown
|
|
|
23
23
|
Requires-Dist: pyyaml>=6.0
|
|
24
24
|
Requires-Dist: rich>=13.0
|
|
25
25
|
Provides-Extra: booster
|
|
26
|
-
Requires-Dist: agent-booster[watch]>=0.
|
|
26
|
+
Requires-Dist: agent-booster[watch]>=0.6.6; extra == "booster"
|
|
27
27
|
|
|
28
28
|
<!-- mcp-name: io.github.sseshachala/conduct-cli -->
|
|
29
29
|
# conduct-cli
|
|
@@ -5,10 +5,6 @@ src/conduct_cli/__init__.py
|
|
|
5
5
|
src/conduct_cli/api.py
|
|
6
6
|
src/conduct_cli/guard.py
|
|
7
7
|
src/conduct_cli/guardmcp.py
|
|
8
|
-
src/conduct_cli/hook_precompact_template.py
|
|
9
|
-
src/conduct_cli/hook_session_start_template.py
|
|
10
|
-
src/conduct_cli/hook_stop_template.py
|
|
11
|
-
src/conduct_cli/hook_template.py
|
|
12
8
|
src/conduct_cli/log_util.py
|
|
13
9
|
src/conduct_cli/main.py
|
|
14
10
|
src/conduct_cli/mcp_server.py
|
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""ConductGuard PreCompact hook — persists session context before compaction."""
|
|
3
|
-
import json
|
|
4
|
-
import os
|
|
5
|
-
import subprocess
|
|
6
|
-
import sys
|
|
7
|
-
from datetime import datetime, timezone
|
|
8
|
-
from pathlib import Path
|
|
9
|
-
|
|
10
|
-
GUARD_DIR = Path.home() / ".conductguard"
|
|
11
|
-
SNAPSHOT_PATH = GUARD_DIR / "session_snapshot.json"
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def _git(cmd):
|
|
15
|
-
try:
|
|
16
|
-
return subprocess.check_output(
|
|
17
|
-
["git"] + cmd, stderr=subprocess.DEVNULL, text=True, timeout=3
|
|
18
|
-
).strip()
|
|
19
|
-
except Exception:
|
|
20
|
-
return ""
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
def _guard_status():
|
|
24
|
-
try:
|
|
25
|
-
out = subprocess.check_output(
|
|
26
|
-
["conductguard", "status", "--json"],
|
|
27
|
-
stderr=subprocess.DEVNULL, text=True, timeout=3,
|
|
28
|
-
)
|
|
29
|
-
return json.loads(out.strip())
|
|
30
|
-
except Exception:
|
|
31
|
-
return None
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
def _memory_headline():
|
|
35
|
-
try:
|
|
36
|
-
root = Path.cwd()
|
|
37
|
-
mem_key = str(root).replace("/", "-").lstrip("-")
|
|
38
|
-
candidates = [
|
|
39
|
-
Path.home() / ".claude" / "projects" / mem_key / "memory" / "MEMORY.md",
|
|
40
|
-
Path.home() / ".codex" / "projects" / mem_key / "memory" / "MEMORY.md",
|
|
41
|
-
]
|
|
42
|
-
for mem_path in candidates:
|
|
43
|
-
if mem_path.exists():
|
|
44
|
-
return "\n".join(mem_path.read_text().splitlines()[:10])
|
|
45
|
-
except Exception:
|
|
46
|
-
pass
|
|
47
|
-
return ""
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
def main():
|
|
51
|
-
try:
|
|
52
|
-
sys.stdin.read()
|
|
53
|
-
except Exception:
|
|
54
|
-
pass
|
|
55
|
-
|
|
56
|
-
try:
|
|
57
|
-
GUARD_DIR.mkdir(parents=True, exist_ok=True)
|
|
58
|
-
snapshot = {
|
|
59
|
-
"compacted_at": datetime.now(timezone.utc).isoformat(),
|
|
60
|
-
"tier1": {
|
|
61
|
-
"git_branch": _git(["branch", "--show-current"]),
|
|
62
|
-
"recent_commits": _git(["log", "--oneline", "-3"]),
|
|
63
|
-
"memory_headline": _memory_headline(),
|
|
64
|
-
},
|
|
65
|
-
"tier2": {"guard_status": _guard_status()},
|
|
66
|
-
"tier3": {"cwd": str(Path.cwd()), "python": sys.version.split()[0]},
|
|
67
|
-
}
|
|
68
|
-
tmp = GUARD_DIR / "session_snapshot.tmp"
|
|
69
|
-
tmp.write_text(json.dumps(snapshot, indent=2))
|
|
70
|
-
tmp.rename(SNAPSHOT_PATH)
|
|
71
|
-
except Exception:
|
|
72
|
-
pass
|
|
73
|
-
|
|
74
|
-
sys.exit(0)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
if __name__ == "__main__":
|
|
78
|
-
main()
|
|
@@ -1,161 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""ConductGuard SessionStart hook — prints context after compaction."""
|
|
3
|
-
import json
|
|
4
|
-
import sys
|
|
5
|
-
from datetime import datetime, timezone
|
|
6
|
-
from pathlib import Path
|
|
7
|
-
|
|
8
|
-
SNAPSHOT_PATH = Path.home() / ".conductguard" / "session_snapshot.json"
|
|
9
|
-
MAX_AGE_HOURS = 2
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
CONDUCT_ENV_PATH = Path.home() / ".conduct" / "env"
|
|
13
|
-
GUARD_CONFIG_PATH = Path.home() / ".conductguard" / "config.json"
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
def _check_proxy_token() -> None:
|
|
17
|
-
"""Warn + alert server if the proxy token is missing or malformed.
|
|
18
|
-
|
|
19
|
-
Reads ~/.conduct/env directly (not shell env) so this works regardless
|
|
20
|
-
of whether the user sourced their rc file in this session.
|
|
21
|
-
"""
|
|
22
|
-
if not CONDUCT_ENV_PATH.exists():
|
|
23
|
-
return
|
|
24
|
-
env_text = CONDUCT_ENV_PATH.read_text()
|
|
25
|
-
# Check if proxy is configured and token is valid
|
|
26
|
-
has_base_url = 'ANTHROPIC_BASE_URL=' in env_text
|
|
27
|
-
has_valid_token = 'ANTHROPIC_API_KEY="guard-mt-' in env_text or "ANTHROPIC_API_KEY='guard-mt-" in env_text
|
|
28
|
-
if not has_base_url:
|
|
29
|
-
return # proxy not configured — nothing to check
|
|
30
|
-
if has_valid_token:
|
|
31
|
-
return # all good
|
|
32
|
-
|
|
33
|
-
# Token is missing or malformed — warn locally and ping the server
|
|
34
|
-
print("## ConductGuard: proxy token missing or malformed")
|
|
35
|
-
print("Run `conduct guard sync` to refresh your token before making LLM calls.\n")
|
|
36
|
-
|
|
37
|
-
# Alert the server so the admin can prompt the developer to re-sync
|
|
38
|
-
try:
|
|
39
|
-
cfg: dict = {}
|
|
40
|
-
if GUARD_CONFIG_PATH.exists():
|
|
41
|
-
cfg = json.loads(GUARD_CONFIG_PATH.read_text())
|
|
42
|
-
workspace_id = cfg.get("workspace_id", "")
|
|
43
|
-
clerk_user_id = cfg.get("clerk_user_id", "") or cfg.get("user_email", "")
|
|
44
|
-
api_url = cfg.get("api_url", "https://api.conductai.ai").rstrip("/")
|
|
45
|
-
member_token = cfg.get("member_token", "")
|
|
46
|
-
if workspace_id and member_token:
|
|
47
|
-
import urllib.request
|
|
48
|
-
payload = json.dumps({
|
|
49
|
-
"workspace_id": workspace_id,
|
|
50
|
-
"clerk_user_id": clerk_user_id,
|
|
51
|
-
"ai_tool": "claude_code",
|
|
52
|
-
"tool_call": "session_start",
|
|
53
|
-
"decision": "warned",
|
|
54
|
-
"rule_id": "proxy_token_missing",
|
|
55
|
-
"rule_message": "Developer proxy token missing or malformed — run conduct guard sync",
|
|
56
|
-
"input_summary": "session_start: proxy token not found in ~/.conduct/env",
|
|
57
|
-
}).encode()
|
|
58
|
-
req = urllib.request.Request(
|
|
59
|
-
f"{api_url}/guard/events",
|
|
60
|
-
data=payload,
|
|
61
|
-
headers={"Content-Type": "application/json"},
|
|
62
|
-
method="POST",
|
|
63
|
-
)
|
|
64
|
-
urllib.request.urlopen(req, timeout=3)
|
|
65
|
-
except Exception:
|
|
66
|
-
pass # best-effort — never block the session
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def main():
|
|
70
|
-
try:
|
|
71
|
-
sys.stdin.read()
|
|
72
|
-
except Exception:
|
|
73
|
-
pass
|
|
74
|
-
|
|
75
|
-
_check_proxy_token()
|
|
76
|
-
|
|
77
|
-
if not SNAPSHOT_PATH.exists():
|
|
78
|
-
sys.exit(0)
|
|
79
|
-
|
|
80
|
-
try:
|
|
81
|
-
snapshot = json.loads(SNAPSHOT_PATH.read_text())
|
|
82
|
-
compacted_at = datetime.fromisoformat(snapshot.get("compacted_at", ""))
|
|
83
|
-
age_hours = (datetime.now(timezone.utc) - compacted_at).total_seconds() / 3600
|
|
84
|
-
if age_hours > MAX_AGE_HOURS:
|
|
85
|
-
sys.exit(0)
|
|
86
|
-
|
|
87
|
-
t1 = snapshot.get("tier1", {})
|
|
88
|
-
branch = t1.get("git_branch", "")
|
|
89
|
-
commits = t1.get("recent_commits", "")
|
|
90
|
-
headline = t1.get("memory_headline", "")
|
|
91
|
-
t2 = snapshot.get("tier2", {})
|
|
92
|
-
guard = t2.get("guard_status") or {}
|
|
93
|
-
|
|
94
|
-
lines = [f"## Session resumed (snapshot from {compacted_at.strftime('%Y-%m-%d %H:%M')} UTC)"]
|
|
95
|
-
if branch:
|
|
96
|
-
last = commits.splitlines()[0] if commits else ""
|
|
97
|
-
lines.append(f"- Branch: {branch}" + (f" | Last: {last}" if last else ""))
|
|
98
|
-
budget = guard.get("budget_pct")
|
|
99
|
-
if budget is not None:
|
|
100
|
-
lines.append(f"- Guard: {budget}% budget used")
|
|
101
|
-
else:
|
|
102
|
-
lines.append("- Guard: state unavailable")
|
|
103
|
-
if headline:
|
|
104
|
-
lines.append(f"- Memory index:\n {headline}")
|
|
105
|
-
else:
|
|
106
|
-
lines.append("- Memory index:\n (none)")
|
|
107
|
-
|
|
108
|
-
# Booster intercept status
|
|
109
|
-
try:
|
|
110
|
-
import shutil, sqlite3
|
|
111
|
-
root = Path.cwd()
|
|
112
|
-
if shutil.which("booster"):
|
|
113
|
-
db_path = root / ".booster" / "symbols.db"
|
|
114
|
-
hooks_path = root / ".claude" / "hooks" / "booster-gate.py"
|
|
115
|
-
if hooks_path.exists() and db_path.exists():
|
|
116
|
-
try:
|
|
117
|
-
conn = sqlite3.connect(str(db_path))
|
|
118
|
-
n = conn.execute("SELECT COUNT(*) FROM symbols").fetchone()[0]
|
|
119
|
-
conn.close()
|
|
120
|
-
lines.append(f"- Agent Booster: ACTIVE — {n} symbols indexed, Read/Grep intercept ON")
|
|
121
|
-
except Exception:
|
|
122
|
-
lines.append("- Agent Booster: installed (index unavailable)")
|
|
123
|
-
elif shutil.which("booster"):
|
|
124
|
-
lines.append("- Agent Booster: installed but NOT wired — run: conduct guard sync")
|
|
125
|
-
else:
|
|
126
|
-
lines.append("- Agent Booster: not installed (pip install 'conduct-cli[booster]')")
|
|
127
|
-
except Exception:
|
|
128
|
-
pass
|
|
129
|
-
|
|
130
|
-
# Inject relevant team memories for the current repo
|
|
131
|
-
try:
|
|
132
|
-
repo = None
|
|
133
|
-
try:
|
|
134
|
-
import subprocess
|
|
135
|
-
out = subprocess.check_output(["git", "remote", "get-url", "origin"],
|
|
136
|
-
stderr=subprocess.DEVNULL, text=True).strip()
|
|
137
|
-
if "github.com" in out:
|
|
138
|
-
repo = out.split("github.com")[-1].lstrip("/:").rstrip(".git")
|
|
139
|
-
except Exception:
|
|
140
|
-
pass
|
|
141
|
-
|
|
142
|
-
from conduct_cli.memory import search_team_memory
|
|
143
|
-
results = search_team_memory("recent learnings patterns bugs", repo=repo, limit=3)
|
|
144
|
-
if results:
|
|
145
|
-
lines.append("- Team knowledge:")
|
|
146
|
-
for r in results[:3]:
|
|
147
|
-
dev = r.get("developer_id", "teammate")[:8]
|
|
148
|
-
summary = r.get("summary", "")[:120]
|
|
149
|
-
lines.append(f" {dev}: {summary}")
|
|
150
|
-
except Exception:
|
|
151
|
-
pass
|
|
152
|
-
|
|
153
|
-
print("\n".join(lines))
|
|
154
|
-
except Exception:
|
|
155
|
-
pass
|
|
156
|
-
|
|
157
|
-
sys.exit(0)
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
if __name__ == "__main__":
|
|
161
|
-
main()
|
|
@@ -1,42 +0,0 @@
|
|
|
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()
|