Skip to content

fix(web): remove dead controls that teach the app is broken - #95

Merged
jusso-dev merged 1 commit into
mainfrom
worktree-agent-a05b04687d756bb14
Jul 30, 2026
Merged

fix(web): remove dead controls that teach the app is broken#95
jusso-dev merged 1 commit into
mainfrom
worktree-agent-a05b04687d756bb14

Conversation

@jusso-dev

@jusso-dev jusso-dev commented Jul 30, 2026

Copy link
Copy Markdown
Owner

Phase 3 of 6.

Permanently-disabled buttons train people to believe the product is broken. Three were reachable from the sidebar.

Changes

  • "New agent" (/agents) — deleted. There is no agent-creation API, so a disabled affordance was pure noise.
  • "Invoke" (/agents/[id]) — now a working link to /operations, labelled "Assign work". Dispatch became real in 9531f9a; this button was a dead end pointing at a live feature. Readiness detail survives as the link title. Navigation is deliberately never blocked: the composer and task drawer already refuse dispatch for a non-ready agent with their own operator-readable reason, so blocking here would duplicate a refusal.
  • Org switcher (top bar) — renders as a plain label when there is a single membership, instead of a disabled dropdown captioned "not available yet". The real <select> only appears with more than one.
  • Copy fix — the agent directory described itself as "Permission-scoped human collaborators". It lists agents.

Tests

apps/web/components/agents-view.test.ts includes a guard rather than a fixed assertion: it walks every disabled occurrence in the file and fails if any lacks an expression, so the next permanently-disabled control is caught at CI rather than by inspection.

company-os-shell.test.ts previously asserted the switcher stays disabled — that assertion was pinning the defect, so it was rewritten.

Reviewer note

The multi-org <select> branch is forward-compat only: its onChange sets local state and does not switch organisation. It cannot render today (SessionContext.organisations returns the current org alone). Worth wiring or removing when multi-org membership lands, so it never becomes the next control that looks live but isn't.

Follow-up found, not fixed

AgentDetailView renders ten tabs but only branches on learning — the other eight all fall through to AgentOverview, so eight distinct-looking links show identical content. Same class of defect, silent rather than visible. Fixing it means building those panels or trimming the strip; larger than a dead-control sweep.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added support for switching between multiple organisations from the top navigation.
    • Added an “Assign work” action linking agent details to the operations board.
    • Updated agent readiness messaging to explain when assignment is unavailable.
  • Bug Fixes

    • Clarified that the agent directory contains permission-scoped agents rather than human collaborators.
    • Removed the unavailable “Invoke” and agent-creation controls.

A disabled control is a promise the product cannot keep. Every one of these
taught an operator that Muster is half-built before they had done anything.

- Drop the "New agent" button. There is no agent-creation API, and an empty
  affordance is worse than no affordance.
- Turn the agent detail "Invoke" button into a link to the operations board,
  where work can genuinely be created, assigned, and dispatched to an agent.
  The readiness reason survives as the link title, so the signal stays without
  the dead end.
- Render the organisation as plain text when the actor has one membership,
  keeping the accessible label. The real select now appears only when a second
  organisation exists, so the switcher is interactive exactly when it works.
- The agent directory lists agents, not "human collaborators".

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 30, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Updates agent directory and detail actions, and enables organisation switching when a session has multiple organisation memberships.

Changes

Agent navigation updates

Layer / File(s) Summary
Agent directory and assignment actions
apps/web/components/agents-view.tsx, apps/web/components/agents-view.test.ts
Updates directory wording, replaces the disabled “Invoke” action with an operations-board “Assign work” link, and adds source-level tests for the new behavior and live disabled states.

Organisation switching

Layer / File(s) Summary
Multi-organisation header switcher
apps/web/components/os/company-os-shell.tsx, apps/web/components/os/company-os-shell.test.ts
Tracks the chosen organisation, derives the selected membership, renders an enabled dropdown for multiple organisations, and renders a read-only label otherwise.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Possibly related PRs

  • jusso-dev/Muster#93: Updates the same CompanyOsShell organisation-switcher behavior and related agent navigation affordances.
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately reflects the main change: removing permanently disabled UI controls from the web app.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch worktree-agent-a05b04687d756bb14

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/web/components/agents-view.test.ts`:
- Around line 21-27: Extend the “routes work assignment to the operations board”
test to cover the readiness-dependent title contract: assert the ready-state
prompt and the not-ready title using agent.readiness.reason. Prefer rendering
the component and verifying the resulting title, or add assertions for both
branches while preserving the existing route and label checks.
- Around line 29-33: Update the disabled-attribute scan in the test “keeps every
remaining disabled control tied to live state” to parse JSX attributes
precisely: support whitespace around the assignment, reject boolean literals
such as disabled={true}, and avoid matching unrelated text. Prefer a JSX-aware
parser; otherwise tighten the regex and assertions to enforce these cases.

In `@apps/web/components/os/company-os-shell.tsx`:
- Around line 341-343: Update the organisation selector’s onChange flow to
persist and verify the chosen membership server-side, then refresh or invalidate
organisation-scoped session and data before committing the new UI selection.
Replace the source-only assertion with a behavior test covering selection,
server confirmation, data refresh, and the resulting organisation context.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 09e06e24-da80-4cfd-9721-46775e2fa53e

📥 Commits

Reviewing files that changed from the base of the PR and between cdc2060 and c43c498.

📒 Files selected for processing (4)
  • apps/web/components/agents-view.test.ts
  • apps/web/components/agents-view.tsx
  • apps/web/components/os/company-os-shell.test.ts
  • apps/web/components/os/company-os-shell.tsx

Comment on lines +21 to +27
describe("Agent detail", () => {
it("routes work assignment to the operations board", async () => {
const source = await readFile(viewUrl, "utf8");
expect(source).toContain('href="/operations"');
expect(source).toContain("Assign work");
expect(source).not.toContain("Invoke");
});

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Cover the readiness-dependent title contract.

This test checks the route and label but not the new title behavior. A regression could remove either the ready prompt or agent.readiness.reason while the test still passes; assert both branches or render the component and verify the resulting title.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/components/agents-view.test.ts` around lines 21 - 27, Extend the
“routes work assignment to the operations board” test to cover the
readiness-dependent title contract: assert the ready-state prompt and the
not-ready title using agent.readiness.reason. Prefer rendering the component and
verifying the resulting title, or add assertions for both branches while
preserving the existing route and label checks.

Comment on lines +29 to +33
it("keeps every remaining disabled control tied to live state", async () => {
const source = await readFile(viewUrl, "utf8");
for (const match of source.matchAll(/disabled(?:={([^}]*)})?/g)) {
expect(match[1], "permanently disabled control").toBeTruthy();
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Parse disabled JSX attributes more precisely.

The regex accepts disabled={true} as valid, misses valid whitespace such as disabled = {state}, and can match unrelated text. Use a JSX-aware parser or at least reject boolean literals and support whitespace around the assignment.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/components/agents-view.test.ts` around lines 29 - 33, Update the
disabled-attribute scan in the test “keeps every remaining disabled control tied
to live state” to parse JSX attributes precisely: support whitespace around the
assignment, reject boolean literals such as disabled={true}, and avoid matching
unrelated text. Prefer a JSX-aware parser; otherwise tighten the regex and
assertions to enforce these cases.

Comment on lines +341 to +343
onChange={(event) =>
setChosenOrganisationId(event.target.value)
}

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Wire organisation selection to an authoritative context switch.

This only updates local UI state. The supplied session builder currently always returns one organisation, so the selector is unreachable; if multi-memberships are later returned, selecting one will change the label while the session and loaded data remain scoped to the previous organisation. Persist and verify the membership change server-side, then refresh/invalidate organisation-scoped data before showing the new selection. Replace the source-only assertion with a behavior test for that flow.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/web/components/os/company-os-shell.tsx` around lines 341 - 343, Update
the organisation selector’s onChange flow to persist and verify the chosen
membership server-side, then refresh or invalidate organisation-scoped session
and data before committing the new UI selection. Replace the source-only
assertion with a behavior test covering selection, server confirmation, data
refresh, and the resulting organisation context.

Source: Coding guidelines

@jusso-dev
jusso-dev merged commit 5d549dd into main Jul 30, 2026
8 checks passed
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