vinta-ai-workflows 0.7.0-alpha24 → 0.7.0-alpha25

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/CHANGELOG.md CHANGED
@@ -393,6 +393,26 @@ the project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
393
393
 
394
394
  ### Fixed
395
395
 
396
+ - **`open-pr.sh` posts inline comments on macOS and reports why a comment
397
+ failed.** Four bugs in the `open-pr-from-context` script, all seen while
398
+ publishing a stacked plan from a Mac:
399
+ - Trimming trailing blank lines from `# Title`, `# Description` and
400
+ `# Comments` used a GNU-only `sed` idiom. BSD `sed` fails on it with
401
+ "unused label" and trims nothing. A portable `awk` helper does it now.
402
+ - A comment with lowercase `side: right` got "422 Validation Failed" from
403
+ GitHub, so failures looked random across files. The script now converts
404
+ `side` to upper case and falls back to `RIGHT` for any other value. The
405
+ `prs-context-comments` schema still only allows `LEFT` / `RIGHT`.
406
+ - The `gh api` call threw away its stderr, so a run of failed comments
407
+ gave no reason. The CLI's error now prints on one line above each
408
+ `FAILED` line, and the comment still counts toward exit `1`. The
409
+ `glab api` call for GitLab had the same problem and gets the same fix.
410
+ - Adding entries to an existing `## Publish log` section passed several
411
+ lines through `awk -v`, which BSD `awk` rejects ("newline in string").
412
+ The entries go through the environment now.
413
+
414
+ Projects that patched their own copy can re-sync with `vinta-sync-ai-tools`.
415
+
396
416
  - **`check-ai-models` no longer mistakes sibling models for snapshots of a
397
417
  cited id.** The id matcher used substring matching, so `claude-sonnet-5`
398
418
  matched `claude-sonnet-5-5` (hiding the newer Sonnet and Opus releases).
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vinta-ai-workflows",
3
- "version": "0.7.0-alpha24",
3
+ "version": "0.7.0-alpha25",
4
4
  "description": "Bootstrap AI tooling (AGENTS.md, skills, sub-agents) across Claude Code, Codex, Cursor, and VS Code + GitHub Copilot.",
5
5
  "type": "module",
6
6
  "bin": {
@@ -25,7 +25,7 @@
25
25
  "minimum": 1
26
26
  },
27
27
  "side": {
28
- "description": "Which side of the diff the comment attaches to. `RIGHT` = post-change (default). `LEFT` = pre-change (rare; for comments on removed code).",
28
+ "description": "Which side of the diff the comment attaches to. `RIGHT` = post-change (default). `LEFT` = pre-change (rare; for comments on removed code). Write it in upper case. `open-pr.sh` also accepts lower case and sends `RIGHT` for any other value, but that is only tolerance in the script: this schema still rejects anything other than `LEFT` / `RIGHT`.",
29
29
  "type": "string",
30
30
  "enum": ["LEFT", "RIGHT"],
31
31
  "default": "RIGHT"
@@ -47,7 +47,7 @@ Pass through whatever the user explicitly asked for; otherwise no flags.
47
47
  Read the script's stdout + exit code:
48
48
 
49
49
  - **Exit 0** — PR opened (or pre-existing detected); all comments posted. File rewritten to `status: published` + `pr_url`. Surface the URL to the user; you're done.
50
- - **Exit 1** — PR opened, but one or more inline comments failed. The script's stderr lists which `(file:line)` failed. Forward the failures verbatim. Most common cause: a force-push between branch push and now invalidated the line position — re-run after pushing.
50
+ - **Exit 1** — PR opened, but one or more inline comments failed. The script's stderr lists which `(file:line)` failed, each one after a `gh error:` / `glab error:` line that holds the API's message (for example `422 Validation Failed`). Forward both verbatim. Most common cause: a force-push between branch push and now invalidated the line position — re-run after pushing.
51
51
  - **Exit 2** — Hard failure (file invalid, branch not pushed, CLI missing/unauthed, missing dependency). Forward the script's error message; do **not** improvise (don't push the branch, don't install CLIs, don't auth on the user's behalf).
52
52
 
53
53
  ## Inputs the script expects
@@ -97,6 +97,19 @@ if [[ "$STATUS" == "published" && -n "$PR_URL" && "$PR_URL" != "null" ]]; then
97
97
  exit 0
98
98
  fi
99
99
 
100
+ # awk, not sed: BSD sed (macOS) can't parse the GNU idiom for this
101
+ # (`:a;...;ba`) — it reports "unused label" and trims nothing.
102
+ trim_trailing_blank_lines() {
103
+ awk '
104
+ { lines[NR] = $0 }
105
+ END {
106
+ last = 0
107
+ for (i = 1; i <= NR; i++) if (lines[i] ~ /[^[:space:]]/) last = i
108
+ for (i = 1; i <= last; i++) print lines[i]
109
+ }
110
+ '
111
+ }
112
+
100
113
  # Body sections — split on `^# ` H1 headings.
101
114
  extract_section() {
102
115
  local heading="$1"
@@ -104,7 +117,7 @@ extract_section() {
104
117
  $0 ~ h { in_sec = 1; next }
105
118
  /^# / && in_sec { in_sec = 0 }
106
119
  in_sec { print }
107
- ' | sed -e ':a;/./,$!d;/^$/{$d;ba;}' # trim trailing blank lines
120
+ ' | trim_trailing_blank_lines
108
121
  }
109
122
 
110
123
  TITLE=$(extract_section "Title" | sed -e '/./,$!d')
@@ -237,6 +250,10 @@ FAILURES=0
237
250
 
238
251
  post_comment_gh() {
239
252
  local file="$1" start="$2" end="$3" side="$4" body="$5"
253
+ # The API only takes upper case; the schema says LEFT/RIGHT, but tolerate
254
+ # hand-written `side: right` rather than 422 on every comment.
255
+ side=$(printf '%s' "${side:-RIGHT}" | tr '[:lower:]' '[:upper:]')
256
+ [[ "$side" == "LEFT" || "$side" == "RIGHT" ]] || side="RIGHT"
240
257
  local repo commit
241
258
  repo=$(gh repo view --json nameWithOwner -q .nameWithOwner)
242
259
  commit=$(git rev-parse "origin/$BRANCH")
@@ -248,12 +265,16 @@ post_comment_gh() {
248
265
  -f "commit_id=$commit"
249
266
  -f "path=$file"
250
267
  -F "line=${end:-$start}"
251
- -f "side=${side:-RIGHT}"
268
+ -f "side=$side"
252
269
  )
253
270
  if [[ -n "$end" && "$end" != "$start" && "$end" != "null" ]]; then
254
- args+=( -F "start_line=$start" -f "start_side=${side:-RIGHT}" )
271
+ args+=( -F "start_line=$start" -f "start_side=$side" )
272
+ fi
273
+ local err
274
+ if ! err=$(gh "${args[@]}" 2>&1 >/dev/null); then
275
+ printf ' gh error: %s\n' "${err//$'\n'/ }" >&2
276
+ return 1
255
277
  fi
256
- gh "${args[@]}" >/dev/null 2>&1
257
278
  }
258
279
 
259
280
  post_comment_glab() {
@@ -264,7 +285,8 @@ post_comment_glab() {
264
285
  base_sha=$(echo "$refs" | jq -r '.base_sha')
265
286
  head_sha=$(echo "$refs" | jq -r '.head_sha')
266
287
  start_sha=$(echo "$refs" | jq -r '.start_sha')
267
- glab api --method POST \
288
+ local err
289
+ if ! err=$(glab api --method POST \
268
290
  "projects/:id/merge_requests/$PR_NUMBER/discussions" \
269
291
  -f "body=$body" \
270
292
  -f "position[base_sha]=$base_sha" \
@@ -273,7 +295,10 @@ post_comment_glab() {
273
295
  -f "position[position_type]=text" \
274
296
  -f "position[new_path]=$file" \
275
297
  -f "position[new_line]=${end:-$start}" \
276
- >/dev/null 2>&1
298
+ 2>&1 >/dev/null); then
299
+ printf ' glab error: %s\n' "${err//$'\n'/ }" >&2
300
+ return 1
301
+ fi
277
302
  }
278
303
 
279
304
  if [[ "$COMMENT_COUNT" -eq 0 ]]; then
@@ -329,7 +354,9 @@ if [[ $DRY_RUN -eq 0 ]]; then
329
354
 
330
355
  # If body already has a publish log, append entries to it; else add new section.
331
356
  if echo "$BODY" | grep -q '^## Publish log'; then
332
- NEW_BODY=$(echo "$BODY" | awk -v entries="$(printf '%s\n' "${PUBLISH_LOG[@]}" | sed 's/^/- /')" '
357
+ # Entries go through the environment: BSD awk rejects a newline in a -v value.
358
+ NEW_BODY=$(echo "$BODY" | PUBLISH_ENTRIES="$(printf '%s\n' "${PUBLISH_LOG[@]}" | sed 's/^/- /')" awk '
359
+ BEGIN { entries = ENVIRON["PUBLISH_ENTRIES"] }
333
360
  /^## Publish log/ { in_log = 1; print; next }
334
361
  /^## / && in_log { in_log = 0; print entries; print; next }
335
362
  { print }
@@ -54,7 +54,7 @@ Two project-level signals decide the actual behavior:
54
54
  The script opens the PR (or detects an existing one), posts each inline comment, rewrites the file's frontmatter to `status: published` + populated `pr_url`, appends a publish log. Exit codes:
55
55
 
56
56
  - `0` — PR up, all comments (if any) posted. Capture `pr_url` for the user update.
57
- - `1` — PR up, ≥1 comment failed. Surface the failed `(file:line)` list to the user; continue to the tracking step.
57
+ - `1` — PR up, ≥1 comment failed. Surface the failed `(file:line)` list to the user, with the `gh error:` / `glab error:` line the script printed above each one; continue to the tracking step.
58
58
  - `2` — Hard failure (deps missing, branch not pushed, CLI unauthed, file invalid). Surface the script's stderr; treat the phase as having no PR. The file stays `status: pending` so the user can re-run after fixing the gap.
59
59
 
60
60
  When policy = "branches only": **don't run the script.** File stays `status: pending`.