d1d4c commited on
Commit
e3abea0
·
verified ·
1 Parent(s): 59aaeb1

feat: v0.6.0 — Fase 1 ContextMemory synthesis + CLAUDE.md (CLAUDE.md)

Browse files
Files changed (1) hide show
  1. CLAUDE.md +167 -0
CLAUDE.md ADDED
@@ -0,0 +1,167 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # CLAUDE.md — Bruno / retro-cpu
2
+
3
+ **Componente:** `d1d4c/retro-cpu` HF Space ("Retro Lite Online")
4
+ **Propietario:** HFPilot (retro-hf)
5
+ **Versión actual:** 0.6.0 (2026-06-21 — Fase 1: síntesis ContextMemory activa)
6
+ **ADRs:** ADR-562 (Harness Independence), ADR-563 (Native Harness)
7
+
8
+ ---
9
+
10
+ ## Qué es Bruno
11
+
12
+ Bruno es la instancia online y ligera de Retro que corre en un HF Docker Space
13
+ con CPU gratuita (`cpu-basic`, free tier). Permite que Dídac opere desde el móvil
14
+ (Telegram) cuando `satelite` está offline. **No es el Retro completo** — es un
15
+ bridge conversacional con memoria propia.
16
+
17
+ Bot Telegram: `@Bruno_Retro_bot`. Solo responde al `chat_id` de Dídac (`6622755810`).
18
+
19
+ ---
20
+
21
+ ## Arquitectura
22
+
23
+ ```
24
+ [Móvil] ──Telegram──> [webhook POST /] ──> retro-cpu (CPU-only)
25
+ │
26
+ ┌─────────────────────┴──────────────────────┐
27
+ │ │
28
+ texto (normal) voz (BLOQUEADA)
29
+ │ │
30
+ retro-space /v1/chat/completions getFile → api.telegram.org
31
+ (Qwen2.5-7B, Bearer HF_TOKEN) (ConnectTimeout en HF)
32
+ │
33
+ respuesta inline en webhook HTTP
34
+ {"method":"sendMessage","chat_id":...}
35
+ ```
36
+
37
+ **Constraint crítico de red (2026-06-21):** HF Spaces no pueden hacer outbound
38
+ a `api.telegram.org`. La respuesta se devuelve inline en el body HTTP del webhook
39
+ (mecanismo oficial de Telegram). Las notas de voz están bloqueadas hasta que haya
40
+ un Cloudflare Worker relay (Fase 1, pendiente).
41
+
42
+ ---
43
+
44
+ ## Memoria — bruno/v1 (sovereign graph)
45
+
46
+ Bruno tiene su **propio grafo soberano**, independiente del HyperGraph central
47
+ de Retro (ADR-562: sin `sys.path` a casa, sin writes a la DB central).
48
+
49
+ ### Stack
50
+
51
+ | Componente | Descripción |
52
+ |------------|-------------|
53
+ | `bruno_graph.py` | Adaptador stdlib (`sqlite3`+`json`), sin deps externas |
54
+ | `/data/bruno_graph.db` | SQLite en bucket `retro-cpu-storage`, **sobrevive reinicios** |
55
+ | `bruno_v1.json` | Ontología SSOT (horneada en imagen + copia en `retro-hf/ontology/`) |
56
+ | `test_bruno_graph.py` | 5 tests de rechazo de violaciones de schema |
57
+
58
+ ### Tipos de nodo
59
+
60
+ | Tipo | Persistencia | Descripción |
61
+ |------|-------------|-------------|
62
+ | `Message` | append-only | Turno de conversación (role, content, turn_index, session_ref) |
63
+ | `ContextMemory` | singleton por chat_id, upsert monotónico | Síntesis LLM cross-session |
64
+ | `Pattern` | declarado | Reservado para patrones detectados |
65
+
66
+ ### Cómo funciona la memoria (v0.6.0 — Fase 1 activa)
67
+
68
+ ```
69
+ Turno de usuario
70
+ │
71
+ ├── 1. build_system_prompt(chat_id, bruno)
72
+ │ └── lee ContextMemory → si synthesis_strategy="llm_qwen2.5-7b"
73
+ │ → inyecta en system prompt
74
+ │
75
+ ├── 2. infer_chat(history, system_prompt)
76
+ │ └── Qwen2.5-7B genera respuesta
77
+ │
78
+ ├── 3. Respuesta inline → Telegram
79
+ │
80
+ └── 4. asyncio.create_task(synthesize_context_memory(...)) ← background
81
+ └── llama a retro-space con meta-prompt de síntesis (≤200 tokens)
82
+ → upsert ContextMemory (synthesis_strategy="llm_qwen2.5-7b")
83
+ ```
84
+
85
+ La síntesis ocurre en background tras enviar la respuesta → latencia = 0 para el usuario.
86
+
87
+ ### API de bruno_graph.py
88
+
89
+ ```python
90
+ from bruno_graph import BrunoGraph
91
+
92
+ bruno = BrunoGraph(db_path="/data/bruno_graph.db", ontology_path="bruno_v1.json")
93
+
94
+ # Append mensaje
95
+ bruno.append_message(chat_id, "user", "hola", source="telegram")
96
+ bruno.append_message(chat_id, "assistant", "hola!", source="qwen2.5-7b")
97
+
98
+ # Carrusel activo (N últimos turnos)
99
+ history = bruno.carousel(chat_id, n=20) # → [{"role": ..., "content": ...}]
100
+
101
+ # ContextMemory (singleton cross-session)
102
+ cm = bruno.get_context_memory(chat_id) # → dict | None
103
+ bruno.upsert_context_memory(chat_id, content, # → crea o actualiza
104
+ synthesis_strategy="llm_qwen2.5-7b")
105
+
106
+ # Reset de sesión (epoch rota, turnos anteriores se conservan)
107
+ bruno.reset_session(chat_id)
108
+ ```
109
+
110
+ ---
111
+
112
+ ## Deploy
113
+
114
+ **⚠️ retro-cpu usa Dev Mode → código horneado en imagen Docker (sin git restore).**
115
+ `api.upload_file()` NO refresca el contenedor. Para aplicar cambios: **`factory_reboot=True`**.
116
+
117
+ ```python
118
+ from huggingface_hub import HfApi
119
+ import os
120
+
121
+ api = HfApi(token=os.environ["HF_TOKEN"])
122
+
123
+ # 1. Subir archivo(s) modificado(s)
124
+ for fname in ["app.py", "bruno_graph.py", "bruno_v1.json"]:
125
+ api.upload_file(
126
+ path_or_fileobj=open(f"retro-cpu/{fname}", "rb").read(),
127
+ path_in_repo=fname,
128
+ repo_id="d1d4c/retro-cpu",
129
+ repo_type="space",
130
+ commit_message=f"deploy: {fname} vX.Y.Z",
131
+ )
132
+
133
+ # 2. Factory reboot SIEMPRE (Dev Mode requiere reconstruir imagen)
134
+ api.restart_space("d1d4c/retro-cpu", factory_reboot=True)
135
+ ```
136
+
137
+ **Secrets del Space** (configurados en HF, no en código):
138
+
139
+ | Secret | Propósito |
140
+ |--------|-----------|
141
+ | `TELEGRAM_BOT_TOKEN` | Bot API token de @BotFather |
142
+ | `HF_TOKEN` | Bearer auth a retro-space + retro-tts (privados) |
143
+ | `WEBHOOK_SECRET` | Secret token del webhook de Telegram |
144
+ | `ALLOWED_CHAT_IDS` | Allowlist de chat_ids (solo Dídac: `6622755810`) |
145
+
146
+ ---
147
+
148
+ ## SSH
149
+
150
+ ```bash
151
+ ssh -i ~/.ssh/hf_space_new d1d4c-retro-cpu@ssh.hf.space
152
+ ```
153
+
154
+ ---
155
+
156
+ ## Roadmap Bruno
157
+
158
+ | Fase | Estado | Descripción |
159
+ |------|--------|-------------|
160
+ | 0 | ✅ DONE | Chat text-only, grafo bruno/v1, persistencia bucket |
161
+ | 1 | ✅ DONE (0.6.0) | Síntesis ContextMemory (LLM background) + inyección en prompt |
162
+ | 1b | Pendiente | CF Worker relay → desbloquea voz in/out desde móvil |
163
+ | 2 | Opcional | Export async unidireccional HF→casa (NUNCA sync bidireccional) |
164
+
165
+ ---
166
+
167
+ **Owner:** HFPilot | **Proyecto:** retro-hf | **Actualizado:** 2026-06-21