Koder Vector Graphics Format (.kvg)
Universal open vector format for the Koder Stack: 2D, animation, and 3D in a single self-contained document. Layered profile model (Core → Motion → Solid) lets renderers declare conformance progressively. Self-hosted-first: no external CDN refs, no proprietary dependencies, fully editable in Koder Dok and rasterizable by kicon. This document is the v0.1 proposal — scope and primitives are open for redesign before ratification.
KVG — Koder Vector Graphics Format
Version: *.1 — Proposal*Status: *re-normative — open for redesign*Editors: Rodrigo Mendonça (lead) Reference impl target: Koder Dok (rasterizer + editor) and kicon (rasterizer-only)
0. Why a new format
A typical Koder product today juggles three vector-adjacent formats:
| Use case | Today | Pain |
|---|---|---|
| Static 2D icons, illustrations, logos | SVG | Pseudo-3D só. Sem semântica de objeto. |
| 2D animated UI (splash, micro-interaction) | Rive / Lottie | Outro pipeline, outro editor, outro runtime |
| 3D real (PBR, hero, viewer) | glTF + Filament | Não edita no Inkscape; pesado pra ícone |
Mantemos *rês sources*(.svg, .riv, .glb) com três pipelines de tooling para descrever a *esma família*de objetos. KVG propõe um source único: *ma cena que pode ser 2D, animada, 3D — ou as três simultaneamente — descritas no mesmo grafo* Renderizadores declaram qual profile suportam; quem só faz 2D ignora as camadas Motion e Solid sem quebrar.
Premissa Koderespecífica: *elfhosted-first* Nenhum .kvg pode depender de CDN externo, font remota, shader hospedado em terceiros. O documento é fechado, distribuído como bytes, executável offline.
0.4 Filosofia de desenvolvimento
KVG é spec de longa duração: arquivos .kvg escritos em 2026 devem renderizar em 2036. Isso impõe uma assimetria sobre como decisões são tomadas neste projeto:
- *ecisões de design fundamentais*— profile boundaries, sintaxe,
primitivas, sandbox da DSL, sistema de coordenadas, semântica de notações — são feitas uma vez para durar 10+ anos. Justificam investimento desproporcional em análise, alternativas comparadas contra diretrizes, e completude antes de congelar.
- *ecisões de implementação iterativa*— qual renderer escrever
primeiro, ordem de fases do roadmap, quais bugs prioritizar, qual algoritmo interno escolher, qual cache adotar — seguem ship discipline normal: pequenas, reversíveis, frequentes.
Relação com policies/hyperscale-first.kmd
A policy diz: "esforço desproporcional → ship simples + ticket de follow-up". No KVG, a barra de "desproporcional" para decisões de *esign da spec*é mais alta que para tickets de produto — porque o custo de errar a spec é viver com migração de breaking change em todo arquivo .kvg em circulação.
Para decisões de *mplementação interna*dentro do projeto KVG (renderer, parser, CLI, editor, kicon integration), aplicar hyperscale-first sem ajuste.
Implicação prática
Quando uma decisão de design v0.1 for ambígua entre "ship enxuto agora + adicionar v0.2" vs "incluir agora com mais investimento":
- Se afeta *orma do
.kvgdistribuído*(sintaxe, primitivas,semântica observável, contrato de runtime) → escolher completude. Custo de migração é alto e atinge todos os autores.
- Se afeta *ó implementação interna*(qual algoritmo, qual cache,
qual ordem de pipeline, qual linguagem do renderer) → ship enxuto + ticket. Custo de migração é zero — é detalhe de produto, não contrato de spec.
Esta filosofia justifica decisões como "todas as constraints em Motion v0.1" (Pergunta 5, decidida 20260430) e "Coons patch em v0.1" (Pergunta 6) que sob hyperscalefirst puro pareceriam overinvestment.
0.5 Princípios e diretrizes
Estas dez diretrizes são o contrato de design do formato. Toda decisão posterior — sintaxe, primitivas, profile boundaries, runtime — pode ser justificada (ou contestada) contra esta lista.
- *impo / simples visualmente.*O source canônico em texto é
confortável de ler sem ferramenta especial. Nada de marcação ruidosa em volta de geometria simples.
- *xtensível via DSL embarcada (kgen).*Documento pode declarar
[[kdef]](primitivas customizadas reutilizáveis) e[[kgen]](geração procedural pontual) para domínios específicos — CAD, VFX, schematics, ou qualquer cenário onde as primitivasbase do KVGCore não bastam. A DSL chamase *gen* é purposebuilt (não é subset de Koder Koda), e está especificada na §13. Ver §11 para o modelo de extensão. - *rático.*A coisa mínima que faz uma coisa útil cabe em poucas
linhas. Casos comuns têm caminho curto.
- *bjetos em todas as dimensões.*1D (curvas e sequências), 2D
(vetorial clássico), 3D (sólido), 4D (3D no tempo), N-D (paramétrico, volume rendering, dados hiperdimensionais). Coordenadas usam vetor genérico —
[x, y],[x, y, z],[x, y, z, t]— sem tag de tipo manual no caso comum. - *státicos ou dinâmicos.*Mesmo formato cobre desde ícone congelado
até cena animada com state machine. Profile Motion é opt-in.
- *ores em todas as notações.*Qualquer primitiva aceita cor por
sólido, gradient, mesh-gradient, textura ou shader. Sem casos onde "este tipo não suporta cor" só por limitação do formato.
- *plicável de desenho simples a CADVFXcinema.*Ícone do Hub e cena
de filme rodam no mesmo formato — não no mesmo profile, mas no mesmo formato. Profiles específicos (CAD
kit, VFXkit) são montados como metaspecs reutilizáveis, não como dialetos separados. - *scalável.*Em duas dimensões: tamanho do documento (de 50 linhas
até GB com streaming) e complexidade da cena (de 6 nós até milhões de triângulos com LOD, instancing, culling).
- *ão verboso.*Default agressivo: o que não foi declarado, herda do
profile ou do parent. Nada de boilerplate por linha.
- *ápida leitura e rápida renderização.*Source de texto parseia em
O(n); binário
.kvgbcarrega em mmap-friendly layout; cenas grandes suportam streaming progressivo; primitivas mapeiam diretamente em chamadas GPU sem tradução pesada.
Tensões reconhecidas
Algumas diretrizes brigam — registramos para tratar conscientemente:
- *1 simples ⚔ #7 todos cenários* cinema/CAD são intrinsecamente
ricos. Resolução: complexidade vive em
[[kdef]]reusáveis (#2), não em primitivas-base. - *9 não verboso ⚔ #4 todas dimensões* 5D paramétrico exige notação
extra. Resolução: 2D/3D são otimizados no caso comum; N-D paga o preço só quando usado.
- *10 rápida leitura ⚔ #7 cinema* cenas grandes obrigam streaming.
Resolução: o binário aceita chunks lidos sob demanda; source texto é sempre carregado todo (assumido pequeno).
- *1 simples ⚔ #2 extensão* blocos
[[kdef]]/[[kgen]]inlinetornam o source mais poderoso mas mais difícil de ler. Resolução: 95 % dos arquivos não definem extensão; os outros 5 % são feitos por autores avançados que aceitam o trade-off.
- *2 extensão ⚔ self
hostedfirst* imports externos quebramauto-suficiência. Resolução em §11:
[[kdef]]mora dentro do mesmo arquivo que a usa; tooling (Dok) inlina ao inserir.
1. Goals
- *niversal scene description* 2D, motion, 3D no mesmo grafo, com
primitivas que se compõem em vez de competirem.
- *ayered profiles* o mínimo viável é Core (2D estático). Motion e Solid
são profiles aditivos, opt-in por documento e por renderer.
- *eterministic rendering* dado o mesmo
.kvge o mesmo profile, doisrenderers conformes produzem o mesmo bitmap (dentro de tolerância de anti-aliasing definida).
- *elf-contained* zero referências externas. Fonts, raster textures,
meshes, scripts — tudo embarcado.
- *ditable* o formato source é texto humano-legível, gerável por código
e editável em Koder Dok com preview ao vivo.
- *bject semantics* cada nó tem identidade e metadata estruturada que
tooling (kicon, koder_kit, search) consulta — "todos os satélites do hub icon" é uma query, não uma heurística sobre bbox.
- *mbeddable runtime* o renderer KVG-Core deve caber em < 200 KB
compactado (alvo: WASM no Web, FFI lib no Flutter, biblioteca KL nativa).
2. Non-goals
- *ubstituir CAD* STEP/OpenSCAD continuam para engenharia.
- *ubstituir vídeo* KVG-Motion é animação vetorial, não codec.
- *irar linguagem de programação* scripts inline são opcionais e
sandboxed (Koder Koda restrito); a base é declarativa.
- *ompatibilidade exata com SVGRiveglTF* KVG é um formato novo. Os
conversores fazem best-effort.
- *ubstituir HTML / Flutter widgets* KVG descreve uma *ena* não uma
UI com layout responsivo, foco e acessibilidade WAI-ARIA.
3. Architecture — Profiles
KVG é especificada em três profiles aditivos. Cada documento declara o mínimo profile que requer; cada renderer declara o máximo profile que suporta. Documento abre num renderer ⇔ profiledoc ⊆ profilerenderer.
3.0 Declaração — aliases canônicos
Documentos declaram o profile no header com um destes aliases:
| Alias | Capacidades incluídas |
|---|---|
Core |
2D estático |
Animated |
Core + Motion |
Spatial |
Core + Solid |
Full |
Core + Motion + Solid |
profile Core // ícone simples, splash estático
profile Animated // logo animado, splash com motion
profile Spatial // hero icon 3D estático
profile Full // cena completa (3D animado)A forma concat-explícita também é aceita pelo parser e equivale ao alias correspondente; kvg fmt normaliza para o alias canônico:
profile Core+Motion+Solid // aceito; kvg fmt → "Full"
profile Core+Motion // aceito; kvg fmt → "Animated"Combinações inválidas (ex: Motion+Solid sem Core) são rejeitadas pelo validador — Core é sempre mandatório.
3.1 KVG-Core (mandatório)
Equivalente a SVG estático. Cobre:
- Primitivas 2D:
path,rect,ellipse,line,polyline,polygon,text(com fonts embarcadas). - Estilo: fill (sólido + gradient linearradialmesh), stroke, opacity,
blend modes, clipping, masks.
- Filters: blur, drop
shadow, colormatrix, displacement-map, lighting(feSpecularLighting equivalent — pseudo-3D barato).
- Grupos hierárquicos com transforms 2D (matrix, translate, rotate, scale,
skew).
- Viewport e units (user space, viewBox como SVG).
Renderer KVG-Core é equivalente em capacidade a um renderer SVG bom. Footprint alvo: * 200 KB* 100 % offline.
3.2 KVG-Motion (opcional)
Adiciona ao Core:
- *imeline* keyframes, easing curves (cubic-bezier nomeados + custom
splines), loopping-pongonce.
- *tate machine* estados nomeados, transições com triggers (input
pointer, evento custom, fim de timeline), interpolação entre estados.
- *onstraints*(todas em v0.1, decidido 2026
0430):- *ook-at 2D/3D* nó rotaciona para apontar a um alvo (point ou
outro nó). Solver: 5-10 LoC, determinístico.
- *ollow-path* nó percorre uma path com parâmetro
t ∈ [0, 1],com modos
loop,ping-pong,once. Suporta amostragem por distância de arco para velocidade uniforme. - *K 2-bone* solver de cinemática inversa para cadeia de 2 ossos
(braço/perna estilo). Suporta pole-target, joint limits, fallback suave em singularidade. Inspiração de API: Rive constraints (modelo bem desenhado e validado em produção).
- *ook-at 2D/3D* nó rotaciona para apontar a um alvo (point ou
- *nputs* pointer (hoverpressdrag), value bindings (data drivers).
Inspiração: Rive (state machine + constraints API), Lottie (timeline).
3.3 KVG-Solid (opcional)
Adiciona ao Core ou Core+Motion:
- *esh primitives* triangle mesh (índices + atributos), CSG primitives
(sphere, cylinder, box, torus) parametricamente expandidos no carregamento.
- *aterial PBR* metallic-roughness model (alinhado a glTF 2.0), normal
maps, emissive, IBL.
- *ighting* directional, point, spot, IBL environment cube ou equirect
embarcado.
- *amera* perspective/orthographic, field
ofview, clip planes. - *D transforms* matrix4, quaternion rotation.
- *er-vertex animation* skinning (joints+weights), morph targets.
Em modo Core+Solid sem Motion, geometria 3D é estática. Em Core+Motion+Solid, animação 3D usa skinning ou morph driven pelo state machine.
*ompositional rule* 2D e 3D coexistem na mesma cena. Um nó 2D vive no plano z=0 do espaço 3D. Um nó 3D pode ser raster-bakeado em runtime para compor com 2D (drop-shadow do 3D no plano 2D, etc.).
4. File format
4.1 KSS — KVG Source Syntax
Sintaxe purpose-built para grafos de cena. Inspirada em KDL e CSS, otimizada para compactação visual e hierarquia nativa. Não é TOMLJSONYAML/KDL emprestado — o KVG carrega sintaxe própria, na mesma filosofia de kgen e das notações KPNKCNKVN: peça purpose-built, controlada pela Koder.
Princípios da sintaxe
- *ierarquia via
{ }* cada bloco abre escopo. Indent é cosmético. - *are identifiers* tipos e nomes de atributos sem aspas
(
ellipse,cx,fill). - *Ds com prefixo
#*#core,#sat-top— estilo CSS. - *tributos posicionais + nomeados* tipos comuns aceitam ordem
posicional para os primeiros valores; nomeados depois.
- *otações embarcadas inline* KPN, KCN, KVN entram bare quando
inequívocas, ou entre aspas como expressões.
- *omentários*com
//(linha) ou(bloco).#é reservadopara IDs.
Exemplo — ícone Koder Hub (núcleo + 1 satélite + 1 gradient)
kvg-version "0.1.0"
profile Core
viewport 0 0 512 512
title "Koder Hub icon"
meta {
author "rpm"
created 2026-04-30
license "CC-BY-4.0"
units px
}
asset font #inter {
data "base64:AAEAAAAR..."
}
gradient #core-grad radial center=[0.35, 0.35] radius=0.7 {
stop 0.00 "#BFDBFE"
stop 0.35 "#3B82F6"
stop 1.00 "#1E3A8A"
}
scene {
ellipse #core role="hub.center" 256 256 r=48 fill=#core-grad
}Estrutura de um node statement
TYPE [#ID] [POSITIONAL_ARGS] [NAMED_ATTRS] [BODY]- *YPE* bare identifier (
ellipse,rect,path,gradient,kdef,kgen,scene,group,meta,asset, ...) - *ID* opcional; quando presente, vira identidade local do nó.
- *OSITIONAL_ARGS* zero ou mais valores anônimos. Cada tipo
documenta a ordem aceita (ex:
ellipse cx cy r,rect x y w h,stop offset color). - *AMED_ATTRS* pares
chave=valorem qualquer ordem. - *ODY* bloco
{ ... }com mais statements aninhados. Opcionalpara nós-folha.
Tipos de valor reconhecidos
| Forma | Tipo | Exemplo |
|---|---|---|
| Inteiro | int | 256, -7 |
| Decimal | float | 3.14, 0.667, 1e-5 |
| Booleano | bool | true, false |
| Bare identifier | ident | Core, radial, ellipse |
| ID/ref | id-ref | #core, #blue-sphere |
| String quotada | string | "texto com espaços" |
| Vec (KVN) | vec | [256, 256], [0.35, 0.35, 0] |
Hex color (KCN, em fillstrokecolor/stop) |
color | "#3B82F6", "#3B82F6CC" |
| Multi-line string | block-string | """...kgen body....""" |
Gramática EBNF resumida
file = (statement)*
statement = node-stmt | comment
node-stmt = type id? value* attr* body? NEWLINE
type = IDENT
id = '#' IDENT
attr = IDENT '=' value
value = number | bool | ident | id-ref | string | vec | block-string
vec = '[' value (',' value)* ']'
block-string = '"""' .* '"""'
body = '{' statement* '}'
comment = '//' .* NEWLINE | ''Convenções de leitura
- *ulti-line agressivo é OK* cenas longas devem usar uma
declaração por linha. Compactação inline com separador
;é permitida (várias declarações na mesma linha) mas desencorajada para fontes versionadas em git (diffs piores). - *ndent é livre* 2 espaços é convenção; o parser ignora.
- *railing comma*em vecs e listas é permitida e ignorada.
Self-host parser
Implementação de referência: ~700 LoC em Koder Koda, distribuída em engines/lang/kvg/parser. Reescrita em Dart (para Flutter) e em Go (para ferramenta CLI) seguem a mesma EBNF — sem dependência de parser externo.
4.2 Binary serialization — .kvgb
Equivalente ao .glb do glTF: *BOR-encoded scene graph + concatenated binary buffers* Usado em runtime para parse rápido, distribuído quando tamanho importa. Conversão kvg ↔ kvgb é round-trip lossless.
4.3 Container variant — .kvg.zip (opcional)
Para projetos com muitos assets pesados (vários .glb mesh, raster textures de alta resolução, audio bindings de motion), KVG aceita empacotamento como ZIP com manifest.kvg na raiz. Apenas conveniência — semanticamente idêntico a um .kvg com tudo embarcado.
4.4 Versionamento
Documento declara versão da spec no header com semver:
kvg-version "0.1.0"
profile Full*egras de versionamento*(decidido 20260430):
- *eader obrigatório* Validador erra se ausente.
- *ajor*(1.0 → 2.0) = breaking change permitido. Ferramenta
obrigatória
kvg upgrademigra arquivos do major anterior. - *inor*(0.1 → 0.2) = aditivo apenas. Documento v0.1 renderiza
inalterado em renderer v0.2. Renderer v0.1 ignora features novas silenciosamente quando declaradas via
requires. - *atch*(0.1.0 → 0.1.1) = clarificação de spec, zero mudança de
capacidade observável.
*mutabilidade do legado* nenhuma primitiva presente em v0.1 desaparece em minor ou patch. Major bump pode remover, sempre com migração ferramenta-assistida.
*apability strings por nó*(opcional, ortogonal à versão):
group #character requires=["ik-2bone"] {
// árvore que precisa do constraint IK
fallback {
// árvore alternativa se renderer não tem ik-2bone
}
}Permite graceful degradation dentro de um mesmo profile/versão. Um renderer KVGMotion pode ter shipado lookat mas não ik-2bone ainda; o campo requires permite ao autor declarar dependência e fornecer fallback. A lista de capability strings é parte da spec da versão e cresce monotonicamente.
*enderer declara compat*
renderer.kvg = {
version-max: "0.2.0",
capabilities: ["Core", "Motion", "look-at", "follow-path",
"ik-2bone", "mesh-coons", ...]
}Validação: documento abre se doc.kvg-version ≤ renderer.version-max **todos os requires declarados em nós estão presentes em renderer.capabilities (ou os nós têm fallback).
5. Coordinate system
*ecisão 2026
0430* Y-up everywhere (Cartesiano padrão). Razão: convenção matemática universal ensinada em escola desde Descartes (1637); alinha com 3D inteiro (glTF, Blender, Maya, Unity, USD, OpenGL); alinha com CADengenhariaplots científicos. Y-down do SVG/Canvas é artefato histórico de raster scan de CRT — não convenção humana. Importadores de SVG aplicam flip uma vez nokvg convert.
- *istema canônico* right
handed Cartesiano, *up* *-right**-out*(saindo da tela em direção ao observador).
- *rigem* por default no canto *nferior-esquerdo*da viewport.
Documento pode declarar
origin centerno header para colocar (0,0) no centro — útil para ícones simétricos. - *lano 2D = z0* nós 2D vivem no plano XY com z0 e normal +Z.
- *iewport*declara um retângulo no plano 2D:
viewport x y w h,onde
(x, y)é o canto *nferior-esquerdo* - *nits* padrão
px; aceitamm,pt,em,vw/vhresolvidos no contexto do consumer.
- *igração SVG* o importer aplica
transform="scale(1, -1) translate(0, -H)"no nó raiz para inverter Y e ancorar a origem. Autor não precisa pensar nisso —
kvg convert foo.svgresolve. - *igração glTF* importação direta sem flip (mesma convenção).
6. Object model
Cada [[node]] tem:
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
id |
string | sim | Identidade local; única no documento |
role |
string (dotted) | não | Semântica para tooling. Ex: hub.satellite.square |
type |
enum | sim | group, path, rect, ellipse, text, mesh, ... |
parent |
id | não | Default: root |
transform |
matrix/keyed | não | 2D ou 3D conforme profile |
tags |
string[] | não | Para queries amplas (ex: ["interactive"]) |
data.* |
livre | não | Metadata arbitrária para consumers |
*ueryability* a runtime expõe scene.query("role:hub.satellite.*") → todos os 6 nós satélite. Substitui o problema atual do kicon que precisa heurística de bbox para entender o que é "objeto" no SVG.
6.1 Acessibilidade
Toda cena KVG deve ser consumível por leitor de tela e outras tecnologias assistivas. Cinco campos a11y.* cobrem o leque relevante para conteúdo gráfico (decidido 20260430):
| Campo | Tipo | Obrigatório | Descrição |
|---|---|---|---|
a11y.label |
string | sim no nó-raiz da scene | Nome curto que o leitor anuncia |
a11y.role |
enum | não (default img) |
img, figure, diagram, decoration, presentation |
a11y.description |
string | não | Descrição longa; serializada em aria-describedby na renderização web |
a11y.decoration |
bool | não (default false) |
Atalho para role="decoration"; leitor pula o nó |
a11y.labelledby |
id-ref | não | Aponta pra outro nó (geralmente text) cujo conteúdo serve como label, evitando duplicação |
Regras de exposição:
- *ó-raiz da scene*deve ter
a11y.label. Validador erra se ausente. - Sub
nós comelementos navegáveis*—a11y.labelpróprio viram *ubtecnologia assistiva trata o conjunto como árvore, à semelhança de
<figure>aninhado em HTML. - Sub-nós *em*
a11y.labelsão opacos para AT (parte da composiçãovisual, não da estrutura semântica).
a11y.decoration=truesalta o nó *nteiramente*— válido paraornamentos puramente visuais.
a11y.labelledby="#some-text-node"resolve em runtime: o leitor lêo conteúdo de texto daquele nó como label.
Diferido para v0.2+: a11y.live (anúncio de mudanças em Motion) e a11y.flowto (ordem custom de leitura em diagramas editoriais). Adicionados quando demanda concreta aparecer.
Exemplo:
scene {
group #hub-icon a11y.label="Koder Hub icon" a11y.role="img" {
ellipse #core 256 256 r=48
rect #sat-top 232 107 48 48 a11y.decoration=true
group #annotation a11y.label="6 connected satellites" a11y.role="figure" {
// ... sub-árvore navegável
}
}
}7. Notações embarcadas
Dentro do KVG, três sub-formatos são notações simbólicas — pequenas linguagens de strings interpretadas por sub-parsers próprios. Não são estrutura TOML; são strings com gramática própria embutidas em campos. Renderer KVG-Core conforme deve entender as três.
7.1 KPN — KVG Path Notation
Notação compacta para descrever curvas e contornos. Inspirada em SVG path data: cada comando é uma letra, seguida de números separados por espaço ou vírgula. Maiúscula = absoluto, minúscula = relativo.
| Comando | Args | Significado |
|---|---|---|
| M / m | x y | Move (caneta sobe, vai para o ponto) |
| L / l | x y | Line (linha reta até o ponto) |
| H / h | x | Horizontal line |
| V / v | y | Vertical line |
| C / c | x1 y1 x2 y2 x y | Cubic Bézier (dois controles + endpoint) |
| Q / q | x1 y1 x y | Quadratic Bézier (um controle + endpoint) |
| A / a | rx ry rot large sweep x y | Elliptical arc |
| T / t | x y | Smooth quadratic continuation |
| S / s | x2 y2 x y | Smooth cubic continuation |
| Z / z | — | Close path (volta para o último M) |
[[node]]
id = "leaf"
type = "path"
d = "M 100 100 C 130 50 170 50 200 100 Q 200 150 150 180 Z"KPN aceita extensão para 3D em KVG-Solid (comandos M3, L3, C3 com três coordenadas), e para N-D paramétrico (sufixo N mais um vetor).
7.2 KCN — KVG Color Notation
Herda do CSS Color Module Level 4 — qualquer renderer KVG aceita as notações abaixo. Um campo fill, stroke, color ou stop-color pode receber qualquer forma:
| Forma | Exemplo |
|---|---|
| Hex curto | #3B8 |
| Hex longo | #3B82F6 |
| Hex com alpha | #3B82F6CC |
| RGB | rgb(59, 130, 246) |
| RGBA | rgb(59, 130, 246, 0.8) |
| HSL | hsl(217, 91%, 60%) |
| OKLCH | oklch(60% 0.18 250) (recomendado para perceptual) |
| Named | transparent, currentColor |
| Gradient ref | gradient(id) (aponta para [gradient.id] declarado) |
Recomendação na §0.5 diretriz #6: produtos Koder devem usar *KLCH*para máxima consistência perceptual entre dispositivos.
7.3 KVN — KVG Coordinate Notation
Notação vetorial unificada para 1D a N-D. Vetor é uma lista TOML; a dimensionalidade é inferida pelo número de componentes:
| Forma | Significado |
|---|---|
[x, y] |
2D — plano padrão |
[x, y, z] |
3D — espaço cartesiano |
[x, y, z, w] |
4D — homogêneo (projetivo) ou 3D + tempo |
[x, y, z, t, p] |
N-D — paramétrico (e.g., volume rendering) |
Operadores e funções da kgen (§13) trabalham polimorficamente sobre KVN — length([3,4]) → 5; length([1,2,2]) → 3; lerp(a,b,t) opera componente a componente.
7.4 Por que notações ao invés de TOML estruturado?
Notações são mais densas, mais legíveis para olho treinado e mais performáticas para parse + render. Compare:
# Notação compacta
d = "M 0 0 L 100 0 L 100 100 Z"
# Forma estruturada equivalente (rejeitada)
[[d.cmd]]
op = "moveTo"
to = [0, 0]
[[d.cmd]]
op = "lineTo"
to = [100, 0]
[[d.cmd]]
op = "lineTo"
to = [100, 100]
[[d.cmd]]
op = "close"Para 50 comandos numa path, a forma estruturada custa ~10× mais bytes e é mais lenta de parsear. A notação ganha em todos os quesitos — desde que seja simples o suficiente pra autor ler na mão.
8. Color & material
8.1 2D (Core)
- Cor:
#RRGGBB,#RRGGBBAA,rgb(),oklch()(recomendado para perceptualconsistency entre dispositivos).
- Fill: sólido, linear
gradient, radialgradient, *eshgradient Coonspatch*(decidido 2026
0430; ver §8.1.1). - Stroke: width, cap, join, miter, dasharray.
- Filter graph: nós conectáveis (blur → color-matrix → composite), idêntico
ao modelo SVG
<filter>mas com tipos checados. - Blend modes: lista CSS Compositing & Blending Level 1.
8.1.1 Mesh gradient (Coons patch)
Mesh gradients permitem transições de cor em 2D ao longo de uma área 4-corner com lados curvos. Modelo: *oons patch*— define cores nos 4 cantos + curvas Bézier nos 4 lados. Bilinear (lados retos) é caso particular sem custo extra de sintaxe.
gradient #fruit-skin mesh {
// 4 cantos em ordem TL → TR → BR → BL (Y-up, então TL = top-left = [0,1])
corner [0, 1] color="#FFE5B0"
corner [1, 1] color="#FFA640"
corner [1, 0] color="#D04020"
corner [0, 0] color="#700"
// 4 lados — cada um straight ou bezier (até 2 controles)
edge top bezier=[[0.3, 1.1], [0.7, 1.1]]
edge right bezier=[[1.1, 0.7], [1.1, 0.3]]
edge bottom straight
edge left straight
}Todos os 4 lados straight ⇒ degenera em bilinear sem boilerplate extra. Coordenadas dos cantos no espaço normalizado [0, 1].
Razão da escolha (20260430): bilinear puro é meio-caminho que envelhece mal em ilustração premium e packaging design (diretrizes 6 e 7); Coons cobre ambos os casos com um único modelo. Custo de impl ~150 LoC amortizado para sempre.
8.2 3D (Solid)
- *BR metallic-roughness*(gltf 2.0 model):
baseColor,metallic,roughness,normal,emissive,occlusion.
- Texturas: raster embarcado (PNG/WebP) ou procedural (gradient como
texture).
- Lighting: directional, point, spot, IBL (cube ou equirect HDR
embarcado, comprimido com Koder kodec-img).
8.3 Shader graph (extensão futura)
Profile *VGShade*(nãov0.1, deixado para v0.2+): grafo declarativo de shader unificando filter graph 2D e PBR 3D. Excluído do escopo desta proposta para limitar v0.1.
9. Animation & Motion
9.1 Timeline
[[timeline]]
id = "intro"
duration = 1.2 # seconds
loop = "once"
[[timeline.track]]
target = "core" # node id
property = "transform.scale"
keyframes = [
{ t = 0.0, value = 0.0, easing = "ease-out-cubic" },
{ t = 0.6, value = 1.05, easing = "ease-in-out" },
{ t = 1.0, value = 1.0 },
]9.2 State machine
[[state-machine]]
id = "idle-hover-press"
default = "idle"
[[state-machine.state]]
name = "idle"
[[state-machine.state]]
name = "hover"
[[state-machine.state]]
name = "press"
[[state-machine.transition]]
from = "idle"
to = "hover"
trigger = "pointer.over"
duration = 0.15
easing = "ease-out"
[[state-machine.transition]]
from = "hover"
to = "press"
trigger = "pointer.down"
duration = 0.08State change interpola valores de propriedades animáveis declaradas em cada estado.
9.3 Constraints
IK 2bone, followpath, look-at 2D. Lista exaustiva fica para v0.2+.
10. 3D solids
Estrutura mínima para Solid:
[[node]]
id = "hero-glb"
type = "mesh"
mesh = "hub-mesh-01"
material = "hub-material-01"
[[asset.mesh]]
id = "hub-mesh-01"
primitives = [
{ mode = "triangles", indices = "buf:0", positions = "buf:1", normals = "buf:2", uvs = "buf:3" }
]
[[asset.material]]
id = "hub-material-01"
type = "pbr-mr"
baseColor = "#3B82F6"
metallic = 0.3
roughness = 0.4
normalTexture = "tex:hub-normal"
[[asset.buffer]]
id = "buf:0"
data = "base64:..."Importação direta de .glb é suportada via converter kvg import gltf, que aterriza meshesmaterialsanimations como [[asset.*]] blocks.
11. Extensão: kdef e kgen
KVG suporta dois mecanismos de extensão no source. Ambos vivem *o próprio arquivo*que os consome — nunca em arquivos separados, nunca buscados por URL. Auto-suficiência do documento é regra dura (§12).
Ambos os mecanismos rodam código escrito na *SL kgen* especificada em §13. Não há campo lang — só existe uma DSL.
11.1 kdef — primitivas customizadas reutilizáveis
kdef define um tipo novo de nó como uma expansão para primitivas-base ou para outras kdefs já definidas no mesmo arquivo:
kdef #spring extends=path params=[start, end, coils, amplitude] {
expand """
let pts = [start]
let segments = coils * 2
for i in range(segments)
let t = (i + 1) / segments
let mid = lerp(start, end, t)
let off = if i % 2 == 0 then amplitude else -amplitude
pts.push([mid.x, mid.y + off])
end
pts.push(end)
pts
"""
}
scene {
spring #shock-absorber start=[50,100] end=[200,100] coils=8 amplitude=12
}Pipeline do parser:
- *ass 1* coleta todas as declarações
kdefdo documento. Ordemde aparição não importa.
- *ass 2* ao encontrar um nó cujo
TYPEcasa com um id de kdef(
spring, no exemplo), busca primeiro as kdefs locais; se não achar, cai nas primitivas-base; se não achar, erroKVG-PARSE-UNKNOWN-TYPE-NNNN. - *xpand* roda o bloco
expandno sandbox kgen; o resultado viranó da primitiva apontada por
extends. - *ender* renderer só vê primitivas-base — nunca soube que
springexiste.
11.2 kgen — geração procedural pontual
Para repetições e parametrizações que não merecem virar tipo nomeado:
kgen #build-satellites {
body """
let r = 125
for i in range(6)
let angle = (90 - i * 60) * PI / 180
emit_node(
id: "sat-" + i.to_s,
role: "hub.satellite",
type: shape_for(i),
cx: 256 + r * cos(angle),
cy: 256 - r * sin(angle)
)
end
"""
}kgen roda no *oad-time* no mesmo sandbox que o expand de kdef. A diferença: kgen emite nós direto, sem virar tipo reutilizável.
11.3 Regras duras (validador rejeita)
- *scopo local ao documento.*kdef definida em A não é visível em
B. Cada
.kvgé mundo fechado. - *em rebinding de primitivas-base.*
[[kdef]] id = "ellipse"éerro. Só extensão, nunca substituição.
- *em ciclos no grafo de dependência.*Se kdef A usa B e B usa A,
validador detecta e falha.
- *andbox kgen — sem I/O, sem rede, sem syscall.*O bloco
expandda
[[kdef]]e obodyda[[kgen]]só podem usar a stdlib kgen (§13) e os helpersemit_*providos pelo runtime. - *eterminismo.*Dado o mesmo input, expansão produz o mesmo output
bit
abit. Semrandomsem seed, sem timestamp, sem leitura externa.
11.4 Distribuição
O .kvgb binário *nlina o resultado*das expansões para parse mais rápido em runtime. O source .kvg texto *reserva*os blocos [[kdef]] e [[kgen]] para edição. Conversão kvg ↔ kvgb é round-trip do source completo (incluindo extensões), não só do output expandido — o autor nunca perde sua extensão ao ir e voltar.
11.5 Biblioteca de kdefs (camada de tooling, não de formato)
O Koder Dok mantém um catálogo de kdefs comuns (spring, gear, bezier-arrow, dimension-callout, gauss-bell, ...). Quando o autor "insere" uma do catálogo, o Dok *opia a definição*para dentro do arquivo aberto. O autor experimenta autocomplete e snippets; o arquivo salvo permanece auto-suficiente. Igual ao padrão de snippets do VSCode.
A biblioteca *ão é parte da especificação do formato*— é conveniência da ferramenta. Outras ferramentas KVG podem implementar suas próprias bibliotecas, ou nenhuma. O .kvg resultante funciona em qualquer renderer compliant.
12. Selfhostedfirst constraints
*egras duras*(decidido 20260430 — strict em v0.1, sem exceções):
- *ero URL externa*em nenhum campo do documento. Validador rejeita
http://,https://,//cdn.x.y/,file://,koder://, e qualquer outro scheme — apenas referências internas (#id) são válidas. - *onts embarcadas*como
asset fontem base64 (TTFOTFWOFF2). - *exturas raster*embarcadas como
asset textureem base64(PNG, WebP, AVIF). Recomenda
se passar pela compressão do kodecimg antes de embed. - *cripts*são kgen inline ou referência por
ida outrokgeninterno. Sem
importourequirede qualquer fonte externa. - *rofile dependencies*(Motion, Solid) são parte da especificação
carregada pelo runtime — nunca buscadas em runtime.
kvg validate <file> falha o documento se alguma regra acima for violada.
Razão (20260430)
A flexibilização foi avaliada e rejeitada para v0.1. Opções consideradas:
koder://URI scheme com cache local — fragmenta determinismo, docdeixa de ser auto-suficiente.
- Refs content
addressable por hash (IPFSstyle) — interessante mascomplexidade desproporcional pra v0.1.
- Header opt
in (chave externalrefs allow) — fragmenta em dois mundos KVG.
Para casos pesados (texturas 4K, brand kit compartilhado), o pacote .kvg.zip (§4.3) já cobre — embarca binários num zip de conveniência sem violar selfhostedfirst.
Sob filosofia §0.4 (long-term): é mais fácil *lexibilizar v0.2 se demanda concreta aparecer*do que retirar permissão depois. Strict primeiro é a aposta segura. Caminho preferencial para v0.2+ se for o caso: hash content-addressable (preserva determinismo, agnóstico de transporte).
13. kgen — language reference v0.1
A DSL embarcada usada pelos blocos [[kdef]] e [[kgen]]. Frozen em v0.1; mudanças futuras viram v0.2 com profile opt-in. Esta seção é a spec completa — implementadores não precisam de mais nada.
13.1 Filosofia
kgen é *urposebuilt* não é subset de Koder Koda. Sintaxefamília de KL (mesmas keywords) mas semântica própria. Alvo de implementação: ~500 LoC parser, ~1.000 LoC interpreter treewalking, total ~50100 KB compilado por renderer.
13.2 Tipos primitivos
| Tipo | Exemplo | Notas |
|---|---|---|
int |
42, -7 |
64 bits sinalizado |
float |
3.14, 1e-5 |
IEEE 754 double |
bool |
true, false |
|
string |
"abc", 'abc' |
UTF-8; sem regex, sem format |
vec |
[1, 2, 3] |
1D-Nd; KVN compatível |
mat |
mat([[1,0],[0,1]]) |
matriz NxM |
list |
[1, "a", true] |
heterogênea |
hash |
{a: 1, b: 2} |
string→valor |
range |
range(0, 10) |
iterador finito |
null |
null |
ausência |
13.3 Operadores
aritméticos: + - * / % **
comparação: == != < > <= >=
lógicos: && || !
acesso: . [ ]Todos componentwise sobre vec e mat ([1,2] + [3,4] → [4,6]).
13.4 Controle de fluxo
let x = 10
if x > 5 then
...
else
...
end
for i in range(0, 6)
...
end
each item in lista
...
end*ão tem* while, loop, goto, break, continue, recursão, closures, exceptions. Loops são bounded por construção (range ou each).
13.5 Funções declaradas
fn distance(a, b)
let d = b - a
return sqrt(d.x * d.x + d.y * d.y)
endFunções são puras, top-level, sem closures. Podem chamar outras funções declaradas no mesmo bloco. *ecursão proibida*— validador detecta e falha. Para repetição, usar for ou each.
13.6 Builtins (~30, congelados em v0.1)
*atemática escalar* abs floor ceil round trunc sqrt pow exp log min max clamp sign
*rigonométricas* sin cos tan asin acos atan atan2
*etoriais* vec length normalize dot cross dist angle_between
*atriciais* mat identity transpose inverse multiply translate rotate scale
*nterpolação* lerp smoothstep mix step
*onversão / string* to_s to_i to_f concat
*onstantes* PI E TAU INF NAN
13.7 Helpers de runtime (injetados pelo KVG)
Apenas dentro de [[kgen]] body ou [[kdef]] expand:
| Helper | Retorno | O que faz |
|---|---|---|
emit_node({...}) |
nó | cria um [[node]] na cena |
emit_path(d, opts) |
nó | cria nó path com KPN |
emit_connector(from, to, opts) |
nó | linha entre dois pontos |
param(name) |
valor | acessa [[kdef]].params[name] |
viewport() |
[w, h] ou [w,h,d] |
dimensões da viewport |
13.8 Sandbox — proibições
- *em IO.*Nenhuma função abrelê arquivo, socket, dispositivo.
- *em rede.*Nenhuma chamada HTTP, DNS, etc.
- *em syscalls.*Sem
exec,fork,signal,time.now. - *em fontes não-determinísticas.*
randomexige seed explícito;timenão existe; ordem de iteração de hash é estável. - *em dynamic code.*Sem
eval,parse,import,require. - *em mutação global.*Variáveis declaradas com
letsão locaisao bloco; sem globals.
- *ounded execution.*Loop limit configurável (default: 1.000.000
iterações totais por bloco); estouro = erro
KGEN-LIMIT-EXCEEDED.
13.9 Determinismo
Implementação compliant deve garantir *it-exact reprodução*entre renderers para o mesmo input. Especificamente:
- Aritmética float segue IEEE 754, ordem de operações canônica
(esquerda→direita, respeitando precedência).
for i in range(...)itera em ordem crescente.eachsobre hash itera em ordem de inserção.random(seed)usa xorshift64 com algoritmo specificado em §13.11.
13.10 Gramática EBNF (resumida)
program = (statement | function-decl)*
statement = let-stmt | if-stmt | for-stmt | each-stmt | expr-stmt | return-stmt
let-stmt = 'let' IDENT '=' expression
if-stmt = 'if' expression 'then' statement* ('else' statement*)? 'end'
for-stmt = 'for' IDENT 'in' expression statement* 'end'
each-stmt = 'each' IDENT 'in' expression statement* 'end'
function-decl = 'fn' IDENT '(' params ')' statement* 'end'
expression = literal | IDENT | unary | binary | call | access
binary = expression op expression
op = '+' | '-' | '*' | '/' | '%' | '**' | '==' | '!=' | '<' | '>' | '<=' | '>=' | '&&' | '||'
literal = INT | FLOAT | STRING | BOOL | NULL | vec-lit | hash-lit
vec-lit = '[' (expression (',' expression)*)? ']'13.11 Implementação de referência
A spec do parser, interpretador, e algoritmos de determinismo (xorshift seed, ordem de hash, IEEE 754 rounding) vivem em engines/lang/kvg/kgen/SPEC.kmd (a criar quando começar implementação). Esta §13 é o contrato; aquela é o blueprint de código.
14. Profile conformance
Documento declara profile Full (alias canônico — equivale a Core+Motion+Solid). Renderer declara capabilities como conjunto, ex: ["Core", "Motion"] (= Animated). Algoritmo:
if profile_doc ⊆ profile_renderer:
render normally
else:
render best-effort (drop unsupported nodes)
emit conformance warning to hostNó individual pode declarar requires = "Solid"; se renderer não tem, nó é silenciosamente substituído pelo seu fallback opcional (um nó 2D estático equivalente). Mecanismo análogo ao <switch> do SVG.
15. Reference toolchain
| Componente | Papel | Status v0.1 |
|---|---|---|
engines/lang/kvg/spec |
Esta spec, schemas JSON/CBOR | Esta proposta |
engines/lang/kvg/parser |
Lib Koder Koda: parse .kvg → scene tree |
A implementar |
engines/lang/kvg/render |
Renderer KVG-Core (Skia backend LinuxAndroid, CoreGraphics iOSmacOS, Canvas2D web) | A implementar |
engines/lang/kvg/render-3d |
Renderer KVG |
A implementar |
engines/sdk/kvg-flutter |
Flutter widget <KvgScene> |
A implementar |
products/horizontal/dok |
Editor canônico, preview ao vivo, export para SVGPNGglTF | Integração a planejar |
products/dev/kicon |
Consome .kvg como source preferencial; gera variants per-platform usando role semantics |
Integração a planejar |
kvg CLI |
kvg validate / convert / build / explode |
A implementar |
16. Migration paths
| De | Para KVG | Estratégia |
|---|---|---|
| SVG | KVG-Core | kvg convert <file>.svg mapeia 1:1 (path, gradient, filter); roles inferidos por classes/ids; viewport + transform mantidos |
| Rive | KVG-Core+Motion | parser do .riv (open spec) extrai timeline + state machine; primitivas vetoriais convertem para KVG paths |
| Lottie | KVG-Core+Motion | parser JSON; expressões After Effects (subconjunto) convertem para easing curves nomeadas |
| glTF | KVG-Core+Solid | meshmaterialanimation 1:1; cenas multi-mesh viram grupos KVG |
| PNG/WebP raster | KVG-Core wrapper | embed como [[asset.texture]] num único nó image — fallback para quem só tem raster |
Round-trip não é garantido em geral (ex: KVG → SVG perde Motion); apenas SVG → KVG e KVG-Core → SVG são lossless por design.
17. Open questions (a resolver antes de v0.2)
- *ource syntax*(decidido 2026
0430): KSS — KVG Source Syntaxpurpose
built, KDLinspired, com hierarquia nativa via{ }, identificadores bare, IDs#prefixados(CSS-style), atributos posicionais + nomeados, notações inline (KPNKCNKVN), comentários//e. Spec da gramática em §4.1. Razão: TOML emprestado força hierarquia flatcomparent-ref (diretriz #1 e #2 sofrem) e[[node]]repetitivo (diretriz #9 sofre). KSS coerente com a filosofia purpose-built do resto da stack (kgen, KPNKCNKVN). - *rofile name*(decidido 2026
0430): aliases canônicosCore/
Animated/Spatial/Fullno header; forma concat-explícita (Core+Motion+Solid) também aceita pelo parser e normalizada para alias canônico pelokvg fmt. Declaração e mapeamento em §3.0. Razão: diretrizes #1 (limpo) e #9 (não verboso) ganham com aliases;kvg-Nnumérico foi rejeitado porque profiles não são cumulativos linearmente (não há número natural paraCore+Solidsem Motion). - *esh
gradient encoding**(decidido 202604-30)*: Coons patch emv0.1. Bilinear (lados retos) é caso particular sem boilerplate extra. Razão: diretrizes #6 (cores em todas notações) e #7 (CAD a cinema) só ficam ★★★★★ com Coons; bilinear envelhece mal em ilustração premium. API e exemplo em §8.1.1.
- *cessibilidade*(decidido 2026
0430): cinco camposa11y.*por nó (label, role, description, decoration, labelledby). Spec em §6.1. Razão: cobre 100 % dos casos relevantes para conteúdo gráfico sem invadir o leque de WAI-ARIA específico de widgets interativos.
a11y.liveea11y.flowtodiferidos para v0.2+ — só fazem sentido com Motion shipado e demanda concreta de diagramas editoriais. - *treaming / progressive load* assets pesados podem ser carregados
sob demanda? (Conflita com self
hostedfirst se requer rede; aceitável se tudo está num.kvg.ziplido stream do disco.) - *ersionamento*(decidido 2026
0430): semver no header(
kvg-version "0.1.0"obrigatório) + capability strings opcionais por nó (requires=[...]comfallback). Imutabilidade do legado: nenhuma primitiva removida em minor/patch; major bump exige ferramentakvg upgrade. Detalhes em §4.4.
18. Roadmap (decidido 20260430)
*acing* spec + Core impl em paralelo (co-evolução, modelo A2). Filosofia §0.4 não exige serial puro — exige cuidado de design; co-evolução com loops curtos satisfaz e revela ambiguidades cedo.
*ompanhia da spec* híbrido (B3) — source em meta/docs/stack/specs/kvg/format.kmd (single source of truth); projeção HTML pública em kvg.koder.dev (renderizada via kmd render --standalone ao build).
| Fase | Escopo | Estimativa |
|---|---|---|
| Spec v0.1 freeze | Este documento marcado como tag kvgspecv0.1.0. | done |
| Core impl em paralelo | Parser KSS + renderer SkiaCanvas + CLI kvg validate / convert / build, em engineslangkvg. Loops curtos com a spec — refinos viram patch v0.1.1. | 4-6 semanas |
| Revisão externa | 1-2 autores externos (industry contacts) + devs Koder revisam spec após primeiras 2 semanas de impl. Ajustes ⇒ patch v0.1.1. | +1 semana |
| Dok integration | Editor live preview + export para SVGPNGglTF. | +3 semanas |
| Subir kvg.koder.dev | Site público com spec rendered + playground + Hub icon vivo + link pro repo. | 2 semanas em paralelo |
| Motion impl | Timeline + state machine + 3 constraints (look |
6-8 semanas |
| Solid impl | Filament backend + Coons mesh-gradient renderer. Migrar hero icon piloto para 3D. | 8-10 semanas |
| kicon integration | kicon lê .kvg como source preferred; usa role semantics para layout per |
+2 semanas |
Total para stateoftheart utilizável em produção: *56 meses*com 1-2 engenheiros dedicados.
19. Decision needed from the user
Antes de avançar para implementação, esta proposta v0.1 precisa de direção em:
- [x] *rofile boundaries*— CoreMotionSolid é o slice certo, ou
mover algo (constraints? text
onpath?) entre profiles? → *ecidido (20260430):*Profiles aditivos CoreMotionSolid conforme §3. Razão: única opção compatível com diretriz #10 (Core renderer < 200 KB factível) e #9 (não verboso — paga só o que usa). Refinamento permitido: nós individuais podem declararrequires+fallbackpara graceful degradation dentro do profile (mecanismo já em §14). - [x] *ource syntax*— TOML-superset, ou outra escolha?
→ *ecidido (2026
0430):*KSS — KVG Source Syntax purpose-built, KDLinspired, descrita em §4.1. Coerente com a filosofia purposebuilt do resto da stack (kgen, KPNKCNKVN). - [x] *istema de coordenadas*— Y
up (matemático, glTF) ou Ydown(SVG, Canvas)? → *ecidido (2026
0430):*Y-up everywhere (Cartesiano padrão). Razão: convenção matemática ensinada em escola universalmente; alinha com 3D inteiro (glTF, Blender, Maya, Unity, USD, OpenGL); alinha com CADengenhariaplots científicos. Y-down do SVG é artefato histórico de raster scan de CRT, não convenção humana. Importadores de SVG aplicam flip uma vez nokvg convert. Detalhes na §5. - [x] *onstraints scope no profile Motion*— IK / follow-path /
look-at todos em v0.1 ou diferir parte? → *ecidido (2026
0430):*todas as três em v0.1. Razão: constraints são primitivas universais em ferramentas vetoriais maduras (Rive, Lottie, AE, Maya, Blender); API design já bem-trodden; performance nativa ordens de magnitude > emulação kgen; autores não querem reimplementar matemática vetorial. Detalhes em §3.2. - [x] *elf
hostedfirst regras*— alguma flexibilização aceitável (ex:permitir
koder://URI scheme para resolução offline em cache local)? → *ecidido (20260430):*zero flexibilização em v0.1. Self-hosted é diretriz dura; abrir exceção convida outras. Para casos pesados,.kvg.zip(§4.3) já cobre. Caminho preferencial v0.2+ se demanda aparecer: hash content-addressable. Detalhes em §12. - [x] *oadmap pacing*— começamos pelo Core impl + Dok preview, ou
ratificamos a spec primeiro com revisão externa? → *ecidido (2026
0430):*modelo A2 — spec v0.1 freeze + Core impl em paralelo. Revisão externa após 2-3 semanas de impl, refinos viram patch v0.1.1. Filosofia §0.4 não exige serial puro — exige cuidado de design; co-evolução com loops curtos revela ambiguidades. Detalhes em §18. - [x] *ompanhia da spec*— abrir um repo público
meta/docs/stack/specs/kvg/(este path) ou domínio própriokvg.koder.devdesde o dia 1? → *ecidido (20260430):*modelo B3 — híbrido. Source emmeta/docs/stack/specs/kvg/format.kmd(single source of truth); projeção HTML pública emkvg.koder.devrendered viakmd render --standaloneao build. Selfhostedfirst identity preservada + presença pública estratégica para "padrão aberto". Detalhes em §18.
*odas as 10 perguntas críticas de v0.1 estão decididas.*Próximo passo: freeze v0.1 da spec + começar Core impl em engines/lang/kvg/.
Apêndice A — Exemplo completo: ícone Koder Hub em KVG-Core
kvg-version "0.1.0"
profile Core
viewport 0 0 512 512
title "Koder Hub icon"
meta {
role "product-icon"
brand "Koder Hub"
slug "khub"
}
// --- gradients ---
gradient #blue-sphere radial center=[0.35, 0.35] radius=0.7 {
stop 0.00 "#BFDBFE"
stop 0.35 "#3B82F6"
stop 1.00 "#1E3A8A"
}
gradient #amber-square radial center=[0.35, 0.35] radius=0.7 {
stop 0.00 "#FDE68A"
stop 0.35 "#F59E0B"
stop 1.00 "#B45309"
}
gradient #emerald-triangle radial center=[0.35, 0.35] radius=0.7 {
stop 0.00 "#A7F3D0"
stop 0.35 "#10B981"
stop 1.00 "#047857"
}
// --- procedural satellites (kgen) ---
kgen #satellites {
body """
let r = 125
let satellites = [
{ angle: 90, shape: "rect", gradient: "amber-square", role: "hub.satellite.square.top" },
{ angle: 30, shape: "ellipse", gradient: "blue-sphere", role: "hub.satellite.circle.upper-right" },
{ angle: -30, shape: "triangle", gradient: "emerald-triangle", role: "hub.satellite.triangle.lower-right" },
{ angle: -90, shape: "rect", gradient: "amber-square", role: "hub.satellite.square.bottom" },
{ angle:-150, shape: "ellipse", gradient: "blue-sphere", role: "hub.satellite.circle.lower-left" },
{ angle: 150, shape: "triangle", gradient: "emerald-triangle", role: "hub.satellite.triangle.upper-left" },
]
each s in satellites
let cx = 256 + r * cos(s.angle * PI / 180)
let cy = 256 + r * sin(s.angle * PI / 180) // Y-up: positive sin → up
emit_connector(from: [256, 256], to: [cx, cy])
emit_satellite(s.shape, cx, cy, gradient: s.gradient, role: s.role)
end
"""
}
// --- core ---
scene {
ellipse #core role="hub.center" 256 256 r=48 fill=#blue-sphere
}Quando rasterizado em 512×512 produz a v2.29.96 atual do ícone do Hub — em ~40 linhas de source contra 47 do SVG equivalente, ~50% mais compacto que a versão TOML anterior, mais expressivo sobre a estrutura ("o que é cada elemento"), e queryable por role.
Fim do documento v0.1. Comentários inline ou via PR no monorepo.