oh-my-claude-sisyphus 3.8.16 → 3.9.0
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/.claude-plugin/marketplace.json +1 -1
- package/.claude-plugin/plugin.json +1 -1
- package/.mcp.json +1 -1
- package/agents/analyst.md +41 -0
- package/agents/architect.md +45 -0
- package/agents/critic.md +42 -0
- package/agents/deep-executor.md +193 -0
- package/agents/planner.md +82 -0
- package/bridge/mcp-server.cjs +181 -181
- package/dist/__tests__/agent-registry.test.js +1 -1
- package/dist/__tests__/installer.test.js +8 -8
- package/dist/__tests__/installer.test.js.map +1 -1
- package/dist/__tests__/omc-tools-server.test.js +2 -2
- package/dist/__tests__/omc-tools-server.test.js.map +1 -1
- package/dist/__tests__/skills.test.js +5 -4
- package/dist/__tests__/skills.test.js.map +1 -1
- package/dist/agents/deep-executor.d.ts +15 -0
- package/dist/agents/deep-executor.d.ts.map +1 -0
- package/dist/agents/deep-executor.js +47 -0
- package/dist/agents/deep-executor.js.map +1 -0
- package/dist/agents/definitions.d.ts +15 -0
- package/dist/agents/definitions.d.ts.map +1 -1
- package/dist/agents/definitions.js +25 -0
- package/dist/agents/definitions.js.map +1 -1
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.d.ts.map +1 -1
- package/dist/agents/index.js +1 -0
- package/dist/agents/index.js.map +1 -1
- package/dist/cli/commands/doctor-conflicts.d.ts +55 -0
- package/dist/cli/commands/doctor-conflicts.d.ts.map +1 -0
- package/dist/cli/commands/doctor-conflicts.js +261 -0
- package/dist/cli/commands/doctor-conflicts.js.map +1 -0
- package/dist/cli/index.js +16 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/features/auto-update.d.ts +12 -0
- package/dist/features/auto-update.d.ts.map +1 -1
- package/dist/features/auto-update.js +4 -1
- package/dist/features/auto-update.js.map +1 -1
- package/dist/features/context-injector/types.d.ts +1 -1
- package/dist/features/context-injector/types.d.ts.map +1 -1
- package/dist/hooks/__tests__/bridge.test.d.ts +2 -0
- package/dist/hooks/__tests__/bridge.test.d.ts.map +1 -0
- package/dist/hooks/__tests__/bridge.test.js +199 -0
- package/dist/hooks/__tests__/bridge.test.js.map +1 -0
- package/dist/hooks/beads-context/__tests__/index.test.d.ts +2 -0
- package/dist/hooks/beads-context/__tests__/index.test.d.ts.map +1 -0
- package/dist/hooks/beads-context/__tests__/index.test.js +150 -0
- package/dist/hooks/beads-context/__tests__/index.test.js.map +1 -0
- package/dist/hooks/beads-context/constants.d.ts +3 -0
- package/dist/hooks/beads-context/constants.d.ts.map +1 -0
- package/dist/hooks/beads-context/constants.js +35 -0
- package/dist/hooks/beads-context/constants.js.map +1 -0
- package/dist/hooks/beads-context/index.d.ts +21 -0
- package/dist/hooks/beads-context/index.d.ts.map +1 -0
- package/dist/hooks/beads-context/index.js +62 -0
- package/dist/hooks/beads-context/index.js.map +1 -0
- package/dist/hooks/beads-context/types.d.ts +7 -0
- package/dist/hooks/beads-context/types.d.ts.map +1 -0
- package/dist/hooks/beads-context/types.js +2 -0
- package/dist/hooks/beads-context/types.js.map +1 -0
- package/dist/hooks/bridge.d.ts +4 -0
- package/dist/hooks/bridge.d.ts.map +1 -1
- package/dist/hooks/bridge.js +76 -23
- package/dist/hooks/bridge.js.map +1 -1
- package/dist/hooks/clear-suggestions/constants.d.ts +54 -0
- package/dist/hooks/clear-suggestions/constants.d.ts.map +1 -0
- package/dist/hooks/clear-suggestions/constants.js +102 -0
- package/dist/hooks/clear-suggestions/constants.js.map +1 -0
- package/dist/hooks/clear-suggestions/index.d.ts +61 -0
- package/dist/hooks/clear-suggestions/index.d.ts.map +1 -0
- package/dist/hooks/clear-suggestions/index.js +282 -0
- package/dist/hooks/clear-suggestions/index.js.map +1 -0
- package/dist/hooks/clear-suggestions/triggers.d.ts +65 -0
- package/dist/hooks/clear-suggestions/triggers.d.ts.map +1 -0
- package/dist/hooks/clear-suggestions/triggers.js +222 -0
- package/dist/hooks/clear-suggestions/triggers.js.map +1 -0
- package/dist/hooks/clear-suggestions/types.d.ts +92 -0
- package/dist/hooks/clear-suggestions/types.d.ts.map +1 -0
- package/dist/hooks/clear-suggestions/types.js +9 -0
- package/dist/hooks/clear-suggestions/types.js.map +1 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +3 -0
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/permission-handler/index.d.ts.map +1 -1
- package/dist/hooks/permission-handler/index.js +3 -1
- package/dist/hooks/permission-handler/index.js.map +1 -1
- package/dist/hooks/setup/index.d.ts.map +1 -1
- package/dist/hooks/setup/index.js +12 -5
- package/dist/hooks/setup/index.js.map +1 -1
- package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
- package/dist/hooks/subagent-tracker/index.js +25 -9
- package/dist/hooks/subagent-tracker/index.js.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/installer/__tests__/claude-md-merge.test.d.ts +6 -0
- package/dist/installer/__tests__/claude-md-merge.test.d.ts.map +1 -0
- package/dist/installer/__tests__/claude-md-merge.test.js +220 -0
- package/dist/installer/__tests__/claude-md-merge.test.js.map +1 -0
- package/dist/installer/__tests__/safe-installer.test.d.ts +6 -0
- package/dist/installer/__tests__/safe-installer.test.d.ts.map +1 -0
- package/dist/installer/__tests__/safe-installer.test.js +172 -0
- package/dist/installer/__tests__/safe-installer.test.js.map +1 -0
- package/dist/installer/hooks.d.ts.map +1 -1
- package/dist/installer/hooks.js +3 -1
- package/dist/installer/hooks.js.map +1 -1
- package/dist/installer/index.d.ts +27 -1
- package/dist/installer/index.d.ts.map +1 -1
- package/dist/installer/index.js +209 -85
- package/dist/installer/index.js.map +1 -1
- package/dist/mcp/omc-tools-server.d.ts +1 -1
- package/dist/mcp/omc-tools-server.d.ts.map +1 -1
- package/dist/mcp/omc-tools-server.js +3 -3
- package/dist/mcp/omc-tools-server.js.map +1 -1
- package/dist/mcp/standalone-server.js +1 -1
- package/dist/mcp/standalone-server.js.map +1 -1
- package/dist/verification/tier-selector.d.ts +40 -0
- package/dist/verification/tier-selector.d.ts.map +1 -0
- package/dist/verification/tier-selector.js +95 -0
- package/dist/verification/tier-selector.js.map +1 -0
- package/dist/verification/tier-selector.test.d.ts +2 -0
- package/dist/verification/tier-selector.test.d.ts.map +1 -0
- package/dist/verification/tier-selector.test.js +282 -0
- package/dist/verification/tier-selector.test.js.map +1 -0
- package/docs/AGENTS.md +1 -1
- package/docs/CLAUDE.md +90 -378
- package/docs/partials/agent-tiers.md +165 -0
- package/docs/partials/features.md +131 -0
- package/docs/partials/mode-hierarchy.md +120 -0
- package/docs/partials/mode-selection-guide.md +82 -0
- package/docs/partials/verification-tiers.md +107 -0
- package/docs/shared/agent-tiers.md +165 -0
- package/docs/shared/features.md +131 -0
- package/docs/shared/mode-hierarchy.md +120 -0
- package/docs/shared/mode-selection-guide.md +82 -0
- package/docs/shared/verification-tiers.md +107 -0
- package/package.json +4 -3
- package/scripts/compose-docs.mjs +44 -0
- package/scripts/keyword-detector.mjs +13 -3
- package/skills/deep-executor/SKILL.md +50 -0
- package/skills/ecomode/SKILL.md +58 -103
- package/skills/omc-setup/SKILL.md +197 -20
- package/skills/plan/SKILL.md +62 -0
- package/skills/project-session-manager/SKILL.md +87 -4
- package/skills/project-session-manager/lib/config.sh +54 -5
- package/skills/project-session-manager/lib/parse.sh +65 -11
- package/skills/project-session-manager/lib/providers/github.sh +52 -0
- package/skills/project-session-manager/lib/providers/interface.sh +76 -0
- package/skills/project-session-manager/lib/providers/jira.sh +79 -0
- package/skills/project-session-manager/lib/session.sh +49 -12
- package/skills/project-session-manager/lib/worktree.sh +37 -4
- package/skills/project-session-manager/psm.sh +116 -51
- package/skills/ralph/SKILL.md +41 -27
- package/skills/ultrawork/SKILL.md +56 -66
- package/templates/hooks/keyword-detector.mjs +21 -13
- package/templates/hooks/lib/stdin.mjs +62 -0
- package/templates/hooks/persistent-mode.mjs +7 -8
- package/templates/hooks/post-tool-use.mjs +8 -10
- package/templates/hooks/pre-tool-use.mjs +9 -6
- package/templates/hooks/session-start.mjs +7 -8
|
@@ -1,6 +1,32 @@
|
|
|
1
1
|
#!/bin/bash
|
|
2
2
|
# PSM Worktree Management
|
|
3
3
|
|
|
4
|
+
# Validate worktree path is under PSM worktree root before deletion
|
|
5
|
+
# Returns 0 if valid, 1 if invalid
|
|
6
|
+
# Usage: validate_worktree_path <path>
|
|
7
|
+
validate_worktree_path() {
|
|
8
|
+
local path="$1"
|
|
9
|
+
local worktree_root
|
|
10
|
+
worktree_root=$(psm_get_worktree_root 2>/dev/null) || return 1
|
|
11
|
+
|
|
12
|
+
# Path must exist and be a directory
|
|
13
|
+
if [[ ! -d "$path" ]]; then
|
|
14
|
+
return 1
|
|
15
|
+
fi
|
|
16
|
+
|
|
17
|
+
# Resolve to absolute paths for comparison
|
|
18
|
+
local abs_path abs_root
|
|
19
|
+
abs_path=$(cd "$path" 2>/dev/null && pwd) || return 1
|
|
20
|
+
abs_root=$(cd "$worktree_root" 2>/dev/null && pwd) || return 1
|
|
21
|
+
|
|
22
|
+
# Check path is under root and doesn't contain ..
|
|
23
|
+
if [[ "$abs_path" != "$abs_root"/* ]] || [[ "$path" == *".."* ]]; then
|
|
24
|
+
echo "error|Invalid worktree path: not under PSM root" >&2
|
|
25
|
+
return 1
|
|
26
|
+
fi
|
|
27
|
+
return 0
|
|
28
|
+
}
|
|
29
|
+
|
|
4
30
|
# Create a worktree for PR review
|
|
5
31
|
# Usage: psm_create_pr_worktree <local_repo> <alias> <pr_number> <pr_branch>
|
|
6
32
|
psm_create_pr_worktree() {
|
|
@@ -146,10 +172,17 @@ psm_remove_worktree() {
|
|
|
146
172
|
fi
|
|
147
173
|
|
|
148
174
|
cd "$local_repo" || return 1
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
175
|
+
|
|
176
|
+
# Validate path is under PSM worktree root before any deletion
|
|
177
|
+
if validate_worktree_path "$worktree_path"; then
|
|
178
|
+
git worktree remove "$worktree_path" --force 2>/dev/null || {
|
|
179
|
+
# Force remove the directory if git worktree remove fails
|
|
180
|
+
rm -rf "$worktree_path"
|
|
181
|
+
}
|
|
182
|
+
else
|
|
183
|
+
echo "error|Refusing to delete path outside worktree root: $worktree_path" >&2
|
|
184
|
+
return 1
|
|
185
|
+
fi
|
|
153
186
|
|
|
154
187
|
echo "removed|$worktree_path"
|
|
155
188
|
return 0
|
|
@@ -13,6 +13,11 @@ source "$SCRIPT_DIR/lib/worktree.sh"
|
|
|
13
13
|
source "$SCRIPT_DIR/lib/tmux.sh"
|
|
14
14
|
source "$SCRIPT_DIR/lib/session.sh"
|
|
15
15
|
|
|
16
|
+
# Source provider files
|
|
17
|
+
source "$SCRIPT_DIR/lib/providers/interface.sh"
|
|
18
|
+
source "$SCRIPT_DIR/lib/providers/github.sh"
|
|
19
|
+
source "$SCRIPT_DIR/lib/providers/jira.sh"
|
|
20
|
+
|
|
16
21
|
# Colors for output
|
|
17
22
|
RED='\033[0;31m'
|
|
18
23
|
GREEN='\033[0;32m'
|
|
@@ -38,15 +43,14 @@ check_dependencies() {
|
|
|
38
43
|
missing+=("jq")
|
|
39
44
|
fi
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
fi
|
|
46
|
+
# Note: gh and jira are checked per-operation, not globally
|
|
47
|
+
# This allows users without gh to still use Jira, and vice versa
|
|
44
48
|
|
|
45
49
|
if [[ ${#missing[@]} -gt 0 ]]; then
|
|
46
50
|
log_error "Missing required dependencies: ${missing[*]}"
|
|
47
51
|
log_info "Install with:"
|
|
48
|
-
log_info " Ubuntu/Debian: sudo apt install git jq
|
|
49
|
-
log_info " macOS: brew install git jq
|
|
52
|
+
log_info " Ubuntu/Debian: sudo apt install git jq"
|
|
53
|
+
log_info " macOS: brew install git jq"
|
|
50
54
|
exit 1
|
|
51
55
|
fi
|
|
52
56
|
|
|
@@ -106,7 +110,21 @@ cmd_review() {
|
|
|
106
110
|
return 1
|
|
107
111
|
fi
|
|
108
112
|
|
|
109
|
-
IFS='|' read -r type alias repo pr_number local_path base <<< "$parsed"
|
|
113
|
+
IFS='|' read -r type alias repo pr_number local_path base provider provider_ref <<< "$parsed"
|
|
114
|
+
|
|
115
|
+
# Provider guard: Jira doesn't have PRs
|
|
116
|
+
if [[ "$provider" == "jira" ]]; then
|
|
117
|
+
log_error "Jira issues cannot be 'reviewed' - Jira has no PR concept."
|
|
118
|
+
log_info "Use 'psm fix $ref' to work on a Jira issue instead."
|
|
119
|
+
log_info "Jira integration supports: fix, feature"
|
|
120
|
+
return 1
|
|
121
|
+
fi
|
|
122
|
+
|
|
123
|
+
# Check GitHub CLI availability
|
|
124
|
+
if ! provider_github_available; then
|
|
125
|
+
log_error "GitHub CLI (gh) not found. Install: brew install gh"
|
|
126
|
+
return 1
|
|
127
|
+
fi
|
|
110
128
|
|
|
111
129
|
if [[ -z "$repo" ]]; then
|
|
112
130
|
log_error "Could not determine repository"
|
|
@@ -117,7 +135,7 @@ cmd_review() {
|
|
|
117
135
|
|
|
118
136
|
# Fetch PR info
|
|
119
137
|
local pr_info
|
|
120
|
-
pr_info=$(
|
|
138
|
+
pr_info=$(provider_call "github" fetch_pr "$pr_number" "$repo") || {
|
|
121
139
|
log_error "Failed to fetch PR #${pr_number}. Check if the PR exists and you have access."
|
|
122
140
|
return 1
|
|
123
141
|
}
|
|
@@ -143,7 +161,9 @@ cmd_review() {
|
|
|
143
161
|
local_path="${HOME}/Workspace/$(basename "$repo")"
|
|
144
162
|
if [[ ! -d "$local_path" ]]; then
|
|
145
163
|
log_info "Cloning repository to $local_path..."
|
|
146
|
-
|
|
164
|
+
local clone_url
|
|
165
|
+
clone_url=$(provider_call "github" clone_url "$repo")
|
|
166
|
+
git clone "$clone_url" "$local_path" || {
|
|
147
167
|
log_error "Failed to clone repository"
|
|
148
168
|
return 1
|
|
149
169
|
}
|
|
@@ -198,18 +218,16 @@ cmd_review() {
|
|
|
198
218
|
fi
|
|
199
219
|
|
|
200
220
|
# Create session metadata
|
|
201
|
-
local metadata
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
}
|
|
208
|
-
EOF
|
|
209
|
-
)
|
|
221
|
+
local metadata
|
|
222
|
+
metadata=$(jq -n \
|
|
223
|
+
--argjson pr_number "$pr_number" \
|
|
224
|
+
--arg pr_title "$pr_title" \
|
|
225
|
+
--arg pr_author "$pr_author" \
|
|
226
|
+
--arg pr_url "$pr_url" \
|
|
227
|
+
'{pr_number: $pr_number, pr_title: $pr_title, pr_author: $pr_author, pr_url: $pr_url}')
|
|
210
228
|
|
|
211
229
|
# 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"
|
|
230
|
+
psm_add_session "$session_id" "review" "$alias" "pr-${pr_number}" "$head_branch" "$base_branch" "$session_name" "$worktree_path" "$local_path" "$metadata" "github" "${repo}#${pr_number}"
|
|
213
231
|
|
|
214
232
|
# Output summary
|
|
215
233
|
echo ""
|
|
@@ -242,24 +260,45 @@ cmd_fix() {
|
|
|
242
260
|
return 1
|
|
243
261
|
fi
|
|
244
262
|
|
|
245
|
-
IFS='|' read -r type alias repo issue_number local_path base <<< "$parsed"
|
|
263
|
+
IFS='|' read -r type alias repo issue_number local_path base provider provider_ref <<< "$parsed"
|
|
246
264
|
|
|
247
|
-
|
|
265
|
+
# Check provider CLI availability
|
|
266
|
+
if [[ "$provider" == "jira" ]]; then
|
|
267
|
+
if ! provider_jira_available; then
|
|
268
|
+
log_error "Jira CLI not found. Install: brew install ankitpokhrel/jira-cli/jira-cli"
|
|
269
|
+
return 1
|
|
270
|
+
fi
|
|
271
|
+
else
|
|
272
|
+
if ! provider_github_available; then
|
|
273
|
+
log_error "GitHub CLI (gh) not found. Install: brew install gh"
|
|
274
|
+
return 1
|
|
275
|
+
fi
|
|
276
|
+
fi
|
|
277
|
+
|
|
278
|
+
if [[ -z "$repo" && "$provider" != "jira" ]]; then
|
|
248
279
|
log_error "Could not determine repository"
|
|
249
280
|
return 1
|
|
250
281
|
fi
|
|
251
282
|
|
|
252
|
-
log_info "Fetching issue #${issue_number}
|
|
283
|
+
log_info "Fetching issue #${issue_number}..."
|
|
253
284
|
|
|
254
285
|
# Fetch issue info
|
|
255
286
|
local issue_info
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
287
|
+
if [[ "$provider" == "jira" ]]; then
|
|
288
|
+
issue_info=$(provider_call "jira" fetch_issue "$provider_ref") || {
|
|
289
|
+
log_error "Failed to fetch Jira issue ${provider_ref}"
|
|
290
|
+
return 1
|
|
291
|
+
}
|
|
292
|
+
local issue_title=$(echo "$issue_info" | jq -r '.fields.summary')
|
|
293
|
+
local issue_url=$(echo "$issue_info" | jq -r '.self // empty')
|
|
294
|
+
else
|
|
295
|
+
issue_info=$(provider_call "github" fetch_issue "$issue_number" "$repo") || {
|
|
296
|
+
log_error "Failed to fetch issue #${issue_number}"
|
|
297
|
+
return 1
|
|
298
|
+
}
|
|
299
|
+
local issue_title=$(echo "$issue_info" | jq -r '.title')
|
|
300
|
+
local issue_url=$(echo "$issue_info" | jq -r '.url')
|
|
301
|
+
fi
|
|
263
302
|
local slug=$(psm_slugify "$issue_title" 20)
|
|
264
303
|
|
|
265
304
|
log_info "Issue: #${issue_number} - ${issue_title}"
|
|
@@ -271,10 +310,19 @@ cmd_fix() {
|
|
|
271
310
|
|
|
272
311
|
# Determine local path
|
|
273
312
|
if [[ -z "$local_path" || ! -d "$local_path" ]]; then
|
|
274
|
-
local_path="${HOME}/Workspace/$(basename "$repo")"
|
|
313
|
+
local_path="${HOME}/Workspace/$(basename "${repo:-$alias}")"
|
|
275
314
|
if [[ ! -d "$local_path" ]]; then
|
|
276
315
|
log_info "Cloning repository..."
|
|
277
|
-
|
|
316
|
+
local clone_url
|
|
317
|
+
if [[ "$provider" == "jira" ]]; then
|
|
318
|
+
clone_url=$(provider_call "jira" clone_url "$alias") || {
|
|
319
|
+
log_error "Failed to get clone URL for '$alias'. Configure 'repo' or 'clone_url' in projects.json"
|
|
320
|
+
return 1
|
|
321
|
+
}
|
|
322
|
+
else
|
|
323
|
+
clone_url=$(provider_call "github" clone_url "$repo")
|
|
324
|
+
fi
|
|
325
|
+
git clone "$clone_url" "$local_path" || return 1
|
|
278
326
|
fi
|
|
279
327
|
fi
|
|
280
328
|
|
|
@@ -309,16 +357,14 @@ cmd_fix() {
|
|
|
309
357
|
fi
|
|
310
358
|
|
|
311
359
|
# Create metadata
|
|
312
|
-
local metadata
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
}
|
|
318
|
-
EOF
|
|
319
|
-
)
|
|
360
|
+
local metadata
|
|
361
|
+
metadata=$(jq -n \
|
|
362
|
+
--argjson issue_number "$issue_number" \
|
|
363
|
+
--arg issue_title "$issue_title" \
|
|
364
|
+
--arg issue_url "$issue_url" \
|
|
365
|
+
'{issue_number: $issue_number, issue_title: $issue_title, issue_url: $issue_url}')
|
|
320
366
|
|
|
321
|
-
psm_add_session "$session_id" "fix" "$alias" "issue-${issue_number}" "$branch_name" "$base" "$session_name" "$worktree_path" "$local_path" "$metadata"
|
|
367
|
+
psm_add_session "$session_id" "fix" "$alias" "issue-${issue_number}" "$branch_name" "$base" "$session_name" "$worktree_path" "$local_path" "$metadata" "$provider" "$provider_ref"
|
|
322
368
|
|
|
323
369
|
echo ""
|
|
324
370
|
log_success "Session ready!"
|
|
@@ -473,15 +519,20 @@ cmd_cleanup() {
|
|
|
473
519
|
|
|
474
520
|
local cleaned=0
|
|
475
521
|
|
|
476
|
-
# Check PR sessions (
|
|
522
|
+
# Check PR sessions (GitHub only)
|
|
477
523
|
while IFS='|' read -r id pr_number project; do
|
|
478
524
|
if [[ -z "$id" ]]; then continue; fi
|
|
479
525
|
|
|
526
|
+
local session_json=$(psm_get_session "$id")
|
|
527
|
+
local provider=$(echo "$session_json" | jq -r '.provider // "github"')
|
|
528
|
+
|
|
529
|
+
# Only GitHub has PRs
|
|
530
|
+
if [[ "$provider" != "github" ]]; then continue; fi
|
|
531
|
+
|
|
480
532
|
local repo=$(psm_get_project "$project" | cut -d'|' -f1)
|
|
481
533
|
|
|
482
534
|
if [[ -n "$repo" && -n "$pr_number" ]]; then
|
|
483
|
-
|
|
484
|
-
if [[ "$pr_state" == "true" ]]; then
|
|
535
|
+
if provider_github_available && provider_call "github" pr_merged "$pr_number" "$repo"; then
|
|
485
536
|
log_info "PR #${pr_number} is merged - cleaning up $id"
|
|
486
537
|
cmd_kill "$id"
|
|
487
538
|
((cleaned++))
|
|
@@ -489,18 +540,32 @@ cmd_cleanup() {
|
|
|
489
540
|
fi
|
|
490
541
|
done < <(psm_get_review_sessions)
|
|
491
542
|
|
|
492
|
-
# Check issue sessions (
|
|
543
|
+
# Check issue sessions (GitHub and Jira)
|
|
493
544
|
while IFS='|' read -r id issue_number project; do
|
|
494
545
|
if [[ -z "$id" ]]; then continue; fi
|
|
495
546
|
|
|
496
|
-
local
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
547
|
+
local session_json=$(psm_get_session "$id")
|
|
548
|
+
local provider=$(echo "$session_json" | jq -r '.provider // "github"')
|
|
549
|
+
local provider_ref=$(echo "$session_json" | jq -r '.provider_ref // empty')
|
|
550
|
+
|
|
551
|
+
if [[ "$provider" == "jira" ]]; then
|
|
552
|
+
# Jira cleanup
|
|
553
|
+
if provider_jira_available && [[ -n "$provider_ref" ]]; then
|
|
554
|
+
if provider_call "jira" issue_closed "$provider_ref"; then
|
|
555
|
+
log_info "Jira issue ${provider_ref} is done - cleaning up $id"
|
|
556
|
+
cmd_kill "$id"
|
|
557
|
+
((cleaned++))
|
|
558
|
+
fi
|
|
559
|
+
fi
|
|
560
|
+
else
|
|
561
|
+
# GitHub cleanup
|
|
562
|
+
local repo=$(psm_get_project "$project" | cut -d'|' -f1)
|
|
563
|
+
if provider_github_available && [[ -n "$repo" && -n "$issue_number" ]]; then
|
|
564
|
+
if provider_call "github" issue_closed "$issue_number" "$repo"; then
|
|
565
|
+
log_info "Issue #${issue_number} is closed - cleaning up $id"
|
|
566
|
+
cmd_kill "$id"
|
|
567
|
+
((cleaned++))
|
|
568
|
+
fi
|
|
504
569
|
fi
|
|
505
570
|
fi
|
|
506
571
|
done < <(psm_get_fix_sessions)
|
package/skills/ralph/SKILL.md
CHANGED
|
@@ -76,7 +76,7 @@ Your workflow:
|
|
|
76
76
|
|
|
77
77
|
## ULTRAWORK MODE (AUTO-ACTIVATED)
|
|
78
78
|
|
|
79
|
-
Ralph
|
|
79
|
+
Ralph is a **persistence wrapper** that includes Ultrawork as a component for maximum parallel execution. You MUST follow these rules:
|
|
80
80
|
|
|
81
81
|
### Parallel Execution Rules
|
|
82
82
|
- **PARALLEL**: Fire independent calls simultaneously - NEVER wait sequentially
|
|
@@ -93,23 +93,11 @@ Ralph automatically activates Ultrawork for maximum parallel execution. You MUST
|
|
|
93
93
|
|
|
94
94
|
### Available Agents by Tier
|
|
95
95
|
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
| **Research** | `researcher-low` | `researcher` | - |
|
|
102
|
-
| **Frontend** | `designer-low` | `designer` | `designer-high` |
|
|
103
|
-
| **Docs** | `writer` | - | - |
|
|
104
|
-
| **Visual** | - | `vision` | - |
|
|
105
|
-
| **Planning** | - | - | `planner` |
|
|
106
|
-
| **Critique** | - | - | `critic` |
|
|
107
|
-
| **Pre-Planning** | - | - | `analyst` |
|
|
108
|
-
| **Testing** | - | `qa-tester` | - |
|
|
109
|
-
| **Security** | `security-reviewer-low` | - | `security-reviewer` |
|
|
110
|
-
| **Build** | `build-fixer-low` | `build-fixer` | - |
|
|
111
|
-
| **TDD** | `tdd-guide-low` | `tdd-guide` | - |
|
|
112
|
-
| **Code Review** | `code-reviewer-low` | - | `code-reviewer` |
|
|
96
|
+
**FIRST ACTION:** Before delegating any work, read the agent reference file:
|
|
97
|
+
```
|
|
98
|
+
Read file: docs/shared/agent-tiers.md
|
|
99
|
+
```
|
|
100
|
+
This provides the complete agent tier matrix, MCP tool assignments, and selection guidance.
|
|
113
101
|
|
|
114
102
|
**CRITICAL: Always pass `model` parameter explicitly!**
|
|
115
103
|
```
|
|
@@ -166,20 +154,46 @@ Before outputting the completion promise:
|
|
|
166
154
|
|
|
167
155
|
**Skipping verification = Task NOT complete**
|
|
168
156
|
|
|
169
|
-
##
|
|
157
|
+
## VERIFICATION PROTOCOL (TIERED)
|
|
170
158
|
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
159
|
+
Ralph uses tiered verification to save tokens while maintaining quality.
|
|
160
|
+
|
|
161
|
+
### Verification Tier Selection
|
|
162
|
+
|
|
163
|
+
Before spawning architect for verification, determine the appropriate tier:
|
|
164
|
+
|
|
165
|
+
| Change Profile | Tier | Agent |
|
|
166
|
+
|----------------|------|-------|
|
|
167
|
+
| <5 files, <100 lines, full tests | LIGHT | architect-low (haiku) |
|
|
168
|
+
| Standard changes | STANDARD | architect-medium (sonnet) |
|
|
169
|
+
| >20 files, security/architectural | THOROUGH | architect (opus) |
|
|
170
|
+
|
|
171
|
+
### Ralph Minimum Verification Tier
|
|
172
|
+
|
|
173
|
+
**Floor: STANDARD (architect-medium / sonnet)**
|
|
174
|
+
|
|
175
|
+
Even for small changes (<5 files), ralph requires at least STANDARD tier verification. The LIGHT tier (haiku) is insufficient for ralph's completion guarantee. When tier selection returns LIGHT, upgrade to STANDARD.
|
|
176
|
+
|
|
177
|
+
### Verification Flow
|
|
178
|
+
|
|
179
|
+
1. **Collect change metadata**: Count files, lines, detect security/architectural patterns
|
|
180
|
+
2. **Select tier**: Apply rules from `/docs/shared/verification-tiers.md`
|
|
181
|
+
3. **Spawn appropriate architect**:
|
|
175
182
|
```
|
|
183
|
+
// LIGHT - small, well-tested changes
|
|
184
|
+
Task(subagent_type="oh-my-claudecode:architect-low", model="haiku", prompt="Quick verification: [describe changes]")
|
|
176
185
|
|
|
177
|
-
|
|
186
|
+
// STANDARD - most changes
|
|
187
|
+
Task(subagent_type="oh-my-claudecode:architect-medium", model="sonnet", prompt="Verify implementation: [describe changes]")
|
|
178
188
|
|
|
179
|
-
|
|
180
|
-
|
|
189
|
+
// THOROUGH - large/security/architectural changes
|
|
190
|
+
Task(subagent_type="oh-my-claudecode:architect", model="opus", prompt="Full verification: [describe changes]")
|
|
191
|
+
```
|
|
192
|
+
4. **Wait for verdict**
|
|
193
|
+
5. **If approved**: Run `/oh-my-claudecode:cancel` to cleanly exit
|
|
194
|
+
6. **If rejected**: Fix issues and re-verify (same tier)
|
|
181
195
|
|
|
182
|
-
|
|
196
|
+
For complete tier selection rules, read: `docs/shared/verification-tiers.md`
|
|
183
197
|
|
|
184
198
|
## ZERO TOLERANCE
|
|
185
199
|
|
|
@@ -1,71 +1,45 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: ultrawork
|
|
3
|
-
description:
|
|
3
|
+
description: Parallel execution engine for high-throughput task completion
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Ultrawork Skill
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
Parallel execution engine. This is a **COMPONENT**, not a standalone persistence mode.
|
|
9
9
|
|
|
10
|
-
##
|
|
11
|
-
|
|
12
|
-
This skill enhances Claude's capabilities by:
|
|
10
|
+
## What Ultrawork Provides
|
|
13
11
|
|
|
14
12
|
1. **Parallel Execution**: Running multiple agents simultaneously for independent tasks
|
|
15
|
-
2. **
|
|
16
|
-
3. **
|
|
17
|
-
4. **Persistence Enforcement**: Never stopping until all tasks are verified complete
|
|
18
|
-
5. **Smart Model Routing**: Using tiered agents to save tokens
|
|
19
|
-
|
|
20
|
-
## Smart Model Routing (CRITICAL - SAVE TOKENS)
|
|
21
|
-
|
|
22
|
-
**Choose tier based on task complexity: LOW (haiku) → MEDIUM (sonnet) → HIGH (opus)**
|
|
23
|
-
|
|
24
|
-
### Available Agents by Tier
|
|
13
|
+
2. **Background Operations**: Using `run_in_background: true` for long operations
|
|
14
|
+
3. **Smart Model Routing**: Using tiered agents to save tokens
|
|
25
15
|
|
|
26
|
-
|
|
27
|
-
|--------|-------------|-----------------|-------------|
|
|
28
|
-
| **Analysis** | `architect-low` | `architect-medium` | `architect` |
|
|
29
|
-
| **Execution** | `executor-low` | `executor` | `executor-high` |
|
|
30
|
-
| **Search** | `explore` | `explore-medium` | - |
|
|
31
|
-
| **Research** | `researcher-low` | `researcher` | - |
|
|
32
|
-
| **Frontend** | `designer-low` | `designer` | `designer-high` |
|
|
33
|
-
| **Docs** | `writer` | - | - |
|
|
34
|
-
| **Visual** | - | `vision` | - |
|
|
35
|
-
| **Planning** | - | - | `planner`, `critic`, `analyst` |
|
|
36
|
-
| **Testing** | - | `qa-tester` | - |
|
|
37
|
-
| **Security** | `security-reviewer-low` | - | `security-reviewer` |
|
|
38
|
-
| **Build** | `build-fixer-low` | `build-fixer` | - |
|
|
39
|
-
| **TDD** | `tdd-guide-low` | `tdd-guide` | - |
|
|
40
|
-
| **Code Review** | `code-reviewer-low` | - | `code-reviewer` |
|
|
16
|
+
## What Ultrawork Does NOT Provide
|
|
41
17
|
|
|
42
|
-
|
|
18
|
+
- **Persistence**: Use `ralph` for "don't stop until done" behavior
|
|
19
|
+
- **Verification Loop**: Use `ralph` for mandatory architect verification
|
|
20
|
+
- **State Management**: Use `ralph` or `autopilot` for session persistence
|
|
43
21
|
|
|
44
|
-
|
|
45
|
-
|-----------------|------|----------|
|
|
46
|
-
| Simple lookups | LOW | "What does this function return?", "Find where X is defined" |
|
|
47
|
-
| Standard work | MEDIUM | "Add error handling", "Implement this feature" |
|
|
48
|
-
| Complex analysis | HIGH | "Debug this race condition", "Refactor auth module across 5 files" |
|
|
22
|
+
## Usage
|
|
49
23
|
|
|
50
|
-
|
|
24
|
+
Ultrawork is automatically activated by:
|
|
25
|
+
- `ralph` (for persistent parallel work)
|
|
26
|
+
- `autopilot` (for autonomous parallel work)
|
|
27
|
+
- Direct invocation when you want parallel-only execution with manual oversight
|
|
51
28
|
|
|
52
|
-
|
|
29
|
+
## Smart Model Routing
|
|
53
30
|
|
|
31
|
+
**FIRST ACTION:** Before delegating any work, read the agent reference file:
|
|
54
32
|
```
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
// Standard implementation → MEDIUM tier
|
|
59
|
-
Task(subagent_type="oh-my-claudecode:executor", model="sonnet", prompt="Add error handling to login")
|
|
60
|
-
|
|
61
|
-
// Complex refactoring → HIGH tier
|
|
62
|
-
Task(subagent_type="oh-my-claudecode:executor-high", model="opus", prompt="Refactor auth module using JWT across 5 files")
|
|
33
|
+
Read file: docs/shared/agent-tiers.md
|
|
34
|
+
```
|
|
35
|
+
This provides the complete agent tier matrix, MCP tool assignments, and selection guidance.
|
|
63
36
|
|
|
64
|
-
|
|
65
|
-
Task(subagent_type="oh-my-claudecode:explore", model="haiku", prompt="Find where UserService is defined")
|
|
37
|
+
**CRITICAL: Always pass `model` parameter explicitly!**
|
|
66
38
|
|
|
67
|
-
|
|
68
|
-
Task(subagent_type="oh-my-claudecode:
|
|
39
|
+
```
|
|
40
|
+
Task(subagent_type="oh-my-claudecode:architect-low", model="haiku", prompt="...")
|
|
41
|
+
Task(subagent_type="oh-my-claudecode:executor", model="sonnet", prompt="...")
|
|
42
|
+
Task(subagent_type="oh-my-claudecode:architect", model="opus", prompt="...")
|
|
69
43
|
```
|
|
70
44
|
|
|
71
45
|
## Background Execution Rules
|
|
@@ -74,32 +48,48 @@ Task(subagent_type="oh-my-claudecode:explore-medium", model="sonnet", prompt="Fi
|
|
|
74
48
|
- Package installation: npm install, pip install, cargo build
|
|
75
49
|
- Build processes: npm run build, make, tsc
|
|
76
50
|
- Test suites: npm test, pytest, cargo test
|
|
77
|
-
- Docker operations: docker build, docker pull
|
|
78
51
|
|
|
79
52
|
**Run Blocking** (foreground):
|
|
80
53
|
- Quick status checks: git status, ls, pwd
|
|
81
54
|
- File reads, edits
|
|
82
55
|
- Simple commands
|
|
83
56
|
|
|
84
|
-
##
|
|
57
|
+
## Relationship to Other Modes
|
|
85
58
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
59
|
+
```
|
|
60
|
+
ralph (persistence wrapper)
|
|
61
|
+
└── includes: ultrawork (this skill)
|
|
62
|
+
└── provides: parallel execution only
|
|
63
|
+
|
|
64
|
+
autopilot (autonomous execution)
|
|
65
|
+
└── includes: ralph
|
|
66
|
+
└── includes: ultrawork (this skill)
|
|
91
67
|
|
|
92
|
-
|
|
68
|
+
ecomode (token efficiency)
|
|
69
|
+
└── modifies: ultrawork's model selection
|
|
70
|
+
```
|
|
93
71
|
|
|
94
|
-
##
|
|
72
|
+
## When to Use Ultrawork Directly
|
|
95
73
|
|
|
96
|
-
|
|
74
|
+
Use ultrawork directly when you want:
|
|
75
|
+
- Parallel execution without persistence guarantees
|
|
76
|
+
- Manual oversight over completion
|
|
77
|
+
- Quick parallel tasks where you'll verify yourself
|
|
97
78
|
|
|
98
|
-
|
|
79
|
+
Use `ralph` instead when you want:
|
|
80
|
+
- Verified completion (architect check)
|
|
81
|
+
- Automatic retry on failure
|
|
82
|
+
- Session persistence for resume
|
|
99
83
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
84
|
+
## Completion Verification (Direct Invocations)
|
|
85
|
+
|
|
86
|
+
When ultrawork is invoked directly (not via ralph), apply lightweight verification before claiming completion:
|
|
87
|
+
|
|
88
|
+
### Quick Verification Checklist
|
|
89
|
+
- [ ] **BUILD:** `tsc --noEmit` or equivalent passes
|
|
90
|
+
- [ ] **TESTS:** Run affected tests, all pass
|
|
91
|
+
- [ ] **ERRORS:** No new errors introduced
|
|
92
|
+
|
|
93
|
+
This is lighter than ralph's full verification but ensures basic quality for direct ultrawork usage.
|
|
104
94
|
|
|
105
|
-
|
|
95
|
+
For full persistence and comprehensive verification, use `ralph` mode instead.
|
|
@@ -24,8 +24,15 @@
|
|
|
24
24
|
*/
|
|
25
25
|
|
|
26
26
|
import { writeFileSync, mkdirSync, existsSync, unlinkSync } from 'fs';
|
|
27
|
-
import { join } from 'path';
|
|
27
|
+
import { join, dirname } from 'path';
|
|
28
28
|
import { homedir } from 'os';
|
|
29
|
+
import { fileURLToPath } from 'url';
|
|
30
|
+
|
|
31
|
+
const __filename = fileURLToPath(import.meta.url);
|
|
32
|
+
const __dirname = dirname(__filename);
|
|
33
|
+
|
|
34
|
+
// Dynamic import for the shared stdin module
|
|
35
|
+
const { readStdin } = await import(join(__dirname, 'lib', 'stdin.mjs'));
|
|
29
36
|
|
|
30
37
|
const ULTRATHINK_MESSAGE = `<think-mode>
|
|
31
38
|
|
|
@@ -44,15 +51,6 @@ Use your extended thinking capabilities to provide the most thorough and well-re
|
|
|
44
51
|
---
|
|
45
52
|
`;
|
|
46
53
|
|
|
47
|
-
// Read all stdin
|
|
48
|
-
async function readStdin() {
|
|
49
|
-
const chunks = [];
|
|
50
|
-
for await (const chunk of process.stdin) {
|
|
51
|
-
chunks.push(chunk);
|
|
52
|
-
}
|
|
53
|
-
return Buffer.concat(chunks).toString('utf-8');
|
|
54
|
-
}
|
|
55
|
-
|
|
56
54
|
// Extract prompt from various JSON structures
|
|
57
55
|
function extractPrompt(input) {
|
|
58
56
|
try {
|
|
@@ -73,10 +71,20 @@ function extractPrompt(input) {
|
|
|
73
71
|
}
|
|
74
72
|
}
|
|
75
73
|
|
|
76
|
-
//
|
|
77
|
-
function
|
|
74
|
+
// Sanitize text to prevent false positives from code blocks, XML tags, URLs, and file paths
|
|
75
|
+
function sanitizeForKeywordDetection(text) {
|
|
78
76
|
return text
|
|
77
|
+
// 1. Strip XML-style tag blocks: <tag-name ...>...</tag-name> (multi-line, greedy on tag name)
|
|
78
|
+
.replace(/<(\w[\w-]*)[\s>][\s\S]*?<\/\1>/g, '')
|
|
79
|
+
// 2. Strip self-closing XML tags: <tag-name />, <tag-name attr="val" />
|
|
80
|
+
.replace(/<\w[\w-]*(?:\s[^>]*)?\s*\/>/g, '')
|
|
81
|
+
// 3. Strip URLs: http://... or https://... up to whitespace
|
|
82
|
+
.replace(/https?:\/\/[^\s)>\]]+/g, '')
|
|
83
|
+
// 4. Strip file paths: /foo/bar/baz or foo/bar/baz (using lookbehind to avoid consuming leading char)
|
|
84
|
+
.replace(/(?<=^|[\s"'`(])(?:\/)?(?:[\w.-]+\/)+[\w.-]+/gm, '')
|
|
85
|
+
// 5. Strip markdown code blocks (existing)
|
|
79
86
|
.replace(/```[\s\S]*?```/g, '')
|
|
87
|
+
// 6. Strip inline code (existing)
|
|
80
88
|
.replace(/`[^`]+`/g, '');
|
|
81
89
|
}
|
|
82
90
|
|
|
@@ -225,7 +233,7 @@ async function main() {
|
|
|
225
233
|
return;
|
|
226
234
|
}
|
|
227
235
|
|
|
228
|
-
const cleanPrompt =
|
|
236
|
+
const cleanPrompt = sanitizeForKeywordDetection(prompt).toLowerCase();
|
|
229
237
|
|
|
230
238
|
// Collect all matching keywords
|
|
231
239
|
const matches = [];
|