Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions app/src/features/catalog/AgencyGrid.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const CATEGORIES: Category[] = [
"learning",
"finance",
"people",
"security",
];

/** A fixed color per role, so the mascots tell the cards apart. */
Expand Down
6 changes: 3 additions & 3 deletions app/src/features/catalog/agency.test.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ describe("the Bot agency", () => {

fireEvent.click(within(invite).getByRole("button", { name: "See all bots" }));
const dialog = await screen.findByRole("dialog", { name: "Bot agency" });
expect(await within(dialog).findAllByRole("listitem")).toHaveLength(86);
expect(await within(dialog).findAllByRole("listitem")).toHaveLength(101);
});

test("a crew with only its chief invites the owner to pick bots, and a click adds one", async () => {
Expand Down Expand Up @@ -82,7 +82,7 @@ describe("the Bot agency", () => {
await openCrewWithChief();
fireEvent.click(screen.getByRole("button", { name: "Bot agency" }));
const dialog = await screen.findByRole("dialog", { name: "Bot agency" });
expect(await within(dialog).findAllByRole("listitem")).toHaveLength(86);
expect(await within(dialog).findAllByRole("listitem")).toHaveLength(101);

fireEvent.click(within(dialog).getByRole("button", { name: "Marketing & sales" }));
expect(within(dialog).getAllByRole("listitem")).toHaveLength(24);
Expand Down Expand Up @@ -129,7 +129,7 @@ describe("the Bot agency", () => {
expect(addCalls(fake)[0]).toMatchObject({ templateId: "code-reviewer" });

fireEvent.click(within(dialog).getByRole("button", { name: "Back to all bots" }));
expect(within(dialog).getAllByRole("listitem")).toHaveLength(86);
expect(within(dialog).getAllByRole("listitem")).toHaveLength(101);
});

test("the same role twice gets another name", async () => {
Expand Down
5 changes: 5 additions & 0 deletions app/src/i18n/en/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@ import { base } from "./catalogBase";
import { contentAndLearning } from "./catalogContent";
import { design } from "./catalogDesign";
import { engineering } from "./catalogEngineering";
import { engineeringMore } from "./catalogEngineeringMore";
import { finance } from "./catalogFinance";
import { marketing } from "./catalogMarketing";
import { paidMedia } from "./catalogPaidMedia";
import { people } from "./catalogPeople";
import { product } from "./catalogProduct";
import { security } from "./catalogSecurity";

// The Bot agency (spec 26): ready-made bots the owner adds to a crew. The
// roles are the daemon's sheets, by id; this is what the owner reads about
Expand Down Expand Up @@ -36,6 +38,7 @@ export const catalog = {
learning: "Learning",
finance: "Finance",
people: "People & HR",
security: "Security",
},
none: "No bot matches that.",
loading: "Loading the bots…",
Expand Down Expand Up @@ -65,5 +68,7 @@ export const catalog = {
...finance,
...paidMedia,
...people,
...engineeringMore,
...security,
},
};
85 changes: 85 additions & 0 deletions app/src/i18n/en/catalogEngineeringMore.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// More engineering roles (spec 26.3): what the owner reads about each. All
// work on the owner's own code, with the Manual mode's approvals.

export const engineeringMore = {
"technical-writer": {
name: "Technical Writer",
role: "Writes clear documentation from the real code and setup: guides, references and how-tos that match what the system does",
summary:
"Writes clear docs from your real code and setup: guides, how-tos and references that stay true",
about:
"Reads your code and runs the commands it documents on a copy, so the steps and the output are real. It writes for one reader at a time: the most common task first, numbered steps, what you should see after each one and what to do when it fails. It tells you what it tested and what it only read.",
when: "When your project has no README, the docs are out of date, or someone new has to take over.",
pairs: "Codebase Guide, for the big picture, and Code Reviewer, to check the technical claims.",
},
"sre-engineer": {
name: "Reliability Engineer",
role: "Makes your service dependable: defines what good looks like, sets up alerts that matter and writes the steps to follow when it breaks",
summary:
"Makes your service dependable: clear targets, alerts that matter and steps to follow when it breaks",
about:
"Turns what your users feel into a few targets in numbers, maps where the service can fail and proposes alerts that mean a person must act now, each with the first thing to check. It writes short runbooks for the usual failures and a blameless review after an incident. It never restarts or changes anything in production on its own.",
when: "When your service goes down too often, or you get alerts you ignore.",
pairs: "DevOps Engineer, for the infrastructure, and Backend Developer, for the fixes in code.",
},
"release-engineer": {
name: "Release Engineer",
role: "Plans and prepares releases: version numbers, change notes, checks before shipping and a way back, without publishing for you",
summary:
"Plans and prepares your releases, with notes, a checklist and a way back, and never ships by itself",
about:
"Reads what changed since the last release, groups it by what users notice and proposes the version number and the notes in plain words. It writes a checklist, the steps to ship and the steps to undo, and says which one is hard to undo. You make the tag, the upload and the announcement yourself, and it never touches your signing keys.",
when: "Before every release of an app, a library or a site.",
pairs: "QA Tester, to run the checklist, and DevOps Engineer, for the pipeline.",
},
"codebase-guide": {
name: "Codebase Guide",
role: "Explains an unfamiliar codebase: the big picture, where things live, how a request flows and where to start changing",
summary:
"Explains an unfamiliar codebase: the big picture, where things live and where to start",
about:
"Tailors a tour to what you need to do, traces one real path from start to end by file and function and points out the conventions, the risky areas and the tests. It says what it is sure of and what it inferred, and ends with a small first task. It only reads; it changes nothing unless you ask.",
when: "When you inherit code, join a project or have to change something you did not write.",
pairs: "Technical Writer, to turn the tour into docs, and Software Architect.",
},
"prompt-engineer": {
name: "Instruction Writer for AI",
role: "Writes and improves the instructions you give to AI models, then tests them on real examples before you rely on them",
summary:
"Writes and improves instructions for AI models and tests them on real examples before you trust them",
about:
"Asks for real examples, including hard ones, writes the instruction with a clear goal, rules, answer format and examples, and tests it, changing one thing at a time. You get a table of results for each version and the weak spots that remain. It warns you when the instruction will read untrusted text that could give orders.",
when: "When an AI feature in your app or workflow gives answers you cannot rely on.",
pairs: "Backend Developer, to wire it in, and QA Tester, to try more cases.",
},
"rapid-prototyper": {
name: "Prototype Builder",
role: "Builds a quick working version of an idea to test it with real people, in the simplest way that works, and says what is faked",
summary:
"Builds a quick working version of your idea to test with real people, and says what is faked",
about:
"Starts from the question the prototype must answer and builds only that, with made-up data and no real accounts. It writes a short test for the people who will try it and a note saying what is faked and what a real version needs, so nobody ships the prototype by accident.",
when: "When you have an idea and want to know if people care before you build it properly.",
pairs: "Designer, for the look, and UX Researcher, to run the test.",
},
"localization-engineer": {
name: "Localization Engineer",
role: "Prepares software for several languages and countries: moves text out of the code, handles dates, numbers and plurals, and checks the result",
summary:
"Prepares your software for several languages and countries and checks that nothing breaks",
about:
"Moves the text out of your code into translation files, with one sentence per key and placeholders instead of joined pieces. It handles plurals, dates, numbers and currencies by the user's region, checks layouts with long words and adds a test that fails when a language is missing a string. It hands the new strings to a translator.",
when: "When you want your app or site in a second language, or a country with different formats.",
pairs: "Translator, for the strings, and Frontend Developer, for the layout.",
},
"refactoring-engineer": {
name: "Code Cleanup Engineer",
role: "Cleans up code in small, safe steps without changing what it does, proving each step with tests",
summary:
"Cleans up your code in small, safe steps without changing what it does, with tests for each step",
about:
"Starts from a reason, makes sure tests exist before it touches anything and then changes one thing at a time, each as its own small commit. It does not mix a cleanup with a behavior change, and it never edits a test just to make a cleanup pass. It lists what it saw but left alone.",
when: "When code is hard to change or understand and you want it better without breaking it.",
pairs: "Code Reviewer, to check each step, and QA Tester, to try the behavior.",
},
};
75 changes: 75 additions & 0 deletions app/src/i18n/en/catalogSecurity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
// Security roles (spec 26.3): what the owner reads about each. All work
// defensively, on the owner's own things, and never repeat a secret.

export const security = {
"threat-modeler": {
name: "Threat Modeler",
role: "Maps what could go wrong in a system before it is built or changed: what to protect, who might attack it, how, and what to do about it",
summary:
"Maps what could go wrong in your system and what to do about it, before it is built or changed",
about:
"Draws your system as a short list of parts and flows, marks where trust changes and asks what could go wrong at each place. It ranks the threats by how likely and how bad, in plain words, and proposes defenses with their cost, split into fix before launch and good to have.",
when: "Before you build or change something that holds valuable data or does something important.",
pairs: "Security Reviewer, to check the code once it is built, and Software Architect.",
},
"incident-responder": {
name: "Incident Responder",
role: "Helps you through a security incident: contain it, work out what happened, fix it, tell the right people and learn from it",
summary:
"Helps you through a security incident, step by step: contain it, understand it, fix it and learn from it",
about:
"When a key leaks, an account is taken over or something looks wrong, it gives you the next step, keeps the timeline and tells you which steps are hard to undo. It asks you to save the evidence, helps you work out how far it went, lists who may need to be told and writes a blameless review at the end. You take the actions.",
when: "As soon as you suspect something went wrong with security.",
pairs: "Secrets Auditor, to find other exposed keys, and Backend Developer, to fix the cause.",
},
"secrets-auditor": {
name: "Secrets Auditor",
role: "Finds passwords, keys and tokens left in your code, files and settings, and plans how to replace and protect them, without repeating their values",
summary:
"Finds passwords, keys and tokens left in your code and files and plans how to replace and protect them",
about:
"Searches your code, its history, settings and documents for passwords, keys and tokens, and tells you where each one is and what kind it is, never the value. It treats every real find as leaked, gives the order to replace it and plans how to keep secrets out in future. It never uses a secret it finds.",
when: "Before you make a project public, share it, or hand it over.",
pairs: "DevOps Engineer, for safe storage, and Security Reviewer.",
},
"privacy-engineer": {
name: "Privacy Engineer",
role: "Checks what personal data your product collects and keeps, whether it needs it, and how to protect it and respect people's choices",
summary:
"Checks what personal data your product collects and keeps, and how to protect it and respect choices",
about:
"Maps every kind of personal data you collect, where it goes and how long it stays, and asks whether you need it. It checks who can read it, whether it shows up in logs and whether people can see, correct or delete their data. It lists the laws that may apply as questions for a lawyer and never says something is compliant.",
when: "Before you launch, collect new data, or when a customer asks how you handle theirs.",
pairs: "HR Policy Writer, for plain-language notices, and Backend Developer, for the changes.",
},
"compliance-checklist": {
name: "Compliance Checklist Assistant",
role: "Turns a security or privacy standard into a plain checklist, shows what you already do and what is missing, and gathers the evidence",
summary:
"Turns a security or privacy standard into a plain checklist and shows what you do and what is missing",
about:
"Takes the standard or the customer questionnaire you have to meet, turns each requirement into a plain question and checks it against what you show it. It marks an item done only with evidence, plans the gaps by effort and effect and drafts honest answers for a questionnaire. It is not an auditor and nothing it writes is a certification.",
when: "When a customer, a contract or a market asks you to prove your security or privacy.",
pairs: "Privacy Engineer and Secrets Auditor, for specific findings.",
},
"ai-code-auditor": {
name: "AI-Written Code Auditor",
role: "Reviews code that an AI wrote for the mistakes it tends to make: invented functions, weak security, missing checks and code nobody understands",
summary:
"Reviews code written by an AI for the mistakes it tends to make, before you rely on it",
about:
"Checks that the libraries and functions the code uses really exist, looks for the basic security holes this kind of code often skips, tests the edge cases and checks that the tests really test something. It also tells you if the code is more complex than it needs to be. You get a verdict: safe, safe after these fixes, or do not use.",
when: "Before code that an AI wrote reaches real users or real data.",
pairs: "Code Reviewer, for a second look, and Security Reviewer.",
},
"cloud-config-reviewer": {
name: "Cloud Setup Reviewer",
role: "Reviews your cloud and server settings for risky choices: open doors, too much access, missing logs and missing backups",
summary:
"Reviews your cloud and server settings for open doors, too much access and missing backups",
about:
"Reads the settings you export and finds the usual risks: storage open to the world, accounts with too much access, no second factor, no backups or backups never tested. Each finding comes with the evidence and the smallest safe change, and it warns about changes that could lock you out. It never signs in to your account.",
when: "After you set up a cloud account or server, and once a year after that.",
pairs: "DevOps Engineer, who applies the changes, and Secrets Auditor.",
},
};
5 changes: 5 additions & 0 deletions app/src/i18n/es/catalog.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,13 @@ import { base } from "./catalogBase";
import { contentAndLearning } from "./catalogContent";
import { design } from "./catalogDesign";
import { engineering } from "./catalogEngineering";
import { engineeringMore } from "./catalogEngineeringMore";
import { finance } from "./catalogFinance";
import { marketing } from "./catalogMarketing";
import { paidMedia } from "./catalogPaidMedia";
import { people } from "./catalogPeople";
import { product } from "./catalogProduct";
import { security } from "./catalogSecurity";

export const catalog: Messages["catalog"] = {
title: "Agencia de bots",
Expand All @@ -33,6 +35,7 @@ export const catalog: Messages["catalog"] = {
learning: "Aprendizaje",
finance: "Finanzas",
people: "Personas y RR. HH.",
security: "Seguridad",
},
none: "Ningún bot coincide con eso.",
loading: "Cargando los bots…",
Expand Down Expand Up @@ -62,5 +65,7 @@ export const catalog: Messages["catalog"] = {
...finance,
...paidMedia,
...people,
...engineeringMore,
...security,
},
};
Loading
Loading