Skip to content

Commit 2a80904

Browse files
feat(pm): pm:mailbox label and the mailbox-open.mjs opener/closer (#25417) (#25433)
<!-- claude-projects-attribution: {"github_login":"os-elon-musk"} --> _Requested by **Elon** · [project thread](https://claude.ai/code/project/chan_01WedDzV26nniwxv7jC88B9D?thread=cmsg_01WedDzV26nniwxv7jC88B9DCMDFdvcggLAgVyfdkyY9Mj)_ Fixes #25417 Dispatched by the `domain:devx` seat 1 (#6023); Claim on #25417 names `claude/project-thread-9gk9rn`. ## What changed - **`scripts/pm/ensure-pm-labels.sh`**: `pm:mailbox` in the five-repo loop (objectstack, objectui, cloud, objectos, hotcrm). Description, 92 chars: *A project's cross-account mailbox PR — never merged, owes no CI, excluded from every ledger*. `check:pm-label-desc-cap` green (42 descriptions, all ≤100). - **`scripts/pm/mailbox-open.mjs`** (new): - `--repo <slug> --login <login>`: ① reads the open pulls and refuses (exit 4) if an open `pm:mailbox` PR already belongs to that login (head `mailbox/<login>` or body line `Mailbox-of: <login>`); ② builds one empty commit on `origin/<base>` with `git commit-tree` (no checkout, index or working tree touched) and pushes it as `mailbox/<login>` through `with-fleet.sh --kind 'git push'`; ③ sends one relay stroke, `pr_create` labelled `pm:mailbox` + `skip-changeset` (draft is forced by the relay); ④ reads the number back off the head and prints it for `subscribe_pr_activity`. - `--head <branch>` uses an existing branch instead of pushing (refuses unless it is ahead of base). This is the route for a cloud seat, because the relay has no ref-creating op and with-fleet refuses a push there. - `--close <n>` reads the pull first and refuses anything but an open `pm:mailbox` PR, then sends `comment` + `issue_patch state: closed` in one stroke. - `--dry-run` is offline (no read, no git, no dispatch) and prints the actions file after the relay's own `validateStroke` has judged it. - Exports `LEDGER_EXCLUSION = '-label:pm:mailbox'` for ledger readers to import (the roster card #25416 and any future landing query). ## Ledger exclusion: what the grep found `git grep -n 'head:claude/' scripts/pm` → **0 hits**, and no script under `scripts/pm/` enumerates open PRs for landing today. The only `head:claude/` reader is prose in `.claude/skills/pm-dispatch/references/landing-operations.md` L26. That file is `.claude/**`, outside this card, and belongs to the sibling skills card for the mailbox protocol. `board-snapshot.mjs` lists every open pull, but only for its archive count check (`open_issues_count` minus open pulls), and there a mailbox **must** be counted. So it is deliberately left unchanged. ## CI exemption `Check Changeset` was the check measured red on #25392's empty diff, and the `changeset-check` job already skips wholesale on `skip-changeset`, which the opener applies. Any other red on a mailbox is declared **red by design** in the body the script writes, so a subscribed thread reads the exemption on the PR itself. ## Not done here, on purpose - The self-test is **not wired into `lint.yml`**. Adding a `check:pm-mailbox-open` step touches `.github/workflows/**`, which flips this PR to Tier H and is outside the dispatched file surface. `check:self-test-wired` stays green without it, because CI does not run the script. Wiring it is a one-step follow-up if the seat wants it. - The script is written here and never run: pushing `mailbox/<login>` is outside this session. ## Verification - `node scripts/pm/mailbox-open.mjs --self-test` → `✓ 40 cases in 7 batteries pass` (battery roster, floor and verdict handshake per AGENTS.md). - `node scripts/pm/mailbox-open.mjs --repo objectstack-ai/objectstack --login os-elon-musk --dry-run` prints the plan and the actions file, exit 0. That file fed to `fleet-write/dispatch.mjs --dry-run` packs without refusal. - `check-governed-merges.mjs --test scripts/pm/mailbox-open.mjs scripts/pm/ensure-pm-labels.sh` → NOT governed (Tier S). - `check-self-test-wired`, `check-step-collectors`, `check-workflow-status-functions` → exit 0. No changeset: scripts-only, publishes nothing (`skip-changeset`). 🤖 Generated with [Claude Code](https://claude.com/claude-code) https://claude.ai/code/session_012EdvwY3utqfHhXSgGvyBHB --- _Generated by [Claude Code](https://claude.ai/code/session_012EdvwY3utqfHhXSgGvyBHB)_ Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: objectstack-fleet[bot] <332303061+objectstack-fleet[bot]@users.noreply.github.com>
1 parent ecb4e69 commit 2a80904

2 files changed

Lines changed: 500 additions & 0 deletions

File tree

‎scripts/pm/ensure-pm-labels.sh‎

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,16 @@ for R in objectstack-ai/objectstack objectstack-ai/objectui objectstack-ai/cloud
303303
# at the hard cap (check:pm-label-desc-cap).
304304
gh label create tooling -R "$R" -c fbca04 -d "Fix lands in tooling, not a product package — enters pm:queue only with Unblocks: or a named surface" 2>/dev/null || true
305305
gh label create pm:epic -R "$R" -c 5319e7 -d "Reserved by a dedicated epic PM, parent or sub-issue; other PMs never take it; never with pm:queue" 2>/dev/null || true
306+
# pm:mailbox marks a project's cross-account mailbox PR (#25417): a draft PR
307+
# on `mailbox/<login>` that a resident thread subscribes to, because a PR
308+
# comment wakes a subscribed session and an issue comment wakes nothing
309+
# (measured on #25392: 70 s from the relay, 4 s from a second account). It is
310+
# never merged and closed on account handover. Named consumers: every query
311+
# that enumerates open PRs for landing appends `-label:pm:mailbox`
312+
# (LEDGER_EXCLUSION, scripts/pm/mailbox-open.mjs, the one opener and closer),
313+
# and a subscribed thread reads it as "owes no CI". In this five-repo loop
314+
# because a lane project may keep its mailbox on any board it works.
315+
gh label create pm:mailbox -R "$R" -c c5def5 -d "A project's cross-account mailbox PR — never merged, owes no CI, excluded from every ledger" 2>/dev/null || true
306316
done
307317

308318
# needs:pack-smoke — the opt-in pre-merge pack smoke (#14214, derived from the

0 commit comments

Comments
 (0)