Skip to content

🤖 refactor: auto-cleanup#3291

Open
mux-bot[bot] wants to merge 21 commits into
mainfrom
auto-cleanup
Open

🤖 refactor: auto-cleanup#3291
mux-bot[bot] wants to merge 21 commits into
mainfrom
auto-cleanup

Conversation

@mux-bot
Copy link
Copy Markdown
Contributor

@mux-bot mux-bot Bot commented May 15, 2026

Summary

Rolling, low-risk cleanup batch. Each run adds one extremely small,
behavior-preserving refactor picked from changes that have landed on main
since the last checkpoint.
Auto-cleanup checkpoint: 789053a

Current diff against main:

  • src/browser/utils/additionalSystemContextStore.ts — drop the
    unused __resetAdditionalSystemContextFocusForTests export and
    promote pendingFocusGeneration from let to const. The reset
    helper was added speculatively alongside the Instructions tab in
    🤖 feat: Instructions tab in right sidebar #3262, but ripgrep across src/ and tests/ finds zero importers —
    no test ever calls it. Removing it lets the only other reason the
    module needed a mutable binding (the pendingFocusGeneration = new Map() reassignment inside the helper) go away, so the binding can
    be a const Map that's still mutated in place via .set(). The
    requestAdditionalSystemContextFocus /
    getAdditionalSystemContextFocusGeneration callers continue to see
    the exact same Map identity and counter semantics — pure dead-code
    removal with no runtime behavior change.

  • src/browser/features/Messages/Mermaid.tsx — hoist the URL-attribute
    set and blocked-scheme list out of sanitizeMermaidSvg into
    module-level constants (SANITIZER_URL_ATTRIBUTES,
    SANITIZER_BLOCKED_URL_SCHEMES). They are pure lookup data with no
    per-call dependency, so allocating them on every Mermaid render was
    wasted work; they now allocate once per module load. Identical
    contents and identical lookup semantics — pure cleanup with no
    behavior change.

  • src/node/services/agentStatusService.ts — hoist the AI SDK v5
    tool-part state → lifecycle phase mapping out of summarizeToolPart
    into a module-level TOOL_PART_PHASE_BY_STATE record. The previous
    nested ternary obscured the actual mapping (output-available and
    output-redacted both fold to "done") and made adding new states a
    multi-line edit. The summarizer now does a single table lookup; the
    union-typed values document the two valid phases inline. States not
    in the table (e.g. input-streaming) still yield null and the bare
    [tool <name>] form, byte-for-byte identical to before.

  • src/browser/utils/slashCommands/experimentVisibility.ts (+ two
    consumers) — add createSlashCommandExperimentResolver(snapshot)
    alongside resolveSlashCommandExperimentValue. Three slash-command
    discovery surfaces (suggestions in ChatInput, the ghost-hint call in
    ChatInput, and the CommandPalette palette query) had each inlined
    the same (experimentId) => resolveSlashCommandExperimentValue(experimentId, snapshot) lambda. The new helper returns the exact same closure each
    callsite previously built inline, so the isExperimentEnabled
    predicate handed to getSlashCommandSuggestions / getCommandGhostHint
    is behaviorally identical; only the wiring detail (that resolution
    is parameterized by experiment id) moves into the visibility module.
    Rebased through the goals GA removal — the snapshot now carries
    only workspaceHeartbeats but the resolver helper itself is
    unchanged.

  • src/cli/run.ts — fold the Runtime type import into the existing
    import type { InitLogger, WorkspaceInitResult } from "../node/runtime/Runtime"
    line. The SSH-provisioning commit (🤖 perf: cut SSH workspace startup ~9× on the warm path via fused single-RTT materialization #3302) added a second import type { Runtime } from "../node/runtime/Runtime" directly below it; merging
    them is byte-identical semantics with one fewer line of boilerplate.
    No behavior change.

  • src/node/services/agentSkills/agentSkillsService.test.ts — extract a
    shared BUILT_IN_SKILL_NAMES constant for the two toEqual([...])
    assertions that previously enumerated the same five built-in skill
    names (imagegen, init, mux-diagram, mux-docs, orchestrate)
    inline. The two call sites differ only in their project-skill prefix;
    spreading the shared constant at the end of each list preserves the
    exact sort order and assertion semantics. The next built-in skill
    added (e.g. when /orchestrate graduates to advertised, or a new
    hidden skill lands) only needs to update one list instead of two.
    Byte-equivalent assertion output; no runtime behavior change.

  • src/browser/features/Settings/Sections/TasksSection.tsx — extract an
    AdvisorSwitch component for the per-agent advisor toggle. The
    Tooltip + Switch + optional Reset button block was duplicated
    between renderAgentDefaults and renderUnknownAgentDefaults (added
    in 🤖 fix: enable advisor for default subagents #3309 when the Advisor experiment gained default-on behavior for
    Exec and Plan). The two call sites differ only in the agent-id
    variable they close over and which setter/resetter to invoke, so the
    shared markup now lives in one place. Same aria-label, same
    tooltip text via getAdvisorSwitchState, same conditional Reset
    semantics — the TasksSection UI test (defaults advisor on for Exec and Plan when the experiment is enabled) still finds both switches
    by their unchanged role + name.

  • src/common/utils/ai/streamChunks.ts (+ two consumers) — hoist the
    ["text", "delta", "textDelta"] field priority used to extract AI SDK
    v5 text-delta payloads into a shared TEXT_OUTPUT_DELTA_FIELDS
    constant. Both streamManager.ts (the fullStream text-delta part
    handler) and tools/advisor.ts (the advisor streamText onChunk
    text-delta handler, added in 🤖 feat: stream advisor output live #3310) had inlined the same array
    literal; centralizing it prevents drift if the AI SDK normalizes
    another alias and documents the intent in one place. The other two
    extractChunkDeltaText callsites in aiService.ts use deliberately
    different field orderings (["textDelta", "delta", "text"] for
    parent-step text-delta capture, ["text", "textDelta", "delta"] for
    reasoning-delta capture) and are intentionally left untouched.
    Byte-equivalent lookup semantics at every callsite — pure DRY.

  • src/browser/features/RightSidebar/GoalTab.tsx — extract a small
    file-scoped StatTileHeader component for the duplicated <dt> +
    inline-Edit-button header row used by BudgetTile and TurnsTile
    (added in 🤖 feat(goals-tab): consolidate Cost/Budget/Remaining + always show Turn cap #3314 when the active-goal stat surface was consolidated).
    The two tiles previously inlined the same flex wrapper, the same
    text-muted text-xs <dt>, and the same text-xs underline Edit
    button — only the label string and aria-label differed. The shared
    helper preserves those two parameters as props and keeps every class
    name, type="button", and aria label byte-for-byte identical, so the
    inline budget/turn-cap editors in GoalTab.test.tsx (which locate
    their openers via getByLabelText("Edit goal budget") /
    getByLabelText("Edit goal turn cap")) still match. Pure DRY; no
    behavior change.

  • src/common/orpc/types.ts (+ three consumers) — hoist the
    GoalInterventionPolicy = NonNullable<SendMessageOptions["goalInterventionPolicy"]>
    alias next to SendMessageOptions itself. After 🤖 feat: add goal intervention policy #3319 added the
    policy field, three independent files re-derived the same alias:
    the browser ChatInput/types.ts barrel, node/services/messageQueue.ts,
    and node/services/agentSession.ts. The canonical alias now lives
    beside its source schema; ChatInput/types.ts re-exports it so the
    feature-local import surface stays unchanged, and the two node-side
    files import directly. Identical type semantics at every callsite —
    pure relocation with no runtime behavior change.

  • src/node/services/agentSession.ts — convert
    synthesizeSilentContinuationSummary from a private method on
    AgentSession to a module-level free function. The helper, added in
    🤖 fix(goals): treat text-only continuation turns as goal completion #3326 as part of the silent-continuation auto-complete hook, only
    depends on its input parts argument — it never touches this.
    Moving it alongside the existing free helpers
    (stripGoalInterventionPolicy, coerceGoalSyntheticMessageKind,
    extractAgentSkillRefs, etc.) makes the no-this contract obvious
    to readers and keeps the file's helper style consistent. The
    companion maybeAutoCompleteGoalFromSilentContinuation method stays
    on the class because it accesses this.workspaceGoalService,
    this.workspaceId, and the instance-scoped log. Byte-for-byte
    identical logic at the only callsite; the
    agentSession.goalAutoPause.test.ts suite (18/18 pass) continues to
    cover the silent-continuation, dynamic-tool-present, manual-user, and
    paused-goal branches.

  • src/node/services/tools/review_pane.ts — switch the dedup seed loop
    in applyReviewPaneUpdate from for (const h of base) { seen.set(..., base.indexOf(h)) } to for (const [i, h] of base.entries()) { seen.set(..., i) }. The previous form ran an O(n²) reference scan on every seed
    iteration even though the loop already had the index in hand; the
    result is byte-equivalent for the realistic case where every entry in
    base is a unique reference (which is always true today — base is
    either [] or [...current] after the previous deduped call) and now
    correct-by-construction even if a future refactor ever introduced
    duplicate references. Same dedup map contents, same final hunk
    ordering — the 15 existing review_pane.test.ts tests (including the
    "dedupes by formatted path:range key when adding, preferring the
    latest comment" case) all pass unchanged. Picked from the
    review_pane_update tool feature landed in 🤖 feat: add review_pane_update tool + Assisted review toggle #3331.

  • src/cli/run.ts — extract a CLI_DISABLED_TOOL_NAMES tuple and build
    the mux run toolPolicy array via .map(name => ({ regex_match: name, action: "disable" as const })). The five entries previously inlined
    in buildSendOptions (ask_user_question, status_set, todo_write,
    todo_read, notify) differed only by tool name and all shared the
    exact same action: "disable" shape. Picked from the
    ask_user_question disable that landed in 🤖 fix: disable ask_user_question in mux run #3336 — that commit added
    a fifth identical-shape entry, so the table form is now strictly
    tidier than five copy-pasted object literals, and the next disabled
    CLI tool drops to one string instead of duplicating the object
    shape. Byte-equivalent toolPolicy contents (same five entries,
    same order, same regex_match and action values), so no behavior
    change.

  • src/browser/features/Tools/AskUserQuestionToolCall.tsx — extract a
    module-level getSectionPillClassName(isSelected, isComplete) helper
    for the executing-UI section pills. The two pill renderers (one per
    question, plus the Summary pill, both added in 🤖 refactor: polish ask_user_question UI #3339 when the
    ask_user_question UI was polished) inlined the exact same nine-class
    Tailwind string and the same three-way selected (accent) / complete
    (success-tinted) / pending (neutral) branch logic — they differed
    only in which boolean drove the "selected" leg (isActive for
    question pills, isOnSummary for the Summary pill) and which boolean
    drove the "complete" leg (answered vs isComplete). The helper
    centralizes the class string so the next visual tweak to those pills
    lives in one place. Byte-equivalent class output at both callsites
    (verified by diffing the rendered class strings), so the existing
    AskUserQuestionToolCall.test.tsx suite (4/4 pass) continues to
    locate the buttons by their unchanged role + accessible name.

  • src/node/services/signingService.test.ts — extract a module-local
    restoreEnvVar(key, savedValue) helper to fold the four inlined
    copies of the SSH env-var restore block (twice in the
    withoutSshAgent finally, twice in afterAll) into single-line
    calls. Each copy used the identical if (saved === undefined) delete process.env[X]; else process.env[X] = saved shape — only the env-var
    name differed (SSH_AUTH_SOCK vs SSH_AGENT_PID). The helper
    preserves that exact delete-vs-assign decision per key, so the
    process.env state after withoutSshAgent returns and after the suite
    tears down is byte-equivalent to before. Picked from 🤖 tests: stabilize flaky signing and best-of task tests #3340, which
    brought this file back under review when it bumped the Ed25519
    "should load key and return capabilities" test to a 15s timeout. The
    full suite (14/14 SigningService tests, including all withoutSshAgent
    paths and the agent-vs-disk priority tests that depend on the
    restore semantics) passes unchanged. Pure DRY; no behavior change.

  • src/browser/features/RightSidebar/CodeReview/ReviewPanel.tsx
    (+ test consumer) — relocate the test-only buildReviewDiffPathFilter
    single-result wrapper out of ReviewPanel.tsx and into
    ReviewPanel.assistedStats.test.ts as a private file-scoped helper.
    The wrapper was introduced in 🤖 fix: surface assisted review hunks reliably #3344 alongside the multi-spec
    buildReviewDiffPathFilterSpecs form so the existing
    buildReviewDiffPathFilter describe block (two assertions: assisted
    mode fetches agent-pinned files, non-assisted mode preserves the
    selected file pathspec) could keep using a pathFilter: string
    return shape. The two production callers in the same file
    (ReviewAssistedStatsReporter's diff-load effect and
    ReviewPanel's diff-load effect) already use the multi-spec
    buildReviewDiffPathFilterSpecs directly so they can fan out across
    per-repo-root pathspecs — nothing in production ever called the
    single-result wrapper. The relocated helper has byte-identical
    implementation (same ...params, projectPath: repoRootProjectPath ?? "" forwarding, same [0]?.pathFilter ?? "" first-spec
    extraction), so the 10/10 ReviewPanel.assistedStats.test.ts
    assertions pass unchanged; ReviewPanel.tsx just stops exporting a
    helper that no production code consumes.

  • src/cli/run.ts — convert the two throw new Error('Invalid --goal-* "' + value + '" ...') messages in the new parseGoalBudgetFlag and
    parseGoalTurnsFlag helpers (added in 🤖 bench: add Terminal-Bench strict goal mode #3348) to backtick template
    literals (`Invalid --goal-budget "${value}". ...`). These were
    the only two throw new Error('...') single-quoted-concatenation
    pairs left in src/cli/run.ts; every other throw new Error( in the
    file — including the adjacent parseMode helper at the top of the
    same block — already uses a backtick template literal. The thrown
    Error message text is byte-for-byte identical (same Invalid --goal-budget "<value>". Expected dollars like 5, $5.00, or cents like 500c and Invalid --goal-turns "<value>". Expected a positive integer strings, same single quotes around the user value), so this
    is a pure stylistic alignment with no behavior change.

  • src/browser/features/RightSidebar/GoalTab.tsx — hoist the duplicated
    neutral-button Tailwind class string used by the Pause / Mark complete
    / Reopen lifecycle action buttons into a single module-level
    GOAL_LIFECYCLE_NEUTRAL_BUTTON_CLASS constant. After 🤖 refactor: style goal row actions as real buttons #3342 reshaped
    the completed-goal action row, three buttons in the same flex flex-wrap gap-2 group inlined the same nine-class string
    (border-border-light bg-surface-secondary text-foreground hover:bg-surface-tertiary inline-flex items-center gap-1.5 rounded-md border px-3 py-1.5 text-sm); the accent-colored Archive and
    success-tinted Resume buttons keep their own inline strings because
    they are the only primary / positive variants in the row. The
    existing active goals expose a de-prominent Clear; completed goals promote Archive as primary assertion (reopenButton.className does
    NOT contain bg-accent; archiveButton.className DOES) and every
    Pause / Mark complete / Reopen aria-label lookup in
    GoalTab.test.tsx (23/23 pass) continue to hold. Byte-equivalent
    class string at every callsite; no behavior change.

  • src/node/runtime/SSHRuntime.ts — dedupe the four receive-pack
    thin-pack failure patterns (unresolved deltas, unpacker error,
    unpack-objects abnormal exit, remote unpack failed) that 🤖 fix(ssh): harden bare base repo against receive-pack thin-pack failures #3356
    introduced inline in both PROJECT_SYNC_RETRYABLE_ERRORS (used by
    the broad retry classifier at the isProjectSyncRetryableError
    callsite) and UNRESOLVED_DELTA_PUSH_PATTERNS (used by
    isUnresolvedDeltaPushFailure to decide whether the next retry
    attempt should add --no-thin). The sub-class is now declared once
    on UNRESOLVED_DELTA_PUSH_PATTERNS (with the long rationale
    consolidated onto its JSDoc) and spread into
    PROJECT_SYNC_RETRYABLE_ERRORS via ...UNRESOLVED_DELTA_PUSH_PATTERNS.
    Both .some((pattern) => errorMsg.includes(pattern)) iterations see
    the same four patterns in the same order, so retry classification and
    the forceNoThinNextAttempt decision are byte-equivalent — pure DRY,
    no behavior change. The existing SSHRuntime.retry.test.ts and
    SSHRuntime.syncContract.test.ts suites both pass unchanged.

  • src/browser/features/Tools/bashCollapsedSummary.ts — extract a
    matchesCommand(value, command) helper next to normalizeForComparison
    and route the three existing normalizeForComparison(X) !== normalizeForComparison(command) callsites through it. The intent-only
    summary mode added in 🤖 feat: add intent-only bash summaries #3360 introduced a second
    normalizeForComparison(displayName) !== normalizeForComparison(command)
    inside the new getIntentOnlyFallback, doubling the predicate that was
    already used to filter a redundant intent and inside
    stripTrailingUsingCommand to detect a redundant trailing using <command> clause. The helper composes the existing normalizer, returns
    the identical boolean, and no callsite changes its branch direction —
    so intent-vs-command redundancy filtering, display-name fallback
    selection, and the using-clause stripper are all byte-for-byte
    identical. The existing bashCollapsedSummary.test.ts suite (10/10)
    exercises every branch — intent equal to command, intent missing,
    intent-only mode falling back to display name, display name equal to
    command, and the nested using-clause sanitize pass — and all pass
    unchanged.

Validation

  • make static-check — eslint, tsgo (×2 configs), and prettier all green
    locally; the only red step is fmt-shell-check failing because shfmt
    isn't installed in this environment (pre-existing env limitation, no
    shell files touched by these changes).
  • bun test src/browser/features/RightSidebar/GoalTab.test.tsx — 23/23 pass.
  • bun test src/browser/features/RightSidebar/CodeReview/ReviewPanel.assistedStats.test.ts
    — 10/10 pass.
  • bun test src/browser/features/Tools/AskUserQuestionToolCall.test.tsx
    — 4/4 pass.
  • bun test src/node/services/signingService.test.ts — 14/14 pass.
  • bun test src/browser/features/Tools/bashCollapsedSummary.test.ts — 10/10 pass.

Generated with mux • Model: anthropic:claude-opus-4-7 • Thinking: xhigh

@mux-bot mux-bot Bot force-pushed the auto-cleanup branch 11 times, most recently from 2ca21da to 31a3fa8 Compare May 19, 2026 20:37
@mux-bot
Copy link
Copy Markdown
Contributor Author

mux-bot Bot commented May 19, 2026

⚠️ Auto-fixup could not resolve CI failure: Windows-only flake in tests/ipc/runtime/backgroundBashDirect.test.ts > Foreground to Background Migration > should migrate foreground bash to background and continue running.

Failure:

expect(received).toContain(expected) // indexOf
Expected substring: "BEFORE_BG_fg_to_bg_1779223264672"
Received string:    "Process sent to background with ID: fg_to_bg_1779223264672
Output so far (0 lines):
"
    at tests/ipc/runtime/backgroundBashDirect.test.ts:410:27

Why this is a flake, not caused by the cleanup commit:

  • This test is already known to be timing-sensitive on Windows. The file defines FOREGROUND_MIGRATION_READY_MS = process.platform === "win32" ? 900 : 300 and there's an existing commit titled "Harden fast-exit foreground migration assertion on Windows" targeting this exact file.
  • The "Output so far (0 lines)" shape means the foreground bash hadn't flushed its first echo line before sendToBackground was called — a Git Bash startup / IO timing race on Windows CI.
  • The auto-cleanup diff touches none of: background process manager, LocalRuntime, bash tool, runtime/, or this test. It only touches UI components, agent session/status/queue/stream services, image/advisor/review_pane tools, agentSkills test, experimentVisibility, cli/run, orpc/types, and streamChunks.

Action: No fix pushed. Recommend retrying the Windows job; if it persists, the Windows ready-wait may need to be bumped above 900ms or the assertion further hardened (separate from this cleanup PR).

@mux-bot mux-bot Bot force-pushed the auto-cleanup branch 8 times, most recently from f4a79eb to 0a996c2 Compare May 21, 2026 20:38
@mux-bot
Copy link
Copy Markdown
Contributor Author

mux-bot Bot commented May 21, 2026

⚠️ Auto-fixup could not resolve CI failure: pre-existing process-wide test pollution flake, unrelated to this PR.

Symptom (run 26251744959): 78 Test / Unit failures cascading from TypeError: window.addEventListener is not a function originating in src/browser/utils/RefreshController.ts:455, with downstream collateral damage in GitStatusStore, WorkspaceHeartbeatModal, InlineSkillMarkdown, goal set objective prompt, task_apply_git_patch, etc.

Root cause: src/browser/stores/WorkspaceStore.test.ts:148 assigns global.window = mockWindow (a partial stub lacking addEventListener). Bun runs all test files in the same process, so any later file that constructs a RefreshController crashes on the leaked partial window.

Why this isn't the cleanup PR's fault:

  • This PR's diff touches 26 files of pure refactors (constants extraction, helper extraction, type relocation). None of them modify RefreshController.ts, GitStatusStore.test.ts, WorkspaceStore.test.ts, usePersistedState.ts, tests/setup.ts, or any window/global-handling code.
  • Running the suspected pair locally (bun test src/browser/stores/WorkspaceStore.test.ts src/browser/stores/GitStatusStore.test.ts) passes 150/150 — the failures only manifest when the full bun test src suite runs in process-wide order.

Existing fixes on other branches (not yet on main):

  • e477ac3e7 on assisted-review-ux-passfix(tests): guard window listeners against partial-window test stubs (adds typeof X === "function" guards in RefreshController constructor/dispose and usePersistedState). Its commit message explicitly notes this affects "unrelated test files even though each passes in isolation".
  • 95312509c on benchmark-m445tests: stabilize GitStatusStore window mock.

Recommendation: cherry-pick e477ac3e7 (or fix WorkspaceStore.test.ts to mock a complete window) onto main as a standalone fix; once merged, re-run CI here. Manual intervention needed.

mux-bot Bot and others added 9 commits May 22, 2026 00:25
Both image_generate and image_edit duplicated the same
"Adjust Settings > Experiments > Image Tools or request fewer
images." setup hint literal when the requested image count
exceeded the configured maxImagesPerCall. Hoist it next to the
existing IMAGE_TOOL_PROVIDER_SETUP_HINT in imageArtifacts.ts so
the guidance has a single source of truth, matching the pattern
established by the prior auto-cleanup PR.
Move `urlAttributes`/`blockedSchemes` out of `sanitizeMermaidSvg` and
into module-level constants (`SANITIZER_URL_ATTRIBUTES`,
`SANITIZER_BLOCKED_URL_SCHEMES`). They are pure lookup data with no
per-call dependency, so allocating them on every render of every Mermaid
diagram was wasted work — these now allocate once per module load.

Pure cleanup: identical contents, identical lookup semantics, no
behavior change. The full Mermaid.test.tsx suite (including the recent
sanitizer regression tests) still passes.

---

_Generated with `mux` • Model: `anthropic:claude-opus-4-7` • Thinking: `xhigh` • Cost: `$`_

<!-- mux-attribution: model=anthropic:claude-opus-4-7 thinking=xhigh costs= -->
`summarizeToolPart` carried the AI SDK v5 `state` → lifecycle phase
mapping inline as a nested ternary plus a multi-line comment listing the
states. The ternary obscured the actual mapping (output-available and
output-redacted both fold to "done") and made adding new states a
multi-line edit.

Hoist the mapping to a `TOOL_PART_PHASE_BY_STATE` record at module
scope, keyed on the SDK state strings and typed as the literal phase
union. The summarizer now does a single table lookup. States not in the
table (e.g. `input-streaming`) still yield `null` and the bare
`[tool <name>]` form, matching prior behavior exactly.

Behavior-preserving: same input strings, same output bytes for every
`state` value the prior code handled, and the same `null` fallthrough
for everything else.
Three slash-command discovery surfaces (suggestions in ChatInput, ghost
hints in ChatInput, and CommandPalette) duplicated the same inline
lambda:

  (experimentId) =>
    resolveSlashCommandExperimentValue(experimentId, {
      goals: goalsExperimentEnabled,
      workspaceHeartbeats: workspaceHeartbeatsExperimentEnabled,
    })

Add createSlashCommandExperimentResolver(snapshot) next to its sibling
resolver so each callsite only describes the experiment snapshot it
observes. The new helper returns the exact same closure each callsite
previously built inline, so behavior is byte-identical.
The SSH-provisioning commit (#3302) added a second `import type { Runtime }
from "../node/runtime/Runtime"` line right below an existing
`import type { InitLogger, WorkspaceInitResult }` from the same module.
Fold the new symbol into the existing import — byte-identical semantics,
one fewer line of boilerplate, no behavior change.
Extract a shared `BUILT_IN_SKILL_NAMES` constant for the two test
assertions in `agentSkillsService.test.ts` that previously enumerated the
same five built-in skill names inline. The two existing call sites differ
only in their project-skill prefix; spreading the shared constant at the
end of each list preserves the exact sort order and assertion semantics.

Byte-equivalent to the previous inline arrays; the only effect is that
the next new built-in skill needs to land in one place instead of two.
The Tooltip + Switch + Reset Button block for the per-agent advisor
toggle was duplicated between renderAgentDefaults and renderUnknownAgentDefaults.
The two call sites differ only in the agent id variable and which
setter/resetter to invoke, so wrap the shared markup in a small
AdvisorSwitch component. Same aria-label, same tooltip text via
getAdvisorSwitchState, same conditional Reset semantics — pure cleanup
with no behavior change.
Hoist the ["text", "delta", "textDelta"] field priority used to extract AI SDK v5 text-delta payloads into a shared TEXT_OUTPUT_DELTA_FIELDS constant in src/common/utils/ai/streamChunks.ts and reuse it from streamManager.ts (fullStream text-delta handling) and tools/advisor.ts (advisor streamText onChunk handling).

Byte-equivalent semantics; only the wiring detail (that the same fallback list applies to both callsites) moves into the shared module.
BudgetTile and TurnsTile each render the same dt-label + Edit-button
header row. Lift the duplicated markup into a small file-scoped
`StatTileHeader` helper so the styling lives in one place and the
tile bodies focus on their own numeric content. Behavior, aria
labels, and class names are unchanged — `GoalTab.test.tsx` (23
tests, including the inline budget/turn-cap editors that locate
the openers via `getByLabelText("Edit goal …")`) still passes.
mux-bot Bot and others added 12 commits May 22, 2026 00:25
Three callsites (ChatInput/types.ts, messageQueue.ts, agentSession.ts)
each privately redeclared the same NonNullable<SendMessageOptions["goalInterventionPolicy"]>
alias after #3319 added the field. Centralizing the type next to
SendMessageOptions itself removes the duplication and ensures future
sub-typing changes only need to land in one place. Pure relocation —
identical type semantics at every callsite.
The silent-continuation summary helper added in #3326 was declared as a
private method on `AgentSession` but only depends on its input `parts`
argument — it never touches `this`. Convert it to a module-level free
function alongside the existing free helpers (`stripGoalInterventionPolicy`,
`coerceGoalSyntheticMessageKind`, `extractAgentSkillRefs`, etc.) so the
no-`this` contract is obvious to readers and the file's helper style stays
consistent.

The companion `maybeAutoCompleteGoalFromSilentContinuation` method stays
on the class because it accesses `this.workspaceGoalService`,
`this.workspaceId`, and `log` indirectly through instance context.

Byte-for-byte identical logic at the only callsite. Pure cleanup, no
behavior change.
The seed loop in applyReviewPaneUpdate built a key→index map for the
existing base list by calling base.indexOf(h) on every iteration —
O(n²) when the loop already had the index in hand. Switch to
`base.entries()` so the position the map stores is unambiguously the
slot we just visited. Behavior-identical for unique references (the
only realistic case), and now correct-by-construction even if a future
refactor ever introduced duplicate references in `base`.
This test-only export was added speculatively in #3262 (Instructions tab)
but no test ever imports it; ripgrep across src/ and tests/ finds zero
callers. Removing the unused export lets pendingFocusGeneration become
`const` since the reset helper was the only reason it was `let`.

The Map is still mutated in place via .set(), and getter/setter exports
are unchanged, so observable runtime behavior is byte-identical.
Five toolPolicy entries differed only by tool name and all shared
`action: "disable" as const`. Hoist the names into a local
`CLI_DISABLED_TOOL_NAMES` tuple and produce the policy array via
`.map(name => ({ regex_match: name, action: "disable" as const }))`.

Picked from the `ask_user_question` disable that landed in #3336 —
that commit added a fifth identical-shape entry, so the table form is
now strictly tidier than five copy-pasted object literals. Adding the
next disabled CLI tool drops to one string instead of duplicating the
shape. Byte-equivalent toolPolicy contents (same five entries, same
order, same action), so no behavior change.

Generated with `mux`
…lCall

The two pill renderers in the ask_user_question executing UI (one per
question plus the Summary pill) inlined the same nine-class Tailwind
string and the same three-way selected/complete/neutral branch logic.
Extract a module-level `getSectionPillClassName(isSelected, isComplete)`
helper so both callsites share one declaration; the next visual tweak to
those pills now lives in one place instead of two. Identical class
strings at both callsites, so the rendered output is byte-equivalent and
the AskUserQuestionToolCall.test.tsx suite (4/4 pass) continues to find
the question pills by their unchanged role and labels.
The SSH_AUTH_SOCK / SSH_AGENT_PID save+restore pattern was inlined four
times (twice in withoutSshAgent's finally block, twice in afterAll) using
the same 'if (saved === undefined) delete; else assign' shape. The new
module-local restoreEnvVar(key, savedValue) helper mirrors that exact
semantics in one place. Each callsite collapses from four lines to one
and the per-key delete-vs-assign decision lives in a single function.

Picked from #3340 - that PR brought signingService.test.ts back under
review when it bumped the Ed25519 capabilities test timeout to 15s.
Tests still pass (14/14).
The single-result `buildReviewDiffPathFilter` wrapper was exported from
ReviewPanel.tsx solely so two assertions in ReviewPanel.assistedStats.test.ts
could grab the first spec's pathFilter. Production callers (ReviewPanel's
diff-load effect and ReviewAssistedStatsReporter) already use the multi-spec
`buildReviewDiffPathFilterSpecs` form directly so they can handle assisted
multi-project pins.

Move the wrapper into the test file as a private helper. Pure relocation —
identical implementation, same two describe-block assertions, same
buildReviewDiffPathFilterSpecs delegation — so the ReviewPanel module's
exported surface drops one helper that no production code ever called.

Picked from the `fix: surface assisted review hunks reliably` change in
#3344, which introduced the test-only wrapper alongside the production
multi-spec form.
The two new `parseGoalBudgetFlag` and `parseGoalTurnsFlag` helpers in
src/cli/run.ts (added in #3348) built their error strings with `'...' +
value + '...'` concatenation, which is the only `throw new Error('...')`
pair in the file — every other error (including the adjacent `parseMode`
helper) uses backtick template literals. Convert these two messages to
template literals for consistency. Pure stylistic alignment; the thrown
Error has the same message text.
Hoist the duplicated Tailwind class string used by the Pause / Mark
complete / Reopen buttons in GoalTab.tsx into a single module-level
GOAL_LIFECYCLE_NEUTRAL_BUTTON_CLASS constant. Each call site previously
inlined the same 'border-border-light bg-surface-secondary text-foreground
hover:bg-surface-tertiary inline-flex items-center gap-1.5 rounded-md
border px-3 py-1.5 text-sm' string; the accent-colored Archive and
success-tinted Resume buttons keep their own class strings because they
are the only primary / positive variants in the row.

Pure DRY relocation: same class string at every callsite, so the existing
GoalTab.test.tsx 'active goals expose a de-prominent Clear; completed
goals promote Archive as primary' assertion (which checks that Reopen's
className does NOT contain 'bg-accent' and that Archive's DOES) still
holds, and every Pause / Mark complete / Reopen aria-label lookup in the
suite continues to resolve. No behavior change.
…RYABLE_ERRORS

#3356 introduced two adjacent constants in SSHRuntime.ts that listed the
same four receive-pack thin-pack failure patterns inline:
PROJECT_SYNC_RETRYABLE_ERRORS (used by the broad retry classifier) and
UNRESOLVED_DELTA_PUSH_PATTERNS (used by isUnresolvedDeltaPushFailure to
decide whether the next retry attempt should add --no-thin).

Define the four-string sub-class once on UNRESOLVED_DELTA_PUSH_PATTERNS
and spread it into PROJECT_SYNC_RETRYABLE_ERRORS so the lists can never
drift. .some(pattern => errorMsg.includes(pattern)) sees the same
patterns in the same order, so the retry classification is
byte-equivalent — pure DRY, no behavior change.
The intent-only summary mode added in #3360 introduced a second normalizeForComparison(value) !== normalizeForComparison(command) call, so the same whitespace- and case-insensitive command-equality check now appears in three spots: filtering a redundant intent, filtering a redundant display-name fallback, and the trailing-using-clause stripper. Pull that predicate into a single matchesCommand helper next to normalizeForComparison so all three callsites read as 'intent (or display name, or candidate) is the same as the command' and any future tweak to the comparison normalization happens in one place. Pure rename/extract: the helper composes the existing normalizer, returns the identical boolean, and no callsite changes its branch direction.
@mux-bot mux-bot Bot force-pushed the auto-cleanup branch from 0a996c2 to a936fc2 Compare May 22, 2026 00:31
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.

1 participant