feat(B-0400): bus-gate integration — allActiveClaims + --with-bus-claims (slice 5)#2959
Merged
Merged
Conversation
…ims (slice 5) - claim.ts: export allActiveClaims() — collects active claims across all backlog items by discovering unique itemIds from claim-topic messages and delegating per-item to activeClaims() for correct release semantics - poll-pr-gate-batch.ts: --with-bus-claims flag appends active bus claims to the BatchReport output (busClaims?: ClaimRecord[]) - BusClaimsFn injectable type + pollFn injection in main() for full DST coverage without gh subprocess in tests - 3 new tests in claim.test.ts (allActiveClaims across items, with release) - 4 new tests in poll-pr-gate-batch.test.ts (flag present/absent, empty list) - bun test tools/bus/ → 64 pass; bun test poll-pr-gate-batch.test.ts → 14 pass - dotnet build -c Release → 0 warnings, 0 errors operative-authorization: aaron 2026-05-13: "cooling periods, harsh-critic reviewers, F# anchor sanity check" Co-Authored-By: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 57c0c7430c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
Pull request overview
Adds bus-claim visibility to the PR gate batch poller so callers can retrieve PR gate state and cross-agent coordination state in a single JSON payload, aligned with B-0400 slice 5.
Changes:
- Export
allActiveClaims()fromtools/bus/claim.tsto aggregate active claims across all backlog items. - Add
--with-bus-claimstopoll-pr-gate-batch.ts, appendingbusClaimsto theBatchReportoutput (with injectableBusClaimsFnfor deterministic tests). - Extend unit tests for both
allActiveClaims()andmain()/--with-bus-claims, and update the B-0400 backlog slice notes.
Reviewed changes
Copilot reviewed 5 out of 5 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tools/github/poll-pr-gate-batch.ts | Adds --with-bus-claims output and injectable BusClaimsFn/pollFn to keep tests deterministic. |
| tools/github/poll-pr-gate-batch.test.ts | Adds main() coverage for --with-bus-claims and stdout capture. |
| tools/bus/claim.ts | Adds allActiveClaims() to aggregate active claims across items. |
| tools/bus/claim.test.ts | Adds tests validating allActiveClaims() behavior across multiple items and releases. |
| docs/backlog/P1/B-0400-inter-agent-ephemeral-communication-bus-nats-protocol.md | Documents slice 5 scope/details for the integration. |
…ctiveClaims, test rename, doc count Three Codex/Copilot review findings resolved: 1. perf(claim.ts): refactor allActiveClaims() from O(items×messages) to single-pass. Previously: list() once to discover item IDs, then activeClaims(id) per item (each calling list() again). Now: one list() call, groupBy (from:itemId) in a single pass — identical tiebreaker logic to activeClaims(). 2. test(poll-pr-gate-batch): rename misleading test — was 'empty-PR early-return path' but actually tests 'busClaimsFn returns empty list'. Updated comment to clarify that --all-open empty path requires injectable listOpenPRs (not done here). 3. docs(B-0400): correct test count 4→3 in slice-5 scope section. All 33 claim tests + 14 poll-pr-gate-batch tests pass. Co-Authored-By: Claude <noreply@anthropic.com>
grok-4.3 collapses thinking/fast into one model identifier; the Mode parameter is preserved for future cursor-agent updates but is currently unread, causing TS6133 under noUnusedLocals. Co-Authored-By: Claude <noreply@anthropic.com>
| timestamp: m.timestamp, | ||
| expiresAt: m.expiresAt, | ||
| }); | ||
| } |
AceHack
added a commit
that referenced
this pull request
May 13, 2026
…nfirmation 2026-05-13 (#3035) Aaron 2026-05-13 activated Otto on Claude Desktop alongside Otto-CLI, running the multi-foreground-surface architecture from PR #3030 for the first time. Preserves operational discoveries: 1. Claude Desktop Routines are GIT-TRACKED (durable across sessions) vs Claude Code CronCreate session-only — supersedes 'every session MUST CronList' mechanism at Desktop scope 2. Two cadence layers in Desktop: Loop (minute, session-bounded) + Routine (configurable, git-tracked). Both fire simultaneously. 3. CRITICAL ARCHITECTURAL GAP: SENDER_IDS in tools/bus/types.ts doesn't distinguish multi-surface instances. claim.ts treats --from otto from CLI and Desktop as IDENTICAL — split-brain prevention fails without schema extension. Vera caught this on PR #3032 review. Workarounds: lane-based + branch-prefix + future schema extension. 4. Approval friction profile shapes lane split natively: - Otto-CLI: better at .claude/rules/ edits (auto-accept covers) - Otto-Desktop: better at substrate + conversation + routines - The lane split emerges from approval costs, not convention — more robust because friction enforces it Generalizable principle: multi-foreground-surface works because surfaces have DIFFERENT cost profiles, not because they're redundant clones. Future multi-instance work should match work to lowest- friction surface for that work shape. Composes with: - Otto canonical bootstream (full canonical + tight) - .claude/rules/tick-must-never-stop.md (CLI cron caveat) - .claude/rules/claim-acquire-before-worktree-work.md (the rule with the architectural gap named) - .claude/rules/holding-without-named-dependency-is-standing-by-failure.md - B-0400 slice 3 (PR #2939) + slice 5 (PR #2959) - fetch-before-push memory (sibling discipline at git scope) Co-authored-by: Claude <noreply@anthropic.com>
AceHack
added a commit
that referenced
this pull request
May 13, 2026
…on for multi-Otto) (#3032) * docs(rules): claim acquire before worktree-creating backlog work (split-brain prevention for multi-Otto) Aaron 2026-05-13 set up Otto on Claude Desktop alongside Otto-CLI, creating a real multi-foreground-surface split-brain risk. Both Ottos share git + bus on one machine and could pick the same backlog row simultaneously. The claim-coordinator (tools/bus/claim.ts, B-0400 slice 3) was built for this — atomic check/acquire/release with PID-liveness + 24h TTL. PR #2939 shipped it; PR #2959 added the gate integration. The infrastructure exists; this rule is the discipline-level mechanization that auto-loads at cold-boot so both Ottos read it + use it before worktree-creating backlog work. Applies to: starting work on a B-NNNN row, creating feature branch + worktree, opening a backlog-advancing PR. Does NOT apply to: CI fixes on already-claimed PRs, ad-hoc memory- file writes, conversation-driven substrate, hot fixes. Composes with: - backlog-item-start-gate.md (this rule adds zero-th step) - dont-ask-permission.md (acquire exit 0 IS the substrate permission) - never-be-idle.md (if acquire fails, pick another row) - B-0400 + slice 3 + slice 5 infrastructure - Otto Claude Desktop bootstream (PR #3030) - fetch-before-push memory (sibling coordination pattern at git scope) Future substrate-level mechanization: pre-commit hook that auto-calls 'claim check' and fails on no-held-claim. Today's rule is the discipline-level fix. Co-Authored-By: Claude <noreply@anthropic.com> * fix(rules): correct Example 2 — multi-surface Otto can't be distinguished by same --from value (Vera P1) Vera caught (PR #3032 review): the original Example 2 showed two Ottos calling 'acquire --from otto' and the second exiting 1. That's WRONG per claim.ts line ~270 — same --from is filtered out as self-re- acquire (idempotent). Both calls succeed; split-brain not prevented. Fix: - Example 2 renamed to "KNOWN GAP" — shows actual behavior (both succeed) + names the architectural cause (SENDER_IDS doesn't distinguish multi-surface instances) - Added workarounds: lane-based convention, branch-prefix discipline, schema extension (otto-cli / otto-desktop) - New Example 3 shows TARGET behavior with schema fix (--from otto-cli vs --from otto-desktop) - Example 3 renamed to Example 4 (crash recovery) The architectural gap is a real follow-up: extending SENDER_IDS to support multi-surface instances of the same logical agent. Future work, not this PR. Operational consequence today: use the lane-based + branch-prefix workarounds. Claim-coordinator is INSUFFICIENT for multi-Otto without the schema extension. Co-Authored-By: Claude <noreply@anthropic.com> * docs(rules): fix false split-brain + PID-liveness claims P1 (PRRT_kwDOSF9kNM6B5VwU): carved sentence claimed split-brain is but claim.ts filters by c.from !== sender, soprevented same-sender instances both exit 0. Updated to state --from must differ and document the known gap explicitly. P2 (PRRT_kwDOSF9kNM6B5VwX): example 4 claimed PID-liveness can reclaim a claim mid- no such mechanism exists. Only TTLTTL expiry or explicit release ends a claim. Corrected comment. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> * fix(rules): remove branch-prefix as split-brain workaround (Vera P2 caught it doesn't work) Vera caught: branch-prefix doesn't prevent split-brain because claim.ts only filters by 'from', not by 'branch'. Two Ottos with same --from otto but different --branch both succeed (both exit 0). The branch field is post-hoc metadata, not a coordination key. Real workarounds reduce to: 1. Lane-based convention (zero-code; ONLY real prevention today) 2. Schema extension (future SENDER_IDS additions) Co-Authored-By: Claude <noreply@anthropic.com> * fix(rules): carved sentence consistency — remove branch-prefix from workarounds (Vera P2) The body of the rule was already corrected (commit 030513f) to remove branch-prefix as a workaround. The carved sentence wasn't updated. Vera caught the inconsistency. Now carved sentence + body both say: lane-based convention is the ONLY real split-brain workaround today. Co-Authored-By: Claude <noreply@anthropic.com> --------- Co-authored-by: Claude <noreply@anthropic.com> Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
claim.ts: exportallActiveClaims()— collects active claims across all backlog items by discovering uniqueitemIds from claim-topic messages, then delegating per-item toactiveClaims()for correct claim/release semanticspoll-pr-gate-batch.ts:--with-bus-claimsflag appends active bus claims (busClaims?: ClaimRecord[]) to theBatchReportJSON, giving the autonomous loop PR-gate state + bus coordination state in one callBusClaimsFninjectable type +pollFninjection inmain()— tests never spawnghor touch the filesystemSlice context
Slices 1–4 shipped (types + CLI + watch + claim-coordinator + status subcommand). This is slice 5: the
poll-pr-gate-batch.tsintegration listed as deferred in the backlog item.Usage after this slice:
bun tools/github/poll-pr-gate-batch.ts --with-bus-claims 2944 2953 # BatchReport now includes busClaims: [{ from: "otto", itemId: "B-0400", branch: "...", ... }]Test results
Checklist
dotnet build -c Release→ 0 warn / 0 errclaim.ts acquire --from otto --item B-0400🤖 Generated with Claude Code