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.
@@ -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 workflow-runner supports this via `context: fork` on individual steps. Anthropic's research confirms "context resets provide clean slates superior to compaction" for long-running evaluation.
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 via Airflow DAG when gh CLI is unavailable or when anonymity is requested.
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 or submit anonymously — without leaving their terminal session. All feedback is filed to the `baekenough/oh-my-customcode` repository.
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 + NOT anonymous
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
- **Route B**: anonymous OR not authenticated (gh available)
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 + not anonymous)
96
+ ### Phase 4A: GitHub Issue Creation (Route A — gh + authenticated)
106
97
 
107
- 1. Show the user a preview of the issue to be created:
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
- 2. Ask for confirmation before creating
108
+ 3. Ask for confirmation before creating
116
109
 
117
- 3. Ensure labels exist (defensive):
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
- 4. Create the issue using `--body-file` for safe markdown handling:
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 "feedback,{category_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
- 5. If label creation fails AND issue creation fails due to labels, retry without labels as fallback
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
- On failure (non-2xx or network error), fall through to Fallback.
160
+ 7. Return the issue URL to the user
200
161
 
201
- ### Phase 4D: Local Fallback (no gh, no curl, or all routes failed)
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 or curl is available
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 | Airflow feedback_type |
231
- |----------|--------------|-----------------------|
232
- | bug | bug | bug |
233
- | feature | enhancement | feature |
234
- | improvement | enhancement | improvement |
235
- | question | question | question |
236
- | (auto-detect fails) | (none) | general |
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
- - Routes B and C submit anonymously submitter identity is not recorded
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