conduct-cli 0.8.8__tar.gz → 0.8.9__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.8.8 → conduct_cli-0.8.9}/PKG-INFO +1 -1
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/pyproject.toml +1 -1
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/pretooluse.py +56 -9
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli.egg-info/PKG-INFO +1 -1
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/README.md +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/setup.cfg +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/setup.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/__init__.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/api.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/guard.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/guard_policy.md +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/guardmcp.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/__init__.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/base.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/posttooluse.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/precompact.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/session_parser.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/session_report_push.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/session_start.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/hooks/stop.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/log_util.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/main.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/mcp_server.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/memory.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/paxel.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli/tool_groups.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli.egg-info/SOURCES.txt +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli.egg-info/dependency_links.txt +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli.egg-info/entry_points.txt +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli.egg-info/requires.txt +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/src/conduct_cli.egg-info/top_level.txt +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_advisory_and_hook.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_api_client.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_bash_operator_signature.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_blast_radius.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_cmd_run.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_command_word_matcher.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_drain_daemon_health.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_guard_policy.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_guard_savings.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_hook_dispatch.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_instruction_files.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_journal_drain.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_log_util.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_proxy_coverage.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_proxy_env.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_report_tool_coverage.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_signed_policy.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/tests/test_switch.py +0 -0
- {conduct_cli-0.8.8 → conduct_cli-0.8.9}/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.8.
|
|
7
|
+
version = "0.8.9"
|
|
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" }
|
|
@@ -321,25 +321,72 @@ DEV_PATH_MARKERS = (
|
|
|
321
321
|
"/apps/api/alembic/versions/",
|
|
322
322
|
"/apps/api/tests/",
|
|
323
323
|
"/apps/api/app/modules/agent_identity/",
|
|
324
|
-
"/apps/api/app/
|
|
325
|
-
|
|
326
|
-
|
|
324
|
+
"/apps/api/app/modules/guard/cedar_adapter/",
|
|
325
|
+
# Removed /apps/web/src/ and /docs/ — too generic; those substrings appear
|
|
326
|
+
# in ordinary Next.js apps and every project with a docs folder, which
|
|
327
|
+
# would silently disable compliance rules in customer repos (#1049).
|
|
327
328
|
)
|
|
328
329
|
|
|
330
|
+
# Sentinel file at repo root marks a Conduct source repo — required for
|
|
331
|
+
# DEV_PATH_MARKERS to activate. Without this file, doc-sensitive rules apply
|
|
332
|
+
# everywhere, including in paths that happen to match Conduct-specific
|
|
333
|
+
# subpaths. Prevents cross-project bypass of compliance rules.
|
|
334
|
+
DEV_SENTINEL_FILENAME = ".conduct-dev-repo"
|
|
335
|
+
|
|
336
|
+
_DEV_SENTINEL_CACHE: dict[str, bool] = {}
|
|
337
|
+
|
|
338
|
+
|
|
339
|
+
def _find_dev_sentinel(start_path: str) -> bool:
|
|
340
|
+
"""Walk up from start_path looking for the DEV_SENTINEL_FILENAME marker.
|
|
341
|
+
|
|
342
|
+
Cached per starting directory. Returns False if start_path is empty or
|
|
343
|
+
the walk hits root without finding the sentinel.
|
|
344
|
+
"""
|
|
345
|
+
if not start_path:
|
|
346
|
+
return False
|
|
347
|
+
try:
|
|
348
|
+
p = Path(start_path).resolve()
|
|
349
|
+
except Exception:
|
|
350
|
+
return False
|
|
351
|
+
d = str(p.parent if not p.is_dir() else p)
|
|
352
|
+
if d in _DEV_SENTINEL_CACHE:
|
|
353
|
+
return _DEV_SENTINEL_CACHE[d]
|
|
354
|
+
cur = Path(d)
|
|
355
|
+
seen: list[str] = []
|
|
356
|
+
while True:
|
|
357
|
+
seen.append(str(cur))
|
|
358
|
+
try:
|
|
359
|
+
if (cur / DEV_SENTINEL_FILENAME).is_file():
|
|
360
|
+
for s in seen:
|
|
361
|
+
_DEV_SENTINEL_CACHE[s] = True
|
|
362
|
+
return True
|
|
363
|
+
except Exception:
|
|
364
|
+
break
|
|
365
|
+
parent = cur.parent
|
|
366
|
+
if parent == cur:
|
|
367
|
+
break
|
|
368
|
+
cur = parent
|
|
369
|
+
for s in seen:
|
|
370
|
+
_DEV_SENTINEL_CACHE[s] = False
|
|
371
|
+
return False
|
|
372
|
+
|
|
329
373
|
|
|
330
374
|
def _is_developer_source_path(tool_input: dict) -> bool:
|
|
331
|
-
"""True if the tool_input targets a path
|
|
375
|
+
"""True if the tool_input targets a path in a Conduct source-repo AND
|
|
376
|
+
matches a Conduct-specific dev marker.
|
|
332
377
|
|
|
333
|
-
|
|
334
|
-
|
|
378
|
+
Both conditions required — the sentinel file gates the exclusion so
|
|
379
|
+
customer repos with similar subpaths do not silently bypass rules.
|
|
335
380
|
"""
|
|
336
381
|
for field in ("file_path", "path"):
|
|
337
382
|
p = tool_input.get(field, "") or ""
|
|
338
383
|
if not p:
|
|
339
384
|
continue
|
|
340
|
-
for marker in DEV_PATH_MARKERS
|
|
341
|
-
|
|
342
|
-
|
|
385
|
+
matched_marker = any(marker in p for marker in DEV_PATH_MARKERS)
|
|
386
|
+
if not matched_marker:
|
|
387
|
+
continue
|
|
388
|
+
if _find_dev_sentinel(p):
|
|
389
|
+
return True
|
|
343
390
|
return False
|
|
344
391
|
|
|
345
392
|
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|