ratifact 1.0.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. ratifact-1.0.0/.gitignore +16 -0
  2. ratifact-1.0.0/LEEME.md +455 -0
  3. ratifact-1.0.0/LICENSE +21 -0
  4. ratifact-1.0.0/PKG-INFO +284 -0
  5. ratifact-1.0.0/README.md +254 -0
  6. ratifact-1.0.0/pyproject.toml +54 -0
  7. ratifact-1.0.0/ratifact/__init__.py +7 -0
  8. ratifact-1.0.0/ratifact/app.py +202 -0
  9. ratifact-1.0.0/ratifact/archivos.py +98 -0
  10. ratifact-1.0.0/ratifact/build.py +227 -0
  11. ratifact-1.0.0/ratifact/busqueda.py +134 -0
  12. ratifact-1.0.0/ratifact/catalogo.py +138 -0
  13. ratifact-1.0.0/ratifact/cli.py +67 -0
  14. ratifact-1.0.0/ratifact/clientes.py +206 -0
  15. ratifact-1.0.0/ratifact/clientes_toml.py +210 -0
  16. ratifact-1.0.0/ratifact/config.py +264 -0
  17. ratifact-1.0.0/ratifact/delegacion.py +175 -0
  18. ratifact-1.0.0/ratifact/doctor.py +299 -0
  19. ratifact-1.0.0/ratifact/esquema.py +204 -0
  20. ratifact-1.0.0/ratifact/herramientas/__init__.py +3 -0
  21. ratifact-1.0.0/ratifact/herramientas/contexto_documentos.py +280 -0
  22. ratifact-1.0.0/ratifact/herramientas/decisiones.py +261 -0
  23. ratifact-1.0.0/ratifact/herramientas/pendientes_sesiones.py +78 -0
  24. ratifact-1.0.0/ratifact/herramientas/proyectos.py +300 -0
  25. ratifact-1.0.0/ratifact/herramientas/tareas.py +286 -0
  26. ratifact-1.0.0/ratifact/herramientas/tareas_brief.py +184 -0
  27. ratifact-1.0.0/ratifact/informe.py +182 -0
  28. ratifact-1.0.0/ratifact/informe_memoria.py +279 -0
  29. ratifact-1.0.0/ratifact/instalacion.py +247 -0
  30. ratifact-1.0.0/ratifact/instalar.py +262 -0
  31. ratifact-1.0.0/ratifact/instalar_extras.py +193 -0
  32. ratifact-1.0.0/ratifact/integraciones/__init__.py +3 -0
  33. ratifact-1.0.0/ratifact/integraciones/base.py +24 -0
  34. ratifact-1.0.0/ratifact/integraciones/codegraph.py +19 -0
  35. ratifact-1.0.0/ratifact/integraciones/engram.py +14 -0
  36. ratifact-1.0.0/ratifact/integraciones/gentle_ai.py +23 -0
  37. ratifact-1.0.0/ratifact/integraciones/registro.py +108 -0
  38. ratifact-1.0.0/ratifact/listado.py +85 -0
  39. ratifact-1.0.0/ratifact/migracion_v2.py +206 -0
  40. ratifact-1.0.0/ratifact/modelos.py +131 -0
  41. ratifact-1.0.0/ratifact/plantillas.py +51 -0
  42. ratifact-1.0.0/ratifact/procesos.py +168 -0
  43. ratifact-1.0.0/ratifact/prompts.py +29 -0
  44. ratifact-1.0.0/ratifact/registros.py +258 -0
  45. ratifact-1.0.0/ratifact/retirado.py +88 -0
  46. ratifact-1.0.0/ratifact/rutas.py +73 -0
  47. ratifact-1.0.0/ratifact/skills/run-task/SKILL.md +56 -0
  48. ratifact-1.0.0/ratifact/upgrade.py +195 -0
  49. ratifact-1.0.0/ratifact/upgrade_aplicar.py +185 -0
  50. ratifact-1.0.0/ratifact/vocabulario.py +82 -0
  51. ratifact-1.0.0/ratifact/workers.py +197 -0
@@ -0,0 +1,16 @@
1
+ # Configuración personal (rutas absolutas de cada usuario): ver projects.example.json
2
+ projects.json
3
+ # Respaldos de configuración (contienen rutas personales)
4
+ projects.json.bak-*
5
+ *.bak-ratifact-*
6
+ # Telemetría local
7
+ logs/
8
+ # Python
9
+ __pycache__/
10
+ *.pyc
11
+ *.tmp
12
+ .pytest_cache/
13
+ # Estado local del agente
14
+ .atl/
15
+ # Paquete (uv build)
16
+ dist/
@@ -0,0 +1,455 @@
1
+ # ratifact (antes memoria-proyectos) — instalación
2
+
3
+ English: [README.md](README.md) (qué es, instalación, primer proyecto, /run-task, comandos, integraciones, upgrade).
4
+
5
+ Servidor MCP local: comando `ratifact serve` (paquete instalable, sección 0; `servidor.py` es su envoltorio hasta 1.1). Proyectos registrados: `projects.json`.
6
+ Desde la v1 el contrato está en inglés: herramientas, parámetros, descripciones y respuestas
7
+ (`docs/v1-english-naming.md`). Pasos para usuarios existentes después de actualizar: `docs/upgrade-v1.md`.
8
+
9
+ Variables de entorno: `RATIFACT_CONFIG` (projects.json), `RATIFACT_LOG` (telemetría) y `RATIFACT_BASE` (carpeta de
10
+ proyectos). Las anteriores `MEMORIA_PROYECTOS_*` siguen funcionando como respaldo hasta 1.1 (gana la nueva; el log del
11
+ servidor avisa una vez por variable). Sin variable, la configuración es `~/.config/ratifact/projects.json` si existe, si
12
+ no `~/.config/memoria-proyectos/projects.json` (no se mueve ni reescribe nada).
13
+
14
+ ## 0. Comando `ratifact` (instalación fija)
15
+ El repositorio es un paquete instalable (`pyproject.toml`, MIT). `uv tool install ratifact` (desde PyPI) o
16
+ `uv tool install ~/Projects/.memoria-proyectos` (desde la copia local) instala una copia fija (no editable) y deja el
17
+ ejecutable `~/.local/bin/ratifact`; después de cada integración en main: `uv tool install --reinstall
18
+ ~/Projects/.memoria-proyectos`, reiniciar los clientes y verificar con `ratifact doctor` (procedimiento completo en
19
+ "Desfase de versiones", más abajo). Los clientes se configuran con `ratifact install --apply`
20
+ (sección 1); las configuraciones viejas con `servidor.py` siguen funcionando hasta 1.1.
21
+
22
+ | Subcomando | Qué hace |
23
+ |---|---|
24
+ | `ratifact serve` | Servidor MCP por stdio (lo que lanzan los clientes). `servidor.py` es un envoltorio de esto hasta 1.1. |
25
+ | `ratifact install [--apply] [--client NOMBRE]` | Configura los clientes MCP que encuentra (Claude Desktop, Claude Code, Pi, Codex (experimental)) y enlaza `/run-task` (sección 1). Sin `--apply` solo muestra el plan. |
26
+ | `ratifact report [--days N] [--project P] [--log RUTA]` | Resumen del uso (sección 7). `analizar_uso.py` es un envoltorio hasta 1.1 (acepta `--dias`/`--proyecto`). |
27
+ | `ratifact doctor` | Solo lectura: versión y de dónde corre (instalación fija o copia de trabajo, con aviso), configuración usada y grafía de sus claves, por proyecto código, memoria (ruta, esquema, `.memorias/` viejo o `.ratifact/` nuevo, estado git) e integraciones detectadas, log, variables `MEMORIA_PROYECTOS_*` y acciones pendientes, el estado de cada cliente (configurado con ratifact / configuración vieja / sin configurar / no encontrado), el build, si la fuente local es más nueva que la instalación y los procesos `ratifact serve` vivos, marcando los anteriores a la instalación. Sale con 0 si no hay nada pendiente, 1 si hay acciones. Si no existe la configuración por defecto pero hay servidores corriendo con `RATIFACT_CONFIG`/`MEMORIA_PROYECTOS_CONFIG` o un `projects.json` junto al repositorio de origen, sugiere el comando exacto (`RATIFACT_CONFIG=<ruta> ratifact upgrade`). |
28
+ | `ratifact upgrade` | Paso explícito, con todos los clientes cerrados. Sin opciones solo muestra el plan; `--apply` lo ejecuta: migra a v2 las memorias v1, mueve `<base>/.memorias/<p>` a `<base>/.ratifact/<p>` (las rutas propias nunca se mueven), escribe `~/.config/ratifact/projects.json` con claves en inglés y renombra el viejo a `projects.json.bak-v1`, regenera las vistas y copia el log viejo. Aborta si hay un servidor corriendo con esa configuración, un `.lock` tomado o una memoria con cambios sin commit (cabecera "Aborted — nothing was changed:", el plan y los motivos; código de salida 1); idempotente; si un paso falla, lo revierte. |
29
+ | `ratifact --version` | Versión instalada. |
30
+
31
+ ## 1. Clientes MCP: `ratifact install`
32
+ Una vez por equipo, con el comando instalado (sección 0):
33
+
34
+ ```
35
+ ratifact install # plan: qué clientes encontró y qué cambiaría; no toca nada
36
+ ratifact install --apply # lo hace, con respaldo de cada archivo
37
+ ```
38
+
39
+ Configura los clientes que encuentra: Claude Desktop (`~/.config/Claude/claude_desktop_config.json`; en macOS
40
+ `~/Library/Application Support/Claude/claude_desktop_config.json`), Claude Code (`claude mcp add --scope user` si existe
41
+ el comando `claude`; si no, `~/.claude.json`), Pi (`~/.pi/agent/mcp.json`) y Codex, experimental (`~/.codex/config.toml`). Cada uno
42
+ queda con el servidor `ratifact`, comando = ruta absoluta del ejecutable instalado, `args ["serve"]` y sin variables de
43
+ entorno; el resto del archivo (otros MCP, preferencias) queda idéntico. Antes de escribir guarda
44
+ `<archivo>.bak-ratifact-<fecha>` junto al archivo (los archivos dentro de un proyecto —`CLAUDE.md`, `AGENTS.md`,
45
+ `.claude/settings.json`— se respaldan en `~/.local/state/ratifact/backups/<fecha>/<ruta absoluta>`, nunca dentro del
46
+ repositorio; un archivo que no se reescribe no tiene respaldo), valida el resultado volviéndolo a parsear y reemplaza el original de forma atómica; un
47
+ archivo inválido (p. ej. una coma de más en el JSON) se informa y no se toca. Un cliente no instalado se informa y se
48
+ salta; `--client claude-desktop|claude-code|pi|codex` limita a uno. Un segundo `--apply` no cambia nada y lo dice.
49
+ Codex es experimental: `ratifact install` lo configura y las herramientas MCP responden, pero aún no se ha
50
+ validado una ejecución completa de `/run-task` (`$run-task` en Codex).
51
+
52
+ Además: reemplaza la entrada vieja `memoria-proyectos` (nunca quedan las dos), renombra los permisos de Claude Code
53
+ `mcp__memoria-proyectos__<herramienta>` → `mcp__ratifact__<herramienta>` (en `~/.claude/settings.json` y en el
54
+ `.claude/settings.json` de cada proyecto registrado; los nombres en español de v0 se traducen), mueve las tablas de
55
+ aprobación por herramienta de Codex a la clave nueva, reescribe el bloque generado de `CLAUDE.md`/`AGENTS.md` de los
56
+ proyectos registrados (solo ese texto exacto, con respaldo fuera del repositorio), enlaza `/run-task` (sección 12), crea
57
+ `~/.config/ratifact/projects.json` vacío si no hay ninguna configuración, informa las integraciones detectadas por
58
+ proyecto y cómo apagarlas (las integraciones se detectan en disco y, por defecto, quedan en automático: nunca se pregunta) y lista lo que no puede hacer solo (las aprobaciones de Claude
59
+ Desktop, sección 10). Reinicie los clientes después.
60
+
61
+ ## Nota de versión
62
+ El servidor fija `mcp>=1.2,<2`. La serie 2.x de la librería `mcp` cambió la API y el servidor se desconecta al
63
+ arrancar. No quite ese límite sin probar antes con `./diagnostico.sh`.
64
+
65
+ ## 2. Claude Code
66
+ Lo configura `ratifact install --apply` (sección 1): equivale a
67
+ `claude mcp add --scope user ratifact -- <home>/.local/bin/ratifact serve`.
68
+
69
+ ## 3. Instrucciones del proyecto en claude.ai
70
+ El texto exacto (en inglés, con los nombres de herramientas v1) lo devuelve `project_instructions("<proyecto>")`:
71
+ péguelo tal cual en *Project instructions*. Empieza así:
72
+
73
+ > project: game
74
+ > At the start of every chat, call `get_context("game")` before answering; assume nothing that is not there.
75
+ > When we reach a decision, record it with `propose_decision` (it stays proposed). Only if I accept it explicitly, call `accept_decision` with my literal words in `user_quote`; the app will ask me to approve it.
76
+ > …
77
+
78
+ ## 4. Agregar otro proyecto
79
+ En cualquier chat con el MCP conectado, pida: "registra el proyecto <nombre> con el código en <ruta>".
80
+ `register_project` lo agrega a `projects.json`, crea su memoria (por defecto en `~/Projects/.ratifact/<nombre>`,
81
+ con repo git propio) y devuelve las instrucciones exactas para pegar en el proyecto de Claude y en CLAUDE.md/AGENTS.md.
82
+ Para recuperar esas instrucciones de un proyecto existente: `project_instructions("<nombre>")`.
83
+ Recomendado: marcar `register_project` como "requiere aprobación" igual que `accept_decision`.
84
+
85
+ ### Actualizar un proyecto ya registrado
86
+
87
+ `update_project(name, path="", tests="", repo="", redetect=False, integrations="", models="", delegation="")` corrige projects.json sin
88
+ editarlo a mano; reemplaza a la antigua `configurar_pruebas` (eliminada). Indique al menos uno de estos campos
89
+ (sin ninguno, la herramienta falla y no toca el archivo):
90
+ - `path`: nueva carpeta del código, cuando el proyecto se movió. Mismas validaciones que `register_project`
91
+ (debe quedar dentro de la carpeta de proyectos, ser una carpeta existente, y no contener la memoria del
92
+ proyecto, porque se commitearía y publicaría con el código; el mensaje de rechazo es distinto al del alta, porque aquí mover la memoria de un
93
+ proyecto existente no está soportado). La respuesta indica la ruta vieja y la nueva. Si el proyecto es de
94
+ varios repositorios y el comando de pruebas guardado queda con claves que ya no son repos bajo la ruta nueva, el
95
+ cambio se aplica igual (no bloquea) pero la respuesta avisa cuáles quedaron huérfanas ("orphan tests") y sugiere
96
+ `redetect=True`.
97
+ - `tests`: comando con que `/run-task` verifica el trabajo. En proyectos de varios repositorios, `repo`
98
+ indica a cuál se aplica.
99
+ - `redetect=True`: vuelve a detectar el comando a partir de los archivos del proyecto, en vez de darlo con
100
+ `tests` (ambos a la vez son incompatibles). En un proyecto de un solo repositorio redetecta el comando
101
+ completo; en uno de varios repositorios redetecta todos, o solo `repo` si se indica. Es la forma de
102
+ recuperar el comportamiento que antes tenía `configurar_pruebas()` llamada sin argumentos.
103
+ - `integrations`: activa o apaga integraciones opcionales, p. ej. `"codegraph=off,gentle-ai=auto"` (valores
104
+ `auto`|`off`; por defecto `auto`). Se guarda en `projects.json` bajo `"integraciones"` (solo las `off`). Un
105
+ nombre o valor desconocido se rechaza listando los válidos. codegraph (`.codegraph/`) y gentle-ai (`.atl/`) se
106
+ detectan en la carpeta del proyecto o en cualquiera de sus repos; engram no se detecta (solo guía condicional).
107
+ Las activas aparecen en `get_context` (una línea + guía para planificar), en `create_task` (la línea) y
108
+ en `update_task(..., "in_progress")` (guía para execute, verify y close); una apagada no aparece nunca.
109
+ - `models`: excepciones del proyecto a los modelos por rol, p. ej. `"explore=haiku,write=sonnet"` (roles
110
+ `explore`, `write`, `verify`; el valor es el nombre de modelo del cliente, texto libre). `inherit` en un rol quita
111
+ la excepción de ese rol, que vuelve a usar el global. Un rol desconocido o un valor vacío se rechazan listando los
112
+ roles válidos. Se guarda en la entrada del proyecto en `projects.json` bajo `"models"`.
113
+
114
+ ### Modelos por rol (`settings.json`)
115
+
116
+ El valor global de los modelos por rol vive en `settings.json`, en la misma carpeta que el `projects.json` activo
117
+ (p. ej. `~/.config/ratifact/settings.json`). Lo crea el usuario a mano (`ratifact install` no lo escribe):
118
+
119
+ ```json
120
+ {"models": {"explore": "haiku", "write": "sonnet", "verify": "sonnet"}}
121
+ ```
122
+
123
+ Se lee en cada llamada. Las excepciones de un proyecto (`update_project(..., models=...)`) ganan rol por rol; los
124
+ roles que el proyecto no define se heredan del global. Si hay al menos un rol configurado,
125
+ `update_task(..., "in_progress")` agrega un bloque "Model routing" con cada rol, su modelo y su origen
126
+ (global/project): es la petición explícita del usuario de fijar ese modelo al delegar el rol a un sub-agente; un
127
+ cliente que no permite elegir el modelo de sub-agentes lo ignora, y los roles sin modelo usan el de la sesión. Sin
128
+ configuración la respuesta no cambia. Un `settings.json` inválido no rompe ninguna herramienta (se ignora con un
129
+ aviso en ese bloque) y `ratifact doctor` lo reporta sin modificarlo; doctor muestra además los modelos efectivos de
130
+ cada proyecto (o `models: session default`).
131
+ No cubre renombrar un proyecto ni mover la ubicación de su memoria (`.ratifact/<nombre>` o la clave `"memoria"`):
132
+ para eso edite `projects.json` a mano y mueva la carpeta con `git mv`/`mv` según corresponda.
133
+
134
+ ### Política de delegación
135
+
136
+ Si una tarea se delega lo decide ratifact al planificar, no el agente que la ejecuta. `"delegation": "required" |
137
+ "suggested" | "off"` va en `settings.json` junto a `"models"` (global; por defecto `required`). Excepción por proyecto:
138
+ `update_project(name, delegation="off")` (`inherit` la quita; un valor desconocido se rechaza con la lista de válidos).
139
+ Excepción por tarea, fijada en la planificación: `create_task(..., delegation="off")` o
140
+ `amend_task(..., delegation="required")` (solo en todo o changes_requested), guardada como `delegation:` en el
141
+ frontmatter. Precedencia: tarea > proyecto > global > `required`. Criterio para `off`: la tarea toca seguridad, es
142
+ transversal o depende de diagnosticar una causa que la especificación aún no conoce.
143
+
144
+ - `required`: `update_task(..., "in_progress")` devuelve un bloque "Delegation" imperativo: la sesión principal
145
+ orquesta y no escribe el código; exploración en un trabajador explore, implementación en trabajadores write,
146
+ verificación en un trabajador verify que no vio la implementación, cada uno con el modelo de su rol (o el de la
147
+ sesión); los encargos llevan la especificación completa; el orquestador revisa el diff completo antes de
148
+ in_review; si un escritor falla la verificación dos veces, el orquestador toma la implementación y lo declara como
149
+ `escalated: write`.
150
+ - `suggested`: el bloque es una sugerencia. `off`: no hay bloque de delegación.
151
+ - El resultado lleva una línea propia, separada de `Integrations used:` (que solo nombra integraciones, nunca roles):
152
+ `Workers: explore/haiku×1, write/sonnet×2, verify/sonnet×1` (más `escalated: write` si corresponde) o
153
+ `Workers: none — reason: <motivo>`. Con `required`, `update_task(..., "in_review")` sin una línea Workers válida
154
+ cambia el estado igual pero responde con un aviso.
155
+ - Formato ampliado: `Workers: <rol>/<modelo>×<n>, …[, rework: <rol>×<n>, …][, escalated: <rol>][ — note: <texto libre>]`.
156
+ `<rol>/<modelo>×<n>` cuenta solo los encargos iniciales, incluso con varios trabajadores del mismo rol en paralelo (dos
157
+ escritores en paralelo son `Workers: write/sonnet×2`); `rework: <rol>×<n>` cuenta los reenvíos de ese rol causados por
158
+ un defecto que encontró el verificador o la revisión del diff del orquestador (el rol debe figurar entre los
159
+ trabajadores, n ≥ 1). La nota empieza en ` — note:` (canónico) o en ` - note:` / ` -- note:`, y se aceptan
160
+ `none - reason:` / `none -- reason:` (`Workers: write/sonnet×1 - note: x`); un guion ASCII en cualquier otro lugar
161
+ (`Workers: write/sonnet×1 - resumed once`) no separa nada y es un token inválido. El parser ignora el texto de la nota. Sin paréntesis: el retrabajo va en
162
+ `rework:`, los comentarios en `— note:`. Ejemplo:
163
+ `Workers: explore/haiku×1, write/sonnet×1, verify/sonnet×1, rework: write×1 — note: diff review found a missing test`.
164
+ Las líneas del formato anterior (sin `rework:` ni nota) siguen siendo válidas.
165
+ - Corrección sin duplicar: si el aviso dice que la línea es inválida, propone una corregida cuando puede derivarla;
166
+ enviar solo esa línea con `update_task(..., "in_review")` reemplaza la línea `Workers:` del último bloque de
167
+ resultado (o la agrega ahí) en lugar de crear un bloque nuevo.
168
+ - Auditoría: al pasar a in_progress se graba en el frontmatter `routing: explore=<m>,write=<m>,verify=<m> ·
169
+ delegation=<política> · build=<build> · at=<hora ISO 8601, a minutos>` (`session` si el rol no tiene modelo; se
170
+ sobrescribe en cada reejecución; `build=` y `at=` solo en las tareas nuevas: las tareas anteriores conservan la forma corta
171
+ y se siguen leyendo). `ratifact report` toma el período de `at=` cuando existe (si no, de `updated`). `ratifact report`
172
+ mide el cumplimiento por proyecto (tareas required con trabajadores reales, escalamientos) y compara tareas
173
+ delegadas y no delegadas en revisiones y en duración in_progress → in_review; las tareas sin `routing:` se cuentan
174
+ aparte. El routing también termina con `· client=<nombre>/<versión>`, tomado del `clientInfo` MCP de la
175
+ inicialización (saneado: sin espacios, sin `·`, sin saltos de línea, máximo 64 caracteres; `client=unknown` si no
176
+ hay dato) y cada registro nuevo de `uso.jsonl` lleva el campo `client`; se graba el valor recibido, sin normalizar.
177
+ `ratifact report` mide además, entre las tareas delegadas (última línea `Workers:` válida de cada una),
178
+ cuántas tuvieron rework, los reenvíos totales por rol, los escalamientos y la tasa de retrabajo (con rework /
179
+ delegadas), y desglosa por cliente (`client=` del routing, `unknown` si falta) tareas, cumplimiento de la delegación
180
+ y tasa de retrabajo. `ratifact doctor` muestra la política efectiva de cada proyecto (p. ej. `delegation=required (global)`).
181
+
182
+ ### Desfase de versiones
183
+ Hay tres copias de ratifact: la fuente (este repositorio), la instalación (directorio de uv tool, al que enlazan las
184
+ skills /run-task) y el servidor en ejecución (un `ratifact serve` por cliente, que conserva el código con el que
185
+ arrancó). Se desfasan al integrar sin reinstalar o al reinstalar sin reiniciar un cliente. Procedimiento tras cada
186
+ cambio: integrar en main → `uv tool install --reinstall ~/Projects/.memoria-proyectos` → reiniciar todos los clientes
187
+ (Claude Desktop, Claude Code, Codex, Pi) → `ratifact doctor`.
188
+
189
+ - **Build:** cada servidor calcula al arrancar `<versión>+<7 hex>` (hash del contenido de su paquete, skills incluidas,
190
+ sin bytecode). `get_context` lo muestra en su primera línea (`ratifact <build>`) y `routing:` lo graba por tarea.
191
+ - **Servidor obsoleto:** el servidor vuelve a mirar sus propios archivos (solo stat, caché de 5 s). Si cambiaron o
192
+ faltan desde que arrancó, `get_context` muestra debajo del build un aviso ⚠ para reiniciar ese cliente, las demás
193
+ herramientas anteponen el mismo aviso y `update_task(..., "in_progress")` se rechaza sin modificar nada: reiniciar
194
+ el cliente y repetir el paso.
195
+ - **Fuente más nueva que la instalación:** si uv instaló ratifact desde una carpeta local (su recibo de instalación),
196
+ `doctor` y `get_context` comparan el paquete de esa carpeta con el instalado y piden reinstalar, con el comando. Las
197
+ instalaciones desde PyPI no muestran este aviso.
198
+ - **`ratifact doctor`** lista además los procesos `ratifact serve` vivos (PID, hora de inicio y proceso padre). Como la
199
+ reinstalación reescribe todos los archivos aunque no cambien, un proceso anterior a la instalación se marca solo si
200
+ su contenido difiere: cada servidor deja su build de arranque en `~/.local/state/ratifact/servers/<pid>.json`
201
+ (se borra al salir y los PID muertos se limpian al arrancar). Mismo contenido → "nada que hacer"; sin
202
+ registro (servidor anterior a esto) → "el contenido puede ser idéntico" y `get_context` en ese cliente da la
203
+ respuesta definitiva. doctor solo lee: no escribe, no envía señales ni termina procesos (Linux y macOS; en otros
204
+ sistemas informa que el listado no está disponible).
205
+ Solo cuenta como servidor el proceso con ese registro: el envoltorio con el que Claude Desktop en Linux lanza el
206
+ MCP (su padre, que también muestra `ratifact serve` en la línea de comando, sin registro) se muestra dentro de la
207
+ entrada de su servidor ("wrapper <pid>, <cliente>"), y cualquier otro proceso sin registro se lista aparte como
208
+ "Unregistered processes" y no cuenta. doctor también avisa si corre en Windows nativo (no soportado:
209
+ instalar ratifact dentro de WSL2, con los repositorios en el sistema de archivos de WSL, no en `/mnt/c`), indica
210
+ cuando corre dentro de WSL y advierte de un repositorio registrado bajo `/mnt/` (lento y con diferencias de git).
211
+ - El autodiagnóstico del servidor funciona igual: una huella distinta se confirma una vez con el hash de contenido,
212
+ así que reinstalar con el mismo código no dispara el aviso ni el rechazo de `in_progress`.
213
+
214
+ `ratifact install --apply` y `ratifact upgrade --apply` terminan recordando reiniciar los clientes y verificar con
215
+ `ratifact doctor`. Un servidor anterior al registro de build/PID no se autodiagnostica; `doctor` sí lo muestra.
216
+
217
+ ## 5. Tareas de código (Claude Desktop → Claude Code)
218
+ Flujo: en Claude Desktop se acuerda un cambio y se registra con `create_task` → queda `.project/tasks/T-NNN.md` →
219
+ en Claude Code, dentro del repositorio, se ejecuta `/run-task T-NNN` (que empieza con `read_task`) → Claude Code crea la rama, implementa, corre las pruebas
220
+ del proyecto ("How to verify") y deja la tarea `in_review` (o `failed`) con el resultado → usted revisa la rama e integra.
221
+
222
+ Instalación del comando: una sola vez por equipo, con los enlaces globales de la sección 12 (no se copia por repositorio).
223
+ Claude Code debe tener el MCP registrado (sección 2) para leer y actualizar la tarea.
224
+
225
+ Las instrucciones del proyecto en claude.ai (`project_instructions`) ya incluyen el flujo: `create_task` con goal,
226
+ criterios verificables, ADR aplicables, archivos y fuera de alcance; el comando `/run-task T-NNN`; `amend_task` para
227
+ ampliar una tarea que todavía no corrió; `list_tasks` y `read_task` para revisar; `request_changes` con findings y
228
+ criterios adicionales para pedir correcciones; `merged`/`discarded` solo con confirmación del usuario.
229
+
230
+ `amend_task(project, id, additional_criteria="", notes="")`: solo para tareas `todo` o `changes_requested`
231
+ (otro estado → error que lo nombra). Agrega un bloque fechado "### Amendment N" (sub-etiquetas **Additional criteria** y
232
+ **Notes**) en la sección "## Amendments" de la spec, antes de "How to verify"; los criterios originales no se tocan. Un
233
+ commit por enmienda; al menos uno de los dos campos; una enmienda idéntica dentro de la ventana de idempotencia
234
+ no se escribe de nuevo.
235
+
236
+ `read_task(project, id)`: brief de trabajo de una tarea en lugar del archivo completo: frontmatter, spec
237
+ completa (con las enmiendas), el bloque relevante según el estado (`changes_requested` → la última Review;
238
+ `in_review`/`failed` → el último resultado; `in_progress` → la última Review si es el último bloque) y un índice de una
239
+ línea (título · rango de líneas · tamaño) de los demás bloques Result/Review, legibles con `read_document` y ese rango.
240
+
241
+ Ciclo de revisión: `todo` → `in_progress` → `in_review` → (`changes_requested` → `in_progress` → `in_review`)* →
242
+ `merged`. Una tarea devuelta se corrige en la misma rama con commits nuevos; cada devolución queda como "Review N" en la
243
+ tarea (con **Findings** y **Additional criteria**). `update_task` rechaza pasar de `in_review` a `todo`: devolver es
244
+ siempre `request_changes`. El parámetro `status` acepta también (hasta 1.1) los nombres en español de antes del esquema v2
245
+ (`pendiente`, `en_curso`, `en_revision`, `fallida`, `integrada`, `descartada`); se guarda y se responde en inglés.
246
+
247
+ Pendientes que resuelve una tarea: `create_task(..., resolves="P-001 (partial)")` — ids separados por
248
+ coma, cada uno opcionalmente con `(parcial)` o `(partial)` (sin distinguir mayúsculas ni espacios; `p-1` vale como `P-001`). Cada id
249
+ debe existir y estar abierto; si alguno no, la herramienta lo rechaza nombrando los inválidos y no escribe nada. Se guarda
250
+ en el frontmatter (`resolves: P-001 (partial)`) y como sección "## Resolves" de la tarea; sin `resolves`, ni
251
+ campo ni sección. Al marcar la tarea `merged`, la respuesta recuerda cada pendiente declarado que siga abierto: los completos
252
+ con la llamada a `close_pending` y los parciales con cómo registrar lo que falta: una nota anexada al archivo del
253
+ pendiente con `update_document(..., mode="append")`, o cerrarlo con `close_pending` y abrir el resto con `add_pending`. Nunca se cierra ni se modifica un
254
+ pendiente automáticamente.
255
+
256
+ ## 6. Ubicación de la memoria
257
+ Con la clave `"memoria"` en `projects.json`, la memoria vive fuera del repositorio del código (repo git propio) y no depende
258
+ de la rama activa. Recomendado para todos los proyectos. Las herramientas siguen usando rutas `.project/...`.
259
+ Sin esa clave, la memoria es `<carpeta de proyectos>/.ratifact/<nombre>`; una que todavía vive en la
260
+ ruta por defecto vieja `.memorias/<nombre>` se sigue encontrando ahí hasta que `ratifact upgrade --apply` la mueve.
261
+ Las claves de cada proyecto en `projects.json` se leen en español (`ruta`, `memoria`, `escritura`, `pruebas`,
262
+ `integraciones`) o en inglés (`path`, `memory`, `writable`, `tests`, `integrations`); si están las dos, gana la inglesa.
263
+ Al escribir se conserva la grafía que ya tiene la entrada. Renombrar las claves y mover las memorias de `.memorias/` a
264
+ `.ratifact/` es `ratifact upgrade --apply` (sección 0), nunca la migración automática.
265
+
266
+ ## 7. Telemetría
267
+ Cada llamada a una herramienta agrega una línea a `~/.local/state/ratifact/uso.jsonl` (`$XDG_STATE_HOME/ratifact/`; hasta
268
+ antes de instalarse como paquete era `<repo>/logs/uso.jsonl`, y `ratifact upgrade` lo copia si el nuevo no existe) con herramienta, proyecto,
269
+ tamaños, duración y error; nunca el contenido. Resumen: `ratifact report --days 7` (opcional `--project game`; también
270
+ `python3 ~/Projects/.memoria-proyectos/analizar_uso.py --dias 7` hasta 1.1).
271
+ El informe lee el mismo log que escribe el servidor: `--log <ruta>` si se indica, si no `RATIFACT_LOG` (o
272
+ `MEMORIA_PROYECTOS_LOG`), y si no `~/.local/state/ratifact/uso.jsonl`. Las filas guardan el nombre inglés de la herramienta; las anteriores
273
+ a la v1 (nombre en español) se traducen al agregar, así el historial suma por herramienta. Si el archivo no existe, lo informa con su ruta y termina con error.
274
+ `get_context` avisa cuando INDEX.md acumula 5 o más cambios sin regenerarse.
275
+ Arranque compacto: `get_context` ya no incluye `OPEN.md`. Después de INDEX.md muestra
276
+ "# Open items (N)" con una línea por pendiente abierto (`- P-NNN · <tema> (<fecha>)`, en orden numérico, tema
277
+ cortado a 100 caracteres, sin extracto ni dueño) y cierra con `Detail: read_document("<proyecto>", "P-NNN")`; sin
278
+ pendientes abiertos, solo "# Open items (0)". "Recently closed" no sale en el arranque. `OPEN.md`
279
+ sigue generándose en disco. Al final, la línea "Content language: <content_language> — …" pide escribir el contenido de
280
+ los registros en ese idioma; las respuestas de las herramientas son siempre en inglés.
281
+ El resumen de `analizar_uso.py` agrega el tamaño de `get_context` por proyecto (p50/máx en caracteres y ~tokens,
282
+ con aviso si el p50 supera la referencia de 2.000 tokens = 8.000 caracteres) y la sección "Pendientes abiertos
283
+ referenciados por tareas integradas": por proyecto, los declarados en `resolves` y los mencionados en el texto de la
284
+ tarea (spec —objetivo, criterios, revisiones— y Result; no cuentan Out of scope, Notes, How to verify ni Resolves),
285
+ con la tarea y su fecha de integración. Lee memorias v1 y v2. También cuenta, por proyecto, las rutas v1 traducidas
286
+ (`alias_ruta` en el log; ver sección 13).
287
+
288
+ ## 8. Confirmación de decisiones
289
+ Toda decisión nace como propuesta. La única vía a "acordada" es `accept_decision`, que exige la frase literal del
290
+ usuario (`user_quote`, guardada en el ADR) y debe requerir aprobación en cada cliente:
291
+ - Claude Desktop: Configuración → conectores/MCP → ratifact → `accept_decision` → requiere aprobación.
292
+ - Claude Code: `"mcp__ratifact__accept_decision"` y `"mcp__ratifact__accept_decisions"` en `permissions.ask` de `.claude/settings.json` (`ratifact install` renombra los `mcp__memoria-proyectos__…` existentes).
293
+ - Pi: sin permisos configurables; la evidencia queda en la sección "Confirmación" del ADR.
294
+
295
+ ## 9. Revisar propuestas
296
+ Desde el chat: "revisa las propuestas pendientes" → `review_proposals` muestra todas con su detalle. Por cada una:
297
+ confirmar (`accept_decision`, con aprobación), ajustar (nueva decisión + `supersede_decision`) o descartar
298
+ (`reject_decision`, con motivo; queda en el historial como descartada).
299
+ Con formularios: "decidamos las propuestas" → `decide_proposals` abre un formulario por propuesta en la aplicación
300
+ (accept / reject / adjust / postpone + comment). La respuesta viene directo del usuario, sin pasar por el
301
+ modelo. Si la aplicación no soporta formularios (MCP elicitation), la herramienta lo indica y se usa el flujo por chat.
302
+
303
+ ## 10. Aprobaciones en Claude Desktop
304
+ Crear registros en la memoria debe pasar por usted; modificar o leer, no. Marque como "requiere aprobación":
305
+ `propose_decision`, `add_pending`, `create_task`, `create_document`, `register_project`, `accept_decision` y
306
+ `accept_decisions`. Las aprobaciones se guardan por nombre de servidor y de herramienta: tras pasar a la clave
307
+ `ratifact` hay que marcarlas de nuevo; `ratifact install` lo recuerda en sus pasos manuales.
308
+ Deje en "permitir siempre" el resto (lecturas, `read_task`, `amend_task`, `update_document` sobre archivos existentes, `update_task`,
309
+ `update_index`, `log_session`, `reject_decision`, `supersede_decision`). El servidor no tiene herramientas
310
+ para borrar archivos: nada se elimina, solo cambia de estado. En Claude Code no se usan aprobaciones para el código.
311
+
312
+ ## 11. Pruebas
313
+ Desde esta carpeta: `uv run --with pytest --with "mcp>=1.2,<2" pytest -q` (o `python3 -m pytest -q` con pytest y mcp instalados).
314
+ Corren contra una carpeta temporal: no tocan `projects.json`, la telemetría ni los proyectos reales.
315
+ `test_cobertura.py` falla si se agrega una herramienta sin pruebas (el criterio 1 de estabilización: suite pytest en verde que cubra todas las herramientas).
316
+
317
+ ## 12. /run-task global (una vez por equipo)
318
+ `/run-task` es genérico: la fuente es `ratifact/skills/run-task/SKILL.md`, que viaja dentro del paquete instalado
319
+ (`skills/` y `run-task.md` en la raíz del repositorio son enlaces a ella). `ratifact install --apply` lo enlaza desde la
320
+ copia instalada (nunca desde la copia de trabajo), así existe en todos los proyectos:
321
+
322
+ - Claude Code: `~/.claude/skills/run-task` (el enlace antiguo `~/.claude/commands/run-task.md` se borra si es nuestro)
323
+ - Pi: `~/.pi/agent/prompts/run-task.md` (y `~/.pi/agent/skills/run-task` si existe esa carpeta)
324
+ - Codex: `~/.codex/skills/run-task` y `~/.agents/skills/run-task` (según la versión lee una u otra; se enlaza la carpeta
325
+ entera porque Codex no sigue un `SKILL.md` enlazado como archivo)
326
+
327
+ Un destino que ya existe como archivo o carpeta real (no enlace) nunca se reemplaza: el plan pide borrarlo a mano.
328
+ Si usa gentle-shell independiente, enlace también `~/.gentle-shell/agent/prompts/run-task.md` a la misma fuente.
329
+
330
+ ## 13. Versión de esquema de la memoria
331
+
332
+ Cada memoria declara en `schema.json` el formato con que fue escrita y el idioma de su contenido:
333
+ `{"version": 2, "content_language": "es"}`. Hoy es v2: carpetas `decisions/`, `pending/`, `sessions/`, `tasks/`;
334
+ vistas `DECISIONS.md` y `OPEN.md`; claves, estados y títulos de sección en inglés (`docs/v1-english-naming.md` §5–§6).
335
+ Las memorias nuevas nacen en v2 con `content_language` `"en"`; las migradas, con `"es"`.
336
+
337
+ Migración automática (v1 → v2), en el **primer acceso** a cada memoria (cualquier herramienta con
338
+ `project`, también las de solo lectura), bajo el bloqueo:
339
+
340
+ - Precondiciones: la memoria es un repo git con al menos un commit y `git status` limpio (salvo `.lock`). Si no, la
341
+ herramienta responde un error que explica por qué y no se toca nada.
342
+ - Antes de cambiar nada crea el tag `pre-v2` (si existe, `pre-v2-2`, `-3`, …).
343
+ - Un solo commit `memory: migrate schema v1 → v2`: renombra las carpetas con `git mv` (historia preservada), cambia
344
+ las claves y los estados del frontmatter, los títulos de sección conocidos y, dentro de los bloques "Revisión N",
345
+ las etiquetas `**Observaciones**`/`**Criterios adicionales**`; regenera `DECISIONS.md`/`OPEN.md` y borra
346
+ `acuerdos.md`/`abiertas.md`. El resto del cuerpo, las citas del usuario, `INDEX.md` y `docs/` no cambian. El cuerpo del
347
+ commit lista lo que quedó como estaba: claves desconocidas y títulos de texto libre.
348
+ - Si algo falla (un paso o el commit), la memoria vuelve exactamente al tag (y se borra el tag); la herramienta da el
349
+ error y la próxima llamada lo reintenta.
350
+ - Vuelta atrás manual: `git -C <memoria> checkout pre-v2` (o `reset --hard pre-v2`) devuelve el árbol anterior.
351
+ - Se mantiene `esquema.json` con `{"version": 2}` como centinela: un servidor anterior a v2 lee "v2" y se niega
352
+ ("usa el esquema v2 y este servidor solo conoce hasta v1"), sin tocar nada. Se quita en 1.1.
353
+ - Despliegue: reinicie todos los clientes (Claude Desktop, Claude Code, Pi, Codex) antes de la primera llamada.
354
+ - Rutas v1 (`.project/tareas/T-001.md`, `.project/acuerdos.md`…, que siguen apareciendo en INDEX.md, docs/ y chats
355
+ viejos): se traduce solo el primer tramo después de `.project/` y la respuesta empieza con
356
+ "(→ .project/<ruta nueva>)". Las vistas no se escriben a mano (ni con el nombre viejo ni con el nuevo). Si una memoria
357
+ tiene a la vez la carpeta v1 y la v2, la llamada falla. Cada uso queda en la telemetría (`alias_ruta`); el alias se
358
+ quita en 1.1 cuando `analizar_uso.py` muestre que no se usa.
359
+
360
+ Una memoria más nueva que el servidor (p. ej. otro equipo con una versión posterior) no se modifica: el servidor pide
361
+ actualizar ratifact. `list_projects` muestra la versión de cada memoria.
362
+
363
+ Para desarrolladores: un cambio de formato sube `VERSION_ESQUEMA` y agrega la función de migración en `MIGRACIONES`
364
+ (con los mismos resguardos: repo limpio, tag `pre-vN`, un commit y vuelta atrás), con su prueba en
365
+ `tests/test_esquema.py`; la de v2 está en `ratifact/migracion_v2.py` y `tests/test_migracion_v2.py`.
366
+
367
+ ## 14. Codex, experimental (CLI, extensión de IDE y app de escritorio)
368
+
369
+ Las tres comparten `~/.codex/config.toml`; lo configura `ratifact install --apply` (sección 1) con una edición acotada:
370
+ solo reescribe las tablas `[mcp_servers.memoria-proyectos]`/`[mcp_servers.ratifact]` y sus subtablas (borra la `.env`,
371
+ renombra las `.tools.<herramienta>` con su `approval_mode`) y deja el resto del archivo byte por byte. Queda:
372
+
373
+ ```toml
374
+ [mcp_servers.ratifact]
375
+ command = "<home>/.local/bin/ratifact"
376
+ args = ["serve"]
377
+ ```
378
+
379
+ Si el servidor está definido de otra forma (tabla en línea, claves con puntos), no toca el archivo y da las
380
+ instrucciones para hacerlo a mano.
381
+
382
+ Codex eliminó los comandos personalizados (`~/.codex/prompts`) en marzo de 2026; `/run-task` se instala como skill
383
+ (enlaces de carpeta de la sección 12; Codex no sigue un `SKILL.md` enlazado como archivo) y se invoca con `$run-task T-NNN`. Codex lee `AGENTS.md`
384
+ de forma nativa, pero solo desde la raíz del repo git hacia abajo: en proyectos de varios repos ponga el bloque en la
385
+ carpeta raíz (si abre Codex ahí) y en el `AGENTS.md` de cada repo. Si hay otra memoria de agente instalada (engram),
386
+ el servidor declara en sus instrucciones MCP que ratifact es la fuente de verdad del proyecto.
387
+
388
+ ## 15. Idempotencia de creación
389
+
390
+ `propose_decision`, `add_pending` y `create_task` son idempotentes: si ya existe un registro del
391
+ mismo tipo (un ADR no compite con una tarea ni con un pendiente, aunque el texto del título coincida) con el
392
+ mismo título normalizado (sin distinguir mayúsculas, recortando los extremos y colapsando espacios internos),
393
+ **creado en los últimos `VENTANA_IDEMPOTENCIA_MINUTOS` minutos** (10 por defecto) en el mismo proyecto, Y QUE
394
+ TODAVÍA ESTÁ EN SU ESTADO INICIAL ("proposed" para ADR, "open" para pendientes, "todo" para tareas),
395
+ la llamada no crea ningún archivo nuevo, no hace commit, y devuelve el id del registro existente avisando que
396
+ ya estaba registrado (en el caso de una tarea, con el comando `/run-task T-NNN` para repetírselo al usuario).
397
+ `amend_task` aplica la misma ventana a una enmienda idéntica de la misma tarea.
398
+
399
+ La condición de estado inicial es deliberada: un registro que ya cambió de estado (rejected, superseded,
400
+ closed, in_progress, in_review, changes_requested, merged, failed, etc.) significa que un humano ya intervino sobre
401
+ él, así que nunca cuenta como duplicado aunque sea reciente. Esto cubre el flujo normal de "proponer → el
402
+ usuario pide un cambio → descartar/cerrar y volver a registrar corregido", que no debe confundirse con un
403
+ reintento perdido (un reintento genuino de un cliente que perdió la respuesta siempre encuentra el registro
404
+ todavía en su estado inicial, porque nadie tuvo tiempo de tocarlo).
405
+
406
+ Esto existe porque la llamada a una tool puede perderse en la capa del cliente (p. ej. Claude Desktop con un
407
+ timeout de 120 s) sin que el modelo sepa si el servidor llegó a ejecutarla; con esto, reintentar a ciegas es
408
+ seguro. No hay idempotency key del cliente (fuera de alcance v1): la detección es solo por título + estado +
409
+ antigüedad. La telemetría registra estas llamadas como exitosas (`error: false`) con un flag `duplicado: true`,
410
+ y `analizar_uso.py` reporta cuántas creaciones fueron duplicados detectados.
411
+
412
+
413
+ ## 16. Code layout
414
+
415
+ `servidor.py` es solo un envoltorio de `ratifact serve` hasta 1.1 (cabecera PEP 723, agrega su carpeta a `sys.path`,
416
+ importa el paquete `ratifact/` y llama a `ratifact.cli`); el punto de entrada es el comando `ratifact` (sección 0). El código
417
+ vive en `ratifact/`; ningún módulo supera 300 líneas y no hay importaciones circulares:
418
+
419
+ | Módulo | Responsabilidad |
420
+ |---|---|
421
+ | `ratifact/cli.py` | Comando `ratifact` (`serve`, `install`, `report`, `doctor`, `upgrade`, `--version`); `servidor()` carga herramientas y prompts. |
422
+ | `ratifact/instalar.py`, `ratifact/instalar_extras.py` | `ratifact install`: plan y ejecución; permisos de Claude Code, bloque de CLAUDE.md/AGENTS.md y enlaces de `/run-task`. |
423
+ | `ratifact/clientes.py`, `ratifact/clientes_toml.py` | Clientes MCP (Claude Desktop, Claude Code, Pi, Codex experimental): detección, estado (también para doctor) y edición de su configuración; la de Codex es una edición acotada del TOML. |
424
+ | `ratifact/archivos.py` | Escritura segura de archivos de otros programas: validación, respaldo `.bak-ratifact-<fecha>` y reemplazo atómico. |
425
+ | `ratifact/skills/` | Skill `run-task`, incluida en el paquete. |
426
+ | `ratifact/rutas.py` | Rutas sin projects.json: configuración nueva/vieja, log por defecto (XDG), copia de trabajo o instalación fija y repositorio de origen. |
427
+ | `ratifact/informe.py`, `ratifact/informe_memoria.py` | `ratifact report` (antes `analizar_uso.py`): agregados del log y los indicadores que salen de las memorias. |
428
+ | `ratifact/instalacion.py` | Inventario de solo lectura para doctor/upgrade: projects.json y sus claves, memorias (ubicación, esquema, git), integraciones, servidores en marcha y `.lock` tomados. |
429
+ | `ratifact/doctor.py` | `ratifact doctor`. |
430
+ | `ratifact/upgrade.py`, `ratifact/upgrade_aplicar.py` | `ratifact upgrade`: plan (sin cambios) y ejecución por pasos con vuelta atrás. |
431
+ | `ratifact/app.py` | Instancia FastMCP `mcp`, decoradores `herramienta`/`herramienta_async`, telemetría (`LOG_USO`, `_registrar_uso`) y `_ejecutar`. |
432
+ | `ratifact/config.py` | Rutas y configuración: `CONFIG` (projects.json, claves en español o inglés: `_valor`, `_clave_escritura`), `BASE_PROYECTOS`, `ErrorMemoria`, `_proyectos`, `_raiz`, `_mem`, ayudantes de repositorios, `_ruta_segura`, `_zonas_escritura` y el alias de rutas v1 (`_traducir_alias`). |
433
+ | `ratifact/vocabulario.py` | Vocabulario del esquema v2 y su equivalente v1: carpetas, vistas, claves, estados por tipo y `_normalizar_estado` (parámetros en español o inglés); mapas del contrato v0 → v1 (`HERRAMIENTAS_V0`, `PARAMETROS_V0`, `PROMPTS_V0`, `MODOS_V0`). |
434
+ | `ratifact/esquema.py` | `VERSION_ESQUEMA`, `MIGRACIONES`, versión (`schema.json` / centinela `esquema.json`), resguardos de la migración (repo limpio, tag, commit, vuelta atrás), `_asegurar_esquema` (primer acceso) y `_bloqueo`. |
435
+ | `ratifact/migracion_v2.py` | Migración v1 → v2: carpetas, frontmatter, títulos, etiquetas de revisión y el informe del commit. |
436
+ | `ratifact/registros.py` | Frontmatter (lectura/escritura), `_escribir_atomico`, `_commit`, ids y slugs, idempotencia, `_regenerar_vistas`, `_resumen_tareas`, `_hoy`/`_ahora`. |
437
+ | `ratifact/catalogo.py` | Catálogo de la memoria derivado en cada llamada: `_catalogo`, resolución de ids de `read_document` (`_resolver_id`), registros de `list_documents` y coincidencias por id/título de `search` (id exacto y hasta 5 títulos al inicio de palabra) y el bloque de pendientes abiertos de `get_context` (`_bloque_pendientes`). Sin índice, caché ni watcher. |
438
+ | `ratifact/busqueda.py` | Respuesta de `search` con cuotas por sección: catálogo, luego memoria y código a partes iguales (lo que un lado no usa pasa al otro), y la línea final con lo omitido por sección. |
439
+ | `ratifact/listado.py` | Listado con profundidad adaptativa de `list_documents`: `_listado` (presupuesto `LIMITE_LISTADO_ENTRADAS`/`LIMITE_LISTADO_CARACTERES` en config). |
440
+ | `ratifact/plantillas.py` | `PLANTILLA_INSTRUCCIONES`, `PLANTILLA_AGENTES` y `TEXTO_CIERRE`. |
441
+ | `ratifact/prompts.py` | Prompts `start` y `close` (antes `inicio` y `cierre`). |
442
+ | `ratifact/integraciones/` | Integraciones opcionales: `base.py` (descriptor `Integracion`, `FASES`), un módulo por integración (`codegraph.py`, `gentle_ai.py`, `engram.py`) y `registro.py` (`INTEGRACIONES`, detección en disco en cada llamada, guía para `get_context`/`create_task`/`update_task` y el parseo de `integraciones`). Agregar una = un módulo + registrarlo. Nunca llama a otros MCP. |
443
+ | `ratifact/herramientas/contexto_documentos.py` | `list_projects`, `get_context`, `search`, `list_documents`, `read_document`, `create_document`, `update_document`, `update_index`. |
444
+ | `ratifact/herramientas/decisiones.py` | `propose_decision`, `accept_decision`, `accept_decisions`, `review_proposals`, `decide_proposals`, `reject_decision`, `supersede_decision`. |
445
+ | `ratifact/herramientas/pendientes_sesiones.py` | `add_pending`, `close_pending`, `log_session`. |
446
+ | `ratifact/herramientas/tareas.py` | `create_task`, `update_task`, `request_changes`, `list_tasks` (y `_comando_pruebas`). |
447
+ | `ratifact/herramientas/tareas_brief.py` | `amend_task` y `read_task`. |
448
+ | `ratifact/herramientas/proyectos.py` | `init_memory`, `project_instructions`, `register_project`, `update_project` y la detección del comando de pruebas. |
449
+
450
+ `tests/contrato_herramientas.json` es la instantánea del contrato MCP (nombre, descripción y esquema de cada
451
+ herramienta y prompt); `tests/test_contrato.py` falla si cambia. Para regenerarla a propósito (descripciones normalizadas con `inspect.cleandoc` y formato fijo, así que
452
+ regenerar dos veces da los mismos bytes): `uv run --with pytest --with "mcp>=1.2,<2" python tests/test_contrato.py`.
453
+ `tests/contrato_herramientas_v0.json` es la
454
+ instantánea anterior al renombrado (v0, en español): la prueba comprueba que cada herramienta vieja tiene exactamente
455
+ una nueva y que `amend_task`/`read_task` son las únicas agregadas.
ratifact-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Emanuel
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.