@softize/opus 22.1.0 → 23.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.
Files changed (52) hide show
  1. package/CHANGELOG.md +74 -1
  2. package/bin/cli.mjs +6 -5
  3. package/bin/lib/check.mjs +23 -8
  4. package/bin/lib/copy.mjs +1 -1
  5. package/bin/lib/gen-manifest.mjs +2 -0
  6. package/bin/lib/gen-runner.mjs +7 -0
  7. package/bin/lib/gen-stubs.mjs +3 -1
  8. package/docs/adr/0005-structural-surfaces-share-an-explicit-anatomy.md +1 -1
  9. package/docs/adr/0032-tab-baseline-respects-the-container-inset.md +16 -12
  10. package/docs/adr/0034-tabs-can-own-a-frame-without-owning-a-surface.md +8 -6
  11. package/docs/adr/0036-tabs-declares-trigger-distribution.md +11 -8
  12. package/docs/adr/0037-design-data-lives-outside-the-contract.md +1 -1
  13. package/docs/adr/0038-content-level-defines-primary-presentation.md +62 -0
  14. package/docs/adr/0039-filter-presentation-is-independent-from-filter-type.md +62 -0
  15. package/docs/adr/0040-tabs-use-a-single-navigation-presentation.md +60 -0
  16. package/docs/adr/0041-actions-declare-effect-and-personal-data.md +139 -0
  17. package/docs/code-style.md +1 -1
  18. package/docs/protocol.md +15 -2
  19. package/package.json +1 -1
  20. package/registry/skills/build-opus-ui/references/ui-patterns.md +1 -1
  21. package/registry/skills/create-opus-action/SKILL.md +7 -2
  22. package/registry/skills/create-opus-action/references/contract-and-binding.md +10 -5
  23. package/registry/skills/create-opus-action/references/evaluations.md +3 -0
  24. package/registry/skills/create-opus-action/scripts/scaffold.mjs +6 -0
  25. package/registry/templates/app/src/domains/tasks/actions/list.ts +2 -0
  26. package/src/core/action-nature.ts +40 -0
  27. package/src/core/audit.ts +12 -4
  28. package/src/core/contracts.ts +1 -1
  29. package/src/core/index.ts +2 -0
  30. package/src/core/runtime.ts +57 -35
  31. package/src/core/types.ts +45 -23
  32. package/src/design/index.ts +14 -3
  33. package/src/mcp/index.ts +6 -0
  34. package/src/testing/index.ts +6 -26
  35. package/src/ui/components/patterns/content-header.tsx +5 -9
  36. package/src/ui/components/patterns/list.tsx +55 -1
  37. package/src/ui/components/patterns/presentation.tsx +1 -1
  38. package/src/ui/components/primitives/icon-picker.tsx +6 -0
  39. package/src/ui/components/primitives/tabs.tsx +55 -87
  40. package/src/ui/components/primitives/toggle.tsx +1 -1
  41. package/src/ui/docs/content/action-list.md +13 -4
  42. package/src/ui/docs/content/actions.md +36 -8
  43. package/src/ui/docs/content/content.md +5 -6
  44. package/src/ui/docs/content/mcp.md +6 -0
  45. package/src/ui/docs/content/semantic-context.md +0 -1
  46. package/src/ui/docs/content/tabs.md +68 -69
  47. package/src/ui/docs/content/testing.md +2 -3
  48. package/src/ui/docs/content/toggle.md +15 -10
  49. package/src/ui/drivers/react.tsx +4 -3
  50. package/src/ui/meta.ts +2 -2
  51. package/src/ui/react.tsx +2 -3
  52. package/src/vite/design.ts +23 -21
@@ -1,7 +1,7 @@
1
1
  ## Alternar painéis relacionados
2
2
 
3
- Use `Tabs` para alternar painéis relacionados no mesmo contexto. O `value` de cada `TabsTrigger`
4
- corresponde ao `TabsContent` que ele abre. `defaultValue` define a aba inicial no modo não
3
+ Use `Tabs` para alternar painéis relacionados no mesmo contexto. O `value` de cada `TabsListItem`
4
+ corresponde ao `TabsPanel` que ele abre. `defaultValue` define a aba inicial no modo não
5
5
  controlado.
6
6
 
7
7
  `icon` posiciona um ícone decorativo antes do rótulo e normaliza SVGs para `1rem`. Quando a aba
@@ -10,31 +10,31 @@ mostrar somente o ícone, declare `aria-label` para preservar seu nome acessíve
10
10
  ```tsx preview col
11
11
  <Tabs defaultValue="sessions">
12
12
  <TabsList>
13
- <TabsTrigger value="overview" icon={<LayoutDashboard />}>
13
+ <TabsListItem value="overview" icon={<LayoutDashboard />}>
14
14
  Visão geral
15
- </TabsTrigger>
16
- <TabsTrigger value="sessions" icon={<History />}>
15
+ </TabsListItem>
16
+ <TabsListItem value="sessions" icon={<History />}>
17
17
  Sessões
18
- </TabsTrigger>
19
- <TabsTrigger value="skills" icon={<Settings />}>
18
+ </TabsListItem>
19
+ <TabsListItem value="skills" icon={<Settings />}>
20
20
  Skills
21
- </TabsTrigger>
21
+ </TabsListItem>
22
22
  </TabsList>
23
- <TabsContent value="overview">
23
+ <TabsPanel value="overview">
24
24
  <p className="text-sm text-muted-foreground">
25
25
  Resumo do workspace Empresa X.
26
26
  </p>
27
- </TabsContent>
28
- <TabsContent value="sessions">
27
+ </TabsPanel>
28
+ <TabsPanel value="sessions">
29
29
  <p className="text-sm text-muted-foreground">
30
30
  3 sessões nesta semana, 1 em andamento.
31
31
  </p>
32
- </TabsContent>
33
- <TabsContent value="skills">
32
+ </TabsPanel>
33
+ <TabsPanel value="skills">
34
34
  <p className="text-sm text-muted-foreground">
35
35
  6 skills vinculadas aos agentes do workspace.
36
36
  </p>
37
- </TabsContent>
37
+ </TabsPanel>
38
38
  </Tabs>
39
39
  ```
40
40
 
@@ -47,20 +47,20 @@ moldura.
47
47
 
48
48
  ```tsx preview col
49
49
  <Tabs defaultValue="overview" framed className="gap-0">
50
- <TabsList variant="line" className="px-2 pt-2">
51
- <TabsTrigger value="overview">Visão geral</TabsTrigger>
52
- <TabsTrigger value="history">Histórico</TabsTrigger>
50
+ <TabsList className="px-2 pt-2">
51
+ <TabsListItem value="overview">Visão geral</TabsListItem>
52
+ <TabsListItem value="history">Histórico</TabsListItem>
53
53
  </TabsList>
54
- <TabsContent value="overview" className="p-4">
54
+ <TabsPanel value="overview" className="p-4">
55
55
  <p className="text-sm text-muted-foreground">
56
56
  Resumo do workspace Empresa X.
57
57
  </p>
58
- </TabsContent>
59
- <TabsContent value="history" className="p-4">
58
+ </TabsPanel>
59
+ <TabsPanel value="history" className="p-4">
60
60
  <p className="text-sm text-muted-foreground">
61
61
  Alterações recentes do workspace.
62
62
  </p>
63
- </TabsContent>
63
+ </TabsPanel>
64
64
  </Tabs>
65
65
  ```
66
66
 
@@ -73,24 +73,23 @@ altera os painéis associados.
73
73
 
74
74
  ```tsx preview col
75
75
  <Tabs defaultValue="overview" distribution="equal">
76
- <TabsList variant="line">
77
- <TabsTrigger value="overview">Visão geral</TabsTrigger>
78
- <TabsTrigger value="contacts">Contatos</TabsTrigger>
79
- <TabsTrigger value="history">Histórico</TabsTrigger>
76
+ <TabsList>
77
+ <TabsListItem value="overview">Visão geral</TabsListItem>
78
+ <TabsListItem value="contacts">Contatos</TabsListItem>
79
+ <TabsListItem value="history">Histórico</TabsListItem>
80
80
  </TabsList>
81
- <TabsContent value="overview">Resumo do atendimento.</TabsContent>
82
- <TabsContent value="contacts">Tentativas de contato.</TabsContent>
83
- <TabsContent value="history">Alterações registradas.</TabsContent>
81
+ <TabsPanel value="overview">Resumo do atendimento.</TabsPanel>
82
+ <TabsPanel value="contacts">Tentativas de contato.</TabsPanel>
83
+ <TabsPanel value="history">Alterações registradas.</TabsPanel>
84
84
  </Tabs>
85
85
  ```
86
86
 
87
- ## Variante line
87
+ ## Linha de navegação
88
88
 
89
- Use `variant="line"` em `TabsList` quando a navegação precisar de uma linha-base, como em um
90
- cabeçalho. Na orientação horizontal, a lista ocupa toda a largura disponível e a aba ativa é
91
- marcada sobre essa linha, em vez de usar uma superfície preenchida. A linha respeita o recuo do
92
- contêiner; dentro de `DrawerBody` e `DialogBody`, ela acompanha o alinhamento do restante do corpo
93
- sem alcançar as laterais da superfície.
89
+ `TabsList` usa uma linha-base porque representa navegação entre painéis, não uma escolha de valor.
90
+ Na orientação horizontal, a lista ocupa toda a largura disponível e a aba ativa é marcada sobre
91
+ essa linha. A linha respeita o recuo do contêiner; dentro de `DrawerBody` e `DialogBody`, ela
92
+ acompanha o alinhamento do restante do corpo sem alcançar as laterais da superfície.
94
93
  Cada item contém uma área interativa com a mesma altura de um Button do tamanho correspondente. A
95
94
  área permanece transparente e recebe fundo apenas no hover; a aba ativa é indicada pela linha
96
95
  primária inferior. Um respiro de `0.375rem` separa o controle dessa linha; em `Tabs framed`, ele
@@ -98,69 +97,68 @@ aumenta para `0.5rem` e acompanha o padding superior da moldura.
98
97
 
99
98
  ```tsx preview col
100
99
  <Tabs defaultValue="agents">
101
- <TabsList variant="line">
102
- <TabsTrigger value="agents">Agentes</TabsTrigger>
103
- <TabsTrigger value="repos">Repositórios</TabsTrigger>
104
- <TabsTrigger value="settings">Configurações</TabsTrigger>
100
+ <TabsList>
101
+ <TabsListItem value="agents">Agentes</TabsListItem>
102
+ <TabsListItem value="repos">Repositórios</TabsListItem>
103
+ <TabsListItem value="settings">Configurações</TabsListItem>
105
104
  </TabsList>
106
- <TabsContent value="agents">
105
+ <TabsPanel value="agents">
107
106
  <p className="text-sm text-muted-foreground">
108
107
  developer, reviewer e designer ativos.
109
108
  </p>
110
- </TabsContent>
111
- <TabsContent value="repos">
109
+ </TabsPanel>
110
+ <TabsPanel value="repos">
112
111
  <p className="text-sm text-muted-foreground">
113
112
  empresa-x-api e empresa-x-web vinculados.
114
113
  </p>
115
- </TabsContent>
116
- <TabsContent value="settings">
114
+ </TabsPanel>
115
+ <TabsPanel value="settings">
117
116
  <p className="text-sm text-muted-foreground">Preferências do workspace.</p>
118
- </TabsContent>
117
+ </TabsPanel>
119
118
  </Tabs>
120
119
  ```
121
120
 
122
121
  ## Vertical
123
122
 
124
- Com `orientation="vertical"`, a lista forma uma coluna. O exemplo usa a variante padrão; com
125
- `variant="line"`, a marca da aba ativa passa para a lateral do gatilho.
123
+ Com `orientation="vertical"`, a lista forma uma coluna e a marca da aba ativa passa para a lateral
124
+ do gatilho.
126
125
 
127
126
  ```tsx preview col
128
127
  <Tabs defaultValue="prompt" orientation="vertical">
129
128
  <TabsList>
130
- <TabsTrigger value="prompt">Prompt</TabsTrigger>
131
- <TabsTrigger value="skills">Skills</TabsTrigger>
132
- <TabsTrigger value="history">Histórico</TabsTrigger>
129
+ <TabsListItem value="prompt">Prompt</TabsListItem>
130
+ <TabsListItem value="skills">Skills</TabsListItem>
131
+ <TabsListItem value="history">Histórico</TabsListItem>
133
132
  </TabsList>
134
- <TabsContent value="prompt">
133
+ <TabsPanel value="prompt">
135
134
  <p className="text-sm text-muted-foreground">
136
135
  O prompt do agente developer.
137
136
  </p>
138
- </TabsContent>
139
- <TabsContent value="skills">
137
+ </TabsPanel>
138
+ <TabsPanel value="skills">
140
139
  <p className="text-sm text-muted-foreground">
141
140
  Skills vinculadas a este agente.
142
141
  </p>
143
- </TabsContent>
144
- <TabsContent value="history">
142
+ </TabsPanel>
143
+ <TabsPanel value="history">
145
144
  <p className="text-sm text-muted-foreground">
146
145
  Sessões anteriores deste agente.
147
146
  </p>
148
- </TabsContent>
147
+ </TabsPanel>
149
148
  </Tabs>
150
149
  ```
151
150
 
152
151
  ## Tamanho
153
152
 
154
- `size="sm"` no `Tabs` reduz a altura da lista de `2.25rem` para `2rem`. É o par do `sm` de `Button` e
155
- `Select` para uma fileira densa, como uma toolbar ou um cabeçalho, em que o segmento não deve ficar
156
- mais alto que os elementos vizinhos.
153
+ `size="sm"` no `Tabs` reduz a área interativa de `2.25rem` para `2rem`. É o par do `sm` de `Button` e
154
+ `Select` para uma fileira densa, como uma toolbar ou um cabeçalho.
157
155
 
158
156
  ```tsx preview col
159
157
  <Tabs defaultValue="preview" size="sm">
160
158
  <TabsList>
161
- <TabsTrigger value="preview">Preview</TabsTrigger>
162
- <TabsTrigger value="code">Código</TabsTrigger>
163
- <TabsTrigger value="ai">IA</TabsTrigger>
159
+ <TabsListItem value="preview">Preview</TabsListItem>
160
+ <TabsListItem value="code">Código</TabsListItem>
161
+ <TabsListItem value="ai">IA</TabsListItem>
164
162
  </TabsList>
165
163
  </Tabs>
166
164
  ```
@@ -172,28 +170,29 @@ mais alto que os elementos vizinhos.
172
170
  | `defaultValue` | `string` | | Aba inicial no modo não controlado. |
173
171
  | `value` | `string` | | Aba ativa no modo controlado. Use com `onValueChange`. |
174
172
  | `onValueChange` | `(value: string) => void` | | Chamado quando a pessoa seleciona outra aba. |
175
- | `size` | `'default' \| 'sm'` | `'default'` | Altura da lista na escala única dos controles (2.25 e 2rem), aplicada em `TabsList`. Não altera a altura de `line` horizontal, que acompanha o conteúdo. |
173
+ | `size` | `'default' \| 'sm'` | `'default'` | Altura da área interativa na escala única dos controles (2.25 e 2rem), aplicada aos gatilhos. |
176
174
  | `distribution` | `'content' \| 'equal'` | `'content'` | Preserva a largura dos rótulos ou divide igualmente a largura disponível entre os gatilhos. |
177
175
  | `framed` | `boolean` | `false` | Aplica borda, raio e recorte ao conjunto sem definir fundo ou foreground. |
178
176
  | `orientation` | `'horizontal' \| 'vertical'` | `'horizontal'` | Direção da lista de abas. |
179
177
 
180
178
  ## Propriedades de TabsList
181
179
 
182
- | Propriedade | Tipo | Padrão | Descrição |
183
- | ----------- | --------------------- | ----------- | ------------------------------------------------------------------------------------------------------------------------- |
184
- | `variant` | `'default' \| 'line'` | `'default'` | `default` usa uma superfície preenchida; `line` cria uma linha-base horizontal de largura total e marca nela a aba ativa. |
180
+ | Propriedade | Tipo | Padrão | Descrição |
181
+ | ------------ | -------- | ------ | --------------------------------------------------------------- |
182
+ | `aria-label` | `string` | | Nomeia a navegação quando não houver um rótulo visível associado. |
183
+ | `className` | `string` | | Ajusta a composição externa sem substituir a linha de navegação. |
185
184
 
186
- ## Propriedades de TabsTrigger
185
+ ## Propriedades de TabsListItem
187
186
 
188
187
  | Propriedade | Tipo | Padrão | Descrição |
189
188
  | ----------- | ----------- | ------- | ----------------------------------------------------------------------------------------------- |
190
- | `value` | `string` | | Identificador que associa o gatilho ao `TabsContent` correspondente. |
189
+ | `value` | `string` | | Identificador que associa o gatilho ao `TabsPanel` correspondente. |
191
190
  | `icon` | `ReactNode` | | Ícone decorativo antes do rótulo, em `1rem`. Em uma aba sem texto, declare também `aria-label`. |
192
191
  | `disabled` | `boolean` | `false` | Impede a seleção da aba. |
193
192
 
194
- ## Propriedades de TabsContent
193
+ ## Propriedades de TabsPanel
195
194
 
196
195
  | Propriedade | Tipo | Padrão | Descrição |
197
196
  | ------------ | -------- | ------ | ---------------------------------------------------------------------- |
198
- | `value` | `string` | | Identificador do painel, igual ao `value` do `TabsTrigger` que o abre. |
197
+ | `value` | `string` | | Identificador do painel, igual ao `value` do `TabsListItem` que o abre. |
199
198
  | `forceMount` | `true` | | Mantém o painel montado mesmo quando outra aba está ativa. |
@@ -90,9 +90,8 @@ expect(emitted).toEqual([{ event: 'task.done', data: { id: '1' } }])
90
90
 
91
91
  Os dados que o modo design mostra não são comportamento da action e não precisam de teste de
92
92
  unidade: o plugin `opusDesign()` os gera a partir do contrato (ver
93
- [Actions](/docs/actions)). Enquanto o `mockHandler` existir, obsoleto desde a 22.1.0,
94
- `runAction` com `OPUS_MODE=design` ainda o executa, como o runtime. Teste a action ligada ao
95
- handler em vez dele.
93
+ [Actions](/docs/actions)). `runAction` executa somente a action ligada ao handler; use cenários do
94
+ plugin para respostas específicas do modo design.
96
95
 
97
96
  ## memStorage
98
97
 
@@ -30,8 +30,8 @@ render(
30
30
 
31
31
  ## Variantes e tamanhos
32
32
 
33
- Na variante `default`, o fundo aparece somente quando o controle está ativo; `outline` mantém a
34
- borda. `size` ajusta a altura.
33
+ Na variante `default`, o fundo aparece somente quando o controle está ativo. `outline` mantém a
34
+ borda e usa um fundo sutil distinto dela no estado ativo. `size` ajusta a altura.
35
35
 
36
36
  ```tsx preview
37
37
  <Toggle aria-label="Quebra de linha">
@@ -140,19 +140,24 @@ render(
140
140
  )
141
141
  ```
142
142
 
143
- ### Variante e espaçamento
143
+ ### Grupo conectado com borda
144
144
 
145
145
  `variant`, `size` e `shape` definidos no grupo chegam aos itens por contexto. `spacing` separa os
146
- itens; com zero, eles formam um bloco contínuo.
146
+ itens. Use `variant="outline"` com `spacing={0}` para formar um controle conectado com contorno
147
+ único. A borda pertence aos itens: o grupo remove as bordas internas duplicadas, arredonda apenas
148
+ as extremidades e preserva o contorno quando um item está ativo.
147
149
 
148
150
  ```tsx preview
149
- <ToggleGroup type="single" variant="outline" spacing={2} defaultValue="developer">
150
- <ToggleGroupItem value="developer">developer</ToggleGroupItem>
151
- <ToggleGroupItem value="reviewer">reviewer</ToggleGroupItem>
152
- <ToggleGroupItem value="designer">designer</ToggleGroupItem>
151
+ <ToggleGroup type="single" variant="outline" spacing={0} defaultValue="call">
152
+ <ToggleGroupItem value="call"><Phone /> Telefone</ToggleGroupItem>
153
+ <ToggleGroupItem value="email"><Mail /> E-mail</ToggleGroupItem>
154
+ <ToggleGroupItem value="whatsapp"><MessageCircle /> WhatsApp</ToggleGroupItem>
153
155
  </ToggleGroup>
154
156
  ```
155
157
 
158
+ Use um valor maior que zero quando cada item precisar preservar sua própria borda e seu próprio
159
+ raio, sem formar um bloco contínuo.
160
+
156
161
  ### Propriedades de ToggleGroup
157
162
 
158
163
  | Propriedade | Tipo | Padrão | Descrição |
@@ -161,10 +166,10 @@ itens; com zero, eles formam um bloco contínuo.
161
166
  | `value` | `string \| string[]` | | Seleção controlada; o tipo acompanha `type`. |
162
167
  | `onValueChange` | `(value: string \| string[]) => void` | | Informa a nova seleção. No modo single, uma string vazia representa nenhum item ativo. |
163
168
  | `defaultValue` | `string \| string[]` | | Seleção inicial no modo não controlado. |
164
- | `variant` | `'default' \| 'outline'` | `'default'` | Tratamento visual repassado aos itens. |
169
+ | `variant` | `'default' \| 'outline'` | `'default'` | Tratamento visual repassado aos itens. `outline` aplica borda a cada item. |
165
170
  | `size` | `'default' \| 'sm' \| 'lg'` | `'default'` | Tamanho repassado aos itens. |
166
171
  | `shape` | `'default' \| 'pill'` | `'default'` | Geometria do grupo e de suas extremidades. |
167
- | `spacing` | `number` | `0` | Distância entre os itens em unidades de spacing. |
172
+ | `spacing` | `number` | `0` | Distância entre os itens em unidades de spacing. Com zero, remove bordas internas duplicadas e conecta o grupo. |
168
173
 
169
174
  ### Propriedades de ToggleGroupItem
170
175
 
@@ -51,11 +51,12 @@ import { objectSchemaShape } from '../lib/object-schema.ts'
51
51
 
52
52
  /**
53
53
  * Dicionário estrutural pro resolvedor de `options: { kind: 'dictionary', ref }`:
54
- * qualquer coisa com `options()` → `{ value, label }`. O `DictType` do `t.dict`
55
- * satisfaz direto — sem este driver importar o driver de schema.
54
+ * qualquer coisa com `options()` → `{ value, label, icon? }`. O `DictType` do `t.dict`
55
+ * satisfaz direto — sem este driver importar o driver de schema. A metadata opcional
56
+ * continua sendo declarada pelo dicionário; o provider não inventa apresentação.
56
57
  */
57
58
  export interface DictLike {
58
- options(): Array<{ value: string; label: string }>
59
+ options(): Array<{ value: string; label: string; icon?: string }>
59
60
  }
60
61
 
61
62
  interface OpusContextValue {
package/src/ui/meta.ts CHANGED
@@ -201,7 +201,7 @@ export const componentMeta = {
201
201
  name: "tabs",
202
202
  ancestry: "shadcn",
203
203
  whenToUse:
204
- 'Alterne entre painéis relacionados no mesmo nível de navegação. Cada TabsTrigger aponta para um TabsContent pelo mesmo `value`; TabsList controla o tratamento visual e Tabs define orientação, escala, distribuição e moldura. Use `distribution="equal"` para repartir a largura entre seções equivalentes e `framed` para delimitar o conjunto sem criar uma nova superfície.',
204
+ 'Navegue entre painéis relacionados no mesmo nível. Cada TabsListItem aponta para um TabsPanel pelo mesmo `value`; TabsList usa uma linha para indicar a aba ativa, enquanto Tabs define orientação, escala, distribuição e moldura. Use ToggleGroup para escolher valores sem navegar entre painéis.',
205
205
  },
206
206
  textarea: {
207
207
  name: "textarea",
@@ -363,7 +363,7 @@ export const componentMeta = {
363
363
  name: "toggle",
364
364
  ancestry: "shadcn",
365
365
  whenToUse:
366
- "Alterne um estado diretamente no contexto atual. ToggleGroup reúne escolhas únicas ou múltiplas e compartilha aparência e escala entre os itens. Para um valor booleano com rótulo em formulário, prefira Switch ou Checkbox.",
366
+ 'Alterne um estado diretamente no contexto atual. ToggleGroup reúne escolhas únicas ou múltiplas e compartilha aparência e escala entre os itens. Use `variant="outline"` com `spacing={0}` para formar um grupo conectado com borda. Para navegar entre painéis, use Tabs.',
367
367
  },
368
368
 
369
369
  confirm: {
package/src/ui/react.tsx CHANGED
@@ -192,8 +192,8 @@ export { Separator } from "./components/primitives/separator.tsx";
192
192
  export {
193
193
  Tabs,
194
194
  TabsList,
195
- TabsTrigger,
196
- TabsContent,
195
+ TabsListItem,
196
+ TabsPanel,
197
197
  } from "./components/primitives/tabs.tsx";
198
198
 
199
199
  export { Skeleton } from "./components/primitives/skeleton.tsx";
@@ -499,7 +499,6 @@ export type {
499
499
  ContentElement,
500
500
  ContentFrameVariant,
501
501
  ContentHeaderLevel,
502
- ContentHeaderVariant,
503
502
  } from "./components/patterns/content-header.tsx";
504
503
 
505
504
  // Layout composicional: Split decide a relação espacial; Pane carrega conteúdo com inset.
@@ -88,8 +88,8 @@ export interface OpusDesignOptions {
88
88
 
89
89
  /**
90
90
  * Cenários de design (ADR 0037): módulos que exportam `defineDesignScenario(contrato, resposta)`.
91
- * Aceita caminhos e globs, como `entry`. O cenário vence o `mockHandler` e a resposta padrão
92
- * gerada pelo `fake`; cenário de action inexistente impede o boot, com a lista no erro.
91
+ * Aceita caminhos e globs, como `entry`. O cenário vence a resposta padrão gerada pelo `fake`;
92
+ * cenário de action inexistente impede o boot, com a lista no erro.
93
93
  * Sem default: o projeto decide onde os cenários ficam e se são versionados.
94
94
  */
95
95
  scenarios?: string | string[]
@@ -116,7 +116,7 @@ export interface OpusDesignOptions {
116
116
  stubs?: Record<string, DesignStubHandler>
117
117
 
118
118
  /**
119
- * Monta o /api também no dev NORMAL (handler real, sem OPUS_MODE).
119
+ * Monta o /api também no dev NORMAL, com os handlers reais.
120
120
  * Default false — devBackend puro não é design (sem sonda, proxy intacto).
121
121
  */
122
122
  devBackend?: boolean
@@ -156,7 +156,7 @@ const PROBE_PATH = '/__opus/design'
156
156
  const RUNTIME_ENDPOINT_PATHS = new Set(['/health', '/ready', '/openapi.json'])
157
157
 
158
158
  /** De onde vem a resposta de cada action no modo design, na ordem de precedência. */
159
- type DesignSource = 'scenario' | 'mock' | 'handler' | 'generated'
159
+ type DesignSource = 'scenario' | 'handler' | 'generated'
160
160
 
161
161
  interface DesignState {
162
162
  handle: NodeServerHandle
@@ -214,9 +214,8 @@ export function opusDesign(options: OpusDesignOptions = {}): Plugin {
214
214
  exProxyPrefixes = Object.keys(config.server?.proxy ?? {})
215
215
  // 2) Mata o proxy: fecha o vazamento preview→prod pra QUALQUER prefixo.
216
216
  if (config.server?.proxy !== undefined) config.server.proxy = undefined
217
- // 3) O execute() roteia pro mockHandler lendo OPUS_MODE (isOpusDesignMode); o boot
218
- // liga em cada action a resposta de design, e o preview fica autossuficiente.
219
- process.env.OPUS_MODE = 'design'
217
+ // 3) O boot liga em cada contrato um handler de cenário ou resposta gerada,
218
+ // e o preview fica autossuficiente sem alterar o runtime de produção.
220
219
  },
221
220
 
222
221
  configureServer(server) {
@@ -362,15 +361,14 @@ export function opusDesign(options: OpusDesignOptions = {}): Plugin {
362
361
  const named = (source: DesignSource): string[] =>
363
362
  state.actions.filter((a) => state.sources.get(a.name) === source).map((a) => a.name)
364
363
  const scenarios = named('scenario')
365
- const mocks = named('mock')
366
364
  payload.runtime = {
367
365
  prefix: apiPrefix,
368
366
  actions: state.actions.length,
369
- // `mocked`/`unmocked` mantêm o formato anterior da sonda: resposta escrita à mão
370
- // (cenário ou mockHandler) contra o resto, que responde por handler real ou `fake`.
371
- mocked: scenarios.length + mocks.length,
367
+ // `mocked`/`unmocked` preservam o formato histórico da sonda: cenário escrito
368
+ // à mão contra respostas vindas de handler real ou geradas pelo `fake`.
369
+ mocked: scenarios.length,
372
370
  unmocked: state.actions
373
- .filter((a) => !['scenario', 'mock'].includes(state.sources.get(a.name) ?? ''))
371
+ .filter((a) => state.sources.get(a.name) !== 'scenario')
374
372
  .map((a) => a.name),
375
373
  scenarios,
376
374
  generated: named('generated'),
@@ -687,8 +685,8 @@ function scenariosOfModule(mod: Record<string, unknown>): DesignScenario[] {
687
685
  }
688
686
 
689
687
  /**
690
- * Liga a cada action a resposta de design, nesta precedência: cenário, `mockHandler` declarado,
691
- * handler real (`bindAction`) e, por fim, a resposta padrão gerada pelo `fake`.
688
+ * Liga a cada action a resposta de design, nesta precedência: cenário, handler real
689
+ * (`bindAction`) e, por fim, a resposta padrão gerada pelo `fake`.
692
690
  */
693
691
  function prepareDesignActions(
694
692
  actions: ActionDef[],
@@ -699,18 +697,23 @@ function prepareDesignActions(
699
697
  const scenario = scenarios.get(action.name)
700
698
  if (scenario !== undefined) {
701
699
  sources.set(action.name, 'scenario')
702
- return { ...action, mockHandler: (ctx: ActionContext, input: unknown) => scenario.respond(input, ctx) } as ActionDef
703
- }
704
- if (action.mockHandler !== undefined) {
705
- sources.set(action.name, 'mock')
706
- return action
700
+ return {
701
+ ...action,
702
+ // Resposta simulada não representa exposição real de dado pessoal (ADR 0041).
703
+ personalData: false,
704
+ handler: (ctx: ActionContext, input: unknown) => scenario.respond(input, ctx),
705
+ } as ActionDef
707
706
  }
708
707
  if (typeof (action as { handler?: unknown }).handler === 'function') {
709
708
  sources.set(action.name, 'handler')
710
709
  return action
711
710
  }
712
711
  sources.set(action.name, 'generated')
713
- return { ...action, mockHandler: async (_ctx: ActionContext, input: unknown) => designResponse(action, input) } as ActionDef
712
+ return {
713
+ ...action,
714
+ personalData: false,
715
+ handler: async (_ctx: ActionContext, input: unknown) => designResponse(action, input),
716
+ } as ActionDef
714
717
  })
715
718
  return { actions: prepared, sources }
716
719
  }
@@ -759,4 +762,3 @@ function sendEnvelope(res: ServerResponse, status: number, input: ErrorInput): v
759
762
  ),
760
763
  )
761
764
  }
762
-