Skip to content

fix(core): route live Bus events before Location fanout - #52922

Open
pascalandr wants to merge 3 commits into
anomalyco:devfrom
pascalandr:bus-location-fanout
Open

pascalandr wants to merge 3 commits into
anomalyco:devfrom
pascalandr:bus-location-fanout

Conversation

@pascalandr

@pascalandr pascalandr commented Oct 3, 2026 •

Copy link
Copy Markdown

Issue for this PR

Closes #52921
Related to #36443; this does not add public SSE client-interest scoping.

Type of change

  • Bug fix
  • New feature
  • Refactor / code improvement
  • Documentation

What does this PR do?

User impact: With many project directories loaded, compaction can leave TUI
refreshes and live updates seconds behind. CodeNomad can suffer even more:
background recovery can load many old directories, and its extra event relay
can further delay updates, making conversations appear frozen while the server
is still working.

Route live Bus events to exact Location/type channels before delivery instead
of broadcasting to unrelated Location consumers and filtering afterward.
Preserve global recipients, publication-time ownership, old/new Session moves,
mixed-type FIFO and scoped channel cleanup. No API/client changes.

How did you verify your code works?

  • 67 focused Bus tests, Core typecheck and targeted lint pass. Original-Bus
    controls fail the new unrelated-subscriber regressions.
  • 220 unrelated Locations/5,280 consumers: 159,180 -> 780 native subscriber
    visits, with all 780 matching/global deliveries and zero unrelated visits.
  • Three alternating official CLI/ConPTY pairs with 220 preloaded native graphs,
    no added Bus observers, one synthetic compaction and 22 traffic sessions:
    Worktrees Ctrl+R 3.626/12.736/13.438 -> 0.805/0.566/1.394 s.
  • Local TUI input did not improve. Natural five-tab runs loaded only five
    graphs and did not establish a general compaction gain. This is not a claim
    that the original CodeNomad freeze is resolved.
  • Independent local code and TUI-evidence reviews found zero actionable issues.
    Full repository typecheck remains blocked by an inherited Windows symlink
    representation in packages/app/src/custom-elements.d.ts; targeted Core passes.

Screenshots / recordings

No layout changes; measured actions used the production TUI and framebuffer.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Partition live subscriptions by exact Location and event type so publishing a
located event does not walk unrelated Location consumers before filtering.
Preserve global recipients, publication-time Session ownership, old/new move
delivery and a single ordered feed for multi-type subscriptions. Release an
unused channel with its stream scope and safely reacquire a fresh channel.

Add real Effect PubSub subscriber-visit regressions, channel lifetime checks,
and queued typed/mixed Session move coverage. The focused Bus suite passes
67 tests; original Bus controls fail the unrelated-subscriber regressions.
Core typecheck and targeted lint pass, with independent code review finding
no actionable issues.

Three alternating official CLI/ConPTY pairs under the same disclosed
220-loaded-Location synthetic shared-server recipe reduce Worktrees manual
refresh from 3.626/12.736/13.438 s to 0.805/0.566/1.394 s. No extra native Bus
observers were added. Local TUI input did not improve, and natural five-tab
runs do not demonstrate a general compaction speedup. These results support
reduced fanout and network-backed delay, not a complete CodeNomad freeze fix.
@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

github-actions Bot commented Oct 3, 2026

Copy link
Copy Markdown
Contributor

The following comment was made by an LLM, it may be inaccurate:

@pascalandr

Copy link
Copy Markdown
Author

Issue #52921 exists and the PR body already contains Closes #52921.
The executed check-standards job
checked only closingIssuesReferences, which is empty for this non-default
v2 target. This appears to explain the needs:issue false positive.

Could a maintainer reconcile that label and authorize the pending fork CI?
The check/test/Nix workflows currently report action_required, not passed.
The PR intentionally targets v2 as required by its contribution guide.

@thdxr
thdxr changed the base branch from v2 to dev October 10, 2026 19:28
pascalandr added a commit to NeuralNomadsAI/CodeNomad that referenced this pull request Oct 10, 2026
…overy (#909)

## Summary

Repeated "Question and permission recovery is incomplete" warnings came
from CodeNomad's own ownership checks, not from OpenCode.

- **Root cause (measured on an affected Windows machine):** the native
loaded-only snapshot RPC answers in about 5 ms, but each pending batch
took 9–35 s and often hit the 30 s deadline. Every candidate directory
spawned `git rev-parse --git-common-dir` before and after the native
read, through the shared two-process Git worker. Each Windows spawn
costs 50–800 ms, and the 30-second liveness pass re-checks every
inventoried worktree (314 in the affected repository), so the queue
stayed saturated and starved other projects.
- **Git common directory without a process:** `readGitCommonDirectory`
resolves the enclosing checkout from its administrative files (`.git`
file/directory, `commondir`, `HEAD`/`objects`), mirroring Git discovery
without crossing devices. Nested bare or separate Git directories, paths
inside `.git`, Git location/discovery environment overrides and
unreadable layouts defer to Git. Each call still reads current state;
only in-flight reads are shared.
- **Per-directory isolation:** an ownership, repository-identity or
deletion-fence failure for one candidate (before or after the native
read), or a rejected returned placement, reports only that directory's
non-authoritative `error` instead of a 503 for the batch. A rejected
placement withholds capability verification.
Root/origin/connection/workspace changes, malformed or duplicate
coverage, count overflow and timeouts still fail the batch.
- **Diagnostics:** phase-only `Server-Timing` on every response;
failures log their phase without queue contents. The root candidate
reuses the root identity (7 → 2 Git identity reads).
- **Warning hysteresis:** the incomplete state and known queues are
retained immediately, but the toast appears only after two consecutive
incomplete recoveries; one success re-arms it.

## Validation

- Real-machine equivalence: **326 directories** (314 worktrees plus
other repositories and nested folders) resolve in **0.5 s instead of
60–112 s** through Git, with **0 mismatches**.
- Pending broker and Git preflight suites: **36/36**, including nested
bare/separate-gitdir, committed HEAD/commondir markers, invalid HEAD
content, dangling and backslash HEAD symlinks, and in-flight deletion
regressions. The 64-directory case drops from over 40 s (already failing
before this change on Windows) to under 1.5 s.
- Full server suite: 958/966; the two failures are load-sensitive timing
tests that pass in isolation.
- UI pending suites **42/42**; rendered interruption-dock regression
**14/14** with the new warning policy; CI restore-ownership command
**423/423**; server and UI typecheck.
- PR CI green on ebc1571 (one unrelated Windows install-fixture `EBUSY`
cleanup failure passed on rerun).

## Scope

This does not replace upstream
[anomalyco/opencode#52922](anomalyco/opencode#52922),
which addresses event fan-out across many loaded Locations. A repository
that Git refuses through `safe.directory` is now accepted by the
filesystem read; only administrative files are read.

## Autonomous Gatekeeper review

**Completed: ZERO FINDINGS at 5077a1b, plus ZERO FINDINGS on the
test-only delta to ebc1571.** A pre-PR review fixed two issues (nested
bare/separate Git directory; deletion starting during final
revalidation). The PR loop then ran five rounds and corrected four more
divergences from Git discovery (committed HEAD/commondir markers,
dangling HEAD symlinks, invalid HEAD content, backslash symlink
targets), each with a regression compared against `git rev-parse`. See
the PR comments for each round.

## Existing large file touched

- `packages/ui/src/stores/instances.ts`: approximately 2,350 lines.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

core: located Bus events visit unrelated Location subscribers

1 participant