Lição 15 · Fusão v3 · Planf3: a meta-skill de planejamento ← índice
Alembic × Hermes — O Curso de Fusão v3 · Execução e planejamento

Planf3: a meta-skill de planejamento internalizada

O @alembic/planf3 é a "Internalized Planf3 planning meta-skill" (descrição do próprio package.json): a disciplina de transformar UM prompt num plano HTML autocontido — purpose, problem, solution, fases com checklists, comandos de validação — e daí derivar GOAL.md, o contrato e um alembic.plan.ts inicial. alembic plan "<prompt>" é a porta; o fallback determinístico garante que SEMPRE sai um plano usável, com ou sem modelo. Nesta lição: o fluxo completo, os extratores que fecham a ponte com o forge, e as 7 imagens de teaching que documentam a filosofia do pacote.

1

createPlan: LLM se der, template se não der

createPlan(userPrompt, options) (packages/planf3/src/index.ts:244–269) materializa plan.html em <outputDir>/<slug>/ (default .alembic/plans/). A decisão central está em generatePlanWithModel (packages/planf3/src/model.ts:69–108): offline ou sem adapters ⇒ undefined — e o chamador cai no template determinístico (defaultPlan, index.ts:148–233); online, roteia para o T2 mais barato via pickAdapter(Tier.T2) (ou o modelo pinado por --model via adapterForModel), pede um JSON no schema planContentSchema (types.ts:15–24: title, purpose, problem, solution, phases[] com min 1, validationCommands, questionables, notes) e valida na borda. O retorno carrega a etiqueta: source: 'llm' | 'fallback'.

packages/planf3/src/model.ts:74–77 — o guard que garante $0 offline
// trecho real, não editado
if (options.offline || options.adapters === undefined) {
  return undefined;
}

A robustez online também é defensiva: o texto do modelo passa por extractJsonObject (model.ts:17–35), que varre do último } de trás para frente até o { balanceado — "models wrap JSON in prose or fences, so we scan back… rather than trusting the whole reply" — e o resultado ainda precisa passar no planContentSchema.safeParse. Modelo que devolve lixo vira err tipado, e o comando cai no fallback (index.ts:259–265): o plano SEMPRE existe.

Pense como… um arquiteto com prancheta elétrica e régua-T: se a energia cair (offline), o desenho sai na régua-T — mais padronizado, menos personalizado, mas com TODAS as vistas obrigatórias. Onde quebra: um arquiteto cansado pula seções; o template não pula nunca — as 5 fases (Scope, Design, Build, Proof, Ship) e os 3 comandos de validação (pnpm -r typecheck, pnpm -r build, pnpm -w test) estão sempre lá (index.ts:170–223).

produto · 0007-factory-forge-cursos · s0
2

alembic plan: quatro artefatos de uma vez

O comando alembic plan "<prompt>" (runPlanCommand, apps/cli/src/commands.ts:2586–2647) não para no HTML. Depois do createPlan, ele chama loadPlanHtml (packages/forge/src/plan-loader.ts:21–44) para EXTRAIR os artefatos do próprio HTML e escreve, lado a lado no plan-dir: GOAL.md (o goal extraído), validation-contract.md ({ version:'1', assertions } — com fallback ['GOAL.md is concrete','tests pass','publish gate clears'] se o plano não listou validação, commands.ts:2618–2623) e alembic.plan.ts (o starter com fases scope/build/proof). Ou seja: a saída de alembic plan é EXATAMENTE a entrada de alembic run --goal … --plan … — e do Scope Gate da lição 11.

alembic plan "<prompt>" slugify → plans/<slug>/ --online? preflight do gateway fallback determinístico 5 fases fixas · source:'fallback' modelo T2 + Zod falhou? ⇒ cai no fallback plan.html autocontido, dark-mode nativo extratores (plan-loader / planf3) h1 → GOAL.md · seção validation → contrato starter alembic.plan.ts (scope/build/proof) alembic run --goal GOAL.md --plan alembic.plan.ts --yes saída do plan = entrada do Scope Gate
commands.ts:2586–2647 — um comando, quatro artefatos: plan.html + GOAL.md + validation-contract.md + alembic.plan.ts.
A ponte com o forge. Os extratores são funções públicas do planf3: extractGoalFromPlanHtml pega o <h1> (ou o primeiro parágrafo do purpose) e extractValidationFromPlanHtml varre os <li> da seção de validação (index.ts:276–304). O forge as consome em loadPlanHtml/compilePlanToModule (forge/src/plan-loader.ts:21–73) — um plano .html entregue ao runner vira um alembic.plan.ts irmão, gerado do próprio HTML. É por isso que ScopeInput.planPath aceita ".ts, .js, or planf3 .html" (forge/src/types.ts:15).
3

A anatomia do plano (e de onde ela vem)

O HTML gerado tem seções fixas — purpose, problem, solution, phases (cada fase com goal + checklist), validation (com o lembrete "🔁 The plan is not complete until every command passes", index.ts:135), questionables (opt-in via --questionable) e notes (index.ts:112–143). Essa anatomia não é invenção do pacote: é a skill Planf3 original internalizada — o diretório packages/planf3/skill/ (exportado como skillDir, index.ts:15) carrega o SKILL.md e 5 workflows: create-plan.md, build-plan.md, update-plan.md, update-references.md e image-generation.md.

plan.html <h1> título · tagline datada purpose · problem · solution phases: fase → goal → checklist ☐ validation: comandos + 🔁 até passar questionables (só com --questionable) notes — canvas livre GOAL.md contract.assertions extractGoalFromPlanHtml (index.ts:276–282) extractValidationFromPlanHtml (index.ts:290–304) skill/ internalizada SKILL.md + 5 workflows: create-plan.md build-plan.md update-plan.md update-references.md image-generation.md exportada como skillDir (index.ts:15)
A anatomia serve a três leitores — você, o time e os agentes — e os extratores fecham o circuito plano→run sem retrabalho manual.

Honestidade de superfície: o que NÃO está implementado

Duas funções exportadas lançam erro honesto em vez de fingir: updateReferences — "not implemented. No reference index is maintained by planf3 yet" (index.ts:355–359) — e generateImages — "not implemented. Add images manually or use an image-generation skill" (index.ts:367–374). Já updatePlan FUNCIONA: regenera o plano a partir de um change-prompt e sobrescreve o arquivo no mesmo diretório, preservando os irmãos GOAL/contrato (index.ts:333–348).

4

As 7 imagens de teaching do pacote

O pacote carrega seu próprio material didático: 7 imagens em packages/planf3/images/, referenciadas pelo README.md do pacote (linhas 11, 58, 64, 93, 115, 135 e 147). Elas documentam a FILOSOFIA da meta-skill — consulte-as no repositório (esta lição as cita por nome, de propósito, para você abrir as originais):

Arquivo (packages/planf3/images/)O que ensina (alt do README)
meta-skill-v5-multiplier-grid.pngUma meta-skill se multiplica em incontáveis planos
02_outsourced_planning.pngEntregar o plano a uma caixa-preta é entregar o resultado
03_templated_engineering.pngUm template carimba a mesma forma estruturada toda vez
04_plan_anatomy.pngA anatomia do plano — metadados, purpose, fases com checklists, loop de validação, notas
05_five_workflows.pngUm prompt roteado a um de cinco workflows dedicados
06_priorities.pngPerformance > velocidade > custo — gaste tokens para vencer
07_trifecta.pngUm plano, três leitores: você, seu time e seus agentes
produto · 0007-factory-forge-cursos · s2
7
imagens de teaching em packages/planf3/images/
5
workflows na skill internalizada (skill/workflows/)
33
comandos CLI — plan é a porta de planejamento deles
5

Cheque seu modelo mental

Sem --online, o que alembic plan "prompt" produz?
Correto: o guard de generatePlanWithModel devolve undefined offline (model.ts:74–77) e createPlan cai no defaultPlan (index.ts:259–265) — Scope, Design, Build, Proof, Ship + pnpm -r typecheck / build / -w test, sempre presentes. O plano existe SEM rede e SEM gasto; o modelo só melhora o conteúdo, nunca é pré-requisito.
E planf3.generateImages(planPath) — o que acontece ao chamar?
Correto: index.ts:367–374 lança "planf3 generateImages is not implemented. Add images manually or use an image-generation skill." As 7 imagens de packages/planf3/images/ são diagramas ESTÁTICOS do README (material de teaching), não saída do código — confundir os dois seria exatamente o tipo de fabricação que o pacote recusa declarando o não-implementado em voz alta.
Camada técnica — comandos copy-paste

Gerar um plano offline, inspecionar os 4 artefatos e abrir o material da skill:

# 1) plano offline ($0, determinístico; --online usa o T2 mais barato)
alembic plan "adicionar exportação CSV ao cockpit"
alembic plan "adicionar exportação CSV ao cockpit" --questionable

# 2) os quatro artefatos lado a lado
ls .alembic/plans/<slug>/
open .alembic/plans/<slug>/plan.html
cat  .alembic/plans/<slug>/GOAL.md
cat  .alembic/plans/<slug>/validation-contract.md

# 3) fechar o circuito: o plano vira run (Scope Gate, lição 11)
alembic run --goal .alembic/plans/<slug>/GOAL.md \
            --plan .alembic/plans/<slug>/alembic.plan.ts --yes

# 4) a skill internalizada e as 7 imagens de teaching
ls packages/planf3/skill/workflows/
ls packages/planf3/images/
grep -n 'images/' packages/planf3/README.md

# fontes desta lição
sed -n '244,269p' packages/planf3/src/index.ts   # createPlan
sed -n '69,108p'  packages/planf3/src/model.ts   # generatePlanWithModel
sed -n '2586,2647p' apps/cli/src/commands.ts     # runPlanCommand

Regra de leitura: o plano é um artefato para TRÊS leitores (você, o time, os agentes) — se um dos três não consegue agir a partir dele, a seção correspondente está fraca.

O que levar desta lição
Pergunta de acompanhamento sugerida: "os system prompts que o planf3, o forge e os workers usam — onde vivem, quem versiona, como evoluem?" — Próxima lição: @alembic/prompts — os prompts como artefato de engenharia versionado do monorepo.