diff --git a/.gitignore b/.gitignore index 83ae8db6..7c0d9ca1 100644 --- a/.gitignore +++ b/.gitignore @@ -54,6 +54,13 @@ reports/* !reports/.gitkeep projects/*/reports/ +# Papers — artefacto local: papers académicos reproducibles. En fase interna viven +# local y gitignored (como los reports); al promocionar a fase publishable se +# vuelven sub-repo Gitea propio (como apps/analyses). Solo el marcador .gitkeep se +# versiona. Convención: docs/capabilities/papers.md +papers/* +!papers/.gitkeep + # Node / pnpm **/node_modules/ diff --git a/bash/functions/io/next_numbered_dir.md b/bash/functions/io/next_numbered_dir.md new file mode 100644 index 00000000..4895cf8a --- /dev/null +++ b/bash/functions/io/next_numbered_dir.md @@ -0,0 +1,58 @@ +--- +name: next_numbered_dir +kind: function +lang: bash +domain: io +version: "1.0.0" +purity: impure +signature: "next_numbered_dir(parent_dir: string, [width: int]) -> string" +description: "Calcula el siguiente prefijo numerico NNNN- para un directorio numerado incremental. Escanea los subdirectorios directos de parent_dir cuyo nombre empiece por NNNN- (4+ digitos seguidos de guion), toma el maximo, le suma 1 y lo imprime con zero-padding al ancho width (default 4). Si parent_dir no existe o no tiene subdirs que matcheen, imprime 0001." +tags: [papers, io, scaffold] +uses_functions: [] +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [] +params: + - name: parent_dir + desc: "directorio padre cuyos subdirectorios numerados (NNNN-...) se escanean; obligatorio" + - name: width + desc: "ancho del zero-padding del numero impreso (default 4); opcional" +output: "el siguiente numero como string con zero-padding a width digitos a stdout (ej. 0003); usage a stderr y exit 1 si falta parent_dir" +tested: false +tests: [] +test_file_path: "" +file_path: "bash/functions/io/next_numbered_dir.sh" +--- + +## Ejemplo + +```bash +source bash/functions/io/next_numbered_dir.sh + +# Sobre un papers/ que ya contiene 0001-foo y 0002-bar +mkdir -p /tmp/papers/{0001-foo,0002-bar} +next_numbered_dir /tmp/papers +# -> 0003 + +# Directorio vacio o inexistente -> primer numero +next_numbered_dir /tmp/papers_nuevo +# -> 0001 + +# Ancho de padding distinto +next_numbered_dir /tmp/papers 6 +# -> 000003 +``` + +## Cuando usarla + +Cuando scaffoldees un artefacto numerado incremental (papers/, reports/, issues/) y necesites el siguiente NNNN sin colision: escanea lo que ya existe en disco y te da el numero libre listo para crear `-`. + +## Gotchas + +- **Impura**: lee el filesystem (estado del directorio en el momento de la llamada). No crea nada — solo calcula e imprime el numero. +- **Octal**: los numeros con cero a la izquierda (`08`, `09`) se interpretan como octal en aritmetica bash y romperian el calculo. La funcion fuerza base 10 con `10#$num` para evitarlo. +- **Solo subdirectorios**: cuenta unicamente subdirs directos. Archivos sueltos (`.gitkeep`, `notas.md`) y subdirs que no matcheen el patron se ignoran. No es recursivo. +- **Patron estricto**: el prefijo debe ser `NNNN-` (minimo 4 digitos seguidos de guion). Un subdir `12-foo` o `0001foo` (sin guion) NO se cuenta. +- No hay deteccion de huecos: devuelve `max+1`, no el primer numero libre intermedio. Si tienes `0001` y `0003`, devuelve `0004`, no `0002`. diff --git a/bash/functions/io/next_numbered_dir.sh b/bash/functions/io/next_numbered_dir.sh new file mode 100644 index 00000000..abc729b2 --- /dev/null +++ b/bash/functions/io/next_numbered_dir.sh @@ -0,0 +1,46 @@ +#!/usr/bin/env bash +# next_numbered_dir — Compute the next NNNN- prefix for a numbered directory. +# +# Scans the DIRECT subdirectories of whose names start with a +# numeric prefix of the form `NNNN-` (4+ digits followed by a hyphen), takes +# the maximum number, adds 1, and prints it zero-padded to (default 4). +# If does not exist or contains no matching subdir, prints the +# first number (0001 at default width). + +next_numbered_dir() { + local parent_dir="${1:-}" + local width="${2:-4}" + + if [[ -z "$parent_dir" ]]; then + echo "usage: next_numbered_dir [width]" >&2 + return 1 + fi + + local max=0 + local entry base num + + if [[ -d "$parent_dir" ]]; then + # Iterate only over direct subdirectories. The trailing slash in the + # glob ensures files (e.g. .gitkeep) are skipped — only dirs match. + for entry in "$parent_dir"/*/; do + # If the glob matched nothing it stays literal; guard with -d. + [[ -d "$entry" ]] || continue + base="$(basename "$entry")" + # Require a prefix of 4+ digits followed by a hyphen. + if [[ "$base" =~ ^([0-9]{4,})- ]]; then + num="${BASH_REMATCH[1]}" + # Force base 10 so leading zeros (08, 09) are not read as octal. + num=$((10#$num)) + if (( num > max )); then + max=$num + fi + fi + done + fi + + printf "%0*d\n" "$width" $(( max + 1 )) +} + +if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then + next_numbered_dir "$@" +fi diff --git a/bash/functions/pipelines/init_paper.md b/bash/functions/pipelines/init_paper.md new file mode 100644 index 00000000..e01e5b88 --- /dev/null +++ b/bash/functions/pipelines/init_paper.md @@ -0,0 +1,69 @@ +--- +name: init_paper +kind: pipeline +lang: bash +domain: pipelines +version: "1.0.0" +purity: impure +signature: "init_paper(slug: string, [--title ] [--domain ] [--tags ]) -> void" +description: "Scaffold de un paper académico reproducible en papers//. Calcula el siguiente número incremental escaneando papers/, crea las subcarpetas (experiments data figures reviews out), copia las plantillas paper.md (IMRaD) + preregistration.md (anti-HARKing) rellenando el frontmatter (title, slug, date de hoy, phase=question, status=draft) y crea references.md. NO hace git init: el paper arranca en fase interna local (papers/ gitignored). Grupo de capacidad papers." +tags: [papers, scaffold, paper, pipeline, bash, launcher] +uses_functions: + - next_numbered_dir_bash_io + - slugify_ascii_py_core +uses_types: [] +returns: [] +returns_optional: false +error_type: "error_go_core" +imports: [] +params: + - name: slug + desc: "identificador legible del paper; se slugifica a ASCII (espacios/acentos se normalizan) y se prefija con el siguiente NNNN incremental" + - name: "--title" + desc: "título del paper (string); si se omite, usa el slug limpio. No debe contener el carácter '|'" + - name: "--domain" + desc: "dominio del paper escrito en el frontmatter (default datascience)" + - name: "--tags" + desc: "tags CSV que se escriben en el frontmatter de paper.md (opcional)" +output: "sin salida directa; crea papers// con paper.md, preregistration.md, references.md y las subcarpetas experiments/ data/ figures/ reviews/ out/. Imprime el resumen y los pasos siguientes a stdout." +tested: false +tests: [] +test_file_path: "" +file_path: "bash/functions/pipelines/init_paper.sh" +--- + +## Ejemplo + +```bash +# Scaffold de un paper nuevo (numera 0001, 0002, ... automáticamente) +fn run init_paper mi-primer-paper --title "Mi primer paper" +fn run init_paper reactive-loop-calls --domain datascience --tags registry,telemetria + +# El slug se slugifica: "Áreas de Mejora" -> papers/0003-areas-de-mejora/ +fn run init_paper "Áreas de Mejora" +``` + +## Cuando usarla + +Cuando empiezas un paper académico nuevo dentro de `fn_registry` y necesitas el esqueleto del artefacto (`papers//`) con las plantillas IMRaD y de pre-registro listas para rellenar. Es el paso 1 del grupo de capacidad `papers` (ver `docs/capabilities/papers.md`), antes de la revisión de literatura y del pre-registro de la hipótesis. + +## Flujo + +1. Parsea `` (posicional) + flags `--title` / `--domain` / `--tags`. Falla con exit ≠ 0 si falta el slug. +2. `slugify_ascii` — normaliza el slug a ASCII lowercase sin diacríticos (reutiliza la función del registry, solo stdlib). +3. `next_numbered_dir papers/` — calcula el siguiente NNNN de 4 dígitos sin colisión. +4. Crea `papers//` con las subcarpetas `experiments/ data/ figures/ reviews/ out/`. +5. Copia `docs/templates/paper.md` + `docs/templates/preregistration.md` y rellena el frontmatter por clave de línea (title, slug, date de hoy, domain, tags; phase=question y status=draft vienen de la plantilla). +6. Crea `references.md` vacío. + +## Gotchas + +- **NO hace `git init`.** El paper arranca en fase interna local; `papers/` está gitignored en el repo padre (solo `papers/.gitkeep` se versiona). Promocionar a sub-repo Gitea (fase publishable) es manual. +- **El `--title` no debe contener el carácter `|`** (se usa como delimitador de sed al rellenar el frontmatter; los `&` y `\` sí se escapan). +- **No indexa el paper en `registry.db`** — los artefactos `papers//` no se indexan en esta fase (KISS); sí se indexa este pipeline. +- Requiere `python3` (del venv del registry o del sistema) para slugificar; `slugify_ascii` solo usa stdlib, así que el venv no es obligatorio. +- Idempotencia: si el directorio destino ya existiera, aborta con exit ≠ 0 en vez de sobrescribir. + +## Notas + +Cada paper es un artefacto independiente (mismo patrón que `apps/` y `analysis/`, pero para investigación). El pipeline usa `set -euo pipefail`: cualquier fallo detiene la ejecución. Parte del grupo de capacidad `papers` — diseño completo en `reports/0001-2026-06-30-papers-system-design.md`. diff --git a/bash/functions/pipelines/init_paper.sh b/bash/functions/pipelines/init_paper.sh new file mode 100644 index 00000000..34e3fa2a --- /dev/null +++ b/bash/functions/pipelines/init_paper.sh @@ -0,0 +1,177 @@ +#!/usr/bin/env bash +# init_paper +# ---------- +# Scaffold de un paper académico reproducible en papers//. +# +# Calcula el siguiente número incremental escaneando papers/, crea el +# directorio con todas las subcarpetas (experiments data figures reviews out), +# copia las plantillas paper.md + preregistration.md rellenando el frontmatter +# (title, slug, date de hoy, phase=question, status=draft) y crea references.md. +# +# NO hace `git init`: el paper arranca en fase interna local (papers/ está +# gitignored en el repo padre, solo .gitkeep se versiona). La promoción a +# sub-repo Gitea (fase publishable) es un paso posterior MANUAL. +# +# Compone: next_numbered_dir (helper de numeración del registry) + +# slugify_ascii (slug ASCII del registry). +# +# USO: +# ./init_paper.sh [--title "..."] [--domain ] [--tags a,b,c] +# +# EJEMPLOS: +# ./init_paper.sh mi-primer-paper --title "Mi primer paper" +# ./init_paper.sh reactive-loop-calls --domain datascience --tags registry,telemetria + +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +REGISTRY_ROOT="$(cd "$SCRIPT_DIR/../../.." && pwd)" + +# Funciones atómicas del registry +source "$REGISTRY_ROOT/bash/functions/io/next_numbered_dir.sh" + +# ── Parsing de argumentos ──────────────────────────────────── + +SLUG_RAW="" +TITLE="" +DOMAIN="datascience" +TAGS="" + +while [ $# -gt 0 ]; do + case "$1" in + --title) + TITLE="$2"; shift 2 ;; + --domain) + DOMAIN="$2"; shift 2 ;; + --tags) + TAGS="$2"; shift 2 ;; + -h|--help) + grep "^#" "$0" | sed 's/^# \?//' ; exit 0 ;; + -*) + echo "Flag desconocido: $1" >&2 ; exit 1 ;; + *) + if [ -z "$SLUG_RAW" ]; then + SLUG_RAW="$1" + else + echo "ERROR: argumento posicional inesperado: '$1' (solo se admite un )." >&2 + exit 1 + fi + shift ;; + esac +done + +if [ -z "$SLUG_RAW" ]; then + echo "ERROR: falta el argumento ." >&2 + echo "Uso: $0 [--title \"...\"] [--domain ] [--tags a,b,c]" >&2 + echo " Ejemplo: $0 mi-primer-paper --title \"Mi primer paper\"" >&2 + exit 1 +fi + +# ── Slugificar (reutiliza slugify_ascii del registry; solo stdlib) ── + +PYBIN="$REGISTRY_ROOT/python/.venv/bin/python3" +[ -x "$PYBIN" ] || PYBIN="$(command -v python3 || true)" +if [ -z "$PYBIN" ]; then + echo "ERROR: no se encontró python3 para slugificar el slug." >&2 + exit 1 +fi + +SLUG_CLEAN=$("$PYBIN" -c ' +import sys, os +sys.path.insert(0, os.path.join(sys.argv[2], "python", "functions")) +from core.slugify_ascii import slugify_ascii +print(slugify_ascii(sys.argv[1], default="paper")) +' "$SLUG_RAW" "$REGISTRY_ROOT") + +# ── Resolver número incremental y directorio destino ───────── + +PAPERS_DIR="$REGISTRY_ROOT/papers" +mkdir -p "$PAPERS_DIR" + +NUM=$(next_numbered_dir "$PAPERS_DIR") +SLUG_FULL="${NUM}-${SLUG_CLEAN}" +PAPER_DIR="$PAPERS_DIR/$SLUG_FULL" + +if [ -d "$PAPER_DIR" ]; then + echo "ERROR: el directorio del paper ya existe: $PAPER_DIR" >&2 + exit 1 +fi + +TODAY=$(date +%Y-%m-%d) +[ -n "$TITLE" ] || TITLE="$SLUG_CLEAN" + +TAGS_YAML="[]" +if [ -n "$TAGS" ]; then + TAGS_YAML="[$(echo "$TAGS" | sed 's/,/, /g')]" +fi + +echo "" +echo "════════════════════════════════════════════════════════════" +echo " INIT PAPER: ${SLUG_FULL}" +echo " Título: ${TITLE}" +echo " Directorio: ${PAPER_DIR}" +echo "════════════════════════════════════════════════════════════" +echo "" + +# ── Crear estructura ───────────────────────────────────────── + +echo "[1/3] Creando estructura..." +mkdir -p "$PAPER_DIR"/experiments "$PAPER_DIR"/data "$PAPER_DIR"/figures \ + "$PAPER_DIR"/reviews "$PAPER_DIR"/out +echo " experiments/ data/ figures/ reviews/ out/" + +# ── Copiar plantillas + rellenar frontmatter ───────────────── + +echo "[2/3] Escribiendo paper.md + preregistration.md..." + +# Escapa caracteres especiales del RHS de sed (delimitador |) +sed_escape() { printf '%s' "$1" | sed -e 's/[\\&|]/\\&/g'; } +TITLE_ESC="$(sed_escape "$TITLE")" +DOMAIN_ESC="$(sed_escape "$DOMAIN")" + +PAPER_MD="$PAPER_DIR/paper.md" +PREREG_MD="$PAPER_DIR/preregistration.md" + +cp "$REGISTRY_ROOT/docs/templates/paper.md" "$PAPER_MD" +cp "$REGISTRY_ROOT/docs/templates/preregistration.md" "$PREREG_MD" + +sed -i \ + -e "s|^title:.*|title: \"${TITLE_ESC}\"|" \ + -e "s|^slug:.*|slug: ${SLUG_FULL}|" \ + -e "s|^date:.*|date: ${TODAY}|" \ + -e "s|^domain:.*|domain: ${DOMAIN_ESC}|" \ + -e "s|^tags:.*|tags: ${TAGS_YAML}|" \ + "$PAPER_MD" + +sed -i \ + -e "s|^paper_slug:.*|paper_slug: ${SLUG_FULL}|" \ + "$PREREG_MD" + +echo " $PAPER_MD" +echo " $PREREG_MD" + +# ── references.md ──────────────────────────────────────────── + +echo "[3/3] Escribiendo references.md..." +cat > "$PAPER_DIR/references.md" << EOF +# References — ${TITLE} + + +EOF +echo " $PAPER_DIR/references.md" + +# ── Resumen ────────────────────────────────────────────────── + +echo "" +echo "════════════════════════════════════════════════════════════" +echo " PAPER '${SLUG_FULL}' LISTO (fase: question, status: draft)" +echo "════════════════════════════════════════════════════════════" +echo "" +echo " Pasos siguientes:" +echo " 1. Revisión de literatura (skill /deep-research) → Related work." +echo " 2. Pre-registro: congela H0/H1 + plan en preregistration.md (preregister_hypothesis)." +echo " 3. Experimentos en experiments/ → análisis (grupo eda) → escritura IMRaD en paper.md." +echo " 4. render_paper_pdf → out/paper.pdf. Peer review adversarial → reviews/." +echo "" +echo " papers/ está gitignored: este paper vive local hasta promocionar a publishable." +echo "" diff --git a/docs/capabilities/INDEX.md b/docs/capabilities/INDEX.md index dbea6af4..7dce2b69 100644 --- a/docs/capabilities/INDEX.md +++ b/docs/capabilities/INDEX.md @@ -39,6 +39,7 @@ Indice de grupos de capacidades del registry. Cada grupo agrupa >=3 funciones qu | [cpp-tables](tql.md) | 9 | Table Query Language C++ puro: filter, group, agg, sort, join, stats, formulas Lua, round-trip emit/apply | | [data-table-renderers](data_table_renderers.md) | 1 | API declarativa de cell renderers para data_table: Badge, Progress, Duration, Icon via TableInput.column_specs | | [scheduler](scheduler.md) | 4 | Cron expression parsing, matching, next-run y traduccion humana (consume `apps/dag_engine`) | +| [papers](papers.md) | — | Papers académicos reproducibles en `papers//`: scaffold del artefacto (`init_paper` + helper `next_numbered_dir`), plantillas IMRaD + pre-registro anti-HARKing, y (en construcción por la flota) congelar hipótesis, funciones estadísticas (effect size/CI/corrección múltiple), render md→PDF y peer-review adversarial. Reutiliza `deep-research`, grupo `eda` y el motor PDF de `datascience`. Diseño: `reports/0001-2026-06-30-papers-system-design.md` | | [extractor](extractor.md) | 15 | Funciones que leen datos de fuentes externas (BD, API, archivos, web). Nodos input de `data_factory` | | [transformer](transformer.md) | 15 | Funciones que clean/dedup/aggregate/feature-engineer datos. Nodos intermedios de `data_factory` | | [sink](sink.md) | 11 | Funciones que escriben datos a destino externo (BD, dashboard, alerta, email). Nodos output | diff --git a/docs/capabilities/papers.md b/docs/capabilities/papers.md new file mode 100644 index 00000000..b5890036 --- /dev/null +++ b/docs/capabilities/papers.md @@ -0,0 +1,82 @@ +# papers — papers académicos reproducibles + +Grupo de capacidad para producir **papers académicos** dentro de `fn_registry`: investigación con hipótesis falsables, experimentos reproducibles, análisis estadístico honesto y escritura en formato IMRaD. Cada paper es un artefacto nuevo en `papers//` que reutiliza infraestructura existente (skill `deep-research` para la revisión de literatura, grupo `eda` para el análisis, motor md→PDF de `datascience`, patrón de verificación adversarial del orquestador) y añade lo que falta como funciones del registry. + +Diseño completo y decisiones: `reports/0001-2026-06-30-papers-system-design.md`. + +> **Regla de oro anti paper-mill:** una hipótesis que **podía** fallar + un experimento con riesgo real de refutación + estadística que no es teatro. Si no hay riesgo de refutación, no es un paper. Los claims nunca superan a la evidencia. El antídoto al HARKing es el **pre-registro**: el plan de análisis se congela *antes* de mirar los datos. + +## Estructura del artefacto + +``` +papers/0001-mi-paper/ + paper.md # frontmatter (title, slug, authors, date, status, phase, tags, domain, hypothesis_id) + cuerpo IMRaD + preregistration.md # H0/H1 + plan de análisis CONGELADO (frozen_at + content_hash) antes de correr + references.md # bibliografía + experiments/ # código / notebooks por experimento (exp01_*, exp02_*) + data/ # crudos + procesados (gitignored si pesa) + figures/ # gráficos generados + reviews/ # outputs del peer-review adversarial + out/ # paper.pdf — entregable final + .git/ # SOLO cuando promociona a fase publishable (sub-repo Gitea) +``` + +`papers/` está gitignored en el repo padre (solo `papers/.gitkeep` se versiona): un paper en fase interna no contamina el repo. Al promocionar a `status: publishable` se vuelve sub-repo Gitea `dataforge/` (como apps y analyses). + +### Fases (campo `phase` de `paper.md`) + +``` +question → review → hypothesis → design → running → analysis → writing → internal-review + → [DONE interno] → polish → submitted [solo en fase publishable] +``` + +## Funciones + +| ID | Pureza | Estado | Qué hace | +|---|---|---|---| +| `init_paper_bash_pipelines` | impure | ✅ disponible | Scaffold de `papers//`: calcula el siguiente NNNN, crea las subcarpetas, copia `paper.md` + `preregistration.md` con el frontmatter relleno (slug, title, date de hoy, `phase: question`, `status: draft`) y `references.md` vacío. NO hace `git init` (el paper arranca en fase interna local). | +| `next_numbered_dir_bash_io` | impure | ✅ disponible | Dado un directorio, devuelve el siguiente número incremental de 4 dígitos (`0001`, `0002`, …) escaneando los subdirs con prefijo `NNNN-`. Helper de numeración de `init_paper` (reutilizable por reports/issues). | +| `preregister_hypothesis` | impure | 🚧 en construcción (flota) | Congela el `preregistration.md` (H0/H1 + plan de análisis) con `frozen_at` + `content_hash`, pasa `status` a `frozen` y escribe `hypothesis_id` en `paper.md`. Mata el HARKing: tras congelar, el plan no se edita. | +| `cohens_d` (effect size) | pure | 🚧 en construcción (flota) | Tamaño del efecto (Cohen's d) entre dos grupos. Reporta magnitud, no solo significancia. | +| `confidence_interval` | pure | 🚧 en construcción (flota) | Intervalo de confianza de una métrica (media/diferencia). | +| `holm_bonferroni` | pure | 🚧 en construcción (flota) | Corrección de comparaciones múltiples (Holm-Bonferroni / FWER) para el plan de análisis. | +| `render_paper_pdf` | impure | 🚧 en construcción (flota) | Markdown IMRaD (`paper.md` + figuras) → `out/paper.pdf`, reutilizando el motor md→PDF del grupo `eda`/`datascience`. | + +> Las funciones estadísticas reutilizan lo que ya exista en `datascience` (p.ej. `fdr_correction_py_datascience` cubre la corrección de comparaciones múltiples por FDR; el agente del rigor experimental decide si añade Holm-Bonferroni o reusa lo existente). Buscar antes de duplicar: `mcp__registry__fn_search query="effect size" domain="datascience"`. + +### Peer review (no es función del registry) + +El agente adversarial `.claude/agents/paper-reviewer.md` (🚧 en construcción por la flota) puntúa novedad, rigor, reproducibilidad y validez, e intenta **refutar** cada claim. Default a "failed" si la evidencia no soporta. Escribe su veredicto en `reviews/`. Es el equivalente al verificador adversarial del orquestador aplicado al paper. + +## Ejemplo canónico (end-to-end) + +```bash +# 1. Scaffold del paper (fase question, local). Crea papers/0001-mi-paper/. +./fn run init_paper mi-paper --title "¿El bucle reactivo reduce las calls inline?" --domain datascience --tags registry,telemetria + +# 2. Revisión de literatura → llena Related work (skill deep-research, fase review). +# /deep-research "..." + +# 3. Pre-registro: congela H0/H1 + plan de análisis ANTES de mirar datos (fase hypothesis). +./fn run preregister_hypothesis papers/0001-mi-paper # 🚧 en construcción + +# 4. Experimentos en papers/0001-mi-paper/experiments/ (fase running) → +# análisis con el grupo `eda` + funciones de effect size / CI / corrección múltiple (fase analysis). + +# 5. Escritura IMRaD en paper.md (fase writing) → render del entregable PDF. +./fn run render_paper_pdf papers/0001-mi-paper # 🚧 en construcción → out/paper.pdf + +# 6. Peer review adversarial (fase internal-review). +# Agent(subagent_type="paper-reviewer", prompt="Revisa papers/0001-mi-paper ...") # 🚧 en construcción +``` + +## Fronteras + +- **NO es para reports de trabajo.** Un report (`reports/`) es el entregable escrito de una tarea (resumen + evidencia + gaps); un paper es investigación con hipótesis falsable y experimento. Ver `.claude/rules/reports.md`. +- **NO se indexa en `registry.db` en esta fase.** No hay tabla `papers` ni `entity_type` `paper` (KISS); se añadiría con migración propia si se decide. Las *funciones* del grupo sí se indexan (viven en `bash/functions/`, `python/functions/`), pero los artefactos `papers//` no. +- **NO hace `git init` en el scaffold.** El paper arranca en fase interna local y gitignored. La promoción a sub-repo Gitea (fase publishable) es un paso manual posterior. +- **NO soporta LaTeX/arXiv todavía.** Formato elegido: Markdown como fuente + PDF como entregable. El soporte LaTeX se añadiría al promocionar un paper a fase publishable. + +## Estado + +Fase de scaffolding. Disponible: estructura del artefacto, plantillas (`docs/templates/paper.md`, `docs/templates/preregistration.md`), pipeline `init_paper` + helper `next_numbered_dir`, esta página y el bloque gitignore de `papers/`. En construcción por la flota: `preregister_hypothesis`, funciones estadísticas (effect size / CI / corrección múltiple), `render_paper_pdf` y el agente `paper-reviewer`. Validación end-to-end con un paper piloto real: pendiente. diff --git a/docs/templates/paper.md b/docs/templates/paper.md new file mode 100644 index 00000000..78dffe23 --- /dev/null +++ b/docs/templates/paper.md @@ -0,0 +1,94 @@ +--- +title: "TITULO DEL PAPER" +slug: NNNN-slug +authors: [Enmanuel] +date: 2026-01-01 +status: draft # draft | internal | publishable +phase: question # question -> review -> hypothesis -> design -> running -> analysis -> writing -> internal-review -> polish -> submitted +tags: [] +domain: datascience +hypothesis_id: "" # lo rellena preregister_hypothesis al congelar el preregistro +--- + + + +# {{título del paper}} + +## Abstract + + + +## 1. Introduction + + + +## 2. Related work + + + +## 3. Methods + + + +## 4. Results + + + +## 5. Discussion + + + +### 5.1 Limitaciones + + + +### 5.2 Amenazas a la validez + + + +## 6. Conclusion + Future work + + + +## References + + diff --git a/docs/templates/preregistration.md b/docs/templates/preregistration.md new file mode 100644 index 00000000..a5de0e2a --- /dev/null +++ b/docs/templates/preregistration.md @@ -0,0 +1,59 @@ +--- +paper_slug: NNNN-slug +frozen_at: "" # timestamp ISO — lo rellena preregister_hypothesis al congelar +content_hash: "" # hash del contenido congelado — lo rellena preregister_hypothesis +status: draft # draft -> frozen (preregister_hypothesis lo pasa a frozen; tras congelar NO se edita) +--- + +> **⚠️ ESTE DOCUMENTO SE CONGELA ANTES DE MIRAR LOS DATOS (anti-HARKing).** +> El plan de análisis se fija aquí *antes* de ejecutar el experimento. Una vez congelado +> (`status: frozen`, con `frozen_at` + `content_hash`), **no se edita**. Inventar o ajustar +> la hipótesis después de ver los resultados (HARKing) invalida el paper. Si el plan cambia +> tras ver datos, eso es análisis exploratorio y se reporta como tal, no como confirmatorio. + +# Pre-registro — {{título del paper}} + +## 1. Pregunta de investigación + + + +## 2. Hipótesis + + + +- **H0 (nula):** +- **H1 (alternativa):** + +## 3. Variables + +- **Independiente(s):** +- **Dependiente(s):** +- **Control:** + +## 4. Diseño + + + +## 5. Plan de análisis + + + +## 6. Predicción cuantitativa + + diff --git a/papers/.gitkeep b/papers/.gitkeep new file mode 100644 index 00000000..e69de29b