| 1 | import assert from "node:assert/strict"; |
| 2 | import { test } from "node:test"; |
| 3 | |
| 4 | import type { DirectoryPerson, DirectoryTeam, PeopleDirectory } from "@g1t/contracts"; |
| 5 | |
| 6 | import { |
| 7 | type PeopleAgent, |
| 8 | NO_TEAM, |
| 9 | agentPath, |
| 10 | agentsOn, |
| 11 | groupByTeam, |
| 12 | teamsByAgent, |
| 13 | budgetFromText, |
| 14 | codeAccessWords, |
| 15 | directoryEntries, |
| 16 | managerChoices, |
| 17 | orgChart, |
| 18 | ownsFromText, |
| 19 | teamBlock, |
| 20 | teamsOfAgent, |
| 21 | } from "./people.ts"; |
| 22 | |
| 23 | const person = (username: string, extra: Partial<DirectoryPerson> = {}): DirectoryPerson => ({ |
| 24 | user_id: `usr_${username}`, |
| 25 | username, |
| 26 | name: null, |
| 27 | avatar: null, |
| 28 | bio: null, |
| 29 | location: null, |
| 30 | pronouns: null, |
| 31 | timezone: null, |
| 32 | role: "member", |
| 33 | title: null, |
| 34 | manager: null, |
| 35 | owns: [], |
| 36 | joined_at: "2026-10-01T00:00:00Z", |
| 37 | ...extra, |
| 38 | }); |
| 39 | |
| 40 | const team = (slug: string, name: string, extra: Partial<DirectoryTeam> = {}): DirectoryTeam => ({ |
| 41 | slug, |
| 42 | name, |
| 43 | description: null, |
| 44 | visibility: "visible", |
| 45 | parent: null, |
| 46 | lead: null, |
| 47 | channel: null, |
| 48 | budget_micros: null, |
| 49 | people: [], |
| 50 | agent_ids: [], |
| 51 | repos_count: 0, |
| 52 | ...extra, |
| 53 | }); |
| 54 | |
| 55 | const agent = (id: string, handle: string, extra: Partial<PeopleAgent> = {}): PeopleAgent => ({ |
| 56 | id, |
| 57 | handle, |
| 58 | display_name: handle[0]!.toUpperCase() + handle.slice(1), |
| 59 | avatar: null, |
| 60 | avatar_seed: handle, |
| 61 | title: "", |
| 62 | role: "", |
| 63 | status: "idle", |
| 64 | responsibilities: [], |
| 65 | builtin: false, |
| 66 | spent_month_micros: 0, |
| 67 | ...extra, |
| 68 | }); |
| 69 | |
| 70 | const directory: PeopleDirectory = { |
| 71 | people: [ |
| 72 | person("chase", { name: "Chase Pierce", title: "Founder", role: "owner" }), |
| 73 | person("sofia", { name: "Sofia Reyes", title: "Head of Sales", manager: "chase", owns: ["the forecast"] }), |
| 74 | person("jordan", { name: "Jordan Lee", title: "Account Executive", manager: "sofia", owns: ["Halcyon", "Bluebird"] }), |
| 75 | person("kai", { name: "Kai Nakamura", title: "Product Designer", manager: "chase" }), |
| 76 | ], |
| 77 | teams: [ |
| 78 | team("sales", "Sales", { |
| 79 | lead: { kind: "user", username: "sofia", name: "Sofia Reyes", avatar: null }, |
| 80 | people: [ |
| 81 | { username: "sofia", role: "maintainer" }, |
| 82 | { username: "jordan", role: "member" }, |
| 83 | ], |
| 84 | agent_ids: ["agt_david"], |
| 85 | repos_count: 0, |
| 86 | }), |
| 87 | team("design", "Design", { people: [{ username: "kai", role: "maintainer" }], repos_count: 2 }), |
| 88 | team("night-shift", "Night shift", { lead: { kind: "agent", agent_id: "agt_atlas" }, agent_ids: ["agt_atlas", "agt_sentinel", "agt_david"] }), |
| 89 | ], |
| 90 | base_permission: "read", |
| 91 | can_manage: true, |
| 92 | }; |
| 93 | |
| 94 | const agents = [ |
| 95 | agent("agt_david", "david", { title: "CRM keeper" }), |
| 96 | agent("agt_atlas", "atlas", { title: "Night watch" }), |
| 97 | agent("agt_sentinel", "sentinel", { title: "Error watch", responsibilities: ["Watches errors"] }), |
| 98 | agent("agt_pax", "pax", { title: "Billing" }), |
| 99 | ]; |
| 100 | |
| 101 | test("an agent is on the teams it is a member of, like anyone", () => { |
| 102 | assert.deepEqual(agentsOn(directory.teams[2]!, agents).map((a) => a.id), ["agt_atlas", "agt_sentinel", "agt_david"]); |
| 103 | assert.deepEqual(teamsOfAgent(directory.teams, agents[0]!).map((t) => t.slug), ["sales", "night-shift"]); |
| 104 | assert.deepEqual(teamsOfAgent(directory.teams, agents[3]!), []); |
| 105 | }); |
| 106 | |
| 107 | test("the Agents sidebar groups agents by their teams: under each team, and the rest last", () => { |
| 108 | const teams = teamsByAgent(directory.teams); |
| 109 | assert.deepEqual(teams.agt_david, [{ slug: "night-shift", name: "Night shift" }, { slug: "sales", name: "Sales" }]); |
| 110 | const groups = groupByTeam(agents, teams).map((g) => [g.label, g.agents.map((a) => a.handle)]); |
| 111 | assert.deepEqual(groups, [ |
| 112 | ["Night shift", ["atlas", "david", "sentinel"]], |
| 113 | ["Sales", ["david"]], |
| 114 | [NO_TEAM, ["pax"]], |
| 115 | ]); |
| 116 | assert.deepEqual(groupByTeam(agents.slice(3), {}).map((g) => g.label), [NO_TEAM]); |
| 117 | }); |
| 118 | |
| 119 | test("the directory lists people only, in one search; agents are never in it", () => { |
| 120 | const names = (query: string) => directoryEntries(directory, query).map((e) => e.person.username); |
| 121 | assert.deepEqual(names(""), ["chase", "sofia", "jordan", "kai"]); |
| 122 | assert.deepEqual(names("sales"), ["sofia", "jordan"]); |
| 123 | assert.deepEqual(names("halcyon"), ["jordan"]); |
| 124 | assert.deepEqual(names("owner"), ["chase"]); |
| 125 | // What only an agent would match (its handle, title or responsibilities) finds no one here. |
| 126 | assert.deepEqual(names("david"), []); |
| 127 | assert.deepEqual(names("errors"), []); |
| 128 | // A team of agents only is no one's team in the directory. |
| 129 | assert.deepEqual(names("night shift"), []); |
| 130 | assert.equal(names("nobody here").length, 0); |
| 131 | // Every entry is a person with their teams; nothing in the shape says "agent". |
| 132 | const sofia = directoryEntries(directory, "sofia")[0]!; |
| 133 | assert.deepEqual(Object.keys(sofia), ["person", "teams"]); |
| 134 | assert.deepEqual(sofia.teams.map((t) => t.slug), ["sales"]); |
| 135 | }); |
| 136 | |
| 137 | test("an agent's profile is its page in Agents, where People links to it", () => { |
| 138 | assert.equal(agentPath("acme", "margo"), "/acme/-/agents/margo"); |
| 139 | }); |
| 140 | |
| 141 | test("the org chart follows reporting lines, with each team's agents beside its lead", () => { |
| 142 | const chart = orgChart(directory, agents); |
| 143 | assert.deepEqual(chart.roots.map((n) => n.person.username), ["chase"]); |
| 144 | const chase = chart.roots[0]!; |
| 145 | assert.deepEqual(chase.reports.map((n) => n.person.username), ["sofia", "kai"]); |
| 146 | const sofia = chase.reports[0]!; |
| 147 | assert.deepEqual(sofia.agents.map((a) => a.handle), ["david"]); |
| 148 | assert.deepEqual(sofia.reports.map((n) => n.person.username), ["jordan"]); |
| 149 | // A team an agent leads sits apart, with its agents. |
| 150 | assert.deepEqual(chart.unled.map((u) => [u.team.slug, u.agents.map((a) => a.handle)]), [["night-shift", ["atlas", "sentinel", "david"]]]); |
| 151 | }); |
| 152 | |
| 153 | test("no one goes missing from the org chart, even in a loop", () => { |
| 154 | const looped: PeopleDirectory = { ...directory, people: [person("a", { manager: "b" }), person("b", { manager: "a" })] }; |
| 155 | const chart = orgChart(looped, []); |
| 156 | const all = (nodes: typeof chart.roots): string[] => nodes.flatMap((n) => [n.person.username, ...all(n.reports)]); |
| 157 | assert.deepEqual(all(chart.roots).sort(), ["a", "b"]); |
| 158 | }); |
| 159 | |
| 160 | test("someone can report to anyone but themselves and the people under them", () => { |
| 161 | assert.deepEqual(managerChoices(directory.people, "sofia").map((p) => p.username), ["chase", "kai"]); |
| 162 | assert.deepEqual(managerChoices(directory.people, "jordan").map((p) => p.username), ["chase", "sofia", "kai"]); |
| 163 | }); |
| 164 | |
| 165 | test("forms read plainly", () => { |
| 166 | assert.deepEqual(ownsFromText("storefront\n the release process ,, billing"), ["storefront", "the release process", "billing"]); |
| 167 | assert.equal(budgetFromText(""), 0); |
| 168 | assert.equal(budgetFromText("$150"), 150_000_000); |
| 169 | assert.equal(budgetFromText("1,250.50"), 1_250_500_000); |
| 170 | assert.equal(budgetFromText("lots"), null); |
| 171 | assert.equal(budgetFromText("-5"), null); |
| 172 | }); |
| 173 | |
| 174 | test("access to Code says where it comes from", () => { |
| 175 | assert.equal(codeAccessWords({ role: "owner" }, "read", []).summary, "Admin on every repository, as an owner"); |
| 176 | const kai = codeAccessWords({ role: "member" }, "read", [directory.teams[1]!]); |
| 177 | assert.equal(kai.summary, "Read on every repository, the workspace's base permission"); |
| 178 | assert.deepEqual(kai.through, ["Roles on 2 repositories through Design"]); |
| 179 | assert.equal(codeAccessWords({ role: "member" }, "none", []).summary, "Only repositories they're given a role on"); |
| 180 | }); |
| 181 | |
| 182 | test("a team's part of what an agent is told", () => { |
| 183 | const told = "## Your teams\n\nIntro.\n\n### Sales\n\nLed by Sofia.\n- @sofia\n\n### Support\n\n- @dev"; |
| 184 | assert.equal(teamBlock(told, "Sales"), "### Sales\n\nLed by Sofia.\n- @sofia"); |
| 185 | assert.equal(teamBlock(told, "Support"), "### Support\n\n- @dev"); |
| 186 | assert.equal(teamBlock(told, "Design"), null); |
| 187 | assert.equal(teamBlock(null, "Sales"), null); |
| 188 | }); |