Skip to content
156 linesCodeBlameRaw

Pick any line to see why it is the way it is: the commit, the pull request and issue it came from, and what the agent was thinking.

Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar1/**
2 * Pieces of the teams pages: a team in a list, and its badges.
3 */
4import { EyeOff, UsersRound } from "lucide-react";
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.5import { Form, Link, useOutletContext } from "react-router";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar6
7import { type Team, teamHandle } from "@g1t/contracts";
8
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.9import type { AgentTeams, PeopleAgent, TeamChange } from "../lib/people";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar10import { teamCounts, teamPath } from "../lib/teams";
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.11import { ErrorText, SubmitButton } from "./ui";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar12import { Badge } from "./ui/badge";
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.13import { SelectField } from "./ui/select";
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.14import { TeamKindMark } from "./people";
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar15
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.16/**
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.17 * What each page of a team gets from the team's layout: the team and the
18 * agents on it, members as its people are.
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.19 */
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.20export type TeamContext = { team: Team; agents: PeopleAgent[] };
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar21
22/** The team whose page this is. */
23export function useTeam(): Team {
24 return useOutletContext<TeamContext>().team;
25}
26
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.27/** The agents on the team whose page this is. */
28export function useTeamAgents(): { agents: PeopleAgent[] } {
29 const { agents } = useOutletContext<TeamContext>();
30 return { agents };
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.31}
32
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar33/** Secret, and the viewer's place in the team. */
34export function TeamBadges({ team }: { team: Pick<Team, "visibility" | "viewer_role"> }) {
35 return (
36 <>
37 {team.visibility === "secret" && (
38 <Badge>
39 <EyeOff size={10} />
40 Secret
41 </Badge>
42 )}
43 {team.viewer_role === "maintainer" && <Badge tone="accent">Maintainer</Badge>}
44 {team.viewer_role === "member" && <Badge>Member</Badge>}
45 </>
46 );
47}
48
49/** One team in a list: its name, handle, what it is for, and how big it is. */
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.50export function TeamRow({ team, agents, children }: { team: Team; agents?: number; children?: React.ReactNode }) {
51 const agentsHere = agents ?? team.agents_count ?? 0;
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar52 return (
53 <li className="flex flex-wrap items-start gap-3 px-4 py-3 transition-colors hover:bg-surface/60 sm:flex-nowrap">
54 <span className="mt-0.5 flex size-7 shrink-0 items-center justify-center rounded-md bg-raised text-muted ring-1 ring-line">
55 <UsersRound size={14} />
56 </span>
57 <div className="min-w-0 grow basis-48">
58 <div className="flex flex-wrap items-center gap-x-2 gap-y-1">
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.59 <TeamKindMark people={team.members_count} agents={agentsHere} />
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar60 <Link to={teamPath(team.workspace, team.slug)} prefetch="intent" className="font-medium hover:underline">
61 {team.name}
62 </Link>
63 <span className="font-mono text-xs text-faint">{teamHandle(team)}</span>
64 <TeamBadges team={team} />
65 </div>
66 {team.description && <p className="mt-0.5 line-clamp-2 text-sm text-muted">{team.description}</p>}
67 <p className="mt-1 text-xs text-faint">
People and teams are front and centre: one directory of people and agents with presence, local time, titles, teams and what each owns; profiles with manager and reports and the agents they work with; an org chart with each team's agents beside the person who leads it; and teams of any mix, with a lead, a channel, a budget agents keep to and the agents on them. Every agent is told its teams each turn (who leads, who owns what, who's around and who to page), and the team page shows exactly what. Member management is Members and invites; the people and teams guide says how.68 {teamCounts(team, agentsHere)}
Teams and CODEOWNERS, labels and milestones, dependency updates, the security suite, and a clearer top bar69 {team.parent && (
70 <>
71 {" · in "}
72 <Link to={teamPath(team.workspace, team.parent.slug)} className="hover:text-fg hover:underline">
73 {team.parent.name}
74 </Link>
75 </>
76 )}
77 </p>
78 </div>
79 {children}
80 </li>
81 );
82}
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.83
84/**
85 * An agent's teams on its profile, as a person's are: each team it is on,
86 * with Remove where the viewer manages the team, and Add to a team. Posts
87 * `join-team` and `leave-team` to the page's action (lib/agent-teams.server.ts).
88 */
89export function AgentTeamsEditor({
90 slug,
91 name,
92 teams,
93 personal = false,
94 change,
95}: {
96 slug: string;
97 /** The agent's name, for the empty line. */
98 name: string;
99 /** Null when its teams couldn't be read. */
100 teams: AgentTeams | null;
101 /** A personal agent is on no team. */
102 personal?: boolean;
103 /** The last change's answer, for its error. */
104 change?: TeamChange | null;
105}) {
106 if (personal) return <p className="text-sm text-faint">A personal agent is on no team. Once an owner promotes it, add it to teams like anyone.</p>;
107 if (!teams) return <p className="text-sm text-faint">Its teams couldn&apos;t be read just now.</p>;
108 const error = (team: string) => (change?.team === team && change.intent === "leave-team" ? change.error : null);
109 return (
110 <div className="space-y-3">
111 {teams.on.length ? (
112 <ul className="space-y-1 text-sm">
113 {teams.on.map((team) => (
114 <li key={team.slug}>
115 <div className="flex min-h-9 flex-wrap items-center gap-2">
116 <TeamKindMark people={team.people} agents={team.agents} />
117 <Link to={teamPath(slug, team.slug)} className="min-w-0 truncate font-medium hover:text-accent">
118 {team.name}
119 </Link>
120 {team.lead && <Badge tone="accent">Lead</Badge>}
121 {team.can_manage && (
122 <Form method="post" className="ml-auto">
123 <input type="hidden" name="intent" value="leave-team" />
124 <input type="hidden" name="team" value={team.slug} />
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.125 <SubmitButton variant="outline" match={{ intent: "leave-team", team: team.slug }} pending="Removing…">
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.126 Remove
127 </SubmitButton>
128 </Form>
129 )}
130 </div>
131 <ErrorText>{error(team.slug)}</ErrorText>
132 </li>
133 ))}
134 </ul>
135 ) : (
136 <p className="text-sm text-faint">{name} isn&apos;t on a team yet.</p>
137 )}
138 {teams.addable.length > 0 && (
139 <Form method="post" key={`teams:${teams.on.length}`} className="flex flex-col gap-2 sm:flex-row sm:items-center">
140 <input type="hidden" name="intent" value="join-team" />
141 <SelectField
142 name="team"
143 aria-label="Add to a team"
144 defaultValue={teams.addable[0]!.slug}
145 className="w-full sm:w-56"
146 options={teams.addable.map((team) => ({ value: team.slug, label: team.name }))}
147 />
The site is built from its shared components: one Button with its variants and sizes, one Badge, Card for every panel, Alert for notices, Kbd for keys, Table for the security tables, and Avatar, Command, Progress, ScrollArea, ToggleGroup, Collapsible and Accordion in the kit; raw buttons, hand-drawn cards and pills and per-file button class lists are gone, outline buttons stand the same height as filled ones, and the phone's Ask g1t loses its tile. Every page was compared pixel by pixel before and after.148 <SubmitButton variant="outline" match={{ intent: "join-team" }} pending="Adding…">
An agent is on teams the way a person is: through team membership, with no team or department of its own. Add it to teams when you create it, from its profile or from the team's page; the Agents sidebar groups agents by the teams they're on, with those on none last; what an agent is told about its teammates, team budgets, skills reach, Spend's By team and the People pages all read memberships. Agents with an old team name matching a team are moved onto it once; the rest are left off a team. Templates name a role only. The agents, teams and people guides say how.149 Add to team
150 </SubmitButton>
151 </Form>
152 )}
153 {change?.intent === "join-team" && <ErrorText>{change.error}</ErrorText>}
154 </div>
155 );
156}