Passo 3 · Fundamentos · Fundamentos · Capabilities atômicas
Curso do Produto Alembic · Visual Course

Capabilities atômicas: os tijolos offline de $0

Ao fim desta lição você vai saber exatamente o que cada comando atômico faz — embed, ocr, triage, notes, context-pack, memory — e por que eles compõem para cima: vamos vetorizar o signal "fábrica de petições personalizadas", triá-lo, e guardar a nota da reunião da C.D Advocacia na memória — tudo offline, determinístico e a custo zero.

Leia primeiro (fonte primária)
apps/cli/src/commands.ts — "o wiring real de cada comando atômico"

Cada brick desta lição é uma função run<Comando> deste arquivo, que escolhe um backend offline determinístico por padrão e devolve Result<T, Error>. É daqui que sai cada string de saída que você vai ver — nunca da memória paramétrica.

Leia a versão simples, ou abra a camada técnica em qualquer seção.
1

A grande ideia


Suposições tolas (o que presumimos de você)
  • Você sabe abrir um terminal e digitar um comando. Só isso.
  • Você leu (ou vai ler) a Lição 0002: o funil destila um corpus em LEARNINGS + SIGNALS. Aqui descemos um nível: as ferramentas de que o funil é feito.
  • Você não precisa saber o que é um "embedding", "OCR" ou "token budget" — cada termo é definido no primeiro uso.

O Alembic não é um programa gigante e monolítico. Ele é feito de tijolos pequenos. Cada tijolo faz uma única coisa, faz bem, e pode ser encaixado em cima de outro. Esta lição apresenta seis desses tijolos — os mais atômicos do produto:

embed
Texto → vetor de números
clique para virar
Transforma uma frase numa lista de 16 números — uma "impressão digital" estável. Serve de chave de cache e de plumbing de índice.
ocr
Imagem → texto
clique para virar
Lê o texto dentro de uma imagem (um print, um PDF escaneado). Offline devolve um placeholder estável; --online usa um servidor de OCR real.
triage
Issue → classificação
clique para virar
Classifica um chamado: severidade, categoria, prioridade 1–10 e labels canônicos (needs-triage…). Fecha em enums fixos.
notes
Transcript → notas
clique para virar
Extrai de uma transcrição: título, resumo, participantes, decisões e action items (cada um com dono e prazo ISO).
context-pack
Arquivos → pacote em 8 camadas
clique para virar
Empacota evidência para um agente em 8 camadas (L0…L7), com orçamento de tokens por papel/modelo e um manifesto com hash.
memory
Fato → linha gravada
clique para virar
Grava e lê memória em 5 sub-lojas (episodic/semantic/procedural/decision/transcript), cada uma um arquivo JSONL só-append.

Os seis compartilham três promessas: fazem uma coisa só, rodam offline e de graça por padrão (resultado determinístico, sem rede), e compõem para cima — a saída de um vira a entrada de outro, e juntos eles formam comandos maiores como o funil e o AI Employee.

Pense como… uma caixa de peças LEGO. Cada peça é simples e burra sozinha; o valor está em encaixá-las. Onde a analogia quebra: peças LEGO são mudas — estes tijolos devolvem Result (sucesso-ou-erro como valor), então quando um encaixe não fecha, ele avisa em vez de explodir.

seis peças simples cada uma: 1 trabalho compõem um comando maior funil · swarm · AI Employee
O valor não está em cada tijolo isolado, mas no encaixe: seis peças simples viram o funil, o swarm, a Iris.
Ao fim desta lição você será capaz de
  • Nomear os seis comandos atômicos e dizer a única coisa que cada um faz.
  • Explicar por que "offline e $0 por padrão" não é uma limitação, mas a disciplina central do produto.
  • Descrever o molde compartilhado: função pura + seam injetável + Result + fail-closed.
  • Ler a saída real de embed, triage, context-pack e memory e saber o que cada campo significa.
  • Encadear dois tijolos (vetorizar um signal → gravá-lo na memória) você mesmo.

Por baixo do capô

"Atômico" aqui tem um sentido preciso: cada comando é uma função pura sobre um seam (uma porta injetável — um backend de embeddings, um adapter de modelo, um FsPort de arquivos) que devolve um Result<T, Error> de @alembic/contracts. O comando não conhece a rede; ele recebe o seam e o chama. Em modo offline, o seam é uma implementação determinística e em-processo (sem rede, sem SDK, sem Math.random(), sem Date.now() — a VM de planos proíbe os dois). Com --online, o mesmo comando recebe um seam real (cliproxyapi, SGLang) e — crucialmente — falha fechado se o backend não estiver configurado, sem nenhuma tentativa de rede silenciosa.

Essa uniformidade é o que torna o produto componível e testável: como todo brick tem a mesma forma (entrada validada → seam → Result validado por Zod), o harness pode injetar fakes nos testes ($0, hermético) e modelos reais em produção sem mudar uma linha do comando.

2

Em uma imagem


Olhe a caixa de ferramentas de cima. Seis tijolos, uma entrada e uma saída cada — e a anatomia comum embaixo: entrada → seam → Result.

SEIS TIJOLOS ATÔMICOS · uma entrada → uma saída cada embed texto → vetor [16 dims] ocr imagem → texto triage issue → severidade/labels notes transcript → notas+ações context-pack arquivos → pacote L0..L7 memory fato → linha JSONL A ANATOMIA COMPARTILHADA (igual nos seis) entrada (validada Zod) seam injetável offline | --online Result<T,E> ok | err offline = determinístico, $0, sem rede · --online = backend real, falha fechado se ausente nunca lança exceção — o erro é um valor
Leia da esquerda → direita: cada tijolo tem uma entrada e uma saída; embaixo, o molde que todos compartilham. O signal "fábrica de petições" entra em embed como texto e sai como um vetor de 16 dimensões.
A wide illustration of an artisan's pegboard workshop wall holding six small, distinct hand tools hung in two neat rows, each tool clearly different in shape (a tiny vial of glowin
A wide illustration of an artisan's pegboard workshop wall holding six small, distinct hand tools hung in two
Por que isto importa para a missão: na Lição 0002 o funil engoliu um corpus de IA jurídica inteiro. Mas o funil não é mágica — por dentro, ele chama exatamente estes tijolos (vetorizar para indexar, ler imagens, extrair notas). Dominar os seis é dominar o vocabulário do qual todo o resto do produto é escrito.
3

Os seis tijolos, um a um


Um tour rápido. Para cada tijolo: o que faz, a cara da saída real (verbatim do CLI), e onde ele se encaixa na história da C.D Advocacia.

1 · embed — texto vira vetor

Você dá uma ou mais frases; ele devolve, para cada uma, uma lista de 16 números. Esse vetor é a "impressão digital" da frase. Vetores parecidos = textos parecidos (no modo --online real); no modo offline é uma impressão estável usada para plumbing e chaves de cache.

embed "fábrica de petições personalizadas" texto (1 string) embed vetor de 16 dims, cada componente em [-1, 1) model text-embedding-3-small
16 barras = as 16 dimensões. A mesma frase dá sempre o mesmo vetor (determinístico).
$ alembic embed "legal AI factory" — saída real (RESOURCES.md)
embed: 1 vector(s) of 16 dims (model text-embedding-3-small)
  preview: [0.2841, -0.5512, 0.1033, …]
OFFLINE ($0) --online impressão estável (hash) serve: cache, plumbing, índice determinístico, sem rede significado semântico serve: busca por similaridade backend real, pode custar
Mesmo comando, dois propósitos: offline é uma impressão para a tubulação; online é o significado de verdade.

2 · ocr — imagem vira texto

Aponte para uma imagem (um print de uma petição, um documento escaneado da C.D). Offline, ele devolve um texto-placeholder estável — útil para testar a tubulação sem GPU. Com --online, usa um servidor de OCR real (e exige a variável ALEMBIC_OCR_BASEURL, senão falha fechado).

Offline ≠ inútil O texto offline é literalmente OCR(<caminho-da-imagem>). Não é reconhecimento de verdade — é uma impressão estável da entrada, suficiente para validar que o pipeline está conectado antes de você gastar com o backend real.
imagem (petição) ocr texto + blocks + pages
Offline: o texto é OCR(<source>) — uma impressão da entrada, não reconhecimento real.

3 · triage — issue vira classificação

Cole o texto de um chamado; ele devolve severidade, categoria, uma prioridade de 1 a 10, e labels tirados de um vocabulário fechado de cinco: needs-triage, needs-info, ready-for-agent, ready-for-human, wontfix.

$ alembic triage "App crashes on login…" — saída real (RESOURCES.md)
triage: medium/question (priority 5/10)
  labels: needs-triage
  Offline deterministic triage placeholder (no model called)
texto do issue triage severity category priority 1–10 label (5 fixos) saída fechada em enums — nada de texto livre
A saída do triage é toda fechada: cada campo só aceita valores de uma lista pré-definida.

4 · notes — transcript vira notas

Dê o caminho de um arquivo de transcrição (a gravação da call de descoberta com a C.D). Ele extrai título, resumo, participantes, decisões e action items — cada ação com dono e prazo em ISO-8601, ou os sentinelas unassigned/unscheduled (nunca um "TBD" solto).

transcript (call C.D) notes título + resumo + participantes decisões action items (owner + due ISO)
Cada action item sai pronto para virar uma unidade de trabalho — com dono e prazo, ou um sentinela honesto.

5 · context-pack — arquivos viram um pacote em camadas

Dê uma lista de arquivos e um brief; ele monta um pacote de contexto em 8 camadas (L0 a L7) para alimentar um agente, com um orçamento de tokens por papel e por modelo, e um manifesto com hash de conteúdo. É o tijolo que prepara "tudo que o agente precisa saber" de forma estratificada.

$ alembic context-pack README.md --brief "…" — saída real (RESOURCES.md)
context-pack: ctxp_… (role validator, model claude-opus-4-8-max)
  layers L0..L7 · budget 5501/100000
arquivos context-pack 8 camadas L0..L7 budget 5501 / 100000
Os arquivos viram um pacote estratificado, com um id ctxp_… (hash) e um orçamento de tokens medido.

6 · memory — um fato vira uma linha gravada

Grava (ou lê) um registro numa de cinco sub-lojas de memória, cada uma um arquivo .jsonl só-append. É como o produto lembra de coisas entre execuções: o que aconteceu, o que aprendeu, o que decidiu.

$ alembic memory episodic add/list — saída real (RESOURCES.md)
memory episodic: appended mem-1 (agent demo)
# depois:
memory episodic: 1 record(s) … mem-1 [agent demo]
--record {…} memory add {… mem prévio …} {… mem prévio …} + {mem-1, agent, at} ← nova episodic.jsonl (só-append)
Gravar é sempre acrescentar uma linha no fim. As linhas antigas nunca mudam — é o que torna a história auditável.
Recall rápido: dos seis, quais nunca chamam um modelo de linguagem nem no --online? embed (usa um modelo de embeddings, não de texto) e memory (puro IO de arquivo) — os outros quatro podem rotear um modelo de texto quando online.

De onde vêm (proveniência)

embed e ocr são pacotes próprios (@alembic/embeddings, @alembic/ocr), cada um com um backend offline e um online. triage e notes são templates tipados de @alembic/hermes — reescritas em idioma Alembic de agentes do catálogo 500-AI-Agents-Projects (a triage vem do agente 07-github-issue-triager; a notes do 10-meeting-notes-agent), só que com saídas fechadas em enums e validadas por Zod em vez do JSON livre do original. context-pack vive em @alembic/council. memory é o multi-store de @alembic/hermes — um ADAPT do subsistema de memória do Agent Swarm, trocando MongoDB/Redis por JSONL só-append sobre FsPort.

A wide illustration of a single universal tool-press mold on a workbench, with six different small raw inputs lined up to be pressed through the SAME mold one by one — each input e
A wide illustration of a single universal tool-press mold on a workbench, with six different small raw inputs
4

O molde compartilhado


Aqui está o pulo do gato. Seis comandos diferentes, mas uma forma só. Entenda a forma uma vez e você entendeu os seis — e qualquer comando futuro que siga o molde.

Preveja antes de revelar

Você roda alembic embed "oi" --online mas o gateway de modelos não está ligado nem o token configurado. O que acontece?

O comando falha fechado: ele faz um preflight do provedor, vê que está ausente, e devolve um err(Error) com mensagem acionável — sem tentar a rede e sem gastar nada. A regra do produto é "fail-closed": diante da dúvida, pare e avise; nunca prossiga às cegas. (No offline, o mesmo comando simplesmente usa o backend determinístico e responde na hora.)
1 · entrada validada por Zod --online? não (default) seam offline determinístico em-processo · $0 · sem rede sim preflight do backend real cliproxyapi · SGLang presente? err(Error) ausente → falha fechado não Result<T, Error>
O mesmo molde nos seis: valida a entrada → escolhe o seam (offline por padrão, online sob flag) → o online faz preflight e falha fechado se ausente → tudo deságua num Result. O erro é sempre um valor, nunca uma exceção.
Offline (o default)

Backend determinístico, em-processo. Mesma entrada → mesma saída, sempre. Custo $0. Sem rede. Perfeito para testes herméticos, CI e para você experimentar sem configurar nada.

--online (opt-in)

Troca o seam por um backend real (cliproxyapi para embed/triage/notes/context, SGLang para ocr). Faz preflight; se o backend não estiver lá, devolve err sem tentar a rede. Pode custar dinheiro — por isso é explícito.

--online backend presente? não err gasto = $0 · sem rede sim chama o backend real
Sem backend, o cadeado fica fechado: err, $0, zero rede. Um flag sozinho nunca gasta — a confiança é estrutural.
Guarde isto "Offline por padrão, online sob flag, sempre fail-closed" é a regra que se repete em todo o produto — não só nestes seis tijolos, mas na marketing factory (trava de gasto), no AI Employee (dry-run) e no funil. É a espinha dorsal da confiança: nada gasta nem chama a rede sem você pedir.

O seam é o ponto de injeção

Em código, cada comando recebe o backend como um argumento ({ backend }) ou resolve um adapter via resolveTemplateAdapter(args.online, deps). A função de domínio (embed, triageIssue, buildLayeredContextPack) nunca instancia a rede; ela só conhece a interface do seam. Isso é injeção de dependência levada a sério: o teste passa um fake, a produção passa o real, e a função do meio não muda. É a mesma "cintura estreita" da Lição 0001 (Result<T,Error>) aplicada às fronteiras de IO.

O determinismo é uma invariante, não um detalhe: os backends offline são proibidos de chamar Date.now() e Math.random() (a VM de planos rejeita ambos). É por isso que o mesmo comando, com a mesma entrada, produz bytes idênticos — o que torna cache, replay e testes de regressão confiáveis.

5

No código


Dois trechos reais. Primeiro, como o embed offline fabrica um vetor sem rede. Depois, a corrente fail-closed do triage.

packages/embeddings/src/offline-backend.ts
// 16 slots; cada slot dobra TODOS os char codes (com a posição)
// num acumulador de 32 bits, depois esmaga em [-1, 1). Puro.
export const OFFLINE_DIMENSION = 16;
const SLOT_SEED = 0x9e3779b1;  // recíproco da razão áurea

const foldSlot = (text, slot) => {
  const multiplier = (SLOT_SEED * (slot + 1)) >>> 0;
  let acc = (slot + 1) >>> 0;
  for (let i = 0; i < text.length; i += 1) {
    const mixed = Math.imul(acc ^ (text.charCodeAt(i) + i + 1), multiplier) >>> 0;
    acc = (mixed + ((acc << 5) >>> 0)) >>> 0;
  }
  return acc;  // squash(acc) = (acc - 2^31) / 2^31  → [-1, 1)
};

Sem rede, sem modelo, sem Math.random(). É um hash polinomial: cada uma das 16 posições mistura os mesmos caracteres com um multiplicador diferente, então frases distintas geram vetores distintos — de forma reprodutível.

packages/hermes/src/templates/issue-triage.ts
export const triageIssue = async (rawInput, model) => {
  // 1) valida a entrada no limite — título vazio falha fechado
  const inputCheck = issueTriageInputSchema.safeParse(rawInput);
  if (!inputCheck.success) return err(toError(inputCheck.error));

  const result = await model.adapter.run(runInput);
  if (!result.ok) return err(new Error(result.error.message));

  // 2) extrai o JSON do texto do modelo (tolerante a prosa)
  const parsed = extractJsonObject(result.text);
  if (!parsed.ok) return err(parsed.error);

  // 3) valida a SAÍDA — enum errado / chave a mais falha fechado
  const validated = issueTriageOutputSchema.safeParse(parsed.value);
  if (!validated.success) return err(toError(validated.error));
  return ok(validated.data);
};

Quatro pontos de falha, cada um devolvendo err em vez de lançar: entrada inválida → adapter falhou → sem JSON → saída fora do schema. A função é pura sobre o adapter — ela não sabe se o modelo é real ou um fake offline.

Abra você mesmo (fonte primária)
packages/embeddings/src/offline-backend.ts — "o hash polinomial determinístico do embed offline"

O comentário do topo do arquivo explica em prosa por que isto NÃO é um embedding semântico — é uma impressão estável para plumbing e cache. A honestidade sobre o que offline é (e não é) é parte da disciplina.

Acesse você mesmo

No repo, os comandos são funções run<Comando> em apps/cli/src/commands.ts (busque por runEmbed, runTriage…). A lógica de domínio fica nos pacotes: packages/embeddings/src/embed.ts, packages/hermes/src/templates/issue-triage.ts. Rode qualquer um offline com, por exemplo, alembic embed "teste" — zero configuração, $0.

6

As 8 camadas do context-pack


De todos os seis, o context-pack é o mais rico — vale uma imagem própria. Ele estratifica o contexto de um agente em 8 camadas, da mais estreita (uma linha) à mais larga (o manifesto completo com hash). Assim, sob pressão de orçamento, dá para descartar as camadas de baixo valor e ainda manter o pacote reproduzível pelo hash.

L0 (estreita, 1 linha) → L7 (larga, manifesto com hash) L0 · brief L1 · repoMap (lista de arquivos) L2 · selectedFiles (arquivos inteiros) L3 · relevantSnippets (trechos + motivo) L4 · summaries (resumos comprimidos) L5 · debateState (fases anteriores) L6 · artifacts + constraints L7 · manifest (inventário SHA-256, 64 hex/arquivo)
Cada camada adiciona contexto sem apagar a de cima. L7 é a "certidão" do pacote: cada arquivo com seu hash SHA-256, tamanho e número de linhas — é o que torna o pacote reproduzível e auditável.
Determinismo de novo: nada aqui lê o relógio. O createdAt é injetado pelo CLI (resolvido do relógio no limite, formatado ISO), e o id do pacote (ctxp_…) e o do manifesto são hashes SHA-256 do conteúdo. Mesmos arquivos → mesmo pacote → mesmo id. É a mesma disciplina dos backends offline, aplicada a um artefato composto.
Exemplo trabalhado · empacotar contexto para a venture C.D
1
Você roda alembic context-pack GOAL.md proposta.md --brief "petições personalizadas p/ C.D" --role validator.
2
O CLI lê cada arquivo verbatim para L2 e os hasheia para o manifesto L7. Um arquivo ilegível falha o comando fechado (não monta um pacote pela metade).
3
Monta as 8 camadas, estima os tokens e compara com o orçamento (default 100000). A saída diz within budget ou OVER BUDGET.
4
Agora você: qual papel/modelo mudaria o orçamento? (Dica: --role e --model definem o par; o default é validator / claude-opus-4-8-max.)
7

Memória multi-store: as 5 sub-lojas


O memory não é uma caixa única. São cinco sub-lojas, cada uma para um tipo de lembrança, cada uma um arquivo .jsonl só-append em <dataDir>/memory/<substore>.jsonl. "Só-append" quer dizer: nunca se edita uma linha — correções são linhas novas. É o mesmo modelo do events.jsonl do harness.

CINCO SUB-LOJAS · cada uma um arquivo .jsonl só-append episodico que aconteceu semanticfatos aprendidos proceduralcomo fazer decisiono que se decidiu transcriptfalas brutas TODO registro carrega o mesmo envelope + o corpo da sua loja id: mem-1contador monotônico agent: demodono do registro at: 1719…epoch-ms (relógio injetado) + corpo da loja (ex.: episodic = episode, context, salience 0..1) leitura newest-first · linha corrompida é pulada, nunca fatal
Cinco lojas, um envelope comum (id/agent/at). O id vem de um contador monotônico (mem-1, mem-2…), nunca de randomUUID() — para ser determinístico em testes e replay.
Sub-lojaGuardaCampos do corpo (além do envelope)
episodicO que aconteceuepisode, context, salience (0..1, default 0.5)
semanticFatos aprendidos, citáveisfato + proveniência
proceduralComo executar uma tarefapassos / procedimento
decisionDecisões e seu racionaldecisão + justificativa
transcriptFalas brutas de reuniõestrechos de transcrição
Cuidado Não existe update nem delete in-place. Um log só-append é a forma do FsPort — uma "correção" é um registro novo que vence o antigo na leitura newest-first. Isso preserva a história e mantém o replay determinístico.
A wide illustration of five separate append-only ledger books standing in a row on a shelf, each book a different color and labeled with a small distinct icon (an hourglass, a ligh
A wide illustration of five separate append-only ledger books standing in a row on a shelf, each book a differ
8

Experimente: componha os tijolos


Aqui está a promessa de "compõem para cima" tornada tangível. Escolha os tijolos, ajuste a entrada, alterne offline/online, e veja a corrente rodar — a saída de um vira a entrada do próximo. Esta é uma simulação fiel das strings reais do CLI (nada chama a rede; é só o terminal aqui na página).

Compose the bricks · encadeie embed → memory

Clique nos tijolos para ligá-los na corrente (a ordem é fixa: cada um alimenta o próximo). Depois rode.

"fábrica de petições…" embed vetor memory mem-1 a saída de um vira a entrada do próximo é assim que tijolos atômicos viram um comando maior
A corrente do demo, desenhada: o signal → embed → o vetor → memory → o registro mem-1 gravado.
Note o encadeamento: o embed produz um vetor de 16 dims; a corrente grava esse fato na memory episodic como um registro mem-1. Dois tijolos atômicos, uma composição útil — exatamente como o funil e o AI Employee são construídos por dentro.
As Dez verdades das capabilities atômicas
  1. Cada tijolo faz uma coisa só — e por isso compõe com os outros.
  2. Offline e $0 é o padrão; --online é sempre uma escolha explícita.
  3. O resultado é sempre um Result<T, Error>o erro é um valor, nunca uma exceção.
  4. Os backends offline são determinísticos: mesma entrada → mesma saída, byte a byte.
  5. embed offline é um hash polinomial de 16 dims — uma impressão, não significado semântico.
  6. triage fecha tudo em enums e 5 labels canônicos — sem JSON livre.
  7. context-pack estratifica em 8 camadas (L0→L7) com orçamento de tokens e manifesto com hash.
  8. memory são 5 sub-lojas só-append; correções são linhas novas, nunca edições.
  9. Tempo e ids são injetados no limite (relógio + contador) — nunca Date.now()/randomUUID().
  10. Dominar estes seis é dominar o vocabulário do qual o funil, o swarm e o Employee são escritos.
Sou seu professor aqui — me pergunte o que ficou solto: "como o --online escolhe o modelo?", "o que é salience na memória?", ou "qual tijolo o funil chama primeiro?". Próxima lição (0004): subimos um andar — como o swarm e o harness orquestram um lead e seus workers, passando por todos os gates, para forjar o signal "fábrica de petições" numa venture.
9

Recapitulando


Passe pelos slides para fixar — depois teste-se nos três quizzes.

A grande ideia

Tijolos, não um monólito

Seis comandos atômicos — embed, ocr, triage, notes, context-pack, memory — cada um faz uma coisa só e compõe para cima.

A regra de ouro

Offline por padrão

Determinístico, $0, sem rede. --online é opt-in e falha fechado se o backend não estiver lá. Nada gasta sem você pedir.

offline · $0 (default) --online (opt-in)

O molde

Função pura + seam + Result

Entrada validada → seam injetável (offline ou real) → Result<T, Error>. A mesma forma nos seis — entenda uma, entendeu todas.

context-pack

8 camadas, L0 → L7

Da linha de brief (L0) ao manifesto SHA-256 (L7), com orçamento de tokens. Dá para descartar camadas sob pressão e ainda reproduzir pelo hash.

L7 manifest

memory

5 sub-lojas, só-append

episodic · semantic · procedural · decision · transcript — cada uma um JSONL. Correções são linhas novas; ids e tempo são injetados.

A história continua

O vocabulário do produto

O funil, o swarm e a Iris são escritos com estes tijolos. Vetorizamos e guardamos o signal "fábrica de petições" — na 0004, o harness o forja numa venture.

1 / 6setas
Teste-se (3 perguntas)
1 · O que significa "offline por padrão" para um comando atômico?
b. Offline = backend determinístico em-processo, $0, sem rede. --online opta por um backend real e falha fechado se ele estiver ausente. Não há download nem dependência de rede.
2 · O embed offline produz um vetor de 16 dimensões. O que esse vetor é?
c. É um hash polinomial determinístico dos char codes — uma impressão reprodutível, útil para wiring, cache e índice. O próprio comentário do arquivo diz que NÃO é um embedding semântico. (E nunca usa Math.random().)
3 · Por que a memória multi-store não tem update/delete in-place?
a. O log só-append é a forma idiomática do FsPort (espelha o events.jsonl do harness). Uma correção é um registro novo que vence na leitura newest-first — preserva a história e mantém o replay determinístico.