opencode-flema-engram-sidebar 0.1.2 → 0.1.3

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 (41) hide show
  1. package/README.md +474 -469
  2. package/dist/adapters/cloud.d.ts +14 -6
  3. package/dist/adapters/cloud.d.ts.map +1 -1
  4. package/dist/adapters/cloud.js +224 -20
  5. package/dist/adapters/cloud.js.map +1 -1
  6. package/dist/adapters/composite.d.ts +2 -1
  7. package/dist/adapters/composite.d.ts.map +1 -1
  8. package/dist/adapters/composite.js +36 -1
  9. package/dist/adapters/composite.js.map +1 -1
  10. package/dist/adapters/factory.d.ts +17 -0
  11. package/dist/adapters/factory.d.ts.map +1 -0
  12. package/dist/adapters/factory.js +76 -0
  13. package/dist/adapters/factory.js.map +1 -0
  14. package/dist/adapters/local.d.ts +2 -1
  15. package/dist/adapters/local.d.ts.map +1 -1
  16. package/dist/adapters/local.js +5 -2
  17. package/dist/adapters/local.js.map +1 -1
  18. package/dist/adapters/types.d.ts +7 -0
  19. package/dist/adapters/types.d.ts.map +1 -1
  20. package/dist/index.d.ts +2 -0
  21. package/dist/index.d.ts.map +1 -1
  22. package/dist/index.js +1 -0
  23. package/dist/index.js.map +1 -1
  24. package/dist/schemas/health.d.ts +14 -0
  25. package/dist/schemas/health.d.ts.map +1 -1
  26. package/dist/schemas/health.js +5 -0
  27. package/dist/schemas/health.js.map +1 -1
  28. package/dist/sidebar/hooks/use-engram.d.ts +3 -1
  29. package/dist/sidebar/hooks/use-engram.d.ts.map +1 -1
  30. package/dist/sidebar/hooks/use-engram.js +5 -3
  31. package/dist/sidebar/hooks/use-engram.js.map +1 -1
  32. package/dist/sidebar/plugin.d.ts +9 -2
  33. package/dist/sidebar/plugin.d.ts.map +1 -1
  34. package/dist/sidebar/plugin.js +62 -16
  35. package/dist/sidebar/plugin.js.map +1 -1
  36. package/dist/stdio.js +0 -0
  37. package/dist/utils/project-resolver.d.ts +7 -1
  38. package/dist/utils/project-resolver.d.ts.map +1 -1
  39. package/dist/utils/project-resolver.js +38 -6
  40. package/dist/utils/project-resolver.js.map +1 -1
  41. package/package.json +74 -74
package/README.md CHANGED
@@ -1,469 +1,474 @@
1
- # Flema Engram para OpenCode
2
-
3
- [![CI](https://github.com/oniricosistemas/flema-engram/actions/workflows/ci.yml/badge.svg)](https://github.com/oniricosistemas/flema-engram/actions/workflows/ci.yml)
4
- [![npm](https://img.shields.io/npm/v/opencode-flema-engram-sidebar?logo=npm)](https://www.npmjs.com/package/opencode-flema-engram-sidebar)
5
- [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D22-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/)
6
- [![License: MIT](https://img.shields.io/github/license/oniricosistemas/flema-engram)](https://github.com/oniricosistemas/flema-engram/blob/main/LICENSE)
7
-
8
- Un sidebar local y de solo lectura que mantiene visible el contexto reciente de
9
- [Engram](https://github.com/Gentleman-Programming/engram) mientras trabajás dentro de OpenCode.
10
-
11
- La canción **“Y aún yo te recuerdo”** inspiró artísticamente la idea central: que la
12
- última memoria guardada siga presente en el contexto de desarrollo. Esta referencia
13
- es un homenaje a esa inspiración; no implica afiliación, patrocinio ni titularidad
14
- sobre la obra.
15
-
16
- > **English summary:** Flema Engram is a local-first, read-only OpenCode
17
- > plugin/sidebar that surfaces Engram health, project context, recent memories,
18
- > blockers, and SDD progress. An MCP stdio adapter is included only as an optional
19
- > integration path.
20
-
21
- ## Inicio rápido
22
-
23
- ### Requisitos
24
-
25
- | Componente | Requisito |
26
- | --- | --- |
27
- | Node.js | 22 o posterior |
28
- | OpenCode | 1.18.25 o posterior |
29
- | Engram | Servicio HTTP local activo en `http://127.0.0.1:7437` |
30
- | Proyecto | Alguna observación o sesión reciente que permita validar el nombre |
31
-
32
- ### 1. Registrá el sidebar en `tui.json`
33
-
34
- Configuración mínima:
35
-
36
- ```json
37
- {
38
- "$schema": "https://opencode.ai/tui.json",
39
- "plugin": ["opencode-flema-engram-sidebar"]
40
- }
41
- ```
42
-
43
- OpenCode instala y cachea el paquete automáticamente; no hace falta instalarlo de
44
- forma global con npm. El spec simple carga `dist/index.js`, cuyo export por defecto es
45
- el plugin TUI. El subpath `/tui` sigue disponible para imports directos, pero no es
46
- necesario en la configuración.
47
-
48
- ### 2. Iniciá Engram y abrí OpenCode en tu proyecto
49
-
50
- El sidebar hace una carga inicial, vuelve a consultar cada 30 segundos de forma
51
- predeterminada y permite refrescar manualmente con <kbd>Alt</kbd>+<kbd>R</kbd>.
52
-
53
- ## Qué es — y qué no es
54
-
55
- | Sí es | No es |
56
- | --- | --- |
57
- | Un plugin para el slot `sidebar_content` de OpenCode | Una TUI independiente |
58
- | Una vista local y de solo lectura sobre Engram | Un reemplazo de Engram |
59
- | Un resumen de contexto, actividad y avance SDD | Un editor o gestor de memorias |
60
- | Un cliente del HTTP local de Engram | Un servicio cloud o de sincronización |
61
- | Un paquete con un adaptador MCP stdio opcional | Un producto centrado en MCP |
62
-
63
- El sidebar es el producto principal. El comando MCP existe para integraciones
64
- avanzadas y puede ignorarse por completo al usar el plugin de OpenCode.
65
-
66
- ## Cómo funciona
67
-
68
- 1. OpenCode carga el export raíz de `opencode-flema-engram-sidebar`.
69
- 2. El plugin resuelve un candidato de proyecto y lo valida contra los proyectos
70
- derivados de observaciones y sesiones recientes de Engram.
71
- 3. Consulta en paralelo salud, proyectos y observaciones del proyecto.
72
- 4. Ordena la actividad por actualización más reciente, detecta artefactos SDD y
73
- reconoce bloqueos explícitos.
74
- 5. Renderiza texto dentro del sidebar de la sesión visible y conserva datos útiles
75
- como `STALE` si una actualización posterior queda incompleta.
76
-
77
- Las llamadas usan exclusivamente `GET` contra el Engram local. El plugin no guarda,
78
- edita ni elimina memorias.
79
-
80
- ### Endpoints utilizados
81
-
82
- | Propósito | Endpoint local |
83
- | --- | --- |
84
- | Salud | `GET /health` |
85
- | Observaciones | `GET /observations/recent` |
86
- | Sesiones para derivar proyectos | `GET /sessions/recent` |
87
-
88
- El adaptador local usa un timeout de 5 segundos. Para mantener la vista acotada, el
89
- sidebar solicita hasta 20 observaciones del proyecto; si la respuesta filtrada está
90
- vacía o mezcla proyectos, usa una consulta sin filtro de hasta 100 registros y aplica
91
- una coincidencia exacta local.
92
-
93
- ## Configuración
94
-
95
- ### Opciones soportadas por el plugin
96
-
97
- Usá la forma `[plugin, options]` solamente cuando necesites opciones:
98
-
99
- ```json
100
- {
101
- "$schema": "https://opencode.ai/tui.json",
102
- "plugin": [
103
- [
104
- "opencode-flema-engram-sidebar",
105
- {
106
- "enabled": true,
107
- "project": "mi-proyecto",
108
- "pollInterval": 30000
109
- }
110
- ]
111
- ]
112
- }
113
- ```
114
-
115
- | Opción | Tipo | Comportamiento |
116
- | --- | --- | --- |
117
- | `enabled` | `boolean` | `false` evita que el plugin registre el sidebar. Por defecto está habilitado. |
118
- | `project` | `string` | Nombre exacto de proyecto Engram. Tiene la prioridad más alta. |
119
- | `pollInterval` | `number` | Intervalo automático en milisegundos; debe ser mayor que cero. Por defecto: `30000`. |
120
-
121
- No hay una opción TUI para cambiar la URL o el timeout del HTTP local. El plugin
122
- incluido usa `http://127.0.0.1:7437` y 5 segundos respectivamente.
123
-
124
- ### Resolución del proyecto
125
-
126
- La precedencia real es:
127
-
128
- 1. `project` no vacío en el `tui.json` que declara el plugin;
129
- 2. variable de entorno `ENGRAM_PROJECT` no vacía;
130
- 3. nombre normalizado del directorio de trabajo y, como segundo candidato automático,
131
- su ruta absoluta normalizada.
132
-
133
- ```powershell
134
- $env:ENGRAM_PROJECT = "mi-proyecto"
135
- opencode .
136
- ```
137
-
138
- Cada candidato debe coincidir con un proyecto conocido por Engram. Se acepta una
139
- coincidencia exacta o una única coincidencia sin distinguir mayúsculas. Un valor
140
- explícito o de entorno inválido **no** cae silenciosamente al nombre del directorio.
141
- Tampoco hay búsqueda difusa, recorrido de directorios padre, selector ni elección
142
- automática del primer proyecto.
143
-
144
- ### Tema
145
-
146
- El render del plugin usa el color de texto del tema activo que entrega OpenCode y no
147
- impone una paleta ni crea archivos de tema propios. Los estados también se distinguen
148
- por etiquetas e iconos, no solamente por color.
149
-
150
- ## Qué muestra el sidebar
151
-
152
- ### Health
153
-
154
- | Estado | Significado |
155
- | --- | --- |
156
- | `CHECKING` | La carga inicial todavía no terminó. |
157
- | `OK` | El HTTP local responde y las observaciones requeridas se obtuvieron. |
158
- | `STALE` | Hay datos utilizables o previos, pero una etapa de la actualización quedó incompleta. |
159
- | `ERROR` | Hubo respuesta parcial o un fallo de salud sin una carga completa. |
160
- | `OFFLINE` | No pudo obtenerse información central de Engram. |
161
-
162
- Los fallos muestran la etapa o endpoint relevante. Un error queda contenido en el
163
- sidebar para no derribar el host de OpenCode.
164
-
165
- ### Proyecto y contexto detectado
166
-
167
- Muestra el nombre validado del proyecto o `unresolved`. Cuando no puede resolverlo,
168
- explica si falta configuración, el candidato no existe, es ambiguo o Engram estaba
169
- offline durante la validación.
170
-
171
- ### Observaciones indexadas
172
-
173
- La línea `Indexed observations` refleja las observaciones del proyecto cargadas para
174
- la vista actual, dentro del límite acotado del sidebar; no debe interpretarse como un
175
- contador histórico total de toda la base. Si no hay registros, se muestra un estado
176
- vacío explícito.
177
-
178
- ### Avance SDD
179
-
180
- Agrupa observaciones cuyo `topic_key` sigue `sdd/<cambio>/<artefacto>`. Reconoce las
181
- fases `init`, `explore`, `proposal`, `spec`, `design`, `tasks`, `apply`, `verify` y
182
- `archive`, incluidos los alias `apply-progress`, `verify-report` y `archive-report`.
183
- Presenta el estado derivado y la secuencia de fases observadas. Si no hay cambios
184
- activos o detectables, indica `No active SDD changes`.
185
-
186
- ### Bloqueos
187
-
188
- Lista títulos de observaciones reconocidas como bloqueos por tipo, título o frases
189
- explícitas como `status: blocked`, `blocker:`, `blocked by`, `depends on` o
190
- `waiting for`. No infiere bloqueos a partir de sentimiento o contexto ambiguo.
191
-
192
- ### Actividad reciente
193
-
194
- Muestra los títulos de las cinco observaciones más recientes del proyecto, ordenadas
195
- por `updated_at` y luego por ID. Cuando no hay actividad, aparece un estado vacío.
196
-
197
- ### Última memoria guardada
198
-
199
- No existe un panel duplicado para “última memoria”: la observación actualizada más
200
- reciente ocupa el primer lugar de **Recent Activity**. La vista muestra su título, no
201
- el contenido completo. Así mantiene presente la referencia más nueva sin convertir
202
- el sidebar en un explorador de memorias.
203
-
204
- ### Refresh, carga y errores
205
-
206
- - La primera carga se agenda una sola vez para el sidebar de la sesión visible.
207
- - El polling automático usa `pollInterval` o 30 segundos.
208
- - <kbd>Alt</kbd>+<kbd>R</kbd> vuelve a resolver el proyecto y repite todas las consultas.
209
- - La tecla `r` sin modificadores queda libre para escribir en el prompt.
210
- - `Refreshing…`, `Refreshed` y `Refresh incomplete` describen el resultado manual.
211
- - Los datos anteriores se conservan como `STALE` cuando siguen siendo útiles.
212
- - Un proyecto sin observaciones, sin cambios SDD o sin bloqueos tiene mensajes vacíos
213
- propios; no se confunde con un error de conexión.
214
-
215
- ## Ejemplos de uso
216
-
217
- ### Detección automática desde el directorio
218
-
219
- ```sh
220
- cd mi-proyecto
221
- opencode .
222
- ```
223
-
224
- Si Engram conoce `mi-proyecto`, el sidebar valida ese nombre y carga sus memorias.
225
-
226
- ### Fijar un proyecto por workspace
227
-
228
- ```json
229
- {
230
- "$schema": "https://opencode.ai/tui.json",
231
- "plugin": [
232
- ["opencode-flema-engram-sidebar", { "project": "backend-api" }]
233
- ]
234
- }
235
- ```
236
-
237
- Esto es útil cuando el nombre del directorio no coincide con el proyecto guardado en
238
- Engram. El valor debe coincidir; una configuración incorrecta queda como `unresolved`.
239
-
240
- ### Reducir la frecuencia de actualización
241
-
242
- ```json
243
- {
244
- "$schema": "https://opencode.ai/tui.json",
245
- "plugin": [
246
- ["opencode-flema-engram-sidebar", { "pollInterval": 60000 }]
247
- ]
248
- }
249
- ```
250
-
251
- El sidebar actualizará cada 60 segundos y seguirá aceptando <kbd>Alt</kbd>+<kbd>R</kbd>.
252
-
253
- ## Instalación desde el código fuente
254
-
255
- ```sh
256
- git clone https://github.com/oniricosistemas/flema-engram.git
257
- cd flema-engram
258
- npm install
259
- ```
260
-
261
- El archivo versionado `tui.example.json` es la referencia para desarrollo desde el
262
- código fuente y apunta directamente a:
263
-
264
- ```json
265
- {
266
- "$schema": "https://opencode.ai/tui.json",
267
- "plugin": [["./src/sidebar/plugin.tsx", {}]]
268
- }
269
- ```
270
-
271
- Creá tu copia local con `Copy-Item tui.example.json tui__.json` en PowerShell o
272
- `cp tui.example.json tui__.json` en shells compatibles. `tui__.json` está ignorado
273
- por Git a propósito: es la copia local para adaptar sin versionar rutas u opciones
274
- específicas de tu máquina. Si tu entorno requiere el nombre `tui.json`, copiá allí el
275
- contenido de `tui__.json` o fusioná su bloque `plugin` en tu configuración existente.
276
-
277
- La ruta se resuelve desde el archivo que declara el plugin. En una configuración
278
- global de Windows, reemplazá la ruta relativa de tu copia local por una URL absoluta:
279
-
280
- ```json
281
- {
282
- "$schema": "https://opencode.ai/tui.json",
283
- "plugin": [
284
- ["file:///D:/general/mcp-flema-engram/src/sidebar/plugin.tsx", {}]
285
- ]
286
- }
287
- ```
288
-
289
- Preservá el resto de tus plugins y opciones al fusionar la configuración.
290
-
291
- ## Solución de problemas
292
-
293
- ### Engram aparece offline
294
-
295
- - Confirmá que Engram escuche en `127.0.0.1:7437`.
296
- - Probá `http://127.0.0.1:7437/health` desde la misma máquina.
297
- - Revisá firewalls o proxies locales; el plugin no intenta conectarse a un servicio
298
- cloud como alternativa.
299
- - Corregí la causa y presioná <kbd>Alt</kbd>+<kbd>R</kbd>.
300
-
301
- ### El proyecto no se detecta
302
-
303
- - Verificá el nombre real guardado en Engram.
304
- - Definí `project` en `tui.json` si el workspace tiene otro nombre.
305
- - Usá `ENGRAM_PROJECT` solamente cuando deba aplicar al proceso completo.
306
- - Recordá la precedencia: `project` explícito gana sobre `ENGRAM_PROJECT`.
307
- - Un proyecto sin observaciones ni sesiones recientes puede no aparecer en la lista
308
- derivada que se usa para validarlo.
309
-
310
- ### Los datos parecen viejos
311
-
312
- - Mirá si Health dice `STALE` y leé el detalle de etapa/endpoint.
313
- - Esperá el próximo polling o usá <kbd>Alt</kbd>+<kbd>R</kbd>.
314
- - Confirmá que la memoria pertenece exactamente al proyecto resuelto.
315
- - El feed solo muestra cinco títulos y la consulta del sidebar está acotada a 20
316
- observaciones.
317
-
318
- ### El plugin no carga
319
-
320
- - Cerrá y reiniciá OpenCode después de cambiar `tui.json`.
321
- - Validá el JSON y la ruta del plugin.
322
- - Confirmá Node.js 22+ y OpenCode 1.18.25+.
323
- - Para npm, usá el nombre exacto `opencode-flema-engram-sidebar`.
324
- - Para fuente local, ejecutá `npm install` y comprobá que la ruta termine en
325
- `src/sidebar/plugin.tsx`.
326
- - Revisá la salida de arranque de OpenCode. El plugin no crea archivos de log propios.
327
-
328
- ### OpenCode no encuentra el export del paquete
329
-
330
- - Confirmá que la versión instalada tiene un export raíz por defecto con `id` y `tui`.
331
- - Ejecutá `npm view opencode-flema-engram-sidebar exports` para inspeccionar la
332
- metadata publicada.
333
- - Si trabajás sobre un tarball local, verificá que incluya
334
- `dist/index.js`, `dist/sidebar/plugin.js` y sus declaraciones.
335
- - Usá `opencode-flema-engram-sidebar` en la configuración. El subpath `/tui` queda
336
- disponible para imports directos, pero OpenCode 1.18.25 puede no cachear ese spec de
337
- npm de forma confiable.
338
-
339
- ### Diagnóstico para contribuidores
340
-
341
- ```sh
342
- npm run typecheck
343
- npm test
344
- npm run verify:package
345
- ```
346
-
347
- `typecheck` valida TypeScript sin emitir archivos; `test` ejecuta Vitest una vez; y
348
- `verify:package` inspecciona un `npm pack --dry-run` contra el contenido compilado
349
- existente. No hay una opción de log JSONL ni un archivo de diagnóstico del sidebar.
350
-
351
- ## Desarrollo y contribución
352
-
353
- ```sh
354
- npm ci
355
- npm run typecheck
356
- npm test
357
- npm run build
358
- npm run verify:package
359
- ```
360
-
361
- | Comando | Qué comprueba |
362
- | --- | --- |
363
- | `npm ci` | Instala exactamente el árbol de `package-lock.json`; es el usado por CI. |
364
- | `npm install` | Instala dependencias y permite actualizar el lockfile en desarrollo. |
365
- | `npm run typecheck` | Ejecuta `tsc --noEmit` con configuración estricta. |
366
- | `npm test` | Ejecuta la suite unitaria y de integración con Vitest. |
367
- | `npm run test:watch` | Mantiene Vitest activo durante el desarrollo. |
368
- | `npm run test:coverage` | Genera cobertura mediante V8. |
369
- | `npm run build` | Compila `src` a ESM, declaraciones y sourcemaps en `dist`. |
370
- | `npm run verify:package` | Valida metadata y contenido del tarball sin publicarlo. Requiere un `dist` actualizado. |
371
- | `npm run mcp` | Inicia desde fuente el adaptador MCP stdio opcional mediante `tsx`. |
372
-
373
- La CI usa Node 22 y ejecuta, en este orden: typecheck, tests, build y verificación del
374
- paquete. No publica artefactos ni necesita secretos. Antes de proponer un cambio:
375
-
376
- - [ ] Mantené el sidebar como producto principal y el MCP como integración opcional.
377
- - [ ] No introduzcas escrituras sobre Engram en el flujo de solo lectura.
378
- - [ ] Agregá o actualizá pruebas para cambios de comportamiento.
379
- - [ ] Ejecutá los cuatro checks de CI.
380
- - [ ] No incluyas `src`, tests, OpenSpec, configs locales ni logs en el tarball.
381
-
382
- ## Empaquetado y publicación
383
-
384
- La lista `files` permite publicar `dist`, `README.md` y `LICENSE`; npm agrega además
385
- la metadata obligatoria. El verificador exige, como mínimo:
386
-
387
- - API raíz: `dist/index.js` y `dist/index.d.ts`;
388
- - plugin: `dist/sidebar/plugin.js` y `dist/sidebar/plugin.d.ts`;
389
- - CLI opcional: `dist/stdio.js`;
390
- - README, licencia y `package.json`.
391
-
392
- `prepublishOnly` ejecuta automáticamente:
393
-
394
- ```sh
395
- npm run typecheck && npm test && npm run build && npm run verify:package
396
- ```
397
-
398
- Para publicar necesitás permisos sobre
399
- [`opencode-flema-engram-sidebar`](https://www.npmjs.com/package/opencode-flema-engram-sidebar),
400
- una sesión npm válida y un `package.json` con versión todavía no publicada. Este
401
- repositorio no configura publicación automática, tokens ni secretos.
402
-
403
- ## Integración MCP opcional
404
-
405
- > Sección avanzada: no es necesaria para usar el sidebar.
406
-
407
- La instalación global expone el comando stdio:
408
-
409
- ```sh
410
- mcp-flema-engram
411
- ```
412
-
413
- Desde el repositorio puede iniciarse sin compilar con:
414
-
415
- ```sh
416
- npm run mcp
417
- ```
418
-
419
- Ejemplo de configuración local de OpenCode, equivalente a `opencode.example.json`:
420
-
421
- ```json
422
- {
423
- "$schema": "https://opencode.ai/config.json",
424
- "mcp": {
425
- "engram": {
426
- "type": "local",
427
- "command": ["npm", "run", "mcp"],
428
- "enabled": true
429
- }
430
- }
431
- }
432
- ```
433
-
434
- El servidor ofrece herramientas y recursos MCP de lectura para salud, proyectos,
435
- observaciones, sesiones y cambios SDD. Sigue usando el mismo HTTP local de Engram;
436
- no agrega persistencia ni sincronización cloud.
437
-
438
- ## Seguridad, privacidad y enfoque local-first
439
-
440
- - Los datos de Engram permanecen en la máquina y el runtime consulta loopback.
441
- - El sidebar no requiere credenciales, telemetría ni servicios cloud.
442
- - No ejecuta operaciones de escritura sobre memorias.
443
- - No crea logs propios con contenido de observaciones.
444
- - El contenido de memorias puede ser sensible: protegé el acceso al proceso y puerto
445
- local de Engram como protegerías cualquier herramienta de desarrollo.
446
- - Las conexiones externas solo son necesarias para tareas ajenas al runtime local,
447
- como instalar desde npm o abrir enlaces de documentación.
448
-
449
- El repositorio contiene una clase experimental de adaptador cloud con operaciones no
450
- implementadas. No forma parte del flujo del plugin ni constituye soporte cloud.
451
-
452
- ## Roadmap y alcance diferido
453
-
454
- Están explícitamente fuera del MVP actual:
455
-
456
- - dashboard visual y acciones/atajos para abrirlo;
457
- - conexión remota mediante `opencode attach`;
458
- - selector manual de proyecto, navegación `j`/`k` y más atajos globales;
459
- - configuración de URL/timeout desde `tui.json`;
460
- - sincronización cloud y edición de memorias.
461
-
462
- ## Licencia y enlaces
463
-
464
- Distribuido bajo la [licencia MIT](./LICENSE).
465
-
466
- - [Repositorio](https://github.com/oniricosistemas/flema-engram)
467
- - [Issues](https://github.com/oniricosistemas/flema-engram/issues)
468
- - [Paquete npm](https://www.npmjs.com/package/opencode-flema-engram-sidebar)
469
- - [CI](https://github.com/oniricosistemas/flema-engram/actions/workflows/ci.yml)
1
+ # Flema Engram para OpenCode
2
+
3
+ [![CI](https://github.com/oniricosistemas/flema-engram/actions/workflows/ci.yml/badge.svg)](https://github.com/oniricosistemas/flema-engram/actions/workflows/ci.yml)
4
+ [![npm](https://img.shields.io/npm/v/opencode-flema-engram-sidebar?logo=npm)](https://www.npmjs.com/package/opencode-flema-engram-sidebar)
5
+ [![Node.js](https://img.shields.io/badge/Node.js-%3E%3D22-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/)
6
+ [![License: MIT](https://img.shields.io/github/license/oniricosistemas/flema-engram)](https://github.com/oniricosistemas/flema-engram/blob/main/LICENSE)
7
+
8
+ Un sidebar local y de solo lectura que mantiene visible el contexto reciente de
9
+ [Engram](https://github.com/Gentleman-Programming/engram) mientras trabajás dentro de OpenCode.
10
+
11
+ La canción **“Y aún yo te recuerdo”** inspiró artísticamente la idea central: que la
12
+ última memoria guardada siga presente en el contexto de desarrollo. Esta referencia
13
+ es un homenaje a esa inspiración; no implica afiliación, patrocinio ni titularidad
14
+ sobre la obra.
15
+
16
+ > **English summary:** Flema Engram is a local-first, read-only OpenCode
17
+ > plugin/sidebar that surfaces Engram health, project context, recent memories,
18
+ > blockers, and SDD progress. An MCP stdio adapter is included only as an optional
19
+ > integration path.
20
+
21
+ ## Inicio rápido
22
+
23
+ ### Requisitos
24
+
25
+ | Componente | Requisito |
26
+ | --- | --- |
27
+ | Node.js | 22 o posterior |
28
+ | OpenCode | 1.18.25 o posterior |
29
+ | Engram | Servicio HTTP local activo en `http://127.0.0.1:7437` |
30
+ | Proyecto | Alguna observación o sesión reciente que permita validar el nombre |
31
+
32
+ ### 1. Registrá el sidebar en `tui.json`
33
+
34
+ Configuración mínima:
35
+
36
+ ```json
37
+ {
38
+ "$schema": "https://opencode.ai/tui.json",
39
+ "plugin": ["opencode-flema-engram-sidebar"]
40
+ }
41
+ ```
42
+
43
+ OpenCode instala y cachea el paquete automáticamente; no hace falta instalarlo de
44
+ forma global con npm. El spec simple carga `dist/index.js`, cuyo export por defecto es
45
+ el plugin TUI. El subpath `/tui` sigue disponible para imports directos, pero no es
46
+ necesario en la configuración.
47
+
48
+ > **Importante:** `npm install -g opencode-flema-engram-sidebar` por sí solo instala el
49
+ > paquete en npm global, pero **no registra el plugin en OpenCode**. La entrada anterior
50
+ > en el `tui.json` global es el único paso de configuración necesario. Después, OpenCode
51
+ > resuelve, descarga y cachea la versión publicada automáticamente.
52
+
53
+ ### 2. Iniciá Engram y abrí OpenCode en tu proyecto
54
+
55
+ El sidebar hace una carga inicial, vuelve a consultar cada 30 segundos de forma
56
+ predeterminada y permite refrescar manualmente con <kbd>Alt</kbd>+<kbd>R</kbd>.
57
+
58
+ ## Qué es — y qué no es
59
+
60
+ | Sí es | No es |
61
+ | --- | --- |
62
+ | Un plugin para el slot `sidebar_content` de OpenCode | Una TUI independiente |
63
+ | Una vista local y de solo lectura sobre Engram | Un reemplazo de Engram |
64
+ | Un resumen de contexto, actividad y avance SDD | Un editor o gestor de memorias |
65
+ | Un cliente del HTTP local de Engram | Un servicio cloud o de sincronización |
66
+ | Un paquete con un adaptador MCP stdio opcional | Un producto centrado en MCP |
67
+
68
+ El sidebar es el producto principal. El comando MCP existe para integraciones
69
+ avanzadas y puede ignorarse por completo al usar el plugin de OpenCode.
70
+
71
+ ## Cómo funciona
72
+
73
+ 1. OpenCode carga el export raíz de `opencode-flema-engram-sidebar`.
74
+ 2. El plugin resuelve un candidato de proyecto y lo valida contra los proyectos
75
+ derivados de observaciones y sesiones recientes de Engram.
76
+ 3. Consulta en paralelo salud, proyectos y observaciones del proyecto.
77
+ 4. Ordena la actividad por actualización más reciente, detecta artefactos SDD y
78
+ reconoce bloqueos explícitos.
79
+ 5. Renderiza texto dentro del sidebar de la sesión visible y conserva datos útiles
80
+ como `STALE` si una actualización posterior queda incompleta.
81
+
82
+ Las llamadas usan exclusivamente `GET` contra el Engram local. El plugin no guarda,
83
+ edita ni elimina memorias.
84
+
85
+ ### Endpoints utilizados
86
+
87
+ | Propósito | Endpoint local |
88
+ | --- | --- |
89
+ | Salud | `GET /health` |
90
+ | Observaciones | `GET /observations/recent` |
91
+ | Sesiones para derivar proyectos | `GET /sessions/recent` |
92
+
93
+ El adaptador local usa un timeout de 5 segundos. Para mantener la vista acotada, el
94
+ sidebar solicita hasta 20 observaciones del proyecto; si la respuesta filtrada está
95
+ vacía o mezcla proyectos, usa una consulta sin filtro de hasta 100 registros y aplica
96
+ una coincidencia exacta local.
97
+
98
+ ## Configuración
99
+
100
+ ### Opciones soportadas por el plugin
101
+
102
+ Usá la forma `[plugin, options]` solamente cuando necesites opciones:
103
+
104
+ ```json
105
+ {
106
+ "$schema": "https://opencode.ai/tui.json",
107
+ "plugin": [
108
+ [
109
+ "opencode-flema-engram-sidebar",
110
+ {
111
+ "enabled": true,
112
+ "project": "mi-proyecto",
113
+ "pollInterval": 30000
114
+ }
115
+ ]
116
+ ]
117
+ }
118
+ ```
119
+
120
+ | Opción | Tipo | Comportamiento |
121
+ | --- | --- | --- |
122
+ | `enabled` | `boolean` | `false` evita que el plugin registre el sidebar. Por defecto está habilitado. |
123
+ | `project` | `string` | Nombre exacto de proyecto Engram. Tiene la prioridad más alta. |
124
+ | `pollInterval` | `number` | Intervalo automático en milisegundos; debe ser mayor que cero. Por defecto: `30000`. |
125
+
126
+ No hay una opción TUI para cambiar la URL o el timeout del HTTP local. El plugin
127
+ incluido usa `http://127.0.0.1:7437` y 5 segundos respectivamente.
128
+
129
+ ### Resolución del proyecto
130
+
131
+ La precedencia real es:
132
+
133
+ 1. `project` no vacío en el `tui.json` que declara el plugin;
134
+ 2. variable de entorno `ENGRAM_PROJECT` no vacía;
135
+ 3. nombre normalizado del directorio de trabajo y, como segundo candidato automático,
136
+ su ruta absoluta normalizada.
137
+
138
+ ```powershell
139
+ $env:ENGRAM_PROJECT = "mi-proyecto"
140
+ opencode .
141
+ ```
142
+
143
+ Cada candidato debe coincidir con un proyecto conocido por Engram. Se acepta una
144
+ coincidencia exacta o una única coincidencia sin distinguir mayúsculas. Un valor
145
+ explícito o de entorno inválido **no** cae silenciosamente al nombre del directorio.
146
+ Tampoco hay búsqueda difusa, recorrido de directorios padre, selector ni elección
147
+ automática del primer proyecto.
148
+
149
+ ### Tema
150
+
151
+ El render del plugin usa el color de texto del tema activo que entrega OpenCode y no
152
+ impone una paleta ni crea archivos de tema propios. Los estados también se distinguen
153
+ por etiquetas e iconos, no solamente por color.
154
+
155
+ ## Qué muestra el sidebar
156
+
157
+ ### Health
158
+
159
+ | Estado | Significado |
160
+ | --- | --- |
161
+ | `CHECKING` | La carga inicial todavía no terminó. |
162
+ | `OK` | El HTTP local responde y las observaciones requeridas se obtuvieron. |
163
+ | `STALE` | Hay datos utilizables o previos, pero una etapa de la actualización quedó incompleta. |
164
+ | `ERROR` | Hubo respuesta parcial o un fallo de salud sin una carga completa. |
165
+ | `OFFLINE` | No pudo obtenerse información central de Engram. |
166
+
167
+ Los fallos muestran la etapa o endpoint relevante. Un error queda contenido en el
168
+ sidebar para no derribar el host de OpenCode.
169
+
170
+ ### Proyecto y contexto detectado
171
+
172
+ Muestra el nombre validado del proyecto o `unresolved`. Cuando no puede resolverlo,
173
+ explica si falta configuración, el candidato no existe, es ambiguo o Engram estaba
174
+ offline durante la validación.
175
+
176
+ ### Observaciones indexadas
177
+
178
+ La línea `Indexed observations` refleja las observaciones del proyecto cargadas para
179
+ la vista actual, dentro del límite acotado del sidebar; no debe interpretarse como un
180
+ contador histórico total de toda la base. Si no hay registros, se muestra un estado
181
+ vacío explícito.
182
+
183
+ ### Avance SDD
184
+
185
+ Agrupa observaciones cuyo `topic_key` sigue `sdd/<cambio>/<artefacto>`. Reconoce las
186
+ fases `init`, `explore`, `proposal`, `spec`, `design`, `tasks`, `apply`, `verify` y
187
+ `archive`, incluidos los alias `apply-progress`, `verify-report` y `archive-report`.
188
+ Presenta el estado derivado y la secuencia de fases observadas. Si no hay cambios
189
+ activos o detectables, indica `No active SDD changes`.
190
+
191
+ ### Bloqueos
192
+
193
+ Lista títulos de observaciones reconocidas como bloqueos por tipo, título o frases
194
+ explícitas como `status: blocked`, `blocker:`, `blocked by`, `depends on` o
195
+ `waiting for`. No infiere bloqueos a partir de sentimiento o contexto ambiguo.
196
+
197
+ ### Actividad reciente
198
+
199
+ Muestra los títulos de las cinco observaciones más recientes del proyecto, ordenadas
200
+ por `updated_at` y luego por ID. Cuando no hay actividad, aparece un estado vacío.
201
+
202
+ ### Última memoria guardada
203
+
204
+ No existe un panel duplicado para “última memoria”: la observación actualizada más
205
+ reciente ocupa el primer lugar de **Recent Activity**. La vista muestra su título, no
206
+ el contenido completo. Así mantiene presente la referencia más nueva sin convertir
207
+ el sidebar en un explorador de memorias.
208
+
209
+ ### Refresh, carga y errores
210
+
211
+ - La primera carga se agenda una sola vez para el sidebar de la sesión visible.
212
+ - El polling automático usa `pollInterval` o 30 segundos.
213
+ - <kbd>Alt</kbd>+<kbd>R</kbd> vuelve a resolver el proyecto y repite todas las consultas.
214
+ - La tecla `r` sin modificadores queda libre para escribir en el prompt.
215
+ - `Refreshing…`, `Refreshed` y `Refresh incomplete` describen el resultado manual.
216
+ - Los datos anteriores se conservan como `STALE` cuando siguen siendo útiles.
217
+ - Un proyecto sin observaciones, sin cambios SDD o sin bloqueos tiene mensajes vacíos
218
+ propios; no se confunde con un error de conexión.
219
+
220
+ ## Ejemplos de uso
221
+
222
+ ### Detección automática desde el directorio
223
+
224
+ ```sh
225
+ cd mi-proyecto
226
+ opencode .
227
+ ```
228
+
229
+ Si Engram conoce `mi-proyecto`, el sidebar valida ese nombre y carga sus memorias.
230
+
231
+ ### Fijar un proyecto por workspace
232
+
233
+ ```json
234
+ {
235
+ "$schema": "https://opencode.ai/tui.json",
236
+ "plugin": [
237
+ ["opencode-flema-engram-sidebar", { "project": "backend-api" }]
238
+ ]
239
+ }
240
+ ```
241
+
242
+ Esto es útil cuando el nombre del directorio no coincide con el proyecto guardado en
243
+ Engram. El valor debe coincidir; una configuración incorrecta queda como `unresolved`.
244
+
245
+ ### Reducir la frecuencia de actualización
246
+
247
+ ```json
248
+ {
249
+ "$schema": "https://opencode.ai/tui.json",
250
+ "plugin": [
251
+ ["opencode-flema-engram-sidebar", { "pollInterval": 60000 }]
252
+ ]
253
+ }
254
+ ```
255
+
256
+ El sidebar actualizará cada 60 segundos y seguirá aceptando <kbd>Alt</kbd>+<kbd>R</kbd>.
257
+
258
+ ## Instalación desde el código fuente
259
+
260
+ ```sh
261
+ git clone https://github.com/oniricosistemas/flema-engram.git
262
+ cd flema-engram
263
+ npm install
264
+ ```
265
+
266
+ El archivo versionado `tui.example.json` es la referencia para desarrollo desde el
267
+ código fuente y apunta directamente a:
268
+
269
+ ```json
270
+ {
271
+ "$schema": "https://opencode.ai/tui.json",
272
+ "plugin": [["./src/sidebar/plugin.tsx", {}]]
273
+ }
274
+ ```
275
+
276
+ Creá tu copia local con `Copy-Item tui.example.json tui__.json` en PowerShell o
277
+ `cp tui.example.json tui__.json` en shells compatibles. `tui__.json` está ignorado
278
+ por Git a propósito: es la copia local para adaptar sin versionar rutas u opciones
279
+ específicas de tu máquina. Si tu entorno requiere el nombre `tui.json`, copiá allí el
280
+ contenido de `tui__.json` o fusioná su bloque `plugin` en tu configuración existente.
281
+
282
+ La ruta se resuelve desde el archivo que declara el plugin. En una configuración
283
+ global de Windows, reemplazá la ruta relativa de tu copia local por una URL absoluta:
284
+
285
+ ```json
286
+ {
287
+ "$schema": "https://opencode.ai/tui.json",
288
+ "plugin": [
289
+ ["file:///D:/general/mcp-flema-engram/src/sidebar/plugin.tsx", {}]
290
+ ]
291
+ }
292
+ ```
293
+
294
+ Preservá el resto de tus plugins y opciones al fusionar la configuración.
295
+
296
+ ## Solución de problemas
297
+
298
+ ### Engram aparece offline
299
+
300
+ - Confirmá que Engram escuche en `127.0.0.1:7437`.
301
+ - Probá `http://127.0.0.1:7437/health` desde la misma máquina.
302
+ - Revisá firewalls o proxies locales; el plugin no intenta conectarse a un servicio
303
+ cloud como alternativa.
304
+ - Corregí la causa y presioná <kbd>Alt</kbd>+<kbd>R</kbd>.
305
+
306
+ ### El proyecto no se detecta
307
+
308
+ - Verificá el nombre real guardado en Engram.
309
+ - Definí `project` en `tui.json` si el workspace tiene otro nombre.
310
+ - Usá `ENGRAM_PROJECT` solamente cuando deba aplicar al proceso completo.
311
+ - Recordá la precedencia: `project` explícito gana sobre `ENGRAM_PROJECT`.
312
+ - Un proyecto sin observaciones ni sesiones recientes puede no aparecer en la lista
313
+ derivada que se usa para validarlo.
314
+
315
+ ### Los datos parecen viejos
316
+
317
+ - Mirá si Health dice `STALE` y leé el detalle de etapa/endpoint.
318
+ - Esperá el próximo polling o usá <kbd>Alt</kbd>+<kbd>R</kbd>.
319
+ - Confirmá que la memoria pertenece exactamente al proyecto resuelto.
320
+ - El feed solo muestra cinco títulos y la consulta del sidebar está acotada a 20
321
+ observaciones.
322
+
323
+ ### El plugin no carga
324
+
325
+ - Cerrá y reiniciá OpenCode después de cambiar `tui.json`.
326
+ - Validá el JSON y la ruta del plugin.
327
+ - Confirmá Node.js 22+ y OpenCode 1.18.25+.
328
+ - Para npm, usá el nombre exacto `opencode-flema-engram-sidebar`.
329
+ - Para fuente local, ejecutá `npm install` y comprobá que la ruta termine en
330
+ `src/sidebar/plugin.tsx`.
331
+ - Revisá la salida de arranque de OpenCode. El plugin no crea archivos de log propios.
332
+
333
+ ### OpenCode no encuentra el export del paquete
334
+
335
+ - Confirmá que la versión instalada tiene un export raíz por defecto con `id` y `tui`.
336
+ - Ejecutá `npm view opencode-flema-engram-sidebar exports` para inspeccionar la
337
+ metadata publicada.
338
+ - Si trabajás sobre un tarball local, verificá que incluya
339
+ `dist/index.js`, `dist/sidebar/plugin.js` y sus declaraciones.
340
+ - Usá `opencode-flema-engram-sidebar` en la configuración. El subpath `/tui` queda
341
+ disponible para imports directos, pero OpenCode 1.18.25 puede no cachear ese spec de
342
+ npm de forma confiable.
343
+
344
+ ### Diagnóstico para contribuidores
345
+
346
+ ```sh
347
+ npm run typecheck
348
+ npm test
349
+ npm run verify:package
350
+ ```
351
+
352
+ `typecheck` valida TypeScript sin emitir archivos; `test` ejecuta Vitest una vez; y
353
+ `verify:package` inspecciona un `npm pack --dry-run` contra el contenido compilado
354
+ existente. No hay una opción de log JSONL ni un archivo de diagnóstico del sidebar.
355
+
356
+ ## Desarrollo y contribución
357
+
358
+ ```sh
359
+ npm ci
360
+ npm run typecheck
361
+ npm test
362
+ npm run build
363
+ npm run verify:package
364
+ ```
365
+
366
+ | Comando | Qué comprueba |
367
+ | --- | --- |
368
+ | `npm ci` | Instala exactamente el árbol de `package-lock.json`; es el usado por CI. |
369
+ | `npm install` | Instala dependencias y permite actualizar el lockfile en desarrollo. |
370
+ | `npm run typecheck` | Ejecuta `tsc --noEmit` con configuración estricta. |
371
+ | `npm test` | Ejecuta la suite unitaria y de integración con Vitest. |
372
+ | `npm run test:watch` | Mantiene Vitest activo durante el desarrollo. |
373
+ | `npm run test:coverage` | Genera cobertura mediante V8. |
374
+ | `npm run build` | Compila `src` a ESM, declaraciones y sourcemaps en `dist`. |
375
+ | `npm run verify:package` | Valida metadata y contenido del tarball sin publicarlo. Requiere un `dist` actualizado. |
376
+ | `npm run mcp` | Inicia desde fuente el adaptador MCP stdio opcional mediante `tsx`. |
377
+
378
+ La CI usa Node 22 y ejecuta, en este orden: typecheck, tests, build y verificación del
379
+ paquete. No publica artefactos ni necesita secretos. Antes de proponer un cambio:
380
+
381
+ - [ ] Mantené el sidebar como producto principal y el MCP como integración opcional.
382
+ - [ ] No introduzcas escrituras sobre Engram en el flujo de solo lectura.
383
+ - [ ] Agregá o actualizá pruebas para cambios de comportamiento.
384
+ - [ ] Ejecutá los cuatro checks de CI.
385
+ - [ ] No incluyas `src`, tests, OpenSpec, configs locales ni logs en el tarball.
386
+
387
+ ## Empaquetado y publicación
388
+
389
+ La lista `files` permite publicar `dist`, `README.md` y `LICENSE`; npm agrega además
390
+ la metadata obligatoria. El verificador exige, como mínimo:
391
+
392
+ - API raíz: `dist/index.js` y `dist/index.d.ts`;
393
+ - plugin: `dist/sidebar/plugin.js` y `dist/sidebar/plugin.d.ts`;
394
+ - CLI opcional: `dist/stdio.js`;
395
+ - README, licencia y `package.json`.
396
+
397
+ `prepublishOnly` ejecuta automáticamente:
398
+
399
+ ```sh
400
+ npm run typecheck && npm test && npm run build && npm run verify:package
401
+ ```
402
+
403
+ Para publicar necesitás permisos sobre
404
+ [`opencode-flema-engram-sidebar`](https://www.npmjs.com/package/opencode-flema-engram-sidebar),
405
+ una sesión npm válida y un `package.json` con versión todavía no publicada. Este
406
+ repositorio no configura publicación automática, tokens ni secretos.
407
+
408
+ ## Integración MCP opcional
409
+
410
+ > Sección avanzada: no es necesaria para usar el sidebar.
411
+
412
+ La instalación global expone el comando stdio:
413
+
414
+ ```sh
415
+ mcp-flema-engram
416
+ ```
417
+
418
+ Desde el repositorio puede iniciarse sin compilar con:
419
+
420
+ ```sh
421
+ npm run mcp
422
+ ```
423
+
424
+ Ejemplo de configuración local de OpenCode, equivalente a `opencode.example.json`:
425
+
426
+ ```json
427
+ {
428
+ "$schema": "https://opencode.ai/config.json",
429
+ "mcp": {
430
+ "engram": {
431
+ "type": "local",
432
+ "command": ["npm", "run", "mcp"],
433
+ "enabled": true
434
+ }
435
+ }
436
+ }
437
+ ```
438
+
439
+ El servidor ofrece herramientas y recursos MCP de lectura para salud, proyectos,
440
+ observaciones, sesiones y cambios SDD. Sigue usando el mismo HTTP local de Engram;
441
+ no agrega persistencia ni sincronización cloud.
442
+
443
+ ## Seguridad, privacidad y enfoque local-first
444
+
445
+ - Los datos de Engram permanecen en la máquina y el runtime consulta loopback.
446
+ - El sidebar no requiere credenciales, telemetría ni servicios cloud.
447
+ - No ejecuta operaciones de escritura sobre memorias.
448
+ - No crea logs propios con contenido de observaciones.
449
+ - El contenido de memorias puede ser sensible: protegé el acceso al proceso y puerto
450
+ local de Engram como protegerías cualquier herramienta de desarrollo.
451
+ - Las conexiones externas solo son necesarias para tareas ajenas al runtime local,
452
+ como instalar desde npm o abrir enlaces de documentación.
453
+
454
+ El repositorio contiene una clase experimental de adaptador cloud con operaciones no
455
+ implementadas. No forma parte del flujo del plugin ni constituye soporte cloud.
456
+
457
+ ## Roadmap y alcance diferido
458
+
459
+ Están explícitamente fuera del MVP actual:
460
+
461
+ - dashboard visual y acciones/atajos para abrirlo;
462
+ - conexión remota mediante `opencode attach`;
463
+ - selector manual de proyecto, navegación `j`/`k` y más atajos globales;
464
+ - configuración de URL/timeout desde `tui.json`;
465
+ - sincronización cloud y edición de memorias.
466
+
467
+ ## Licencia y enlaces
468
+
469
+ Distribuido bajo la [licencia MIT](./LICENSE).
470
+
471
+ - [Repositorio](https://github.com/oniricosistemas/flema-engram)
472
+ - [Issues](https://github.com/oniricosistemas/flema-engram/issues)
473
+ - [Paquete npm](https://www.npmjs.com/package/opencode-flema-engram-sidebar)
474
+ - [CI](https://github.com/oniricosistemas/flema-engram/actions/workflows/ci.yml)