-
Notifications
You must be signed in to change notification settings - Fork 0
fix(web): remove dead controls that teach the app is broken #95
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import { readFile } from "node:fs/promises"; | ||
| import { describe, expect, it } from "vitest"; | ||
|
|
||
| const viewUrl = new URL("./agents-view.tsx", import.meta.url); | ||
|
|
||
| describe("Agent directory", () => { | ||
| it("describes agents, not humans", async () => { | ||
| const source = await readFile(viewUrl, "utf8"); | ||
| expect(source).toContain( | ||
| 'description="Permission-scoped agents with governed learning"', | ||
| ); | ||
| expect(source).not.toContain("human collaborators"); | ||
| }); | ||
|
|
||
| it("offers no affordance for agent creation, which has no API", async () => { | ||
| const source = await readFile(viewUrl, "utf8"); | ||
| expect(source).not.toContain("New agent"); | ||
| }); | ||
| }); | ||
|
|
||
| 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"); | ||
| }); | ||
|
|
||
| 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(); | ||
| } | ||
|
Comment on lines
+29
to
+33
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 🤖 Prompt for AI Agents |
||
| }); | ||
| }); | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -245,6 +245,7 @@ export function CompanyOsShell({ children }: { children: ReactNode }) { | |
| const [mobileOpen, setMobileOpen] = useState(false); | ||
| const [paletteOpen, setPaletteOpen] = useState(false); | ||
| const [theme, setTheme] = useState<"dark" | "light">("dark"); | ||
| const [chosenOrganisationId, setChosenOrganisationId] = useState(""); | ||
|
|
||
| useEffect(() => { | ||
| const current = | ||
|
|
@@ -266,6 +267,10 @@ export function CompanyOsShell({ children }: { children: ReactNode }) { | |
| const pendingApprovals = command.data?.pendingApprovalCount ?? 0; | ||
| const overallHealth = toHealthState(command.data?.overallHealth ?? "unknown"); | ||
| const org = session.data?.organisation; | ||
| const organisations = session.data?.organisations ?? []; | ||
| // The switcher only earns its interactivity once a second membership exists; | ||
| // with one organisation the top bar states it instead of offering a choice. | ||
| const selectedOrganisationId = chosenOrganisationId || org?.id || ""; | ||
| const actor = session.data?.actor; | ||
| const environment = session.data?.environment ?? "unknown"; | ||
|
|
||
|
|
@@ -324,20 +329,33 @@ export function CompanyOsShell({ children }: { children: ReactNode }) { | |
|
|
||
| <div className="min-w-0 flex-1"> | ||
| <div className="flex flex-wrap items-center gap-2"> | ||
| <label className="sr-only" htmlFor="org-switcher"> | ||
| Organisation | ||
| </label> | ||
| <select | ||
| id="org-switcher" | ||
| className="max-w-[12rem] truncate rounded-md border border-border bg-background px-2 py-1 text-xs font-medium" | ||
| value={org?.id ?? ""} | ||
| disabled | ||
| title="Multi-organisation membership is not available yet" | ||
| > | ||
| <option value={org?.id ?? ""}> | ||
| {org?.name ?? (session.isLoading ? "Loading…" : "Organisation")} | ||
| </option> | ||
| </select> | ||
| {organisations.length > 1 ? ( | ||
| <> | ||
| <label className="sr-only" htmlFor="org-switcher"> | ||
| Organisation | ||
| </label> | ||
| <select | ||
| id="org-switcher" | ||
| className="max-w-[12rem] truncate rounded-md border border-border bg-background px-2 py-1 text-xs font-medium" | ||
| value={selectedOrganisationId} | ||
| onChange={(event) => | ||
| setChosenOrganisationId(event.target.value) | ||
| } | ||
|
Comment on lines
+341
to
+343
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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 AgentsSource: Coding guidelines |
||
| > | ||
| {organisations.map((membership) => ( | ||
| <option key={membership.id} value={membership.id}> | ||
| {membership.name} | ||
| </option> | ||
| ))} | ||
| </select> | ||
| </> | ||
| ) : ( | ||
| <p className="max-w-[12rem] truncate text-xs font-medium"> | ||
| <span className="sr-only">Organisation: </span> | ||
| {org?.name ?? | ||
| (session.isLoading ? "Loading…" : "Organisation")} | ||
| </p> | ||
| )} | ||
| {session.data?.customer ? ( | ||
| <Badge className="bg-muted text-muted-foreground"> | ||
| Customer: {session.data.customer.name} | ||
|
|
||
There was a problem hiding this comment.
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
titlecontract.This test checks the route and label but not the new title behavior. A regression could remove either the ready prompt or
agent.readiness.reasonwhile the test still passes; assert both branches or render the component and verify the resulting title.🤖 Prompt for AI Agents