Runtime autocontido
Como o motor do Apothem roda a partir de qualquer checkout — dependências internalizadas, o modelo de invocação PYTHONPATH=src e o bootstrap da árvore do plugin.
Runtime autocontido
O motor do Apothem é um runtime autocontido: ele roda sem registro de pacotes,
diretamente a partir de qualquer checkout ou árvore de código-fonte posicionada,
porque suas dependências de terceiros viajam com ele. Duas peças fazem isso
funcionar — uma árvore de dependências internalizadas e um modelo de invocação
python -m que não precisa de scripts de console instalados.
Árvore de dependências internalizadas
A pilha de validação e serialização é internalizada como código-fonte em Python
puro sob src/apothem/_vendor/, cada pacote ao lado do arquivo de licença do
seu projeto original:
yaml(o parser/emissor em Python puro; a extensão C opcional libyaml não é incluída)jsonschema, com sua cadeia de dependênciasattrs(e seu aliasattr),referencingejsonschema_specificationsrpds— um shim em Python puro que reimplementa a superfícieHashTrieMap,HashTrieSeteListquejsonschemaereferencingusam, apoiado em tipos embutidos, de modo que a pilha roda com zero extensões compiladastyping_extensions
As cópias internalizadas têm precedência sobre qualquer versão instalada no
sistema: o bootstrap do plugin, o shim do npm, os instaladores e o próprio ponto
de entrada python -m apothem colocam, cada um, o diretório vendor no
sys.path à frente de site-packages. A política de seleção — o que é
internalizado, o que não é e como os pacotes internalizados são atualizados —
está documentada na
estratégia de internalização de dependências.
Duas dependências ficam fora da árvore: click e rich, as bibliotecas
voltadas ao terminal que a CLI importa. Elas precisam ser importáveis no
interpretador que roda o motor; os instaladores verificam ambas, nomeiam
qualquer uma que esteja faltando e oferecem instalá-la para você — com sua
confirmação, ou automaticamente com --yes / APOTHEM_AUTO_INSTALL_DEPS=1. Em
todos os outros canais, o ponto de entrada verifica ambas com a biblioteca
padrão antes de importar a CLI, e a falta de uma delas o interrompe com um erro
que nomeia o comando pip exato para o interpretador em execução (um envelope
JSON com o código runtime.dependency_missing sob --json).
O modelo de invocação python -m
O Apothem intencionalmente não declara scripts de console no pyproject.toml —
scripts de console só existem quando um gerenciador de pacotes os coloca no
PATH, e o runtime autocontido nunca pressupõe um. Em vez disso, o motor tem
duas superfícies de invocação:
| Superfície | Invocação | Contexto |
|---|---|---|
| CLI do motor | python -m apothem <command> | Uma árvore de código-fonte com src/ em PYTHONPATH (checkout, cache do npx, árvore do plugin) |
| Runtime de hooks | <resolved CPython> "<harness-root>/.apothem/support/hooks/dispatch.py" <event> | A materialização do Claude Code: a cópia sob a árvore compartilhada .apothem/support/ da raiz do harness, por caminho absoluto |
python -m apothemexecutasrc/apothem/__main__.py, que colocasrc/apothem/_vendornosys.path, verifica seclickerichsão importáveis e então chamaapothem.cli:main— o grupo de comandos do Click.- As entradas de hook no
settings.json/hooks.jsonmaterializado invocam o despachante (e, para o Claude Code, o conformity gate em<harness-root>/.apothem/support/conformity/gate.py) por caminho absoluto de script. Ambos são scripts autônomos da biblioteca padrão que fazem o bootstrap do própriosys.path, e os fixtures de schema do gate ficam ao lado dele em<harness-root>/.apothem/support/schemas/, de modo que os hooks rodam sem nenhum pacoteapothemimportável no host. Os templates carregam um token${HARNESS_ROOT}que oapothem installrenderiza como o caminho real da raiz do harness, com barras normais. - A partir de um checkout do código-fonte, as formas de módulo
python -m apothem.hooks.dispatchepython -m apothem.conformity.gateexecutam o mesmo código para desenvolvimento.
O diretório do pacote se torna importável ao antepor o diretório src/ do
checkout ao PYTHONPATH:
PYTHONPATH="$HOME/.apothem/src" python -m apothem <command>Quando o lançador apothem não está no PATH, o install.sh imprime esta forma
ao concluir, com o diretório de dependências incorporadas antes de src/ e o
CPython que ele resolveu no lugar de python. O install.ps1 imprime as mesmas
duas configurações na forma do PowerShell: uma atribuição a $env:PYTHONPATH
que une os diretórios de dependências incorporadas e src/ com ;, seguida de
& '<CPython>' -m apothem <command>.
Bootstrap da árvore do plugin
O plugin do Claude Code empacota o motor sob <plugin_root>/lib/apothem em vez
de depender do PYTHONPATH. O módulo de bootstrap
apothem.lib.plugin_bootstrap expõe bootstrap_syspath, que antepõe, de forma
idempotente, <plugin_root>/lib e o diretório vendor ao sys.path, para que
import apothem e cada dependência internalizada sejam resolvidos a partir da
árvore do plugin. Uma árvore malformada (sem lib/) lança
PluginBootstrapError em vez de importar silenciosamente uma cópia
desatualizada do sistema.
O que o instalador coloca em disco
Os instaladores por script colocam um clone git da árvore de código-fonte em
~/.apothem (substituível com APOTHEM_HOME) e rodam o motor a partir dele —
nenhum pacote Python é instalado em site-packages além da oferta opcional do
pré-requisito click / rich. O clone é o repositório completo, incluindo a
suíte de testes e o site de documentação que o runtime nunca importa, por duas
razões deliberadas: o motor materializa seus cohorts — regras, skills,
comandos e templates — diretamente da árvore em cada harness, de modo que a
árvore é a fonte da verdade viva, e não apenas um runtime; e o diretório .git
permanece no lugar para que o apothem update faça checkout da tag de release no
clone existente em vez de baixá-lo novamente.
Este layout de execução a partir do código-fonte é o mesmo padrão que
ferramentas como nvm, pyenv e oh-my-zsh usam — alguns megabytes de
código-fonte mais o histórico, removíveis em um único passo com o desinstalador
(não há estado de sistema a desfazer). Uma pegada menor — um checkout raso ou
esparso que omita tests/ e site/ — é possível, mas abriria mão do caminho de
atualização no local, verificado por assinatura e baseado em git; o layout
atual privilegia uma atualização simples e verificável em vez de um uso mínimo
de disco.
Como o runtime encontra o Python
Os instaladores de uma única etapa e o shim do npx sondam nomes diferentes e
aplicam as mesmas regras. Os instaladores sondam python3, python e os nomes
versionados (python3.14 até python3.10). O shim do npx sonda APOTHEM_PYTHON
quando ele está definido e, em seguida, python3, python e py -3; ele não
tem nomes versionados. Ambos rejeitam os shims do lançador da Microsoft Store e
aceitam o primeiro candidato que informar a versão 3.10 ou mais recente. Quando
executados a partir de uma árvore de código-fonte, os instaladores reutilizam o
localizador empacotado hooks/lib/find-python, que aplica o mesmo piso.
Próximo passo recomendado
Execute python -m apothem --help com o diretório src/ do checkout no
PYTHONPATH para confirmar que o caminho da CLI autocontida é resolvido no seu
host.
Fluxo de instalação
Como apothem install, update e uninstall funcionam de ponta a ponta.
Estratégia de internalização de dependências
Quais pacotes de terceiros o Apothem internaliza sob src/apothem/_vendor/, quais permanecem como pré-requisitos do sistema e como as cópias internalizadas são atualizadas.