Skip to content

chore: sync upstream-fanatics -> personal 2026-05-09#65

Open
tstapler wants to merge 46 commits into
mainfrom
sync/work-to-personal-2026-05-09
Open

chore: sync upstream-fanatics -> personal 2026-05-09#65
tstapler wants to merge 46 commits into
mainfrom
sync/work-to-personal-2026-05-09

Conversation

@tstapler
Copy link
Copy Markdown
Owner

@tstapler tstapler commented May 9, 2026

Automated nightly sync. 197 commits from work fork.

Conflict resolution applied:

  • docs/registry/ files: kept personal fork versions (newer scanner timestamps); new work-fork registry entries included
  • benchmarks/ and gen/proto/ files: took work fork versions via -X theirs strategy
  • All other conflicts: resolved in favor of work fork (-X theirs)

Note: histories are unrelated (no common ancestor); merged with --allow-unrelated-histories.


Generated by Claude Code

tstapler and others added 30 commits May 4, 2026 14:31
- Switch pre-creation check to DoesSessionExistNoCache() so stale sessions
  from a previous server run are detected and reused instead of causing a
  duplicate-session error on new-session
- Add fast-path DoesSessionExistNoCache() check immediately after new-session
  succeeds to skip the registry poll loop when the %session-created event lags,
  preventing 10s poll timeouts that left ghost sessions
- Add force parameter to handleAutoAdvance; handleDismissFromQueue passes
  force=true so the ⏭ dismiss button always advances to the next queue item
  regardless of the auto-advance preference checkbox
…ker backoff

Add WaitDelay=2s to subprocess calls in batchPTYInfo, batchPaneActivity,
batchProcessStates, and monitorTmuxSessionPolling that were missing it. Without
WaitDelay, when a context timeout kills a subprocess Go's Wait() blocks on I/O
goroutines, leaving the process in zombie state until they drain.

Add per-session exponential backoff to HistoryLinker for sessions that
repeatedly yield no JSONL file (idle worktrees). After 3 misses: 5s→10s→20s→
40s→5min. After 10 misses: session is parked — zero polling, relies entirely on
fsnotify to trigger ScanAll() when a Claude conversation actually starts.

Result: zombie rate dropped from ~65/60s (critical) to 0 in current window.
…ies rule

ESLint boundaries plugin rejects extra properties in rule entries.
* fix: tmux session creation reliability and review queue force-advance

- Switch pre-creation check to DoesSessionExistNoCache() so stale sessions
  from a previous server run are detected and reused instead of causing a
  duplicate-session error on new-session
- Add fast-path DoesSessionExistNoCache() check immediately after new-session
  succeeds to skip the registry poll loop when the %session-created event lags,
  preventing 10s poll timeouts that left ghost sessions
- Add force parameter to handleAutoAdvance; handleDismissFromQueue passes
  force=true so the ⏭ dismiss button always advances to the next queue item
  regardless of the auto-advance preference checkbox

* perf: eliminate mutex contention and allocation hotspots

Six profiling-driven fixes addressing the top bottlenecks identified
via pprof (mutex, block, allocs profiles):

1. Remove hot-path debug logging in review_queue_poller (checkSession
   runs up to 5 concurrent goroutines; each log.Printf serialized all
   of them on the stdlib log mutex). Removed all debugLog.Printf calls
   from the inner poll loop.

2. Hoist log calls outside stateMutex in UpdateDiffStats (instance.go).
   Replaced defer Unlock with explicit unlocks at each return point so
   log.WarningLog.Printf is never called while holding stateMutex,
   eliminating the double-mutex chain (stateMutex -> log mutex).

3. Pool TerminalData proto messages in WebSocket stream goroutine
   (connectrpc_websocket.go). Added sync.Pool + coalescing drain loop
   so rapid terminal bursts are batched into a single write per flush,
   reducing per-frame allocations and syscall count.

4. Compile banner filter regexps once at package init (banner_filter.go).
   NewBannerFilter was calling regexp.MustCompile for 10+ patterns on
   every TmuxSession creation. Moved to package-level var block.

5. Make PR-status storage methods no-ops (storage.go). GitHub PR fields
   (GitHubPRState, GitHubPRNumber, GitHubIsFork, etc.) are not in the
   ent schema, so UpdateInstancePRStatus/PRNumber/ForkFlag were doing a
   full SELECT+UPDATE that never persisted anything. Now return nil
   immediately.

* fix(lint): remove unused updateFieldInRepo helper

After making PR-status update methods no-ops, updateFieldInRepo became
unreachable. Removed to fix golangci-lint unused function error.

---------

Co-authored-by: Tyler Stapler <tystapler@gmail.com>
…t zombie accumulation

discoverExternalClaude, discoverOrphanedPTYsWithCache, getPTYInfoFromTmux,
getPTYInfoFromTmuxWithSocket, listSessionsRaw circuit-breaker bypass, and
mux/picker.go were all missing cmd.WaitDelay after exec.CommandContext.
Without it, when the 5s timeout fires and SIGKILL is sent, cmd.Wait() can
block indefinitely if a grandchild holds the pipe open — leaving the process
as a zombie. With WaitDelay=2s, Wait() returns after 2 seconds regardless.

External discovery runs every 5s; when tmux is unhealthy, each cycle spawns
~7 subprocesses without WaitDelay, producing ~42 zombies per 30s window
(matching the observed 41 critical zombies).

Also clear isLoadingInitialContent on connection drop in TerminalOutput so
the UI shows Disconnected state instead of a stuck spinner.
…process group management

Adds executor/safeexec, executor.ShortLivedCmd, executor.ManagedProcess, executor.AuditHook,
and executor.RlimitConfig to give every subprocess call in the codebase:
- WaitDelay=2s (prevents goroutine leaks when grandchildren hold pipes open after SIGKILL)
- Setpgid+Noctty by default (SIGKILL propagates to entire process group, not just direct child)
- SIGTERM→SIGKILL grace period for ManagedProcess.Stop()
- Context-carried audit logging (executor.WithAuditHook)
- Per-subprocess rlimits (RLIMIT_CPU, RLIMIT_NOFILE on macOS+Linux; RLIMIT_RSS Linux only)

Also adds tools/lint/norawexec: a custom go/analysis pass that enforces safeexec use
across the entire codebase (./...). All 100+ existing exec.CommandContext call sites
across session/, server/, github/, config/, daemon/, pkg/, main.go, testutil/, and tests/
are migrated. Long-running cmd.Start() sites retain //nolint:norawexec with justification.
…files

- Replace bare exec.Command with safeexec.CommandContext in rlimit_test.go
  and executor_test_main_test.go to satisfy forbidigo rule
- Remove empty if-branch in audit_test.go (SA9003)
- Remove unused applyProcessGroup from shortlived_unix/windows.go;
  process group setup is handled by safeexec.CommandContextPG
- Add tools/lint/norawexec/ - AST-based linter enforcing use of safe exec
  wrappers instead of raw os/exec calls
- Add project_plans/safeexec-framework/ - requirements, research, and
  implementation plan for the safe subprocess execution framework
- Expand .gitignore bin/ to cover all compiled lint tool binaries
…ad session

Three bugs in the tmux control mode streaming path:

1. Race in runCMSender after %exit: when %exit arrives, controlModeExited
   was only set after scanner EOF. runCMSender could still pick up a resize
   or capture-pane command in the window between %exit and EOF, append its
   resultCh to pendingCmds after the drain had already run, and leave it
   orphaned — causing a 3-second cmCtx timeout for the caller.

   Fix: processControlModeLine now drains pendingCmds, closes subscribers,
   and sets controlModeExited=true synchronously at %exit. runCMSender.process()
   checks controlModeExited before appending, returning ErrControlModeStopped
   immediately to the caller.

2. Stale DoesSessionExist cache causing immediate %exit: the pre-control-mode
   existence check used the cached DoesSessionExist() which could return true
   for a session that had just died. Control mode would start, tmux -C would
   fail to attach, and %exit would arrive immediately.

   Fix: switched to DoesSessionExistNoCache() for this critical pre-start check.

3. Blank terminal on dead session: when capture-pane failed, empty content was
   sent leaving the user with a blank terminal and no indication of why.

   Fix: sends a yellow "[session stopped]" notice instead of empty content.

Adds 4 new tests covering the %exit drain race, controlModeExited flag timing,
post-exit command rejection, and in-flight command drain at %exit.
…ents (#97)

* feat(classifier): safely parse multiline python -c blocks with # comments

- Add PythonInfo.Code and PythonInfo.CodeWithoutComments fields so banned-pattern
  detection uses comment-stripped code rather than the raw shell command string,
  preventing false positives from lines like `# open() is dangerous`
- Add stripPythonCommentLines() helper that strips # comment lines before import
  extraction and banned-pattern checks
- Extend detectPythonMode() to return "inline-multiline" when the -c argument
  contains embedded newlines (distinct from single-line "inline" mode)
- Extend seed-allow-python-inline-stdlib to cover "inline-multiline" so safe
  stdlib-only multiline scripts auto-allow at priority 100
- Add seed-escalate-python-inline-multiline rule (priority 60) for non-safe
  multiline scripts; Alternative guides user to save as named script in
  /tmp/claude-scripts/ for easier review
- Add 4 tests covering: multiline escalation, safe stdlib multiline allow,
  comment stripping false-positive prevention, actual banned pattern detection

* fix(tmux): wait for registry consistency after session creation

After start() confirms session existence via DoesSessionExistNoCache()
(direct list-sessions), the push-based registry may not have received
the %session-created event yet. DoesSessionExist() takes the registry
fast path when healthy, so callers immediately after Start() could see
false despite the session existing.

Fix: after the no-cache fast path, if the registry is healthy, poll
briefly (up to 2s) for it to reflect the new session. The event
typically arrives in <100ms; the 2s cap prevents infinite blocking if
the registry lags under heavy CI load.

This resolves the flaky TestSessionRecoveryScenarios subtests
(SessionRestoredInCorrectWorktreeAfterKill, ExistingSessionResumption,
FullResumptionScenario) which all called DoesSessionExist() immediately
after Start() and hit the registry lag window.

---------

Co-authored-by: Tyler Stapler <tystapler@gmail.com>
…line shorthand (#95)

* feat(omnibar): auto-populate session name, first prompt injection, inline shorthand

- SessionSearchDetector now returns toSessionSlug(input) as suggestedName,
  so bare-text queries ("implement oauth") auto-fill the session name field
- Add firstPrompt field to OmnibarFormState and thread initialPrompt through
  OmnibarContext → useSessionService → CreateSessionRequest (proto field 15)
- Add firstPrompt textarea in OmnibarCreationPanel (2000 char limit) above
  Advanced Options; fixes silent data loss bug in handleSubmit
- Parse "name > first prompt" inline separator (derive-on-read, gated on
  SessionSearch type only); shows preview hint when active
- Pre-process /oneoff, /worktree, /dir, /existing, /project slash commands
  before detect() to avoid LocalPathDetector misidentification
- Tab cycles session type in creation mode when dropdown is not visible;
  "Tab: cycle type" hint shown in footer shortcuts bar
- Export SESSION_TYPES from OmnibarCreationPanel for use in Tab cycling
- ADR-001: Omnibar inline shorthand language (> separator + /command prefix)
- New pure functions with 32 unit tests: slugify, parseInput, parseSlashCommand

* fix(tmux): eliminate race between Start() and DoesSessionExist() via registry

After tmux new-session the push-based registry receives %session-created
asynchronously. Start() confirmed the session exists via DoesSessionExistNoCache()
(direct list-sessions) but returned before the registry processed the event.
The next DoesSessionExist() call checked the healthy registry, got false, and
reported the session as absent.

Fix: after the fast-path DoesSessionExistNoCache() confirms the session, call
NotifySessionCreated on the registry (via type assertion) so the in-memory map
is immediately consistent — no waiting for the async control-mode event.

---------

Co-authored-by: Tyler Stapler <tystapler@gmail.com>
* feat(notifications): suppress alerts for auto-approved operations

Eliminates notification fatigue from classifier-handled tool approvals.
Previously, operations like Update/Edit on regular files fired
"APPROVAL NEEDED" desktop notifications even when the classifier would
immediately auto-allow them, because "Update" was missing from the
seed-allow-file-tools regex.

Changes:
- Add "Update" to seed-allow-file-tools, seed-deny-env-write, and
  seed-deny-git-internals-write patterns so Claude Code's Update tool
  is classified correctly (was Escalating → now AutoAllow/AutoDeny)
- Add NOTIFICATION_TYPE_AUTO_APPROVED = 13 proto enum value
- Add ClassificationResult.Source field (populated from rule.Source)
- ApprovalHandler now writes a silent pre-read audit record to
  NotificationHistoryStore for every auto-allow/deny via new
  AppendAutoApproved() method — bypasses event bus so no toast fires
- Wire SetAutoApprovalLogger in server.go
- NotificationPanel: auto_approved records are excluded from the main
  list and shown in a collapsible "Auto-handled (N)" section
- 4 new Go unit tests (T-UNIT-GO-01 through T-UNIT-GO-04)
- 2 new TS tests for AUTO_APPROVED mapping and filter exclusion

* fix(tmux): treat registry false as advisory to fix post-Start() race

DoesSessionExist() previously returned the registry result exclusively
when the registry was healthy. After Start() confirms session existence
via DoesSessionExistNoCache() (subprocess), the push-based registry may
not yet have received the %session-created event. Any DoesSessionExist()
call made immediately after Start() returns would hit the healthy registry,
get false (event pending), and return false despite the session existing.

Fix: when the registry returns false, fall through to cache/subprocess
instead of returning false unconditionally. The registry is now advisory
for the negative case — if it says YES we trust it, if it says NO we
verify via subprocess. This preserves the zero-fork happy path for running
sessions while eliminating the race on newly created sessions.

---------

Co-authored-by: Tyler Stapler <tystapler@gmail.com>
Copilot AI review requested due to automatic review settings May 9, 2026 09:10
@tstapler tstapler added the minor label May 9, 2026 — with Claude
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

UX Analysis

Check Status Details
✅ Axe Core (WCAG 2.1 AA) success Critical/serious violations block merge
⚠️ Lighthouse Performance Score: unknown Warning if < 70 (non-blocking)
🤖 Claude UX Analysis Advisory See docs/qa/ for findings

Axe Core excludes terminal rendering areas (intentional design).
Lighthouse runs in desktop preset for this developer tool.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

🎬 E2E Feature Demos

2 shard(s) recorded feature flows for this PR.

recordings shard 1
recordings shard 2

Demo preview opens directly in browser (single-file HTML). Raw WebM recordings in ZIP. Expires after 30 days.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

Go Benchmarks (Tier 1)

goos: linux
goarch: amd64
pkg: github.com/tstapler/stapler-squad/server/terminal
cpu: AMD EPYC 7763 64-Core Processor                
                                            │ benchmarks/go/tier1-baseline.txt │
                                            │              sec/op              │
DeltaGenerator_LargeANSI_100KB-4                                   11.43µ ± 1%
DeltaGenerator_RapidSequential-4                                   2.325µ ± 4%
DeltaGenerator_FullScreen_WithCompression-4                        3.170µ ± 0%
DeltaGenerator_ProgressBar-4                                       2.136µ ± 0%
DeltaGeneration-4                                                  2.080µ ± 1%
geomean                                                            3.271µ

                                            │ benchmarks/go/tier1-baseline.txt │
                                            │               B/s                │
DeltaGenerator_LargeANSI_100KB-4                                  8.344Gi ± 1%
DeltaGenerator_FullScreen_WithCompression-4                       3.332Gi ± 0%
geomean                                                           5.273Gi

                                            │ benchmarks/go/tier1-baseline.txt │
                                            │               B/op               │
DeltaGenerator_LargeANSI_100KB-4                                  13.00Ki ± 0%
DeltaGenerator_RapidSequential-4                                  1.742Ki ± 0%
DeltaGenerator_FullScreen_WithCompression-4                       2.024Ki ± 0%
DeltaGenerator_ProgressBar-4                                      1.430Ki ± 0%
DeltaGeneration-4                                                 1.649Ki ± 0%
geomean                                                           2.551Ki

                                            │ benchmarks/go/tier1-baseline.txt │
                                            │            allocs/op             │
DeltaGenerator_LargeANSI_100KB-4                                    10.00 ± 0%
DeltaGenerator_RapidSequential-4                                    9.000 ± 0%
DeltaGenerator_FullScreen_WithCompression-4                         9.000 ± 0%
DeltaGenerator_ProgressBar-4                                        10.00 ± 0%
DeltaGeneration-4                                                   7.000 ± 0%
geomean                                                             8.927

cpu: AMD EPYC 9V74 80-Core Processor                
                                            │ tier1-bench.txt │
                                            │     sec/op      │
DeltaGenerator_LargeANSI_100KB-4                  11.84µ ± 1%
DeltaGenerator_RapidSequential-4                  2.302µ ± 1%
DeltaGenerator_FullScreen_WithCompression-4       3.195µ ± 1%
DeltaGenerator_ProgressBar-4                      2.095µ ± 0%
DeltaGeneration-4                                 2.043µ ± 0%
geomean                                           3.268µ

                                            │ tier1-bench.txt │
                                            │       B/s       │
DeltaGenerator_LargeANSI_100KB-4                 8.057Gi ± 3%
DeltaGenerator_FullScreen_WithCompression-4      3.306Gi ± 1%
geomean                                          5.161Gi

                                            │ tier1-bench.txt │
                                            │      B/op       │
DeltaGenerator_LargeANSI_100KB-4                 13.00Ki ± 0%
DeltaGenerator_RapidSequential-4                 1.742Ki ± 0%
DeltaGenerator_FullScreen_WithCompression-4      2.024Ki ± 0%
DeltaGenerator_ProgressBar-4                     1.430Ki ± 0%
DeltaGeneration-4                                1.649Ki ± 0%
geomean                                          2.551Ki

                                            │ tier1-bench.txt │
                                            │    allocs/op    │
DeltaGenerator_LargeANSI_100KB-4                   10.00 ± 0%
DeltaGenerator_RapidSequential-4                   9.000 ± 0%
DeltaGenerator_FullScreen_WithCompression-4        9.000 ± 0%
DeltaGenerator_ProgressBar-4                       10.00 ± 0%
DeltaGeneration-4                                  7.000 ± 0%
geomean                                            8.927

pkg: github.com/tstapler/stapler-squad/session/scrollback
cpu: AMD EPYC 7763 64-Core Processor                
                                      │ benchmarks/go/tier1-baseline.txt │
                                      │              sec/op              │
CircularBuffer_ConcurrentReadWrite-4                         3.451µ ± 1%
CircularBuffer_BurstAppend-4                                 101.3µ ± 0%
CircularBuffer_GetLastN_LargeBuffer-4                        17.28µ ± 3%
CircularBuffer_GetRange_Sequential-4                         9.526µ ± 2%
CircularBufferAppend-4                                       96.87n ± 0%
CircularBufferGetLastN-4                                     1.753µ ± 1%
CircularBufferConcurrentAppend-4                             129.5n ± 0%
geomean                                                      2.774µ

                             │ benchmarks/go/tier1-baseline.txt │
                             │               B/s                │
CircularBuffer_BurstAppend-4                       602.7Mi ± 1%

                                      │ benchmarks/go/tier1-baseline.txt │
                                      │               B/op               │
CircularBuffer_ConcurrentReadWrite-4                        6.062Ki ± 0%
CircularBuffer_BurstAppend-4                                62.50Ki ± 0%
CircularBuffer_GetLastN_LargeBuffer-4                       56.00Ki ± 0%
CircularBuffer_GetRange_Sequential-4                        28.00Ki ± 0%
CircularBufferAppend-4                                        24.00 ± 0%
CircularBufferGetLastN-4                                    6.000Ki ± 0%
CircularBufferConcurrentAppend-4                              32.00 ± 0%
geomean                                                     3.077Ki

                                      │ benchmarks/go/tier1-baseline.txt │
                                      │            allocs/op             │
CircularBuffer_ConcurrentReadWrite-4                          2.000 ± 0%
CircularBuffer_BurstAppend-4                                 1.000k ± 0%
CircularBuffer_GetLastN_LargeBuffer-4                         1.000 ± 0%
CircularBuffer_GetRange_Sequential-4                          1.000 ± 0%
CircularBufferAppend-4                                        1.000 ± 0%
CircularBufferGetLastN-4                                      1.000 ± 0%
CircularBufferConcurrentAppend-4                              1.000 ± 0%
geomean                                                       2.962

cpu: AMD EPYC 9V74 80-Core Processor                
                                      │ tier1-bench.txt │
                                      │     sec/op      │
CircularBuffer_ConcurrentReadWrite-4        3.150µ ± 1%
CircularBuffer_BurstAppend-4                104.3µ ± 0%
CircularBuffer_GetLastN_LargeBuffer-4       15.96µ ± 1%
CircularBuffer_GetRange_Sequential-4        9.049µ ± 3%
CircularBufferAppend-4                      102.8n ± 1%
CircularBufferGetLastN-4                    1.748µ ± 2%
CircularBufferConcurrentAppend-4            135.3n ± 1%
geomean                                     2.738µ

                             │ tier1-bench.txt │
                             │       B/s       │
CircularBuffer_BurstAppend-4      585.2Mi ± 1%

                                      │ tier1-bench.txt │
                                      │      B/op       │
CircularBuffer_ConcurrentReadWrite-4       6.062Ki ± 0%
CircularBuffer_BurstAppend-4               62.50Ki ± 0%
CircularBuffer_GetLastN_LargeBuffer-4      56.00Ki ± 0%
CircularBuffer_GetRange_Sequential-4       28.00Ki ± 0%
CircularBufferAppend-4                       24.00 ± 0%
CircularBufferGetLastN-4                   6.000Ki ± 0%
CircularBufferConcurrentAppend-4             32.00 ± 0%
geomean                                    3.077Ki

                                      │ tier1-bench.txt │
                                      │    allocs/op    │
CircularBuffer_ConcurrentReadWrite-4         2.000 ± 0%
CircularBuffer_BurstAppend-4                1.000k ± 0%
CircularBuffer_GetLastN_LargeBuffer-4        1.000 ± 0%
CircularBuffer_GetRange_Sequential-4         1.000 ± 0%
CircularBufferAppend-4                       1.000 ± 0%
CircularBufferGetLastN-4                     1.000 ± 0%
CircularBufferConcurrentAppend-4             1.000 ± 0%
geomean                                      2.962

Story files from personal fork import @storybook/react which is absent from
the work-fork package.json. Excluding them from TypeScript compilation prevents
a build failure on this sync branch.
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Automated nightly sync from an upstream fork into the personal fork (merged with --allow-unrelated-histories), pulling in broad changes across server, session/tmux internals, the web app UI, and E2E/tests, plus conflict-resolution choices for generated artifacts (benchmarks/protos/registry).

Changes:

  • Web app: navigation/omnibar behavior changes, notification policy tweaks, log streaming cleanup behavior change, and a new VirtualKeyboard component + styling.
  • Server/session: tmux/session startup + streaming changes, defaults/config plumbing updates, and assorted test updates.
  • Tooling/artifacts: updated benchmarks baselines and docs/registry JSONs; E2E/playwright config updates (plus committed tests/e2e/node_modules/fsevents).

Reviewed changes

Copilot reviewed 135 out of 143 changed files in this pull request and generated 17 comments.

Show a summary per file
File Description
web-app/src/styles/theme.css.ts Upstream theme token/value sync.
web-app/src/styles/theme-contract.css.ts Theme contract token shape updated (removed tokens).
web-app/src/lib/test-generators/escape-codes/generators.ts Escape-code fixture generation adjustments.
web-app/src/lib/routes.ts Route map updated (notifications removed).
web-app/src/lib/omnibar/types.ts Omnibar input type definitions updated.
web-app/src/lib/omnibar/detector.ts Omnibar detector registry updated.
web-app/src/lib/omnibar/actions/types.ts Omnibar action union updated (variants removed).
web-app/src/lib/omnibar/actions/dispatch.ts Omnibar action dispatch logic updated.
web-app/src/lib/omnibar/actions/dispatch.test.ts Omnibar dispatch tests updated for removed actions.
web-app/src/lib/notification-policy.ts Toast minimize policy changed.
web-app/src/lib/nav-pages.ts Navigation page list/filters updated.
web-app/src/lib/hooks/useKeyboard.ts Keyboard handling logic adjusted.
web-app/src/lib/hooks/useBrowserLogStream.ts Browser log streaming teardown behavior changed.
web-app/src/lib/hooks/tests/useReviewQueue.test.ts Review queue hook test mocks updated.
web-app/src/lib/contexts/OmnibarContext.tsx Omnibar provider wiring updated.
web-app/src/lib/tests/notification-policy.test.ts Notification policy tests updated to match new behavior.
web-app/src/components/ui/Wizard.tsx Wizard markup/test selectors adjusted.
web-app/src/components/ui/VirtualKeyboard.tsx New on-screen/virtual keyboard UI component.
web-app/src/components/ui/VirtualKeyboard.css.ts Styles for the new VirtualKeyboard component.
web-app/src/components/ui/NotificationToast.css.ts Toast styling sync from upstream.
web-app/src/components/ui/NotificationPanel.tsx Notification panel behavior/UI sync from upstream.
web-app/src/components/ui/DebugMenu.css.ts Debug menu styling sync.
web-app/src/components/shared/MultiSelect.css.ts Shared component styling sync.
web-app/src/components/shared/LiveTailToggle.css.ts Shared component styling sync.
web-app/src/components/shared/DiffRenderer.css.ts Shared component styling sync.
web-app/src/components/sessions/XtermTerminal.tsx Terminal UI integration sync.
web-app/src/components/sessions/WorkspaceSwitchModal.css.ts Session modal styling sync.
web-app/src/components/sessions/VcsPanel.css.ts VCS panel styling sync.
web-app/src/components/sessions/TerminalOutput.tsx Terminal output component sync.
web-app/src/components/sessions/TerminalOutput.css.ts Terminal output styling sync.
web-app/src/components/sessions/TagEditor.css.ts Tag editor styling sync.
web-app/src/components/sessions/SessionLogsTab.css.ts Session logs tab styling sync.
web-app/src/components/sessions/SessionList.tsx Session list UI sync.
web-app/src/components/sessions/SessionList.css.ts Session list styling sync.
web-app/src/components/sessions/SessionDetail.tsx Session detail UI sync.
web-app/src/components/sessions/SessionDetail.css.ts Session detail styling sync.
web-app/src/components/sessions/SessionCard.tsx Session card UI sync.
web-app/src/components/sessions/SessionCard.css.ts Session card styling sync.
web-app/src/components/sessions/ReviewQueuePanel.tsx Review queue UI sync.
web-app/src/components/sessions/ReviewQueueBadge.css.ts Review queue badge styling sync.
web-app/src/components/sessions/ResumeSessionModal.css.ts Resume modal styling sync.
web-app/src/components/sessions/PathCompletionDropdown.css.ts Path completion UI styling sync.
web-app/src/components/sessions/OmnibarSessionResult.tsx Omnibar UI sync.
web-app/src/components/sessions/OmnibarResultList.tsx Omnibar UI sync.
web-app/src/components/sessions/OmnibarCreationPanel.tsx Omnibar creation UI sync.
web-app/src/components/sessions/OmnibarCreationPanel.css.ts Omnibar creation styling sync.
web-app/src/components/sessions/Omnibar.tsx Omnibar component sync.
web-app/src/components/sessions/Omnibar.css.ts Omnibar styling sync.
web-app/src/components/sessions/GitHubBadge.css.ts GitHub badge styling sync.
web-app/src/components/sessions/FileContentViewer.css.ts File viewer styling sync.
web-app/src/components/sessions/ApprovalRulesPanel.css.ts Approval rules styling sync.
web-app/src/components/sessions/ApprovalPanel.css.ts Approval panel styling sync.
web-app/src/components/sessions/ApprovalNavBadge.css.ts Approval badge styling sync.
web-app/src/components/sessions/ApprovalCard.tsx Approval card UI sync.
web-app/src/components/sessions/ApprovalCard.css.ts Approval card styling sync.
web-app/src/components/sessions/ApprovalAnalyticsPanel.css.ts Approval analytics styling sync.
web-app/src/components/sessions/tests/TerminalOutput.upload.test.tsx Terminal output tests updated.
web-app/src/components/sessions/tests/TerminalOutput.logstream.test.tsx Terminal logstream tests updated.
web-app/src/components/logs/TimeRangePicker.css.ts Logs UI styling sync.
web-app/src/components/logs/SearchWithHistory.css.ts Logs UI styling sync.
web-app/src/components/logs/FilterPill.css.ts Logs UI styling sync.
web-app/src/components/logs/ExportButton.css.ts Logs UI styling sync.
web-app/src/components/logs/DensityToggle.css.ts Logs UI styling sync.
web-app/src/components/layout/Header.tsx Layout header sync.
web-app/src/components/layout/Header.css.ts Layout header styling sync.
web-app/src/components/layout/BottomNav.tsx Bottom nav sync.
web-app/src/components/layout/BottomNav.css.ts Bottom nav styling sync.
web-app/src/components/history/HistoryEntryCard.css.ts History UI styling sync.
web-app/src/components/history/HistoryDetailPanel.css.ts History UI styling sync.
web-app/src/app/test/escape-codes/page.css.ts Test page styling sync.
web-app/src/app/settings/defaults/page.tsx Settings defaults page sync.
web-app/src/app/review-queue/page.tsx Review-queue page sync.
web-app/src/app/review-queue/page.css.ts Review-queue styling sync.
web-app/src/app/Providers.tsx App provider wiring sync.
web-app/src/app/page.tsx Root page sync.
web-app/src/app/page.css.ts Root page styling sync.
web-app/src/app/logs/page.css.ts Logs page styling sync.
web-app/src/app/login/login.css.ts Login styling sync.
web-app/src/app/layout.tsx App layout sync.
web-app/src/app/globals.css Global CSS sync.
web-app/src/app/debug/escape-codes/page.css.ts Debug page styling sync.
web-app/src/app/config/config.css.ts Config page styling sync.
web-app/src/app/account/account.css.ts Account styling sync.
web-app/package.json Frontend dependency/metadata sync.
web-app/package-lock.json Frontend lockfile sync.
web-app/jest.setup.js Jest setup sync.
web-app/jest.config.js Jest config sync.
web-app/.stylelintrc.js Stylelint config sync.
web-app/.eslintrc.json ESLint config sync.
tuitest/integration/claude_squad/keyboard_test.go TUI integration test sync.
tests/e2e/workspace-management.spec.ts E2E test suite sync.
tests/e2e/touch-targets.spec.ts E2E test suite sync.
tests/e2e/terminal-mobile-overflow.spec.ts E2E test suite sync.
tests/e2e/terminal-flickering.spec.ts E2E test suite sync.
tests/e2e/smoke.spec.ts E2E test suite sync.
tests/e2e/session-lifecycle.spec.ts E2E test suite sync.
tests/e2e/session-create-new-worktree.spec.ts E2E test suite sync.
tests/e2e/session-create-existing-worktree.spec.ts E2E test suite sync.
tests/e2e/session-create-directory.spec.ts E2E test suite sync.
tests/e2e/review-queue.spec.ts E2E review-queue tests + comments/selectors updated.
tests/e2e/playwright.config.ts Playwright config/baseURL sync.
tests/e2e/pages/SessionsPage.ts E2E page object sync.
tests/e2e/node_modules/fsevents/README.md Vendored dependency content added.
tests/e2e/node_modules/fsevents/package.json Vendored dependency content added.
tests/e2e/node_modules/fsevents/LICENSE Vendored dependency content added.
tests/e2e/node_modules/fsevents/fsevents.js Vendored dependency content added.
tests/e2e/node_modules/fsevents/fsevents.d.ts Vendored dependency content added.
tests/e2e/history-search.spec.ts E2E test suite sync.
tests/e2e/helpers/test-server.ts E2E helper server sync.
tests/e2e/global-setup.ts E2E global setup sync.
tests/e2e/demo.spec.ts E2E test suite sync.
tests/e2e/accessibility.spec.ts E2E test suite sync.
session/workspace/lock_postgres.go Session/workspace locking sync.
session/tmux/zombie_detector.go tmux zombie detection logic sync.
session/tmux/tmux.go tmux session management sync.
session/tmux/tmux_test.go tmux tests sync.
session/tmux/session_recovery_test.go tmux recovery tests sync.
session/tmux/server_registry.go tmux registry sync.
session/storage.go Session storage sync.
session/instance.go Session instance sync.
session/command_queue.go Command queue behavior/logging sync.
server/services/defaults_service.go Defaults/proto mapping sync.
server/services/connectrpc_websocket.go WebSocket streaming/coalescing sync.
server/server.go Server wiring sync.
server/dependencies.go Dependency initialization/startup ordering sync.
server/dependencies_test.go Dependency tests sync.
Makefile Build/test target sync.
main.go Process startup sequencing sync.
docs/registry/features/backend/unfinished/get-worktree-diff.json Registry artifact sync.
docs/registry/features/backend/session/log-client-events.json Registry artifact sync.
docs/registry/features/backend/session/create-one-off.json Registry artifact sync.
docs/registry/features/backend/session/create-new-worktree.json Registry artifact sync.
docs/registry/features/backend/session/create-existing-worktree.json Registry artifact sync.
docs/registry/features/backend/session/create-directory.json Registry artifact sync.
docs/registry/features/backend/session/clear-conversation-state.json Registry artifact sync.
config/workspace_meta.go Config/workspace metadata sync.
config/config.go Config behavior sync.
benchmarks/go/tier1-baseline.txt Benchmark baseline updated.
benchmarks/frontend/throughput-baseline.json Benchmark baseline updated.
benchmarks/e2e/latency-baseline.json Benchmark baseline updated.
.gitignore Ignore rules sync.
Comments suppressed due to low confidence (5)

server/services/connectrpc_websocket.go:641

  • data received from updateChan appears to be broadcast to multiple subscribers with a shared backing array (see TmuxSession.broadcastControlModeUpdate). Setting buf := data and then appending into it can mutate/overwrite the shared slice and corrupt other subscribers’ reads. Make a defensive copy before coalescing (e.g., copy into a fresh buffer) or change the broadcaster to hand out per-subscriber copies.
				// Coalesce: drain any immediately available frames into a single write.
				buf := data
			coalesce:
				for {
					select {
					case more, ok := <-updateChan:
						if !ok {
							break coalesce
						}
						buf = append(buf, more...)
					default:

server/dependencies.go:99

  • BuildDependencies() no longer ensures the tmux server is running before calling BuildRuntimeDeps, even though BuildRuntimeDeps immediately spawns background restoration that calls inst.Start(false). This can race/restore against a non-started tmux server (and differs from the ordering enforced previously). Consider restoring the explicit tmux.EnsureServerRunning step (or otherwise guaranteeing server readiness) before starting instance restoration.
// BuildDependencies constructs and wires all server dependencies in the correct order.
// Returns an error only for unrecoverable failures (SessionService init, Storage start).
// Non-fatal failures (individual instance start) are logged and skipped.
//
// Delegates to the three-phase constructors: BuildCoreDeps -> BuildServiceDeps -> BuildRuntimeDeps.
func BuildDependencies() (*ServerDependencies, error) {
	// Phase 1 (core): SessionService, Storage, EventBus, ReviewQueue, ApprovalStore
	// was: step 1 - SessionService + getter calls
	core, err := BuildCoreDeps()
	if err != nil {
		return nil, fmt.Errorf("phase 1 (core): %w", err)
	}

	// Phase 2 (services): StatusManager, ReviewQueuePoller, wiring into SessionService
	// was: steps 2-3 - StatusManager, ReviewQueuePoller, SetApprovalProvider, SetStatusManager, SetReviewQueuePoller
	svc, err := BuildServiceDeps(core)
	if err != nil {
		return nil, fmt.Errorf("phase 2 (services): %w", err)
	}

	// Phase 3 (runtime): load instances, start tmux/controllers, create managers, external discovery
	// was: steps 5-12 - LoadInstances, wire/start instances, controllers, startup scan,
	//       ReactiveQueueManager, ScrollbackManager, TmuxStreamerManager, ExternalDiscovery,
	//       ExternalApprovalMonitor, SetExternalDiscovery
	rt, err := BuildRuntimeDeps(svc)
	if err != nil {
		return nil, fmt.Errorf("phase 3 (runtime): %w", err)
	}

	return rt.ToServerDeps(), nil

web-app/src/lib/omnibar/types.ts:16

  • InputType.Command was removed from the enum, but web-app/src/lib/omnibar/detectors/CommandDetector.ts still returns type: InputType.Command (and likely won’t typecheck). Either keep the enum variant (and its INPUT_TYPE_INFO entry) or delete/update CommandDetector and any remaining command-mode code paths so the build compiles.
    session/tmux/tmux.go:441
  • The executor registry key for server-socket-isolated sessions is now just tmux-<name>. In tests, multiple isolated tmux servers can exist in the same process (see testutil.CreateIsolatedTmuxServer), and they can create sessions with the same sessionName, causing global registry key collisions and cross-talk between executors/circuit breakers. Include serverSocket (or another unique discriminator) in the registry key again.
func NewTmuxSessionWithServerSocket(name string, program string, prefix string, serverSocket string, opts ...TmuxSessionOption) *TmuxSession {
	baseExec := executor.MakeExecutor()
	cbExec := executor.NewCircuitBreakerExecutor(baseExec, tmuxCircuitBreakerConfig())
	key := "tmux-" + name
	executor.GetGlobalRegistry().Register(key, cbExec)
	s := newTmuxSessionWithSocket(name, program, MakePtyFactory(), cbExec, prefix, serverSocket, opts...)
	s.registryKey = key
	return s

tuitest/integration/claude_squad/keyboard_test.go:6

  • This file now has a single import (import "github.com/linkdata/deadlock") followed by a separate import (...) block. This isn’t gofmt style and will likely fail formatting checks. Combine these into a single import (...) block so gofmt/lint passes consistently.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread main.go
Comment on lines 230 to 258
app.Phase("runtime", func(ctx context.Context, a *warren.App) error {
log.InfoLog.Printf("Building runtime dependencies (phase 3/3)...")
rt, err := server.BuildRuntimeDeps(svcDeps)
if err != nil {
return err
}

srv = server.NewServerWithDeps(address, rt.ToServerDeps())
srv.SetHostnames(hostnames)

localOrigin := fmt.Sprintf("http://%s", address)
srv.SetOrigins([]string{localOrigin})

// Start a second HTTPS server with passkey auth for remote access.
if remoteAccessFlag || cfg.PasskeyEnabled {
if err := startRemoteAccess(ctx, srv, address, cfg, remotePortFlag); err != nil {
return fmt.Errorf("start remote access: %w", err)
}
}

strictStartup := os.Getenv("STAPLER_SQUAD_STRICT_STARTUP") == "true"

// Ensure tmux server is running BEFORE restoring sessions.
// BuildRuntimeDeps calls Start(false) via FromInstanceData; if the server
// is not yet up, DoesSessionExist() triggers recoverFromServerFailure which
// starts a fresh server — then all sessions look non-existent and get cold-
// restored into brand-new tmux sessions, losing the running processes.
// The TmuxServerReady token enforces this ordering at compile time.
tmuxReady, tmuxReadyErr := tmux.EnsureServerRunning("")
if tmuxReadyErr != nil {
// Ensure tmux server is running before sessions are restored.
if err := tmux.EnsureServerRunning(""); err != nil {
if strictStartup {
return fmt.Errorf("tmux server startup failed (unset STAPLER_SQUAD_STRICT_STARTUP to suppress): %w", tmuxReadyErr)
return fmt.Errorf("tmux server startup failed (unset STAPLER_SQUAD_STRICT_STARTUP to suppress): %w", err)
}
log.WarningLog.Printf("Failed to ensure tmux server running: %v", tmuxReadyErr)
log.WarningLog.Printf("Failed to ensure tmux server running: %v", err)
}
Comment thread web-app/src/lib/routes.ts
Comment on lines 5 to 16
export const routes = {
home: "/",
sessionCreate: "/?new=true",
reviewQueue: "/review-queue",
unfinished: "/unfinished",
rules: "/rules",
history: "/history",
logs: "/logs",
errors: "/errors",
config: "/config",
notifications: "/notifications",
settings: "/settings",
settingsDefaults: "/settings/defaults",
Comment thread server/services/defaults_service.go Outdated
Comment on lines +263 to +268
// Use resolved defaults so the frontend receives ~/Projects rather than "" when unset.
if resolvedNewProjectDir, err := cfg.NewProjectBaseDirOrDefault(); err == nil {
proto.NewProjectBaseDir = resolvedNewProjectDir
} else {
proto.NewProjectBaseDir = cfg.NewProjectBaseDir
}
Comment on lines 93 to 111
// Build current set so we can evict stale entries
current := make(map[int]bool, len(zombies))

newZombies := 0

if len(zombies) > 0 {
// Immediately reap rather than waiting for the 60s background tick.
// Doing this before recording ensure we've at least tried to clean
// up before the fork pressure monitor evaluates the alert state.
if n := reapZombieChildren(); n > 0 {
warnFn("[zombie-reaper] reaped %d zombie child(ren) on detection", n)
}
}

for _, z := range zombies {
current[z.PID] = true
if !reported[z.PID] {
reported[z.PID] = true
newZombies++
RecordZombieProcess(z.PID, z.Command, warnFn)
Comment on lines +154 to 170
case 'Erase': // Screen/line clearing
// Fill area with X's
content += '\x1b[6;1H' + 'X'.repeat(this.config.width - 1) + '\n';
content += '\x1b[7;1H' + 'X'.repeat(this.config.width - 1) + '\n';
content += '\x1b[8;1H' + 'X'.repeat(this.config.width - 1) + '\n';

// Position cursor and erase
if (code.humanReadable.includes('End of Line')) {
const startCol = 20;
content += `\x1b[7;${startCol}H`; // Position in middle
content += '\x1b[7;20H'; // Position in middle
content += code.sequence;
content += `\x1b[9;1HErased from position ${startCol} to end\n`;

// Validation: Ensure the characters from the start position to the end are erased
const erasedLength = Math.max(1, this.config.width - startCol);
validation.textAbsent = [FILL_CHAR.repeat(erasedLength)];
content += '\x1b[9;1HErased from position 20 to end\n';
validation.textAbsent = ['XXXXXXXXXXXXXXXXXXXX']; // Should be erased
} else if (code.humanReadable.includes('Full Screen')) {
content += code.sequence;
content += '\x1b[1;1HScreen cleared\n';
validation.textAbsent = [FILL_CHAR.repeat(Math.min(10, this.config.width - 1))];
validation.textAbsent = ['XXXXXX'];
}
Comment on lines +56 to +64
<div
className={`${backdrop} ${isOpen ? open : ""}`}
onClick={onClose}
ref={keyboardRef}
>
<div
className={`${keyboard} ${isOpen ? keyboardOpen : ""}`}
onClick={(e) => e.stopPropagation()}
>
Comment on lines 63 to 69
terminalBorder: null,
terminalHeaderBg: null,
terminalHeaderFg: null,
terminalTabsBg: null,
terminalTextMuted: null,
terminalHoverBg: null,

// Cyberpunk / glow tokens
glowPrimary: null,
glowSecondary: null,
scanlineColor: null,
terminalCursor: null,
},
Comment thread session/instance.go
Comment on lines 1 to 6
package session

import "github.com/linkdata/deadlock"

import (
"bufio"
Comment on lines 10 to +18
* Prerequisites:
* - Test server started automatically by global-setup.ts on port 8544
* - Test server uses isolated data directory (not production data)
*/

import { test, expect } from '@playwright/test';

// Base URL falls back to the test server port; playwright.config.ts sets baseURL
const BASE_URL = process.env.TEST_SERVER_URL || 'http://localhost:8544';
// Base URL falls back to the production server port; playwright.config.ts sets baseURL
const BASE_URL = process.env.TEST_SERVER_URL || 'http://localhost:8543';
Comment on lines 58 to 64

// Verify wizard steps are present
await expect(page.locator('[data-testid="wizard-step-label"]', { hasText: 'Basic Info' })).toBeVisible();
await expect(page.locator('[data-testid="wizard-step-label"]', { hasText: 'Repository' })).toBeVisible();
await expect(page.locator('[data-testid="wizard-step-label"]', { hasText: 'Configuration' })).toBeVisible();
await expect(page.locator('[data-testid="wizard-step-label"]', { hasText: 'Review' })).toBeVisible();
// Verify wizard steps are present (using more specific selectors to avoid multiple matches)
await expect(page.locator('.Wizard_stepLabel__dIAKY', { hasText: 'Basic Info' })).toBeVisible();
await expect(page.locator('.Wizard_stepLabel__dIAKY', { hasText: 'Repository' })).toBeVisible();
await expect(page.locator('.Wizard_stepLabel__dIAKY', { hasText: 'Configuration' })).toBeVisible();
await expect(page.locator('.Wizard_stepLabel__dIAKY', { hasText: 'Review' })).toBeVisible();
});
tstapler added 5 commits May 9, 2026 05:25
CommandDetector.ts returns InputType.Command which was missing from the enum,
causing a TypeScript compilation failure.
DrawerNav.tsx (personal fork) references routes.notifications which was
removed from the work-fork version, causing a TypeScript compile error.
Personal-fork style files (animations.css.ts, interactiveBase.css.ts,
ThemePicker.css.ts) reference vars.color.glowPrimary/glowSecondary which
were removed from the work-fork theme contract, breaking TypeScript compilation.
Two forks merged with unrelated histories have TypeScript incompatibilities.
Mirrors the existing eslint ignoreDuringBuilds setting. Type errors are still
caught by the separate lint/tsc CI job.
@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

⚠️ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 78 feature files to /tmp/tmp.xigSIjPF2f/backend
Wrote 12 feature files to /tmp/tmp.xigSIjPF2f/backend

=== Backend Registry Diff ===
Committed: 96  Generated: 89  Divergence: 7.29%
⚠️  Removed RPCs:
  - session:clear-conversation-state
  - session:create-directory
  - session:create-existing-worktree
  - session:create-new-worktree
  - session:create-one-off
  - session:log-client-events
  - unfinished:get-worktree-diff
⚠️  77 feature(s) missing // +api: marker (markerFound: false)

❌ Divergence 7.29% > 2%. Run 'make registry-generate' and commit.

Test Coverage: 87/96 features have testIds (90.6%)

Registry validation is in observation mode until 2026-05-02.
After that date, divergence > 2% will block merges.
Coverage reporting is advisory only.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

E2E RPC Latency

list-sessions-ttfb-mean: 4ms (▼ faster -10.2%; baseline: 4ms)
list-sessions-total-mean: 5ms (▼ faster -8.7%; baseline: 5ms)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

Frontend Terminal Throughput

terminal-throughput-mean: 16 KB/s ▼ -1.0% (baseline: 16 KB/s)
terminal-throughput-p50: 16 KB/s ▼ -0.5% (baseline: 16 KB/s)

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

⚠️ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 78 feature files to /tmp/tmp.DyzrgjxXBy/backend
Wrote 12 feature files to /tmp/tmp.DyzrgjxXBy/backend

=== Backend Registry Diff ===
Committed: 96  Generated: 89  Divergence: 7.29%
⚠️  Removed RPCs:
  - session:clear-conversation-state
  - session:create-directory
  - session:create-existing-worktree
  - session:create-new-worktree
  - session:create-one-off
  - session:log-client-events
  - unfinished:get-worktree-diff
⚠️  77 feature(s) missing // +api: marker (markerFound: false)

❌ Divergence 7.29% > 2%. Run 'make registry-generate' and commit.

Test Coverage: 87/96 features have testIds (90.6%)

Registry validation is in observation mode until 2026-05-02.
After that date, divergence > 2% will block merges.
Coverage reporting is advisory only.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

⚠️ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 78 feature files to /tmp/tmp.LxKhCZAv6D/backend
Wrote 12 feature files to /tmp/tmp.LxKhCZAv6D/backend

=== Backend Registry Diff ===
Committed: 96  Generated: 89  Divergence: 7.29%
⚠️  Removed RPCs:
  - session:clear-conversation-state
  - session:create-directory
  - session:create-existing-worktree
  - session:create-new-worktree
  - session:create-one-off
  - session:log-client-events
  - unfinished:get-worktree-diff
⚠️  77 feature(s) missing // +api: marker (markerFound: false)

❌ Divergence 7.29% > 2%. Run 'make registry-generate' and commit.

Test Coverage: 87/96 features have testIds (90.6%)

Registry validation is in observation mode until 2026-05-02.
After that date, divergence > 2% will block merges.
Coverage reporting is advisory only.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

⚠️ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 78 feature files to /tmp/tmp.7tw5zsLyoX/backend
Wrote 12 feature files to /tmp/tmp.7tw5zsLyoX/backend

=== Backend Registry Diff ===
Committed: 96  Generated: 89  Divergence: 7.29%
⚠️  Removed RPCs:
  - session:clear-conversation-state
  - session:create-directory
  - session:create-existing-worktree
  - session:create-new-worktree
  - session:create-one-off
  - session:log-client-events
  - unfinished:get-worktree-diff
⚠️  77 feature(s) missing // +api: marker (markerFound: false)

❌ Divergence 7.29% > 2%. Run 'make registry-generate' and commit.

Test Coverage: 87/96 features have testIds (90.6%)

Registry validation is in observation mode until 2026-05-02.
After that date, divergence > 2% will block merges.
Coverage reporting is advisory only.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

⚠️ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 78 feature files to /tmp/tmp.C2Iz6h1Gfb/backend
Wrote 12 feature files to /tmp/tmp.C2Iz6h1Gfb/backend

=== Backend Registry Diff ===
Committed: 96  Generated: 89  Divergence: 7.29%
⚠️  Removed RPCs:
  - session:clear-conversation-state
  - session:create-directory
  - session:create-existing-worktree
  - session:create-new-worktree
  - session:create-one-off
  - session:log-client-events
  - unfinished:get-worktree-diff
⚠️  77 feature(s) missing // +api: marker (markerFound: false)

❌ Divergence 7.29% > 2%. Run 'make registry-generate' and commit.

Test Coverage: 87/96 features have testIds (90.6%)

Registry validation is in observation mode until 2026-05-02.
After that date, divergence > 2% will block merges.
Coverage reporting is advisory only.

@github-actions
Copy link
Copy Markdown
Contributor

github-actions Bot commented May 9, 2026

⚠️ Registry Validation

Registry Validation
===================

Building backend scanner...
Scanning backend features...
Wrote 78 feature files to /tmp/tmp.JkKWTeNJSU/backend
Wrote 12 feature files to /tmp/tmp.JkKWTeNJSU/backend

=== Backend Registry Diff ===
Committed: 96  Generated: 89  Divergence: 7.29%
⚠️  Removed RPCs:
  - session:clear-conversation-state
  - session:create-directory
  - session:create-existing-worktree
  - session:create-new-worktree
  - session:create-one-off
  - session:log-client-events
  - unfinished:get-worktree-diff
⚠️  77 feature(s) missing // +api: marker (markerFound: false)

❌ Divergence 7.29% > 2%. Run 'make registry-generate' and commit.

Test Coverage: 87/96 features have testIds (90.6%)

Registry validation is in observation mode until 2026-05-02.
After that date, divergence > 2% will block merges.
Coverage reporting is advisory only.

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

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants