Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 39 additions & 6 deletions .github/skills/devin-review/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,19 +70,52 @@ chrome-devtools new_page "https://app.devin.ai/review/<owner>/<repo>/pull/<numbe
sleep 6
```

Close this tab when done to avoid accumulating isolated-context tabs.
**Pin to the right tab and verify the PR before reading anything.** Multiple PR reviews
opened in the same `devin-noauth` context are separate tabs that all share that context, and
`evaluate_script`/`take_snapshot` operate on whatever page is currently *selected* — which can
drift to another PR's tab. So always select your tab explicitly and confirm the page header
shows the PR you expect:

### 2. Check if Review is Complete
```bash
chrome-devtools list_pages # find the index of YOUR pull/<number> tab
chrome-devtools select_page <id> # pin future calls to it
chrome-devtools evaluate_script "() => (document.body.innerText.match(/PR #\d+/)||['?'])[0]"
# → must print "PR #<number>". If not, you are about to read the wrong review.
```

Close stray tabs when done to avoid accumulating isolated-context tabs.

### 2. Check if Review is Complete — beware STALE results

Reviews take a while (**10–20+ minutes**), and a **new push invalidates the prior review**:
Devin keeps showing the *old* commit's findings, prefixed with an **"Outdated"** badge, until
the re-review of the new HEAD finishes. So "I see `1 Bug` / `6 Flags`" does **NOT** mean the
results are current — you must check they are not marked Outdated.

Do **not** grep `document.body.innerText` for status. The page embeds the entire diff inline,
so keywords like `pending`, `complete`, `reviewing`, and even commit SHAs match diff/source
text and give false positives. Read the finding **buttons** in the sidebar instead:

```bash
chrome-devtools evaluate_script "() => document.body.innerText" 2>/dev/null | grep -E "Bug|Flags"
chrome-devtools evaluate_script "() => { const b=[...document.querySelectorAll('button')]; const headers=b.filter(x=>/\d+\s+(Bug|Flag)s?/.test(x.textContent)).map(x=>x.textContent.trim().replace(/\s+/g,' ')); return JSON.stringify(headers); }"
```

- If you see lines like `1 Bug` or `6 Flags` → review is complete. Proceed to step 3.
- If the page shows only a loading state or no Bug/Flags section → review is not yet done. Report "Devin review not yet complete" and return. Come back in 5–10 minutes.
- Headers like `"1 Bug"`, `"6 Flags"` with **no** `Outdated` prefix → review is current for the
selected commit. Proceed to step 3.
- Headers like "Outdated 1 Bug", "Outdated 6 Flags" → these are the *previous* commit's
results; the re-review is still running. Report "Devin re-review still in progress" and come
back in 5–10 minutes. Re-checking requires a reload (`chrome-devtools navigate_page --type reload`).
- No Bug/Flags buttons at all → review hasn't produced results yet; come back later.
- Timeout after 30 minutes total from trigger.

The review typically takes 10–20 minutes from first page navigation.
**There is no GitHub-side signal.** Devin does not post a commit status/check, so `gh pr checks`
will not tell you whether the review is done — the web UI is the only source. (A "pending"
entry in Devin's commit-status popup is some *other* GitHub check, e.g. `code-review/reviewable`,
not Devin.)

**Do not pre-judge the findings.** Even when a push looks purely mechanical (e.g. a master
merge), wait for the non-Outdated results and enumerate them — don't assume the prior set
carries over.

### 3. Enumerate Findings

Expand Down
125 changes: 125 additions & 0 deletions .github/skills/pr-kanban-sync/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
---
name: pr-kanban-sync
description: State machine and scripts for keeping Orca board, GitHub Projects board, and YouTrack in sync as PRs move through review stages. Use these scripts instead of raw GraphQL or direct CLI calls whenever moving a PR between stages.
argument-hint: "status to move to: waiting-ai | in-review | has-comments | completed"
user-invocable: true
---

# PR Kanban Sync

## Overview

Three systems track the same PRs. They must stay aligned:

| State key | Orca column | GitHub board | YouTrack |
|---|---|---|---|
| `waiting-ai` | Waiting on AI Review | Waiting for AI-Review | In Progress |
| `in-review` | In human review | Ready for Human | Ready For Code Review |
| `has-comments` | Has Comments | Has Comments | Has Comments |
| `completed` | completed (archived) | auto-hidden on merge | leave for human |

## Scripts

Both scripts live at `scripts/` in the repo root and require Node.js 18+.

### `sync-move.mjs` — move one item manually

```bash
# Move all three systems at once (preferred):
node scripts/sync-move.mjs all <pr-number> <status-key>

# Individual systems:
node scripts/sync-move.mjs gh <pr-number> <status-key>
node scripts/sync-move.mjs orca <worktree-path> <status-key>
node scripts/sync-move.mjs yt <BL-xxxxx> <status-key>
```

`all` resolves the Orca worktree via `linkedPR` and the YouTrack issue via BL# from branch → display name → PR title → PR body. If either lookup fails it warns and skips that system; use the individual subcommands as fallback.

Requires env var `YOUTRACK` (YouTrack permanent token).

### `sync-pr-status.mjs` — polling reconciler (zero tokens)

```bash
node scripts/sync-pr-status.mjs
```

Reads all Orca worktrees with `linkedPR` set, fetches GitHub board status in one batch call, and updates any Orca worktrees + YouTrack issues that are out of sync. Intended to run every 15 minutes via Orca automation (see **Automation** below). Also safe to run manually to force a re-sync.

## State Machine

```
[PR opened / first push]
→ node scripts/sync-move.mjs all <pr> waiting-ai

[Devin and CI finish cleanly → ready for human]
→ node scripts/sync-move.mjs all <pr> in-review

[Human reviewer: CHANGES_REQUESTED]
→ node scripts/sync-move.mjs all <pr> has-comments

[Author pushes new commits while in has-comments or in-review]
→ node scripts/sync-move.mjs all <pr> waiting-ai (restart bot-wait)

[PR merged or closed]
→ node scripts/sync-move.mjs all <pr> completed
(YouTrack is skipped for completed — type-dependent, leave for human)
```

## GitHub Board Reference

Project: **PR Review Tracker** — https://github.com/orgs/BloomBooks/projects/2

GraphQL IDs (hardcoded in `sync-move.mjs` — do not re-query unless they stop working):
- Project ID: `PVT_kwDOAFlSFM4Bawkp`
- Status field ID: `PVTSSF_lADOAFlSFM4BawkpzhVl0_w`
- Option IDs: `97860183` (Waiting for AI-Review), `05eedb52` (Ready for Human), `99a3f545` (Has Comments)

## Adding a PR to the Board

`sync-move.mjs` only updates items already on the board. To add a new PR:

```bash
PR_NODE_ID=$(gh pr view <number> --repo BloomBooks/BloomDesktop --json id --jq '.id')
gh api graphql -f query="mutation {
addProjectV2ItemById(input: {
projectId: \"PVT_kwDOAFlSFM4Bawkp\"
contentId: \"$PR_NODE_ID\"
}) { item { id } }
}"
# Then immediately set its status:
node scripts/sync-move.mjs gh <pr-number> waiting-ai
```

## Automation (15-minute polling)

Register once per machine (the automation targets the `master-2` worktree as a stable shell host):

```powershell
orca automations create `
--name "Sync PR Status" `
--trigger "*/15 * * * *" `
--workspace "path:D:/orca-worktrees/bloom/master-2" `
--reuse-session `
--prompt "Run this command and report its output: node scripts/sync-pr-status.mjs" `
--provider claude `
--json
```

To list or remove:
```bash
orca automations list --json
orca automations remove <automationId> --json
```

## Known Limitations

- `all` and the polling script only update Orca if `linkedPR` is set on the worktree. Orca sets this automatically when a PR is opened through its UI. If you created the PR via `gh pr create`, link it manually:
```bash
# Not yet supported by orca CLI — use individual subcommands as fallback
node scripts/sync-move.mjs gh <pr> <status>
orca worktree set --worktree active --workspace-status <orca-status>
node scripts/sync-move.mjs yt <BL-xxxxx> <status>
```
- YouTrack is skipped if no `BL-xxxxx` appears anywhere in the branch name, display name, PR title, or PR body.
- The `completed` transition leaves YouTrack alone (bug vs feature determines the final state there).
83 changes: 25 additions & 58 deletions .github/skills/pr-ready-for-human/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,14 @@ When the user says **"This is ready for human review"** (or equivalent), execute

When the user pushes a new commit to a PR that is already in a review state, re-enter at **Stage 4** (reset to bot-wait).

## GitHub Project Board Reference
Project: **PR Review Tracker** — https://github.com/orgs/BloomBooks/projects/2
## Board & Sync Reference
All Orca / GitHub board / YouTrack moves use the scripts documented in the `pr-kanban-sync` skill. Status keys: `waiting-ai` | `in-review` | `has-comments` | `completed`.

GraphQL IDs (hardcoded — do not re-query unless these stop working):
- Project ID: `PVT_kwDOAFlSFM4Bawkp`
- Status field ID: `PVTSSF_lADOAFlSFM4BawkpzhVl0_w`
- Status option IDs:
- `97860183` → "Waiting for AI-Review"
- `99a3f545` → "Has Comments"
- `05eedb52` → "Ready for Human"
```bash
node scripts/sync-move.mjs all <pr-number> <status-key>
```

See `.github/skills/pr-kanban-sync/SKILL.md` for IDs, limitations, and individual-system fallbacks.

## Stage 1: Committed & Pushed

Expand Down Expand Up @@ -66,54 +64,34 @@ curl -s -X POST "https://issues.bloomlibrary.org/youtrack/api/issues/<issue-id>/
-d "{\"text\": \"PR: <PR URL>\"}"
```

If `$YOUTRACK_TOKEN` is not set, tell the user: "I need a YouTrack API token to post the PR link. Set `YOUTRACK_TOKEN` in your environment or post the comment manually: PR: <PR URL>"
If `$YOUTRACK` is not set, tell the user: "I need a YouTrack API token to post the PR link. Set `YOUTRACK` in your environment or post the comment manually: PR: <PR URL>"

## Stage 4: GitHub Project Board — Add to Project & Set "Waiting for AI-Review"

### Find or add the PR's project item
### Ensure the PR is on the board
Check if it's already there:
```bash
gh api graphql -f query='{
repository(owner:"BloomBooks", name:"BloomDesktop") {
pullRequest(number:<PR-number>) {
projectItems(first:10) {
nodes { id project { number } }
}
}
}
}'
gh project item-list 2 --owner BloomBooks --format json --limit 200 | \
node -e "const d=JSON.parse(require('fs').readFileSync('/dev/stdin','utf8')); console.log(d.items.find(i=>i.content?.number===<PR-number>)?.id ?? 'not found')"
```

If the PR is not in project 2, add it:
If not on the board, add it:
```bash
gh api graphql -f query='mutation {
PR_NODE_ID=$(gh pr view <number> --repo BloomBooks/BloomDesktop --json id --jq '.id')
gh api graphql -f query="mutation {
addProjectV2ItemById(input: {
projectId: "PVT_kwDOAFlSFM4Bawkp"
contentId: "<PR node id>"
projectId: \"PVT_kwDOAFlSFM4Bawkp\"
contentId: \"$PR_NODE_ID\"
}) { item { id } }
}'
```

Get the PR node ID with:
```bash
gh pr view <number> --repo BloomBooks/BloomDesktop --json id --jq '.id'
}"
```

### Set Status to "Waiting for AI-Review"
### Set all three systems to "waiting-ai"
```bash
gh api graphql -f query='mutation {
updateProjectV2ItemFieldValue(input: {
projectId: "PVT_kwDOAFlSFM4Bawkp"
itemId: "<itemId>"
fieldId: "PVTSSF_lADOAFlSFM4BawkpzhVl0_w"
value: { singleSelectOptionId: "97860183" }
}) { projectV2Item { id } }
}'
node scripts/sync-move.mjs all <pr-number> waiting-ai
```

### Also reset Orca card to "in-progress" if re-entering after a commit
```bash
orca worktree set --worktree active --workspace-status in-progress --json
```
This sets GitHub board → "Waiting for AI-Review", Orca → "status-5" (Waiting on AI Review), YouTrack → "In Progress". If `all` warns about a missing Orca link, fall back to individual commands (see `pr-kanban-sync` skill).

## Stage 5: Bot-Review Wait Cycle

Expand Down Expand Up @@ -153,29 +131,18 @@ If the user says "skip bots, just move it to human review" → honor explicitly

## Stage 6: Move to "Ready for Human"

### GitHub project board
```bash
gh api graphql -f query='mutation {
updateProjectV2ItemFieldValue(input: {
projectId: "PVT_kwDOAFlSFM4Bawkp"
itemId: "<itemId>"
fieldId: "PVTSSF_lADOAFlSFM4BawkpzhVl0_w"
value: { singleSelectOptionId: "05eedb52" }
}) { projectV2Item { id } }
}'
node scripts/sync-move.mjs all <pr-number> in-review
```

### Orca board
```bash
orca worktree set --worktree active --workspace-status in-review --json
```
This sets GitHub board → "Ready for Human", Orca → "in-review", YouTrack → "Ready For Code Review".

### Report
"PR #<number> is now in **Ready for Human** review. PR: <URL>"

## Re-entry After a New Commit
When a commit is pushed to a PR already in "Ready for Human" or "Has Comments":
1. Re-run Stage 4 (set project card back to "Waiting for AI-Review", set Orca to "in-progress").
1. Re-run Stage 4 (`node scripts/sync-move.mjs all <pr> waiting-ai` — resets all three systems).
2. Re-run Stages 5–6 (new bot-wait cycle, then back to human when quiet).

The whole cycle must restart because bots re-run on every commit.
Expand All @@ -185,5 +152,5 @@ The whole cycle must restart because bots re-run on every commit.
- Never move to "Ready for Human" without Devin having run.
- Always check for duplicate YouTrack comments before posting.
- Always post Devin findings as GitHub PR comments before moving to any review state.
- If `YOUTRACK_TOKEN` is unavailable, note it and continue — the YouTrack comment is the lowest-stakes step.
- If `YOUTRACK` is unavailable, note it and continue — the YouTrack comment is the lowest-stakes step.
- If the Orca browser is unavailable for Devin, tell the user what URL to open manually.
Loading