Skip to content

feat(pm): epic seats open a mailbox and show on the fleet roster - #28751

Merged
os-zhuang merged 2 commits into
mainfrom
claude/issue-28718-epic-seat-mailbox
Nov 1, 2026
Merged

os-zhuang merged 2 commits into
mainfrom
claude/issue-28718-epic-seat-mailbox

Conversation

@objectstack-fleet

Copy link
Copy Markdown
Contributor

Requested by 田騏 · project thread
Fixes #28718
Clause-②: no
Metadata-protocol: none

维护者速读

What changes

1. mailbox-open.mjs — the seat grammar reads the epic lane. seatKey now accepts epic:#N#K (the seat-signature spelling the pm-dispatch references and check-half-states.mjs's SIGNATURE_LANE_SOURCE already use; measured live as epic:#27293#1, epic:#8345#1 on the parent cards' signature lines). epic:#N alone is seat 1, as for every lane. The epic kind is one new exported constant, SEAT_EPIC_KIND, and both the shape and the reserved set are built from it.

  • Key stays as spelled (epic:#27293#1); slug is epic-27293-1 (the :# after the kind becomes one hyphen, then the seat's #), so the branch is mailbox/LOGIN/epic-27293-1 — a legal ref segment.
  • Collision measured: an epic slug always carries two numbers after epic-; repo: slugs start repo-, bare lanes are triage-N/director-N. The only lane that could reach epic-N-K is a domain:epic-N lane, so domain:epic-… joins domain:repo-… in the reserved set (no domain:epic* label exists today). domain:epic / domain:epics still read.
  • Malformed epic spellings stay refused: epic, epic:, epic:#, epic:12, epic#12, epic:#0, epic:#012, epic:#12#0, epic:#12#, epic:#12#1#2, epic:#abc, epic:#12-1, epic:skills#1.
  • The self-test case that pinned seatKey('epic:#12') as null now pins it as epic:#12#1 / epic-12-1.
  • record-recognisers.mjs is not edited: it reads To: and every key's seat field through seatKey, so To: epic:#27293#1 now reads (measured: a Notify: seat-online · epic:#27293#1 · … line reads with to: "epic:#27293#1"; To: epic:27293 is still refused). Its self-test passes unchanged.

2. fleet-roster.mjs — epic rows (the card's option (a)). One new read per repo, GET /repos/R/issues?state=open&labels=pm:epic, and a row per open pm:epic parent — sub-issues under it AND a session_… registration in its body, both halves of H45's h45DelegationNodeSignals (held equal by the self-test; not imported, so the relay, which imports ROSTER_MARKER from this file, never loads the patrol). Lane epic:#N, the seat link is the parent card.

  • Seats: one row per epic:#N#K seat with an open mailbox (seat K, seated by the login on its Mailbox-of: line — a mailbox opens at seating and closes at hand-over); with none open, one row, seat 1, status unknown (? —), so an epic seat nobody can ring is visible as one.
  • An epic mailbox is no longer listed under the table as "on no seat row"; a mailbox of an epic that is not an open delegated parent still is (no seat post or epic parent carries this seat).
  • The roster reads no epic in-flight cards or rulings, so an epic row is never flagged 疑似撞墙 on a partial activity reading.
  • Why (a) over (b): (b), a Mailbox: line on the epic card body, needs the same epic-card read (or one read per epic mailbox) AND a new body protocol on epic cards; (a) needs only the read and reuses the delegation signal the epic lane already defines (「父单打 pm:epic + 正文写会话 ID」). Reading rows off the mailboxes alone (zero reads) was rejected: a mailbox of a closed epic would show as a live seat.

3. project-forms.md 〈信箱 PR〉 — one line. The section's first line now says an epic seat (epic:#N#K spelling in the rule) opens a mailbox like any seat. The file sits at its ratchet ceiling (54/54, headroom 0) and every line is near the 120-byte cap, so the clause is paid in place by deleting the branch spelling from the same line — a tooling detail whose one owner is mailbox-open.mjs's header. Line count unchanged, the line is 115 bytes.

Session: https://claude.ai/code/session_017ihL2g7RyXa8ErM6GAkHyc

Tests

  • node scripts/pm/mailbox-open.mjs --self-test → ✓ mailbox-open self-test: 81 cases in 10 batteries pass. (pins raised: arguments 13→14, seat 7→11, open plan 10→11, owner 7→8, finding 9→10, CLI 6→7).
  • node scripts/pm/fleet-roster.mjs --self-test → ✓ fleet-roster self-test: 88 cases in 8 batteries pass. (fixture battery 18→22, rendered body 9→10). The fixture gains two delegated parents (one with a mailbox, one without), a pm:epic child, an undelegated parent with sub-issues, an epic mailbox and a mailbox of a closed epic.
  • Importers unchanged and green: record-recognisers.mjs --self-test (351 cases), check-owed-reviews.mjs --self-test (65), fleet-write/dispatch.mjs --self-test (265).
  • Live read-only run node scripts/pm/fleet-roster.mjs --repos objectstack-ai/objectstack --json (no write): 30 rows, three epic rows epic:#26676, epic:#27293, epic:#8345, each seat 1 status unknown (no epic mailbox is open yet).

Acceptance notes

  • record-recognisers.mjs's readSeat docblock still lists four lanes in prose; behaviour already follows seatKey. Left alone: outside this card's file surface.
  • #8345's body says its epic seat is vacant in prose; the roster does not parse prose and shows it as unknown, the same as an epic with a live session but no mailbox. The mailbox is the seated signal.
  • A delegated parent with no sub-issue filed yet gets no row until its first one; the H45 registration half alone is too loose to make a row (every seat-filed child carries a session on its signature line).
  • Epic parent numbers are repo-relative while the epic:#N lane is not; a mailbox is matched to a parent by number across the repos read. No two live parents share a number today.

Verification

Local gate union on head 27657d802c (dispatch-gates.mjs --commands --repo objectstack-ai/objectstack, 38 derived families), each exit captured before any pipe; --ran reconciliation: ✓ dispatch-gates --ran: 38 derived famil(ies) accounted for — 38 run, 0 NOT-MEASURED (a DERIVED zero — all 38 recorded an exit code and none of them is 3).

Derived families and exits

All 38 exit 0. On the first pass, nine exited 3 (PREREQUISITE NOT MET: no node_modules, and @objectstack/formula / @objectstack/lint unbuilt) and check-self-test-workflow-commands.mjs exited 1 on release-pending-publish.mjs failing to import @changesets/cli — all environment, none measured anything. After pnpm install --frozen-lockfile and turbo run build --filter=@objectstack/formula --filter=@objectstack/lint (lock VERDICT command-exit 0) every one re-ran to exit 0. pnpm check:pm-dispatch-gates: ✓ dispatch-gates self-test (fast tier): 1937 cases pass; 7 slow section(s) deferred.

Among them, the four the order names: pnpm check:pm-skill-ratchet 0 (project-forms.md 54 lines, ceiling 54), pnpm check:pm-skill-id-lint 0, pnpm check:skill-frame-sync 0. Outside the derived set, also run: pnpm check:pm-governed-prose 0, and both scripts' --self-test 0.

No changeset: scripts/pm/** and .claude/** publish nothing (skip-changeset).

🤖 Generated with Claude Code

seatKey reads the epic lane `epic:#<parent>#K` (slug `epic-<parent>-K`; a
`domain:epic-…` lane is refused so the slug stays one-to-one), so
mailbox-open opens an epic seat's mailbox and a `To: epic:#N#K` doorbell
reads. fleet-roster gives every open delegated `pm:epic` parent a row (one
read per repo), seated by the login on its open mailbox, else seat 1 with
status unknown; an epic mailbox is no longer flagged as on no seat row.
project-forms 〈信箱 PR〉 says an epic seat opens one like any seat, paid by
dropping the tool-owned branch spelling from the same line.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2g7RyXa8ErM6GAkHyc
@objectstack-fleet objectstack-fleet Bot added the skip-changeset PR has no user-facing published change; bypasses the changeset gate label Nov 1, 2026
@github-actions github-actions Bot added size/m documentation Improvements or additions to documentation labels Nov 1, 2026
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · marchtian · session_017ihL2g7RyXa8ErM6GAkHyc

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: 27657d802c42d48d0a12c78cd7ad20278ff13c21
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/project-forms.md + scripts/pm/mailbox-open.mjs (SEAT_SHAPE, RESERVED_DOMAIN_LANE, seatKey, mailboxBranch, MAILBOX_OF_LINE, mailboxOwner, openMailboxesOf), scripts/pm/fleet-roster.mjs (isEpicParent, buildRows epic loop, unassignedMailboxes, renderBody, readsFor, readLive), scripts/pm/fleet-roster.fixture.json, scripts/pm/record-recognisers.mjs (readSeat, readMailboxLine — read, not reviewed), scripts/pm/check-half-states.mjs (EPIC_REGISTRATION_MARKER, h45DelegationNodeSignals, SIGNATURE_LANE_SOURCE — read), .claude/skills/pm-dispatch/SKILL.md and references/seat-lifecycle.md 〈Epic 子树车道〉 (read), scripts/pm/check-governed-merges.mjs GOVERNED_SURFACES (read, for ③). The remainder of the diff (the two scripts and the fixture as code) is the lane seat's ACCEPT at TIER_DEFAULT.

Inputs: card #28718 body and all four comments (triage 6560301001, state 6560747188, claim 6560767706, dev report 6561170948); PR #28751 body, file list (4 files, +109/−43) and git diff origin/main...27657d80; the check-runs on 27657d80 read from GitHub. Read-only: nothing checked out, built or run.

① Derived judgments

  • seatKey accept-set widens by exactly epic:#N / epic:#N#K (SEAT_SHAPE gains epic:#[1-9][0-9]*, same digit shape as check-half-states SIGNATURE_LANE_SOURCE); key keeps the spelling, slug epic-N-K via /:#?/g. Right. Malformed epic spellings (epic:27293, epic:#0, epic:#012, epic:#12#1#2, epic:skills#1) stay null; the old pin seatKey('epic:#12') === null is replaced by epic:#12#1, which is the card's Wanted ①.
  • Reserved set widens by domain:epic-… so the slug stays one-to-one (domain:epic-12#1 would slug to epic-12-1). Right, and narrow: domain:epic, domain:epics, domain:epic#12 (slug epic-12, two segments) and repo:epic-12 (slug repo-epic-12-1) still read. I tried epic:#1#21 vs epic:#12#1, triage#12, domain:12#1: distinct slugs. No domain:epic* label exists today.
  • New public exports: SEAT_EPIC_KIND (consumed by fleet-roster, built into both regexes) and isEpicParent (self-test). Right. --seat refusal prose now gives an epic example. Right.
  • Every reader of the seat grammar through seatKey accepts epic seats without an edit: record-recognisers readMailboxLine (To: line) and readSeat (key fields; lastIndexOf('#') splits epic:#27293#1 into lane epic:#27293, n 1 — read, correct), mailboxOwner (MAILBOX_OF_LINE takes \S+), openMailboxesOf (slug match). Right, and intended by the card.
  • fleet-roster: one new read per repo (issues?state=open&labels=pm:epic, in readsFor and readLive); a row per open delegated pm:epic parent, seats = open mailboxes whose body line names epic:#N#K, else seat 1 unknown; cardLaneMatch stays false for epic lanes (no in-flight, no rulings); suspectedWall forced off for epic rows; summary line reads N seat rows (K epic); orphan text no seat post or epic parent carries this seat. Right. No other file consumes the two changed strings (grep on main).
  • A closed epic never becomes a row (query is state=open, and the loop guards state === 'closed'); an undelegated parent (no registration, or no sub-issue) is no row; a mailbox of either is listed under the table (fixture 25398 → epic:#28130#1). The brief's three probes — a slugging collision, a closed or undelegated epic shown live, a To: epic:… mis-read — all hold.
  • isEpicParent is byte-equal to H45's two halves (EPIC_REGISTRATION_MARKER = /session_[A-Za-z0-9]{4,}/, sub_issues_summary.total > 0), re-spelled rather than imported so the relay never loads the patrol; the self-test pins the equality over the fixture. Right.
  • Check-runs on 27657d80: the runs that had concluded when this record was written are all success or skipped (Governed Surface Queue Guard, Check Changeset, Check PR Size, PR-body guards, Dogfood Regression Gate, tooling self-tests, Type Check workspace/debt ledger, Test UI, Plan Test Core shards, Auto Label, filter); at the time of this write every check-run on the head has completed — 46 runs, 26 success, 20 skipped, 0 failure, none pending (Lint · PM dispatch-gates, Lint · CI/release/engine gates, Lint · docs & code guards, Lint · repo & tooling gates, Lint · ESLint, Type Check · source/consumer gates, Test Core 1/8 and 2/8 among the successes). Those conclusions are the gate verdicts; nothing was re-run here.

② Semver level

Clause-②: no on the PR body and in the claim; label skip-changeset; Check Changeset success. The diff publishes nothing — scripts/pm/** and .claude/** are outside every package — so no changeset is owed and no (narrowing) arm applies. Right.

③ Boundary flags

Dev deviations (report 6561170948), each answered:

  1. First gate pass before pnpm install (nine exit 3, one exit 1) then all 38 re-ran to 0 after install/build under the lock — environment, nothing measured; the CI check-runs are the gate verdicts here. Accepted.
  2. First check:pm-dispatch-gates run backgrounded without exit capture, re-run with exit 0 recorded. Accepted.
  3. The 〈信箱 PR〉 rule is one EDITED line, the file at ceiling 54/54, paid by dropping the branch spelling mailbox/LOGIN/SLUG. Accepted — see ④: the branch is tool-owned and the rule still names the tool.
  4. PR body footer is the order's 🤖 Generated with … line, not AGENTS' session-URL footer. Not a hits file; the PR-body guards check is green. Noted for the owning seat; a relay pr_create template matter, not this diff.
  5. PR opened with no assignee though AGENTS says the PR assignee mirrors the card's. Noted; the executor sets it at pr_create, no seat writes it by hand. Not blocking.

open_questions, both answered:

  • Q1 (uniform seat line on epic parents?) — A, keep. The lane's delegation signal (pm:epic + a session in the body, seat-lifecycle 〈Epic 子树车道〉) says delegated, not currently seated; [Epic] multi-currency (shape C′): record currency, dated exchange rates, write-time home-currency projection — 17 children, R1/R2/R3 release pairing (ruling 6465431966) #8345 carries a registration and says vacant in prose. unknown is the honest reading and the open mailbox is exactly the ringable signal the card is about. A machine seat line on epic bodies is a seat-lifecycle protocol change — a card of its own if ever wanted, outside this file surface.
  • Q2 (which record lands this PR?) — A, Tier S. GOVERNED_SURFACES row claude-tree (.claude/**) is GOVERNED_TIER_S for objectstack; AGENTS §14 says Tier S is all of .claude/**; scripts/pm/** is on no register row. Triage's "Tier H for the skill line" is an audit remark, not a ruling and not the register. This record, with a PASS and every check green, is the landing record; the owning seat lands it through the queue.

Reviewer disclosure: this record is rendered by a contract-review subagent inside the domain:skills#2 seat session that dispatched the dev (Implemented-by is the dev's branch, Reviewed-by the seat session — the branch/session independence pair, per the record template).

④ Design judgment

.claude/skills/pm-dispatch/references/project-forms.md 〈信箱 PR〉 line 36 — judged against the card's Wanted ③ ("one rules line says an epic seat opens a mailbox like any seat"), the spec it teaches on main (seat-lifecycle 〈Epic 子树车道〉, the epic lane SKILL.md names) and the cited code on the head:

  • The claim "epic 席 … 同样开" (the line spells the seat as epic:#N#K, the parent number as an angle-bracket placeholder) holds against the code: mailbox-open.mjs --seat epic:#27293#1 --login L parses, plans branch mailbox/L/epic-27293-1, body first line Mailbox-of: epic:#27293#1 · L, title pm:mailbox — epic:#27293#1 · L, passes validateStroke; mailboxOwner reads it back by body and by head; a second open for the same seat is refused, another epic's or domain:epic's is not; the roster shows it on the parent's row. The rule and its gate agree.
  • Dropping the branch spelling 分支 mailbox/LOGIN/SLUG loses nothing a seat acts on: line 37 still sends the seat to mailbox-open.mjs, which owns mailboxBranch and MAILBOX_BRANCH_PREFIX, and fleet-roster imports both rather than re-spelling them; no other skill file carried the branch form (grep on main). This is the AGENTS "stated once, the script's header is the authority on detail" shape. Line count 54/54 unchanged, the line 115 bytes; check-skill-id-lint's /#[0-9]{3,}/ sees no number on the line.
  • Breaking attempts: epic:#N alone reads as seat 1, as the line's #K implies for every lane; To: epic:#27293#1 on the mailbox reads (record-recognisers through seatKey); the seat signature spelling on epic cards (epic:#27293#1 · login · session) is the same string, so a seat can copy it verbatim into --seat. Nothing in the line contradicts the roster's reading (seat K = the open mailbox's Mailbox-of: key).

Findings — no must-fix:

  • should-fix (project-forms line 36): the placeholder pair is mixed — the parent number in angle brackets, the seat number a bare K — while the rest of the file spells every placeholder in angle brackets (席位, login, slug). Bracketing k the same way is 117 bytes, under the cap; a reader could take K as a literal.
  • should-fix (fleet-roster buildRows epic loop, cited code): held reads only mailboxes whose BODY names the seat (m.seat); an epic mailbox named by head slug alone (mailbox/L/epic-27293-1, no Mailbox-of: line — a hand-made one) shows in the row's mailbox column (slug match) while the row reads ? —. Matching held by slug (epic-N-K) as the mailbox column does would make the two readings agree; the opener always writes the body line, so no live mailbox hits this today.
  • should-fix (fleet-roster isEpicParent, cited code): a freshly delegated parent (registration, no sub-issue filed yet) has no row, so the mailbox its PM opened at seating is listed under the table as "no seat post or epic parent carries this seat" until the first child is filed — a transient false flag with a wording that is false for that parent. The PR's Acceptance notes name the choice (H45's both halves); either a registration-only row or a wording that says "no delegated epic parent" closes it.
  • noted, not a finding of this diff: the epic:#N lane is not repo-qualified (the signature grammar's own shape), so a mailbox for epic:#N#1 attaches to every open delegated parent numbered N across the repos read; the PR names it, no two live parents collide today.

Implemented-by: claude/issue-28718-epic-seat-mailbox
Reviewed-by: session_017ihL2g7RyXa8ErM6GAkHyc

VERDICT: PASS

…ted parents

Contract-review should-fixes: the 〈信箱 PR〉 line brackets the seat number
like the parent (`epic:#<n>#<k>`); an epic row's seats are matched by
seatKey's slug `epic-<n>-<k>`, so a head-only epic mailbox seats its row as
the mailbox column already reads it; and a registered `pm:epic` issue that
an open mailbox names is a row before its first sub-issue
(`isSeatedFreshEpic`), while `isEpicParent` stays equal to H45's two halves.

Co-Authored-By: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_017ihL2g7RyXa8ErM6GAkHyc
@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · marchtian · session_017ihL2g7RyXa8ErM6GAkHyc

Contract review

Served-tier: CONTRACT_REVIEW_TIER
Head-sha: ed0cc244e46a68611333a6d2b1e0e36bcd3d7a5f
Local-runs: none
Scope: .claude/skills/pm-dispatch/references/project-forms.md + scripts/pm/fleet-roster.mjs (isEpicParent, isEpicRegistered, isSeatedFreshEpic, epicSeatsHeld, buildRows epic loop, unassignedMailboxes), scripts/pm/fleet-roster.fixture.json, scripts/pm/mailbox-open.mjs (seatKey, mailboxOwner — unchanged since the prior head, read), scripts/pm/check-half-states.mjs (EPIC_REGISTRATION_MARKER, h45DelegationNodeSignals, epicCardNamesParent — read). The remainder of the diff (the two scripts and the fixture as code) is the lane seat's ACCEPT at TIER_DEFAULT.

This record supersedes 6561348241 (head 27657d80) for the PR's current head. Inputs: card #28718 body and comments through the patch report 6561503444; PR #28751 body, file list (4 files, +141/−43 vs main), git diff 27657d80..ed0cc244 (3 files, +49/−17) and the full net diff vs main; the check-runs on ed0cc244 read from GitHub. Read-only: nothing checked out, built or run.

① Derived judgments

  • mailbox-open.mjs is byte-identical to the prior head: every ① judgment of 6561348241 on seatKey, the reserved set, the exports and the readers through seatKey stands.
  • fleet-roster epic loop: the parent guard moves below the mailbox read and becomes isEpicParent(epic) || isSeatedFreshEpic(epic, held); held is now epicSeatsHeld(lane, mailboxes), matched by slug epic-N-K (body line or head alike) with every candidate round-tripped through seatKey (seatKey(lane#k).slug === m.slug). Right. Accept-set change: a head-only epic mailbox now seats its row; a registered pm:epic issue with no sub-issue yet becomes a row once a mailbox names it. Both are the two should-fixes asked for.
  • isEpicParent is unchanged in meaning (sub_issues > 0 && isEpicRegistered), still byte-equal to H45's two halves, now pinned over six fixture cards. Right. isEpicRegistered is private; isSeatedFreshEpic and epicSeatsHeld are new exports consumed only by the self-test. Right.
  • Fixture: 28800 (registered, total 0) + mailbox 25399 (Mailbox-of: epic:#28800#2) → one seated row, not flagged; 25400 (head mailbox/os-bill/epic-27293-2, empty body) → 27293 seat 2 seated by os-bill; 28647 (child: registration, total 0, no mailbox) stays no row; orphans unchanged at three (25395, 25396, 25398 — the closed-or-unlisted epic 28130). Summary line (4 epic). Right.
  • Check-runs on ed0cc244: at the time of this write every run has completed — 41 runs, 25 success, 16 skipped, 0 failure, none pending; Governed Surface Queue Guard, Lint · PM dispatch-gates, tooling self-tests, PR-body guards, Test Core shards all success. Those conclusions are the gate verdicts; nothing was re-run here.

② Semver level

Unchanged from 6561348241: Clause-②: no, skip-changeset, nothing published from scripts/pm/** or .claude/**; no (narrowing) arm. Right.

③ Boundary flags

The patch report carries no deviations and no open_questions. The prior round's five deviations and two answers (Q1 A keep; Q2 A Tier S — GOVERNED_SURFACES claude-tree is Tier S for objectstack) stand unchanged. The PR body's acceptance bullet "a delegated parent with no sub-issue filed yet gets no row" is now stale against the tree; the owning seat corrects it in the ACCEPT, not a finding here.

Reviewer disclosure as before: rendered by a contract-review subagent inside the domain:skills#2 seat session; Implemented-by the dev's branch, Reviewed-by the seat session.

④ Design judgment

project-forms.md 〈信箱 PR〉 line 36 — the seat is now spelled with both numbers as angle-bracket placeholders, matching the file's own placeholder convention; 54/54 lines, the line 117 bytes, no 3+-digit number for check-skill-id-lint. The claim "an epic seat opens one like any seat" holds against the unchanged opener exactly as judged on 27657d80, and now also against the roster for a head-only mailbox. Should-fix 1 resolved.

Cited code, each prior should-fix against the new head:

  • Should-fix 2 resolved. epicSeatsHeld derives the stem epic-N- from seatKey(lane).slug (trailing 1 of -1 stripped; a parent number ending in 1 keeps its digit since only the final char goes), then accepts a mailbox only when seatKey('epic:#N#k').slug reproduces its slug. Tried: epic-27293-0, epic-27293-01, epic-27293-1-2 (k fails seatKey, dropped); epic-272931-1 against stem epic-27293- (no prefix match, the stem ends in -); epic-2864-7-1 against epic-2864- (k 7-1 refused). Body-named and head-only mailboxes read through the same slug, so the row and its mailbox column can no longer disagree.
  • Should-fix 3 resolved. isSeatedFreshEpic is registration AND a held seat — never registration alone (a child has a registration too) and never a mailbox alone (an unregistered parent with a stray mailbox stays an orphan flag). A parent delegated before its first sub-issue is a seated row the moment its PM opens the mailbox, which is the seating act the rule prescribes.
  • Breaking attempts on the new conditions: a closed epic is never listed (state=open query plus the guard), so its mailbox stays under the table — no closed epic reads live; an undelegated parent with sub-issues and no registration stays no row even with a mailbox; a child shares no number pattern with its parent's seats (the stem's trailing - and the seatKey round-trip see to it). A pm:epic child becomes a row only if a mailbox is opened under the child's own number — a mis-typed --seat the opener cannot see (it reads no card), and the row is then at least visible rather than an orphan line; the list-issues read carries no parent field to guard on (H45 reads the parent separately), so this stays a noted limitation, not a finding. Cross-repo attachment is as before: epic:#N is not repo-qualified by the signature grammar, named in the PR, no live collision.

Findings: none — no must-fix, no should-fix.

Implemented-by: claude/issue-28718-epic-seat-mailbox
Reviewed-by: session_017ihL2g7RyXa8ErM6GAkHyc

VERDICT: PASS

@objectstack-fleet

Copy link
Copy Markdown
Contributor Author

domain:skills#2 · marchtian · session_017ihL2g7RyXa8ErM6GAkHyc

维护者速读(席位终稿 · head ed0cc244e46a68611333a6d2b1e0e36bcd3d7a5f)

席位意见:ACCEPT.

席位核对

@objectstack-fleet objectstack-fleet Bot added the needs-user-decision Blocked on a maintainer decision — do not dispatch; decision cards only, never on a PR label Nov 1, 2026
@os-zhuang
os-zhuang marked this pull request as ready for review November 1, 2026 20:49
@os-zhuang
os-zhuang enabled auto-merge November 1, 2026 20:49
@objectstack-fleet objectstack-fleet Bot removed the needs-user-decision Blocked on a maintainer decision — do not dispatch; decision cards only, never on a PR label Nov 1, 2026
@os-zhuang
os-zhuang added this pull request to the merge queue Nov 1, 2026
Merged via the queue into main with commit b9b877c Nov 1, 2026
50 checks passed
@os-zhuang
os-zhuang deleted the claude/issue-28718-epic-seat-mailbox branch November 1, 2026 21:06
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation size/m skip-changeset PR has no user-facing published change; bypasses the changeset gate

Projects

None yet

Development

Successfully merging this pull request may close these issues.

pm-dispatch(mailbox): epic seats cannot be rung — mailbox-open refuses epic: seat keys and the fleet roster has no epic rows

2 participants