ADR 0011 — Pipeline determinista: targets orquesta, Parquet como contrato, DVC solo para raw/
- Estado: aceptado
- Fecha: 2026-10-16
- Fuente: Fase 1, informes 10 (+ anexo manifiesto), 22 (+
benchmarks/results.md), 24 (+ anexorun), 11, 26; ADR 0006 (imagen), ADR 0007 (DVC en R2)
Contexto
La especificación pedía elegir entre targets + renv, DVC pipelines, Snakemake y Kedro, justificando por Windows, caché, Parquet/DuckDB y legibilidad para agentes. La Fase 0.6 ya mostró que DVC necesita --no-scm en bind mounts de Windows (la libgit2 embebida no renombra objetos) y que dvc exp exige Git (informe 10), lo que descarta DVC como orquestador. targets registra hash de datos, comando y dependencias, semilla y tiempo por target en tar_meta(), admite format = "parquet" y format = "file", y tar_resources_aws() acepta endpoint S3-compatible (https://docs.ropensci.org/targets/reference/tar_target.html, 2026-10-16). El benchmark del ítem 22 midió el costo de arranque de cada runtime (Python 1,1 s, R 1,3 s, Julia 1,7 s más 6–9 s de compilación JIT por proceso) y confirmó que el intercambio por Parquet es viable entre los tres lenguajes.
Alternativas
- DVC pipelines (
dvc.yaml/dvc repro): descartado como orquestador por la dependencia de Git en bind mounts de Windows y pordvc exp; se conserva para versionarraw/. - Kedro / nf-core / Snakemake: descartados como motor (otra pila, sin ventaja para un equipo R); se toman ideas:
versionedyvalidatorde Kedro, esquema JSON de parámetros y módulos que reportan versiones de nf-core. - Puentes en proceso (
reticulate,JuliaCall) para trabajo pesado: descartados: acoplan entornos y memoria, y ocultan el contrato de datos.
Decisión
targets(R) orquesta todo el pipeline desde_targets.R, concrewpara paralelismo limitado pormachine-profile.json(targets_workers). Caché en el volumentargets-store(ya montado encompose.yaml).- Parquet es el único contrato de intercambio entre lenguajes y entre capas; cada Parquet lleva en
custom_metadatala versión del Table Schema que cumple (ADR 0009). Prohibido intercambiar objetos serializados (.rds,.pkl,.jld2) entre lenguajes o entre capas; dentro de R, un target puede pasar a otro objetos no tabulares (p. ej.svydesign, modelos) con el formato nativo detargets. - Etapas en Python o Julia se declaran como targets
format = "file"que lanzan un proceso (uv run --no-sync python ...,julia --project=... -t auto ...) y devuelven la ruta del Parquet producido;reticulateyJuliaCallquedan para llamadas pequeñas e interactivas. Julia lee Parquet vía DuckDB.jl (Arrow.jl no lee Parquet; benchmark 22). - DVC versiona solo
raw/(dvc init --no-scm, caché en/dvc-cache, remoter2); los punteros.dvcy manifiestos viven en git dentro deraw/(ADR 0006 corrección). Las capasstandardized/,harmonized/ymarts/son regenerables portargetsy no entran en git ni en DVC; los marts de nivel 1–2 se publican como artefactos de release; los fila-nivel de nivel 3 nunca salen del volumen local (ADR 0010, ADR 0014). - Manifiesto por corrida (esquema en ADR 0009, decisión 9) escrito por el último target a
reports/manifest-<run_id>.json, construido desdetar_meta()más el perfil de máquina, el digest de la imagen y los campos de agente (model,claude_code_version,skills_hash,cost_usd). - Validación declarativa por capa:
pointblanken R ypanderaen Python contra los Table Schema delcdm; un target de validación por capa falla el pipeline con mensaje accionable. - Un clic sin agente (informe 24):
run.sh/run.batverifican Docker,.env, imagen y datos (dvc pullsolo con credenciales locales del remote correspondiente; sin credenciales der2-restrictedcae aTQ_SYNTHETIC=1, ADR 0014) y ejecutandocker compose run --rm -T pipeline Rscript -e 'targets::tar_make()'; el último target estarchetypes::tar_quarto()que escribereports/index.html. Códigos de salida: 10–13 prerrequisitos, 20 pipeline, 21 informe ausente. - Prueba en máquina limpia: local en
.tq-tmp/con proyecto de compose distinto y datos sintéticos; en CI, jobe2edel workflowimageconclaudeausente del PATH.
Consecuencias
- Fase 3 crea
_targets.R,R/con funciones por etapa,python/yjulia/con scripts de proceso,run.sh/run.baty el jobe2e. - El benchmark 22 fija la regla: una etapa en otro lenguaje solo se justifica si ahorra más que su arranque medido (ADR 0012, decisión 6: Python ≈ 1,1 s, R ≈ 1,3 s, Julia ≈ 1,7 s más la compilación de lo que use) y lo demuestra con
bench::mark. - Provisional (cierra Fase 3):
tar_resources_aws(endpoint = ...)contra R2 sin probar; código de salida detar_make()ante target fallido (el script revisatar_progress()); comportamiento decrewbajomem_limit.