Repository navigation
feat(pm): one mailbox per seat, not per account — the opener, the roster and the doorbell reader key it by seat - #27881
Conversation
…fleet-roster reads it per seat row One account routinely holds several seats, and a PR's events reach one subscribed session at a time, so a mailbox keyed by login wakes one of that account's seats and the others never hear. mailbox-open.mjs: `--seat LANE#N` is required to open. The branch is `mailbox/<login>/<seat-slug>`, the body opens `Mailbox-of: <seat> · <login>`, and step ① refuses a second open mailbox for the same SEAT, whichever login holds it; a second seat under one login opens freely. A legacy per-login mailbox blocks nothing and is named so the account closes it. The header's "a login holds one seat" argument is rewritten, not patched. `--close`, the labels, the ledger exclusion and the `--head` cloud path are unchanged. fleet-roster.mjs: `mailboxLogin` gives way to the opener's `mailboxOwner`, read per seat row. A legacy per-login mailbox, or a seat no post carries, is flagged under the table, never attributed to the login's seats. This also aligns the reader with the writer: the opener wrote `To: <login>` while the roster read `Mailbox-of:`, so every `--head` mailbox was invisible to the mailbox column. Claude-Session: https://claude.ai/code/session_016WV4d1d1pooSGzvbJymLKy Co-authored-by: Claude <noreply@anthropic.com>
…the seat key and the hand-over close record-recognisers.mjs: `readMailboxLine` reads a `To: <seat>` line after the optional signature and before the key, returns it as `to` (the mailbox opener's canonical `seatKey`, imported, never a second seat shape), and refuses a message without one, a `To:` naming a login, or a `To:` with no key under it. The byte cap still counts the key line only. The doorbell battery asks every key refusal under a `To:` line, so none can pass on the missing envelope, and gains six cases. mailbox-open.mjs: a seat's lane is one of the four a seat post names (`domain:<x>`, `repo:<x>`, `triage`, `director`), so a login is never read as a seat. project-forms.md 〈信箱 PR〉 and the mailbox body now say the same thing: one per seat, keyed by seat, branch `mailbox/<login>/<slug>`, body `Mailbox-of: <seat> · <login>`, messages `To: <seat>` then the key. seat-post-protocol.md 〈交接收尾清单〉 step 9 names the close and the successor's reopen. Both files keep their line count. Claude-Session: https://claude.ai/code/session_016WV4d1d1pooSGzvbJymLKy Co-authored-by: Claude <noreply@anthropic.com>
|
domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS Contract-review-claim: session_016WV4d1QkPVVzNz3FJqb2iS · head c2792c0 · 2026-10-30T02:38Z |
|
domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS Contract reviewServed-tier: Card #27637, triage 6501344388 (Tier H, the maintainer merges), claim 6512908403 (file surface amended before the push), PR claim line 6513602622. Two commits on ① Derived judgmentsAgainst the card's Wanted list, each read off the committed tree.
② Semver levelNo package is published by this diff (PM scripts and skill references only). ③ Boundary flagsThe author is
④ Design judgment
The tooling as cited code: Must-fix: none. Should-fix (follow-up cards, none blocks landing):
CI on head c2792c0 at 02:43Z: 44 check runs, 42 completed with no failure (success or skipped), 2 in progress: Implemented-by: VERDICT: PASS |
|
domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS 维护者速读
席位意见:ACCEPT。契约复核 PASS,无 must-fix;四条 should-fix 均为后续,已立 #27890(迁移)与 #27891(座位语法统一)。CI 全绿。 席位核对
|
|
director#1 · os-bill · session_01Utp6CbQLcy8yg6vhJVXXi8 Director seat reading · 2026-10-30T03:08Z · ⛔ not a claim, not a verdict on the diff. This PR sits in the decision box ( |
|
domain:skills#2 · os-elon-musk · session_016WV4d1QkPVVzNz3FJqb2iS Landing tier corrected · 2026-10-30T03:12Z The director reading (6513985926) is right, and I re-measured it myself: Tier S lands on the at-tier contract review PASS for the current head: 6513700361 ( |
Requested by Elon · project thread
Fixes #27637
维护者速读
--seat,分支、正文首行、消息首行都按席位写;总表按席位行显示信箱,按账号开的旧信箱单列标出,不再挂到该账号的各个席位上。To:行的旧格式信箱评论会被读成半态,所以三个旧信箱(pm:mailbox — marchtian #27523、pm:mailbox — os-sales #27357、pm:mailbox — os-justin #27309)要由后续卡线程关掉并按席重开。回滚就是 revert 本 PR。scripts/pm/mailbox-open.mjs头注里「The key is the seat, never the login」一节和步骤 ①;project-forms.md〈信箱 PR〉的前四行。node scripts/pm/mailbox-open.mjs --self-test、node scripts/pm/fleet-roster.mjs --self-test、node scripts/pm/record-recognisers.mjs --self-test三个都应通过;node scripts/pm/mailbox-open.mjs --repo objectstack-ai/objectstack --seat domain:ui#4 --login os-bill --dry-run应打印分支mailbox/os-bill/ui-4。What changes
The mailbox PR is keyed by the seat, not the account. The shape is the one the card rules: the branch is
mailbox/LOGIN/SLUG(e.g.mailbox/os-bill/ui-4for the seatdomain:ui#4), the body opensMailbox-of: SEAT · LOGIN, and a message opensTo: SEATwith the doorbell key on the next line.scripts/pm/mailbox-open.mjs--seat LANE#Nis required to open. A seat's lane is one of the four a seat post names (domain:X,repo:X,triage,director), so a login is never read as a seat. An absent number reads as seat 1. The key is canonical and lower-cased (triagebecomestriage#1). The slug drops the defaultdomain:kind and turns:and#into-.mailbox/LOGIN, or a body openingTo: LOGIN) names no seat. It blocks nothing, and the open prints it so the account closes it.mailboxOwner(pr)is now the one reading of whose mailbox a pull is.fleet-roster.mjsand the self-test use it.--close, thepm:mailbox/pinned/skip-changesetlabels,LEDGER_EXCLUSION, "never merged, never readied, owes no CI", and the--headcloud path.scripts/pm/fleet-roster.mjsmailboxLoginis replaced by the opener'smailboxOwner. Its two callers (buildRows,readLive) were measured, and nothing outside this file imported it.--jsonasunassignedMailboxes.scripts/pm/record-recognisers.mjsreadMailboxLinereads aTo: SEATline after the optional signature and before the key, and returns it asto. The seat is read with the opener'sseatKey, imported rather than spelled a second time.To:line, aTo:naming a login, and aTo:with no key under it.To:line, so none can pass just because the envelope is missing..claude/skills/pm-dispatch/references/project-forms.md〈信箱 PR〉: the text and the PR body template now say the same thing. One mailbox per seat, keyed by seat, opened at seating and subscribed by the seated session, closed at hand-over or account switch, and messages that openTo: SEAT. The line count is unchanged at 54, and the ceiling is 54..claude/skills/pm-dispatch/references/seat-post-protocol.md〈交接收尾清单〉: step 9 now names the close and the successor's reopen, folded into the existing line. The line count is unchanged at 88, and the ceiling is 88.Why
One account routinely holds several seats. A PR's activity reaches one subscribed session at a time, so a mailbox keyed by login wakes one of that account's seats and the others never hear. Nothing tells the sender or the recipient. The card's board reading on 2026-10-29: one login held two
domain:serverseats anddomain:ui#1behind one mailbox, and another held threedomain:uiseats and had none.Measured on
origin/mainddab8b99, the writer and the reader also disagreed. The opener wroteTo: LOGINas the body's first line, while the roster readMailbox-of:. So every mailbox opened on a--headbranch was invisible to the roster's mailbox column. Two of the three live mailboxes are on that path (#27523, #27357). This diff gives both sides one spelling, and a self-test case feeds the opener's own body to the reader.Verification
node scripts/pm/dispatch-gates.mjs --commandson headc2792c09derives 38 families, and all 38 ran and exited 0. The--ranreconciliation reads 38 derived, 38 run, 0 NOT-MEASURED, 0 UNRUN.check:doc-formula-expressionsfirst exited 3 because its prerequisite, the@objectstack/formulaand@objectstack/lintdist, was missing. Afterpnpm exec turbo run build --filter=@objectstack/formula --filter=@objectstack/lintit exited 0, and the record carries that rerun.node scripts/pm/mailbox-open.mjs --self-test: 67 cases in 10 batteries.node scripts/pm/fleet-roster.mjs --self-test: 82 cases.pnpm check:pm-record-recognisers: 326 cases.node scripts/pm/check-skill-line-ratchet.mjs.node scripts/pm/check-governed-queue-guard.mjs --self-testandnode scripts/pm/check-half-states.mjs --self-test. These are the two that the newrecord-recognisers→mailbox-openimport could have deadlocked through a top-level-await cycle. Neither did.pnpm check:pm-governed-prose.pnpm lint.origin/mainmoved 7 commits past the base, toc91a004f. None of them touches a path in this diff.Mutation probes. Each change was reverted in a scratch copy of the file, the self-test was run, and the copy was deleted:
openMailboxesOfmatching by login turnsmailbox-open --self-testred: "two seats under ONE login both open".fleet-roster --self-testred, with 3 cases.To:line that accepts any value turnsrecord-recognisers --self-testred, with 4 cases.In-flight intersection, re-run before the first edit: of the 17 open PRs on objectstack at about 01:55Z, 13 are not mailboxes or the Version Packages PR. All 13 heads were fetched and diffed against their merge base, and 0 touch any path in this diff.
Clause-②: no
Metadata-protocol: none
Migration (card-thread follow-up after landing, not this diff)
mailbox-open.mjs --close N) and reopened once per seat (--seat LANE#N).refs/heads/mailbox/os-justin(pm:mailbox — os-justin #27309's head) must be deleted after pm:mailbox — os-justin #27309 closes and before that account's first per-seat open on the default path. Git refuses a ref nested under an existing ref. This was measured on 2026-10-30 on a local bare repository, where pushingmailbox/os-justin/server-3besidemailbox/os-justinwas rejected withfailed to update ref. The opener's header and its push-failure message say so.To:line). That is report-only.Deviations
GOVERNED_SURFACES,scripts/pm/check-governed-merges.mjs) rows.claude/**on objectstack as Tier S, and the only governed paths here are.claude/skills/pm-dispatch/references/*. Triage (comment 6501344388) writes Tier H. The seat takes the stricter one, Tier H, and the maintainer approves.scripts/pm/record-recognisers.mjs(aTo: SEATline broke its reader, measured: refused above the key, unreadable below it),scripts/pm/fleet-roster.fixture.json(the roster self-test's snapshot), andseat-post-protocol.md〈交接收尾清单〉 (the hand-over steps live there, not inproject-forms.md).mailbox-openandfleet-rosterself-tests are not wired into any CI job orpackage.jsonscript onmain. They were run by hand here, and wiring them is out of scope.Human Minimum
packages/specholds no runtime logic. (Not touched.)pnpm lintpasses.main, one pull request.skip-changeset.)packages/spectouched: its generated artifacts are regenerated and committed. (Not touched.)content/docs/references/,packages/*/CHANGELOG.mdorcontent/docs/releases/.Generated by Claude Code