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.
Files changed (160) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/.mcp.json +1 -1
  4. package/agents/analyst.md +41 -0
  5. package/agents/architect.md +45 -0
  6. package/agents/critic.md +42 -0
  7. package/agents/deep-executor.md +193 -0
  8. package/agents/planner.md +82 -0
  9. package/bridge/mcp-server.cjs +181 -181
  10. package/dist/__tests__/agent-registry.test.js +1 -1
  11. package/dist/__tests__/installer.test.js +8 -8
  12. package/dist/__tests__/installer.test.js.map +1 -1
  13. package/dist/__tests__/omc-tools-server.test.js +2 -2
  14. package/dist/__tests__/omc-tools-server.test.js.map +1 -1
  15. package/dist/__tests__/skills.test.js +5 -4
  16. package/dist/__tests__/skills.test.js.map +1 -1
  17. package/dist/agents/deep-executor.d.ts +15 -0
  18. package/dist/agents/deep-executor.d.ts.map +1 -0
  19. package/dist/agents/deep-executor.js +47 -0
  20. package/dist/agents/deep-executor.js.map +1 -0
  21. package/dist/agents/definitions.d.ts +15 -0
  22. package/dist/agents/definitions.d.ts.map +1 -1
  23. package/dist/agents/definitions.js +25 -0
  24. package/dist/agents/definitions.js.map +1 -1
  25. package/dist/agents/index.d.ts +1 -0
  26. package/dist/agents/index.d.ts.map +1 -1
  27. package/dist/agents/index.js +1 -0
  28. package/dist/agents/index.js.map +1 -1
  29. package/dist/cli/commands/doctor-conflicts.d.ts +55 -0
  30. package/dist/cli/commands/doctor-conflicts.d.ts.map +1 -0
  31. package/dist/cli/commands/doctor-conflicts.js +261 -0
  32. package/dist/cli/commands/doctor-conflicts.js.map +1 -0
  33. package/dist/cli/index.js +16 -1
  34. package/dist/cli/index.js.map +1 -1
  35. package/dist/features/auto-update.d.ts +12 -0
  36. package/dist/features/auto-update.d.ts.map +1 -1
  37. package/dist/features/auto-update.js +4 -1
  38. package/dist/features/auto-update.js.map +1 -1
  39. package/dist/features/context-injector/types.d.ts +1 -1
  40. package/dist/features/context-injector/types.d.ts.map +1 -1
  41. package/dist/hooks/__tests__/bridge.test.d.ts +2 -0
  42. package/dist/hooks/__tests__/bridge.test.d.ts.map +1 -0
  43. package/dist/hooks/__tests__/bridge.test.js +199 -0
  44. package/dist/hooks/__tests__/bridge.test.js.map +1 -0
  45. package/dist/hooks/beads-context/__tests__/index.test.d.ts +2 -0
  46. package/dist/hooks/beads-context/__tests__/index.test.d.ts.map +1 -0
  47. package/dist/hooks/beads-context/__tests__/index.test.js +150 -0
  48. package/dist/hooks/beads-context/__tests__/index.test.js.map +1 -0
  49. package/dist/hooks/beads-context/constants.d.ts +3 -0
  50. package/dist/hooks/beads-context/constants.d.ts.map +1 -0
  51. package/dist/hooks/beads-context/constants.js +35 -0
  52. package/dist/hooks/beads-context/constants.js.map +1 -0
  53. package/dist/hooks/beads-context/index.d.ts +21 -0
  54. package/dist/hooks/beads-context/index.d.ts.map +1 -0
  55. package/dist/hooks/beads-context/index.js +62 -0
  56. package/dist/hooks/beads-context/index.js.map +1 -0
  57. package/dist/hooks/beads-context/types.d.ts +7 -0
  58. package/dist/hooks/beads-context/types.d.ts.map +1 -0
  59. package/dist/hooks/beads-context/types.js +2 -0
  60. package/dist/hooks/beads-context/types.js.map +1 -0
  61. package/dist/hooks/bridge.d.ts +4 -0
  62. package/dist/hooks/bridge.d.ts.map +1 -1
  63. package/dist/hooks/bridge.js +76 -23
  64. package/dist/hooks/bridge.js.map +1 -1
  65. package/dist/hooks/clear-suggestions/constants.d.ts +54 -0
  66. package/dist/hooks/clear-suggestions/constants.d.ts.map +1 -0
  67. package/dist/hooks/clear-suggestions/constants.js +102 -0
  68. package/dist/hooks/clear-suggestions/constants.js.map +1 -0
  69. package/dist/hooks/clear-suggestions/index.d.ts +61 -0
  70. package/dist/hooks/clear-suggestions/index.d.ts.map +1 -0
  71. package/dist/hooks/clear-suggestions/index.js +282 -0
  72. package/dist/hooks/clear-suggestions/index.js.map +1 -0
  73. package/dist/hooks/clear-suggestions/triggers.d.ts +65 -0
  74. package/dist/hooks/clear-suggestions/triggers.d.ts.map +1 -0
  75. package/dist/hooks/clear-suggestions/triggers.js +222 -0
  76. package/dist/hooks/clear-suggestions/triggers.js.map +1 -0
  77. package/dist/hooks/clear-suggestions/types.d.ts +92 -0
  78. package/dist/hooks/clear-suggestions/types.d.ts.map +1 -0
  79. package/dist/hooks/clear-suggestions/types.js +9 -0
  80. package/dist/hooks/clear-suggestions/types.js.map +1 -0
  81. package/dist/hooks/index.d.ts +1 -0
  82. package/dist/hooks/index.d.ts.map +1 -1
  83. package/dist/hooks/index.js +3 -0
  84. package/dist/hooks/index.js.map +1 -1
  85. package/dist/hooks/permission-handler/index.d.ts.map +1 -1
  86. package/dist/hooks/permission-handler/index.js +3 -1
  87. package/dist/hooks/permission-handler/index.js.map +1 -1
  88. package/dist/hooks/setup/index.d.ts.map +1 -1
  89. package/dist/hooks/setup/index.js +12 -5
  90. package/dist/hooks/setup/index.js.map +1 -1
  91. package/dist/hooks/subagent-tracker/index.d.ts.map +1 -1
  92. package/dist/hooks/subagent-tracker/index.js +25 -9
  93. package/dist/hooks/subagent-tracker/index.js.map +1 -1
  94. package/dist/index.js +1 -1
  95. package/dist/index.js.map +1 -1
  96. package/dist/installer/__tests__/claude-md-merge.test.d.ts +6 -0
  97. package/dist/installer/__tests__/claude-md-merge.test.d.ts.map +1 -0
  98. package/dist/installer/__tests__/claude-md-merge.test.js +220 -0
  99. package/dist/installer/__tests__/claude-md-merge.test.js.map +1 -0
  100. package/dist/installer/__tests__/safe-installer.test.d.ts +6 -0
  101. package/dist/installer/__tests__/safe-installer.test.d.ts.map +1 -0
  102. package/dist/installer/__tests__/safe-installer.test.js +172 -0
  103. package/dist/installer/__tests__/safe-installer.test.js.map +1 -0
  104. package/dist/installer/hooks.d.ts.map +1 -1
  105. package/dist/installer/hooks.js +3 -1
  106. package/dist/installer/hooks.js.map +1 -1
  107. package/dist/installer/index.d.ts +27 -1
  108. package/dist/installer/index.d.ts.map +1 -1
  109. package/dist/installer/index.js +209 -85
  110. package/dist/installer/index.js.map +1 -1
  111. package/dist/mcp/omc-tools-server.d.ts +1 -1
  112. package/dist/mcp/omc-tools-server.d.ts.map +1 -1
  113. package/dist/mcp/omc-tools-server.js +3 -3
  114. package/dist/mcp/omc-tools-server.js.map +1 -1
  115. package/dist/mcp/standalone-server.js +1 -1
  116. package/dist/mcp/standalone-server.js.map +1 -1
  117. package/dist/verification/tier-selector.d.ts +40 -0
  118. package/dist/verification/tier-selector.d.ts.map +1 -0
  119. package/dist/verification/tier-selector.js +95 -0
  120. package/dist/verification/tier-selector.js.map +1 -0
  121. package/dist/verification/tier-selector.test.d.ts +2 -0
  122. package/dist/verification/tier-selector.test.d.ts.map +1 -0
  123. package/dist/verification/tier-selector.test.js +282 -0
  124. package/dist/verification/tier-selector.test.js.map +1 -0
  125. package/docs/AGENTS.md +1 -1
  126. package/docs/CLAUDE.md +90 -378
  127. package/docs/partials/agent-tiers.md +165 -0
  128. package/docs/partials/features.md +131 -0
  129. package/docs/partials/mode-hierarchy.md +120 -0
  130. package/docs/partials/mode-selection-guide.md +82 -0
  131. package/docs/partials/verification-tiers.md +107 -0
  132. package/docs/shared/agent-tiers.md +165 -0
  133. package/docs/shared/features.md +131 -0
  134. package/docs/shared/mode-hierarchy.md +120 -0
  135. package/docs/shared/mode-selection-guide.md +82 -0
  136. package/docs/shared/verification-tiers.md +107 -0
  137. package/package.json +4 -3
  138. package/scripts/compose-docs.mjs +44 -0
  139. package/scripts/keyword-detector.mjs +13 -3
  140. package/skills/deep-executor/SKILL.md +50 -0
  141. package/skills/ecomode/SKILL.md +58 -103
  142. package/skills/omc-setup/SKILL.md +197 -20
  143. package/skills/plan/SKILL.md +62 -0
  144. package/skills/project-session-manager/SKILL.md +87 -4
  145. package/skills/project-session-manager/lib/config.sh +54 -5
  146. package/skills/project-session-manager/lib/parse.sh +65 -11
  147. package/skills/project-session-manager/lib/providers/github.sh +52 -0
  148. package/skills/project-session-manager/lib/providers/interface.sh +76 -0
  149. package/skills/project-session-manager/lib/providers/jira.sh +79 -0
  150. package/skills/project-session-manager/lib/session.sh +49 -12
  151. package/skills/project-session-manager/lib/worktree.sh +37 -4
  152. package/skills/project-session-manager/psm.sh +116 -51
  153. package/skills/ralph/SKILL.md +41 -27
  154. package/skills/ultrawork/SKILL.md +56 -66
  155. package/templates/hooks/keyword-detector.mjs +21 -13
  156. package/templates/hooks/lib/stdin.mjs +62 -0
  157. package/templates/hooks/persistent-mode.mjs +7 -8
  158. package/templates/hooks/post-tool-use.mjs +8 -10
  159. package/templates/hooks/pre-tool-use.mjs +9 -6
  160. 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
- git worktree remove "$worktree_path" --force 2>/dev/null || {
150
- # Force remove the directory if git worktree remove fails
151
- rm -rf "$worktree_path"
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
- if ! command -v gh &> /dev/null; then
42
- missing+=("gh (GitHub CLI)")
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 gh"
49
- log_info " macOS: brew install git jq gh"
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=$(gh pr view "$pr_number" --repo "$repo" --json number,title,author,headRefName,baseRefName,body,url 2>/dev/null) || {
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
- git clone "https://github.com/${repo}.git" "$local_path" || {
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=$(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
- )
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
- if [[ -z "$repo" ]]; then
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} from ${repo}..."
283
+ log_info "Fetching issue #${issue_number}..."
253
284
 
254
285
  # Fetch issue info
255
286
  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')
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
- git clone "https://github.com/${repo}.git" "$local_path" || return 1
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=$(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
- )
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 (use process substitution to avoid subshell)
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
- local pr_state=$(gh pr view "$pr_number" --repo "$repo" --json merged 2>/dev/null | jq -r '.merged')
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 (use process substitution to avoid subshell)
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 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++))
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)
@@ -76,7 +76,7 @@ Your workflow:
76
76
 
77
77
  ## ULTRAWORK MODE (AUTO-ACTIVATED)
78
78
 
79
- Ralph automatically activates Ultrawork for maximum parallel execution. You MUST follow these rules:
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
- | Domain | LOW (Haiku) | MEDIUM (Sonnet) | HIGH (Opus) |
97
- |--------|-------------|-----------------|-------------|
98
- | **Analysis** | `architect-low` | `architect-medium` | `architect` |
99
- | **Execution** | `executor-low` | `executor` | `executor-high` |
100
- | **Search** | `explore` | `explore-medium` | - |
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
- ## ARCHITECT VERIFICATION (MANDATORY)
157
+ ## VERIFICATION PROTOCOL (TIERED)
170
158
 
171
- When you believe the task is complete:
172
- 1. **First**, spawn Architect to verify your work (ALWAYS pass model explicitly!):
173
- ```
174
- Task(subagent_type="oh-my-claudecode:architect", model="opus", prompt="Verify this implementation is complete: [describe what you did]")
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
- 2. **Wait for Architect's assessment**
186
+ // STANDARD - most changes
187
+ Task(subagent_type="oh-my-claudecode:architect-medium", model="sonnet", prompt="Verify implementation: [describe changes]")
178
188
 
179
- 3. **If Architect approves**: Run `/oh-my-claudecode:cancel` to cleanly exit ralph mode
180
- 4. **If Architect finds issues**: Fix them, then repeat verification
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
- DO NOT exit without Architect verification.
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: Activate maximum performance mode with parallel agent orchestration for high-throughput task completion
3
+ description: Parallel execution engine for high-throughput task completion
4
4
  ---
5
5
 
6
6
  # Ultrawork Skill
7
7
 
8
- Activates maximum performance mode with parallel agent orchestration.
8
+ Parallel execution engine. This is a **COMPONENT**, not a standalone persistence mode.
9
9
 
10
- ## When Activated
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. **Aggressive Delegation**: Routing tasks to specialist agents immediately
16
- 3. **Background Operations**: Using `run_in_background: true` for long operations
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
- | Domain | LOW (Haiku) | MEDIUM (Sonnet) | HIGH (Opus) |
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
- ### Tier Selection Guide
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
- | Task Complexity | Tier | Examples |
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
- ### Routing Examples
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
- **CRITICAL: Always pass `model` parameter explicitly - Claude Code does NOT auto-apply models from agent definitions!**
29
+ ## Smart Model Routing
53
30
 
31
+ **FIRST ACTION:** Before delegating any work, read the agent reference file:
54
32
  ```
55
- // Simple question → LOW tier (saves tokens!)
56
- Task(subagent_type="oh-my-claudecode:architect-low", model="haiku", prompt="What does this function return?")
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
- // Quick file lookup LOW tier
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
- // Thorough search → MEDIUM tier
68
- Task(subagent_type="oh-my-claudecode:explore-medium", model="sonnet", prompt="Find all authentication patterns in the codebase")
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
- ## Verification Checklist
57
+ ## Relationship to Other Modes
85
58
 
86
- Before stopping, verify:
87
- - [ ] TODO LIST: Zero pending/in_progress tasks
88
- - [ ] FUNCTIONALITY: All requested features work
89
- - [ ] TESTS: All tests pass (if applicable)
90
- - [ ] ERRORS: Zero unaddressed errors
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
- **If ANY checkbox is unchecked, CONTINUE WORKING.**
68
+ ecomode (token efficiency)
69
+ └── modifies: ultrawork's model selection
70
+ ```
93
71
 
94
- ## STATE CLEANUP ON COMPLETION
72
+ ## When to Use Ultrawork Directly
95
73
 
96
- **IMPORTANT: Delete state files on completion - do NOT just set `active: false`**
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
- When all verification passes and work is complete:
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
- ```bash
101
- # Delete ultrawork state files
102
- rm -f .omc/state/ultrawork-state.json
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
- This ensures clean state for future sessions. Stale state files with `active: false` should not be left behind.
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
- // Remove code blocks to prevent false positives
77
- function removeCodeBlocks(text) {
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 = removeCodeBlocks(prompt).toLowerCase();
236
+ const cleanPrompt = sanitizeForKeywordDetection(prompt).toLowerCase();
229
237
 
230
238
  // Collect all matching keywords
231
239
  const matches = [];