chat_presence was recorded (active, waiting_approval, thinking) but never
surfaced. Map each status to a colour and render a presence dot on the
counterpart's avatar in the direct-message list, matching the design.
The PRD calls for company, division, department, project, pod and ad-hoc
spaces, but only company, department, project and direct were accepted. Add
division, pod and ad_hoc to the command contract, the service whitelist and the
new-space dialog. The space_type column is free text, so no migration is
needed.
Any employee in the org could send a message as the board (freeze, takeover,
force-approval), because requireSender only checked that the board sender was a
valid employee. Enforce the approval_decider role (org_admin inherits it) via
IdentityAccessService, which also records an access decision for denied
attempts, and only render the thread board-control form for principals who hold
that authority — others get a read-only view of past interventions.
The Home budget card invented a cap of 4x the allocated total and listed agent
counts under a money heading; the Members table hardcoded every human's
department as Executive with a blank budget. Source the cap from the real
per-department monthly budget envelope (hiring policies), show real allocated
dollars per provider, and render humans (which carry no department or budget)
as not-applicable instead of a fabricated department.
Chat and Settings escaped the content padding with a hardcoded
calc(100vh - 44px) height and negative margins, while Files and Social let the
whole page scroll, so secondary panes (channel list, settings nav, file tree)
scrolled away. Add a .content.flush modifier the Shell applies to the chat,
settings, files and social routes, plus a reusable .pane-scroll region, and
rework those pages to fill the content area with each pane scrolling on its
own. Removes the magic-number coupling to the topbar height.
Each page rendered its primary actions inside the scrolling body, so they
drifted away on scroll and diverged from the design, which places them in the
topbar next to the breadcrumbs. Introduce a TopbarSlotContext that the Shell
publishes from its topbar action area, and a TopbarActions portal that Home,
Team, Work, Files, Social and Approvals use to render their controls there.
The provider step was filtered to API_KEY only, which hid GitHub
Copilot, Google Antigravity, and GPT account from the founding-CEO
runtime picker even though they are first-class providers in the
catalog. Show every non-cloud provider, render an "Access token" field
in place of the API-key field for OAuth and account auths, and surface
a button that opens the provider's official sign-in page via the new
openExternalUrl IPC (validated to http(s) only).
OnboardingService.resolveProvider now accepts any non-cloud auth type.
Cloud providers still route through Settings since their multi-field
config does not fit the linear onboarding step.
The catalog only carried one defaultModel string per provider, which
forced users to type model ids by hand and made the onboarding /
providers panel feel like the original AgentCompany was missing models.
- src/shared/provider-models.ts holds the canonical id/name list per
provider key (~165 entries across OpenAI, Anthropic, xAI, Groq,
GitHub Copilot, Antigravity, GPT account, Azure, Bedrock, Vertex)
- ProviderCatalogEntry now exposes a models[] array
- Onboarding ProviderStep renders a <select> populated from the active
provider's catalog instead of a freeform text input
- ProvidersPanel connect dialog uses the same picker for API key,
OAuth, and account auth flows
- TeamPage hire dialog adds a <datalist> with every catalog model so
manual entry is autocompletable
OAuth, account, and cloud providers previously fell into the same
password input as API key providers, which made them impossible to
connect properly. Split the connect dialog by auth type:
- api_key: secret + model (unchanged)
- oauth_pkce / account_subscription: button that opens the provider's
official sign-in URL in a session-partitioned BrowserWindow, then a
paste field for the access token returned by the provider
- cloud: multi-field form (base URL, region, project, deployment,
credential) serialized into the encrypted secret payload
Each catalog entry now carries signInUrl and credentialHelp so the
dialog can render the right instructions without baking copy into the
renderer.
Backed by a new launchProviderSignIn IPC method on ProviderService that
opens a hardened popup (nodeIntegration off, contextIsolation on,
sandbox on, permission denies) and records an audit event.
The sidebar org button was inert: clicking it did nothing. Add a real
dropdown menu listing every organization, a "New organization" entry
that re-enters onboarding without resetting the database, and a per-org
delete affordance with inline confirmation. Active org is now persisted
in a single-row app_state table so the snapshot keeps a stable
selection across restarts and the renderer drives switching via two new
IPC channels (setActiveOrganization, deleteOrganization).
- migration 006 adds app_state(id=1, active_org_id, updated_at)
- snapshot resolves active org from app_state with the first-org fallback
- OrganizationService gains setActive + delete + bootstrap upsert
- new OrgSwitcher renderer component keeps Shell.tsx lean
The empty-thread "No replies yet." / "Thread {state}" line was status
text — disallowed by the no-status rule — and the design uses the
textarea placeholder "Reply in thread…" for the same affordance. Drop
the line and the now-unused thread prop.
The previous logic seeded each provider-default row with the count of
agents whose modelId matched the provider model, then iterated agents
again and incremented that same row. CEOs bound to the provider default
were counted twice. Seed default rows with zero and let the agent loop
populate counts once.
The narrow-viewport collapse rule was hiding nav-item labels everywhere,
including the chat channel list, settings sub-nav, and files tree. The
collapse is only meant for the primary aside; scope the selectors so
secondary panes keep their labels at narrow widths.
useSnapshot now memoizes the actions object so dependants don't see a
fresh reference on every render. ChatPage's mark-read effect keys off
activeSpaceId/latestActiveMessageId primitives instead of the snapshot
objects that re-allocate on reload, which prevents the markRead → reload
→ rerender loop that was deadlocking the Electron click path under
Playwright.
Also constrains HomePage agenda time to same-day activity so the
'Today' column doesn't surface a meaningless wall-clock for older tasks.
Adds chat_read_state migration (employee_id + space_id, last read
message + timestamp) wired through ChatService.markSpaceRead, IPC
markChatSpaceRead, and an effect in ChatPage that flushes the active
space whenever the latest message id changes.
Shell.computeBadges now derives the Messages badge from
(message.createdAt > read_state.last_read_at) minus messages the viewer
sent, so the sidebar shows true unread instead of total throughput.
Removes "Nothing pending.", "No tasks…", "Empty.", "No messages…", "No
files…", and similar status descriptions across Home/Work/Chat/Files/
Approvals/Social/Team/Settings panels — design-source never renders this
copy, and the user-frontend rule forbids status narration.
Lets the snapshot loader throw on IPC failure instead of holding a banner
string; the shell topbar handles its own crash boundary.
Fixes Team org-chart connector when only one agent is hired, switches
Settings to use one breadcrumb path, drops the unread badge until we have
read-state tracking, and snaps the Providers grid to the two-column
design spec.
The global webRequest.onHeadersReceived CSP rewrite was attached to
session.defaultSession, which intercepts every Chromium request
(including devtools and network service internals) and crashed the
network service in dev. Drop the global override and rely on the
renderer-level meta tag, widened to allow Vite's localhost HMR
connections.
- Port design tokens, sidebar, topbar, and icons to inline SVG set
- Rewrite each page (Home/Team/Work/Chat/Files/Approvals/Social/Settings)
to drive real snapshot data and match the bento, kanban, three-pane chat,
file tree + pinned cards, approval queue, social schedule + calendar,
and settings sub-nav layouts
- Split Chat and Settings into per-concern subcomponents so every file
stays under 500 lines
- Add schema v4 for pinned files and scheduled posts plus IPC + service
wiring; cover new behavior in unit tests
- Update onboarding labels and Hire form to remove ambiguity for the
expanded e2e suite (all settings tabs + 8 routes at 1280 and 980)
- TeamPage: add SVG connector lines between CEO and subordinate agent cards
- WorkPage: add Board/List view toggle and Filter button matching design topbar
- List view shows all tasks in table format with status/priority/assignee columns