oh-my-customcode 0.69.0 → 0.71.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/README.md +7 -7
- package/dist/cli/index.js +167 -29
- package/dist/index.js +101 -13
- package/package.json +1 -1
- package/templates/.claude/hooks/hooks.json +10 -0
- package/templates/.claude/hooks/scripts/omcustom-auto-update.sh +170 -0
- package/templates/.claude/skills/claude-native/SKILL.md +215 -0
- package/templates/.claude/skills/evaluator-optimizer/SKILL.md +1 -1
- package/templates/.claude/skills/omcustom-feedback/SKILL.md +36 -77
- package/templates/.claude/skills/pipeline/SKILL.md +102 -0
- package/templates/CLAUDE.md +4 -3
- package/templates/manifest.json +2 -2
- package/templates/workflows/auto-dev.yaml +5 -5
- package/templates/.claude/skills/workflow/SKILL.md +0 -68
- package/templates/.claude/skills/workflow-resume/SKILL.md +0 -26
- package/templates/.claude/skills/workflow-runner/SKILL.md +0 -75
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# SessionStart auto-update hook — interactive omcustom update check
|
|
3
|
+
# Trigger: SessionStart (runs BEFORE session-env-check.sh)
|
|
4
|
+
# Purpose: Check for oh-my-customcode updates, prompt user, optionally update
|
|
5
|
+
# Protocol: stdin JSON -> stdout pass-through, exit 0 ALWAYS
|
|
6
|
+
# Design: GitHub issue #752
|
|
7
|
+
|
|
8
|
+
# Pass through stdin immediately — capture for later output
|
|
9
|
+
input=$(cat)
|
|
10
|
+
|
|
11
|
+
# --- Guard: skip conditions ---
|
|
12
|
+
|
|
13
|
+
# Skip if explicitly disabled
|
|
14
|
+
if [ "${OMCUSTOM_SKIP_AUTO_UPDATE:-}" = "true" ]; then
|
|
15
|
+
echo "$input"
|
|
16
|
+
exit 0
|
|
17
|
+
fi
|
|
18
|
+
|
|
19
|
+
# Skip if /dev/tty not available (CI, Docker, non-interactive)
|
|
20
|
+
if ! [ -c /dev/tty ] 2>/dev/null; then
|
|
21
|
+
echo "$input"
|
|
22
|
+
exit 0
|
|
23
|
+
fi
|
|
24
|
+
|
|
25
|
+
# --- Configuration ---
|
|
26
|
+
CACHE_DIR="$HOME/.oh-my-customcode"
|
|
27
|
+
CACHE_FILE="${CACHE_DIR}/self-update-cache.json"
|
|
28
|
+
CACHE_MAX_AGE=3600 # 1 hour in seconds
|
|
29
|
+
NPM_TIMEOUT=3 # seconds for npm view
|
|
30
|
+
INPUT_TIMEOUT=10 # seconds for user prompt
|
|
31
|
+
PACKAGE_NAME="oh-my-customcode"
|
|
32
|
+
|
|
33
|
+
# --- Helper: semantic version compare ---
|
|
34
|
+
# Returns 0 if $1 < $2 (update available)
|
|
35
|
+
version_lt() {
|
|
36
|
+
local older
|
|
37
|
+
older=$(printf '%s\n' "$1" "$2" | sort -V | head -1)
|
|
38
|
+
[ "$older" = "$1" ] && [ "$1" != "$2" ]
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
# --- Step 1: Get current installed version ---
|
|
42
|
+
CURRENT_VERSION=""
|
|
43
|
+
|
|
44
|
+
# Try .omcustomrc.json in current directory
|
|
45
|
+
if [ -f ".omcustomrc.json" ]; then
|
|
46
|
+
CURRENT_VERSION=$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' .omcustomrc.json 2>/dev/null | head -1 | grep -o '"[^"]*"$' | tr -d '"')
|
|
47
|
+
fi
|
|
48
|
+
|
|
49
|
+
# Fallback: try npm list
|
|
50
|
+
if [ -z "$CURRENT_VERSION" ]; then
|
|
51
|
+
CURRENT_VERSION=$(npm list -g "$PACKAGE_NAME" --depth=0 2>/dev/null | grep -o "${PACKAGE_NAME}@[^ ]*" | cut -d'@' -f2)
|
|
52
|
+
fi
|
|
53
|
+
|
|
54
|
+
# Cannot determine current version — skip
|
|
55
|
+
if [ -z "$CURRENT_VERSION" ]; then
|
|
56
|
+
echo "$input"
|
|
57
|
+
exit 0
|
|
58
|
+
fi
|
|
59
|
+
|
|
60
|
+
# --- Step 2: Get latest version (cache-first, network fallback) ---
|
|
61
|
+
LATEST_VERSION=""
|
|
62
|
+
CACHE_HIT=false
|
|
63
|
+
|
|
64
|
+
# Ensure cache directory exists
|
|
65
|
+
mkdir -p "$CACHE_DIR" 2>/dev/null
|
|
66
|
+
|
|
67
|
+
# Check cache freshness
|
|
68
|
+
if [ -f "$CACHE_FILE" ]; then
|
|
69
|
+
CACHE_TIMESTAMP=$(grep -o '"timestamp"[[:space:]]*:[[:space:]]*[0-9]*' "$CACHE_FILE" 2>/dev/null | grep -o '[0-9]*$')
|
|
70
|
+
CACHED_VERSION=$(grep -o '"version"[[:space:]]*:[[:space:]]*"[^"]*"' "$CACHE_FILE" 2>/dev/null | grep -o '"[^"]*"$' | tr -d '"')
|
|
71
|
+
|
|
72
|
+
if [ -n "$CACHE_TIMESTAMP" ] && [ -n "$CACHED_VERSION" ]; then
|
|
73
|
+
NOW=$(date +%s)
|
|
74
|
+
AGE=$((NOW - CACHE_TIMESTAMP))
|
|
75
|
+
|
|
76
|
+
if [ "$AGE" -lt "$CACHE_MAX_AGE" ]; then
|
|
77
|
+
LATEST_VERSION="$CACHED_VERSION"
|
|
78
|
+
CACHE_HIT=true
|
|
79
|
+
fi
|
|
80
|
+
fi
|
|
81
|
+
fi
|
|
82
|
+
|
|
83
|
+
# Cache miss or stale — fetch from npm registry
|
|
84
|
+
if [ "$CACHE_HIT" = false ]; then
|
|
85
|
+
if command -v npm >/dev/null 2>&1; then
|
|
86
|
+
LATEST_VERSION=$(timeout "$NPM_TIMEOUT" npm view "$PACKAGE_NAME" version 2>/dev/null || echo "")
|
|
87
|
+
|
|
88
|
+
# Update cache on successful fetch
|
|
89
|
+
if [ -n "$LATEST_VERSION" ]; then
|
|
90
|
+
NOW=$(date +%s)
|
|
91
|
+
cat > "$CACHE_FILE" << EOF
|
|
92
|
+
{
|
|
93
|
+
"version": "${LATEST_VERSION}",
|
|
94
|
+
"timestamp": ${NOW},
|
|
95
|
+
"source": "npm-registry"
|
|
96
|
+
}
|
|
97
|
+
EOF
|
|
98
|
+
fi
|
|
99
|
+
fi
|
|
100
|
+
fi
|
|
101
|
+
|
|
102
|
+
# Could not determine latest version — skip
|
|
103
|
+
if [ -z "$LATEST_VERSION" ]; then
|
|
104
|
+
echo "$input"
|
|
105
|
+
exit 0
|
|
106
|
+
fi
|
|
107
|
+
|
|
108
|
+
# --- Step 3: Compare versions ---
|
|
109
|
+
if ! version_lt "$CURRENT_VERSION" "$LATEST_VERSION"; then
|
|
110
|
+
# Already up to date
|
|
111
|
+
echo "$input"
|
|
112
|
+
exit 0
|
|
113
|
+
fi
|
|
114
|
+
|
|
115
|
+
# --- Step 4: Prompt user for update ---
|
|
116
|
+
echo "" >&2
|
|
117
|
+
echo "--- [oh-my-customcode Update Available] ---" >&2
|
|
118
|
+
echo " New version: v${LATEST_VERSION} (current: v${CURRENT_VERSION})" >&2
|
|
119
|
+
echo "" >&2
|
|
120
|
+
|
|
121
|
+
# Interactive prompt via /dev/tty (SessionStart stdin is JSON pipe)
|
|
122
|
+
printf " Update oh-my-customcode to v%s? [y/N] " "$LATEST_VERSION" >/dev/tty 2>/dev/null
|
|
123
|
+
if read -r -t "$INPUT_TIMEOUT" answer </dev/tty 2>/dev/null; then
|
|
124
|
+
case "$answer" in
|
|
125
|
+
[yY]|[yY][eE][sS])
|
|
126
|
+
echo " Installing oh-my-customcode@${LATEST_VERSION}..." >&2
|
|
127
|
+
if npm install -g "${PACKAGE_NAME}@latest" >&2 2>&1; then
|
|
128
|
+
echo " ✓ Updated to v${LATEST_VERSION}" >&2
|
|
129
|
+
|
|
130
|
+
# Check if project harness should be updated too
|
|
131
|
+
if [ -f ".omcustomrc.json" ]; then
|
|
132
|
+
printf " Update project harness too? [y/N] " >/dev/tty 2>/dev/null
|
|
133
|
+
if read -r -t "$INPUT_TIMEOUT" harness_answer </dev/tty 2>/dev/null; then
|
|
134
|
+
case "$harness_answer" in
|
|
135
|
+
[yY]|[yY][eE][sS])
|
|
136
|
+
echo " Updating project harness..." >&2
|
|
137
|
+
if command -v omcustom >/dev/null 2>&1; then
|
|
138
|
+
omcustom update --force >&2 2>&1 || echo " ⚠ Harness update failed (non-blocking)" >&2
|
|
139
|
+
echo " ✓ Project harness updated" >&2
|
|
140
|
+
else
|
|
141
|
+
echo " ⚠ omcustom command not found after install" >&2
|
|
142
|
+
fi
|
|
143
|
+
;;
|
|
144
|
+
*)
|
|
145
|
+
echo " Skipped harness update" >&2
|
|
146
|
+
;;
|
|
147
|
+
esac
|
|
148
|
+
else
|
|
149
|
+
echo "" >&2
|
|
150
|
+
echo " Timed out — skipped harness update" >&2
|
|
151
|
+
fi
|
|
152
|
+
fi
|
|
153
|
+
else
|
|
154
|
+
echo " ⚠ Update failed (non-blocking, continuing session)" >&2
|
|
155
|
+
fi
|
|
156
|
+
;;
|
|
157
|
+
*)
|
|
158
|
+
echo " Skipped update" >&2
|
|
159
|
+
;;
|
|
160
|
+
esac
|
|
161
|
+
else
|
|
162
|
+
echo "" >&2
|
|
163
|
+
echo " Timed out — skipped update" >&2
|
|
164
|
+
fi
|
|
165
|
+
|
|
166
|
+
echo "------------------------------------" >&2
|
|
167
|
+
|
|
168
|
+
# Always pass through and exit 0
|
|
169
|
+
echo "$input"
|
|
170
|
+
exit 0
|
|
@@ -0,0 +1,215 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: claude-native
|
|
3
|
+
description: Monitor Claude Code releases and auto-generate GitHub issues for each new version
|
|
4
|
+
scope: core
|
|
5
|
+
user-invocable: true
|
|
6
|
+
argument-hint: "[--backfill] [--dry-run]"
|
|
7
|
+
version: 1.0.0
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# Claude Native Skill
|
|
11
|
+
|
|
12
|
+
Monitor Claude Code (the CLI tool) release history and auto-generate GitHub issues for each new version that has not yet been tracked. Replaces the deprecated customclaw Airflow-based monitoring (deprecated 2026-03-18).
|
|
13
|
+
|
|
14
|
+
## Options
|
|
15
|
+
|
|
16
|
+
```
|
|
17
|
+
--backfill Process ALL versions >= v2.1.86 (default behavior when flag is present)
|
|
18
|
+
Without flag: only check the latest 5 releases
|
|
19
|
+
--dry-run Show what issues would be created without actually creating them
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## Workflow
|
|
23
|
+
|
|
24
|
+
### Phase 1: Fetch CC Releases
|
|
25
|
+
|
|
26
|
+
Fetch all Claude Code releases from the GitHub API:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
gh api repos/anthropics/claude-code/releases \
|
|
30
|
+
--paginate \
|
|
31
|
+
--jq '.[] | {tag_name: .tag_name, published_at: .published_at, html_url: .html_url, body: .body}'
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
- Without `--backfill`: fetch only the latest 5 releases (`--limit 5` or first 5 results)
|
|
35
|
+
- With `--backfill`: fetch all releases (use `--paginate`)
|
|
36
|
+
- Filter: only process versions >= v2.1.86 (monitoring stopped after v2.1.85 / issue #683)
|
|
37
|
+
|
|
38
|
+
### Phase 2: Check Existing Issues
|
|
39
|
+
|
|
40
|
+
Search for existing tracking issues to avoid duplicates:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
gh issue list \
|
|
44
|
+
--state all \
|
|
45
|
+
--search "[Claude Code v" \
|
|
46
|
+
--json number,title \
|
|
47
|
+
--limit 100
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
Build a set of already-tracked versions by extracting version strings from issue titles matching the pattern `[Claude Code v{version}]`.
|
|
51
|
+
|
|
52
|
+
### Phase 3: Dedup
|
|
53
|
+
|
|
54
|
+
For each fetched release version:
|
|
55
|
+
- Parse the version string from `tag_name` (e.g., `v2.1.86`)
|
|
56
|
+
- If a matching issue title already exists → skip (already tracked)
|
|
57
|
+
- If no matching issue → add to "needs issue" list
|
|
58
|
+
|
|
59
|
+
### Phase 4: Create Issues (or Dry-Run Report)
|
|
60
|
+
|
|
61
|
+
#### Dry-Run Mode (`--dry-run`)
|
|
62
|
+
|
|
63
|
+
Print a report of what would be created:
|
|
64
|
+
|
|
65
|
+
```
|
|
66
|
+
[Dry Run] Would create issues for:
|
|
67
|
+
- v2.1.86 (published: 2026-01-15)
|
|
68
|
+
- v2.1.87 (published: 2026-01-22)
|
|
69
|
+
...
|
|
70
|
+
No issues were created.
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
#### Live Mode
|
|
74
|
+
|
|
75
|
+
For each version in the "needs issue" list, create a GitHub issue:
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
gh issue create \
|
|
79
|
+
--title "[Claude Code v{version}] New release detected" \
|
|
80
|
+
--label "automated,claude-code-release" \
|
|
81
|
+
--body "{body}"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
Issue body format (matching the pattern established by issue #683):
|
|
85
|
+
|
|
86
|
+
```markdown
|
|
87
|
+
# Claude Code v{version}
|
|
88
|
+
|
|
89
|
+
**Release:** v{version}
|
|
90
|
+
**Published:** {published_at}
|
|
91
|
+
**Link:** {html_url}
|
|
92
|
+
|
|
93
|
+
## Release Summary
|
|
94
|
+
|
|
95
|
+
{release_notes_body — truncated to first 2000 chars if too long}
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## Action Items
|
|
100
|
+
|
|
101
|
+
- [ ] Review release notes for impact on oh-my-customcode
|
|
102
|
+
- [ ] Update agent definitions if new Claude Code features affect agents
|
|
103
|
+
- [ ] Test compatibility with current oh-my-customcode version
|
|
104
|
+
- [ ] Update CLAUDE.md if new capabilities are relevant
|
|
105
|
+
|
|
106
|
+
---
|
|
107
|
+
|
|
108
|
+
_This issue was created by the `/omcustom:claude-native` skill._
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
**Notes:**
|
|
112
|
+
- If `body` from the release is empty, use `_No release notes provided._`
|
|
113
|
+
- Truncate release body at 2000 characters and append `... (truncated)` if needed
|
|
114
|
+
- The `automated` and `claude-code-release` labels must exist in the repository; create them if missing:
|
|
115
|
+
```bash
|
|
116
|
+
gh label create "automated" --color "#0075ca" --description "Automated issue" 2>/dev/null || true
|
|
117
|
+
gh label create "claude-code-release" --color "#e4e669" --description "Claude Code release tracking" 2>/dev/null || true
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
### Phase 5: Report Results
|
|
121
|
+
|
|
122
|
+
After processing all versions:
|
|
123
|
+
|
|
124
|
+
```
|
|
125
|
+
[claude-native] Scan complete
|
|
126
|
+
|
|
127
|
+
Versions checked: {N}
|
|
128
|
+
New issues created: {M}
|
|
129
|
+
|
|
130
|
+
Created:
|
|
131
|
+
- #1234 [Claude Code v2.1.86] New release detected
|
|
132
|
+
- #1235 [Claude Code v2.1.87] New release detected
|
|
133
|
+
|
|
134
|
+
Already tracked (skipped):
|
|
135
|
+
- v2.1.85 → #683
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
If no new releases found:
|
|
139
|
+
|
|
140
|
+
```
|
|
141
|
+
[claude-native] No new releases found. All versions >= v2.1.86 are already tracked.
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Version Filtering Logic
|
|
145
|
+
|
|
146
|
+
```
|
|
147
|
+
MIN_VERSION = "2.1.86"
|
|
148
|
+
|
|
149
|
+
For each release:
|
|
150
|
+
version = strip_v_prefix(tag_name) # "v2.1.86" → "2.1.86"
|
|
151
|
+
parts = split(version, ".") # ["2", "1", "86"]
|
|
152
|
+
if compare_semver(version, MIN_VERSION) >= 0:
|
|
153
|
+
include
|
|
154
|
+
else:
|
|
155
|
+
skip
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
Semver comparison: major → minor → patch (all numeric). Pre-release suffixes (e.g., `-beta`) are included and compared lexicographically after numeric parts.
|
|
159
|
+
|
|
160
|
+
## Error Handling
|
|
161
|
+
|
|
162
|
+
| Error | Action |
|
|
163
|
+
|-------|--------|
|
|
164
|
+
| `gh` not authenticated | Report: "Error: gh CLI not authenticated. Run `gh auth login` first." |
|
|
165
|
+
| Rate limit hit | Report current status, list remaining versions |
|
|
166
|
+
| Label creation fails | Warn and continue (issue created without label) |
|
|
167
|
+
| Release body parse error | Use empty body fallback, continue |
|
|
168
|
+
|
|
169
|
+
## Integration Options
|
|
170
|
+
|
|
171
|
+
### Manual
|
|
172
|
+
|
|
173
|
+
```
|
|
174
|
+
/omcustom:claude-native
|
|
175
|
+
/omcustom:claude-native --backfill
|
|
176
|
+
/omcustom:claude-native --dry-run
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
### Automatic (SessionStart Hook)
|
|
180
|
+
|
|
181
|
+
Can be integrated into the SessionStart hook to check for new releases at session start:
|
|
182
|
+
|
|
183
|
+
```json
|
|
184
|
+
{
|
|
185
|
+
"SessionStart": [
|
|
186
|
+
{
|
|
187
|
+
"command": "bash .claude/hooks/scripts/claude-native-check.sh"
|
|
188
|
+
}
|
|
189
|
+
]
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
A lightweight wrapper script can run a `--dry-run` check and notify if new releases exist.
|
|
194
|
+
|
|
195
|
+
### Scheduled (CronCreate)
|
|
196
|
+
|
|
197
|
+
Can be set up as a scheduled remote agent using `/schedule`:
|
|
198
|
+
|
|
199
|
+
```
|
|
200
|
+
/schedule "daily at 9am: /omcustom:claude-native"
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
Or via CronCreate MCP tool for programmatic scheduling.
|
|
204
|
+
|
|
205
|
+
## Prerequisites
|
|
206
|
+
|
|
207
|
+
- `gh` CLI installed and authenticated (`gh auth status`)
|
|
208
|
+
- Repository: `baekenough/oh-my-customcode` (default, detected from git remote)
|
|
209
|
+
- Labels `automated` and `claude-code-release` (auto-created if missing)
|
|
210
|
+
|
|
211
|
+
## Background
|
|
212
|
+
|
|
213
|
+
- Last manually tracked release: v2.1.85 (issue #683)
|
|
214
|
+
- Monitoring gap: v2.1.86 onwards (customclaw deprecated 2026-03-18)
|
|
215
|
+
- This skill fills the monitoring gap and provides ongoing tracking
|
|
@@ -379,7 +379,7 @@ When ecomode is active (R013), compress output:
|
|
|
379
379
|
- The evaluator prompt MUST include the full rubric to ensure consistent scoring
|
|
380
380
|
- Iteration state (best score, best output) is tracked by the orchestrator
|
|
381
381
|
- The hard cap of 5 iterations prevents runaway refinement loops
|
|
382
|
-
- For multi-sprint runs (5+ iterations), consider context reset: spawn a fresh evaluator agent rather than continuing with degraded context. The
|
|
382
|
+
- For multi-sprint runs (5+ iterations), consider context reset: spawn a fresh evaluator agent rather than continuing with degraded context. The pipeline skill supports this via `context: fork` on individual steps. Anthropic's research confirms "context resets provide clean slates superior to compaction" for long-running evaluation.
|
|
383
383
|
|
|
384
384
|
## Domain Examples
|
|
385
385
|
|
|
@@ -9,11 +9,11 @@ argument-hint: "[description or leave empty for interactive] [--anonymous]"
|
|
|
9
9
|
|
|
10
10
|
# Feedback Submitter
|
|
11
11
|
|
|
12
|
-
Submit feedback about oh-my-customcode (bugs, features, improvements, questions) directly from the CLI session. Supports anonymous submission
|
|
12
|
+
Submit feedback about oh-my-customcode (bugs, features, improvements, questions) directly from the CLI session. Supports anonymous submission with `[Anonymous Feedback]` title prefix when `--anonymous` flag is used.
|
|
13
13
|
|
|
14
14
|
## Purpose
|
|
15
15
|
|
|
16
|
-
Lowers the barrier for submitting feedback by allowing users to create GitHub issues
|
|
16
|
+
Lowers the barrier for submitting feedback by allowing users to create GitHub issues — without leaving their terminal session. All feedback is filed to the `baekenough/oh-my-customcode` repository.
|
|
17
17
|
|
|
18
18
|
## Usage
|
|
19
19
|
|
|
@@ -59,22 +59,13 @@ if [ "$GH_AVAILABLE" = "true" ]; then
|
|
|
59
59
|
else
|
|
60
60
|
GH_AUTHED=false
|
|
61
61
|
fi
|
|
62
|
-
|
|
63
|
-
# Check curl availability
|
|
64
|
-
command -v curl >/dev/null 2>&1 && CURL_AVAILABLE=true || CURL_AVAILABLE=false
|
|
65
62
|
```
|
|
66
63
|
|
|
67
|
-
**Route A**: `gh` available + authenticated
|
|
64
|
+
**Route A**: `gh` available + authenticated
|
|
68
65
|
- Use GitHub Issue creation (see Phase 4A)
|
|
66
|
+
- If `--anonymous`: adds `[Anonymous Feedback]` prefix and `anonymous` label
|
|
69
67
|
|
|
70
|
-
**
|
|
71
|
-
- Use `curl` to Airflow REST API (see Phase 4C)
|
|
72
|
-
- Phase 4B (workflow_dispatch) reserved for future use
|
|
73
|
-
|
|
74
|
-
**Route C**: `gh` NOT available (or Route B curl fallback)
|
|
75
|
-
- Use `curl` to Airflow REST API (see Phase 4C)
|
|
76
|
-
|
|
77
|
-
**Fallback**: Neither `gh` nor `curl` available
|
|
68
|
+
**Fallback**: `gh` NOT available or not authenticated
|
|
78
69
|
- Save feedback locally and inform the user (see Phase 4D)
|
|
79
70
|
|
|
80
71
|
### Phase 3: Environment Collection
|
|
@@ -102,24 +93,30 @@ For anonymous submissions, do NOT include the project name. Offer to include pro
|
|
|
102
93
|
- Ask: "Include environment info (version, OS) in the anonymous report? [Y/n]"
|
|
103
94
|
- If declined, set `PROJECT_CONTEXT=""`
|
|
104
95
|
|
|
105
|
-
### Phase 4A: GitHub Issue Creation (Route A — gh + authenticated
|
|
96
|
+
### Phase 4A: GitHub Issue Creation (Route A — gh + authenticated)
|
|
106
97
|
|
|
107
|
-
1.
|
|
98
|
+
1. If `ANONYMOUS=true`, prepend `[Anonymous Feedback] ` to the title and add `anonymous` to the label list.
|
|
99
|
+
|
|
100
|
+
2. Show the user a preview of the issue to be created:
|
|
108
101
|
```
|
|
109
102
|
[Preview]
|
|
110
103
|
├── Title: {title}
|
|
111
104
|
├── Category: {category}
|
|
112
|
-
├── Labels: feedback, {category-label}
|
|
105
|
+
├── Labels: feedback, {category-label}[, anonymous]
|
|
113
106
|
└── Repo: baekenough/oh-my-customcode
|
|
114
107
|
```
|
|
115
|
-
|
|
108
|
+
3. Ask for confirmation before creating
|
|
116
109
|
|
|
117
|
-
|
|
110
|
+
4. Ensure labels exist (defensive):
|
|
118
111
|
```bash
|
|
119
112
|
gh label create feedback --description "User feedback via /omcustom-feedback" --color 0E8A16 --repo baekenough/oh-my-customcode 2>/dev/null || true
|
|
113
|
+
# If anonymous, ensure the anonymous label exists
|
|
114
|
+
if [ "$ANONYMOUS" = "true" ]; then
|
|
115
|
+
gh label create anonymous --description "Anonymous feedback submission" --color C5DEF5 --repo baekenough/oh-my-customcode 2>/dev/null || true
|
|
116
|
+
fi
|
|
120
117
|
```
|
|
121
118
|
|
|
122
|
-
|
|
119
|
+
5. Create the issue using `--body-file` for safe markdown handling:
|
|
123
120
|
```bash
|
|
124
121
|
# Write body to temp file to avoid shell escaping issues
|
|
125
122
|
cat > /tmp/omcustom-feedback-body.md << 'FEEDBACK_EOF'
|
|
@@ -141,64 +138,28 @@ For anonymous submissions, do NOT include the project name. Offer to include pro
|
|
|
141
138
|
*Submitted via `/omcustom-feedback`*
|
|
142
139
|
FEEDBACK_EOF
|
|
143
140
|
|
|
141
|
+
# Build label string
|
|
142
|
+
LABELS="feedback,${CATEGORY_LABEL}"
|
|
143
|
+
if [ "$ANONYMOUS" = "true" ]; then
|
|
144
|
+
LABELS="${LABELS},anonymous"
|
|
145
|
+
fi
|
|
146
|
+
|
|
144
147
|
# Create issue
|
|
145
148
|
gh issue create \
|
|
146
149
|
--repo baekenough/oh-my-customcode \
|
|
147
150
|
--title "{title}" \
|
|
148
|
-
--label "
|
|
151
|
+
--label "$LABELS" \
|
|
149
152
|
--body-file /tmp/omcustom-feedback-body.md
|
|
150
153
|
|
|
151
154
|
# Clean up
|
|
152
155
|
rm -f /tmp/omcustom-feedback-body.md
|
|
153
156
|
```
|
|
154
157
|
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
6. Return the issue URL to the user
|
|
158
|
-
|
|
159
|
-
### Phase 4B: Anonymous via GitHub Actions (Route B — FUTURE)
|
|
160
|
-
|
|
161
|
-
> **Note**: This route is reserved for future implementation. The `feedback-submission.yml` workflow does not yet exist. All anonymous/unauthenticated submissions currently fall through to Route C (Airflow REST API).
|
|
162
|
-
|
|
163
|
-
```bash
|
|
164
|
-
gh workflow run feedback-submission.yml \
|
|
165
|
-
--repo baekenough/oh-my-customcode \
|
|
166
|
-
-f title="$TITLE" \
|
|
167
|
-
-f body="$BODY" \
|
|
168
|
-
-f feedback_type="$TYPE" \
|
|
169
|
-
-f anonymous=true \
|
|
170
|
-
-f project_context="$PROJECT_CONTEXT"
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
On success, inform the user:
|
|
174
|
-
```
|
|
175
|
-
[Done] Anonymous feedback submitted via GitHub Actions workflow.
|
|
176
|
-
```
|
|
177
|
-
|
|
178
|
-
If `gh workflow run` fails (e.g., permissions), fall through to Route C.
|
|
179
|
-
|
|
180
|
-
### Phase 4C: Anonymous via Airflow REST API (Route C — no gh)
|
|
181
|
-
|
|
182
|
-
```bash
|
|
183
|
-
# Build JSON payload safely with jq
|
|
184
|
-
PAYLOAD=$(jq -n --arg title "$TITLE" --arg body "$BODY" --arg type "$TYPE" --arg ctx "$PROJECT_CONTEXT" \
|
|
185
|
-
'{"conf":{"title":$title,"body":$body,"feedback_type":$type,"anonymous":true,"submitter":"","project_context":$ctx}}')
|
|
186
|
-
|
|
187
|
-
curl -X POST "https://airflow.baekenough.com/api/v2/dags/omc_feedback_collector/dagRuns" \
|
|
188
|
-
-H "Content-Type: application/json" \
|
|
189
|
-
-d "$PAYLOAD" \
|
|
190
|
-
--silent --show-error \
|
|
191
|
-
--max-time 15
|
|
192
|
-
```
|
|
193
|
-
|
|
194
|
-
On HTTP 200/201, inform the user:
|
|
195
|
-
```
|
|
196
|
-
[Done] Anonymous feedback submitted via Airflow.
|
|
197
|
-
```
|
|
158
|
+
6. If label creation fails AND issue creation fails due to labels, retry without labels as fallback
|
|
198
159
|
|
|
199
|
-
|
|
160
|
+
7. Return the issue URL to the user
|
|
200
161
|
|
|
201
|
-
### Phase 4D: Local Fallback (
|
|
162
|
+
### Phase 4D: Local Fallback (gh not available, not authenticated, or issue creation failed)
|
|
202
163
|
|
|
203
164
|
```bash
|
|
204
165
|
mkdir -p ~/.omcustom/feedback
|
|
@@ -222,25 +183,23 @@ Inform the user:
|
|
|
222
183
|
[Saved] Feedback saved locally to ~/.omcustom/feedback/{timestamp}.json
|
|
223
184
|
Submit manually when connectivity is available:
|
|
224
185
|
- GitHub Issues: https://github.com/baekenough/oh-my-customcode/issues/new
|
|
225
|
-
- Or run /omcustom:feedback again when gh
|
|
186
|
+
- Or run /omcustom:feedback again when gh is available
|
|
226
187
|
```
|
|
227
188
|
|
|
228
189
|
### Category-to-Label Mapping
|
|
229
190
|
|
|
230
|
-
| Category | GitHub Label |
|
|
231
|
-
|
|
232
|
-
| bug | bug |
|
|
233
|
-
| feature | enhancement |
|
|
234
|
-
| improvement | enhancement |
|
|
235
|
-
| question | question |
|
|
236
|
-
| (auto-detect fails) | (none) |
|
|
191
|
+
| Category | GitHub Label |
|
|
192
|
+
|----------|--------------|
|
|
193
|
+
| bug | bug |
|
|
194
|
+
| feature | enhancement |
|
|
195
|
+
| improvement | enhancement |
|
|
196
|
+
| question | question |
|
|
197
|
+
| (auto-detect fails) | (none) |
|
|
237
198
|
|
|
238
199
|
## Notes
|
|
239
200
|
|
|
240
201
|
- Route A creates a visible GitHub issue attributed to the user's gh account
|
|
241
|
-
-
|
|
242
|
-
- Route B requires `gh` but NOT authentication to the repo (public workflow)
|
|
243
|
-
- Route C requires `curl` (available on macOS/Linux by default)
|
|
202
|
+
- When `--anonymous` is used, the title is prefixed with `[Anonymous Feedback]` and the `anonymous` label is added
|
|
244
203
|
- Fallback ensures no feedback is silently lost even in offline environments
|
|
245
204
|
- `disable-model-invocation: true` ensures this skill only runs when explicitly invoked by the user
|
|
246
205
|
- Target repo is hardcoded to `baekenough/oh-my-customcode` — feedback is always about omcustom itself
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pipeline
|
|
3
|
+
description: Invoke and resume YAML-defined pipelines by name — /pipeline auto-dev runs the full release pipeline
|
|
4
|
+
scope: harness
|
|
5
|
+
user-invocable: true
|
|
6
|
+
effort: high
|
|
7
|
+
argument-hint: "<pipeline-name> | resume | (no args to list available)"
|
|
8
|
+
source:
|
|
9
|
+
type: external
|
|
10
|
+
origin: github
|
|
11
|
+
url: https://github.com/baekenough/baekenough-skills
|
|
12
|
+
version: 1.0.0
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
# /pipeline — Pipeline Invocation
|
|
16
|
+
|
|
17
|
+
## Usage
|
|
18
|
+
|
|
19
|
+
```
|
|
20
|
+
/pipeline auto-dev # Run the auto-dev pipeline
|
|
21
|
+
/pipeline # List available pipelines
|
|
22
|
+
/pipeline resume # Resume a halted pipeline
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Behavior
|
|
26
|
+
|
|
27
|
+
### List Mode (no arguments or --list flag)
|
|
28
|
+
|
|
29
|
+
Execute these steps to display available pipelines:
|
|
30
|
+
|
|
31
|
+
1. **Scan built-in pipelines**: Use `Glob("workflows/*.yaml")` (NOT templates/) to find all pipeline definitions
|
|
32
|
+
2. **Extract metadata**: For each YAML file found, use `Bash` to extract name and description:
|
|
33
|
+
```bash
|
|
34
|
+
for f in workflows/*.yaml; do
|
|
35
|
+
name=$(grep -m1 '^name:' "$f" | sed 's/^name: *//' | tr -d '"')
|
|
36
|
+
desc=$(grep -m1 '^description:' "$f" | sed 's/^description: *//' | tr -d '"')
|
|
37
|
+
echo " $name — $desc"
|
|
38
|
+
done
|
|
39
|
+
```
|
|
40
|
+
3. **Scan template pipelines**: Use `Glob("templates/workflows/*.yaml")` for template examples
|
|
41
|
+
4. **Display formatted output**:
|
|
42
|
+
```
|
|
43
|
+
Available pipelines:
|
|
44
|
+
{name} — {description}
|
|
45
|
+
{name} — {description}
|
|
46
|
+
|
|
47
|
+
Template pipelines (in templates/workflows/):
|
|
48
|
+
{name} — {description}
|
|
49
|
+
```
|
|
50
|
+
5. If no pipelines found, display: "No pipelines found in workflows/ directory."
|
|
51
|
+
6. If YAML parsing fails for a file, skip it and show: ` {filename} — (parse error, skipped)`
|
|
52
|
+
|
|
53
|
+
### Run Mode (with pipeline name)
|
|
54
|
+
|
|
55
|
+
1. Validate pipeline exists: `workflows/{name}.yaml`
|
|
56
|
+
2. Load and validate YAML structure:
|
|
57
|
+
- Required fields: `name`, `description`, `steps[]`
|
|
58
|
+
- Each step has either `skill:` or `prompt:` (not both)
|
|
59
|
+
- Referenced skills exist in `.claude/skills/`
|
|
60
|
+
- Skill names must match `^[a-z0-9-]+$` (kebab-case only) — reject path traversal attempts
|
|
61
|
+
3. Announce: `[Pipeline] Starting {name} — {step_count} steps`
|
|
62
|
+
4. Execute steps top-to-bottom:
|
|
63
|
+
- **Skill steps** (`skill: name`): Invoke via Skill tool — `Skill(skill: "{name}")`
|
|
64
|
+
- **Prompt steps** (`prompt: text`): Execute the described action using appropriate agents/tools
|
|
65
|
+
- **Foreach steps** (`foreach: collection`): Iterate over collection from previous step output
|
|
66
|
+
5. Report completion or failure
|
|
67
|
+
|
|
68
|
+
### Resume Mode (/pipeline resume)
|
|
69
|
+
|
|
70
|
+
1. Scan `/tmp/.claude-pipeline-*-{PPID}.json` for state files
|
|
71
|
+
2. If none found: "No halted pipelines found."
|
|
72
|
+
3. If found: display pipeline name, failed step, error message
|
|
73
|
+
4. Options:
|
|
74
|
+
- **Retry** — Re-execute the failed step
|
|
75
|
+
- **Skip** — Mark failed step as skipped, continue to next
|
|
76
|
+
- **Abort** — Delete state file, cancel pipeline
|
|
77
|
+
5. On resume: execute from the failed step
|
|
78
|
+
|
|
79
|
+
## State Tracking
|
|
80
|
+
|
|
81
|
+
Track per-step state:
|
|
82
|
+
```json
|
|
83
|
+
{
|
|
84
|
+
"pipeline": "{name}",
|
|
85
|
+
"started": "ISO-8601",
|
|
86
|
+
"status": "running|completed|halted",
|
|
87
|
+
"current_step": 0,
|
|
88
|
+
"steps": [
|
|
89
|
+
{"name": "triage", "status": "completed", "duration_ms": 5000},
|
|
90
|
+
{"name": "plan", "status": "running"}
|
|
91
|
+
]
|
|
92
|
+
}
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
State saved to `/tmp/.claude-pipeline-{name}-{PPID}.json` on failure.
|
|
96
|
+
|
|
97
|
+
## Error Handling
|
|
98
|
+
|
|
99
|
+
- Pipeline not found → list available pipelines with suggestion
|
|
100
|
+
- YAML parse error → report with line number
|
|
101
|
+
- Step failure (error: halt-and-report) → stop execution, save state, report failure with context
|
|
102
|
+
- All file writes delegated to subagents per R010
|