canopy-cli 3.1.0__py3-none-any.whl
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.
- canopy/__init__.py +2 -0
- canopy/actions/__init__.py +32 -0
- canopy/actions/aliases.py +421 -0
- canopy/actions/augments.py +55 -0
- canopy/actions/bootstrap.py +249 -0
- canopy/actions/bot_resolutions.py +123 -0
- canopy/actions/bot_status.py +133 -0
- canopy/actions/commit.py +511 -0
- canopy/actions/conflicts.py +314 -0
- canopy/actions/doctor.py +1459 -0
- canopy/actions/draft_replies.py +185 -0
- canopy/actions/drift.py +241 -0
- canopy/actions/errors.py +115 -0
- canopy/actions/evacuate.py +192 -0
- canopy/actions/feature_state.py +607 -0
- canopy/actions/historian.py +612 -0
- canopy/actions/ide_workspace.py +49 -0
- canopy/actions/last_visit.py +83 -0
- canopy/actions/migrate_slots.py +313 -0
- canopy/actions/preflight_state.py +97 -0
- canopy/actions/push.py +199 -0
- canopy/actions/reads.py +304 -0
- canopy/actions/resume.py +582 -0
- canopy/actions/review_filter.py +135 -0
- canopy/actions/ship.py +399 -0
- canopy/actions/slot_details.py +208 -0
- canopy/actions/slot_load.py +383 -0
- canopy/actions/slots.py +221 -0
- canopy/actions/stash.py +230 -0
- canopy/actions/switch.py +775 -0
- canopy/actions/switch_preflight.py +192 -0
- canopy/actions/thread_actions.py +88 -0
- canopy/actions/thread_resolutions.py +101 -0
- canopy/actions/triage.py +286 -0
- canopy/agent/__init__.py +5 -0
- canopy/agent/runner.py +129 -0
- canopy/agent_setup/__init__.py +264 -0
- canopy/agent_setup/skills/augment-canopy/SKILL.md +116 -0
- canopy/agent_setup/skills/using-canopy/SKILL.md +191 -0
- canopy/cli/__init__.py +0 -0
- canopy/cli/main.py +4152 -0
- canopy/cli/render.py +98 -0
- canopy/cli/ui.py +150 -0
- canopy/features/__init__.py +2 -0
- canopy/features/coordinator.py +1256 -0
- canopy/git/__init__.py +0 -0
- canopy/git/hooks.py +173 -0
- canopy/git/multi.py +435 -0
- canopy/git/repo.py +859 -0
- canopy/git/templates/post-checkout.py +67 -0
- canopy/graph/__init__.py +0 -0
- canopy/integrations/__init__.py +0 -0
- canopy/integrations/github.py +983 -0
- canopy/integrations/linear.py +307 -0
- canopy/integrations/precommit.py +239 -0
- canopy/mcp/__init__.py +0 -0
- canopy/mcp/client.py +329 -0
- canopy/mcp/server.py +1797 -0
- canopy/providers/__init__.py +105 -0
- canopy/providers/github_issues.py +289 -0
- canopy/providers/linear.py +341 -0
- canopy/providers/types.py +149 -0
- canopy/workspace/__init__.py +4 -0
- canopy/workspace/config.py +378 -0
- canopy/workspace/context.py +224 -0
- canopy/workspace/discovery.py +197 -0
- canopy/workspace/workspace.py +173 -0
- canopy_cli-3.1.0.dist-info/METADATA +282 -0
- canopy_cli-3.1.0.dist-info/RECORD +71 -0
- canopy_cli-3.1.0.dist-info/WHEEL +4 -0
- canopy_cli-3.1.0.dist-info/entry_points.txt +3 -0
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# __CANOPY_HOOK_MARKER__ post-checkout v1
|
|
3
|
+
"""Canopy post-checkout hook — records HEAD state to .canopy/state/heads.json.
|
|
4
|
+
|
|
5
|
+
Installed by `canopy hooks install`. Never blocks git operations on errors.
|
|
6
|
+
Chains to a pre-existing post-checkout.canopy-chained if present.
|
|
7
|
+
"""
|
|
8
|
+
import fcntl
|
|
9
|
+
import json
|
|
10
|
+
import os
|
|
11
|
+
import subprocess
|
|
12
|
+
import sys
|
|
13
|
+
from datetime import datetime, timezone
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
|
|
16
|
+
# Substituted at install time.
|
|
17
|
+
CANOPY_REPO = "__CANOPY_REPO__"
|
|
18
|
+
CANOPY_WORKSPACE_ROOT = Path("__CANOPY_WORKSPACE_ROOT__")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
def _record_state() -> None:
|
|
22
|
+
if len(sys.argv) < 4:
|
|
23
|
+
return
|
|
24
|
+
prev_sha, new_sha, is_branch_checkout = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
25
|
+
# Only record on branch checkouts (not file checkouts).
|
|
26
|
+
if is_branch_checkout != "1":
|
|
27
|
+
return
|
|
28
|
+
|
|
29
|
+
branch = subprocess.run(
|
|
30
|
+
["git", "rev-parse", "--abbrev-ref", "HEAD"],
|
|
31
|
+
capture_output=True, text=True, check=False,
|
|
32
|
+
).stdout.strip()
|
|
33
|
+
if not branch or branch == "HEAD":
|
|
34
|
+
return # detached; skip
|
|
35
|
+
|
|
36
|
+
ts = datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
|
|
37
|
+
entry = {"branch": branch, "sha": new_sha, "prev_sha": prev_sha, "ts": ts}
|
|
38
|
+
|
|
39
|
+
state_dir = CANOPY_WORKSPACE_ROOT / ".canopy" / "state"
|
|
40
|
+
state_dir.mkdir(parents=True, exist_ok=True)
|
|
41
|
+
state_file = state_dir / "heads.json"
|
|
42
|
+
lock_file = state_dir / "heads.json.lock"
|
|
43
|
+
|
|
44
|
+
with open(lock_file, "w") as lock:
|
|
45
|
+
fcntl.flock(lock.fileno(), fcntl.LOCK_EX)
|
|
46
|
+
try:
|
|
47
|
+
state = json.loads(state_file.read_text())
|
|
48
|
+
except (FileNotFoundError, json.JSONDecodeError):
|
|
49
|
+
state = {}
|
|
50
|
+
state[CANOPY_REPO] = entry
|
|
51
|
+
tmp = state_file.with_suffix(".json.tmp")
|
|
52
|
+
tmp.write_text(json.dumps(state, indent=2))
|
|
53
|
+
os.replace(tmp, state_file)
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
def _chain_existing() -> None:
|
|
57
|
+
chained = Path(__file__).parent / "post-checkout.canopy-chained"
|
|
58
|
+
if chained.is_file() and os.access(chained, os.X_OK):
|
|
59
|
+
os.execv(str(chained), [str(chained), *sys.argv[1:]])
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
if __name__ == "__main__":
|
|
63
|
+
try:
|
|
64
|
+
_record_state()
|
|
65
|
+
except Exception:
|
|
66
|
+
pass # never block git on hook failure
|
|
67
|
+
_chain_existing()
|
canopy/graph/__init__.py
ADDED
|
File without changes
|
|
File without changes
|