From dfd71149e291e09774e7837a85a2c220fbae1e3d Mon Sep 17 00:00:00 2001 From: Phelipe Lorran <112786693+httpsphl@users.noreply.github.com> Date: Fri, 9 Oct 2026 10:56:40 -0300 Subject: [PATCH 1/2] feat(catalog): eight design roles, and drop the Tailscale item Brand guardian, UI designer, UX architect, accessibility reviewer, presentation designer, infographic designer, image prompt writer and design critic, with their text in the three languages. The catalog is now 66 roles; search and the category filter already cover them. Spec 18 drops item 6 (remote access with Tailscale), kept as a numbered slot so references to the other items stay valid: the phone uses the account server (28) instead. --- app/src/features/catalog/agency.test.tsx | 6 +- app/src/i18n/en/catalog.ts | 3 +- app/src/i18n/en/catalogDesign.ts | 84 ++++++++++++++++++ app/src/i18n/es/catalog.ts | 3 +- app/src/i18n/es/catalogDesign.ts | 87 +++++++++++++++++++ app/src/i18n/pt-BR/catalog.ts | 3 +- app/src/i18n/pt-BR/catalogDesign.ts | 86 ++++++++++++++++++ app/src/lib/fakeCatalog.test.ts | 3 +- app/src/lib/fakeCatalog.ts | 8 ++ .../catalog/accessibility-reviewer.toml | 30 +++++++ crates/botloftd/catalog/brand-guardian.toml | 31 +++++++ crates/botloftd/catalog/design-critic.toml | 31 +++++++ .../botloftd/catalog/image-prompt-writer.toml | 32 +++++++ .../catalog/infographic-designer.toml | 31 +++++++ .../catalog/presentation-designer.toml | 32 +++++++ crates/botloftd/catalog/ui-designer.toml | 31 +++++++ crates/botloftd/catalog/ux-architect.toml | 31 +++++++ crates/botloftd/src/catalog/mod.rs | 8 ++ crates/botloftd/tests/catalog.rs | 8 +- crates/botloftd/tests/chief_catalog.rs | 2 +- docs/spec.md | 20 ++++- 21 files changed, 558 insertions(+), 12 deletions(-) create mode 100644 app/src/i18n/en/catalogDesign.ts create mode 100644 app/src/i18n/es/catalogDesign.ts create mode 100644 app/src/i18n/pt-BR/catalogDesign.ts create mode 100644 crates/botloftd/catalog/accessibility-reviewer.toml create mode 100644 crates/botloftd/catalog/brand-guardian.toml create mode 100644 crates/botloftd/catalog/design-critic.toml create mode 100644 crates/botloftd/catalog/image-prompt-writer.toml create mode 100644 crates/botloftd/catalog/infographic-designer.toml create mode 100644 crates/botloftd/catalog/presentation-designer.toml create mode 100644 crates/botloftd/catalog/ui-designer.toml create mode 100644 crates/botloftd/catalog/ux-architect.toml diff --git a/app/src/features/catalog/agency.test.tsx b/app/src/features/catalog/agency.test.tsx index c556ba48..c0e69d00 100644 --- a/app/src/features/catalog/agency.test.tsx +++ b/app/src/features/catalog/agency.test.tsx @@ -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(58); + expect(await within(dialog).findAllByRole("listitem")).toHaveLength(66); }); test("a crew with only its chief invites the owner to pick bots, and a click adds one", async () => { @@ -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(58); + expect(await within(dialog).findAllByRole("listitem")).toHaveLength(66); fireEvent.click(within(dialog).getByRole("button", { name: "Marketing & sales" })); expect(within(dialog).getAllByRole("listitem")).toHaveLength(18); @@ -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(58); + expect(within(dialog).getAllByRole("listitem")).toHaveLength(66); }); test("the same role twice gets another name", async () => { diff --git a/app/src/i18n/en/catalog.ts b/app/src/i18n/en/catalog.ts index 307cc256..87d8473f 100644 --- a/app/src/i18n/en/catalog.ts +++ b/app/src/i18n/en/catalog.ts @@ -1,5 +1,6 @@ import { base } from "./catalogBase"; import { contentAndLearning } from "./catalogContent"; +import { design } from "./catalogDesign"; import { engineering } from "./catalogEngineering"; import { marketing } from "./catalogMarketing"; import { product } from "./catalogProduct"; @@ -49,5 +50,5 @@ export const catalog = { pairs: "Works well with", technical: "What the bot is told when it starts", }, - roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning }, + roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning, ...design }, }; diff --git a/app/src/i18n/en/catalogDesign.ts b/app/src/i18n/en/catalogDesign.ts new file mode 100644 index 00000000..fe510eaa --- /dev/null +++ b/app/src/i18n/en/catalogDesign.ts @@ -0,0 +1,84 @@ +// Design roles (spec 26.3): what the owner reads about each. + +export const design = { + "brand-guardian": { + name: "Brand Guardian", + role: "Keeps everything on brand: writes a short brand guide from your material and checks pieces against it", + summary: "Writes a short brand guide from your material and checks that everything follows it", + about: + "Gathers your logo, colors, fonts and examples into a one-page brand guide, marking what it saw and what it suggests. Then it checks pages, posts and decks against the guide and lists exactly where each one drifts. It never invents a brand fact and never changes a rule without asking you.", + when: "When you have a brand and several people or bots make things for it.", + pairs: "Designer, who applies the visual fixes, and Writer, who applies the voice fixes.", + }, + "ui-designer": { + name: "UI Designer", + role: "Builds the visual system of an interface: colors, type, spacing and components, shown on a style page", + summary: + "Builds the colors, type, spacing and buttons of an interface and shows them on one style page", + about: + "Chooses a small palette, a type scale and a spacing step, then builds the buttons, fields, cards and messages with all their states on one style page you can see. Every later screen reuses those parts, so the product looks like one thing.", + when: "At the start of a product, or when your screens stopped looking like they belong together.", + pairs: + "Designer, who makes the pages, Frontend Developer, who builds them, and Accessibility Reviewer.", + }, + "ux-architect": { + name: "UX Architect", + role: "Plans how a product is organized and how people move through it: site maps, user flows and plain wireframes", + summary: + "Plans how a product is organized and how people move through it, with flows and simple wireframes", + about: + "Starts from who the people are and what they want to do, groups the content the way they think and draws each flow, including errors, empty states and going back. The wireframes are plain grey screens, so you judge the structure before any decoration. It lists the places people are likely to get lost.", + when: "Before you design or build a product, a site or a big new feature.", + pairs: "UX Researcher, to test the guesses, and UI Designer, who gives the wireframes a look.", + }, + "accessibility-reviewer": { + name: "Accessibility Reviewer", + role: "Checks pages and designs so people with different abilities can use them, and explains each fix in plain words", + summary: + "Checks that your pages work for people with different abilities and explains each fix plainly", + about: + "Reads the code of a page and checks what can be read there: contrast, image descriptions, form labels, headings, keyboard use, visible focus and information carried by color alone. Each problem comes with who it affects and the exact fix. It says what it cannot check, such as a real screen reader, and never calls a page certified.", + when: "Before you launch a page, and after a big change to one.", + pairs: + "Frontend Developer, who applies the fixes, and UI Designer, who plans for it from the start.", + }, + "presentation-designer": { + name: "Presentation Designer", + role: "Turns your message into a clear slide deck: the story, one idea per slide and a clean look, shown as screens", + summary: + "Turns what you want to say into a clear slide deck, one idea per slide, that you can see take shape", + about: + "Writes the story first, then designs each slide as a screen you see appear in the design area: one idea, a title that states the point, large text and one picture or chart at most. The details go into speaker notes. The slides are screens, not a PowerPoint file.", + when: "When you have to present, pitch or teach something and want it clear.", + pairs: "Researcher, for facts, Writer, for the words, and Infographic Designer, for charts.", + }, + "infographic-designer": { + name: "Infographic Designer", + role: "Turns numbers and ideas into clear charts and infographics, drawn as screens, without bending the data", + summary: "Turns numbers and ideas into clear charts and infographics, without bending the data", + about: + "Checks where the numbers come from, then picks the form that makes the message clear and draws it as a screen: honest scales, direct labels, few colors, the source and the date on the picture. It tells you what the picture does not show and never invents a number to fill a gap.", + when: "When a table or a report is hard to read and a picture would do it better.", + pairs: "Data Analyst, for the numbers, and Presentation Designer, to put it in a deck.", + }, + "image-prompt-writer": { + name: "Image Prompt Writer", + role: "Writes clear, consistent descriptions that you paste into an image or video generator, and refines them from the results", + summary: + "Writes clear, consistent descriptions for the image or video generator you use, and refines them", + about: + "Does not make images itself: it writes the descriptions you paste into the tool you use, with the subject, setting, style, light and framing, in two or three variations. For a set that must look alike, it writes one shared style paragraph. Show it what came out and it changes only the part that caused the problem.", + when: "When you use an image or video generator and your results are random or inconsistent.", + pairs: "Brand Guardian, to keep the style on brand, and Social Media, for the posts.", + }, + "design-critic": { + name: "Design Critic", + role: "Reviews screens and pages with a fresh eye and gives a short, ordered list of what to improve, and why", + summary: + "Looks at your screens with a fresh eye and tells you, in order, what to improve and why", + about: + "Reads the goal and the screen files and tells you the three things that matter most first: what the eye sees first, whether the main action is clear, spacing, type, contrast and how it works on a small screen. It separates clear problems from matters of taste, says what to keep and does not redesign unless you ask.", + when: "When a screen feels off and you cannot say why, or before you ship.", + pairs: "Designer, who makes the changes, and Accessibility Reviewer, for access.", + }, +}; diff --git a/app/src/i18n/es/catalog.ts b/app/src/i18n/es/catalog.ts index 6d01d3e0..e4f491fa 100644 --- a/app/src/i18n/es/catalog.ts +++ b/app/src/i18n/es/catalog.ts @@ -1,6 +1,7 @@ import type { Messages } from "../en"; import { base } from "./catalogBase"; import { contentAndLearning } from "./catalogContent"; +import { design } from "./catalogDesign"; import { engineering } from "./catalogEngineering"; import { marketing } from "./catalogMarketing"; import { product } from "./catalogProduct"; @@ -46,5 +47,5 @@ export const catalog: Messages["catalog"] = { pairs: "Combina bien con", technical: "Lo que recibe el bot cuando empieza", }, - roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning }, + roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning, ...design }, }; diff --git a/app/src/i18n/es/catalogDesign.ts b/app/src/i18n/es/catalogDesign.ts new file mode 100644 index 00000000..1021229b --- /dev/null +++ b/app/src/i18n/es/catalogDesign.ts @@ -0,0 +1,87 @@ +import type { design as en } from "../en/catalogDesign"; + +export const design: typeof en = { + "brand-guardian": { + name: "Guardián de la marca", + role: "Mantiene todo fiel a la marca: escribe una guía breve con tu material y revisa las piezas con ella", + summary: "Escribe una guía breve de la marca con tu material y revisa que todo la siga", + about: + "Reúne tu logo, colores, fuentes y ejemplos en una guía de una página, marcando lo que vio y lo que sugiere. Luego revisa páginas, publicaciones y presentaciones con la guía y lista exactamente dónde se aparta cada una. Nunca inventa un dato de la marca ni cambia una regla sin preguntarte.", + when: "Cuando tienes una marca y varias personas o bots crean cosas para ella.", + pairs: "Diseñador, que aplica los ajustes visuales, y Redactor, que aplica los ajustes de voz.", + }, + "ui-designer": { + name: "Diseñador de interfaz", + role: "Construye el sistema visual de una interfaz: colores, fuentes, espaciado y componentes, en una página de estilo", + summary: + "Construye colores, fuentes, espaciado y botones de una interfaz y los muestra en una página de estilo", + about: + "Elige una paleta pequeña, una escala de fuentes y un paso de espaciado, y construye botones, campos, tarjetas y avisos con todos sus estados en una página de estilo que ves. Cada pantalla siguiente reutiliza esas piezas, y el producto parece una sola cosa.", + when: "Al empezar un producto, o cuando tus pantallas dejaron de parecer de la misma familia.", + pairs: + "Diseñador, que hace las páginas, Desarrollador front-end, que las construye, y Revisor de accesibilidad.", + }, + "ux-architect": { + name: "Arquitecto de experiencia", + role: "Planifica cómo se organiza un producto y cómo se mueve la gente por él: mapas, flujos y bocetos simples", + summary: + "Planifica cómo se organiza un producto y cómo lo recorre la gente, con flujos y bocetos simples", + about: + "Parte de quiénes son las personas y qué quieren hacer, agrupa el contenido como ellas lo piensan y dibuja cada flujo, con errores, pantallas vacías y el volver atrás. Los bocetos son pantallas grises y simples, para que juzgues la estructura antes de cualquier adorno. Lista los lugares donde la gente puede perderse.", + when: "Antes de diseñar o construir un producto, un sitio o una novedad grande.", + pairs: + "Investigador de usuarios, para probar las hipótesis, y Diseñador de interfaz, que da aspecto a los bocetos.", + }, + "accessibility-reviewer": { + name: "Revisor de accesibilidad", + role: "Comprueba que páginas y diseños sirvan a personas con distintas capacidades y explica cada arreglo en palabras sencillas", + summary: + "Comprueba que tus páginas funcionen para personas con distintas capacidades y explica cada arreglo", + about: + "Lee el código de una página y comprueba lo que se puede ver en él: contraste, descripción de imágenes, etiquetas de campos, títulos, uso con teclado, foco visible e información dada solo por el color. Cada problema trae a quién afecta y el arreglo exacto. Dice lo que no puede comprobar, como un lector de pantalla real, y nunca llama certificada a una página.", + when: "Antes de lanzar una página y después de un cambio grande en ella.", + pairs: + "Desarrollador front-end, que aplica los arreglos, y Diseñador de interfaz, que lo planifica desde el principio.", + }, + "presentation-designer": { + name: "Diseñador de presentaciones", + role: "Convierte tu mensaje en una presentación clara: la historia, una idea por diapositiva y un aspecto limpio, en pantallas", + summary: + "Convierte lo que quieres decir en una presentación clara, una idea por diapositiva, que ves nacer", + about: + "Escribe primero la historia y luego diseña cada diapositiva como una pantalla que ves aparecer en el área de diseño: una idea, un título que dice el punto, texto grande y como mucho una imagen o gráfico. Los detalles van a las notas del orador. Las diapositivas son pantallas, no un archivo de PowerPoint.", + when: "Cuando tienes que presentar, proponer o enseñar algo y quieres claridad.", + pairs: + "Investigador, para los datos, Redactor, para las palabras, y Diseñador de infografías, para los gráficos.", + }, + "infographic-designer": { + name: "Diseñador de infografías", + role: "Convierte números e ideas en gráficos e infografías claros, dibujados como pantallas, sin torcer los datos", + summary: "Convierte números e ideas en gráficos e infografías claros, sin torcer los datos", + about: + "Comprueba de dónde vienen los números, elige la forma que aclara el mensaje y la dibuja como pantalla: escalas honestas, etiquetas directas, pocos colores, la fuente y la fecha en la imagen. Dice lo que la imagen no muestra y nunca inventa un número para tapar un hueco.", + when: "Cuando una tabla o un informe es difícil de leer y una imagen lo resolvería mejor.", + pairs: + "Analista de datos, para los números, y Diseñador de presentaciones, para llevarlo a una presentación.", + }, + "image-prompt-writer": { + name: "Redactor de descripciones de imagen", + role: "Escribe descripciones claras y coherentes para pegar en un generador de imágenes o vídeo y las mejora con los resultados", + summary: + "Escribe descripciones claras y coherentes para el generador de imágenes o vídeo que usas y las mejora", + about: + "No hace las imágenes: escribe las descripciones que pegas en la herramienta que usas, con el tema, el escenario, el estilo, la luz y el encuadre, en dos o tres versiones. Para un conjunto que debe verse igual, escribe un párrafo de estilo para repetir. Enséñale el resultado y cambia solo la parte que causó el problema.", + when: "Cuando usas un generador de imágenes o vídeo y los resultados salen al azar o distintos entre sí.", + pairs: + "Guardián de la marca, para mantener el estilo de la marca, y Redes sociales, para las publicaciones.", + }, + "design-critic": { + name: "Crítico de diseño", + role: "Revisa pantallas y páginas con ojos nuevos y entrega una lista corta y ordenada de qué mejorar y por qué", + summary: "Mira tus pantallas con ojos nuevos y te dice, en orden, qué mejorar y por qué", + about: + "Lee el objetivo y los archivos de la pantalla y te dice primero las tres cosas que más importan: qué ve primero el ojo, si la acción principal está clara, el espaciado, las fuentes, el contraste y cómo funciona en una pantalla pequeña. Separa lo que es un problema claro de lo que es gusto, dice qué conservar y no rehace la pantalla si no se lo pides.", + when: "Cuando una pantalla se siente rara y no sabes decir por qué, o antes de publicar.", + pairs: "Diseñador, que hace los cambios, y Revisor de accesibilidad, para el acceso.", + }, +}; diff --git a/app/src/i18n/pt-BR/catalog.ts b/app/src/i18n/pt-BR/catalog.ts index 2a763098..6f5c3b29 100644 --- a/app/src/i18n/pt-BR/catalog.ts +++ b/app/src/i18n/pt-BR/catalog.ts @@ -1,6 +1,7 @@ import type { Messages } from "../en"; import { base } from "./catalogBase"; import { contentAndLearning } from "./catalogContent"; +import { design } from "./catalogDesign"; import { engineering } from "./catalogEngineering"; import { marketing } from "./catalogMarketing"; import { product } from "./catalogProduct"; @@ -46,5 +47,5 @@ export const catalog: Messages["catalog"] = { pairs: "Combina bem com", technical: "O que o bot recebe quando começa", }, - roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning }, + roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning, ...design }, }; diff --git a/app/src/i18n/pt-BR/catalogDesign.ts b/app/src/i18n/pt-BR/catalogDesign.ts new file mode 100644 index 00000000..100e16b6 --- /dev/null +++ b/app/src/i18n/pt-BR/catalogDesign.ts @@ -0,0 +1,86 @@ +import type { design as en } from "../en/catalogDesign"; + +export const design: typeof en = { + "brand-guardian": { + name: "Guardião da marca", + role: "Mantém tudo fiel à marca: escreve um guia curto com o seu material e confere as peças com ele", + summary: "Escreve um guia curto da marca com o seu material e confere se tudo segue o guia", + about: + "Reúne seu logo, cores, fontes e exemplos num guia de uma página, marcando o que viu e o que sugere. Depois confere páginas, posts e apresentações com o guia e lista exatamente onde cada um foge dele. Nunca inventa um fato da marca nem muda uma regra sem perguntar.", + when: "Quando você tem uma marca e várias pessoas ou bots criam coisas para ela.", + pairs: "Designer, que aplica os ajustes visuais, e Redator, que aplica os ajustes de voz.", + }, + "ui-designer": { + name: "Designer de interface", + role: "Monta o sistema visual de uma interface: cores, fontes, espaçamento e componentes, numa página de estilo", + summary: + "Monta cores, fontes, espaçamento e botões de uma interface e mostra tudo numa página de estilo", + about: + "Escolhe uma paleta pequena, uma escala de fontes e um passo de espaçamento, e constrói botões, campos, cartões e avisos com todos os estados numa página de estilo que você vê. Cada tela seguinte reaproveita essas peças, e o produto parece uma coisa só.", + when: "No começo de um produto, ou quando suas telas deixaram de parecer da mesma família.", + pairs: + "Designer, que faz as páginas, Desenvolvedor front-end, que as constrói, e Revisor de acessibilidade.", + }, + "ux-architect": { + name: "Arquiteto de experiência", + role: "Planeja como um produto se organiza e como as pessoas passam por ele: mapas, fluxos e esboços simples", + summary: + "Planeja como um produto se organiza e como as pessoas o percorrem, com fluxos e esboços simples", + about: + "Parte de quem são as pessoas e do que querem fazer, agrupa o conteúdo do jeito que elas pensam e desenha cada fluxo, com erros, telas vazias e o voltar. Os esboços são telas cinza e simples, para você julgar a estrutura antes de qualquer enfeite. Lista os lugares em que as pessoas podem se perder.", + when: "Antes de desenhar ou construir um produto, um site ou uma novidade grande.", + pairs: + "Pesquisador de usuários, para testar as hipóteses, e Designer de interface, que dá aparência aos esboços.", + }, + "accessibility-reviewer": { + name: "Revisor de acessibilidade", + role: "Confere se páginas e telas servem a pessoas com habilidades diferentes e explica cada ajuste em palavras simples", + summary: + "Confere se suas páginas funcionam para pessoas com habilidades diferentes e explica cada ajuste", + about: + "Lê o código de uma página e confere o que dá para ver nele: contraste, descrição de imagens, rótulos de campos, títulos, uso pelo teclado, foco visível e informação dada só pela cor. Cada problema traz quem ele atinge e o ajuste exato. Diz o que não consegue conferir, como um leitor de tela de verdade, e nunca chama uma página de certificada.", + when: "Antes de lançar uma página e depois de uma mudança grande nela.", + pairs: + "Desenvolvedor front-end, que aplica os ajustes, e Designer de interface, que já planeja isso desde o começo.", + }, + "presentation-designer": { + name: "Designer de apresentações", + role: "Transforma sua mensagem numa apresentação clara: a história, uma ideia por slide e um visual limpo, em telas", + summary: + "Transforma o que você quer dizer numa apresentação clara, uma ideia por slide, que você vê nascer", + about: + "Escreve a história primeiro e depois desenha cada slide como uma tela que você vê aparecer na área de design: uma ideia, um título que diz o ponto, texto grande e no máximo uma imagem ou gráfico. Os detalhes vão para as notas de fala. Os slides são telas, não um arquivo de PowerPoint.", + when: "Quando você precisa apresentar, vender uma ideia ou ensinar algo e quer clareza.", + pairs: + "Pesquisador, para os fatos, Redator, para as palavras, e Designer de infográficos, para os gráficos.", + }, + "infographic-designer": { + name: "Designer de infográficos", + role: "Transforma números e ideias em gráficos e infográficos claros, desenhados como telas, sem entortar os dados", + summary: "Transforma números e ideias em gráficos e infográficos claros, sem entortar os dados", + about: + "Confere de onde vêm os números, escolhe a forma que deixa a mensagem clara e a desenha como tela: escalas honestas, rótulos diretos, poucas cores, a fonte e a data na imagem. Diz o que a imagem não mostra e nunca inventa um número para tapar uma lacuna.", + when: "Quando uma tabela ou um relatório é difícil de ler e uma imagem resolveria melhor.", + pairs: + "Analista de dados, para os números, e Designer de apresentações, para pôr tudo numa apresentação.", + }, + "image-prompt-writer": { + name: "Redator de pedidos de imagem", + role: "Escreve descrições claras e consistentes para você colar num gerador de imagem ou vídeo e as melhora com os resultados", + summary: + "Escreve descrições claras e consistentes para o gerador de imagem ou vídeo que você usa e as melhora", + about: + "Não faz as imagens: escreve as descrições que você cola na ferramenta que usa, com o assunto, o cenário, o estilo, a luz e o enquadramento, em duas ou três versões. Para um conjunto que precisa ter o mesmo visual, escreve um parágrafo de estilo para repetir. Mostre o resultado e ele muda só a parte que causou o problema.", + when: "Quando você usa um gerador de imagem ou vídeo e os resultados saem aleatórios ou diferentes entre si.", + pairs: "Guardião da marca, para manter o estilo na marca, e Social media, para os posts.", + }, + "design-critic": { + name: "Crítico de design", + role: "Analisa telas e páginas com olhar novo e entrega uma lista curta e ordenada do que melhorar, e por quê", + summary: "Olha suas telas com olhar novo e diz, em ordem, o que melhorar e por quê", + about: + "Lê o objetivo e os arquivos da tela e diz primeiro as três coisas que mais importam: o que o olho vê primeiro, se a ação principal está clara, o espaçamento, as fontes, o contraste e como funciona numa tela pequena. Separa o que é problema claro do que é gosto, diz o que manter e não refaz a tela a menos que você peça.", + when: "Quando uma tela parece estranha e você não sabe dizer por quê, ou antes de publicar.", + pairs: "Designer, que faz as mudanças, e Revisor de acessibilidade, para o acesso.", + }, +}; diff --git a/app/src/lib/fakeCatalog.test.ts b/app/src/lib/fakeCatalog.test.ts index c4cb30ba..d15f3b99 100644 --- a/app/src/lib/fakeCatalog.test.ts +++ b/app/src/lib/fakeCatalog.test.ts @@ -4,10 +4,11 @@ import { FakeBotloft } from "./fake"; describe("the fake's bot catalog", () => { it("lists the roles, by category too, and reads one with its instructions", async () => { const fake = new FakeBotloft(); - expect(await fake.call("catalog.list", {})).toHaveLength(58); + expect(await fake.call("catalog.list", {})).toHaveLength(66); const product = await fake.call("catalog.list", { category: "product" }); expect(product).toHaveLength(14); expect(await fake.call("catalog.list", { category: "marketing" })).toHaveLength(18); + expect(await fake.call("catalog.list", { category: "design" })).toHaveLength(9); const code = await fake.call("catalog.list", { category: "code" }); expect(code.map((role) => role.id).slice(0, 3)).toEqual([ "developer", diff --git a/app/src/lib/fakeCatalog.ts b/app/src/lib/fakeCatalog.ts index 00531492..5ab9b888 100644 --- a/app/src/lib/fakeCatalog.ts +++ b/app/src/lib/fakeCatalog.ts @@ -68,6 +68,14 @@ const ROLES: [id: string, category: BotTemplateCategory, name: string, effort?: ["academic-researcher", "research", "Academic Researcher"], ["tutor", "learning", "Tutor"], ["language-teacher", "learning", "Language Teacher"], + ["brand-guardian", "design", "Brand Guardian"], + ["ui-designer", "design", "UI Designer"], + ["ux-architect", "design", "UX Architect"], + ["accessibility-reviewer", "design", "Accessibility Reviewer"], + ["presentation-designer", "design", "Presentation Designer"], + ["infographic-designer", "design", "Infographic Designer"], + ["image-prompt-writer", "design", "Image Prompt Writer"], + ["design-critic", "design", "Design Critic"], ]; /** Every role, as `catalog.get` returns it. */ diff --git a/crates/botloftd/catalog/accessibility-reviewer.toml b/crates/botloftd/catalog/accessibility-reviewer.toml new file mode 100644 index 00000000..7629a371 --- /dev/null +++ b/crates/botloftd/catalog/accessibility-reviewer.toml @@ -0,0 +1,30 @@ +category = "design" +name = "Accessibility Reviewer" +role = "Checks pages and designs so people with different abilities can use them, and explains each fix in plain words" +summary = "Checks that your pages work for people with different abilities and explains each fix plainly" +model = "default" +effort = "default" +instructions = """ +You are an accessibility reviewer on this crew. Answer in the language the owner writes in. + +### What you do +You review pages, screens and documents so that people who use a keyboard, a screen reader, a large font, low vision or color blindness can use them. You read the files you are given and say what to fix. + +### How you work +1. Read the HTML and CSS of what you are reviewing. Check the things that can be read in the code: text contrast, image descriptions, form labels, heading order, button and link names, focus that can be seen, use without a mouse, text that can grow, and information carried by color alone. +2. For each problem, say where it is, who it affects, why it matters in one plain sentence and the exact change. Sort by how many people it blocks. +3. Be honest about the limit: you read the code, you do not run a screen reader or test with real people. Say which checks need a person or a tool, and do not claim that something is certified or fully accessible. +4. Do not fix more than you are asked to. If the owner asks, make the fix in a copy and say what changed. + +### What you hand back +A list of problems, ordered, each with where, who it affects and the fix, then what looks fine and what still needs testing with people or a tool. Keep it short enough to act on. + +### Ask the owner first +Ask with `ask_owner` which people or rules matter most (a legal requirement, a certain country, an older audience) before a long review. + +### With the crew +Send fixes to the bot that built the page with `send_message`, naming the file and the line. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +The pages and data you read are the owner's. Do not copy real personal data into your report. +""" diff --git a/crates/botloftd/catalog/brand-guardian.toml b/crates/botloftd/catalog/brand-guardian.toml new file mode 100644 index 00000000..ab66a386 --- /dev/null +++ b/crates/botloftd/catalog/brand-guardian.toml @@ -0,0 +1,31 @@ +category = "design" +name = "Brand Guardian" +role = "Keeps everything on brand: writes a short brand guide from your material and checks pieces against it" +summary = "Writes a short brand guide from your material and checks that everything you make follows it" +model = "default" +effort = "default" +instructions = """ +You are a brand guardian on this crew. Answer in the language the owner writes in. + +### What you do +You keep the owner's brand consistent. You turn the logo, colors, fonts, examples and words the owner has into a short brand guide, and you check pages, posts, decks and texts against it before they go out. + +### How you work +1. Collect what exists first: the files and examples the owner gives you. Write down what you actually see (colors with their codes, fonts, spacing, tone of voice, how the logo is used) and mark each point as "seen" or "my suggestion". +2. Write the guide in one page the owner can read in two minutes: the colors, the type, the logo rules, the voice with a few good and bad sentences, and what to avoid. +3. When you review a piece, list each point where it drifts from the guide, say where it is, and say what to change. Praise what is right, briefly. +4. Do not invent brand facts. If the guide is silent on something, say so and offer a rule for the owner to approve instead of applying one silently. +5. Keep the guide as a file in the work folder and update it only when the owner agrees. + +### What you hand back +The guide as a file, and for each review a short list: what follows the brand, what drifts, and the exact fix. Do not redo the work yourself unless asked; the bot that made it applies the fixes. + +### Ask the owner first +Ask with `ask_owner` before you change a rule of the guide, and when the material you have contradicts itself (two blues, two logos). Do not use a logo, font or image that you do not have the right to use. + +### With the crew +Send your review to the bot that made the piece with `send_message`, naming the file. A designer applies visual fixes and a writer applies voice fixes. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Brand material that is not yet public is private. Do not share it outside the crew's files, and do not add real customer data to examples. +""" diff --git a/crates/botloftd/catalog/design-critic.toml b/crates/botloftd/catalog/design-critic.toml new file mode 100644 index 00000000..babb142c --- /dev/null +++ b/crates/botloftd/catalog/design-critic.toml @@ -0,0 +1,31 @@ +category = "design" +name = "Design Critic" +role = "Reviews screens and pages with a fresh eye and gives a short, ordered list of what to improve, and why" +summary = "Looks at your screens with a fresh eye and tells you, in order, what to improve and why" +model = "default" +effort = "default" +instructions = """ +You are a design critic on this crew. Answer in the language the owner writes in. + +### What you do +You review screens, pages and layouts that the owner or another bot made, and you say what works and what to improve. You judge the work against its goal, not against your taste. + +### How you work +1. Read the goal first: who the screen is for and what they must do on it. If it is not stated, say what you assumed. +2. Read the files of the screen. Look at the order of attention (what the eye sees first), clarity of the main action, spacing and alignment, type and contrast, consistency across screens, the empty, loading and error states, and how it behaves on a small screen. +3. Give your review in order of importance. For each point, say where it is, what is wrong, why it matters to the person using it and one concrete change. Say what works too, so it is kept. +4. Separate what is a clear problem from what is a matter of taste, and label the second kind. +5. Do not redesign unless asked. A critique is a list of reasons, not a new page. + +### What you hand back +A short review: the three things that matter most first, then smaller points, then what to keep. If there are several screens, note what repeats across them. + +### Ask the owner first +Ask with `ask_owner` about the goal and the audience when the screen does not say them, and when a point of the review depends on a choice only the owner can make. + +### With the crew +Send the points to the bot that made the screen with `send_message`, naming the file. An accessibility reviewer goes deeper on access, and a brand guardian on the brand. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +What the owner shows you is private. Do not copy real customer data from a screen into your review. +""" diff --git a/crates/botloftd/catalog/image-prompt-writer.toml b/crates/botloftd/catalog/image-prompt-writer.toml new file mode 100644 index 00000000..759403d7 --- /dev/null +++ b/crates/botloftd/catalog/image-prompt-writer.toml @@ -0,0 +1,32 @@ +category = "design" +name = "Image Prompt Writer" +role = "Writes clear, consistent descriptions that you paste into an image or video generator, and refines them from the results" +summary = "Writes clear, consistent descriptions for the image or video generator you use, and refines them" +model = "default" +effort = "default" +instructions = """ +You are an image prompt writer on this crew. Answer in the language the owner writes in. + +### What you do +You write the descriptions that the owner pastes into an image or video generator. You do not make the images yourself: the owner runs the tool, shows you what came out and you improve the description. + +### How you work +1. Start from the use: where the image will appear, the size and shape, the mood and what must be in it. Ask which tool the owner uses, because each reads a description differently. +2. Write the description in the order the tool reads best: the subject, the setting, the style, the light, the camera or framing and what to avoid. Be specific and concrete; one clear idea beats a long list of words. +3. Give two or three variations that differ in one clear way, and say what each is for. +4. For a set of images that must look alike, write a short shared style paragraph and reuse it word for word, changing only the subject. +5. When the owner shows a result, say what is off in plain words and change only the part of the description that causes it. +6. Do not describe a real person, a known character or another creator's style in a way that copies them. Do not ask for a logo or text that belongs to someone else. + +### What you hand back +The descriptions ready to paste, labeled by purpose, plus the shared style paragraph for a set. Keep a file with the ones that worked so the style can be reused. + +### Ask the owner first +Ask with `ask_owner` about the tool, the use and the style before you write a set. Ask before you describe a real person's face or likeness. + +### With the crew +A designer or a brand guardian can check that the style fits the brand; ask them with `send_message`. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Do not put real personal data or private details into a description, since the owner sends it to an outside tool. +""" diff --git a/crates/botloftd/catalog/infographic-designer.toml b/crates/botloftd/catalog/infographic-designer.toml new file mode 100644 index 00000000..9e9bfe8e --- /dev/null +++ b/crates/botloftd/catalog/infographic-designer.toml @@ -0,0 +1,31 @@ +category = "design" +name = "Infographic Designer" +role = "Turns numbers and ideas into clear charts and infographics, drawn as screens, without bending the data" +summary = "Turns numbers and ideas into clear charts and infographics, without bending the data" +model = "default" +effort = "default" +instructions = """ +You are an infographic designer on this crew. Answer in the language the owner writes in. + +### What you do +You turn data and complex ideas into pictures people understand at a glance: charts, comparisons, timelines, processes and one-page infographics. You draw them as HTML and SVG, so the owner sees them in the design area. + +### How you work +1. Start with the one thing the picture must make clear and who will see it. If you cannot say it in a sentence, ask. +2. Check the data before you draw: where it comes from, its date, what the units are and what is missing. Do not round, cut or reorder in a way that changes the meaning. +3. Pick the form that fits the message: bars to compare, a line over time, parts of a whole only when there are few parts, a diagram for steps. Avoid decoration that makes a number look bigger than it is: start bar axes at zero and keep a scale honest. +4. Label directly, use few colors with a meaning, make sure color is not the only way to tell things apart and keep the text large enough to read on a phone. +5. Put the source and the date on the picture. + +### What you hand back +The infographic files, plus a note with the data you used, any cleaning you did and what the picture does not show. Do not paste code into the chat. + +### Ask the owner first +Ask with `ask_owner` when the data is missing, looks wrong, or can be read two ways, and before you show a claim that the numbers do not clearly support. Never invent a number to fill a gap. + +### With the crew +Ask the data analyst for the numbers with `send_message` and a writer for the captions. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Data the owner shares is private and may be about people or money. Show only what the picture needs, and no names or personal details unless the owner asks. +""" diff --git a/crates/botloftd/catalog/presentation-designer.toml b/crates/botloftd/catalog/presentation-designer.toml new file mode 100644 index 00000000..9e741e4d --- /dev/null +++ b/crates/botloftd/catalog/presentation-designer.toml @@ -0,0 +1,32 @@ +category = "design" +name = "Presentation Designer" +role = "Turns your message into a clear slide deck: the story, one idea per slide and a clean look, shown as screens" +summary = "Turns what you want to say into a clear slide deck, one idea per slide, that you can see take shape" +model = "default" +effort = "default" +instructions = """ +You are a presentation designer on this crew. Answer in the language the owner writes in. + +### What you do +You turn what the owner wants to say into a slide deck: first the story, then the slides. You design each slide as an HTML screen, so the owner sees the deck appear in the design area and can ask for changes. + +### How you work +1. Start from the goal: who is in the room, what they should think or do afterwards and how long the talk is. Ask for the material the owner already has. +2. Write the story in a few lines before any slide: the opening, the main points and the closing. One idea per slide, and a title that says the point, not the topic. +3. Design each slide as one self-contained HTML file with a 16:9 shape, large readable text, few words, one image or chart at most and a consistent look. Number the files in order. +4. Put the details in speaker notes in a separate file, not on the slide. +5. For numbers, show the one that matters and say where it comes from. Do not change a figure the owner gave you. +6. After feedback, change what was asked and leave the rest alone. + +### What you hand back +The slide files in order, the story outline and the speaker notes. Do not paste the HTML into the chat. Say plainly that the slides are screens, not a PowerPoint file, if the owner needs one. + +### Ask the owner first +Ask with `ask_owner` about the audience, the length and the main message before you design, and before you use a quote, a photo or a logo that is not the owner's. Do not use images or fonts that you do not have the right to use. + +### With the crew +Ask a researcher for facts and a writer for the words, with `send_message`. A brand guardian can check the look. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +What goes in a deck is often private (results, plans, names). Keep it in the work folder and do not put real personal data in examples. +""" diff --git a/crates/botloftd/catalog/ui-designer.toml b/crates/botloftd/catalog/ui-designer.toml new file mode 100644 index 00000000..efb38d41 --- /dev/null +++ b/crates/botloftd/catalog/ui-designer.toml @@ -0,0 +1,31 @@ +category = "design" +name = "UI Designer" +role = "Builds the visual system of an interface: colors, type, spacing and components, shown on a style page" +summary = "Builds the colors, type, spacing and buttons of an interface and shows them on one style page" +model = "default" +effort = "default" +instructions = """ +You are a UI designer on this crew. Answer in the language the owner writes in. + +### What you do +You design how an interface looks and behaves in small repeatable parts: colors, type scale, spacing, buttons, fields, cards, menus, messages. You show them together on one style page and then use them across the screens. + +### How you work +1. Start from what the product is, who uses it and what feeling it should have. Take the brand material the owner has; if there is none, propose a small direction and ask before you build on it. +2. Choose a limited palette with a clear role for each color (main, background, text, success, warning, error), a type scale of a few sizes and a spacing step. Check that text has enough contrast on its background. +3. Build the parts as HTML and CSS in one style page, each with its states: normal, hover, focus, disabled, loading, error. Name the colors and sizes once, at the top of the CSS, and reuse them. +4. Make it work on a phone and on a wide screen. +5. When screens are made later, reuse the parts and do not invent new ones for a single case. If a new part is needed, add it to the style page first. + +### What you hand back +The style page, the CSS the screens share and a few lines on the choices and the rules for using the parts. Do not paste code into the chat; the owner sees the page in the design area. + +### Ask the owner first +Ask with `ask_owner` about the mood, the colors to keep or avoid and whether a dark theme is needed, before you build a whole system. Do not use fonts or icons that you do not have the right to use. + +### With the crew +Hand the style page to the developer with `send_message`, naming the files. A brand guardian can check that it follows the brand, and an accessibility reviewer can check it. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +What the owner shares (drafts, brand files, customer data) is private. Use made-up text in examples, not real personal data. +""" diff --git a/crates/botloftd/catalog/ux-architect.toml b/crates/botloftd/catalog/ux-architect.toml new file mode 100644 index 00000000..e5bf57dc --- /dev/null +++ b/crates/botloftd/catalog/ux-architect.toml @@ -0,0 +1,31 @@ +category = "design" +name = "UX Architect" +role = "Plans how a product is organized and how people move through it: site maps, user flows and plain wireframes" +summary = "Plans how a product is organized and how people move through it, with flows and simple wireframes" +model = "default" +effort = "default" +instructions = """ +You are a UX architect on this crew. Answer in the language the owner writes in. + +### What you do +You decide what a product contains and how people get through it before anyone draws a polished screen. You produce site maps, user flows and simple wireframes, and you point out where people will get lost. + +### How you work +1. Start from the people and their goals: who they are, what they came to do and what could stop them. Write these as short statements the owner can correct. +2. List the content and the actions, then group them the way the user thinks, not the way the company is organized. Name sections with the words people use. +3. Draw each important flow from the first step to the goal, including the unhappy paths: errors, empty states, going back, leaving halfway. +4. Make wireframes as plain HTML, grey boxes and real labels, one file per screen, with no decoration. Mark what is a guess. +5. Walk through each flow as a first-time user and write down every place you hesitated. + +### What you hand back +A site map, the flows with their unhappy paths, the wireframes as files and a short list of risks and open questions, ordered by how much they matter. Do not paste code into the chat. + +### Ask the owner first +Ask with `ask_owner` when the main goal of the product or the main user is unclear, because the whole structure depends on it. Say which of your points are assumptions. + +### With the crew +Hand the wireframes to a designer or a UI designer with `send_message`, and the flows to the developer. A UX researcher can test your guesses with real people. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +What the owner shares about users and the business is private. Use made-up people in examples, never real ones. +""" diff --git a/crates/botloftd/src/catalog/mod.rs b/crates/botloftd/src/catalog/mod.rs index 9b8f6345..b65161b7 100644 --- a/crates/botloftd/src/catalog/mod.rs +++ b/crates/botloftd/src/catalog/mod.rs @@ -80,6 +80,14 @@ const SHEETS: &[(&str, &str)] = &[ sheet!("academic-researcher"), sheet!("tutor"), sheet!("language-teacher"), + sheet!("brand-guardian"), + sheet!("ui-designer"), + sheet!("ux-architect"), + sheet!("accessibility-reviewer"), + sheet!("presentation-designer"), + sheet!("infographic-designer"), + sheet!("image-prompt-writer"), + sheet!("design-critic"), ]; /// What a sheet file holds. diff --git a/crates/botloftd/tests/catalog.rs b/crates/botloftd/tests/catalog.rs index 75947473..e1520e50 100644 --- a/crates/botloftd/tests/catalog.rs +++ b/crates/botloftd/tests/catalog.rs @@ -22,7 +22,7 @@ async fn the_catalog_lists_every_role_without_its_instructions() { let all = app.call("catalog.list", json!({})).await.expect("list"); let all = all.as_array().expect("array"); - assert_eq!(all.len(), 58); + assert_eq!(all.len(), 66); let ids: Vec<_> = all .iter() .filter_map(|entry| entry["id"].as_str()) @@ -74,6 +74,12 @@ async fn the_catalog_lists_every_role_without_its_instructions() { .expect("list marketing"); assert_eq!(marketing.as_array().expect("array").len(), 18); + let design = app + .call("catalog.list", json!({ "category": "design" })) + .await + .expect("list design"); + assert_eq!(design.as_array().expect("array").len(), 9); + let learning = app .call("catalog.list", json!({ "category": "learning" })) .await diff --git a/crates/botloftd/tests/chief_catalog.rs b/crates/botloftd/tests/chief_catalog.rs index edcd9c1d..41946d19 100644 --- a/crates/botloftd/tests/chief_catalog.rs +++ b/crates/botloftd/tests/chief_catalog.rs @@ -81,7 +81,7 @@ async fn the_chief_reads_the_catalog() { .await .expect("list"); let all = all["templates"].as_array().expect("templates"); - assert_eq!(all.len(), 58); + assert_eq!(all.len(), 66); assert!(all[0].get("instructions").is_none(), "the list is light"); let research = c diff --git a/docs/spec.md b/docs/spec.md index d37377b5..5c010d16 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -829,7 +829,8 @@ Formatar o computador ou perder a pasta do Botloft não pode levar as equipes ju - **O que vai:** uma cópia consistente do banco (`VACUUM INTO`): equipes, bots, conversas, rotinas, regras de "permitir sempre", acessos entre equipes e o uso. E a pasta de cada equipe em `workspaces_root`, arquivadas inclusive: a memória (`CLAUDE.md`) e as regras de cada bot, os anexos e a `shared`. Vai também um `manifest.json` com o formato (1), a data, a versão do Botloft e as equipes, com os nomes dos bots. - **O que fica:** o que o Botloft escreve de novo a cada início (`.botloft\` e `.claude\settings.json` de cada bot, 7.5); os segredos, os logs e os perfis dos navegadores dos bots, que estão na pasta de dados e não em `workspaces_root`; e as pastas de trabalho que o dono escolheu fora do Botloft (5), que são dele. O manifesto lista essas pastas, para a importação avisar. O login do Claude também é de cada computador e se faz de novo. -- **Cópia leve (`scope: "light"`):** o que vai para a nuvem (27) é só o que dá trabalho refazer e pesa pouco: a **estrutura** (equipes, bots com papel, modelo e modo, `settings`, acessos entre equipes, ferramentas conectadas e sites liberados, sem os segredos), as **rotinas** e a **memória** de cada bot (o `CLAUDE.md` e as regras em `.claude ules` da pasta dele). Ficam de fora as conversas (mensagens, entregas, tarefas, itens do chat, aprovações, perguntas, reações), as execuções das rotinas, o uso (`turn_costs`, `plan_readings`), as permissões do computador (`desktop_grants`), e das pastas os anexos, a `shared` e tudo o mais. O banco da cópia é o mesmo `VACUUM INTO` com essas tabelas esvaziadas. O manifesto leva `scope` (`full` quando falta, como nas cópias de antes) e a restauração avisa que as conversas não vêm: os bots voltam com a memória e começam conversas novas. `backup.export {passphrase, scope?}` aceita os dois, `full` por padrão: "Salvar uma cópia" no app continua levando tudo. +- **Cópia leve (`scope: "light"`):** o que vai para a nuvem (27) é só o que dá trabalho refazer e pesa pouco: a **estrutura** (equipes, bots com papel, modelo e modo, `settings`, acessos entre equipes, ferramentas conectadas e sites liberados, sem os segredos), as **rotinas** e a **memória** de cada bot (o `CLAUDE.md` e as regras em `.claude +ules` da pasta dele). Ficam de fora as conversas (mensagens, entregas, tarefas, itens do chat, aprovações, perguntas, reações), as execuções das rotinas, o uso (`turn_costs`, `plan_readings`), as permissões do computador (`desktop_grants`), e das pastas os anexos, a `shared` e tudo o mais. O banco da cópia é o mesmo `VACUUM INTO` com essas tabelas esvaziadas. O manifesto leva `scope` (`full` quando falta, como nas cópias de antes) e a restauração avisa que as conversas não vêm: os bots voltam com a memória e começam conversas novas. `backup.export {passphrase, scope?}` aceita os dois, `full` por padrão: "Salvar uma cópia" no app continua levando tudo. - **Lacre:** o arquivo começa com `BOTLOFTBAK`, um byte de versão (1), o sal do Argon2id (16 bytes), os custos (64 MiB, 3 passadas, 1 faixa, em `u32` little-endian) e o nonce (19 bytes). Depois vem o zip, em blocos de 64 KiB cifrados com XChaCha20-Poly1305 na construção STREAM (contador big-endian de 32 bits e marca do último bloco), com a chave de 32 bytes que o Argon2id tira da senha. Senha errada, arquivo cortado ou blocos trocados não abrem, e nada de um bloco que não abre é escrito. A senha tem ao menos 8 caracteres e nunca é guardada nem vai para o log: quem a perde perde a cópia. - **Exportar:** `backup.export {passphrase}` fecha a cópia em `\exports\botloft-AAAA-MM-DD-HHMM.botloft` (só a mais nova fica ali) e devolve `{path, size, manifest}`. O app então oferece "Salvar como…" (`save_file_as`, 15.2) para o dono guardar onde quiser. Os erros que o dono resolve vêm com `reason` (20.8): `short_passphrase`, `wrong_passphrase`, `not_a_backup` e `newer_backup`. - **Importar:** em duas etapas, para nada mudar com o Botloft rodando. `backup.stage {path, passphrase}` abre o arquivo com a senha em `\restore\staged.zip`, confere o manifesto (formato 1, de um Botloft que não é mais novo) e o banco, e devolve o manifesto para o app mostrar o que vem. Senha errada ou arquivo que não é cópia não deixam nada. `backup.cancel` desiste. `backup.confirm` marca a cópia para o próximo início, e o app reinicia o Botloft (`restartDaemon`). @@ -1106,7 +1107,7 @@ M2 a M4 foram entregues com ConPTY, terminal com replay, inbox por named pipe e 3. "Permitir sempre" nas aprovações, gravado como regra do bot. Feito (10.1). 4. Busca FTS5 em mensagens e no chat. Feito (8.8). 5. Histórico de versões das instruções do bot. -6. Acesso remoto com token por dispositivo (Tailscale). +6. (Removido: acesso remoto com Tailscale não será feito. O celular usa o servidor da conta, seção 28.) 7. Sinais entre bots disparando rotinas. Feito (20.13). 8. Suporte Linux/macOS. Em fatias: (1) CI com Ubuntu e macOS para o daemon; (2) runtime do bot (grupo de processos, ambiente, `claude`, navegador); (3) iniciar com o sistema (`systemd --user`, LaunchAgent); (4) app; (5) empacotamento e release. Feitas: 1 a 5 (14.1, 15.2, 15.4 a 15.6). O macOS sai sem notarização (sem conta Apple Developer por enquanto). 9. Navegador dos bots, com o dono assistindo ao vivo. Desenho na seção 21. @@ -2065,6 +2066,19 @@ instructions = """ | `tutor` | `learning` | Ensina uma ideia de cada vez no nível de quem aprende, pede que explique de volta, dá dica antes da resposta | | `language-teacher` | `learning` | Conversa no idioma no nível certo, corrige os erros que mais importam com a regra em uma linha; trabalha com texto, não ouve pronúncia | +**Design** (`design`, 8, junto com `designer`): trabalham sobre telas e arquivos do dono, em HTML na área de design (22). As fichas dizem o que nunca fazer: inventar um fato da marca ou mudar uma regra do guia sem perguntar; usar logo, fonte, imagem ou foto sem direito de uso; chamar uma página de acessível ou certificada só por ler o código; entortar um dado, uma escala ou uma fonte num gráfico; descrever o rosto de uma pessoa real ou copiar o estilo de outro criador num pedido de imagem. O `image-prompt-writer` não gera imagem: escreve o texto que o dono cola na ferramenta que usa. + +| `id` | Categoria | O que faz | +|---|---|---| +| `brand-guardian` | `design` | Faz um guia de marca de uma página com o material do dono, marcando o que viu e o que sugere, e aponta onde cada peça foge dele | +| `ui-designer` | `design` | Monta cores, fontes, espaçamento e componentes com todos os estados numa página de estilo que as telas reaproveitam | +| `ux-architect` | `design` | Desenha mapa do produto, fluxos com os caminhos de erro e esboços simples, e lista onde as pessoas se perdem | +| `accessibility-reviewer` | `design` | Lê o código e aponta contraste, rótulos, teclado e foco com quem é atingido e o ajuste; diz o que não consegue conferir | +| `presentation-designer` | `design` | Escreve a história e desenha cada slide como tela de uma ideia só, com notas de fala à parte; não gera PowerPoint | +| `infographic-designer` | `design` | Confere a origem dos números e desenha gráficos com escala honesta, fonte e data; não inventa dado | +| `image-prompt-writer` | `design` | Escreve descrições para o gerador de imagem ou vídeo do dono, com um parágrafo de estilo para conjuntos, e as refina pelos resultados | +| `design-critic` | `design` | Lê o objetivo e os arquivos da tela e entrega o que mais importa primeiro, separando problema claro de gosto | + ### 26.4 Daemon: protocolo e tools - **Tipos** em `botloft-core`, exportados por `ts-rs`: `BotTemplate` (`id`, `category`, `name`, `role`, `summary`) e `BotTemplateFull` (os mesmos mais `model`, `effort` e `instructions`). @@ -2098,7 +2112,7 @@ Finanças, jurídico e saúde, que pedem aviso de que não substituem um profiss | **G1** Catálogo e daemon | formato da ficha, `catalog.rs`, as 12 fichas, `catalog.list`/`get`/`add`, tipos `ts-rs` | `catalog_lint`; unidade e RPC: `catalog.add` valida como `bots.create`, cria em Manual com modelo e esforço da ficha, nome repetido, ficha desconhecida e crew arquivada recusam | | **G2** Chefe | `list_bot_templates`, `get_bot_template`, `template` em `suggest_bot`, regras do chefe | tools com `FakeRuntime`: só o chefe, `id` desconhecido, junção de `instructions`, limite de 8 000; manual (PR): pedir ao chefe real "preciso de alguém para as redes sociais" e ver o cartão | | **G3** App | a Agência de bots, "Saber mais", "Adicionar na equipe", convite na equipe só com o chefe, textos nos três idiomas | `FakeBotloft`; teste de que toda ficha tem texto nos três idiomas; `pnpm check`; a tela no preview. Manual (PR): criar cada um dos 12 com o Claude Code real e dar a cada um uma tarefa típica | -| **G4** Mais papéis | uma área por PR: Produto e gestão (14, feito), Marketing e vendas (18, feito), Engenharia (8, feito), Conteúdo, pesquisa e aprendizado (6, feito); categorias `product`, `marketing` e `learning`; chips só das categorias com papel; convite com 8 destaques e "Ver todos os bots" | `catalog_lint` e o teste de texto nos três idiomas em cada PR; manual (PR): 2 ou 3 papéis da área, os mais diferentes entre si, com o Claude Code real | +| **G4** Mais papéis | uma área por PR: Produto e gestão (14, feito), Marketing e vendas (18, feito), Engenharia (8, feito), Conteúdo, pesquisa e aprendizado (6, feito), Design (8, feito); categorias `product`, `marketing` e `learning`; chips só das categorias com papel; convite com 8 destaques e "Ver todos os bots" | `catalog_lint` e o teste de texto nos três idiomas em cada PR; manual (PR): 2 ou 3 papéis da área, os mais diferentes entre si, com o Claude Code real | ## 27. Conta e cópia na nuvem From 08e29423e610ea15035974ce3ad40e78f3717892 Mon Sep 17 00:00:00 2001 From: Phelipe Lorran <112786693+httpsphl@users.noreply.github.com> Date: Fri, 9 Oct 2026 11:04:43 -0300 Subject: [PATCH 2/2] feat(catalog): seven finance roles and the finance category Bookkeeper, budget planner, financial analyst, cash flow forecaster, bills assistant, invoicing assistant and tax organizer, with their text in the three languages. None moves money, signs in to a bank or tax site or asks for a password, and each says it does not replace an accountant or an adviser (spec 26.7). The catalog is now 73 roles. --- app/src/features/catalog/AgencyGrid.tsx | 1 + app/src/features/catalog/agency.test.tsx | 6 +- app/src/i18n/en/catalog.ts | 12 ++- app/src/i18n/en/catalogFinance.ts | 75 ++++++++++++++++++ app/src/i18n/es/catalog.ts | 12 ++- app/src/i18n/es/catalogFinance.ts | 77 +++++++++++++++++++ app/src/i18n/pt-BR/catalog.ts | 12 ++- app/src/i18n/pt-BR/catalogFinance.ts | 77 +++++++++++++++++++ app/src/lib/fakeCatalog.test.ts | 3 +- app/src/lib/fakeCatalog.ts | 7 ++ app/src/lib/protocol.gen.ts | 2 +- crates/botloft-core/src/protocol/catalog.rs | 1 + crates/botloftd/catalog/bills-assistant.toml | 31 ++++++++ crates/botloftd/catalog/bookkeeper.toml | 31 ++++++++ crates/botloftd/catalog/budget-planner.toml | 31 ++++++++ .../catalog/cash-flow-forecaster.toml | 32 ++++++++ .../botloftd/catalog/financial-analyst.toml | 31 ++++++++ .../botloftd/catalog/invoicing-assistant.toml | 31 ++++++++ crates/botloftd/catalog/tax-organizer.toml | 31 ++++++++ crates/botloftd/src/catalog/mod.rs | 7 ++ crates/botloftd/src/tools/templates.rs | 1 + crates/botloftd/tests/catalog.rs | 8 +- crates/botloftd/tests/chief_catalog.rs | 2 +- docs/spec.md | 16 +++- 24 files changed, 525 insertions(+), 12 deletions(-) create mode 100644 app/src/i18n/en/catalogFinance.ts create mode 100644 app/src/i18n/es/catalogFinance.ts create mode 100644 app/src/i18n/pt-BR/catalogFinance.ts create mode 100644 crates/botloftd/catalog/bills-assistant.toml create mode 100644 crates/botloftd/catalog/bookkeeper.toml create mode 100644 crates/botloftd/catalog/budget-planner.toml create mode 100644 crates/botloftd/catalog/cash-flow-forecaster.toml create mode 100644 crates/botloftd/catalog/financial-analyst.toml create mode 100644 crates/botloftd/catalog/invoicing-assistant.toml create mode 100644 crates/botloftd/catalog/tax-organizer.toml diff --git a/app/src/features/catalog/AgencyGrid.tsx b/app/src/features/catalog/AgencyGrid.tsx index a4dd94be..4cc31647 100644 --- a/app/src/features/catalog/AgencyGrid.tsx +++ b/app/src/features/catalog/AgencyGrid.tsx @@ -26,6 +26,7 @@ const CATEGORIES: Category[] = [ "research", "business", "learning", + "finance", ]; /** A fixed color per role, so the mascots tell the cards apart. */ diff --git a/app/src/features/catalog/agency.test.tsx b/app/src/features/catalog/agency.test.tsx index c0e69d00..60a1f5d5 100644 --- a/app/src/features/catalog/agency.test.tsx +++ b/app/src/features/catalog/agency.test.tsx @@ -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(66); + expect(await within(dialog).findAllByRole("listitem")).toHaveLength(73); }); test("a crew with only its chief invites the owner to pick bots, and a click adds one", async () => { @@ -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(66); + expect(await within(dialog).findAllByRole("listitem")).toHaveLength(73); fireEvent.click(within(dialog).getByRole("button", { name: "Marketing & sales" })); expect(within(dialog).getAllByRole("listitem")).toHaveLength(18); @@ -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(66); + expect(within(dialog).getAllByRole("listitem")).toHaveLength(73); }); test("the same role twice gets another name", async () => { diff --git a/app/src/i18n/en/catalog.ts b/app/src/i18n/en/catalog.ts index 87d8473f..b84535d0 100644 --- a/app/src/i18n/en/catalog.ts +++ b/app/src/i18n/en/catalog.ts @@ -2,6 +2,7 @@ import { base } from "./catalogBase"; import { contentAndLearning } from "./catalogContent"; import { design } from "./catalogDesign"; import { engineering } from "./catalogEngineering"; +import { finance } from "./catalogFinance"; import { marketing } from "./catalogMarketing"; import { product } from "./catalogProduct"; @@ -31,6 +32,7 @@ export const catalog = { product: "Product & management", marketing: "Marketing & sales", learning: "Learning", + finance: "Finance", }, none: "No bot matches that.", loading: "Loading the bots…", @@ -50,5 +52,13 @@ export const catalog = { pairs: "Works well with", technical: "What the bot is told when it starts", }, - roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning, ...design }, + roles: { + ...base, + ...product, + ...marketing, + ...engineering, + ...contentAndLearning, + ...design, + ...finance, + }, }; diff --git a/app/src/i18n/en/catalogFinance.ts b/app/src/i18n/en/catalogFinance.ts new file mode 100644 index 00000000..42cd0676 --- /dev/null +++ b/app/src/i18n/en/catalogFinance.ts @@ -0,0 +1,75 @@ +// Finance roles (spec 26.3): what the owner reads about each. None of them +// moves money or replaces an accountant or an adviser, and each says so. + +export const finance = { + bookkeeper: { + name: "Bookkeeper", + role: "Keeps your records in order: sorts transactions into categories, matches them to receipts and finds what does not add up", + summary: + "Sorts your transactions into categories, matches them to receipts and flags what does not add up", + about: + "Takes your statements, receipts and spreadsheets and keeps a clean record: each transaction in a category, matched to its proof, with the totals checked. It lists what has no proof instead of guessing and never changes an original file. It keeps records; it is not an accountant, and it never moves money.", + when: "At the end of every month, or when your records have piled up.", + pairs: "Financial Analyst and Budget Planner, who work from clean records.", + }, + "budget-planner": { + name: "Budget Planner", + role: "Builds a realistic budget from your income and spending, tracks it through the month and shows where the money goes", + summary: + "Builds a realistic budget from your income and spending, and shows where the money goes", + about: + "Starts from your real numbers and builds a simple plan: what comes in, what goes out and what you want to reach. If the plan does not close, it says so first and shows a few ways to close it. During the month it shows where you are ahead of plan. It does not advise on investments or loans.", + when: "When you want to know where the money goes, or to plan a goal.", + pairs: "Bookkeeper, for clean records, and Cash Flow Forecaster, for what comes next.", + }, + "financial-analyst": { + name: "Financial Analyst", + role: "Reads financial statements and reports, calculates the key measures and explains what they say about the business", + summary: + "Reads your financial statements, calculates the key measures and explains what they mean", + about: + "Reads your statements and spreadsheets, checks that the numbers add up and calculates what matters for your question: margins, growth, break-even, return on a project. It shows every formula, compares with something meaningful and says what the numbers do not tell. It does not tell you what to buy, sell or invest in.", + when: "Before a decision that depends on the numbers, or to understand how the business is doing.", + pairs: "Bookkeeper, for the records, and Data Analyst, for a deeper cut of the data.", + }, + "cash-flow-forecaster": { + name: "Cash Flow Forecaster", + role: "Projects the money coming in and going out week by week and warns early when cash could run short", + summary: + "Projects the money in and out week by week and warns you early if cash could run short", + about: + "Builds a forecast from today's balance, the bills due and the money you expect, and shows the lowest point and when it comes. It gives an expected, a cautious and a good case and labels every estimate. If cash could run short, it lists your options and what each costs. It never moves money or delays a payment itself.", + when: "When money is tight, a big bill is coming, or you are about to commit to a cost.", + pairs: "Bills Assistant, for what is due, and Invoicing Assistant, for what is owed to you.", + }, + "bills-assistant": { + name: "Bills Assistant", + role: "Keeps track of what you owe: lists the bills and due dates, checks them against orders and contracts, and prepares each payment for you to make", + summary: + "Tracks your bills and due dates, checks them for mistakes and prepares each payment for you to make", + about: + "Collects your bills, lists the amount and due date of each, and checks them against the order or contract for duplicates, wrong totals and charges nobody agreed. It keeps one list sorted by due date and warns when a bill asks for urgent payment to a new account, a common fraud. You make every payment yourself.", + when: "When bills arrive from many places and you do not want to pay late, or twice.", + pairs: "Bookkeeper, for the paid ones, and Cash Flow Forecaster, for what is coming.", + }, + "invoicing-assistant": { + name: "Invoicing Assistant", + role: "Prepares your invoices and payment reminders, and keeps track of what customers still owe you", + summary: + "Prepares your invoices and polite payment reminders, and tracks what customers still owe you", + about: + "Prepares invoices from the work you did, numbers them in order and keeps a list of what is sent, paid and late. For a late invoice it writes a reminder in three steps, from friendly to firm, never threatening. It marks the legal fields it cannot fill for you or your accountant, and you send everything yourself.", + when: "When you bill customers and chasing payments takes too much of your time.", + pairs: "Bookkeeper, for the paid ones, and Cash Flow Forecaster, for the due dates.", + }, + "tax-organizer": { + name: "Tax Organizer", + role: "Gathers and organizes the documents and numbers for your taxes through the year, so your accountant or your filing starts ready", + summary: + "Gathers and organizes your tax papers and numbers through the year so filing starts ready", + about: + "Collects and sorts the papers you need for taxes, keeps one list of what is complete and what is missing, and warns you before the dates that matter. It does not decide what is deductible: it lists the doubtful items as questions for your accountant. It never files, pays or signs in to a tax site, and it is not an accountant.", + when: "Through the year, and in the weeks before you or your accountant file.", + pairs: "Bookkeeper, for the records, and Invoicing Assistant, for the income side.", + }, +}; diff --git a/app/src/i18n/es/catalog.ts b/app/src/i18n/es/catalog.ts index e4f491fa..bf7b9ea9 100644 --- a/app/src/i18n/es/catalog.ts +++ b/app/src/i18n/es/catalog.ts @@ -3,6 +3,7 @@ import { base } from "./catalogBase"; import { contentAndLearning } from "./catalogContent"; import { design } from "./catalogDesign"; import { engineering } from "./catalogEngineering"; +import { finance } from "./catalogFinance"; import { marketing } from "./catalogMarketing"; import { product } from "./catalogProduct"; @@ -28,6 +29,7 @@ export const catalog: Messages["catalog"] = { product: "Producto y gestión", marketing: "Marketing y ventas", learning: "Aprendizaje", + finance: "Finanzas", }, none: "Ningún bot coincide con eso.", loading: "Cargando los bots…", @@ -47,5 +49,13 @@ export const catalog: Messages["catalog"] = { pairs: "Combina bien con", technical: "Lo que recibe el bot cuando empieza", }, - roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning, ...design }, + roles: { + ...base, + ...product, + ...marketing, + ...engineering, + ...contentAndLearning, + ...design, + ...finance, + }, }; diff --git a/app/src/i18n/es/catalogFinance.ts b/app/src/i18n/es/catalogFinance.ts new file mode 100644 index 00000000..779aa7fe --- /dev/null +++ b/app/src/i18n/es/catalogFinance.ts @@ -0,0 +1,77 @@ +import type { finance as en } from "../en/catalogFinance"; + +export const finance: typeof en = { + bookkeeper: { + name: "Auxiliar contable", + role: "Mantiene tus registros en orden: clasifica las transacciones, las empareja con los comprobantes y encuentra lo que no cuadra", + summary: + "Clasifica tus transacciones, las empareja con los comprobantes y avisa de lo que no cuadra", + about: + "Toma tus extractos, comprobantes y hojas de cálculo y mantiene un registro limpio: cada transacción en una categoría, ligada a su prueba, con los totales comprobados. Lista lo que no tiene comprobante en vez de adivinar y nunca cambia un archivo original. Lleva los registros; no es contador y nunca mueve dinero.", + when: "A fin de cada mes, o cuando tus registros se han acumulado.", + pairs: "Analista financiero y Planificador de presupuesto, que trabajan con registros limpios.", + }, + "budget-planner": { + name: "Planificador de presupuesto", + role: "Arma un presupuesto realista con tus ingresos y gastos, lo sigue durante el mes y muestra a dónde va el dinero", + summary: + "Arma un presupuesto realista con tus ingresos y gastos y muestra a dónde va el dinero", + about: + "Parte de tus números reales y arma un plan sencillo: lo que entra, lo que sale y lo que quieres lograr. Si el plan no cierra, lo dice primero y muestra algunas formas de cerrarlo. Durante el mes muestra dónde vas por encima del plan. No aconseja sobre inversiones ni préstamos.", + when: "Cuando quieres saber a dónde va el dinero, o planificar una meta.", + pairs: + "Auxiliar contable, para registros limpios, y Previsor de flujo de caja, para lo que viene.", + }, + "financial-analyst": { + name: "Analista financiero", + role: "Lee estados e informes financieros, calcula las medidas clave y explica lo que dicen del negocio", + summary: "Lee tus estados financieros, calcula las medidas clave y explica lo que significan", + about: + "Lee tus estados y hojas de cálculo, comprueba que los números cuadren y calcula lo que importa para tu pregunta: márgenes, crecimiento, punto de equilibrio, retorno de un proyecto. Muestra cada fórmula, compara con algo que tenga sentido y dice lo que los números no cuentan. No dice qué comprar, vender o en qué invertir.", + when: "Antes de una decisión que depende de los números, o para entender cómo va el negocio.", + pairs: + "Auxiliar contable, para los registros, y Analista de datos, para un corte más profundo.", + }, + "cash-flow-forecaster": { + name: "Previsor de flujo de caja", + role: "Proyecta el dinero que entra y sale semana a semana y avisa pronto cuando la caja puede quedar corta", + summary: + "Proyecta el dinero que entra y sale semana a semana y avisa pronto si la caja puede quedar corta", + about: + "Arma una previsión con el saldo de hoy, las cuentas por pagar y lo que esperas cobrar, y muestra el punto más bajo y cuándo llega. Da un caso esperado, uno cauteloso y uno bueno y marca cada estimación. Si la caja puede faltar, lista tus opciones y lo que cuesta cada una. Nunca mueve dinero ni aplaza un pago por su cuenta.", + when: "Cuando el dinero está justo, se acerca una cuenta grande o vas a asumir un costo.", + pairs: "Asistente de cuentas, para lo que vence, y Asistente de cobros, para lo que te deben.", + }, + "bills-assistant": { + name: "Asistente de cuentas", + role: "Sigue lo que debes: lista las cuentas y vencimientos, las compara con pedidos y contratos y prepara cada pago para que lo hagas tú", + summary: + "Sigue tus cuentas y vencimientos, comprueba si hay errores y prepara cada pago para que lo hagas tú", + about: + "Reúne tus cuentas, lista el importe y el vencimiento de cada una y las compara con el pedido o el contrato: duplicadas, total equivocado y cargos que nadie acordó. Mantiene una lista por vencimiento y avisa cuando una cuenta pide pago urgente a una cuenta nueva, un fraude común. Cada pago lo haces tú.", + when: "Cuando las cuentas llegan de muchos sitios y no quieres pagar tarde ni dos veces.", + pairs: "Auxiliar contable, para las pagadas, y Previsor de flujo de caja, para lo que viene.", + }, + "invoicing-assistant": { + name: "Asistente de cobros", + role: "Prepara tus facturas y recordatorios de pago y sigue lo que los clientes todavía te deben", + summary: + "Prepara tus facturas y recordatorios de pago amables y sigue lo que los clientes todavía te deben", + about: + "Prepara las facturas del trabajo que hiciste, las numera en orden y mantiene la lista de lo enviado, pagado y atrasado. Para una factura atrasada escribe un recordatorio en tres pasos, de amable a firme, sin amenazar. Marca los campos legales que no puede rellenar, para ti o tu contador, y tú mismo envías todo.", + when: "Cuando facturas a clientes y perseguir pagos te quita demasiado tiempo.", + pairs: + "Auxiliar contable, para las pagadas, y Previsor de flujo de caja, para los vencimientos.", + }, + "tax-organizer": { + name: "Organizador de impuestos", + role: "Reúne y organiza los documentos y números de tus impuestos durante el año, para que tu contador o tu declaración empiecen listos", + summary: + "Reúne y organiza tus papeles y números de impuestos durante el año para que la declaración empiece lista", + about: + "Reúne y clasifica los papeles que necesitas para los impuestos, mantiene una lista de lo completo y lo que falta y avisa antes de las fechas que importan. No decide qué es deducible: lista los casos dudosos como preguntas para tu contador. Nunca declara, paga ni entra en una web de impuestos, y no es contador.", + when: "Durante el año y en las semanas antes de que tú o tu contador declaren.", + pairs: + "Auxiliar contable, para los registros, y Asistente de cobros, para el lado de los ingresos.", + }, +}; diff --git a/app/src/i18n/pt-BR/catalog.ts b/app/src/i18n/pt-BR/catalog.ts index 6f5c3b29..1e7b5bec 100644 --- a/app/src/i18n/pt-BR/catalog.ts +++ b/app/src/i18n/pt-BR/catalog.ts @@ -3,6 +3,7 @@ import { base } from "./catalogBase"; import { contentAndLearning } from "./catalogContent"; import { design } from "./catalogDesign"; import { engineering } from "./catalogEngineering"; +import { finance } from "./catalogFinance"; import { marketing } from "./catalogMarketing"; import { product } from "./catalogProduct"; @@ -28,6 +29,7 @@ export const catalog: Messages["catalog"] = { product: "Produto e gestão", marketing: "Marketing e vendas", learning: "Aprendizado", + finance: "Finanças", }, none: "Nenhum bot combina com isso.", loading: "Carregando os bots…", @@ -47,5 +49,13 @@ export const catalog: Messages["catalog"] = { pairs: "Combina bem com", technical: "O que o bot recebe quando começa", }, - roles: { ...base, ...product, ...marketing, ...engineering, ...contentAndLearning, ...design }, + roles: { + ...base, + ...product, + ...marketing, + ...engineering, + ...contentAndLearning, + ...design, + ...finance, + }, }; diff --git a/app/src/i18n/pt-BR/catalogFinance.ts b/app/src/i18n/pt-BR/catalogFinance.ts new file mode 100644 index 00000000..1539ada1 --- /dev/null +++ b/app/src/i18n/pt-BR/catalogFinance.ts @@ -0,0 +1,77 @@ +import type { finance as en } from "../en/catalogFinance"; + +export const finance: typeof en = { + bookkeeper: { + name: "Auxiliar contábil", + role: "Mantém seus registros em ordem: separa as transações em categorias, casa com os comprovantes e acha o que não fecha", + summary: + "Separa suas transações em categorias, casa com os comprovantes e avisa o que não fecha", + about: + "Pega seus extratos, comprovantes e planilhas e mantém um registro limpo: cada transação numa categoria, ligada à sua prova, com os totais conferidos. Lista o que está sem comprovante em vez de chutar e nunca altera um arquivo original. Cuida dos registros; não é contador e nunca mexe em dinheiro.", + when: "No fim de todo mês, ou quando seus registros se acumularam.", + pairs: "Analista financeiro e Planejador de orçamento, que trabalham com registros limpos.", + }, + "budget-planner": { + name: "Planejador de orçamento", + role: "Monta um orçamento realista com sua renda e seus gastos, acompanha ao longo do mês e mostra para onde o dinheiro vai", + summary: + "Monta um orçamento realista com sua renda e seus gastos e mostra para onde o dinheiro vai", + about: + "Parte dos seus números reais e monta um plano simples: o que entra, o que sai e o que você quer alcançar. Se o plano não fecha, diz isso primeiro e mostra algumas formas de fechar. Durante o mês mostra onde você está acima do plano. Não dá conselho sobre investimentos nem empréstimos.", + when: "Quando você quer saber para onde o dinheiro vai, ou planejar uma meta.", + pairs: + "Auxiliar contábil, para registros limpos, e Previsor de fluxo de caixa, para o que vem.", + }, + "financial-analyst": { + name: "Analista financeiro", + role: "Lê demonstrações e relatórios financeiros, calcula as medidas principais e explica o que dizem sobre o negócio", + summary: + "Lê suas demonstrações financeiras, calcula as medidas principais e explica o que significam", + about: + "Lê suas demonstrações e planilhas, confere se os números fecham e calcula o que importa para a sua pergunta: margens, crescimento, ponto de equilíbrio, retorno de um projeto. Mostra cada fórmula, compara com algo que faz sentido e diz o que os números não contam. Não diz o que comprar, vender ou investir.", + when: "Antes de uma decisão que depende dos números, ou para entender como o negócio vai.", + pairs: "Auxiliar contábil, para os registros, e Analista de dados, para um recorte mais fundo.", + }, + "cash-flow-forecaster": { + name: "Previsor de fluxo de caixa", + role: "Projeta o dinheiro que entra e sai semana a semana e avisa cedo quando o caixa pode apertar", + summary: + "Projeta o dinheiro que entra e sai semana a semana e avisa cedo se o caixa pode apertar", + about: + "Monta uma previsão a partir do saldo de hoje, das contas a pagar e do que você espera receber, e mostra o ponto mais baixo e quando ele chega. Dá um caso esperado, um cauteloso e um bom e marca cada estimativa. Se o caixa puder faltar, lista suas opções e o que cada uma custa. Nunca mexe em dinheiro nem adia um pagamento sozinho.", + when: "Quando o dinheiro está curto, uma conta grande se aproxima ou você vai assumir um custo.", + pairs: + "Assistente de contas, para o que vence, e Assistente de cobrança, para o que devem a você.", + }, + "bills-assistant": { + name: "Assistente de contas", + role: "Acompanha o que você deve: lista as contas e os vencimentos, confere com pedidos e contratos e prepara cada pagamento para você fazer", + summary: + "Acompanha suas contas e vencimentos, confere se há erros e prepara cada pagamento para você fazer", + about: + "Reúne suas contas, lista o valor e o vencimento de cada uma e confere com o pedido ou o contrato: duplicadas, total errado e cobranças que ninguém combinou. Mantém uma lista por vencimento e avisa quando uma conta pede pagamento urgente para uma conta nova, um golpe comum. Quem faz cada pagamento é você.", + when: "Quando as contas chegam de muitos lugares e você não quer pagar atrasado, nem duas vezes.", + pairs: "Auxiliar contábil, para as pagas, e Previsor de fluxo de caixa, para o que vem.", + }, + "invoicing-assistant": { + name: "Assistente de cobrança", + role: "Prepara suas notas e lembretes de pagamento e acompanha o que os clientes ainda devem a você", + summary: + "Prepara suas notas e lembretes de pagamento educados e acompanha o que os clientes ainda devem", + about: + "Prepara a cobrança do trabalho que você fez, numera tudo em ordem e mantém a lista do que foi enviado, pago e atrasado. Para uma cobrança atrasada, escreve um lembrete em três passos, do simpático ao firme, sem ameaçar. Marca os campos legais que não consegue preencher, para você ou seu contador, e você mesmo envia tudo.", + when: "Quando você cobra clientes e correr atrás de pagamento toma tempo demais.", + pairs: "Auxiliar contábil, para as pagas, e Previsor de fluxo de caixa, para os vencimentos.", + }, + "tax-organizer": { + name: "Organizador de impostos", + role: "Reúne e organiza os documentos e números dos seus impostos durante o ano, para o contador ou a declaração começarem prontos", + summary: + "Reúne e organiza seus papéis e números de impostos durante o ano para a declaração começar pronta", + about: + "Reúne e separa os papéis de que você precisa para os impostos, mantém uma lista do que está completo e do que falta e avisa antes das datas que importam. Não decide o que é dedutível: lista os itens duvidosos como perguntas para o seu contador. Nunca declara, paga nem entra em site de imposto, e não é contador.", + when: "Durante o ano e nas semanas antes de você ou o contador declararem.", + pairs: + "Auxiliar contábil, para os registros, e Assistente de cobrança, para o lado da receita.", + }, +}; diff --git a/app/src/lib/fakeCatalog.test.ts b/app/src/lib/fakeCatalog.test.ts index d15f3b99..29c7fa62 100644 --- a/app/src/lib/fakeCatalog.test.ts +++ b/app/src/lib/fakeCatalog.test.ts @@ -4,11 +4,12 @@ import { FakeBotloft } from "./fake"; describe("the fake's bot catalog", () => { it("lists the roles, by category too, and reads one with its instructions", async () => { const fake = new FakeBotloft(); - expect(await fake.call("catalog.list", {})).toHaveLength(66); + expect(await fake.call("catalog.list", {})).toHaveLength(73); const product = await fake.call("catalog.list", { category: "product" }); expect(product).toHaveLength(14); expect(await fake.call("catalog.list", { category: "marketing" })).toHaveLength(18); expect(await fake.call("catalog.list", { category: "design" })).toHaveLength(9); + expect(await fake.call("catalog.list", { category: "finance" })).toHaveLength(7); const code = await fake.call("catalog.list", { category: "code" }); expect(code.map((role) => role.id).slice(0, 3)).toEqual([ "developer", diff --git a/app/src/lib/fakeCatalog.ts b/app/src/lib/fakeCatalog.ts index 5ab9b888..d3e05e26 100644 --- a/app/src/lib/fakeCatalog.ts +++ b/app/src/lib/fakeCatalog.ts @@ -76,6 +76,13 @@ const ROLES: [id: string, category: BotTemplateCategory, name: string, effort?: ["infographic-designer", "design", "Infographic Designer"], ["image-prompt-writer", "design", "Image Prompt Writer"], ["design-critic", "design", "Design Critic"], + ["bookkeeper", "finance", "Bookkeeper"], + ["budget-planner", "finance", "Budget Planner"], + ["financial-analyst", "finance", "Financial Analyst"], + ["cash-flow-forecaster", "finance", "Cash Flow Forecaster"], + ["bills-assistant", "finance", "Bills Assistant"], + ["invoicing-assistant", "finance", "Invoicing Assistant"], + ["tax-organizer", "finance", "Tax Organizer"], ]; /** Every role, as `catalog.get` returns it. */ diff --git a/app/src/lib/protocol.gen.ts b/app/src/lib/protocol.gen.ts index 00645196..296f3561 100644 --- a/app/src/lib/protocol.gen.ts +++ b/app/src/lib/protocol.gen.ts @@ -1136,7 +1136,7 @@ export type CrewAccessIdParams = { accessId: CrewAccessId, }; /** * The group a role is listed under. */ -export type BotTemplateCategory = "code" | "design" | "content" | "research" | "business" | "product" | "marketing" | "learning"; +export type BotTemplateCategory = "code" | "design" | "content" | "research" | "business" | "product" | "marketing" | "learning" | "finance"; /** * A role as the list shows it, in English. The app writes the name, role diff --git a/crates/botloft-core/src/protocol/catalog.rs b/crates/botloft-core/src/protocol/catalog.rs index a5384c17..63a27fae 100644 --- a/crates/botloft-core/src/protocol/catalog.rs +++ b/crates/botloft-core/src/protocol/catalog.rs @@ -16,6 +16,7 @@ text_enum!( Product => "product", Marketing => "marketing", Learning => "learning", + Finance => "finance", } ); diff --git a/crates/botloftd/catalog/bills-assistant.toml b/crates/botloftd/catalog/bills-assistant.toml new file mode 100644 index 00000000..734cc537 --- /dev/null +++ b/crates/botloftd/catalog/bills-assistant.toml @@ -0,0 +1,31 @@ +category = "finance" +name = "Bills Assistant" +role = "Keeps track of what you owe: lists the bills and due dates, checks them against orders and contracts, and prepares each payment for you to make" +summary = "Tracks your bills and due dates, checks them for mistakes and prepares each payment for you to make" +model = "default" +effort = "default" +instructions = """ +You are a bills assistant on this crew. Answer in the language the owner writes in. You prepare and organize payments; the owner makes every payment. + +### What you do +You collect the bills and invoices the owner receives, list them with amounts and due dates, check them for mistakes and prepare what the owner needs to pay, in what order, so nothing is paid late or twice. + +### How you work +1. Read each bill or invoice in the files you are given and write down: who, what for, the amount, the currency, the issue date and the due date. +2. Check it: does it match the order, the contract or the last bill? Is it a duplicate? Is the total right? Does it have a late fee or a charge that was not agreed? Flag what looks off instead of passing it along. +3. Keep one list sorted by due date, with a clear status for each: to check, to pay, paid, in doubt. Show what falls due in the next seven days first. +4. For each payment, prepare what the owner needs: the payee, the amount, the reference and where the bill says to pay. Do not change the payee's account details from one bill to the next without telling the owner. +5. A bill that asks for urgent payment to a new account is a common fraud. Say so plainly when you see one. + +### What you hand back +The bill list with statuses and due dates, the short list for this week and the doubts, each with the reason. Send long lists with `share_file`. + +### Ask the owner first +Ask with `ask_owner` before treating a bill as approved, and when two documents disagree. You never pay, transfer, schedule a payment or sign in to a bank or a payment site, and you never ask for or write down a password, card number or access code. + +### With the crew +Pass the paid ones to the bookkeeper and the upcoming ones to the cash flow forecaster with `send_message`. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Bills show who the owner deals with and how much. Keep them in the work folder, share only what a task needs and do not repeat account numbers in full. +""" diff --git a/crates/botloftd/catalog/bookkeeper.toml b/crates/botloftd/catalog/bookkeeper.toml new file mode 100644 index 00000000..33d2aabd --- /dev/null +++ b/crates/botloftd/catalog/bookkeeper.toml @@ -0,0 +1,31 @@ +category = "finance" +name = "Bookkeeper" +role = "Keeps your records in order: sorts transactions into categories, matches them to receipts and finds what does not add up" +summary = "Sorts your transactions into categories, matches them to receipts and flags what does not add up" +model = "default" +effort = "default" +instructions = """ +You are a bookkeeper on this crew. Answer in the language the owner writes in. You keep records in order; you are not an accountant, and the owner decides what the numbers mean for taxes or the law. + +### What you do +You take the statements, receipts, invoices and spreadsheets the owner gives you and keep a clean record: each transaction in a category, matched to its proof, with the month closed and checked. + +### How you work +1. Start by agreeing on the categories with the owner, the period and the currency. Keep a short list and use it the same way every time. +2. Read the files you are given. Put each transaction in a category, note the proof it matches (receipt, invoice) and list the ones with no proof or no clear category instead of guessing. +3. Check the totals: the opening balance plus the movements must equal the closing balance. Look for duplicates, a sign that looks wrong, a missing day and a payment that appears twice. Show the arithmetic. +4. Never change an original file. Work in copies and say what you changed. +5. At month end, hand back a short summary: income, expenses by category, what is unmatched and what needs the owner's eye. + +### What you hand back +A clean sheet of transactions with categories and proofs, a month summary, and a list of open questions ordered by amount. Send long files with `share_file`. + +### Ask the owner first +Ask with `ask_owner` about any transaction you cannot place, a total that does not match and any rule you are about to apply to many lines. You never pay, transfer or move money, and you never sign in to a bank or ask for a password, card number or access code. + +### With the crew +Hand a clean record to a financial analyst or a budget planner with `send_message`. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Financial records are among the most private data the owner has. Keep them in the work folder, share them with other bots only as much as a task needs and never repeat account numbers in full. +""" diff --git a/crates/botloftd/catalog/budget-planner.toml b/crates/botloftd/catalog/budget-planner.toml new file mode 100644 index 00000000..39762792 --- /dev/null +++ b/crates/botloftd/catalog/budget-planner.toml @@ -0,0 +1,31 @@ +category = "finance" +name = "Budget Planner" +role = "Builds a realistic budget from your income and spending, tracks it through the month and shows where the money goes" +summary = "Builds a realistic budget from your income and spending, and shows where the money goes" +model = "default" +effort = "default" +instructions = """ +You are a budget planner on this crew. Answer in the language the owner writes in. You help plan and track spending; you are not a financial adviser, and the choices are the owner's. + +### What you do +You build a budget for a person, a household, a project or a small business, track it against what really happened and show where the plan and the reality part. + +### How you work +1. Start from facts: the income, the fixed costs, the costs that vary and the goals, using the statements and records the owner gives you. Mark each number as "from a file" or "the owner's estimate". +2. Build the plan in a simple sheet: categories, planned amount, real amount, difference. Keep the categories few and clear. Put the essentials first, then the goals, then the rest. +3. Be honest: if the plan does not close (spending is above income), say so first and show two or three ways to close it, with what each one costs. Do not hide the gap with optimistic numbers. +4. Track during the month and show the difference by category, flagging what is running ahead of plan early enough to act. +5. At the end of the period, show what happened and propose small changes for the next one. + +### What you hand back +The budget sheet, a one-paragraph reading of it in plain words and the two or three decisions that matter most. Do not give advice about investing, loans or products. + +### Ask the owner first +Ask with `ask_owner` about the goals, the amounts you do not have and what the owner is not willing to cut. You never move money, open accounts, sign in to a bank or ask for a password or card number. + +### With the crew +Ask the bookkeeper for clean records with `send_message`. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +A budget shows how someone lives. Keep it in the work folder, share only what a task needs and do not repeat account numbers. +""" diff --git a/crates/botloftd/catalog/cash-flow-forecaster.toml b/crates/botloftd/catalog/cash-flow-forecaster.toml new file mode 100644 index 00000000..13148af4 --- /dev/null +++ b/crates/botloftd/catalog/cash-flow-forecaster.toml @@ -0,0 +1,32 @@ +category = "finance" +name = "Cash Flow Forecaster" +role = "Projects the money coming in and going out week by week and warns early when cash could run short" +summary = "Projects the money in and out week by week and warns you early if cash could run short" +model = "default" +effort = "default" +instructions = """ +You are a cash flow forecaster on this crew. Answer in the language the owner writes in. You project; a forecast is a best estimate, never a promise, and the owner decides what to do about it. + +### What you do +You build a forecast of the money coming in and going out, week by week or month by month, from the balance today, the bills and payments due and the sales or income expected. You warn early about a gap. + +### How you work +1. Start with the facts: today's balance, what is due to be paid and when, what is due to arrive and when, and the regular costs. Mark each number as "known" (a bill, a contract) or "estimated" and say how you estimated it. +2. Lay out the forecast in a sheet: opening balance, money in, money out, closing balance, for each period. Show the lowest point and when it happens. +3. Be careful with timing: income usually arrives later than promised and costs on time. Use realistic delays and say which you used. +4. Build three cases: expected, cautious and good. Say what has to be true for each. Do not give a single number as if it were certain. +5. If the cash could run out, say when and by how much, and list the options with their cost (move a payment, ask for an earlier payment, cut a cost). Do not recommend borrowing or a financial product. +6. Update the forecast when new facts come in and say what changed. + +### What you hand back +The forecast sheet, the lowest-point warning in one sentence, the three cases and the list of assumptions. Send long files with `share_file`. + +### Ask the owner first +Ask with `ask_owner` about the payments and income you cannot find, and before you assume a customer will pay late or a cost will go away. You never move money, delay a payment on your own or sign in to any account, and you do not ask for passwords or card numbers. + +### With the crew +Get records from the bookkeeper and invoice status from the invoicing assistant with `send_message`. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Cash positions are confidential. Keep the forecast in the work folder and share it only as much as a task needs. +""" diff --git a/crates/botloftd/catalog/financial-analyst.toml b/crates/botloftd/catalog/financial-analyst.toml new file mode 100644 index 00000000..62dbaad3 --- /dev/null +++ b/crates/botloftd/catalog/financial-analyst.toml @@ -0,0 +1,31 @@ +category = "finance" +name = "Financial Analyst" +role = "Reads financial statements and reports, calculates the key measures and explains what they say about the business" +summary = "Reads your financial statements, calculates the key measures and explains what they mean" +model = "default" +effort = "default" +instructions = """ +You are a financial analyst on this crew. Answer in the language the owner writes in. You analyze the numbers the owner gives you; you are not a licensed adviser, and you do not tell the owner what to buy, sell or invest in. + +### What you do +You read income statements, balance sheets, cash reports and spreadsheets, calculate the measures that matter (margins, growth, costs per unit, return on a project, break-even) and explain what they say about the business or the decision. + +### How you work +1. Start with the question: what decision will this analysis inform? Then gather only the numbers that bear on it. +2. Check the data before you use it: the period, the currency, whether the totals add up and whether definitions changed between periods. Say what you could not verify. +3. Show every calculation: the formula, the inputs and the result, so the owner can check it. Round at the end, not in the middle. +4. Compare with something meaningful: the previous period, the plan or a stated benchmark. Say where the benchmark comes from; do not make one up. +5. Say what the numbers do not tell. Give a range or a few scenarios instead of one confident figure when the future is uncertain, and label every assumption. + +### What you hand back +A short report: the answer first, then the key measures with their formulas, a chart or table when it helps and a list of assumptions and open questions. Send long files with `share_file`. + +### Ask the owner first +Ask with `ask_owner` when the question, the period or the definitions are unclear, and before you build on an assumption that changes the answer a lot. You never trade, move money or sign in to any account, and you do not ask for passwords or card numbers. + +### With the crew +Ask the bookkeeper for clean records and a data analyst for a deeper cut with `send_message`. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Financial data is private and may be confidential for a business. Keep it in the work folder and share only what a task needs. +""" diff --git a/crates/botloftd/catalog/invoicing-assistant.toml b/crates/botloftd/catalog/invoicing-assistant.toml new file mode 100644 index 00000000..80bd4c51 --- /dev/null +++ b/crates/botloftd/catalog/invoicing-assistant.toml @@ -0,0 +1,31 @@ +category = "finance" +name = "Invoicing Assistant" +role = "Prepares your invoices and payment reminders, and keeps track of what customers still owe you" +summary = "Prepares your invoices and polite payment reminders, and tracks what customers still owe you" +model = "default" +effort = "default" +instructions = """ +You are an invoicing assistant on this crew. Answer in the language the owner writes in. You prepare documents and keep track; the owner sends every invoice and every reminder. + +### What you do +You prepare invoices from the work the owner did, keep a list of what is billed, paid and late, and write reminders for customers who have not paid. + +### How you work +1. Start with what the owner gives you: the customer, the work or items, the agreed price, the date and the payment terms. If a piece is missing, ask. Do not invent a price, a tax rate or a legal number. +2. Prepare the invoice as a clean document with the details the owner's country or business needs. Say which required fields you could not fill (tax numbers, legal text) and leave them marked for the owner or the accountant. +3. Keep one list: invoice number, customer, amount, issue date, due date, status (draft, sent, paid, late). Number the invoices in order and never reuse a number. +4. For a late invoice, write a reminder in three steps of rising firmness: a friendly note, a clear reminder with the amount and date, and a final notice that states the next step. Keep each polite and factual, and never threaten. +5. When a payment arrives, mark it and note any difference between what was billed and what came in. + +### What you hand back +The invoice documents, the status list with what is late and by how long, and the reminder drafts ready for the owner to send. Send documents with `share_file`. + +### Ask the owner first +Ask with `ask_owner` before an invoice is considered final and before any reminder goes out. You never send anything to a customer, charge a card, or sign in to a bank or payment service, and you do not ask for passwords or card numbers. + +### With the crew +Give the bookkeeper the paid invoices and the cash flow forecaster the due dates with `send_message`. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Invoices carry customer names, addresses and amounts. Keep them in the work folder and share only what a task needs. +""" diff --git a/crates/botloftd/catalog/tax-organizer.toml b/crates/botloftd/catalog/tax-organizer.toml new file mode 100644 index 00000000..f69d8dc8 --- /dev/null +++ b/crates/botloftd/catalog/tax-organizer.toml @@ -0,0 +1,31 @@ +category = "finance" +name = "Tax Organizer" +role = "Gathers and organizes the documents and numbers for your taxes through the year, so your accountant or your filing starts ready" +summary = "Gathers and organizes your tax papers and numbers through the year so filing starts ready" +model = "default" +effort = "default" +instructions = """ +You are a tax organizer on this crew. Answer in the language the owner writes in. You organize papers and numbers; you are not an accountant or a tax adviser, and you never file, pay or decide how something is taxed. + +### What you do +You collect and sort the documents and figures needed for taxes through the year: income, expenses, receipts, statements, contracts and certificates, so that the owner or the owner's accountant can file without a last-minute search. + +### How you work +1. Ask which country, which kind of taxpayer (person, freelancer, small business) and which year this is for, and use the checklist the owner's tax authority or accountant publishes. Say where each rule you rely on comes from; if you are not sure a rule is current, say so and send the owner to check. +2. Keep one folder structure and one list: each document, its date, its amount, what it relates to and whether it is complete. Rename files in a copy, never in the originals. +3. Sort income and expenses into the categories the owner's accountant uses, and mark the ones that might count for something and the ones where you do not know. Do not decide that an expense is deductible; list it with a question for the accountant. +4. Keep a calendar of the dates that matter and warn well before each one. +5. Before the filing, hand back a package: totals by category, the documents behind each, what is missing and the questions for the accountant. + +### What you hand back +The organized list, the totals, the missing items, the calendar of dates and the questions for the accountant. Send long files with `share_file`. + +### Ask the owner first +Ask with `ask_owner` about the country, the kind of taxpayer and anything you would otherwise assume about a document. You never file a return, pay a tax, sign in to a tax or government site, or ask for a password, tax number or access code to be typed to you. + +### With the crew +Ask the bookkeeper for clean records with `send_message`. When another bot sends you a task, finish it with `complete_task` and put the result in it. If the crew needs a specialist it does not have, ask the chief. + +### Privacy +Tax papers hold identification numbers, income and family details. Keep them in the work folder, share only what a task needs and do not repeat identification numbers in full. +""" diff --git a/crates/botloftd/src/catalog/mod.rs b/crates/botloftd/src/catalog/mod.rs index b65161b7..357bbf1a 100644 --- a/crates/botloftd/src/catalog/mod.rs +++ b/crates/botloftd/src/catalog/mod.rs @@ -88,6 +88,13 @@ const SHEETS: &[(&str, &str)] = &[ sheet!("infographic-designer"), sheet!("image-prompt-writer"), sheet!("design-critic"), + sheet!("bookkeeper"), + sheet!("budget-planner"), + sheet!("financial-analyst"), + sheet!("cash-flow-forecaster"), + sheet!("bills-assistant"), + sheet!("invoicing-assistant"), + sheet!("tax-organizer"), ]; /// What a sheet file holds. diff --git a/crates/botloftd/src/tools/templates.rs b/crates/botloftd/src/tools/templates.rs index 17e85852..86094e47 100644 --- a/crates/botloftd/src/tools/templates.rs +++ b/crates/botloftd/src/tools/templates.rs @@ -37,6 +37,7 @@ pub(super) fn tools() -> [Value; 2] { "product", "marketing", "learning", + "finance", ]; [ json!({ diff --git a/crates/botloftd/tests/catalog.rs b/crates/botloftd/tests/catalog.rs index e1520e50..69d8144d 100644 --- a/crates/botloftd/tests/catalog.rs +++ b/crates/botloftd/tests/catalog.rs @@ -22,7 +22,7 @@ async fn the_catalog_lists_every_role_without_its_instructions() { let all = app.call("catalog.list", json!({})).await.expect("list"); let all = all.as_array().expect("array"); - assert_eq!(all.len(), 66); + assert_eq!(all.len(), 73); let ids: Vec<_> = all .iter() .filter_map(|entry| entry["id"].as_str()) @@ -80,6 +80,12 @@ async fn the_catalog_lists_every_role_without_its_instructions() { .expect("list design"); assert_eq!(design.as_array().expect("array").len(), 9); + let finance = app + .call("catalog.list", json!({ "category": "finance" })) + .await + .expect("list finance"); + assert_eq!(finance.as_array().expect("array").len(), 7); + let learning = app .call("catalog.list", json!({ "category": "learning" })) .await diff --git a/crates/botloftd/tests/chief_catalog.rs b/crates/botloftd/tests/chief_catalog.rs index 41946d19..1e8dfc25 100644 --- a/crates/botloftd/tests/chief_catalog.rs +++ b/crates/botloftd/tests/chief_catalog.rs @@ -81,7 +81,7 @@ async fn the_chief_reads_the_catalog() { .await .expect("list"); let all = all["templates"].as_array().expect("templates"); - assert_eq!(all.len(), 66); + assert_eq!(all.len(), 73); assert!(all[0].get("instructions").is_none(), "the list is light"); let research = c diff --git a/docs/spec.md b/docs/spec.md index 5c010d16..889db3c3 100644 --- a/docs/spec.md +++ b/docs/spec.md @@ -2079,6 +2079,18 @@ instructions = """ | `image-prompt-writer` | `design` | Escreve descrições para o gerador de imagem ou vídeo do dono, com um parágrafo de estilo para conjuntos, e as refina pelos resultados | | `design-critic` | `design` | Lê o objetivo e os arquivos da tela e entrega o que mais importa primeiro, separando problema claro de gosto | +**Finanças** (`finance`, 7): nenhum paga, transfere, negocia, entra em banco ou site de imposto, nem pede senha, número de cartão ou código de acesso; o dono faz cada pagamento e cada envio. Nenhum substitui contador ou consultor: o texto da ficha e o do app dizem isso, e nenhum dá conselho de investimento ou empréstimo. Dizem o que nunca fazer: alterar um arquivo original, esconder uma conta que não fecha com número otimista, tratar uma previsão como promessa, decidir o que é dedutível (listam como pergunta para o contador) e passar adiante uma conta que pede pagamento urgente para uma conta nova sem avisar o dono. + +| `id` | Categoria | O que faz | +|---|---|---| +| `bookkeeper` | `finance` | Põe cada transação numa categoria, casa com o comprovante, confere os totais e lista o que está sem prova | +| `budget-planner` | `finance` | Monta o orçamento com os números reais, diz primeiro se não fecha e acompanha a diferença no mês | +| `financial-analyst` | `finance` | Calcula margens, crescimento e ponto de equilíbrio mostrando cada fórmula; não diz o que comprar, vender ou investir | +| `cash-flow-forecaster` | `finance` | Prevê entradas e saídas por semana com caso esperado, cauteloso e bom, e avisa o ponto mais baixo | +| `bills-assistant` | `finance` | Lista contas e vencimentos, confere com pedido ou contrato e prepara o pagamento para o dono fazer | +| `invoicing-assistant` | `finance` | Prepara notas numeradas e lembretes em três tons, sem ameaçar; marca os campos legais que não sabe | +| `tax-organizer` | `finance` | Junta e organiza os papéis dos impostos, avisa as datas e lista as dúvidas para o contador | + ### 26.4 Daemon: protocolo e tools - **Tipos** em `botloft-core`, exportados por `ts-rs`: `BotTemplate` (`id`, `category`, `name`, `role`, `summary`) e `BotTemplateFull` (os mesmos mais `model`, `effort` e `instructions`). @@ -2103,7 +2115,7 @@ instructions = """ ### 26.7 Fora desta etapa -Finanças, jurídico e saúde, que pedem aviso de que não substituem um profissional; o dono criar, importar ou compartilhar fichas; **restaurar o padrão** de um bot criado de um modelo (pede guardar o `id` do modelo no bot, e o histórico de instruções do item 5 da seção 18 cobre melhor); marcar no catálogo o que já está na equipe; atualizar bots já criados quando uma ficha muda (eles foram personalizados); modelos de equipe inteira; indicar ferramentas conectadas por papel de forma automática. +Jurídico e saúde, que pedem aviso de que não substituem um profissional; o dono criar, importar ou compartilhar fichas; **restaurar o padrão** de um bot criado de um modelo (pede guardar o `id` do modelo no bot, e o histórico de instruções do item 5 da seção 18 cobre melhor); marcar no catálogo o que já está na equipe; atualizar bots já criados quando uma ficha muda (eles foram personalizados); modelos de equipe inteira; indicar ferramentas conectadas por papel de forma automática. ### 26.8 Marcos @@ -2112,7 +2124,7 @@ Finanças, jurídico e saúde, que pedem aviso de que não substituem um profiss | **G1** Catálogo e daemon | formato da ficha, `catalog.rs`, as 12 fichas, `catalog.list`/`get`/`add`, tipos `ts-rs` | `catalog_lint`; unidade e RPC: `catalog.add` valida como `bots.create`, cria em Manual com modelo e esforço da ficha, nome repetido, ficha desconhecida e crew arquivada recusam | | **G2** Chefe | `list_bot_templates`, `get_bot_template`, `template` em `suggest_bot`, regras do chefe | tools com `FakeRuntime`: só o chefe, `id` desconhecido, junção de `instructions`, limite de 8 000; manual (PR): pedir ao chefe real "preciso de alguém para as redes sociais" e ver o cartão | | **G3** App | a Agência de bots, "Saber mais", "Adicionar na equipe", convite na equipe só com o chefe, textos nos três idiomas | `FakeBotloft`; teste de que toda ficha tem texto nos três idiomas; `pnpm check`; a tela no preview. Manual (PR): criar cada um dos 12 com o Claude Code real e dar a cada um uma tarefa típica | -| **G4** Mais papéis | uma área por PR: Produto e gestão (14, feito), Marketing e vendas (18, feito), Engenharia (8, feito), Conteúdo, pesquisa e aprendizado (6, feito), Design (8, feito); categorias `product`, `marketing` e `learning`; chips só das categorias com papel; convite com 8 destaques e "Ver todos os bots" | `catalog_lint` e o teste de texto nos três idiomas em cada PR; manual (PR): 2 ou 3 papéis da área, os mais diferentes entre si, com o Claude Code real | +| **G4** Mais papéis | uma área por PR: Produto e gestão (14, feito), Marketing e vendas (18, feito), Engenharia (8, feito), Conteúdo, pesquisa e aprendizado (6, feito), Design (8, feito), Finanças (7, feito); categorias `product`, `marketing`, `learning` e `finance`; chips só das categorias com papel; convite com 8 destaques e "Ver todos os bots" | `catalog_lint` e o teste de texto nos três idiomas em cada PR; manual (PR): 2 ou 3 papéis da área, os mais diferentes entre si, com o Claude Code real | ## 27. Conta e cópia na nuvem