Hot Path: alembic distill → Funnel T0-T3
Traçado completo e anotado linha a linha do caminho mais comum de execução do Alembic. Começa no CLI, injeta adapters, entra no runFunnel, passa por T0 (determinístico $0), T1 (extração local + gate PII), T2 (frontier com budget) e T3 (council + verifier). Todo passo ancorado em arquivo:linha real.
Visão Geral do Fluxo (SVG)
Estágios do Hot Path (Stepper)
Estágio 1 — CLI (apps/cli/src/commands.ts)
63|export const runDistill = async (args, deps) => {
68| const readable = await assertCorpusReadable(args.corpus);
69| if (!readable.ok) return err(...);
75| const adapters = buildRegistry(args.offline);
83| const report = await runFunnel(args.corpus, { adapters, budget, dataDir, fs: nodeFsPort });
90| renderDistill(...);
95| return ok(report);
}
err(). Nunca throw. Isso é a cintura do sistema (ver contracts/result.ts).Estágio 2 — Registry + Preflight (commands.ts:52 + config.ts)
52|const buildRegistry = (offline) =>
53| offline ? createAdapterRegistry({ offline: { asDefault: true } })
54| : createAdapterRegistry(liveRegistryOptions());
76|if (!args.offline) {
77| const pf = await preflightLiveProvider(adapters);
78| if (!pf.ok) return err(...);
}
offline: true, o adapter offline é bound em todos os tiers via asDefault. Run hermético $0 garantido.Estágio 3 — Entrada no Funnel (harness/src/funnel.ts:83)
83|export async function runFunnel(corpus, opts: FunnelOptions) {
...
260| const t0 = await runT0Pipeline(...);
...
// depois T1 extraction + emitSafeSignal (PII gate)
// T2 shortlist com BudgetGuard
// T3: council + verifyPanel
}
Estágio 4 — T0 Determinístico (etl/pipeline.ts + priors)
// T0 roda 100% do corpus (exceto Repos/Models + Prompts)
// dedupe por SHA-256, score 6 eixos, routesToResidue
// tudo antes de qualquer LLM
Estágio 5 — T1 + Gate PII (funnel.ts:243)
243|const emitSafeSignal = (entry) => {
244| if (!isPrivateChannel(...)) return ...
246| const redacted = redactSignal(...);
247| const gate = assertRedactedForEmit(redacted, channel);
248| return gate.ok ? redacted.signal : undefined; // fail-closed
}
Estágio 6 — T3 Council + Verifier (council/verifier*.ts)
// debate → aggregate → verifyPanel (faithfulness + domain lenses)
// quorum + dissent preservado
// loop > MAX → parkedTier = T4 (humano)
Anotações Linha-a-Linha Críticas
| Arquivo:linha | O que faz | Invariante |
|---|---|---|
apps/cli/src/commands.ts:68 | assertCorpusReadable via tryCatchAsync → Result | Never throws |
commands.ts:75 | buildRegistry injeta adapters (offline ou live) | Adapter-agnostic |
harness/src/funnel.ts:243 | emitSafeSignal + assertRedactedForEmit | PII gate |
etl/src/pii.ts:246 | redactSignal + gate antes de qualquer write | Fail-closed |
council/src/verifier-panel.ts | verifyPanel + quorum + preserve dissent | Dissent forçado |
packages/contracts/src/result.ts | ok/err discriminado, tryCatchAsync | Narrow waist |
Como Verificar Este Hot Path
pnpm build node apps/cli/dist/index.js distill /caminho/para/corpus --offline --json # ou pnpm factory # executa o ADW que usa o mesmo harness internamente
Observe no output: T0 sempre executa, T1/T2/T3 só tocam residue, custo só aparece em tiers pagos, e nenhum sinal privado sem redação chega ao store.
Common Confusions + Practice Task
Confusão 1: Achar que T1/T2/T3 sempre rodam. Não. Só o que passou no T0 (routesToResidue) chega neles. T0 é o filtro massivo e barato (ver etl/priors.ts + pipeline.ts:260). Residue é o único caminho para LLM.
Confusão 2: Achar que o PII gate é "depois do modelo". Falso. Em funnel.ts:243 o gate roda em emitSafeSignal antes de qualquer store write. Private channel → redact → assertRedactedForEmit → só então vira BusinessSignal.
Confusão 3: Achar que budget é só "número". Falso. createBudgetGuard envolve toda chamada T2/T3 (fail-closed). Se projeção excede, a chamada é bloqueada e o tier degrada.
Prática (toque o código real): 1. Rode alembic distill ./corpus --offline --dataDir /tmp/test1. 2. Abra /tmp/test1/_alembic-residue.jsonl. 3. Pegue um item de canal privado (whatsapp, discord etc). 4. Rode novamente com um adapter que não redige e observe t1PiiBlocked > 0 no report. 5. Depois leia emitSafeSignal em funnel.ts:243 e assertRedactedForEmit em etl/pii.ts. Anote as linhas.
Exercício avançado: Mude temporariamente o código de buildRegistry em commands.ts:52 para forçar offline mesmo sem flag. Rode o CLI. Observe que custoUsd fica 0 e nenhum adapter de rede é chamado. Depois desfaça e rode com --offline false (se tiver credenciais). Compare os dois FunnelReport.
Por que este caminho é o mais importante do sistema
Este é o único fluxo que todo usuário e todo job de factory toca quando quer destilar corpus em sinais de negócio ou learnings. Ele exerce simultaneamente as quatro invariantes centrais:
- Result nunca lança — do CLI até o último appendOpportunityRecord
- PII redaction + emit gate — obrigatório antes de qualquer dado privado sair
- Budget fail-closed — T2 e T3 nunca gastam mais que o configurado
- Append-only content-addressed — stores só crescem, nunca sobrescritos
Qualquer regressão neste path quebra a promessa de "destilação barata, segura e reprodutível" que justifica a existência do Alembic. Por isso todo novo adapter, toda mudança no verifier, todo ajuste de budget ou pii deve ser acompanhado de re-execução deste hot path com corpus de teste e inspeção do FunnelReport resultante. Este é o caminho de ouro que todo job de destilação e todo ciclo do factory percorre quando o objetivo é transformar corpus privado em sinais verificados sem surpresas de custo ou vazamento. Entender este fluxo linha a linha é pré-requisito para qualquer trabalho sério no engine.