{"_id":"@aryrabelo/omp-green-gh","name":"@aryrabelo/omp-green-gh","dist-tags":{"latest":"0.2.0"},"versions":{"0.2.0":{"name":"@aryrabelo/omp-green-gh","version":"0.2.0","description":"OMP harness extension: the current branch's pull request status plus the repo's other open PRs in your statusline — what is green, and what is blocking it?","type":"module","license":"MIT","author":{"name":"Ary Rabelo"},"publishConfig":{"access":"public"},"repository":{"type":"git","url":"git+https://github.com/aryrabelo/omp-green-gh.git"},"homepage":"https://github.com/aryrabelo/omp-green-gh#readme","bugs":{"url":"https://github.com/aryrabelo/omp-green-gh/issues"},"keywords":["omp","oh-my-pi","pi","extension","plugin","github","pull-request","status-bar","coding-agent"],"omp":{"extensions":["./src/main.ts"]},"engines":{"bun":">=1.0.0"},"scripts":{"test":"bun test","typecheck":"tsc --noEmit","lint":"biome check .","format":"biome check --write ."},"peerDependencies":{"@oh-my-pi/pi-coding-agent":"^16.0.0","@oh-my-pi/pi-tui":"^16.0.0"},"devDependencies":{"@biomejs/biome":"^2.4.16","@oh-my-pi/pi-coding-agent":"^16.4.8","@oh-my-pi/pi-tui":"^16.4.8","@types/bun":"^1.3.0","@types/node":"^22","typescript":"^5.6.0"},"_id":"@aryrabelo/omp-green-gh@0.2.0","gitHead":"17f12d0df9adf958b7f9ebbec4ee7902dfefbadc","_nodeVersion":"22.23.2","_npmVersion":"10.9.8","dist":{"integrity":"sha512-503xtH7/ts9IGhFMTqDC1qmkeUKgoowb3pdpPZZEhureQlWcR5tpimlfxJ/xeEeiPt56Wm80x3lLFVDgDiL6LA==","shasum":"872db720e44c80e3a85edbdaa49a7c6a6d621e46","tarball":"https://registry.npmjs.org/@aryrabelo/omp-green-gh/-/omp-green-gh-0.2.0.tgz","fileCount":6,"unpackedSize":41648,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCexYZAedDV9MFwTfvtlOxGjA3LTuhkjwX+6q9pKfnh9gIgKpU8zieewjgDYRiqqQp5aNG3d/rzVzMcr/AimfXZH9w="}]},"_npmUser":{"name":"aryrabelo","email":"aryrabelo@gmail.com"},"directories":{},"maintainers":[{"name":"aryrabelo","email":"aryrabelo@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/omp-green-gh_0.2.0_1788470291824_0.3871257840497806"},"_hasShrinkwrap":false}},"time":{"created":"2026-09-03T21:18:11.651Z","0.2.0":"2026-09-03T21:18:23.274Z","modified":"2026-09-03T21:18:23.465Z"},"maintainers":[{"name":"aryrabelo","email":"aryrabelo@gmail.com"}],"description":"OMP harness extension: the current branch's pull request status plus the repo's other open PRs in your statusline — what is green, and what is blocking it?","homepage":"https://github.com/aryrabelo/omp-green-gh#readme","keywords":["omp","oh-my-pi","pi","extension","plugin","github","pull-request","status-bar","coding-agent"],"repository":{"type":"git","url":"git+https://github.com/aryrabelo/omp-green-gh.git"},"author":{"name":"Ary Rabelo"},"bugs":{"url":"https://github.com/aryrabelo/omp-green-gh/issues"},"license":"MIT","readme":"<div align=\"center\">\n\n# omp-green-gh\n\n[![CI](https://github.com/aryrabelo/omp-green-gh/actions/workflows/ci.yml/badge.svg)](https://github.com/aryrabelo/omp-green-gh/actions/workflows/ci.yml)\n[![License: MIT](https://img.shields.io/badge/license-MIT-blue.svg)](LICENSE)\n![Runtime: Bun](https://img.shields.io/badge/runtime-Bun-000000.svg?logo=bun)\n\n**Your repository's pull requests in the OMP statusline — is the current branch green,\nwhat is blocking it, and what else is open?**\n\n⭐ Star omp-green-gh on GitHub — it's a one-person project and every star helps.\n\n</div>\n\n## Table of contents\n\n- [💡 The idea](#-the-idea)\n- [🔍 Reading the lines](#-reading-the-lines)\n- [🔁 The second line](#-the-second-line)\n- [🚦 The blocker ladder](#-the-blocker-ladder)\n- [⌨️ Commands](#-commands)\n- [📦 Install](#-install)\n- [🔧 How it works](#-how-it-works)\n- [⚠️ Known limits](#-known-limits)\n- [📁 Project layout](#-project-layout)\n- [✅ Verification](#-verification)\n- [🧬 Provenance](#-provenance)\n- [🚫 Non-goals (v1)](#-non-goals-v1)\n- [🤝 Contributing](#-contributing)\n- [📄 License](#-license)\n\n## 💡 The idea\n\nYou are on a branch. There is a pull request open for it. You do not know whether it\nis green, and if it isn't, you do not know what is holding it up — so you go and look:\na browser tab, or `gh pr view`, or `gh pr checks`, every few minutes.\n\nomp-green-gh is an OMP (Oh My Pi) harness extension that answers that question where\nyou are already looking. It writes two statusline lines, through\n`ctx.ui.setStatus(\"gh-pr\", …)` and `ctx.ui.setStatus(\"gh-pr-others\", …)`:\n\n```\nPR #11 ⌛ 1/3 → Set reviewers\naryrabelo/omp-green-gh#10 draft · ❌ 1/2 → Fix CI (1/3)\n```\n\nThe first line is the current branch's pull request. The second is one of the\nrepository's *other* open pull requests, labelled `owner/repo#N`, with its position in\nthe rotation: `(1/3)` is the first of three.\n\nEach is one line on purpose. The harness statusline collapses newlines to spaces and\ntruncates to the terminal width, so the next action rides inline after the arrow\ninstead of on a row that never renders.\n\nEither line can appear without the other. On `main` there is no pull request for the\nbranch, so the first line is silent and the second still reports what is open.\n\n## 🔍 Reading the lines\n\n| Piece | What it tells you |\n| --- | --- |\n| `✅ 12/12` | Every check completed and passed — 12 of 12 passed. |\n| `⌛ 3/12` | Nothing failed, but 3 of 12 are still running or not started yet. |\n| `❌ 2/12` | 2 of 12 checks failed. |\n| `draft` | The pull request is still a draft, so it cannot merge yet. |\n| `approved` | The review decision is approval. |\n| `changes requested` | A reviewer asked for changes. |\n| `review required` | Review is still required — nobody has approved yet. |\n| `💬 2` | Two unresolved review threads are waiting on you. |\n| `conflicts` | The branch no longer merges cleanly into its base. |\n| `merged` / `closed` | Terminal state, collapsed to that one word. |\n| `owner/repo#N` | Second line only: which pull request, since it is not the branch you are on. |\n| `(1/3)` | Second line only: position in the rotation — the first of three other open pull requests. |\n| `→ ...` | The next action: the highest-priority thing blocking the merge. |\n\nThe numerator always counts whatever the icon is reporting: failures on `❌`, still-running\non `⌛`, passes on `✅`. So `❌ 2/12` is two failures, not two passes.\n\nThe check verdict follows a strict precedence: **❌ beats ⌛ beats ✅**. A failure\noutranks anything still running, and any check that is not `COMPLETED` counts as\npending. That ordering is what keeps the line honest — it can never claim green while\nCI is still in flight, which is exactly the moment a naive reading of \"no failures\nyet\" would be wrong.\n\nCheck names are normalized to strip provider prefixes, so `ci/circleci: unit` shows up\nas `unit`.\n\n## 🔁 The second line\n\nThe second line is one of the repository's other open pull requests, and it steps to\nthe next one on every redraw — a redraw being session start and the end of a turn.\nThere is no timer, so an idle session does not rotate, and a repository with three\nother open pull requests shows all three across three turns.\n\n- **Label** — `owner/repo#N`, owner and name parsed from the `origin` remote, because\n  a bare `#N` says nothing about which pull request the rotation landed on.\n- **Position** — the trailing `(i/n)`: which of the `n` other open pull requests this\n  is.\n- **Order** — by pull request number, descending, so the order is stable between\n  redraws.\n- **Which ones** — open pull requests, up to 20, minus the current branch's own (that\n  one is the first line).\n- **No \"Set reviewers\"** — `gh pr list` cannot report reviewer counts, so that rung of\n  the ladder is skipped here rather than guessed. Every other rung applies.\n- **No `💬 N`** — unresolved review threads need a GraphQL query per pull request, so\n  the second line does without the count. The first line has it.\n\nRotating is free: the list is fetched once, pre-rendered with its positions, and\ncached for 60 seconds per directory, so stepping to the next pull request only indexes\ninto an array and spawns nothing. The feature costs one extra subprocess per cache\nwindow.\n\n## 🚦 The blocker ladder\n\nThe text after the arrow is the first match in this fixed priority order, top to\nbottom:\n\n1. **Fix CI** — a check failed; the failure has to go away before anything else\n   matters.\n2. **Resolve conflicts with base** — rebase, or merge the base branch back in.\n3. **Publish draft** — take it out of draft so it can be reviewed and merged.\n4. **Resolve N review comment(s)** — N review threads are unresolved; answer or\n   resolve them.\n5. **Set reviewers** — nobody is on the hook to review it yet.\n6. **Address changes requested** — a reviewer blocked it; push the fixes.\n7. **Waiting for approval** — it is on the reviewers now, not on you.\n8. **CI running** — nothing to do but wait for the checks to finish.\n9. **Merge PR** — nothing is blocking it.\n\n## ⌨️ Commands\n\n| Command | What it does |\n| --- | --- |\n| `/gh-open` | Opens the current branch's pull request in your browser, via `gh pr view --web`. |\n| `/gh-open 7` or `/gh-open #7` | Opens pull request 7. An argument that is not a number is refused before any subprocess runs. |\n| `/green` | Hands the agent a prompt to get the current branch's pull request green. |\n\n`/green` runs nothing itself. It sends the agent a request to inspect the pull request\nwith `gh` — the failing checks and their logs, the unresolved review threads with the\nbody of every comment, whether the branch is behind its base, any merge conflict —\nthen fix what is fixable in the working tree and report what it changed and what it\nleft alone. The prompt tells it not to merge and not to force-push.\n\n## 📦 Install\n\nPrerequisites:\n\n- [Bun](https://bun.sh) >= 1.0.0\n- [`gh`](https://cli.github.com) on your `PATH` and authenticated (`gh auth status`)\n\n```sh\nbun install\nln -s \"$PWD/src/main.ts\" ~/.omp/agent/extensions/omp-green-gh.ts\n```\n\nUser-level extensions are auto-discovered from `~/.omp/agent/extensions/` — `.ts` and\n`.js` files, symlinks included — so the symlink is the whole installation step. Start\nOMP in a repository with an open pull request and the lines appear.\n\n> [!NOTE]\n> If `gh` is missing or unauthenticated, both lines stay silent. There is no error and\n> no warning, so a blank statusline in a repository you know has open pull requests is\n> worth checking with `gh auth status` first.\n\nTo turn it off without uninstalling, in `~/.omp/agent/config.yml`:\n\n```yaml\ndisabledExtensions:\n  - extension-module:omp-green-gh\n```\n\n## 🔧 How it works\n\nFive subprocesses at most, each capped at 8 seconds:\n\n1. `git branch --show-current`\n2. `git remote get-url origin`\n3. `gh pr view <branch> --repo <origin> --json\n   number,url,state,isDraft,mergeable,reviewDecision`\n4. `gh api graphql` on the pull request url — unresolved review threads, reviewers,\n   and the check rollup\n5. `gh pr list --repo <origin> --state open --limit 20 --json\n   number,url,isDraft,mergeable,reviewDecision,statusCheckRollup` — every other open\n   pull request, in one round trip, for the second line\n\nOn a trunk branch, 3 and 4 are skipped: only the git pair and the list call run.\n\nThe owner and repository name always come from the `origin` remote, never from\nconfiguration. That is the point: the same extension works in every checkout you open\nwithout being told where it is. SSH remotes work too, since `gh` accepts the SSH URL\nas `--repo`.\n\nThe GraphQL call exists because `gh pr view --json` cannot report unresolved review\nthreads at all. The `💬 N` count and the \"Resolve N review comment(s)\" rung of the\nladder are only possible through GraphQL, so the detail query is a separate step\nrather than a nicety.\n\nThe list call is one round trip for all of them on purpose. A GraphQL query per pull\nrequest would buy the second line its `💬 N` count and its reviewer check at a cost of\nup to 20 subprocesses; it goes without both instead.\n\nIt has no credentials of its own — `gh` owns authentication. It makes no network call\ndirectly, keeps no configuration file, writes no files, and sends no telemetry.\n\nRefresh is event-driven: both lines are redrawn on `session_start` and `turn_end`,\nfire-and-forget, so a turn never blocks waiting on `gh`. The answer is cached for 60\nseconds per directory, which means an idle session spends no subprocesses at all.\n\nA line is cleared — not left stale — whenever it has nothing to say: `setStatus` is\ncalled with `undefined`, which removes the segment, where `\"\"` would leave an empty one\nbehind. The first line is silent when there is:\n\n- no git repository\n- a trunk branch: `main`, `master`, `trunk`, or `develop`\n- no `origin` remote\n- no pull request for the branch\n- no `gh`, or an unauthenticated one\n\nThe second line is silent when there is no `origin` remote, when `origin` is a url\n`repoSlug` will not parse, when `gh` is missing or unauthenticated, or when the\nrepository has no other open pull request.\n\nMerged and closed pull requests collapse to one word and skip the detail query. The\nwhole extension is a no-op when `ctx.hasUI` is false, so headless, print, and subagent\nruns cost nothing.\n\n## ⚠️ Known limits\n\n- **No colour and no clickable link.** The extension emits ANSI colours and an OSC 8\n  hyperlink on the pull request number, and neither survives the harness statusline —\n  what you see is the emoji and the plain text. That is why the rendering leans on\n  emoji, and why `/gh-open` exists.\n- **`origin` urls with inline credentials are not parsed.** `repoSlug` accepts\n  `git@host:owner/repo`, `ssh://git@host/owner/repo` and `https://host/owner/repo`,\n  with or without `.git`. It rejects a remote like\n  `https://user:token@host/owner/repo`, and the second line is simply absent for such\n  a checkout. The first line still works there, because it hands the raw `origin` url\n  to `gh --repo`.\n- **The second line carries no `💬 N` and never says \"Set reviewers\"** — see\n  [The second line](#-the-second-line).\n- **20 pull requests at most** in the rotation — that is `gh pr list --limit 20`.\n- **Failures are silent.** A missing or unauthenticated `gh`, a timeout, or malformed\n  json produces no line and no warning.\n\n## 📁 Project layout\n\n```\nsrc/\n  pr-status.ts    the gh calls plus the pure functions: the check fold, the verdict,\n                  the blocker ladder, the rendering, the rotation, the origin parse\n  main.ts         wiring only: the session events into ctx.ui.setStatus, and the\n                  /gh-open and /green commands\ntests/\n  pr-status.test.ts   the pure functions, case by case\n  main.test.ts        the wiring, the commands, and the silence conditions\n```\n\n44 tests, run with `bun test`.\n\n## ✅ Verification\n\n```sh\nbun run lint && bun run typecheck && bun test\n```\n\n## 🧬 Provenance\n\nomp-green-gh is a port of the PR block of the CNX Claude Code statusline\n([aryrabelo/cnx-claude](https://github.com/aryrabelo/cnx-claude)):\n`cnx/scripts/lib/pr-status.ts` for the data, and the `getNextAction` ladder of\n`cnx/statusline/statusline.ts` for the arrow.\n\nEverything installation-specific was cut so it runs in any repository:\n\n| CNX | here |\n| --- | --- |\n| hardcoded `entrc/entrc-backend` repository | owner and repository from `origin` |\n| CircleCI check-group name lists | every check, folded into one verdict |\n| `preview-app` / `canix-UAT` label squares | dropped |\n| Linear and Jira gates | dropped |\n| `/cnx:` command suffixes on the next action | plain action text |\n\n## 🚫 Non-goals (v1)\n\n- No pull request management from the extension itself: it never merges, approves,\n  comments, or labels. `/gh-open` opens a browser, and `/green` asks the agent — with\n  instructions not to merge and not to force-push.\n- No background watcher and no refresh timer — it redraws on session events only.\n- No forge other than GitHub, and no GitHub access that bypasses `gh`.\n- No cross-repository dashboard: both lines describe the `origin` of the current\n  directory, and the second is capped at 20 open pull requests.\n- No configuration file: no custom thresholds, no per-repo check groups, no label\n  rules, no way to change the rotation or its order.\n- No ticket-tracker integration (Linear, Jira) — deliberately cut from the CNX\n  original.\n- No desktop or terminal notifications.\n\n## 🤝 Contributing\n\nBug reports, feature ideas, and pull requests are welcome. See\n[CONTRIBUTING.md](CONTRIBUTING.md) for how to set up the project, the verification a\nchange has to pass, and the scope this project keeps (see **Non-goals** above).\nSecurity issues: please follow [SECURITY.md](SECURITY.md) instead of opening a public\nissue.\n\n## 📄 License\n\n[MIT](LICENSE) © Ary Rabelo\n","readmeFilename":"README.md","_rev":"1-fbde5d6a85cce2e5478df90a2d670a25"}