Repository navigation
List and count teammates' shared machines with the person's own - #790
Merged
Merged
Conversation
…er it for their work The favorite, the one machine Automatic and Default machine prefer for a person, could only be one of the person's own. It can now be a machine a teammate shares, so a person with no machine of their own, or who works best on a shared one, can make it their default. POST /api/connector/machines/:id/favorite accepts a machine another person shares when it is listed to the caller: shared, not revoked, its owner and the caller able to push to a repository. That is the Machines page's own listing check (`listedTo()`, over the same `reach` cache and held GitHub lists), so it asks GitHub nothing new. A machine that is not shared, whose owner can't push, or that the person can't use is a 404, as is clearing a favorite the person does not have; /label, /shared and /revoke stay the owner's. A person still has one favorite, across their own machines and teammates'. A teammate's row in GET /api/connector/machines now carries `favorite`, the viewer's own flag, never its owner's. Storage keeps this consistent in both adapters: `MachineStore.favor()` accepts a shared machine of another person; the owner no longer sharing a machine deletes the others' favorites of it (in the same transaction on PostgreSQL, and `favor()` takes a row lock on the machine so a favorite cannot race an unshare), leaving the owner's own; and the memory adapter's revoke now forgets everyone's favorite of the machine, where it forgot only the owner's, as PostgreSQL always did. The in-memory favorites follow with `Connections.unfavor()`. No schema change. For a document with no machine chosen, a teammate's shared machine the person favors now comes first for their Build, Retry, Run, investigations and manual rebuild, while it is connected, serves the repository and its owner can push to it (`requested()`, `allows()` and `mayTake()`, the checks a chosen shared machine already has); a machine chosen for the document still comes before it. The document's machine state names it as what Automatic uses now. Default machine runs the creator's Planner on it ahead of their own machines (`favoritePlannerMachine()`), `reachShared()` checks its owner's push access even when the creator has a machine of their own, and the Planner moves there, and back, when the creator's favorite changes. Offline, unshared, or its owner unable to push, work goes where it would without it. Rebuilds and prototypes Chopin starts by itself (LIVE_BUILD, LIVE_SPIKES) still run only on their builder's own machines. The docs and AGENTS.md say that a teammate's machine may be a person's favorite, that sharing is the owner's consent for a person who chose it or made it their default, and that unsharing clears teammates' favorites. Assistant-model: Claude Sonnet 5.5 Assistant-workflow: goal (run ea3bb0ce-3067-42c3-949c-86a4fa4b7d59) Assistant-verification: bun test apps/server passed: 4374 pass, 1 skip, 0 fail on the tree before the web changes, with a PostgreSQL 17 database at TEST_DATABASE_URL, run with GIT_CONFIG_GLOBAL=/dev/null because the global commit signing breaks one test's scratch repository Assistant-verification: bun test apps/server/src/storage/memory apps/server/src/storage/postgres passed: the machine contract, 232 pass and 0 fail on memory and PostgreSQL together after the storage change; two of the three new or rewritten favorite cases fail on the memory adapter before it Assistant-verification: bun test planner-dispatch.test.ts and tasks/routes.test.ts passed: the new favorite, Default machine and Automatic build cases fail before the route and connection change and pass after it (the build cases failed, two of four; the fallback cases pass either way) Assistant-verification: four one-line mutation checks passed: the local-agent check dropping the favorite, reachShared() skipping it, the unshare clearing of teammates' favorites removed from the server, and mayTake() ignoring it were each caught by a test Assistant-verification: bun run fix, bun run ci and bun run types passed on this commit's tree alone (the web changes stashed): 71 lint warnings as before, tokens, design contract, design record and design check, the whole workspace and e2e User-preference: Shared machines are listed and counted plainly with the person's own, not grouped by owner Co-authored-by: Alex Lavaee <lavaman131@github.com>
…he sidebar, the machine button and the Machines page
A machine a teammate shares is one the person can use, but the sidebar counted only their own machines, the machine button's menu grouped the others under "Shared by <owner>", the sidebar's Machines menu left them out, and the Machines page kept them in a separate "Shared with you" table. They are now counted and listed plainly with the person's own, in the groups every machine is in.
The sidebar's Machines count includes them: one own machine and one shared machine, both connected, read 2/2. `MachineSummary` is now `{ total, connected }` over the person's own machines and the teammates' shared ones (`summarizeLive()`), and the accessible name is `Machines, N connected`, `Machines, X of Y connected` or `Machines, none of Y connected`, so it still contains what the entry shows. The Machines page's "N machine(s)" counts every row of its table the same way.
The sidebar's Machines menu lists a teammate's machines under Local and Cloud with the person's own, as radio items that set their default; choosing one favorites it through the route the previous commit allows, and the star marks it at once in either list (`machineFeed.favor()`). The entry opens that menu, not a link to /machines, when the person has no machine of their own but can use a shared one. "Any connected" still says which of their own machines Automatic uses.
The machine button's menu lists every machine in its Local and Cloud groups, the person's own before the teammates' within each, offline ones disabled, with no "Shared by" group. A teammate's login follows a machine's name, in quiet ink, only where another machine in the list has the same name (`ownerHint()`), in both menus.
The Machines page loses its "Shared with you" table. A teammate's machine is a row of the one table, in its columns: name, owner, host and agent (a dash: the API gives a teammate neither), version, Shared, last seen. Its Shared switch is on and disabled, it has no actions menu, no Update badge, and nothing to rename, disconnect or set up; only its owner changes it. Its star, the person's own default, works. On a phone its row is in the one list, and its view offers the star alone. Search finds it by name, owner and release. The table and its section keep their name, "Your machines", which assistive technology and the existing specs use; the repositories a machine serves, still in the API, are no longer shown. `SharedWithYou`, its table, rows and heading style are removed.
The sharing switch's tooltip says teammates see the machine in their list and can make it their default, docs/chopin-cli.md describes the count, the menus and the one table, and apps/web/DESIGN.md says the sidebar's Machines menu lists the machines the person can use. The reviewed whole-file hashes of machine-button.tsx and experiments/machines.tsx in the design-contract exceptions are renewed: their edits leave the `presence.className` flow they record alone.
Assistant-model: Claude Sonnet 5.5
Assistant-workflow: goal (run ea3bb0ce-3067-42c3-949c-86a4fa4b7d59)
Assistant-verification: bun test passed: 7261 pass, 17 skip, 0 fail across the repository on the final source, with a PostgreSQL 17 database at TEST_DATABASE_URL, run with GIT_CONFIG_GLOBAL=/dev/null because the global commit signing breaks one test's scratch repository
Assistant-verification: bun test apps/server/src/storage/postgres passed: 128 pass, 0 fail against a disposable PostgreSQL 17 on port 5433, run in place of bun run test:postgres, whose fixed port 5432 is another project's database on this machine
Assistant-verification: bun run fix, bun run ci and bun run types passed on this commit's tree: 71 lint warnings as before, tokens, design contract with the two renewed hashes, design record and design check, the whole workspace and e2e
Assistant-verification: impeccable detect passed: no findings on the changed web components and stylesheets
Assistant-verification: GIT_CONFIG_GLOBAL=/dev/null bun run e2e planner-picker machines machine-choice connector passed on this commit's tree with a freshly built client: 62 passed, 0 failed, on four disposable PostgreSQL 17 databases; an earlier run of planner-picker alone failed the new same-name case, because the owner's login ran into the name for assistive technology, and passes since a space was added
Assistant-verification: screenshots viewed: /tmp/chopin-shots-shared-plain/ machines-count-shared.png (2/2), machines-menu-shared.png, machines-menu-same-name.png, machine-button-menu-shared.png, shared-machine-menu.png, machines-table-shared-and-own.png, machines-table-shared.png, machines-shared-no-checkout.png, machines-shared-phone.png and shared-machine-phone-sheet.png, from Playwright runs of the same web code
User-preference: Shared machines are listed and counted plainly with the person's own, not grouped by owner
Co-authored-by: Alex Lavaee <lavaman131@github.com>
Assistant-duration: 39m converged, estimated 90m
…ed favorite from coming back, and rebuild on a shared machine made the favorite after the first build Three gaps in the previous two commits. Machines are now listed in one order, newest paired first, then by id: the order the server already lists a person's own machines in (`created_at DESC, id`). The sidebar's Machines menu, the Machines table and the machine button's menu put all of the person's own machines before all of a teammate's, so a teammate's machine paired after one of theirs sat below it. A teammate's machine row in `GET /api/connector/machines`, and every machine of a document's menu (`GET /api/documents/:id/machine`), now carry `createdAt`, the stored machine's creation time (a field, not a GitHub call), and `newestFirst()` sorts both kinds together with it. `allMachines()` and `machineRows()` use it, so a teammate's machine is above or below the person's own by when it was paired, in Local and in Cloud, and the count is unchanged. The tests that locked in own-first are replaced by interleaved cases in both directions. The favorite route stored a favorite and then published it to the in-memory choices, and the unshare route stored its clearing and then published that. An unshare landing between the favorite's two steps left storage with no favorite and memory with one, which came back when the machine was shared again and which Automatic, Default machine and `mayTake()` preferred with nothing stored. A favorite change, stopping sharing a machine and revoking it (the owner's route and the machine's own unpair) now run one at a time per machine, each storing and then publishing with nothing between (`changingFavorites()`). The unshare's in-memory clearing moved up beside its storage write; nothing between them read favorites. A person's pressed rebuild tried the connection of the build before it first, so a shared machine made their favorite after that build was ignored. It now tries their favorite shared machine first (`favoriteShared()`, through the same `takers()` and `mayTake()` checks: connected, serving the repository, its owner able to push, not busy), then the original connection and their others as before. A machine chosen for the document still wins, since no favorite applies while one is chosen, and rebuilds Chopin starts by itself (LIVE_BUILD) still stay on their builder's own machines. The docs, AGENTS.md and the design guide say machines are listed together newest paired first, and that a pressed rebuild follows the person's current shared favorite. Assistant-model: Claude Sonnet 5.5 Assistant-workflow: goal (run ea3bb0ce-3067-42c3-949c-86a4fa4b7d59) Assistant-verification: bun test passed: 7269 pass, 17 skip, 0 fail across the repository on the final source (7261 on the previous commit plus 8 new cases), with a disposable PostgreSQL 17 at TEST_DATABASE_URL on port 5433, run with GIT_CONFIG_GLOBAL=/dev/null because the global commit signing breaks one test's scratch repository Assistant-verification: bun test apps/server/src/storage/postgres passed: 128 pass, 0 fail against the same PostgreSQL 17 on port 5433, run in place of bun run test:postgres, whose fixed port 5432 is another project's database on this machine Assistant-verification: the new and changed cases fail on the previous commit's server and web code and pass after: with the five production files (experiments/routes.ts, tasks/builds.ts, tasks/routes.ts, machine-summary.ts, machine-choice.ts) restored to 9216a30 and these tests kept, tasks/routes.test.ts, planner-dispatch.test.ts, machine-summary.test.ts, machine-choice.test.ts and machine-list.test.ts gave 11 fail and 225 pass: the three favorite-versus-owner interleavings (unshare then reshare, revoke, unpair), the rebuild on a favorite made after the first build, the teammate's and the menu's `createdAt`, and the four ordering cases (the sidebar and table list, the menu rows, a tie, the table) Assistant-verification: five one-line mutation checks were each caught by exactly the case for the code it breaks: the machine's own unpair, the owner's revoke and the unshare each taken back outside the per-machine order failed only their own interleaving case, the favorite route taken outside it failed all three, and queueRebuild ignoring the favorite failed the rebuild case alone Assistant-verification: bun run fix, bun run types and bun run ci passed on the final tree: fix changed nothing, 14 of 14 workspaces and e2e typed, 71 lint warnings as before, tokens, design contract, design record and design check Assistant-verification: GIT_CONFIG_GLOBAL=/dev/null CHOPIN_SHOTS=/tmp/chopin-shots-shared-plain bun run e2e planner-picker machines machine-choice connector passed on the final tree with a freshly built client: 63 passed, 0 failed, on four disposable PostgreSQL 17 databases, including the new interleaved-order case; an earlier run of the same specs gave 62 passed and 1 failed, machine-choice.e2e.ts:682 (the sidebar machine menu closes on browser history navigation: the menu does not open on the second click), which also fails on the unchanged previous commit in 4 of 82 repeats against 7 of 58 on this tree, so it is an intermittent failure of the test, its cause not found Assistant-verification: screenshots viewed after the retake: /tmp/chopin-shots-shared-plain/ machines-menu-order.png, machines-table-order.png and machine-button-menu-order.png (six machines, three of them teammates', listed Desk, Studio, Laptop under Local and Edge, Rack, Build box under Cloud, 6/6, interleaved by when each was paired), machines-count-shared.png (2/2), machines-menu-shared.png, machine-button-menu-shared.png, machines-table-shared-and-own.png and machines-menu-same-name.png, from Playwright runs of the same web code Assistant-verification: not run: the phone screenshots and the Docker image build (no dependency, workspace or Docker change), bun run design:behavior, the full bun run e2e suite (only the four specs that touch machines), and GitHub's checks on a pushed head (no branch was pushed and no PR was opened) User-preference: Shared machines are listed and counted plainly with the person's own, not grouped by owner Co-authored-by: Alex Lavaee <lavaman131@github.com> Assistant-duration: 53m converged, estimated 120m
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Count and list teammates' shared machines with the person's own, and let one be their default
Summary
A machine a teammate shares is now treated like one of the person's own wherever machines are counted or listed. The sidebar's Machines count includes it (one own machine and one shared machine, both connected, read 2/2). The Machines menu in the sidebar, the machine button's menu beside Build plan, and the Machines page list it plainly under Local or Cloud, sorted with the person's own (newest paired first, whoever owns the machine), with no "Shared by " group and no separate "Shared with you" table. A person can make an eligible shared machine their default (their favorite), and Default machine and Automatic prefer it for their documents where it serves the repository, falling back as before where it doesn't. Owner-only actions (rename, the Shared switch, disconnect, setup and update) stay with the owner.
What changed
Count.
summarizeMachinesnow countstotal(notpaired) over the person's own machines and the teammates' shared ones. The entry reads2/2, and its accessible name isMachines, N connected,Machines, X of Y connectedorMachines, none of Y connected. The Machines page's "N machine(s)" counts every row of its one table.Order. Every list of machines is in one order, newest paired first, then by id: the order the server already lists the person's own machines in (
created_at DESC, id). A teammate's machine row, and a machine in a document's menu, now carrycreatedAt(a field of the stored machine, not a GitHub call), andnewestFirst()sorts the person's own and teammates' machines together with it.allMachines()(the sidebar menu, the Machines table and the count) andmachineRows()(the machine button's menu) use it, so a teammate's machine paired after one of the person's own is above it in Local or Cloud, and one paired before is below it, on all three surfaces. Nothing groups by owner.Machine button menu.
machineRows()returns one list: Local, then Cloud, each in that order, offline ones disabled. The per-owner groups are gone. A teammate's login appears after the name, in quiet ink, only where another machine in the list has the same name.Sidebar Machines menu. It lists teammates' machines beside the person's own, as radio items that set their default. The entry opens the menu, not a link to /machines, when the person has no machine of their own but can use a shared one.
Machines page. The "Shared with you" table is removed. A teammate's machine is a row of the one table, in the same columns: name, owner (its owner's login), host and agent (a dash, as the API gives none), version, Shared, last seen, actions. Its Shared switch is on and disabled, it has no actions menu, no Update badge, and no rename, disconnect or setup; its star, the person's own default, works. On a phone the same rows are in the one list and its view offers the star alone.
Favorite.
POST /api/connector/machines/:id/favoritenow accepts a machine a teammate shares when it is listed to the person: shared, not revoked, its owner and the person able to push to a repository (the Machines page's ownlistedTo(), over the samereachcache and held GitHub lists; no new GitHub call). Anything else, and anyone clearing a favorite they don't have, is a 404. A person has one favorite across their own and teammates' machines.GET /api/connector/machinesgives a teammate's rowfavorite(the viewer's own flag, never its owner's)./label,/sharedand/revokestill answer a non-owner 404.Clearing. The owner stopping sharing a machine clears teammates' favorites of it (not their own); revoking it clears everyone's. Storage does both:
MachineStore.favor()accepts a shared machine of another person,share(false)deletes the others' favorites in the same transaction on PostgreSQL, and the memory adapter's revoke now clears every person's favorite (it cleared only the owner's). No schema change.Favorite and unshare. The favorite route stored a favorite, then published it to the in-memory choices; unsharing stored its clearing, then published that. An unshare that landed between a favorite's two steps cleared storage, then the favorite's publication put it back in memory, so it reappeared on the next share and Automatic, Default machine and
mayTake()preferred it with nothing stored. A favorite change, stopping sharing a machine, and revoking it (the owner's and the machine's own unpair) now run one at a time per machine (changingFavorites()), each storing and then publishing with nothing between, so memory never keeps a favorite storage has cleared. No new GitHub call.Rebuild. A pressed rebuild tried the connection of the build before it first, so a shared machine made the person's favorite after that build was ignored. It now tries the person's favorite shared machine first (
favoriteShared(), through the sametakers()/mayTake()checks: connected, serving the repository, its owner able to push, not busy), then the original connection and the person's others as before; a machine chosen for the document still wins (no favorite applies while one is chosen), and rebuilds Chopin starts by itself (LIVE_BUILD) still stay on their builder's own machines.Preference. For a document with no machine chosen, a teammate's shared machine the person favors takes their Build, Retry, Run, investigations and manual rebuild first while it is connected, serves the repository and its owner can push to it (
requested(),allows(),mayTake(); the same checks as a chosen shared machine), and the document's machine state names it as what Automatic uses. A machine chosen for the document comes first. Default machine runs the creator's Planner on it before their own machines (favoritePlannerMachine(), andreachShared()now checks it even when the creator has a machine of their own); it moves there, and back, when the creator's favorite changes. Offline, unshared, or its owner no longer able to push: they go where they would without it. Rebuilds and prototypes Chopin starts by itself (LIVE_BUILD, LIVE_SPIKES) still run only on their builder's own machines.Docs. docs/chopin-cli.md, docs/implementation-lifecycle.md, docs/local-launcher.md, docs/storage.md, docs/hosted-agent.md, docs/agent-connection.md, AGENTS.md and apps/web/DESIGN.md say so.
Tests
machine-contract.ts, memory and PostgreSQL): a favorite may be a teammate's shared machine, refused while it is not shared or someone else's; one favorite per person across both; unsharing clears teammates' favorites and not the owner's; revoking clears everyone's; owner-only actions stay with the owner.planner-dispatch.test.ts: favoriting allowed when eligible, refused when not shared, whose owner can't push, or that the person can't use, and for an unknown id; one per person; the viewer's flag on the listing and none for the owner; cleared on unshare and on revoke; rename, share and revoke still refused; Automatic's machine in the document's state; Default machine runs the Planner on the favorite ahead of the creator's own machine, falls back offline, when unshared and when its owner can no longer push, and moves it when the favorite changes.tasks/routes.test.ts: Build on Automatic goes to the favorite shared machine and runs there for the person; the person's choice for the document beats it; it falls back to their own machine offline, unshared, and where its owner can't push; it counts as the local agent; a pressed rebuild goes there and an automatic one never does.reachShared()skipping the favorite, no clearing in memory on unshare,mayTake()ignoring the favorite) are each caught.machine-summary.test.ts), the menu rows and same-name owner (machine-choice.test.ts), the one table with teammates' rows, the disabled checked switch, no actions, the star and the count (machine-list.test.ts). The ordering cases replace the ones that locked in own-first: a newer shared machine above an older own one and an older one below a newer own one, in Local and Cloud, whatever order the lists arrive in, and one order for machines paired at the same moment (allMachines(),machineRows()and the table).planner-dispatch.test.ts: a teammate's row, and a machine of the document's menu, carry the machine'screatedAt, the stored one; the teammate's row has no other owner-only field.tasks/routes.test.ts: forced interleavings of the favorite request, held after it stored the favorite and before it publishes it, with the owner stopping sharing the machine (then sharing it again), revoking it, and the machine unpairing itself: afterwards the person has no favorite in storage or memory, nor on the reshare. A rebuild goes to the shared machine the person made their favorite after the first build ran on their own; it stays where the first build ran while that favorite is offline, and a machine chosen for the document still takes it.e2e/planner-picker.e2e.ts,HARNESS=remote): the sidebar menu, the Machines table and the document's menu list six machines, three of them teammates', newest paired first, interleaved in Local and Cloud; and the one Machines table with the count and a disabled switch on a teammate's row, on a phone too; owner-only routes refused; the Build button menu and the phone sheet with Cloud rather than "Shared by"; the sidebar's 2/2, its menu listing and choosing a shared machine as the default, the Machines page, Automatic's "Runs on", offline, and the default let go on unsharing; and a person with no machine of their own opening the menu, with the owner named only beside a same-named machine.e2e/machine-choice.e2e.ts: the count label.Screenshots
All under
/tmp/chopin-shots-shared-plain/(taken from the Playwright run, viewed and reviewed):machines-count-shared.png: the sidebar entry reading 2/2machines-menu-shared.png: the Machines menu with Local (Laptop) and Cloud (Build box), no owner groupmachines-menu-same-name.png: two machines named Desk, the teammate's with its owner's login in quiet inkmachine-button-menu-shared.png: the Build button's menu, Local and Cloud, the shared machine in useshared-machine-menu.png: the same for a person whose only machine is a teammate'smachines-table-shared-and-own.png: the Machines page, "2 machines", Local and Cloud, the shared row's switch on and disabled, its star setmachines-menu-order.png,machines-table-order.pngandmachine-button-menu-order.png: six machines, three of them teammates', 6/6, in the sidebar menu, the Machines table and the document's menu; Local is Desk, Studio (a teammate's), Laptop and Cloud is Edge (a teammate's), Rack, Build box (a teammate's), so a teammate's machine is above or below the person's own by when it was pairedmachines-table-shared.pngandmachines-shared-no-checkout.png: the Machines page for a person with only a shared machinemachines-shared-phone.png: a shared machine's view on a phone, the star aloneshared-machine-phone-sheet.png: the phone's machine sheetRisks
Verification
Each command ran on the source it names; the branch is three signed commits on
origin/main9fb72d4 (#789): the favorite as a teammate's machine, the count and the lists, and the repair of three review findings (the order machines are listed in, a favorite surviving an unshare, a rebuild ignoring a new shared favorite). The trailers below are the repair commit's, plus the earlier commits' checks that still hold.Assistant-model: Claude Sonnet 5.5
Assistant-workflow: goal (run ea3bb0ce-3067-42c3-949c-86a4fa4b7d59)
Assistant-duration: 53m converged, estimated 120m (the repair commit; the count and lists commit was 39m converged, estimated 90m)
Assistant-verification: bun test passed: 7269 pass, 17 skip, 0 fail across the repository on the final source (7261 on the previous commit plus 8 new cases), with a disposable PostgreSQL 17 at TEST_DATABASE_URL on port 5433, run with GIT_CONFIG_GLOBAL=/dev/null because the global commit signing breaks one test's scratch repository
Assistant-verification: bun test apps/server/src/storage/postgres passed: 128 pass, 0 fail against the same PostgreSQL 17 on port 5433, run in place of bun run test:postgres, whose fixed port 5432 is another project's database on the machine this was written on; the three favorite contract cases pass on memory and PostgreSQL
Assistant-verification: the new and changed cases fail on the previous commit's server and web code and pass after: with the five production files (experiments/routes.ts, tasks/builds.ts, tasks/routes.ts, machine-summary.ts, machine-choice.ts) restored to 9216a30 and these tests kept, tasks/routes.test.ts, planner-dispatch.test.ts, machine-summary.test.ts, machine-choice.test.ts and machine-list.test.ts gave 11 fail and 225 pass: the three favorite-versus-owner interleavings (unshare then reshare, revoke, unpair), the rebuild on a favorite made after the first build, the teammate's and the menu's
createdAt, and the four ordering cases (the sidebar and table list, the menu rows, a tie, the table)Assistant-verification: five one-line mutation checks were each caught by exactly the case for the code it breaks: the machine's own unpair, the owner's revoke and the unshare each taken back outside the per-machine order failed only their own interleaving case, the favorite route taken outside it failed all three, and queueRebuild ignoring the favorite failed the rebuild case alone; the earlier four (the local-agent check dropping the favorite, reachShared() skipping it, the unshare clearing of teammates' favorites removed, and mayTake() ignoring it) are still each caught
Assistant-verification: bun run fix, bun run types and bun run ci passed on the final tree: fix changed nothing, 14 of 14 workspaces and e2e typed, 71 lint warnings as before, tokens, design contract, design record and design check
Assistant-verification: GIT_CONFIG_GLOBAL=/dev/null CHOPIN_SHOTS=/tmp/chopin-shots-shared-plain bun run e2e planner-picker machines machine-choice connector passed on the final tree with a freshly built client: 63 passed, 0 failed, on four disposable PostgreSQL 17 databases, including the new interleaved-order case; an earlier run of the same specs gave 62 passed and 1 failed, machine-choice.e2e.ts:682 (the sidebar machine menu closes on browser history navigation: the menu does not open on the second click), which also fails on the unchanged previous commit in 4 of 82 repeats against 7 of 58 on this tree, so it is an intermittent failure of the test, its cause not found
Assistant-verification: screenshots viewed after the retake: the three
*-order.pngshots (six machines, three of them teammates', listed Desk, Studio, Laptop under Local and Edge, Rack, Build box under Cloud, 6/6, interleaved by when each was paired),machines-count-shared.png(2/2),machines-menu-shared.png,machine-button-menu-shared.png,machines-table-shared-and-own.pngandmachines-menu-same-name.png, from Playwright runs of the same web codeAssistant-verification: not run: the phone screenshots' review after the retake, the Docker image build (no dependency, workspace or Docker change), bun run design:behavior and the full bun run e2e suite (only the four specs that touch machines), and GitHub's checks on a pushed head (no branch was pushed and no PR was opened)
User-preference: Shared machines are listed and counted plainly with the person's own, not grouped by owner
Co-authored-by: Alex Lavaee lavaman131@github.com