oh-my-claude-sisyphus 3.6.1 → 3.6.3
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.
- package/commands/doctor.md +1 -1
- package/commands/psm.md +180 -0
- package/dist/__tests__/analytics/analytics-summary.test.d.ts +2 -0
- package/dist/__tests__/analytics/analytics-summary.test.d.ts.map +1 -0
- package/dist/__tests__/analytics/analytics-summary.test.js +267 -0
- package/dist/__tests__/analytics/analytics-summary.test.js.map +1 -0
- package/dist/__tests__/analytics/cost-estimator.test.d.ts +2 -0
- package/dist/__tests__/analytics/cost-estimator.test.d.ts.map +1 -0
- package/dist/__tests__/analytics/cost-estimator.test.js +212 -0
- package/dist/__tests__/analytics/cost-estimator.test.js.map +1 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts +7 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.d.ts.map +1 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js +374 -0
- package/dist/__tests__/hooks/auto-slash-command/executor.test.js.map +1 -0
- package/dist/__tests__/hud/auto-tracking.integration.test.d.ts +2 -0
- package/dist/__tests__/hud/auto-tracking.integration.test.d.ts.map +1 -0
- package/dist/__tests__/hud/auto-tracking.integration.test.js +12 -0
- package/dist/__tests__/hud/auto-tracking.integration.test.js.map +1 -0
- package/dist/__tests__/installer.test.js +1 -1
- package/dist/__tests__/learned-skills/config.test.d.ts +2 -0
- package/dist/__tests__/learned-skills/config.test.d.ts.map +1 -0
- package/dist/__tests__/learned-skills/config.test.js +37 -0
- package/dist/__tests__/learned-skills/config.test.js.map +1 -0
- package/dist/__tests__/learned-skills/detector.test.d.ts +2 -0
- package/dist/__tests__/learned-skills/detector.test.d.ts.map +1 -0
- package/dist/__tests__/learned-skills/detector.test.js +99 -0
- package/dist/__tests__/learned-skills/detector.test.js.map +1 -0
- package/dist/__tests__/learned-skills/finder.test.d.ts +2 -0
- package/dist/__tests__/learned-skills/finder.test.d.ts.map +1 -0
- package/dist/__tests__/learned-skills/finder.test.js +59 -0
- package/dist/__tests__/learned-skills/finder.test.js.map +1 -0
- package/dist/__tests__/learned-skills/loader.test.d.ts +2 -0
- package/dist/__tests__/learned-skills/loader.test.d.ts.map +1 -0
- package/dist/__tests__/learned-skills/loader.test.js +69 -0
- package/dist/__tests__/learned-skills/loader.test.js.map +1 -0
- package/dist/__tests__/learned-skills/parser.test.d.ts +2 -0
- package/dist/__tests__/learned-skills/parser.test.d.ts.map +1 -0
- package/dist/__tests__/learned-skills/parser.test.js +81 -0
- package/dist/__tests__/learned-skills/parser.test.js.map +1 -0
- package/dist/__tests__/learned-skills/validator.test.d.ts +2 -0
- package/dist/__tests__/learned-skills/validator.test.d.ts.map +1 -0
- package/dist/__tests__/learned-skills/validator.test.js +85 -0
- package/dist/__tests__/learned-skills/validator.test.js.map +1 -0
- package/dist/__tests__/skills.test.js +6 -5
- package/dist/__tests__/skills.test.js.map +1 -1
- package/dist/agents/codex-agents.d.ts +20 -0
- package/dist/agents/codex-agents.d.ts.map +1 -0
- package/dist/agents/codex-agents.js +36 -0
- package/dist/agents/codex-agents.js.map +1 -0
- package/dist/agents/document-writer.d.ts +11 -0
- package/dist/agents/document-writer.d.ts.map +1 -0
- package/dist/agents/document-writer.js +209 -0
- package/dist/agents/document-writer.js.map +1 -0
- package/dist/agents/frontend-engineer.d.ts +11 -0
- package/dist/agents/frontend-engineer.d.ts.map +1 -0
- package/dist/agents/frontend-engineer.js +115 -0
- package/dist/agents/frontend-engineer.js.map +1 -0
- package/dist/agents/librarian.d.ts +12 -0
- package/dist/agents/librarian.d.ts.map +1 -0
- package/dist/agents/librarian.js +103 -0
- package/dist/agents/librarian.js.map +1 -0
- package/dist/agents/metis.d.ts +12 -0
- package/dist/agents/metis.d.ts.map +1 -0
- package/dist/agents/metis.js +117 -0
- package/dist/agents/metis.js.map +1 -0
- package/dist/agents/momus.d.ts +12 -0
- package/dist/agents/momus.d.ts.map +1 -0
- package/dist/agents/momus.js +128 -0
- package/dist/agents/momus.js.map +1 -0
- package/dist/agents/multimodal-looker.d.ts +11 -0
- package/dist/agents/multimodal-looker.d.ts.map +1 -0
- package/dist/agents/multimodal-looker.js +70 -0
- package/dist/agents/multimodal-looker.js.map +1 -0
- package/dist/agents/oracle.d.ts +13 -0
- package/dist/agents/oracle.d.ts.map +1 -0
- package/dist/agents/oracle.js +191 -0
- package/dist/agents/oracle.js.map +1 -0
- package/dist/agents/orchestrator-sisyphus.d.ts +11 -0
- package/dist/agents/orchestrator-sisyphus.d.ts.map +1 -0
- package/dist/agents/orchestrator-sisyphus.js +115 -0
- package/dist/agents/orchestrator-sisyphus.js.map +1 -0
- package/dist/agents/prometheus.d.ts +12 -0
- package/dist/agents/prometheus.d.ts.map +1 -0
- package/dist/agents/prometheus.js +195 -0
- package/dist/agents/prometheus.js.map +1 -0
- package/dist/agents/sisyphus-junior.d.ts +12 -0
- package/dist/agents/sisyphus-junior.d.ts.map +1 -0
- package/dist/agents/sisyphus-junior.js +93 -0
- package/dist/agents/sisyphus-junior.js.map +1 -0
- package/dist/cli/analytics.js +0 -0
- package/dist/cli/components/CostDashboard.d.ts +15 -0
- package/dist/cli/components/CostDashboard.d.ts.map +1 -0
- package/dist/cli/components/CostDashboard.js +15 -0
- package/dist/cli/components/CostDashboard.js.map +1 -0
- package/dist/cli/components/LiveStats.d.ts +16 -0
- package/dist/cli/components/LiveStats.d.ts.map +1 -0
- package/dist/cli/components/LiveStats.js +16 -0
- package/dist/cli/components/LiveStats.js.map +1 -0
- package/dist/cli/components/SessionBrowser.d.ts +14 -0
- package/dist/cli/components/SessionBrowser.d.ts.map +1 -0
- package/dist/cli/components/SessionBrowser.js +14 -0
- package/dist/cli/components/SessionBrowser.js.map +1 -0
- package/dist/cli/index.js +0 -0
- package/dist/cli/tui.d.ts +21 -0
- package/dist/cli/tui.d.ts.map +1 -0
- package/dist/cli/tui.js +21 -0
- package/dist/cli/tui.js.map +1 -0
- package/dist/hooks/autopilot/signals.d.ts +20 -0
- package/dist/hooks/autopilot/signals.d.ts.map +1 -0
- package/dist/hooks/autopilot/signals.js +75 -0
- package/dist/hooks/autopilot/signals.js.map +1 -0
- package/dist/hooks/autopilot/summary.d.ts +27 -0
- package/dist/hooks/autopilot/summary.d.ts.map +1 -0
- package/dist/hooks/autopilot/summary.js +160 -0
- package/dist/hooks/autopilot/summary.js.map +1 -0
- package/dist/hooks/autopilot/transition.d.ts +39 -0
- package/dist/hooks/autopilot/transition.d.ts.map +1 -0
- package/dist/hooks/autopilot/transition.js +216 -0
- package/dist/hooks/autopilot/transition.js.map +1 -0
- package/dist/hooks/context-window-limit-recovery/constants.d.ts +28 -0
- package/dist/hooks/context-window-limit-recovery/constants.d.ts.map +1 -0
- package/dist/hooks/context-window-limit-recovery/constants.js +85 -0
- package/dist/hooks/context-window-limit-recovery/constants.js.map +1 -0
- package/dist/hooks/context-window-limit-recovery/index.d.ts +62 -0
- package/dist/hooks/context-window-limit-recovery/index.d.ts.map +1 -0
- package/dist/hooks/context-window-limit-recovery/index.js +201 -0
- package/dist/hooks/context-window-limit-recovery/index.js.map +1 -0
- package/dist/hooks/context-window-limit-recovery/parser.d.ts +31 -0
- package/dist/hooks/context-window-limit-recovery/parser.d.ts.map +1 -0
- package/dist/hooks/context-window-limit-recovery/parser.js +241 -0
- package/dist/hooks/context-window-limit-recovery/parser.js.map +1 -0
- package/dist/hooks/context-window-limit-recovery/types.d.ts +84 -0
- package/dist/hooks/context-window-limit-recovery/types.d.ts.map +1 -0
- package/dist/hooks/context-window-limit-recovery/types.js +34 -0
- package/dist/hooks/context-window-limit-recovery/types.js.map +1 -0
- package/dist/hooks/edit-error-recovery/index.d.ts +62 -0
- package/dist/hooks/edit-error-recovery/index.d.ts.map +1 -0
- package/dist/hooks/edit-error-recovery/index.js +89 -0
- package/dist/hooks/edit-error-recovery/index.js.map +1 -0
- package/dist/hooks/learned-skills/config.d.ts +53 -0
- package/dist/hooks/learned-skills/config.d.ts.map +1 -0
- package/dist/hooks/learned-skills/config.js +103 -0
- package/dist/hooks/learned-skills/config.js.map +1 -0
- package/dist/hooks/learned-skills/constants.d.ts +24 -0
- package/dist/hooks/learned-skills/constants.d.ts.map +1 -0
- package/dist/hooks/learned-skills/constants.js +26 -0
- package/dist/hooks/learned-skills/constants.js.map +1 -0
- package/dist/hooks/learned-skills/detection-hook.d.ts +39 -0
- package/dist/hooks/learned-skills/detection-hook.d.ts.map +1 -0
- package/dist/hooks/learned-skills/detection-hook.js +83 -0
- package/dist/hooks/learned-skills/detection-hook.js.map +1 -0
- package/dist/hooks/learned-skills/detector.d.ts +30 -0
- package/dist/hooks/learned-skills/detector.d.ts.map +1 -0
- package/dist/hooks/learned-skills/detector.js +150 -0
- package/dist/hooks/learned-skills/detector.js.map +1 -0
- package/dist/hooks/learned-skills/finder.d.ts +21 -0
- package/dist/hooks/learned-skills/finder.d.ts.map +1 -0
- package/dist/hooks/learned-skills/finder.js +117 -0
- package/dist/hooks/learned-skills/finder.js.map +1 -0
- package/dist/hooks/learned-skills/index.d.ts +62 -0
- package/dist/hooks/learned-skills/index.d.ts.map +1 -0
- package/dist/hooks/learned-skills/index.js +137 -0
- package/dist/hooks/learned-skills/index.js.map +1 -0
- package/dist/hooks/learned-skills/loader.d.ts +20 -0
- package/dist/hooks/learned-skills/loader.d.ts.map +1 -0
- package/dist/hooks/learned-skills/loader.js +107 -0
- package/dist/hooks/learned-skills/loader.js.map +1 -0
- package/dist/hooks/learned-skills/parser.d.ts +21 -0
- package/dist/hooks/learned-skills/parser.d.ts.map +1 -0
- package/dist/hooks/learned-skills/parser.js +190 -0
- package/dist/hooks/learned-skills/parser.js.map +1 -0
- package/dist/hooks/learned-skills/promotion.d.ts +29 -0
- package/dist/hooks/learned-skills/promotion.d.ts.map +1 -0
- package/dist/hooks/learned-skills/promotion.js +87 -0
- package/dist/hooks/learned-skills/promotion.js.map +1 -0
- package/dist/hooks/learned-skills/types.d.ts +109 -0
- package/dist/hooks/learned-skills/types.d.ts.map +1 -0
- package/dist/hooks/learned-skills/types.js +8 -0
- package/dist/hooks/learned-skills/types.js.map +1 -0
- package/dist/hooks/learned-skills/validator.d.ts +15 -0
- package/dist/hooks/learned-skills/validator.d.ts.map +1 -0
- package/dist/hooks/learned-skills/validator.js +87 -0
- package/dist/hooks/learned-skills/validator.js.map +1 -0
- package/dist/hooks/learned-skills/writer.d.ts +27 -0
- package/dist/hooks/learned-skills/writer.d.ts.map +1 -0
- package/dist/hooks/learned-skills/writer.js +126 -0
- package/dist/hooks/learned-skills/writer.js.map +1 -0
- package/dist/hooks/mnemosyne/config.d.ts +53 -0
- package/dist/hooks/mnemosyne/config.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/config.js +103 -0
- package/dist/hooks/mnemosyne/config.js.map +1 -0
- package/dist/hooks/mnemosyne/constants.d.ts +24 -0
- package/dist/hooks/mnemosyne/constants.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/constants.js +26 -0
- package/dist/hooks/mnemosyne/constants.js.map +1 -0
- package/dist/hooks/mnemosyne/detection-hook.d.ts +39 -0
- package/dist/hooks/mnemosyne/detection-hook.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/detection-hook.js +83 -0
- package/dist/hooks/mnemosyne/detection-hook.js.map +1 -0
- package/dist/hooks/mnemosyne/detector.d.ts +30 -0
- package/dist/hooks/mnemosyne/detector.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/detector.js +150 -0
- package/dist/hooks/mnemosyne/detector.js.map +1 -0
- package/dist/hooks/mnemosyne/finder.d.ts +21 -0
- package/dist/hooks/mnemosyne/finder.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/finder.js +117 -0
- package/dist/hooks/mnemosyne/finder.js.map +1 -0
- package/dist/hooks/mnemosyne/index.d.ts +62 -0
- package/dist/hooks/mnemosyne/index.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/index.js +137 -0
- package/dist/hooks/mnemosyne/index.js.map +1 -0
- package/dist/hooks/mnemosyne/loader.d.ts +20 -0
- package/dist/hooks/mnemosyne/loader.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/loader.js +113 -0
- package/dist/hooks/mnemosyne/loader.js.map +1 -0
- package/dist/hooks/mnemosyne/parser.d.ts +21 -0
- package/dist/hooks/mnemosyne/parser.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/parser.js +190 -0
- package/dist/hooks/mnemosyne/parser.js.map +1 -0
- package/dist/hooks/mnemosyne/promotion.d.ts +29 -0
- package/dist/hooks/mnemosyne/promotion.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/promotion.js +87 -0
- package/dist/hooks/mnemosyne/promotion.js.map +1 -0
- package/dist/hooks/mnemosyne/types.d.ts +109 -0
- package/dist/hooks/mnemosyne/types.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/types.js +8 -0
- package/dist/hooks/mnemosyne/types.js.map +1 -0
- package/dist/hooks/mnemosyne/validator.d.ts +15 -0
- package/dist/hooks/mnemosyne/validator.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/validator.js +87 -0
- package/dist/hooks/mnemosyne/validator.js.map +1 -0
- package/dist/hooks/mnemosyne/writer.d.ts +27 -0
- package/dist/hooks/mnemosyne/writer.d.ts.map +1 -0
- package/dist/hooks/mnemosyne/writer.js +126 -0
- package/dist/hooks/mnemosyne/writer.js.map +1 -0
- package/dist/hooks/ralph-loop/index.d.ts +116 -0
- package/dist/hooks/ralph-loop/index.d.ts.map +1 -0
- package/dist/hooks/ralph-loop/index.js +322 -0
- package/dist/hooks/ralph-loop/index.js.map +1 -0
- package/dist/hooks/ralph-prd/index.d.ts +130 -0
- package/dist/hooks/ralph-prd/index.d.ts.map +1 -0
- package/dist/hooks/ralph-prd/index.js +310 -0
- package/dist/hooks/ralph-prd/index.js.map +1 -0
- package/dist/hooks/ralph-progress/index.d.ts +102 -0
- package/dist/hooks/ralph-progress/index.d.ts.map +1 -0
- package/dist/hooks/ralph-progress/index.js +408 -0
- package/dist/hooks/ralph-progress/index.js.map +1 -0
- package/dist/hooks/ralph-verifier/index.d.ts +72 -0
- package/dist/hooks/ralph-verifier/index.d.ts.map +1 -0
- package/dist/hooks/ralph-verifier/index.js +223 -0
- package/dist/hooks/ralph-verifier/index.js.map +1 -0
- package/dist/hooks/session-recovery/constants.d.ts +56 -0
- package/dist/hooks/session-recovery/constants.d.ts.map +1 -0
- package/dist/hooks/session-recovery/constants.js +78 -0
- package/dist/hooks/session-recovery/constants.js.map +1 -0
- package/dist/hooks/session-recovery/index.d.ts +53 -0
- package/dist/hooks/session-recovery/index.d.ts.map +1 -0
- package/dist/hooks/session-recovery/index.js +321 -0
- package/dist/hooks/session-recovery/index.js.map +1 -0
- package/dist/hooks/session-recovery/storage.d.ts +76 -0
- package/dist/hooks/session-recovery/storage.d.ts.map +1 -0
- package/dist/hooks/session-recovery/storage.js +383 -0
- package/dist/hooks/session-recovery/storage.js.map +1 -0
- package/dist/hooks/session-recovery/types.d.ts +145 -0
- package/dist/hooks/session-recovery/types.d.ts.map +1 -0
- package/dist/hooks/session-recovery/types.js +8 -0
- package/dist/hooks/session-recovery/types.js.map +1 -0
- package/dist/hooks/sisyphus-orchestrator/constants.d.ts +23 -0
- package/dist/hooks/sisyphus-orchestrator/constants.d.ts.map +1 -0
- package/dist/hooks/sisyphus-orchestrator/constants.js +142 -0
- package/dist/hooks/sisyphus-orchestrator/constants.js.map +1 -0
- package/dist/hooks/sisyphus-orchestrator/index.d.ts +113 -0
- package/dist/hooks/sisyphus-orchestrator/index.d.ts.map +1 -0
- package/dist/hooks/sisyphus-orchestrator/index.js +309 -0
- package/dist/hooks/sisyphus-orchestrator/index.js.map +1 -0
- package/dist/hooks/subagent-tracker/index.d.ts +83 -0
- package/dist/hooks/subagent-tracker/index.d.ts.map +1 -0
- package/dist/hooks/subagent-tracker/index.js +207 -0
- package/dist/hooks/subagent-tracker/index.js.map +1 -0
- package/dist/hooks/ultraqa-loop/index.d.ts +94 -0
- package/dist/hooks/ultraqa-loop/index.d.ts.map +1 -0
- package/dist/hooks/ultraqa-loop/index.js +216 -0
- package/dist/hooks/ultraqa-loop/index.js.map +1 -0
- package/dist/hooks/ultrawork-state/index.d.ts +62 -0
- package/dist/hooks/ultrawork-state/index.d.ts.map +1 -0
- package/dist/hooks/ultrawork-state/index.js +208 -0
- package/dist/hooks/ultrawork-state/index.js.map +1 -0
- package/dist/hud/sisyphus-state.d.ts +31 -0
- package/dist/hud/sisyphus-state.d.ts.map +1 -0
- package/dist/hud/sisyphus-state.js +163 -0
- package/dist/hud/sisyphus-state.js.map +1 -0
- package/dist/installer/index.d.ts +1 -1
- package/dist/installer/index.js +1 -1
- package/docs/MIGRATION.md +2 -2
- package/docs/design/project-session-manager.md +1033 -0
- package/package.json +1 -1
- package/skills/doctor/SKILL.md +1 -1
- package/skills/project-session-manager/SKILL.md +410 -0
- package/skills/project-session-manager/lib/config.sh +86 -0
- package/skills/project-session-manager/lib/parse.sh +121 -0
- package/skills/project-session-manager/lib/session.sh +132 -0
- package/skills/project-session-manager/lib/tmux.sh +103 -0
- package/skills/project-session-manager/lib/worktree.sh +171 -0
- package/skills/project-session-manager/psm.sh +629 -0
- package/skills/project-session-manager/templates/feature.md +56 -0
- package/skills/project-session-manager/templates/issue-fix.md +57 -0
- package/skills/project-session-manager/templates/pr-review.md +65 -0
- package/skills/project-session-manager/templates/projects.json +19 -0
|
@@ -0,0 +1,629 @@
|
|
|
1
|
+
#!/bin/bash
|
|
2
|
+
# Project Session Manager (PSM) - Main Script
|
|
3
|
+
# Usage: psm.sh <command> [args...]
|
|
4
|
+
|
|
5
|
+
set -euo pipefail
|
|
6
|
+
|
|
7
|
+
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
8
|
+
|
|
9
|
+
# Source library files
|
|
10
|
+
source "$SCRIPT_DIR/lib/config.sh"
|
|
11
|
+
source "$SCRIPT_DIR/lib/parse.sh"
|
|
12
|
+
source "$SCRIPT_DIR/lib/worktree.sh"
|
|
13
|
+
source "$SCRIPT_DIR/lib/tmux.sh"
|
|
14
|
+
source "$SCRIPT_DIR/lib/session.sh"
|
|
15
|
+
|
|
16
|
+
# Colors for output
|
|
17
|
+
RED='\033[0;31m'
|
|
18
|
+
GREEN='\033[0;32m'
|
|
19
|
+
YELLOW='\033[1;33m'
|
|
20
|
+
BLUE='\033[0;34m'
|
|
21
|
+
NC='\033[0m' # No Color
|
|
22
|
+
|
|
23
|
+
# Logging
|
|
24
|
+
log_info() { echo -e "${BLUE}[PSM]${NC} $*"; }
|
|
25
|
+
log_success() { echo -e "${GREEN}[PSM]${NC} $*"; }
|
|
26
|
+
log_warn() { echo -e "${YELLOW}[PSM]${NC} $*"; }
|
|
27
|
+
log_error() { echo -e "${RED}[PSM]${NC} $*" >&2; }
|
|
28
|
+
|
|
29
|
+
# Check dependencies
|
|
30
|
+
check_dependencies() {
|
|
31
|
+
local missing=()
|
|
32
|
+
|
|
33
|
+
if ! command -v git &> /dev/null; then
|
|
34
|
+
missing+=("git")
|
|
35
|
+
fi
|
|
36
|
+
|
|
37
|
+
if ! command -v jq &> /dev/null; then
|
|
38
|
+
missing+=("jq")
|
|
39
|
+
fi
|
|
40
|
+
|
|
41
|
+
if ! command -v gh &> /dev/null; then
|
|
42
|
+
missing+=("gh (GitHub CLI)")
|
|
43
|
+
fi
|
|
44
|
+
|
|
45
|
+
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
46
|
+
log_error "Missing required dependencies: ${missing[*]}"
|
|
47
|
+
log_info "Install with:"
|
|
48
|
+
log_info " Ubuntu/Debian: sudo apt install git jq gh"
|
|
49
|
+
log_info " macOS: brew install git jq gh"
|
|
50
|
+
exit 1
|
|
51
|
+
fi
|
|
52
|
+
|
|
53
|
+
# tmux is optional but warn if missing
|
|
54
|
+
if ! command -v tmux &> /dev/null; then
|
|
55
|
+
log_warn "tmux not found. Sessions will be created without tmux."
|
|
56
|
+
fi
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
# Print usage
|
|
60
|
+
usage() {
|
|
61
|
+
cat << 'EOF'
|
|
62
|
+
Project Session Manager (PSM) - Isolated dev environments
|
|
63
|
+
|
|
64
|
+
Usage: psm <command> [args...]
|
|
65
|
+
|
|
66
|
+
Commands:
|
|
67
|
+
review <ref> Create PR review session
|
|
68
|
+
fix <ref> Create issue fix session
|
|
69
|
+
feature <proj> <name> Create feature development session
|
|
70
|
+
list [project] List active sessions
|
|
71
|
+
attach <session> Attach to existing session
|
|
72
|
+
kill <session> Kill and cleanup session
|
|
73
|
+
cleanup [--force] Clean merged PRs and closed issues
|
|
74
|
+
status Show current session info
|
|
75
|
+
|
|
76
|
+
Reference formats:
|
|
77
|
+
omc#123 Project alias + number
|
|
78
|
+
owner/repo#123 Full GitHub reference
|
|
79
|
+
https://... GitHub URL
|
|
80
|
+
#123 Number only (uses current repo)
|
|
81
|
+
|
|
82
|
+
Examples:
|
|
83
|
+
psm review omc#123
|
|
84
|
+
psm fix Yeachan-Heo/oh-my-claudecode#42
|
|
85
|
+
psm feature omc add-webhooks
|
|
86
|
+
psm list
|
|
87
|
+
psm attach omc:pr-123
|
|
88
|
+
psm kill omc:pr-123
|
|
89
|
+
psm cleanup
|
|
90
|
+
EOF
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
# Command: review
|
|
94
|
+
cmd_review() {
|
|
95
|
+
local ref="$1"
|
|
96
|
+
local no_claude="${2:-false}"
|
|
97
|
+
local no_tmux="${3:-false}"
|
|
98
|
+
|
|
99
|
+
log_info "Parsing reference: $ref"
|
|
100
|
+
|
|
101
|
+
# Parse reference
|
|
102
|
+
local parsed
|
|
103
|
+
parsed=$(psm_parse_ref "$ref")
|
|
104
|
+
if [[ $? -ne 0 ]] || [[ "$parsed" == error* ]]; then
|
|
105
|
+
log_error "Failed to parse reference: $ref"
|
|
106
|
+
return 1
|
|
107
|
+
fi
|
|
108
|
+
|
|
109
|
+
IFS='|' read -r type alias repo pr_number local_path base <<< "$parsed"
|
|
110
|
+
|
|
111
|
+
if [[ -z "$repo" ]]; then
|
|
112
|
+
log_error "Could not determine repository"
|
|
113
|
+
return 1
|
|
114
|
+
fi
|
|
115
|
+
|
|
116
|
+
log_info "Fetching PR #${pr_number} from ${repo}..."
|
|
117
|
+
|
|
118
|
+
# Fetch PR info
|
|
119
|
+
local pr_info
|
|
120
|
+
pr_info=$(gh pr view "$pr_number" --repo "$repo" --json number,title,author,headRefName,baseRefName,body,url 2>/dev/null) || {
|
|
121
|
+
log_error "Failed to fetch PR #${pr_number}. Check if the PR exists and you have access."
|
|
122
|
+
return 1
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
local pr_title=$(echo "$pr_info" | jq -r '.title')
|
|
126
|
+
local pr_author=$(echo "$pr_info" | jq -r '.author.login')
|
|
127
|
+
local head_branch=$(echo "$pr_info" | jq -r '.headRefName')
|
|
128
|
+
local base_branch=$(echo "$pr_info" | jq -r '.baseRefName')
|
|
129
|
+
local pr_url=$(echo "$pr_info" | jq -r '.url')
|
|
130
|
+
|
|
131
|
+
log_info "PR: #${pr_number} - ${pr_title}"
|
|
132
|
+
log_info "Author: @${pr_author}"
|
|
133
|
+
log_info "Branch: ${head_branch} -> ${base_branch}"
|
|
134
|
+
|
|
135
|
+
# Determine alias if not set
|
|
136
|
+
if [[ -z "$alias" ]]; then
|
|
137
|
+
alias=$(echo "$repo" | tr '/' '-')
|
|
138
|
+
fi
|
|
139
|
+
|
|
140
|
+
# Determine local path
|
|
141
|
+
if [[ -z "$local_path" || ! -d "$local_path" ]]; then
|
|
142
|
+
# Clone if needed
|
|
143
|
+
local_path="${HOME}/Workspace/$(basename "$repo")"
|
|
144
|
+
if [[ ! -d "$local_path" ]]; then
|
|
145
|
+
log_info "Cloning repository to $local_path..."
|
|
146
|
+
git clone "https://github.com/${repo}.git" "$local_path" || {
|
|
147
|
+
log_error "Failed to clone repository"
|
|
148
|
+
return 1
|
|
149
|
+
}
|
|
150
|
+
fi
|
|
151
|
+
fi
|
|
152
|
+
|
|
153
|
+
# Create worktree
|
|
154
|
+
log_info "Creating worktree..."
|
|
155
|
+
local worktree_result
|
|
156
|
+
worktree_result=$(psm_create_pr_worktree "$local_path" "$alias" "$pr_number" "$head_branch")
|
|
157
|
+
|
|
158
|
+
local worktree_status
|
|
159
|
+
local worktree_path
|
|
160
|
+
IFS='|' read -r worktree_status worktree_path <<< "$worktree_result"
|
|
161
|
+
|
|
162
|
+
if [[ "$worktree_status" == "exists" ]]; then
|
|
163
|
+
log_warn "Worktree already exists at $worktree_path"
|
|
164
|
+
log_info "Use 'psm attach ${alias}:pr-${pr_number}' to attach"
|
|
165
|
+
return 0
|
|
166
|
+
elif [[ "$worktree_status" == "error" ]]; then
|
|
167
|
+
log_error "Failed to create worktree: $worktree_path"
|
|
168
|
+
return 1
|
|
169
|
+
fi
|
|
170
|
+
|
|
171
|
+
log_success "Worktree created at $worktree_path"
|
|
172
|
+
|
|
173
|
+
# Create tmux session
|
|
174
|
+
local session_name="psm:${alias}:pr-${pr_number}"
|
|
175
|
+
local session_id="${alias}:pr-${pr_number}"
|
|
176
|
+
|
|
177
|
+
if [[ "$no_tmux" != "true" ]]; then
|
|
178
|
+
log_info "Creating tmux session..."
|
|
179
|
+
local tmux_result
|
|
180
|
+
tmux_result=$(psm_create_tmux_session "$session_name" "$worktree_path")
|
|
181
|
+
|
|
182
|
+
local tmux_status
|
|
183
|
+
IFS='|' read -r tmux_status _ <<< "$tmux_result"
|
|
184
|
+
|
|
185
|
+
if [[ "$tmux_status" == "error" ]]; then
|
|
186
|
+
log_warn "Could not create tmux session. Continuing without tmux."
|
|
187
|
+
elif [[ "$tmux_status" == "exists" ]]; then
|
|
188
|
+
log_warn "Tmux session already exists"
|
|
189
|
+
else
|
|
190
|
+
log_success "Tmux session created: $session_name"
|
|
191
|
+
|
|
192
|
+
# Launch Claude Code
|
|
193
|
+
if [[ "$no_claude" != "true" ]]; then
|
|
194
|
+
log_info "Launching Claude Code..."
|
|
195
|
+
psm_launch_claude "$session_name"
|
|
196
|
+
fi
|
|
197
|
+
fi
|
|
198
|
+
fi
|
|
199
|
+
|
|
200
|
+
# Create session metadata
|
|
201
|
+
local metadata=$(cat << EOF
|
|
202
|
+
{
|
|
203
|
+
"pr_number": $pr_number,
|
|
204
|
+
"pr_title": $(echo "$pr_title" | jq -R .),
|
|
205
|
+
"pr_author": "$pr_author",
|
|
206
|
+
"pr_url": "$pr_url"
|
|
207
|
+
}
|
|
208
|
+
EOF
|
|
209
|
+
)
|
|
210
|
+
|
|
211
|
+
# Add to registry
|
|
212
|
+
psm_add_session "$session_id" "review" "$alias" "pr-${pr_number}" "$head_branch" "$base_branch" "$session_name" "$worktree_path" "$local_path" "$metadata"
|
|
213
|
+
|
|
214
|
+
# Output summary
|
|
215
|
+
echo ""
|
|
216
|
+
log_success "Session ready!"
|
|
217
|
+
echo ""
|
|
218
|
+
echo " ID: $session_id"
|
|
219
|
+
echo " Type: review"
|
|
220
|
+
echo " PR: #${pr_number} - ${pr_title}"
|
|
221
|
+
echo " Worktree: $worktree_path"
|
|
222
|
+
echo " Tmux: $session_name"
|
|
223
|
+
echo ""
|
|
224
|
+
echo "Commands:"
|
|
225
|
+
echo " Attach: tmux attach -t $session_name"
|
|
226
|
+
echo " Kill: psm kill $session_id"
|
|
227
|
+
echo " Cleanup: psm cleanup"
|
|
228
|
+
echo ""
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
# Command: fix
|
|
232
|
+
cmd_fix() {
|
|
233
|
+
local ref="$1"
|
|
234
|
+
local no_claude="${2:-false}"
|
|
235
|
+
|
|
236
|
+
log_info "Parsing reference: $ref"
|
|
237
|
+
|
|
238
|
+
local parsed
|
|
239
|
+
parsed=$(psm_parse_ref "$ref")
|
|
240
|
+
if [[ $? -ne 0 ]] || [[ "$parsed" == error* ]]; then
|
|
241
|
+
log_error "Failed to parse reference: $ref"
|
|
242
|
+
return 1
|
|
243
|
+
fi
|
|
244
|
+
|
|
245
|
+
IFS='|' read -r type alias repo issue_number local_path base <<< "$parsed"
|
|
246
|
+
|
|
247
|
+
if [[ -z "$repo" ]]; then
|
|
248
|
+
log_error "Could not determine repository"
|
|
249
|
+
return 1
|
|
250
|
+
fi
|
|
251
|
+
|
|
252
|
+
log_info "Fetching issue #${issue_number} from ${repo}..."
|
|
253
|
+
|
|
254
|
+
# Fetch issue info
|
|
255
|
+
local issue_info
|
|
256
|
+
issue_info=$(gh issue view "$issue_number" --repo "$repo" --json number,title,body,labels,url 2>/dev/null) || {
|
|
257
|
+
log_error "Failed to fetch issue #${issue_number}"
|
|
258
|
+
return 1
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
local issue_title=$(echo "$issue_info" | jq -r '.title')
|
|
262
|
+
local issue_url=$(echo "$issue_info" | jq -r '.url')
|
|
263
|
+
local slug=$(psm_slugify "$issue_title" 20)
|
|
264
|
+
|
|
265
|
+
log_info "Issue: #${issue_number} - ${issue_title}"
|
|
266
|
+
|
|
267
|
+
# Determine alias
|
|
268
|
+
if [[ -z "$alias" ]]; then
|
|
269
|
+
alias=$(echo "$repo" | tr '/' '-')
|
|
270
|
+
fi
|
|
271
|
+
|
|
272
|
+
# Determine local path
|
|
273
|
+
if [[ -z "$local_path" || ! -d "$local_path" ]]; then
|
|
274
|
+
local_path="${HOME}/Workspace/$(basename "$repo")"
|
|
275
|
+
if [[ ! -d "$local_path" ]]; then
|
|
276
|
+
log_info "Cloning repository..."
|
|
277
|
+
git clone "https://github.com/${repo}.git" "$local_path" || return 1
|
|
278
|
+
fi
|
|
279
|
+
fi
|
|
280
|
+
|
|
281
|
+
# Create worktree
|
|
282
|
+
log_info "Creating worktree and branch..."
|
|
283
|
+
local worktree_result
|
|
284
|
+
worktree_result=$(psm_create_issue_worktree "$local_path" "$alias" "$issue_number" "$slug" "$base")
|
|
285
|
+
|
|
286
|
+
local worktree_status worktree_path branch_name
|
|
287
|
+
IFS='|' read -r worktree_status worktree_path branch_name <<< "$worktree_result"
|
|
288
|
+
|
|
289
|
+
if [[ "$worktree_status" == "exists" ]]; then
|
|
290
|
+
log_warn "Worktree already exists at $worktree_path"
|
|
291
|
+
return 0
|
|
292
|
+
elif [[ "$worktree_status" == "error" ]]; then
|
|
293
|
+
log_error "Failed to create worktree: $worktree_path"
|
|
294
|
+
return 1
|
|
295
|
+
fi
|
|
296
|
+
|
|
297
|
+
log_success "Worktree created at $worktree_path"
|
|
298
|
+
log_info "Branch: $branch_name"
|
|
299
|
+
|
|
300
|
+
# Create tmux session
|
|
301
|
+
local session_name="psm:${alias}:issue-${issue_number}"
|
|
302
|
+
local session_id="${alias}:issue-${issue_number}"
|
|
303
|
+
|
|
304
|
+
log_info "Creating tmux session..."
|
|
305
|
+
psm_create_tmux_session "$session_name" "$worktree_path"
|
|
306
|
+
|
|
307
|
+
if [[ "$no_claude" != "true" ]]; then
|
|
308
|
+
psm_launch_claude "$session_name"
|
|
309
|
+
fi
|
|
310
|
+
|
|
311
|
+
# Create metadata
|
|
312
|
+
local metadata=$(cat << EOF
|
|
313
|
+
{
|
|
314
|
+
"issue_number": $issue_number,
|
|
315
|
+
"issue_title": $(echo "$issue_title" | jq -R .),
|
|
316
|
+
"issue_url": "$issue_url"
|
|
317
|
+
}
|
|
318
|
+
EOF
|
|
319
|
+
)
|
|
320
|
+
|
|
321
|
+
psm_add_session "$session_id" "fix" "$alias" "issue-${issue_number}" "$branch_name" "$base" "$session_name" "$worktree_path" "$local_path" "$metadata"
|
|
322
|
+
|
|
323
|
+
echo ""
|
|
324
|
+
log_success "Session ready!"
|
|
325
|
+
echo ""
|
|
326
|
+
echo " ID: $session_id"
|
|
327
|
+
echo " Type: fix"
|
|
328
|
+
echo " Issue: #${issue_number} - ${issue_title}"
|
|
329
|
+
echo " Branch: $branch_name"
|
|
330
|
+
echo " Worktree: $worktree_path"
|
|
331
|
+
echo " Tmux: $session_name"
|
|
332
|
+
echo ""
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
# Command: feature
|
|
336
|
+
cmd_feature() {
|
|
337
|
+
local project="$1"
|
|
338
|
+
local feature_name="$2"
|
|
339
|
+
|
|
340
|
+
log_info "Creating feature session for: $feature_name"
|
|
341
|
+
|
|
342
|
+
# Resolve project
|
|
343
|
+
local project_info
|
|
344
|
+
project_info=$(psm_get_project "$project")
|
|
345
|
+
if [[ $? -ne 0 ]]; then
|
|
346
|
+
log_error "Unknown project: $project"
|
|
347
|
+
return 1
|
|
348
|
+
fi
|
|
349
|
+
|
|
350
|
+
IFS='|' read -r repo local_path base <<< "$project_info"
|
|
351
|
+
|
|
352
|
+
if [[ ! -d "$local_path" ]]; then
|
|
353
|
+
log_error "Local path not found: $local_path"
|
|
354
|
+
return 1
|
|
355
|
+
fi
|
|
356
|
+
|
|
357
|
+
# Create worktree
|
|
358
|
+
log_info "Creating worktree and branch..."
|
|
359
|
+
local worktree_result
|
|
360
|
+
worktree_result=$(psm_create_feature_worktree "$local_path" "$project" "$feature_name" "$base")
|
|
361
|
+
|
|
362
|
+
local worktree_status worktree_path branch_name
|
|
363
|
+
IFS='|' read -r worktree_status worktree_path branch_name <<< "$worktree_result"
|
|
364
|
+
|
|
365
|
+
if [[ "$worktree_status" == "exists" ]]; then
|
|
366
|
+
log_warn "Worktree already exists at $worktree_path"
|
|
367
|
+
return 0
|
|
368
|
+
elif [[ "$worktree_status" == "error" ]]; then
|
|
369
|
+
log_error "Failed to create worktree"
|
|
370
|
+
return 1
|
|
371
|
+
fi
|
|
372
|
+
|
|
373
|
+
log_success "Worktree created at $worktree_path"
|
|
374
|
+
|
|
375
|
+
local safe_name=$(psm_sanitize "$feature_name")
|
|
376
|
+
local session_name="psm:${project}:feat-${safe_name}"
|
|
377
|
+
local session_id="${project}:feat-${safe_name}"
|
|
378
|
+
|
|
379
|
+
psm_create_tmux_session "$session_name" "$worktree_path"
|
|
380
|
+
psm_launch_claude "$session_name"
|
|
381
|
+
|
|
382
|
+
psm_add_session "$session_id" "feature" "$project" "feat-${safe_name}" "$branch_name" "$base" "$session_name" "$worktree_path" "$local_path" "{}"
|
|
383
|
+
|
|
384
|
+
echo ""
|
|
385
|
+
log_success "Session ready!"
|
|
386
|
+
echo ""
|
|
387
|
+
echo " ID: $session_id"
|
|
388
|
+
echo " Type: feature"
|
|
389
|
+
echo " Branch: $branch_name"
|
|
390
|
+
echo " Worktree: $worktree_path"
|
|
391
|
+
echo " Tmux: $session_name"
|
|
392
|
+
echo ""
|
|
393
|
+
}
|
|
394
|
+
|
|
395
|
+
# Command: list
|
|
396
|
+
cmd_list() {
|
|
397
|
+
local project="${1:-}"
|
|
398
|
+
|
|
399
|
+
echo ""
|
|
400
|
+
echo "Active PSM Sessions:"
|
|
401
|
+
echo ""
|
|
402
|
+
printf "%-25s | %-8s | %-10s | %s\n" "ID" "Type" "State" "Worktree"
|
|
403
|
+
printf "%-25s-+-%-8s-+-%-10s-+-%s\n" "-------------------------" "--------" "----------" "----------------------------------------"
|
|
404
|
+
|
|
405
|
+
psm_list_sessions "$project" | while IFS='|' read -r id type state worktree; do
|
|
406
|
+
# Check if tmux session exists
|
|
407
|
+
local tmux_state="detached"
|
|
408
|
+
if psm_tmux_session_exists "psm:${id}"; then
|
|
409
|
+
tmux_state="$state"
|
|
410
|
+
else
|
|
411
|
+
tmux_state="no-tmux"
|
|
412
|
+
fi
|
|
413
|
+
|
|
414
|
+
printf "%-25s | %-8s | %-10s | %s\n" "$id" "$type" "$tmux_state" "$worktree"
|
|
415
|
+
done
|
|
416
|
+
|
|
417
|
+
echo ""
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
# Command: attach
|
|
421
|
+
cmd_attach() {
|
|
422
|
+
local session_id="$1"
|
|
423
|
+
local session_name="psm:${session_id}"
|
|
424
|
+
|
|
425
|
+
if ! psm_tmux_session_exists "$session_name"; then
|
|
426
|
+
log_error "Session not found: $session_name"
|
|
427
|
+
log_info "Use 'psm list' to see available sessions"
|
|
428
|
+
return 1
|
|
429
|
+
fi
|
|
430
|
+
|
|
431
|
+
echo "Attaching to $session_name..."
|
|
432
|
+
echo "Run: tmux attach -t $session_name"
|
|
433
|
+
}
|
|
434
|
+
|
|
435
|
+
# Command: kill
|
|
436
|
+
cmd_kill() {
|
|
437
|
+
local session_id="$1"
|
|
438
|
+
|
|
439
|
+
log_info "Killing session: $session_id"
|
|
440
|
+
|
|
441
|
+
# Get session info
|
|
442
|
+
local session_json
|
|
443
|
+
session_json=$(psm_get_session "$session_id")
|
|
444
|
+
if [[ -z "$session_json" ]]; then
|
|
445
|
+
log_error "Session not found in registry: $session_id"
|
|
446
|
+
return 1
|
|
447
|
+
fi
|
|
448
|
+
|
|
449
|
+
local tmux_name=$(echo "$session_json" | jq -r '.tmux')
|
|
450
|
+
local worktree_path=$(echo "$session_json" | jq -r '.worktree')
|
|
451
|
+
local source_repo=$(echo "$session_json" | jq -r '.source_repo')
|
|
452
|
+
|
|
453
|
+
# Kill tmux
|
|
454
|
+
psm_kill_tmux_session "$tmux_name"
|
|
455
|
+
log_info "Killed tmux session: $tmux_name"
|
|
456
|
+
|
|
457
|
+
# Remove worktree
|
|
458
|
+
psm_remove_worktree "$source_repo" "$worktree_path"
|
|
459
|
+
log_info "Removed worktree: $worktree_path"
|
|
460
|
+
|
|
461
|
+
# Remove from registry
|
|
462
|
+
psm_remove_session "$session_id"
|
|
463
|
+
log_info "Removed from registry"
|
|
464
|
+
|
|
465
|
+
log_success "Session killed: $session_id"
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
# Command: cleanup
|
|
469
|
+
cmd_cleanup() {
|
|
470
|
+
local force="${1:-false}"
|
|
471
|
+
|
|
472
|
+
log_info "Starting cleanup..."
|
|
473
|
+
|
|
474
|
+
local cleaned=0
|
|
475
|
+
|
|
476
|
+
# Check PR sessions (use process substitution to avoid subshell)
|
|
477
|
+
while IFS='|' read -r id pr_number project; do
|
|
478
|
+
if [[ -z "$id" ]]; then continue; fi
|
|
479
|
+
|
|
480
|
+
local repo=$(psm_get_project "$project" | cut -d'|' -f1)
|
|
481
|
+
|
|
482
|
+
if [[ -n "$repo" && -n "$pr_number" ]]; then
|
|
483
|
+
local pr_state=$(gh pr view "$pr_number" --repo "$repo" --json merged 2>/dev/null | jq -r '.merged')
|
|
484
|
+
if [[ "$pr_state" == "true" ]]; then
|
|
485
|
+
log_info "PR #${pr_number} is merged - cleaning up $id"
|
|
486
|
+
cmd_kill "$id"
|
|
487
|
+
((cleaned++))
|
|
488
|
+
fi
|
|
489
|
+
fi
|
|
490
|
+
done < <(psm_get_review_sessions)
|
|
491
|
+
|
|
492
|
+
# Check issue sessions (use process substitution to avoid subshell)
|
|
493
|
+
while IFS='|' read -r id issue_number project; do
|
|
494
|
+
if [[ -z "$id" ]]; then continue; fi
|
|
495
|
+
|
|
496
|
+
local repo=$(psm_get_project "$project" | cut -d'|' -f1)
|
|
497
|
+
|
|
498
|
+
if [[ -n "$repo" && -n "$issue_number" ]]; then
|
|
499
|
+
local issue_state=$(gh issue view "$issue_number" --repo "$repo" --json closed 2>/dev/null | jq -r '.closed')
|
|
500
|
+
if [[ "$issue_state" == "true" ]]; then
|
|
501
|
+
log_info "Issue #${issue_number} is closed - cleaning up $id"
|
|
502
|
+
cmd_kill "$id"
|
|
503
|
+
((cleaned++))
|
|
504
|
+
fi
|
|
505
|
+
fi
|
|
506
|
+
done < <(psm_get_fix_sessions)
|
|
507
|
+
|
|
508
|
+
if [[ $cleaned -eq 0 ]]; then
|
|
509
|
+
log_success "Cleanup complete - no sessions to clean"
|
|
510
|
+
else
|
|
511
|
+
log_success "Cleanup complete - removed $cleaned session(s)"
|
|
512
|
+
fi
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
# Command: status
|
|
516
|
+
cmd_status() {
|
|
517
|
+
# Try to detect current session
|
|
518
|
+
local current_session=$(psm_current_tmux_session)
|
|
519
|
+
|
|
520
|
+
if [[ -n "$current_session" && "$current_session" == psm:* ]]; then
|
|
521
|
+
local session_id="${current_session#psm:}"
|
|
522
|
+
local session_json=$(psm_get_session "$session_id")
|
|
523
|
+
|
|
524
|
+
if [[ -n "$session_json" ]]; then
|
|
525
|
+
echo ""
|
|
526
|
+
echo "Current Session: $session_id"
|
|
527
|
+
echo ""
|
|
528
|
+
echo " Type: $(echo "$session_json" | jq -r '.type')"
|
|
529
|
+
echo " Branch: $(echo "$session_json" | jq -r '.branch')"
|
|
530
|
+
echo " Base: $(echo "$session_json" | jq -r '.base')"
|
|
531
|
+
echo " Worktree: $(echo "$session_json" | jq -r '.worktree')"
|
|
532
|
+
echo " Created: $(echo "$session_json" | jq -r '.created_at')"
|
|
533
|
+
echo ""
|
|
534
|
+
return 0
|
|
535
|
+
fi
|
|
536
|
+
fi
|
|
537
|
+
|
|
538
|
+
# Check if we're in a worktree
|
|
539
|
+
local cwd=$(pwd)
|
|
540
|
+
local worktree_root=$(psm_get_worktree_root)
|
|
541
|
+
|
|
542
|
+
if [[ "$cwd" == "$worktree_root"* ]]; then
|
|
543
|
+
local meta_file="${cwd}/.psm-session.json"
|
|
544
|
+
if [[ -f "$meta_file" ]]; then
|
|
545
|
+
cat "$meta_file" | jq .
|
|
546
|
+
return 0
|
|
547
|
+
fi
|
|
548
|
+
fi
|
|
549
|
+
|
|
550
|
+
log_info "Not in a PSM session"
|
|
551
|
+
log_info "Use 'psm list' to see available sessions"
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
# Main entry point
|
|
555
|
+
main() {
|
|
556
|
+
if [[ $# -eq 0 ]]; then
|
|
557
|
+
usage
|
|
558
|
+
exit 0
|
|
559
|
+
fi
|
|
560
|
+
|
|
561
|
+
# Check dependencies first
|
|
562
|
+
check_dependencies
|
|
563
|
+
|
|
564
|
+
# Initialize PSM
|
|
565
|
+
psm_init
|
|
566
|
+
|
|
567
|
+
local cmd="$1"
|
|
568
|
+
shift
|
|
569
|
+
|
|
570
|
+
case "$cmd" in
|
|
571
|
+
review|r|pr)
|
|
572
|
+
if [[ $# -lt 1 ]]; then
|
|
573
|
+
log_error "Usage: psm review <ref>"
|
|
574
|
+
exit 1
|
|
575
|
+
fi
|
|
576
|
+
cmd_review "$@"
|
|
577
|
+
;;
|
|
578
|
+
fix|issue|i)
|
|
579
|
+
if [[ $# -lt 1 ]]; then
|
|
580
|
+
log_error "Usage: psm fix <ref>"
|
|
581
|
+
exit 1
|
|
582
|
+
fi
|
|
583
|
+
cmd_fix "$@"
|
|
584
|
+
;;
|
|
585
|
+
feature|feat|f)
|
|
586
|
+
if [[ $# -lt 2 ]]; then
|
|
587
|
+
log_error "Usage: psm feature <project> <name>"
|
|
588
|
+
exit 1
|
|
589
|
+
fi
|
|
590
|
+
cmd_feature "$@"
|
|
591
|
+
;;
|
|
592
|
+
list|ls|l)
|
|
593
|
+
cmd_list "$@"
|
|
594
|
+
;;
|
|
595
|
+
attach|a)
|
|
596
|
+
if [[ $# -lt 1 ]]; then
|
|
597
|
+
log_error "Usage: psm attach <session>"
|
|
598
|
+
exit 1
|
|
599
|
+
fi
|
|
600
|
+
cmd_attach "$@"
|
|
601
|
+
;;
|
|
602
|
+
kill|k|rm)
|
|
603
|
+
if [[ $# -lt 1 ]]; then
|
|
604
|
+
log_error "Usage: psm kill <session>"
|
|
605
|
+
exit 1
|
|
606
|
+
fi
|
|
607
|
+
cmd_kill "$@"
|
|
608
|
+
;;
|
|
609
|
+
cleanup|gc|clean)
|
|
610
|
+
cmd_cleanup "$@"
|
|
611
|
+
;;
|
|
612
|
+
status|st)
|
|
613
|
+
cmd_status
|
|
614
|
+
;;
|
|
615
|
+
help|-h|--help)
|
|
616
|
+
usage
|
|
617
|
+
;;
|
|
618
|
+
*)
|
|
619
|
+
log_error "Unknown command: $cmd"
|
|
620
|
+
usage
|
|
621
|
+
exit 1
|
|
622
|
+
;;
|
|
623
|
+
esac
|
|
624
|
+
}
|
|
625
|
+
|
|
626
|
+
# Run if executed directly
|
|
627
|
+
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
628
|
+
main "$@"
|
|
629
|
+
fi
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Feature Development Context
|
|
2
|
+
|
|
3
|
+
You are developing feature: **{{FEATURE_NAME}}**
|
|
4
|
+
|
|
5
|
+
## Details
|
|
6
|
+
|
|
7
|
+
- **Branch**: `{{BRANCH_NAME}}`
|
|
8
|
+
- **Base**: `{{BASE_BRANCH}}`
|
|
9
|
+
- **Project**: {{PROJECT}}
|
|
10
|
+
|
|
11
|
+
## Feature Scope
|
|
12
|
+
|
|
13
|
+
{{FEATURE_DESCRIPTION}}
|
|
14
|
+
|
|
15
|
+
## Development Approach
|
|
16
|
+
|
|
17
|
+
1. **Plan**
|
|
18
|
+
- Define requirements
|
|
19
|
+
- Break into subtasks
|
|
20
|
+
- Identify dependencies
|
|
21
|
+
|
|
22
|
+
2. **Implement**
|
|
23
|
+
- Follow project patterns
|
|
24
|
+
- Write clean, testable code
|
|
25
|
+
- Commit incrementally
|
|
26
|
+
|
|
27
|
+
3. **Test**
|
|
28
|
+
- Unit tests for new code
|
|
29
|
+
- Integration tests if needed
|
|
30
|
+
- Manual testing
|
|
31
|
+
|
|
32
|
+
4. **Document**
|
|
33
|
+
- Update relevant docs
|
|
34
|
+
- Add code comments where needed
|
|
35
|
+
- Update CHANGELOG if applicable
|
|
36
|
+
|
|
37
|
+
## Commands
|
|
38
|
+
|
|
39
|
+
```bash
|
|
40
|
+
# Run tests
|
|
41
|
+
npm test # or appropriate test command
|
|
42
|
+
|
|
43
|
+
# Check build
|
|
44
|
+
npm run build # or appropriate build command
|
|
45
|
+
|
|
46
|
+
# Create PR when ready
|
|
47
|
+
gh pr create --title "Feature: {{FEATURE_NAME}}" --body "## Summary\n\n<description>\n\n## Changes\n\n- <change 1>\n- <change 2>"
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Feature Checklist
|
|
51
|
+
|
|
52
|
+
- [ ] Requirements understood
|
|
53
|
+
- [ ] Implementation complete
|
|
54
|
+
- [ ] Tests written and passing
|
|
55
|
+
- [ ] Documentation updated
|
|
56
|
+
- [ ] Ready for PR
|