oh-my-claude-sisyphus 3.8.15 → 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/README.md +9 -11
- 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 +1 -1
- package/commands/autopilot.md +2 -6
- package/commands/hud.md +7 -2
- package/commands/ralph.md +3 -3
- package/commands/ultrapilot.md +2 -6
- package/dist/__tests__/agent-registry.test.js +1 -1
- package/dist/__tests__/delegation-enforcement-levels.test.js +0 -1
- package/dist/__tests__/delegation-enforcement-levels.test.js.map +1 -1
- package/dist/__tests__/hooks/learner/parser.test.d.ts +5 -0
- package/dist/__tests__/hooks/learner/parser.test.d.ts.map +1 -0
- package/dist/__tests__/hooks/learner/parser.test.js +201 -0
- package/dist/__tests__/hooks/learner/parser.test.js.map +1 -0
- package/dist/__tests__/hud/cwd.test.d.ts +2 -0
- package/dist/__tests__/hud/cwd.test.d.ts.map +1 -0
- package/dist/__tests__/hud/cwd.test.js +62 -0
- package/dist/__tests__/hud/cwd.test.js.map +1 -0
- package/dist/__tests__/hud/defaults.test.d.ts +2 -0
- package/dist/__tests__/hud/defaults.test.d.ts.map +1 -0
- package/dist/__tests__/hud/defaults.test.js +21 -0
- package/dist/__tests__/hud/defaults.test.js.map +1 -0
- package/dist/__tests__/hud/render.test.d.ts +2 -0
- package/dist/__tests__/hud/render.test.d.ts.map +1 -0
- package/dist/__tests__/hud/render.test.js +141 -0
- package/dist/__tests__/hud/render.test.js.map +1 -0
- package/dist/__tests__/hud/thinking.test.d.ts +2 -0
- package/dist/__tests__/hud/thinking.test.d.ts.map +1 -0
- package/dist/__tests__/hud/thinking.test.js +32 -0
- package/dist/__tests__/hud/thinking.test.js.map +1 -0
- package/dist/__tests__/installer.test.js +8 -8
- package/dist/__tests__/installer.test.js.map +1 -1
- package/dist/__tests__/mnemosyne/parser.test.js +1 -1
- package/dist/__tests__/mnemosyne/parser.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/features/continuation-enforcement.js +1 -1
- package/dist/features/state-manager/index.d.ts.map +1 -1
- package/dist/features/state-manager/index.js +7 -4
- package/dist/features/state-manager/index.js.map +1 -1
- package/dist/features/verification/example.d.ts.map +1 -1
- package/dist/features/verification/example.js +4 -2
- package/dist/features/verification/example.js.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 +80 -47
- package/dist/hooks/bridge.js.map +1 -1
- package/dist/hooks/index.d.ts +2 -1
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +4 -1
- package/dist/hooks/index.js.map +1 -1
- package/dist/hooks/learner/parser.d.ts.map +1 -1
- package/dist/hooks/learner/parser.js +12 -5
- package/dist/hooks/learner/parser.js.map +1 -1
- package/dist/hooks/mode-registry/index.d.ts +2 -0
- package/dist/hooks/mode-registry/index.d.ts.map +1 -1
- package/dist/hooks/mode-registry/index.js +8 -19
- package/dist/hooks/mode-registry/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/persistent-mode/index.d.ts +1 -1
- package/dist/hooks/persistent-mode/index.d.ts.map +1 -1
- package/dist/hooks/persistent-mode/index.js +5 -33
- package/dist/hooks/persistent-mode/index.js.map +1 -1
- package/dist/hooks/ralph/index.d.ts +1 -1
- package/dist/hooks/ralph/index.d.ts.map +1 -1
- package/dist/hooks/ralph/index.js +1 -1
- package/dist/hooks/ralph/index.js.map +1 -1
- package/dist/hooks/ralph/loop.d.ts +1 -9
- package/dist/hooks/ralph/loop.d.ts.map +1 -1
- package/dist/hooks/ralph/loop.js +1 -37
- package/dist/hooks/ralph/loop.js.map +1 -1
- package/dist/hooks/ralph/prd.js +1 -1
- package/dist/hooks/ralph/verifier.d.ts +4 -5
- package/dist/hooks/ralph/verifier.d.ts.map +1 -1
- package/dist/hooks/ralph/verifier.js +7 -10
- package/dist/hooks/ralph/verifier.js.map +1 -1
- package/dist/hooks/session-end/index.d.ts +13 -0
- package/dist/hooks/session-end/index.d.ts.map +1 -1
- package/dist/hooks/session-end/index.js +69 -0
- package/dist/hooks/session-end/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/hooks/ultrawork/index.d.ts +2 -2
- package/dist/hooks/ultrawork/index.d.ts.map +1 -1
- package/dist/hooks/ultrawork/index.js +2 -46
- package/dist/hooks/ultrawork/index.js.map +1 -1
- package/dist/hud/elements/cwd.d.ts +15 -0
- package/dist/hud/elements/cwd.d.ts.map +1 -0
- package/dist/hud/elements/cwd.js +39 -0
- package/dist/hud/elements/cwd.js.map +1 -0
- package/dist/hud/elements/index.d.ts +1 -0
- package/dist/hud/elements/index.d.ts.map +1 -1
- package/dist/hud/elements/index.js +1 -0
- package/dist/hud/elements/index.js.map +1 -1
- package/dist/hud/elements/thinking.d.ts +7 -5
- package/dist/hud/elements/thinking.d.ts.map +1 -1
- package/dist/hud/elements/thinking.js +18 -6
- package/dist/hud/elements/thinking.js.map +1 -1
- package/dist/hud/index.js +5 -3
- package/dist/hud/index.js.map +1 -1
- package/dist/hud/omc-state.d.ts +1 -1
- package/dist/hud/omc-state.d.ts.map +1 -1
- package/dist/hud/omc-state.js +14 -31
- package/dist/hud/omc-state.js.map +1 -1
- package/dist/hud/render.d.ts +9 -0
- package/dist/hud/render.d.ts.map +1 -1
- package/dist/hud/render.js +27 -7
- package/dist/hud/render.js.map +1 -1
- package/dist/hud/state.d.ts +2 -2
- package/dist/hud/state.d.ts.map +1 -1
- package/dist/hud/state.js +4 -33
- package/dist/hud/state.js.map +1 -1
- package/dist/hud/transcript.d.ts +4 -1
- package/dist/hud/transcript.d.ts.map +1 -1
- package/dist/hud/transcript.js +4 -9
- package/dist/hud/transcript.js.map +1 -1
- package/dist/hud/types.d.ts +20 -1
- package/dist/hud/types.d.ts.map +1 -1
- package/dist/hud/types.js +38 -9
- package/dist/hud/types.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 +1 -1
- package/dist/installer/hooks.d.ts.map +1 -1
- package/dist/installer/hooks.js +4 -2
- 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 +100 -0
- package/docs/ARCHITECTURE.md +11 -7
- package/docs/CLAUDE.md +89 -379
- package/docs/DELEGATION-ENFORCER.md +1 -2
- package/docs/MIGRATION.md +1 -1
- package/docs/REFERENCE.md +29 -9
- package/docs/SYNC-SYSTEM.md +0 -2
- 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/scripts/persistent-mode.mjs +78 -47
- package/scripts/test-mutual-exclusion.ts +3 -3
- package/skills/AGENTS.md +59 -44
- package/skills/autopilot/SKILL.md +0 -2
- package/skills/cancel/SKILL.md +13 -32
- package/skills/deep-executor/SKILL.md +50 -0
- package/skills/ecomode/SKILL.md +58 -104
- package/skills/hud/SKILL.md +3 -2
- 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 +48 -44
- package/skills/ultrawork/SKILL.md +56 -67
- package/templates/hooks/keyword-detector.mjs +21 -13
- package/templates/hooks/lib/stdin.mjs +62 -0
- package/templates/hooks/persistent-mode.mjs +75 -34
- 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
- package/agents/AGENTS.md +0 -144
|
@@ -146,23 +146,81 @@ mkdir -p .claude && echo ".claude directory ready"
|
|
|
146
146
|
### Download Fresh CLAUDE.md
|
|
147
147
|
|
|
148
148
|
```bash
|
|
149
|
+
# Define target path
|
|
150
|
+
TARGET_PATH=".claude/CLAUDE.md"
|
|
151
|
+
|
|
149
152
|
# Extract old version before download
|
|
150
|
-
OLD_VERSION=$(grep -m1 "^# oh-my-claudecode"
|
|
153
|
+
OLD_VERSION=$(grep -m1 "^# oh-my-claudecode" "$TARGET_PATH" 2>/dev/null | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' || echo "none")
|
|
151
154
|
|
|
152
|
-
# Backup existing
|
|
153
|
-
if [ -f "
|
|
154
|
-
BACKUP_DATE=$(date +%Y-%m-%
|
|
155
|
-
BACKUP_PATH=".
|
|
156
|
-
cp
|
|
155
|
+
# Backup existing
|
|
156
|
+
if [ -f "$TARGET_PATH" ]; then
|
|
157
|
+
BACKUP_DATE=$(date +%Y-%m-%d_%H%M%S)
|
|
158
|
+
BACKUP_PATH="${TARGET_PATH}.backup.${BACKUP_DATE}"
|
|
159
|
+
cp "$TARGET_PATH" "$BACKUP_PATH"
|
|
157
160
|
echo "Backed up existing CLAUDE.md to $BACKUP_PATH"
|
|
158
161
|
fi
|
|
159
162
|
|
|
160
|
-
# Download fresh
|
|
161
|
-
|
|
162
|
-
|
|
163
|
+
# Download fresh OMC content to temp file
|
|
164
|
+
TEMP_OMC=$(mktemp /tmp/omc-claude-XXXXXX.md)
|
|
165
|
+
trap 'rm -f "$TEMP_OMC"' EXIT
|
|
166
|
+
curl -fsSL "https://raw.githubusercontent.com/Yeachan-Heo/oh-my-claudecode/main/docs/CLAUDE.md" -o "$TEMP_OMC"
|
|
167
|
+
|
|
168
|
+
if [ ! -s "$TEMP_OMC" ]; then
|
|
169
|
+
echo "ERROR: Failed to download CLAUDE.md. Aborting."
|
|
170
|
+
rm -f "$TEMP_OMC"
|
|
171
|
+
return 1
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
# Strip existing markers from downloaded content (idempotency)
|
|
175
|
+
if grep -q '<!-- OMC:START -->' "$TEMP_OMC"; then
|
|
176
|
+
# Extract content between markers
|
|
177
|
+
sed -n '/<!-- OMC:START -->/,/<!-- OMC:END -->/{//!p}' "$TEMP_OMC" > "${TEMP_OMC}.clean"
|
|
178
|
+
mv "${TEMP_OMC}.clean" "$TEMP_OMC"
|
|
179
|
+
fi
|
|
180
|
+
|
|
181
|
+
if [ ! -f "$TARGET_PATH" ]; then
|
|
182
|
+
# Fresh install: wrap in markers
|
|
183
|
+
{
|
|
184
|
+
echo '<!-- OMC:START -->'
|
|
185
|
+
cat "$TEMP_OMC"
|
|
186
|
+
echo '<!-- OMC:END -->'
|
|
187
|
+
} > "$TARGET_PATH"
|
|
188
|
+
rm -f "$TEMP_OMC"
|
|
189
|
+
echo "Installed CLAUDE.md (fresh)"
|
|
190
|
+
else
|
|
191
|
+
# Merge: preserve user content outside OMC markers
|
|
192
|
+
if grep -q '<!-- OMC:START -->' "$TARGET_PATH"; then
|
|
193
|
+
# Has markers: replace OMC section, keep user content
|
|
194
|
+
BEFORE_OMC=$(sed -n '1,/<!-- OMC:START -->/{ /<!-- OMC:START -->/!p }' "$TARGET_PATH")
|
|
195
|
+
AFTER_OMC=$(sed -n '/<!-- OMC:END -->/,${ /<!-- OMC:END -->/!p }' "$TARGET_PATH")
|
|
196
|
+
{
|
|
197
|
+
[ -n "$BEFORE_OMC" ] && printf '%s\n' "$BEFORE_OMC"
|
|
198
|
+
echo '<!-- OMC:START -->'
|
|
199
|
+
cat "$TEMP_OMC"
|
|
200
|
+
echo '<!-- OMC:END -->'
|
|
201
|
+
[ -n "$AFTER_OMC" ] && printf '%s\n' "$AFTER_OMC"
|
|
202
|
+
} > "${TARGET_PATH}.tmp"
|
|
203
|
+
mv "${TARGET_PATH}.tmp" "$TARGET_PATH"
|
|
204
|
+
echo "Updated OMC section (user customizations preserved)"
|
|
205
|
+
else
|
|
206
|
+
# No markers: wrap new content in markers, append old content as user section
|
|
207
|
+
OLD_CONTENT=$(cat "$TARGET_PATH")
|
|
208
|
+
{
|
|
209
|
+
echo '<!-- OMC:START -->'
|
|
210
|
+
cat "$TEMP_OMC"
|
|
211
|
+
echo '<!-- OMC:END -->'
|
|
212
|
+
echo ""
|
|
213
|
+
echo "<!-- User customizations (migrated from previous CLAUDE.md) -->"
|
|
214
|
+
printf '%s\n' "$OLD_CONTENT"
|
|
215
|
+
} > "${TARGET_PATH}.tmp"
|
|
216
|
+
mv "${TARGET_PATH}.tmp" "$TARGET_PATH"
|
|
217
|
+
echo "Migrated existing CLAUDE.md (added OMC markers, preserved old content)"
|
|
218
|
+
fi
|
|
219
|
+
rm -f "$TEMP_OMC"
|
|
220
|
+
fi
|
|
163
221
|
|
|
164
222
|
# Extract new version and report
|
|
165
|
-
NEW_VERSION=$(grep -m1 "^# oh-my-claudecode"
|
|
223
|
+
NEW_VERSION=$(grep -m1 "^# oh-my-claudecode" "$TARGET_PATH" 2>/dev/null | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' || echo "unknown")
|
|
166
224
|
if [ "$OLD_VERSION" = "none" ]; then
|
|
167
225
|
echo "Installed CLAUDE.md: $NEW_VERSION"
|
|
168
226
|
elif [ "$OLD_VERSION" = "$NEW_VERSION" ]; then
|
|
@@ -227,23 +285,81 @@ Do not continue to HUD setup or other steps.
|
|
|
227
285
|
### Download Fresh CLAUDE.md
|
|
228
286
|
|
|
229
287
|
```bash
|
|
288
|
+
# Define target path
|
|
289
|
+
TARGET_PATH="$HOME/.claude/CLAUDE.md"
|
|
290
|
+
|
|
230
291
|
# Extract old version before download
|
|
231
|
-
OLD_VERSION=$(grep -m1 "^# oh-my-claudecode"
|
|
292
|
+
OLD_VERSION=$(grep -m1 "^# oh-my-claudecode" "$TARGET_PATH" 2>/dev/null | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' || echo "none")
|
|
232
293
|
|
|
233
|
-
# Backup existing
|
|
234
|
-
if [ -f "$
|
|
235
|
-
BACKUP_DATE=$(date +%Y-%m-%
|
|
236
|
-
BACKUP_PATH="$
|
|
237
|
-
cp "$
|
|
294
|
+
# Backup existing
|
|
295
|
+
if [ -f "$TARGET_PATH" ]; then
|
|
296
|
+
BACKUP_DATE=$(date +%Y-%m-%d_%H%M%S)
|
|
297
|
+
BACKUP_PATH="${TARGET_PATH}.backup.${BACKUP_DATE}"
|
|
298
|
+
cp "$TARGET_PATH" "$BACKUP_PATH"
|
|
238
299
|
echo "Backed up existing CLAUDE.md to $BACKUP_PATH"
|
|
239
300
|
fi
|
|
240
301
|
|
|
241
|
-
# Download fresh
|
|
242
|
-
|
|
243
|
-
|
|
302
|
+
# Download fresh OMC content to temp file
|
|
303
|
+
TEMP_OMC=$(mktemp /tmp/omc-claude-XXXXXX.md)
|
|
304
|
+
trap 'rm -f "$TEMP_OMC"' EXIT
|
|
305
|
+
curl -fsSL "https://raw.githubusercontent.com/Yeachan-Heo/oh-my-claudecode/main/docs/CLAUDE.md" -o "$TEMP_OMC"
|
|
306
|
+
|
|
307
|
+
if [ ! -s "$TEMP_OMC" ]; then
|
|
308
|
+
echo "ERROR: Failed to download CLAUDE.md. Aborting."
|
|
309
|
+
rm -f "$TEMP_OMC"
|
|
310
|
+
return 1
|
|
311
|
+
fi
|
|
312
|
+
|
|
313
|
+
# Strip existing markers from downloaded content (idempotency)
|
|
314
|
+
if grep -q '<!-- OMC:START -->' "$TEMP_OMC"; then
|
|
315
|
+
# Extract content between markers
|
|
316
|
+
sed -n '/<!-- OMC:START -->/,/<!-- OMC:END -->/{//!p}' "$TEMP_OMC" > "${TEMP_OMC}.clean"
|
|
317
|
+
mv "${TEMP_OMC}.clean" "$TEMP_OMC"
|
|
318
|
+
fi
|
|
319
|
+
|
|
320
|
+
if [ ! -f "$TARGET_PATH" ]; then
|
|
321
|
+
# Fresh install: wrap in markers
|
|
322
|
+
{
|
|
323
|
+
echo '<!-- OMC:START -->'
|
|
324
|
+
cat "$TEMP_OMC"
|
|
325
|
+
echo '<!-- OMC:END -->'
|
|
326
|
+
} > "$TARGET_PATH"
|
|
327
|
+
rm -f "$TEMP_OMC"
|
|
328
|
+
echo "Installed CLAUDE.md (fresh)"
|
|
329
|
+
else
|
|
330
|
+
# Merge: preserve user content outside OMC markers
|
|
331
|
+
if grep -q '<!-- OMC:START -->' "$TARGET_PATH"; then
|
|
332
|
+
# Has markers: replace OMC section, keep user content
|
|
333
|
+
BEFORE_OMC=$(sed -n '1,/<!-- OMC:START -->/{ /<!-- OMC:START -->/!p }' "$TARGET_PATH")
|
|
334
|
+
AFTER_OMC=$(sed -n '/<!-- OMC:END -->/,${ /<!-- OMC:END -->/!p }' "$TARGET_PATH")
|
|
335
|
+
{
|
|
336
|
+
[ -n "$BEFORE_OMC" ] && printf '%s\n' "$BEFORE_OMC"
|
|
337
|
+
echo '<!-- OMC:START -->'
|
|
338
|
+
cat "$TEMP_OMC"
|
|
339
|
+
echo '<!-- OMC:END -->'
|
|
340
|
+
[ -n "$AFTER_OMC" ] && printf '%s\n' "$AFTER_OMC"
|
|
341
|
+
} > "${TARGET_PATH}.tmp"
|
|
342
|
+
mv "${TARGET_PATH}.tmp" "$TARGET_PATH"
|
|
343
|
+
echo "Updated OMC section (user customizations preserved)"
|
|
344
|
+
else
|
|
345
|
+
# No markers: wrap new content in markers, append old content as user section
|
|
346
|
+
OLD_CONTENT=$(cat "$TARGET_PATH")
|
|
347
|
+
{
|
|
348
|
+
echo '<!-- OMC:START -->'
|
|
349
|
+
cat "$TEMP_OMC"
|
|
350
|
+
echo '<!-- OMC:END -->'
|
|
351
|
+
echo ""
|
|
352
|
+
echo "<!-- User customizations (migrated from previous CLAUDE.md) -->"
|
|
353
|
+
printf '%s\n' "$OLD_CONTENT"
|
|
354
|
+
} > "${TARGET_PATH}.tmp"
|
|
355
|
+
mv "${TARGET_PATH}.tmp" "$TARGET_PATH"
|
|
356
|
+
echo "Migrated existing CLAUDE.md (added OMC markers, preserved old content)"
|
|
357
|
+
fi
|
|
358
|
+
rm -f "$TEMP_OMC"
|
|
359
|
+
fi
|
|
244
360
|
|
|
245
361
|
# Extract new version and report
|
|
246
|
-
NEW_VERSION=$(grep -m1 "^# oh-my-claudecode"
|
|
362
|
+
NEW_VERSION=$(grep -m1 "^# oh-my-claudecode" "$TARGET_PATH" 2>/dev/null | grep -oE 'v[0-9]+\.[0-9]+\.[0-9]+' || echo "unknown")
|
|
247
363
|
if [ "$OLD_VERSION" = "none" ]; then
|
|
248
364
|
echo "Installed CLAUDE.md: $NEW_VERSION"
|
|
249
365
|
elif [ "$OLD_VERSION" = "$NEW_VERSION" ]; then
|
|
@@ -456,6 +572,67 @@ All functionality is available through the plugin system:
|
|
|
456
572
|
|
|
457
573
|
Skip this step - the plugin provides all features.
|
|
458
574
|
|
|
575
|
+
## Step 3.8.5: Select Task Management Tool
|
|
576
|
+
|
|
577
|
+
First, detect available task tools:
|
|
578
|
+
|
|
579
|
+
```bash
|
|
580
|
+
# Detect beads (bd)
|
|
581
|
+
BD_VERSION=""
|
|
582
|
+
if command -v bd &>/dev/null; then
|
|
583
|
+
BD_VERSION=$(bd --version 2>/dev/null | head -1 || echo "installed")
|
|
584
|
+
fi
|
|
585
|
+
|
|
586
|
+
# Detect beads-rust (br)
|
|
587
|
+
BR_VERSION=""
|
|
588
|
+
if command -v br &>/dev/null; then
|
|
589
|
+
BR_VERSION=$(br --version 2>/dev/null | head -1 || echo "installed")
|
|
590
|
+
fi
|
|
591
|
+
|
|
592
|
+
# Report findings
|
|
593
|
+
if [ -n "$BD_VERSION" ]; then
|
|
594
|
+
echo "Found beads (bd): $BD_VERSION"
|
|
595
|
+
fi
|
|
596
|
+
if [ -n "$BR_VERSION" ]; then
|
|
597
|
+
echo "Found beads-rust (br): $BR_VERSION"
|
|
598
|
+
fi
|
|
599
|
+
if [ -z "$BD_VERSION" ] && [ -z "$BR_VERSION" ]; then
|
|
600
|
+
echo "No external task tools found. Using built-in Tasks."
|
|
601
|
+
fi
|
|
602
|
+
```
|
|
603
|
+
|
|
604
|
+
If **neither** beads nor beads-rust is detected, skip this step (default to built-in).
|
|
605
|
+
|
|
606
|
+
If beads or beads-rust is detected, use AskUserQuestion:
|
|
607
|
+
|
|
608
|
+
**Question:** "Which task management tool should I use for tracking work?"
|
|
609
|
+
|
|
610
|
+
**Options:**
|
|
611
|
+
1. **Built-in Tasks (default)** - Use Claude Code's native TaskCreate/TodoWrite. Tasks are session-only.
|
|
612
|
+
2. **Beads (bd)** - Git-backed persistent tasks. Survives across sessions. [Only if detected]
|
|
613
|
+
3. **Beads-Rust (br)** - Lightweight Rust port of beads. [Only if detected]
|
|
614
|
+
|
|
615
|
+
(Only show options 2/3 if the corresponding tool is detected)
|
|
616
|
+
|
|
617
|
+
Store the preference:
|
|
618
|
+
|
|
619
|
+
```bash
|
|
620
|
+
CONFIG_FILE="$HOME/.claude/.omc-config.json"
|
|
621
|
+
mkdir -p "$(dirname "$CONFIG_FILE")"
|
|
622
|
+
|
|
623
|
+
if [ -f "$CONFIG_FILE" ]; then
|
|
624
|
+
EXISTING=$(cat "$CONFIG_FILE")
|
|
625
|
+
else
|
|
626
|
+
EXISTING='{}'
|
|
627
|
+
fi
|
|
628
|
+
|
|
629
|
+
# USER_CHOICE is "builtin", "beads", or "beads-rust" based on user selection
|
|
630
|
+
echo "$EXISTING" | jq --arg tool "USER_CHOICE" '. + {taskTool: $tool, taskToolConfig: {injectInstructions: true, useMcp: false}}' > "$CONFIG_FILE"
|
|
631
|
+
echo "Task tool set to: USER_CHOICE"
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
**Note:** The beads context instructions will be injected automatically on the next session start. No restart is needed for config to take effect.
|
|
635
|
+
|
|
459
636
|
## Step 4: Verify Plugin Installation
|
|
460
637
|
|
|
461
638
|
```bash
|
package/skills/plan/SKILL.md
CHANGED
|
@@ -17,6 +17,20 @@ You guide users through planning by:
|
|
|
17
17
|
|
|
18
18
|
## Planning Modes
|
|
19
19
|
|
|
20
|
+
| Mode | Trigger | Behavior |
|
|
21
|
+
|------|---------|----------|
|
|
22
|
+
| interview | Default | Interactive requirements gathering with adaptive exploration |
|
|
23
|
+
| direct | --direct, detailed request | Skip interview, generate plan directly |
|
|
24
|
+
| consensus | --consensus, "ralplan" | Planner → Architect → Critic loop until consensus |
|
|
25
|
+
| review | --review | Critic review of existing plan |
|
|
26
|
+
|
|
27
|
+
### Review Mode
|
|
28
|
+
|
|
29
|
+
When `--review` is specified or user says "review this plan":
|
|
30
|
+
1. Read the plan file from `.omc/plans/`
|
|
31
|
+
2. Spawn Critic agent to review
|
|
32
|
+
3. Return verdict (OKAY or REJECT with improvements)
|
|
33
|
+
|
|
20
34
|
### Auto-Detection: Interview vs Direct Planning
|
|
21
35
|
|
|
22
36
|
**Interview Mode** (when request is BROAD):
|
|
@@ -53,6 +67,54 @@ Ask clarifying questions about: Goals, Constraints, Context, Risks, Preferences
|
|
|
53
67
|
|
|
54
68
|
**When plain text is OK:** Questions needing specific values (port numbers, names) or follow-up clarifications.
|
|
55
69
|
|
|
70
|
+
## Adaptive Context Gathering (CRITICAL)
|
|
71
|
+
|
|
72
|
+
Before asking ANY question, classify it:
|
|
73
|
+
|
|
74
|
+
### Question Classification
|
|
75
|
+
|
|
76
|
+
| Type | Examples | Action |
|
|
77
|
+
|------|----------|--------|
|
|
78
|
+
| **Codebase Fact** | "What patterns exist?", "Where is X implemented?" | Explore first, DON'T ask user |
|
|
79
|
+
| **User Preference** | "Priority?", "Timeline?", "Risk tolerance?" | Ask user via AskUserQuestion |
|
|
80
|
+
| **Scope Decision** | "Include feature Y?" | Ask user |
|
|
81
|
+
| **Requirement** | "Performance constraints?" | Ask user |
|
|
82
|
+
|
|
83
|
+
### Adaptive Flow
|
|
84
|
+
|
|
85
|
+
1. Generate interview question
|
|
86
|
+
2. Classify: Is this a codebase fact or user preference?
|
|
87
|
+
3. If **CODEBASE FACT**:
|
|
88
|
+
a. Spawn `explore` agent (haiku, 30s timeout)
|
|
89
|
+
b. Query: focused on the specific fact needed
|
|
90
|
+
c. Use findings to inform next question or skip question entirely
|
|
91
|
+
4. If **USER PREFERENCE**:
|
|
92
|
+
a. Use AskUserQuestion tool with options
|
|
93
|
+
b. Wait for response
|
|
94
|
+
5. Repeat for next question
|
|
95
|
+
|
|
96
|
+
### Exploration Integration
|
|
97
|
+
|
|
98
|
+
When context is gathered via explore agent:
|
|
99
|
+
- **DO NOT** ask "What patterns does the codebase use?"
|
|
100
|
+
- **DO** say "I see the codebase uses [pattern X]. Would you like to follow this pattern or try something different?"
|
|
101
|
+
|
|
102
|
+
### Example Adaptive Interview
|
|
103
|
+
|
|
104
|
+
**Without Adaptive (BAD):**
|
|
105
|
+
```
|
|
106
|
+
Planner: "Where is authentication implemented in your codebase?"
|
|
107
|
+
User: "Uh, somewhere in src/auth I think?"
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
**With Adaptive (GOOD):**
|
|
111
|
+
```
|
|
112
|
+
Planner: [spawns explore agent: "find authentication implementation"]
|
|
113
|
+
Planner: [receives: "Auth is in src/auth/ using JWT with passport.js"]
|
|
114
|
+
Planner: "I see you're using JWT authentication with passport.js in src/auth/.
|
|
115
|
+
For this new feature, should we extend the existing auth or add a separate auth flow?"
|
|
116
|
+
```
|
|
117
|
+
|
|
56
118
|
**MANDATORY: Single Question at a Time**
|
|
57
119
|
|
|
58
120
|
**Core Rule:** Never ask multiple questions in one message during interview mode.
|
|
@@ -49,6 +49,85 @@ Supported formats:
|
|
|
49
49
|
}
|
|
50
50
|
```
|
|
51
51
|
|
|
52
|
+
## Providers
|
|
53
|
+
|
|
54
|
+
PSM supports multiple issue tracking providers:
|
|
55
|
+
|
|
56
|
+
| Provider | CLI Required | Reference Formats | Commands |
|
|
57
|
+
|----------|--------------|-------------------|----------|
|
|
58
|
+
| GitHub (default) | `gh` | `owner/repo#123`, `alias#123`, GitHub URLs | review, fix, feature |
|
|
59
|
+
| Jira | `jira` | `PROJ-123` (if PROJ configured), `alias#123` | fix, feature |
|
|
60
|
+
|
|
61
|
+
### Jira Configuration
|
|
62
|
+
|
|
63
|
+
To use Jira, add an alias with `jira_project` and `provider: "jira"`:
|
|
64
|
+
|
|
65
|
+
```json
|
|
66
|
+
{
|
|
67
|
+
"aliases": {
|
|
68
|
+
"mywork": {
|
|
69
|
+
"jira_project": "MYPROJ",
|
|
70
|
+
"repo": "mycompany/my-project",
|
|
71
|
+
"local": "~/Workspace/my-project",
|
|
72
|
+
"default_base": "develop",
|
|
73
|
+
"provider": "jira"
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Important:** The `repo` field is still required for cloning the git repository. Jira tracks issues, but you work in a git repo.
|
|
80
|
+
|
|
81
|
+
For non-GitHub repos, use `clone_url` instead:
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"aliases": {
|
|
85
|
+
"private": {
|
|
86
|
+
"jira_project": "PRIV",
|
|
87
|
+
"clone_url": "git@gitlab.internal:team/repo.git",
|
|
88
|
+
"local": "~/Workspace/repo",
|
|
89
|
+
"provider": "jira"
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Jira Reference Detection
|
|
96
|
+
|
|
97
|
+
PSM only recognizes `PROJ-123` format as Jira when `PROJ` is explicitly configured as a `jira_project` in your aliases. This prevents false positives from branch names like `FIX-123`.
|
|
98
|
+
|
|
99
|
+
### Jira Examples
|
|
100
|
+
|
|
101
|
+
```bash
|
|
102
|
+
# Fix a Jira issue (MYPROJ must be configured)
|
|
103
|
+
psm fix MYPROJ-123
|
|
104
|
+
|
|
105
|
+
# Fix using alias (recommended)
|
|
106
|
+
psm fix mywork#123
|
|
107
|
+
|
|
108
|
+
# Feature development (works same as GitHub)
|
|
109
|
+
psm feature mywork add-webhooks
|
|
110
|
+
|
|
111
|
+
# Note: 'psm review' is not supported for Jira (no PR concept)
|
|
112
|
+
# Use 'psm fix' for Jira issues
|
|
113
|
+
```
|
|
114
|
+
|
|
115
|
+
### Jira CLI Setup
|
|
116
|
+
|
|
117
|
+
Install the Jira CLI:
|
|
118
|
+
```bash
|
|
119
|
+
# macOS
|
|
120
|
+
brew install ankitpokhrel/jira-cli/jira-cli
|
|
121
|
+
|
|
122
|
+
# Linux
|
|
123
|
+
# See: https://github.com/ankitpokhrel/jira-cli#installation
|
|
124
|
+
|
|
125
|
+
# Configure (interactive)
|
|
126
|
+
jira init
|
|
127
|
+
```
|
|
128
|
+
|
|
129
|
+
The Jira CLI handles authentication separately from PSM.
|
|
130
|
+
|
|
52
131
|
## Directory Structure
|
|
53
132
|
|
|
54
133
|
```
|
|
@@ -371,10 +450,14 @@ Parse `{{ARGUMENTS}}` to determine:
|
|
|
371
450
|
|
|
372
451
|
## Requirements
|
|
373
452
|
|
|
374
|
-
|
|
375
|
-
- `
|
|
376
|
-
- `
|
|
377
|
-
- `
|
|
453
|
+
Required:
|
|
454
|
+
- `git` - Version control (with worktree support v2.5+)
|
|
455
|
+
- `jq` - JSON parsing
|
|
456
|
+
- `tmux` - Session management (optional, but recommended)
|
|
457
|
+
|
|
458
|
+
Optional (per provider):
|
|
459
|
+
- `gh` - GitHub CLI (for GitHub workflows)
|
|
460
|
+
- `jira` - Jira CLI (for Jira workflows)
|
|
378
461
|
|
|
379
462
|
## Initialization
|
|
380
463
|
|
|
@@ -48,11 +48,12 @@ psm_get_project() {
|
|
|
48
48
|
return 1
|
|
49
49
|
fi
|
|
50
50
|
|
|
51
|
-
local repo=$(jq -r ".aliases[
|
|
52
|
-
local local_path=$(jq -r ".aliases[
|
|
53
|
-
local default_base=$(jq -r ".aliases[
|
|
51
|
+
local repo=$(jq -r --arg a "$alias" '.aliases[$a].repo // empty' "$PSM_PROJECTS")
|
|
52
|
+
local local_path=$(jq -r --arg a "$alias" '.aliases[$a].local // empty' "$PSM_PROJECTS")
|
|
53
|
+
local default_base=$(jq -r --arg a "$alias" '.aliases[$a].default_base // "main"' "$PSM_PROJECTS")
|
|
54
54
|
|
|
55
|
-
|
|
55
|
+
local clone_url=$(jq -r --arg a "$alias" '.aliases[$a].clone_url // empty' "$PSM_PROJECTS")
|
|
56
|
+
if [[ -z "$repo" && -z "$clone_url" ]]; then
|
|
56
57
|
return 1
|
|
57
58
|
fi
|
|
58
59
|
|
|
@@ -62,6 +63,53 @@ psm_get_project() {
|
|
|
62
63
|
echo "${repo}|${local_path}|${default_base}"
|
|
63
64
|
}
|
|
64
65
|
|
|
66
|
+
# Get provider for a project alias
|
|
67
|
+
# Usage: psm_get_project_provider "mywork"
|
|
68
|
+
# Returns: "github" | "jira" | empty (defaults to github)
|
|
69
|
+
psm_get_project_provider() {
|
|
70
|
+
local alias="$1"
|
|
71
|
+
if [[ ! -f "$PSM_PROJECTS" ]]; then
|
|
72
|
+
echo "github"
|
|
73
|
+
return
|
|
74
|
+
fi
|
|
75
|
+
local provider
|
|
76
|
+
provider=$(jq -r --arg a "$alias" '.aliases[$a].provider // "github"' "$PSM_PROJECTS")
|
|
77
|
+
echo "$provider"
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
# Get Jira project key for alias
|
|
81
|
+
# Usage: psm_get_project_jira_project "mywork"
|
|
82
|
+
# Returns: "MYPROJ" or empty
|
|
83
|
+
psm_get_project_jira_project() {
|
|
84
|
+
local alias="$1"
|
|
85
|
+
if [[ ! -f "$PSM_PROJECTS" ]]; then
|
|
86
|
+
return
|
|
87
|
+
fi
|
|
88
|
+
jq -r --arg a "$alias" '.aliases[$a].jira_project // empty' "$PSM_PROJECTS"
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
# Get explicit clone_url for alias (for non-GitHub repos)
|
|
92
|
+
# Usage: psm_get_project_clone_url "mywork"
|
|
93
|
+
# Returns: URL or empty
|
|
94
|
+
psm_get_project_clone_url() {
|
|
95
|
+
local alias="$1"
|
|
96
|
+
if [[ ! -f "$PSM_PROJECTS" ]]; then
|
|
97
|
+
return
|
|
98
|
+
fi
|
|
99
|
+
jq -r --arg a "$alias" '.aliases[$a].clone_url // empty' "$PSM_PROJECTS"
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
# Get repo field for alias
|
|
103
|
+
# Usage: psm_get_project_repo "mywork"
|
|
104
|
+
# Returns: "owner/repo" or empty
|
|
105
|
+
psm_get_project_repo() {
|
|
106
|
+
local alias="$1"
|
|
107
|
+
if [[ ! -f "$PSM_PROJECTS" ]]; then
|
|
108
|
+
return
|
|
109
|
+
fi
|
|
110
|
+
jq -r --arg a "$alias" '.aliases[$a].repo // empty' "$PSM_PROJECTS"
|
|
111
|
+
}
|
|
112
|
+
|
|
65
113
|
# Add or update project alias
|
|
66
114
|
psm_set_project() {
|
|
67
115
|
local alias="$1"
|
|
@@ -70,7 +118,8 @@ psm_set_project() {
|
|
|
70
118
|
local default_base="${4:-main}"
|
|
71
119
|
|
|
72
120
|
local tmp=$(mktemp)
|
|
73
|
-
jq "
|
|
121
|
+
jq --arg a "$alias" --arg r "$repo" --arg l "$local_path" --arg b "$default_base" \
|
|
122
|
+
'.aliases[$a] = {"repo": $r, "local": $l, "default_base": $b}' \
|
|
74
123
|
"$PSM_PROJECTS" > "$tmp" && mv "$tmp" "$PSM_PROJECTS"
|
|
75
124
|
}
|
|
76
125
|
|
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
# #123 -> number=123 (use current repo)
|
|
10
10
|
#
|
|
11
11
|
# Usage: psm_parse_ref "omc#123"
|
|
12
|
-
# Returns: type|alias|repo|number|local_path|base
|
|
12
|
+
# Returns: type|alias|repo|number|local_path|base|provider|provider_ref
|
|
13
13
|
psm_parse_ref() {
|
|
14
14
|
local ref="$1"
|
|
15
15
|
local type=""
|
|
@@ -29,7 +29,7 @@ psm_parse_ref() {
|
|
|
29
29
|
if [[ -n "$alias" ]]; then
|
|
30
30
|
IFS='|' read -r _ local_path base <<< "$(psm_get_project "$alias")"
|
|
31
31
|
fi
|
|
32
|
-
echo "pr|${alias:-}|$repo|$number|${local_path:-}|$base"
|
|
32
|
+
echo "pr|${alias:-}|$repo|$number|${local_path:-}|$base|github|${repo}#${number}"
|
|
33
33
|
return 0
|
|
34
34
|
fi
|
|
35
35
|
|
|
@@ -42,11 +42,24 @@ psm_parse_ref() {
|
|
|
42
42
|
if [[ -n "$alias" ]]; then
|
|
43
43
|
IFS='|' read -r _ local_path base <<< "$(psm_get_project "$alias")"
|
|
44
44
|
fi
|
|
45
|
-
echo "issue|${alias:-}|$repo|$number|${local_path:-}|$base"
|
|
45
|
+
echo "issue|${alias:-}|$repo|$number|${local_path:-}|$base|github|${repo}#${number}"
|
|
46
46
|
return 0
|
|
47
47
|
fi
|
|
48
48
|
|
|
49
|
-
#
|
|
49
|
+
# Jira direct reference (PROJ-123) - config-validated
|
|
50
|
+
local jira_info
|
|
51
|
+
if jira_info=$(psm_detect_jira_key "$ref"); then
|
|
52
|
+
IFS='|' read -r alias project_key issue_number <<< "$jira_info"
|
|
53
|
+
local project_info
|
|
54
|
+
project_info=$(psm_get_project "$alias")
|
|
55
|
+
if [[ $? -eq 0 ]]; then
|
|
56
|
+
IFS='|' read -r repo local_path base <<< "$project_info"
|
|
57
|
+
echo "issue|${alias}|${repo}|${issue_number}|${local_path}|${base}|jira|${project_key}-${issue_number}"
|
|
58
|
+
return 0
|
|
59
|
+
fi
|
|
60
|
+
fi
|
|
61
|
+
|
|
62
|
+
# alias#number format (e.g., omc#123 or mywork#123)
|
|
50
63
|
if [[ "$ref" =~ ^([a-zA-Z][a-zA-Z0-9_-]*)#([0-9]+)$ ]]; then
|
|
51
64
|
alias="${BASH_REMATCH[1]}"
|
|
52
65
|
number="${BASH_REMATCH[2]}"
|
|
@@ -55,11 +68,22 @@ psm_parse_ref() {
|
|
|
55
68
|
project_info=$(psm_get_project "$alias")
|
|
56
69
|
if [[ $? -eq 0 ]]; then
|
|
57
70
|
IFS='|' read -r repo local_path base <<< "$project_info"
|
|
58
|
-
|
|
59
|
-
|
|
71
|
+
local provider
|
|
72
|
+
provider=$(psm_get_project_provider "$alias")
|
|
73
|
+
local provider_ref=""
|
|
74
|
+
|
|
75
|
+
if [[ "$provider" == "jira" ]]; then
|
|
76
|
+
local jira_proj
|
|
77
|
+
jira_proj=$(psm_get_project_jira_project "$alias")
|
|
78
|
+
provider_ref="${jira_proj}-${number}"
|
|
79
|
+
else
|
|
80
|
+
provider_ref="${repo}#${number}"
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
echo "ref|$alias|$repo|$number|$local_path|$base|$provider|$provider_ref"
|
|
60
84
|
return 0
|
|
61
85
|
else
|
|
62
|
-
echo "error|Unknown project alias: $alias
|
|
86
|
+
echo "error|Unknown project alias: $alias|||||||"
|
|
63
87
|
return 1
|
|
64
88
|
fi
|
|
65
89
|
fi
|
|
@@ -72,7 +96,7 @@ psm_parse_ref() {
|
|
|
72
96
|
if [[ -n "$alias" ]]; then
|
|
73
97
|
IFS='|' read -r _ local_path base <<< "$(psm_get_project "$alias")"
|
|
74
98
|
fi
|
|
75
|
-
echo "ref|${alias:-}|$repo|$number|${local_path:-}|$base"
|
|
99
|
+
echo "ref|${alias:-}|$repo|$number|${local_path:-}|$base|github|${repo}#${number}"
|
|
76
100
|
return 0
|
|
77
101
|
fi
|
|
78
102
|
|
|
@@ -88,11 +112,11 @@ psm_parse_ref() {
|
|
|
88
112
|
alias=$(psm_find_alias_for_repo "$repo")
|
|
89
113
|
fi
|
|
90
114
|
fi
|
|
91
|
-
echo "ref|${alias:-}|${repo:-}|$number|${local_path:-}|$base"
|
|
115
|
+
echo "ref|${alias:-}|${repo:-}|$number|${local_path:-}|$base|github|${repo:+${repo}#${number}}"
|
|
92
116
|
return 0
|
|
93
117
|
fi
|
|
94
118
|
|
|
95
|
-
echo "error|Cannot parse reference: $ref
|
|
119
|
+
echo "error|Cannot parse reference: $ref||||||"
|
|
96
120
|
return 1
|
|
97
121
|
}
|
|
98
122
|
|
|
@@ -103,7 +127,7 @@ psm_find_alias_for_repo() {
|
|
|
103
127
|
return 1
|
|
104
128
|
fi
|
|
105
129
|
|
|
106
|
-
jq -r ".aliases | to_entries[] | select(.value.repo ==
|
|
130
|
+
jq -r --arg r "$target_repo" '.aliases | to_entries[] | select(.value.repo == $r) | .key' "$PSM_PROJECTS" | head -1
|
|
107
131
|
}
|
|
108
132
|
|
|
109
133
|
# Sanitize a string for use in filenames/session names
|
|
@@ -119,3 +143,33 @@ psm_slugify() {
|
|
|
119
143
|
local max_len="${2:-30}"
|
|
120
144
|
echo "$title" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/--*/-/g' | sed 's/^-//' | sed 's/-$//' | head -c "$max_len"
|
|
121
145
|
}
|
|
146
|
+
|
|
147
|
+
# Check if input matches a configured Jira project
|
|
148
|
+
# Usage: psm_detect_jira_key "PROJ-123"
|
|
149
|
+
# Returns: alias|project_key|issue_number OR exits 1
|
|
150
|
+
psm_detect_jira_key() {
|
|
151
|
+
local input="$1"
|
|
152
|
+
|
|
153
|
+
# Must match PROJ-123 pattern (uppercase project, dash, digits)
|
|
154
|
+
if [[ ! "$input" =~ ^([A-Z][A-Z0-9]*)-([0-9]+)$ ]]; then
|
|
155
|
+
return 1
|
|
156
|
+
fi
|
|
157
|
+
|
|
158
|
+
local project_prefix="${BASH_REMATCH[1]}"
|
|
159
|
+
local issue_number="${BASH_REMATCH[2]}"
|
|
160
|
+
|
|
161
|
+
# Verify this project prefix exists in config
|
|
162
|
+
if [[ ! -f "$PSM_PROJECTS" ]]; then
|
|
163
|
+
return 1
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
local matching_alias
|
|
167
|
+
matching_alias=$(jq -r --arg p "$project_prefix" '.aliases | to_entries[] | select(.value.jira_project == $p) | .key' "$PSM_PROJECTS" | head -1)
|
|
168
|
+
|
|
169
|
+
if [[ -n "$matching_alias" ]]; then
|
|
170
|
+
echo "${matching_alias}|${project_prefix}|${issue_number}"
|
|
171
|
+
return 0
|
|
172
|
+
fi
|
|
173
|
+
|
|
174
|
+
return 1
|
|
175
|
+
}
|