@softize/opus 11.1.0 → 12.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +59 -1
- package/README.md +31 -1
- package/bin/cli.mjs +97 -27
- package/bin/lib/check.mjs +55 -43
- package/bin/lib/copy.mjs +2202 -0
- package/bin/lib/create.mjs +227 -39
- package/bin/lib/db-migrate-runner.mjs +9 -6
- package/bin/lib/db-project-path.mjs +20 -0
- package/bin/lib/db-scaffold-runner.mjs +23 -8
- package/bin/lib/db.mjs +6 -4
- package/bin/lib/gen.mjs +60 -29
- package/bin/lib/init.mjs +212 -56
- package/bin/lib/introspect.mjs +3 -2
- package/bin/lib/materialize.mjs +623 -97
- package/bin/lib/postinstall.mjs +6 -5
- package/bin/lib/validate-skill.mjs +502 -30
- package/docs/code-style.md +142 -7
- package/docs/consumer-upgrade-propagation.md +4 -3
- package/docs/releasing.md +28 -17
- package/package.json +6 -1
- package/registry/git/pre-push.d/00-opus-copy +14 -0
- package/registry/git/pre-push.d/opus +7 -21
- package/registry/git/run-opus-pre-push.mjs +141 -0
- package/registry/hooks/opus-check-on-stop.mjs +13 -31
- package/registry/instructions/opus.md +11 -5
- package/registry/skills/build-opus-ui/SKILL.md +5 -4
- package/registry/skills/create-opus-action/SKILL.md +4 -4
- package/registry/skills/implement-opus-change/SKILL.md +7 -5
- package/registry/skills/upgrade-opus/SKILL.md +8 -4
- package/registry/skills/upgrade-opus/references/upgrade-checklist.md +4 -1
- package/registry/templates/app/package.json +4 -0
- package/registry/templates/app/pnpm-workspace.yaml +3 -2
- package/registry/templates/app/src/domains/tasks/actions/list.ts +1 -1
- package/registry/templates/monorepo/pnpm-workspace.yaml +3 -1
- package/src/ui/docs/DocBrowser.tsx +10 -2
- package/src/ui/docs/content/cli.md +8 -7
- package/src/ui/docs/content/communication.md +83 -0
- package/src/ui/docs/content/getting-started.md +29 -16
- package/src/ui/docs/registry.tsx +2 -2
- package/registry/skills/write-product-communication/SKILL.md +0 -28
- package/registry/skills/write-product-communication/agents/openai.yaml +0 -4
- package/registry/templates/app/_npmrc +0 -1
- package/registry/templates/monorepo/_npmrc +0 -1
- package/src/ui/docs/content/microcopy.md +0 -130
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
name: create-opus-action
|
|
3
3
|
description: Cria uma action Opus no split canônico de defineContract e bindAction, incluindo registro e validação. Use ao adicionar endpoint, comando, consulta ou operação de domínio em projeto baseado no Opus.
|
|
4
4
|
---
|
|
5
|
+
<!-- softize-skill-route: $test-opus-action -->
|
|
5
6
|
|
|
6
7
|
# Criar action Opus
|
|
7
8
|
|
|
@@ -21,16 +22,15 @@ registrados no runtime do projeto.
|
|
|
21
22
|
1. Rodar `node scripts/scaffold.mjs <resource> <verb> <kind>` a partir desta skill.
|
|
22
23
|
2. Colocar o contrato em módulo importável pelos consumidores e o binding no lado servidor.
|
|
23
24
|
3. Substituir os exemplos do scaffold por schemas, descrições e comportamento do domínio.
|
|
24
|
-
Usar `write-product-communication` nas descrições, mensagens e textos projetados para UI
|
|
25
|
-
ou documentação.
|
|
26
25
|
4. Declarar `requires` somente com `authorize` efetivo; `requires` sozinho não protege a action.
|
|
27
26
|
5. Exportar e registrar o binding no domínio/runtime existente.
|
|
28
|
-
6.
|
|
27
|
+
6. Carregar e seguir `$test-opus-action` para cobrir contrato, sucesso, erros e efeitos relevantes.
|
|
29
28
|
|
|
30
29
|
## Verificação
|
|
31
30
|
|
|
32
31
|
Rodar `opus check <escopo>`, typecheck e testes do domínio. Se o projeto gera manifest,
|
|
33
|
-
OpenAPI ou docs, regenerar e conferir o diff.
|
|
32
|
+
OpenAPI ou docs, regenerar e conferir o diff. Regenerar também o inventário com `opus copy`
|
|
33
|
+
e executar `base copy check` quando o contrato declarar texto humano.
|
|
34
34
|
|
|
35
35
|
## Limites
|
|
36
36
|
|
|
@@ -2,6 +2,9 @@
|
|
|
2
2
|
name: implement-opus-change
|
|
3
3
|
description: Implementa uma mudança em projeto baseado no Opus preservando contrato, binding, registro e projeções. Use ao alterar domínio, action, runtime ou integração que utilize @softize/opus.
|
|
4
4
|
---
|
|
5
|
+
<!-- softize-skill-route: $create-opus-action -->
|
|
6
|
+
<!-- softize-skill-route: $test-opus-action -->
|
|
7
|
+
<!-- softize-skill-route: $build-opus-ui -->
|
|
5
8
|
|
|
6
9
|
# Implementar mudança Opus
|
|
7
10
|
|
|
@@ -22,16 +25,15 @@ dependências server-only, bindings registrados, testes e gates verdes.
|
|
|
22
25
|
2. Modelar primeiro o contrato observável: nome, descrição, input, output, erros e metadata.
|
|
23
26
|
3. Manter código compartilhável fora de banco, segredo, filesystem e drivers server-only.
|
|
24
27
|
4. Implementar o binding e registrar o `ActionDef` no domínio/runtime conforme a topologia local.
|
|
25
|
-
5.
|
|
26
|
-
nesses workflows especializados.
|
|
28
|
+
5. Carregar e seguir `$create-opus-action`, `$test-opus-action` ou `$build-opus-ui` antes
|
|
29
|
+
do passo correspondente quando a mudança entrar nesses workflows especializados.
|
|
27
30
|
6. Atualizar manifest, docs geradas e exemplos somente pelos comandos do repo.
|
|
28
|
-
7. Usar `write-product-communication` sempre que a mudança alcançar documentação, UI, CLI,
|
|
29
|
-
mensagens de erro ou outro texto destinado a uma pessoa.
|
|
30
31
|
|
|
31
32
|
## Verificação
|
|
32
33
|
|
|
33
34
|
Rodar `opus check` no escopo correto, testes afetados, typecheck e os geradores que o
|
|
34
|
-
projeto declara.
|
|
35
|
+
projeto declara. Se o contrato mudou texto humano, regenerar com `opus copy` e executar
|
|
36
|
+
`opus copy --check` seguido de `base copy check`. Conferir o diff gerado antes do handoff.
|
|
35
37
|
|
|
36
38
|
## Limites
|
|
37
39
|
|
|
@@ -15,12 +15,16 @@ materializados e projeções geradas consistentes no mesmo diff.
|
|
|
15
15
|
1. Registrar versão atual e alvo e ler todas as entradas intermediárias do `CHANGELOG.md`,
|
|
16
16
|
priorizando seções Breaking e instruções de migração.
|
|
17
17
|
2. Atualizar a dependência com o package manager do repo.
|
|
18
|
-
3. Executar `
|
|
18
|
+
3. Executar o script do projeto (`pnpm run setup` ou, no monorepo,
|
|
19
|
+
`pnpm --filter <workspace> run setup`) para materializar Base e Opus na ordem declarada.
|
|
20
|
+
`pnpm setup` sem `run` continua reservado ao setup da própria máquina.
|
|
19
21
|
4. Aplicar migrações no código por domínio, sem compatibilidade temporária silenciosa.
|
|
20
22
|
5. Rodar `opus check`, typecheck, testes, build e geradores declarados pelo projeto.
|
|
21
|
-
6.
|
|
22
|
-
|
|
23
|
-
|
|
23
|
+
6. Remover configuração obsoleta da registry privada: o setup limpa a diretiva conhecida
|
|
24
|
+
no `.npmrc` do projeto; diagnosticar também `pnpm config get @softize:registry --global`
|
|
25
|
+
e, se apontar para `registry.softize.com.br`, executar
|
|
26
|
+
`pnpm config delete @softize:registry --global` com autorização do dono da máquina.
|
|
27
|
+
7. Conferir `base.json`, lockfile, skills, hooks, instruções e outputs gerados no diff.
|
|
24
28
|
|
|
25
29
|
## Verificação
|
|
26
30
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
# Checklist de upgrade
|
|
2
2
|
|
|
3
3
|
- versão alvo presente em `package.json`, lockfile, `base.json` e `opus.json` aplicáveis;
|
|
4
|
-
- `
|
|
4
|
+
- `pnpm run setup` (ou `pnpm --filter <workspace> run setup`) e `opus check` verdes;
|
|
5
|
+
- `.npmrc` do projeto sem `@softize:registry=...registry.softize.com.br` e configuração
|
|
6
|
+
global antiga removida com autorização explícita;
|
|
7
|
+
- `opus copy --check` e `base copy check` verdes quando o inventário estiver configurado;
|
|
5
8
|
- breakings intermediários tratados;
|
|
6
9
|
- typecheck, testes e build verdes;
|
|
7
10
|
- manifest, OpenAPI e docs regenerados quando configurados;
|
|
@@ -3,6 +3,7 @@
|
|
|
3
3
|
"private": true,
|
|
4
4
|
"type": "module",
|
|
5
5
|
"scripts": {
|
|
6
|
+
"setup": "opus setup && base setup",
|
|
6
7
|
"dev": "vite",
|
|
7
8
|
"dev:design": "vite --mode design --configLoader runner",
|
|
8
9
|
"build": "tsc --noEmit && vite build",
|
|
@@ -11,6 +12,8 @@
|
|
|
11
12
|
"test": "vitest run",
|
|
12
13
|
"format": "prettier --write src",
|
|
13
14
|
"format:check": "prettier --check src",
|
|
15
|
+
"copy": "opus copy",
|
|
16
|
+
"copy:check": "opus copy --check && base copy check",
|
|
14
17
|
"manifest": "opus gen",
|
|
15
18
|
"manifest:check": "opus gen && git diff --exit-code .opus/manifest.json"
|
|
16
19
|
},
|
|
@@ -27,6 +30,7 @@
|
|
|
27
30
|
"zod": "^3.24.0"
|
|
28
31
|
},
|
|
29
32
|
"devDependencies": {
|
|
33
|
+
"@softize/base": "^2.0.0",
|
|
30
34
|
"@tailwindcss/vite": "^4.1.0",
|
|
31
35
|
"@types/node": "^22.0.0",
|
|
32
36
|
"@types/react": "^19.0.0",
|
|
@@ -5,7 +5,8 @@ allowBuilds:
|
|
|
5
5
|
'@softize/opus': true
|
|
6
6
|
esbuild: true
|
|
7
7
|
|
|
8
|
-
#
|
|
9
|
-
#
|
|
8
|
+
# Opus e Base são publicados juntos no npm público: os dois ficam fora da quarentena
|
|
9
|
+
# para que um rollout recém-publicado não combine protocolo novo com política antiga.
|
|
10
10
|
minimumReleaseAgeExclude:
|
|
11
11
|
- '@softize/opus'
|
|
12
|
+
- '@softize/base'
|
|
@@ -24,7 +24,7 @@ export const taskList = defineContract({
|
|
|
24
24
|
|
|
25
25
|
// Fixture em memória — o domínio-exemplo não tem banco; troque pelo seu repositório.
|
|
26
26
|
const TASKS = [
|
|
27
|
-
{ id: '1', title: 'Conhecer
|
|
27
|
+
{ id: '1', title: 'Conhecer o Opus.', done: true },
|
|
28
28
|
{ id: '2', title: 'Modelar o primeiro domínio real.', done: false },
|
|
29
29
|
]
|
|
30
30
|
|
|
@@ -9,6 +9,8 @@ allowBuilds:
|
|
|
9
9
|
'@softize/opus': true
|
|
10
10
|
esbuild: true
|
|
11
11
|
|
|
12
|
-
#
|
|
12
|
+
# Opus e Base são publicados juntos no npm público; não deixe a quarentena montar uma
|
|
13
|
+
# combinação de versões que nunca passou pelos gates da release.
|
|
13
14
|
minimumReleaseAgeExclude:
|
|
14
15
|
- '@softize/opus'
|
|
16
|
+
- '@softize/base'
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* DocBrowser — a VERDADE VISUAL da casa, como doc completa. Seção multi-página: conceitos
|
|
3
|
-
* (Introdução, Tokens & Tema,
|
|
3
|
+
* (Introdução, Tokens & Tema, Comunicação, Customização) + uma página por componente do
|
|
4
4
|
* opus/ui, agrupados por seção. O que você vê aqui é o que os apps entregam (o site
|
|
5
5
|
* do shadcn é catálogo do que existe; a expectativa visual nasce aqui).
|
|
6
6
|
*
|
|
@@ -35,6 +35,8 @@ export interface DocBrowserProps {
|
|
|
35
35
|
path?: string
|
|
36
36
|
/** Seções a exibir (seção → grupo → página). Default = catálogo inteiro. */
|
|
37
37
|
sections?: DocSection[]
|
|
38
|
+
/** Slugs antigos que devem abrir e substituir a URL pela página canônica. */
|
|
39
|
+
redirects?: Readonly<Record<string, string>>
|
|
38
40
|
/** Monta o `document.title` a partir do título da página atual (ex.: `(t) => `${t} · Opus``).
|
|
39
41
|
* Ausente = não mexe no title. */
|
|
40
42
|
documentTitle?: (pageTitle: string) => string
|
|
@@ -44,6 +46,7 @@ export function DocBrowser({
|
|
|
44
46
|
basePath = '/docs',
|
|
45
47
|
path: controlledPath,
|
|
46
48
|
sections = DOC_SECTIONS,
|
|
49
|
+
redirects = {},
|
|
47
50
|
documentTitle,
|
|
48
51
|
}: DocBrowserProps): React.ReactElement {
|
|
49
52
|
// Standalone: o path vem do router da casa (`usePathname` — pathname É o estado).
|
|
@@ -56,13 +59,18 @@ export function DocBrowser({
|
|
|
56
59
|
// Slug = TODOS os segmentos após o basePath, unidos (rota aninhada: `/docs/guias/deploy`
|
|
57
60
|
// → `guias/deploy`). Slug flat de 1 segmento continua igual (`join` de 1 elemento = ele).
|
|
58
61
|
const rel = path.startsWith(basePath) ? path.slice(basePath.length) : ''
|
|
59
|
-
const
|
|
62
|
+
const requestedSlug = rel.split('/').filter(Boolean).join('/') || defaultSlug
|
|
63
|
+
const slug = redirects[requestedSlug] ?? requestedSlug
|
|
60
64
|
const page = findPage(sections, slug) ?? findPage(sections, defaultSlug)
|
|
61
65
|
|
|
62
66
|
// `navigate` emite `popstate`, então o host é notificado nos dois modos — inclusive o
|
|
63
67
|
// que ainda escuta o evento na unha, que era como este componente avisava antes.
|
|
64
68
|
const go = (to: string): void => navigate(to)
|
|
65
69
|
|
|
70
|
+
useEffect(() => {
|
|
71
|
+
if (requestedSlug !== slug) navigate(`${basePath}/${slug}`, { replace: true })
|
|
72
|
+
}, [basePath, requestedSlug, slug])
|
|
73
|
+
|
|
66
74
|
// O title da aba acompanha a página atual (quando o host fornece o formato).
|
|
67
75
|
useEffect(() => {
|
|
68
76
|
if (page && documentTitle) document.title = documentTitle(page.title)
|
|
@@ -32,20 +32,21 @@ opus introspect --json
|
|
|
32
32
|
## Bootstrap e templates
|
|
33
33
|
|
|
34
34
|
> `create` scaffolda um app novo com os pré-requisitos plugados; `setup` é per-app
|
|
35
|
-
> (idempotente, nunca sobrescreve o seu); `add` copia um template do
|
|
35
|
+
> (idempotente, nunca sobrescreve o seu); `add` copia um template do catálogo empacotado.
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
opus create meu-app # app canônico do zero: protocolo + UI + preview +
|
|
38
|
+
opus create meu-app # app canônico do zero: protocolo + UI + preview + automação
|
|
39
39
|
opus create meu-cliente --monorepo # a RAIZ de um workspace (apps/* + packages/*)
|
|
40
40
|
opus create apps/portal # dentro de um workspace: só o app (modo detectado)
|
|
41
|
-
opus setup # grava opus.json
|
|
41
|
+
opus setup # grava opus.json e materializa a camada específica do SDK
|
|
42
42
|
opus list # lista os templates disponíveis
|
|
43
|
-
opus add action-form # copia um template do
|
|
43
|
+
opus add action-form # copia um template do catálogo pro projeto
|
|
44
44
|
```
|
|
45
45
|
|
|
46
46
|
O esqueleto do `create` versiona com o Opus (sai do mesmo pacote que o SDK que ele
|
|
47
|
-
configura) e nasce com os gates verdes: domínio-exemplo canônico, teste, manifest
|
|
48
|
-
|
|
47
|
+
configura) e nasce com os gates verdes: domínio-exemplo canônico, teste, manifest e o dev
|
|
48
|
+
server pronto pro preview do Maestro. O método geral, a memória e a revisão vêm da Base
|
|
49
|
+
depois de `pnpm run setup`. Dois modos, por detecção:
|
|
49
50
|
repo standalone (template inteiro) ou **app em monorepo** (dentro de um workspace pnpm:
|
|
50
51
|
só os arquivos do app; o que a raiz precisa ter vira aviso, sem clobber).
|
|
51
52
|
|
|
@@ -55,5 +56,5 @@ só os arquivos do app; o que a raiz precisa ter vira aviso, sem clobber).
|
|
|
55
56
|
> action no formato canônico sem decorar convenção.
|
|
56
57
|
|
|
57
58
|
`opus mcp` sobe o server (configurado em `.mcp.json`): o agente consulta a estrutura, roda o
|
|
58
|
-
check e gera o esqueleto de uma action nova pela skill
|
|
59
|
+
check e gera o esqueleto de uma action nova pela skill `$create-opus-action` — a mesma régua do
|
|
59
60
|
`opus check`, por construção.
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
title: Comunicação
|
|
3
|
+
---
|
|
4
|
+
|
|
5
|
+
# Comunicação do Opus
|
|
6
|
+
|
|
7
|
+
Esta página registra somente o vocabulário, as superfícies e os mapeamentos próprios do
|
|
8
|
+
Opus. Princípios gerais de comunicação humana — contexto, impacto, próxima ação, gramática,
|
|
9
|
+
pontuação e consistência — pertencem à skill `write-product-communication` da
|
|
10
|
+
`@softize/base`. As regras mecanicamente verificáveis de copy ficam na política versionada,
|
|
11
|
+
em `node_modules/@softize/base/docs/copy-policy.md`, e no catálogo executável
|
|
12
|
+
`node_modules/@softize/base/policies/copy.json`.
|
|
13
|
+
|
|
14
|
+
A separação é intencional: uma mudança editorial universal acontece na Base; esta página
|
|
15
|
+
muda apenas quando o produto ou os componentes Opus mudam.
|
|
16
|
+
|
|
17
|
+
## Língua e termos no Opus
|
|
18
|
+
|
|
19
|
+
| Camada | Convenção local |
|
|
20
|
+
|---|---|
|
|
21
|
+
| Identificadores de código, arquivos, diretórios e domínios | Inglês |
|
|
22
|
+
| Nomes de action e rota | Inglês, no formato `resource.verb` |
|
|
23
|
+
| Colunas e tabelas de banco | Inglês, em `snake_case` |
|
|
24
|
+
| Enums, status e chaves de dicionário | Inglês, inclusive em exemplos e fixtures (`active`, não `ativo`) |
|
|
25
|
+
| Texto de UI visível | pt-BR; o contrato fornece o label humano para valores técnicos |
|
|
26
|
+
| Comentários e documentação deste repositório | pt-BR |
|
|
27
|
+
|
|
28
|
+
`Opus` e `Softize` são nomes próprios em prosa (`o Opus`, `a Softize`). Tokens técnicos
|
|
29
|
+
preservam a grafia de código: `opus check`, `@softize/opus`, `opus.json` e
|
|
30
|
+
`softize.com.br`.
|
|
31
|
+
|
|
32
|
+
Use sempre o termo de produto, não o nome interno da implementação: `sessão`, `ambiente`,
|
|
33
|
+
`cliente` e `agente`. Se a interface diz “cliente”, outra superfície não deve dizer
|
|
34
|
+
“client” para a mesma entidade.
|
|
35
|
+
|
|
36
|
+
## Papel semântico
|
|
37
|
+
|
|
38
|
+
O componente ou o contrato Opus classifica cada texto antes de a Base aplicar a política.
|
|
39
|
+
Essa classificação decide, por exemplo, se o conteúdo é um fragmento estrutural ou uma
|
|
40
|
+
frase. Não copie as regras da Base para cá.
|
|
41
|
+
|
|
42
|
+
| Superfície Opus | Papel enviado à Base |
|
|
43
|
+
|---|---|
|
|
44
|
+
| `label`, botão de confirmação e filhos de `Button` | `button` |
|
|
45
|
+
| `title`, `CardTitle`, `DialogTitle` | `title` |
|
|
46
|
+
| `description`, `hint`, `help` | `description` ou `helper-text` |
|
|
47
|
+
| `messages.success` e `messages.error` | `success` e `error` |
|
|
48
|
+
| `confirm.message`, `DialogDescription` | `dialog-body` |
|
|
49
|
+
| label de campo, filtro ou opção | `label` ou `menu-item` |
|
|
50
|
+
| placeholder de campo ou busca | `placeholder` |
|
|
51
|
+
| `Select.emptyText` e grupos de opção | `empty-state` e `heading` |
|
|
52
|
+
| confirmação local do `ActionTrigger` | `title`, `dialog-body` e `button` |
|
|
53
|
+
|
|
54
|
+
Copy visual e nome acessível são superfícies cumulativas. Um `aria-label` estático nomeia
|
|
55
|
+
um controle icon-only, mas não torna aceitável nem invisível ao gate um texto visual opaco.
|
|
56
|
+
Em `Select`, mantenha o texto auditável no `label` string; `content`/`triggerLabel` com JSX
|
|
57
|
+
estático e inequívoco também entram no inventário, inclusive com transformações nos
|
|
58
|
+
descendentes. Composição ambígua ou dinâmica faz a geração falhar, pois pode introduzir texto
|
|
59
|
+
visual que o protocolo não representa com segurança.
|
|
60
|
+
`ActionTrigger.itemLabel` é conteúdo de domínio em runtime (o nome do registro alvo), não
|
|
61
|
+
é copy editorial estável; `label` e `confirm.*` são as superfícies editoriais cobertas.
|
|
62
|
+
|
|
63
|
+
O mapeamento completo, o limite de cobertura e os comandos do gate estão em
|
|
64
|
+
`docs/code-style.md` do pacote.
|
|
65
|
+
|
|
66
|
+
## Convenções dos componentes
|
|
67
|
+
|
|
68
|
+
- Placeholders de seleção, simples, buscável ou múltipla, usam
|
|
69
|
+
`Selecione <artigo> <coisa>…`, sempre com o caractere `…`. Declare o placeholder no
|
|
70
|
+
contrato; o default do componente é apenas uma rede de segurança.
|
|
71
|
+
- Exemplos são neutros e duráveis: use Empresa X / Empresa Y e
|
|
72
|
+
`contato@empresa-x.com.br`, nunca um cliente real ou que pareça real.
|
|
73
|
+
- Em campos Opus, quando o termo canônico precisa de explicação persistente, mantenha o
|
|
74
|
+
termo curto em `label` e descreva o efeito em `help`. Por exemplo: `Staff` com
|
|
75
|
+
`Tem acesso ao back-office e a todos os workspaces.`
|
|
76
|
+
- Abreviações só entram quando o espaço do componente realmente exigir. Prefira `mínimo`,
|
|
77
|
+
`máximo` e `configuração`; `Ex.:` é tolerado em placeholder.
|
|
78
|
+
|
|
79
|
+
## Vocabulário de estado
|
|
80
|
+
|
|
81
|
+
Nas superfícies de UI do Opus, use “indisponível” para um recurso que não pode ser usado,
|
|
82
|
+
em vez dos rótulos alarmistas “ERRO” ou “FALHOU”. Endpoint, status HTTP e stack pertencem
|
|
83
|
+
ao console, ao log ou à documentação técnica, não ao texto dos componentes.
|
|
@@ -23,25 +23,35 @@ base versionada.
|
|
|
23
23
|
> Projeto novo não se monta à mão: o esqueleto canônico sai do `opus create`, com os
|
|
24
24
|
> pré-requisitos do protocolo, da UI e do preview já plugados — e os gates verdes.
|
|
25
25
|
|
|
26
|
+
O Opus e a Base ficam no npm público: leitura não exige token nem configuração de escopo.
|
|
27
|
+
Crie o projeto e materialize as duas camadas antes dos gates:
|
|
28
|
+
|
|
26
29
|
```bash
|
|
27
30
|
pnpm dlx @softize/opus create meu-app
|
|
28
|
-
cd meu-app && git init && pnpm install && pnpm test
|
|
31
|
+
cd meu-app && git init && pnpm install && pnpm run setup && pnpm test
|
|
29
32
|
```
|
|
30
33
|
|
|
31
|
-
O comando cria a estrutura inicial e instala a versão estável disponível.
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
34
|
+
O comando cria a estrutura inicial e instala a versão estável disponível. Em uma máquina nova,
|
|
35
|
+
se o `dlx` informar que o diretório global de binários não está no `PATH`, execute `pnpm setup`
|
|
36
|
+
e abra outra sessão do terminal. Se o setup encontrar uma seção antiga do pnpm no arquivo de
|
|
37
|
+
inicialização do shell (`ERR_PNPM_BAD_SHELL_SECTION`), `pnpm setup --force` substitui somente
|
|
38
|
+
esse bloco.
|
|
39
|
+
|
|
40
|
+
Durante as primeiras 24 horas de uma release, a quarentena do pnpm pode resolver silenciosamente
|
|
41
|
+
uma versão anterior. Se o CLI responder com “Comando desconhecido”, informe a versão explicitamente
|
|
42
|
+
com `pnpm dlx @softize/opus@<versão> create meu-app` ou desative a quarentena apenas nessa chamada
|
|
43
|
+
com `pnpm --config.minimum-release-age=0 dlx …`. Dentro do projeto, o workspace exclui Opus e Base
|
|
44
|
+
da quarentena para preservar o par validado.
|
|
35
45
|
|
|
36
46
|
Nasce com: `opus.config.ts` + domínio-exemplo canônico (0 violações, spec documentada),
|
|
37
47
|
vite + react + tema do Opus (Tailwind v4 CSS-first), dev server na porta que o Maestro
|
|
38
|
-
injeta no preview, `opus.json` (pin),
|
|
39
|
-
e o
|
|
48
|
+
injeta no preview, `opus.json` (pin), instruções, skills e hooks gerenciados. A Base é
|
|
49
|
+
dona do método geral, memória e revisão; o Opus acrescenta somente o conhecimento do SDK.
|
|
40
50
|
|
|
41
51
|
**Monorepo:** a raiz nasce do `--monorepo` e cada app nasce dentro dela — o create
|
|
42
|
-
detecta o `pnpm-workspace.yaml` e gera só o que é do app (
|
|
43
|
-
|
|
44
|
-
|
|
52
|
+
detecta o `pnpm-workspace.yaml` e gera só o que é do app (sem workspace yaml aninhado),
|
|
53
|
+
**avisando** o que a raiz precisa ter (glob de packages, allowBuilds e exclusões de
|
|
54
|
+
quarentena para Opus/Base) sem tocar nos seus arquivos:
|
|
45
55
|
|
|
46
56
|
```bash
|
|
47
57
|
pnpm dlx @softize/opus create meu-cliente --monorepo # a raiz do workspace
|
|
@@ -54,14 +64,17 @@ pnpm dlx @softize/opus create apps/portal # o app (modo detectado)
|
|
|
54
64
|
> O `opus.json` registra a versão usada pelo projeto. Se o arquivo ainda não existe, o setup
|
|
55
65
|
> cria a estrutura necessária antes das demais etapas.
|
|
56
66
|
|
|
57
|
-
A versão do Opus fica pinada em `opus.json`. O `opus setup` é per-app: grava o
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
`@softize/opus/ui/react`; o tema, por CSS.
|
|
67
|
+
A versão do Opus fica pinada em `opus.json`. O `opus setup` é per-app: grava o marcador,
|
|
68
|
+
o inventário de copy e as projeções específicas do SDK. O `base setup` materializa o
|
|
69
|
+
método geral, memória, agentes e revisão na raiz do repositório. Os componentes vêm do
|
|
70
|
+
barrel `@softize/opus/ui/react`; o tema, por CSS.
|
|
61
71
|
|
|
62
72
|
```bash
|
|
63
|
-
# Bootstrap
|
|
64
|
-
|
|
73
|
+
# Bootstrap idempotente de um projeto existente.
|
|
74
|
+
pnpm add @softize/opus
|
|
75
|
+
pnpm add -D @softize/base
|
|
76
|
+
pnpm exec opus setup
|
|
77
|
+
pnpm exec base setup
|
|
65
78
|
|
|
66
79
|
# index.css do app — o tema canônico + os componentes do Opus no scan do Tailwind.
|
|
67
80
|
@import '@softize/opus/ui/theme.css';
|
package/src/ui/docs/registry.tsx
CHANGED
|
@@ -39,7 +39,7 @@ import runtimeMd from './content/runtime.md?raw'
|
|
|
39
39
|
import uiMd from './content/ui.md?raw'
|
|
40
40
|
import cliMd from './content/cli.md?raw'
|
|
41
41
|
import tokensMd from './content/tokens.md?raw'
|
|
42
|
-
import
|
|
42
|
+
import communicationMd from './content/communication.md?raw'
|
|
43
43
|
import customizationMd from './content/customization.md?raw'
|
|
44
44
|
|
|
45
45
|
// — Componentes —
|
|
@@ -267,7 +267,7 @@ export const UI_SECTIONS: DocSection[] = [
|
|
|
267
267
|
{
|
|
268
268
|
pages: [
|
|
269
269
|
{ slug: 'tokens', title: 'Tokens & Tema', render: doc(tokensMd) },
|
|
270
|
-
{ slug: '
|
|
270
|
+
{ slug: 'communication', title: 'Comunicação', render: doc(communicationMd) },
|
|
271
271
|
{ slug: 'customization', title: 'Customização', render: doc(customizationMd) },
|
|
272
272
|
],
|
|
273
273
|
},
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: write-product-communication
|
|
3
|
-
description: Escreve e revisa comunicação de produto clara, humana e orientada ao leitor. Usar ao criar ou alterar documentação, mensagens de erro, textos de interface, CLI, onboarding, ajuda, explicações, comentários ou qualquer conteúdo que uma pessoa precise compreender.
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# Escrever comunicação de produto
|
|
7
|
-
|
|
8
|
-
## Resultado
|
|
9
|
-
|
|
10
|
-
Entregar uma comunicação que parte da situação do leitor, oferece o contexto necessário e
|
|
11
|
-
permite que a pessoa compreenda ou prossiga sem decodificar a linguagem interna da equipe.
|
|
12
|
-
|
|
13
|
-
## Procedimento
|
|
14
|
-
|
|
15
|
-
1. Identificar quem lerá o texto, o que essa pessoa tenta fazer e o que precisa compreender ou
|
|
16
|
-
decidir em seguida.
|
|
17
|
-
2. Ler a comunicação no fluxo completo em que aparecerá, incluindo estados anteriores e
|
|
18
|
-
posteriores.
|
|
19
|
-
3. Escrever a partir do problema e do efeito percebido; introduzir mecanismos e termos técnicos
|
|
20
|
-
somente quando acrescentarem precisão.
|
|
21
|
-
4. Distinguir princípios, regras, recomendações, comportamentos, verificações e exceções.
|
|
22
|
-
5. Revisar o texto fora do contexto da implementação e remover pressupostos, slogans,
|
|
23
|
-
advertências desnecessárias e detalhes internos.
|
|
24
|
-
6. Confirmar que erros explicam o ocorrido, o impacto e uma próxima ação real quando ela existir.
|
|
25
|
-
|
|
26
|
-
## Referência canônica
|
|
27
|
-
|
|
28
|
-
<!-- opus-doc: microcopy.md -->
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@softize:registry=https://registry.softize.com.br/
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
@softize:registry=https://registry.softize.com.br/
|
|
@@ -1,130 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
title: Comunicação
|
|
3
|
-
---
|
|
4
|
-
|
|
5
|
-
# Comunicação
|
|
6
|
-
|
|
7
|
-
Toda comunicação do produto deve ajudar alguém a compreender o que está acontecendo e a
|
|
8
|
-
seguir adiante com confiança. Esta orientação vale para documentação, interfaces, mensagens
|
|
9
|
-
de erro, CLI, onboarding, textos explicativos, comentários e respostas produzidas por agentes.
|
|
10
|
-
|
|
11
|
-
Clareza não significa apenas escrever frases curtas. Um texto claro parte da situação do
|
|
12
|
-
leitor, apresenta o que ele precisa saber e oferece contexto suficiente para que a próxima
|
|
13
|
-
decisão não dependa de adivinhação.
|
|
14
|
-
|
|
15
|
-
## Antes de escrever
|
|
16
|
-
|
|
17
|
-
Identifique quem lerá o texto, o que essa pessoa está tentando fazer e qual decisão ou ação
|
|
18
|
-
deve ser possível depois da leitura. Quando essas respostas não estiverem claras, investigue o
|
|
19
|
-
fluxo antes de escolher as palavras.
|
|
20
|
-
|
|
21
|
-
Organize a explicação nesta ordem sempre que ela ajudar:
|
|
22
|
-
|
|
23
|
-
1. apresente a situação ou o problema reconhecível pelo leitor;
|
|
24
|
-
2. explique o benefício ou o efeito esperado;
|
|
25
|
-
3. descreva o mecanismo somente no nível necessário;
|
|
26
|
-
4. indique a próxima ação quando houver uma.
|
|
27
|
-
|
|
28
|
-
Não comece pela arquitetura interna quando a necessidade do leitor oferece uma introdução
|
|
29
|
-
mais natural. Termos técnicos são bem-vindos quando acrescentam precisão, mas devem ser
|
|
30
|
-
apresentados antes de serem usados como parte da explicação.
|
|
31
|
-
|
|
32
|
-
## Voz
|
|
33
|
-
|
|
34
|
-
Escreva de maneira calma, próxima e segura. A comunicação pode ser firme sem parecer uma
|
|
35
|
-
ordem interna ou um manifesto.
|
|
36
|
-
|
|
37
|
-
- Prefira explicações completas a slogans, máximas e frases de efeito.
|
|
38
|
-
- Evite absolutos como “sempre”, “nunca”, “zero” e “é” quando houver contexto, condição ou
|
|
39
|
-
exceção relevante.
|
|
40
|
-
- Não use caixa-alta, negrito ou pontuação para fabricar autoridade.
|
|
41
|
-
- Evite sequências telegráficas, equações e símbolos usados como conectores em prosa.
|
|
42
|
-
- Não presuma que o leitor já concorda com a arquitetura ou conhece o vocabulário da equipe.
|
|
43
|
-
- Explique decisões pelo valor que oferecem às pessoas, não apenas pela disciplina que impõem.
|
|
44
|
-
- Mantenha o mesmo termo para o mesmo conceito em todas as superfícies.
|
|
45
|
-
|
|
46
|
-
Em vez de “O domínio é a aplicação. Front e back são cascas”, explique a relação:
|
|
47
|
-
|
|
48
|
-
> O Opus mantém as regras e os contratos do domínio em uma camada compartilhada. Assim,
|
|
49
|
-
> cliente e servidor trabalham com as mesmas definições, sem duplicar schemas, validações ou
|
|
50
|
-
> tipos de transporte.
|
|
51
|
-
|
|
52
|
-
## Documentação
|
|
53
|
-
|
|
54
|
-
Uma documentação deve formar o modelo mental do leitor antes de cobrar decisões baseadas
|
|
55
|
-
nele. Apresente primeiro o problema, depois a ideia, um exemplo concreto e os próximos passos.
|
|
56
|
-
Detalhes operacionais e situações excepcionais devem ficar próximos da etapa em que se tornam
|
|
57
|
-
úteis, sem interromper a introdução principal.
|
|
58
|
-
|
|
59
|
-
Ao registrar uma norma, deixe claro o peso da afirmação:
|
|
60
|
-
|
|
61
|
-
- **Princípio:** explica a intenção que orienta as decisões.
|
|
62
|
-
- **Regra:** descreve um requisito obrigatório e seu escopo.
|
|
63
|
-
- **Recomendação:** apresenta o caminho preferido quando outras opções continuam válidas.
|
|
64
|
-
- **Comportamento:** informa o que o produto faz automaticamente.
|
|
65
|
-
- **Verificação:** mostra como confirmar que a regra foi atendida.
|
|
66
|
-
- **Exceção:** delimita quando a orientação não se aplica.
|
|
67
|
-
|
|
68
|
-
Uma regra normativa deve informar a condição em que se aplica, a razão que a sustenta e como
|
|
69
|
-
ela é verificada. Por exemplo:
|
|
70
|
-
|
|
71
|
-
> Cada action deve ser declarada em um arquivo próprio. Essa separação permite que o registro e
|
|
72
|
-
> os geradores identifiquem cada action de forma determinística. O `opus check` informa quais
|
|
73
|
-
> arquivos precisam ser separados quando encontra mais de uma declaração.
|
|
74
|
-
|
|
75
|
-
Evite substituir essa explicação por “Uma por arquivo. O gate reprova”. A versão curta omite o
|
|
76
|
-
motivo, não delimita o escopo e transforma uma ajuda em uma advertência.
|
|
77
|
-
|
|
78
|
-
## Mensagens de erro
|
|
79
|
-
|
|
80
|
-
Uma mensagem de erro deve responder, nessa ordem, ao que aconteceu, como isso afeta a tarefa e
|
|
81
|
-
o que a pessoa pode fazer. Não culpe o usuário e não exponha endpoint, stack trace, status HTTP
|
|
82
|
-
ou detalhes do runtime na interface; esses dados pertencem ao log ou à área de diagnóstico.
|
|
83
|
-
|
|
84
|
-
| Situação | Prefira | Evite |
|
|
85
|
-
|---|---|---|
|
|
86
|
-
| Serviço indisponível | O Multica não respondeu. Tente novamente em alguns instantes. | ERRO: request failed (500) |
|
|
87
|
-
| Recurso ausente | Este workspace não existe mais. Volte à lista para escolher outro. | Workspace inválido. |
|
|
88
|
-
| Permissão | Você não tem acesso a este workspace. Peça acesso a um administrador. | Acesso negado. |
|
|
89
|
-
| Validação | Informe um endereço de e-mail válido. | Campo inválido. |
|
|
90
|
-
|
|
91
|
-
Quando não houver uma ação possível, diga isso com honestidade e preserve o trabalho já feito.
|
|
92
|
-
Não ofereça “tente novamente” como resposta automática para falhas que uma nova tentativa não
|
|
93
|
-
pode resolver.
|
|
94
|
-
|
|
95
|
-
## Textos de interface
|
|
96
|
-
|
|
97
|
-
Código e valores internos permanecem em inglês. O que uma pessoa lê na interface usa pt-BR,
|
|
98
|
-
salvo quando o produto declarar outro idioma.
|
|
99
|
-
|
|
100
|
-
- Frases começam com maiúscula e terminam com ponto.
|
|
101
|
-
- Labels, títulos, itens de menu e botões usam sentence case e não levam ponto.
|
|
102
|
-
- Placeholders de seleção usam `Selecione <artigo> <coisa>…`.
|
|
103
|
-
- Placeholders ajudam a responder, mas não substituem o label do campo.
|
|
104
|
-
- Botões descrevem a ação que executarão, como `Publicar` ou `Salvar alterações`.
|
|
105
|
-
- Textos de ajuda explicam o efeito percebido, não a implementação interna.
|
|
106
|
-
- Abreviações são usadas somente quando o espaço ou o vocabulário do domínio as justificam.
|
|
107
|
-
|
|
108
|
-
| Tipo | Prefira | Evite |
|
|
109
|
-
|---|---|---|
|
|
110
|
-
| Frase | A configuração não carregou. | Config indisponível. |
|
|
111
|
-
| Label | Nova sessão | Nova sessão. |
|
|
112
|
-
| Botão | Publicar | PUBLICAR |
|
|
113
|
-
| Placeholder | Selecione um cliente… | Selecionar |
|
|
114
|
-
| Ajuda | Os agentes deste workspace passam a usar esta skill. | O push sobrescreve o runtime. |
|
|
115
|
-
|
|
116
|
-
## Revisão
|
|
117
|
-
|
|
118
|
-
Antes de entregar, releia o texto fora do contexto da implementação e confirme:
|
|
119
|
-
|
|
120
|
-
- o leitor consegue reconhecer a situação sem conhecer o código;
|
|
121
|
-
- conceitos novos são explicados antes de orientar decisões;
|
|
122
|
-
- regras obrigatórias estão separadas de recomendações;
|
|
123
|
-
- a razão da orientação aparece quando ajuda a compreendê-la;
|
|
124
|
-
- mensagens de erro preservam a calma e oferecem uma saída real;
|
|
125
|
-
- a frase soa como uma conversa profissional, não como log, slogan ou ordem interna;
|
|
126
|
-
- detalhes técnicos permanecem disponíveis no lugar adequado sem dominar a comunicação.
|
|
127
|
-
|
|
128
|
-
Leia o fluxo completo, não apenas strings isoladas. Um conjunto de frases corretas ainda pode
|
|
129
|
-
produzir uma experiência confusa quando repete informações, muda de vocabulário ou apresenta
|
|
130
|
-
ações fora da ordem em que a pessoa precisa delas.
|