feat(nouser): Phase D — proveedor Nous mock + cliente remoto
Cierra el patrón "Nous como módulo aparte intercambiable": el contrato
del proveedor de embeddings vive en su crate, el mock determinístico
implementa ese contrato sirviéndolo por Unix socket, y nouser-core
sabe consumirlo remotamente. El switch mock↔real (futuro) será vía
priority_contexts en el broker.
Crates nuevos:
- crates/modules/nouser/nous: contrato compartido.
- EmbedRequest { kind: { EmbedFile | EmbedText | Ping }, payload }.
- EmbedFilePayload (path, ext, size, mtime), EmbedTextPayload.
- EmbedResponse (embedding, model, elapsed_ms), PingResponse,
ErrorResponse.
- Wire: line-delimited JSON sobre Unix socket, single-shot.
- Constants FLOW_EMBED_REQUEST, FLOW_EMBED_RESULT, FLOW_TYPE_NAME.
- transport::default_socket_path con env NOUSER_NOUS_SOCKET.
- crates/modules/nouser/nous-mock: bin nouser-nous-mock.
- Sidecarea a brahman-init con Card kind=Ente declarando los flows
embed-request/embed-result + priority_contexts.test = +1.
- Bind del socket Nous + accept loop tokio.
- EmbedFile delega a nouser_core::embed::embed (Phase C).
- Modelo: "mock-pseudo-32d".
Cambios:
- nouser-core: dep nueva nouser-nous. Subcomando attract --remote
abre un UnixStream blocking, envía EmbedRequest, lee response.
Imprime "embed: local|remote" para ver cuál ruta corrió.
Bug encontrado y corregido:
- ContextBias tenía #[serde(skip_serializing_if = ...)] en sus campos.
Postcard NO soporta skip-condicional en formatos no self-describing:
el serializer omitía bytes que el deserializer esperaba, rompiendo
la wire de cualquier Card con priority_contexts poblada.
Síntoma: "postcard decode: Hit the end of buffer" en el server,
"early eof" en el cliente.
- Fix: removidos los skip_serializing_if de ContextBias. JSON pretty
ahora emite {"pin_to": null, "priority_offset": 0} pero el wire
funciona. Trade-off aceptado.
- Test wirecard_postcard_with_priority_contexts en brahman-card que
ejercita el roundtrip postcard con biases poblados.
Validación end-to-end:
$ ente-zero & nouser-nous-mock & nouser daemon crates/core
$ brahman-status
Sessions (7):
[ente] nouser.nous_mock flows: embed-request, embed-result
[ente] brahman.nouser_engine
[data] src summary: 6 archivos en crates/core/brahman-handshake/src
[data] graph summary: 7 archivos en crates/core/ente-zero/src/graph
...
$ nouser attract --remote crates/core <archivo>.rs
embed: remote
🧲 0.9058 src ...
(mock log: embed_file path=...)
Tests: 75. cargo check --workspace: 0 errores, 0 warnings.
Próximo natural: Phase D-2 — real-nous con ONNX/Llama text-embedding.
Declara la misma Card con priority_contexts.prod = +1 y el swap es
transparente para el consumer.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -6,6 +6,80 @@ ratio/diff ver `git show <sha>`.
|
||||
|
||||
## 2026-05-08
|
||||
|
||||
### feat(nouser): Phase D — proveedor Nous mock + cliente remoto
|
||||
Cierra el patrón "Nous como módulo aparte intercambiable": el contrato
|
||||
del proveedor de embeddings vive en su crate, el mock determinístico
|
||||
implementa ese contrato sirviéndolo por Unix socket, y `nouser-core`
|
||||
sabe consumirlo remotamente. El switch entre mock y real (futuro) se
|
||||
hará vía priority_contexts en el broker.
|
||||
|
||||
Crates nuevos:
|
||||
|
||||
- `crates/modules/nouser/nous`: contrato compartido. Tipos
|
||||
`EmbedRequest`, `RequestKind { EmbedFile, EmbedText, Ping }`,
|
||||
`EmbedFilePayload`, `EmbedTextPayload`, `EmbedResponse`,
|
||||
`PingResponse`, `ErrorResponse`. Wire format: line-delimited JSON
|
||||
por Unix socket, single-shot per conexión. Constants para los nombres
|
||||
de flow (`embed-request`/`embed-result`) y el tipo (`json`). Helper
|
||||
`transport::default_socket_path()` con env var
|
||||
`NOUSER_NOUS_SOCKET`.
|
||||
- `crates/modules/nouser/nous-mock`: bin `nouser-nous-mock`. Sidecarea
|
||||
a brahman-init con Card kind=Ente declarando los flows
|
||||
`embed-request:json`/`embed-result:json` y un
|
||||
`priority_contexts.test = { priority_offset: +1 }` (gana sobre
|
||||
cualquier real-nous en contexto test). Bind del socket Nous, accept
|
||||
loop, despacha por `RequestKind`. EmbedFile usa
|
||||
`nouser_core::embed::embed` (los pseudo-embeddings de Phase C).
|
||||
Modelo: `mock-pseudo-32d`.
|
||||
|
||||
Cambios:
|
||||
|
||||
- `nouser-core`: dep nueva `nouser-nous`. Subcomando `attract` ahora
|
||||
acepta `--remote` que abre un socket UnixStream blocking, envía un
|
||||
`EmbedRequest` y lee la response. Imprime `embed: local|remote`
|
||||
para que se vea cuál ruta corrió.
|
||||
|
||||
Validación end-to-end (un solo terminal, varios procesos):
|
||||
|
||||
$ ente-zero &
|
||||
$ nouser-nous-mock &
|
||||
$ NOUSER_MIN_FILES=5 nouser daemon crates/core &
|
||||
$ brahman-status
|
||||
|
||||
Sessions (7):
|
||||
[ente] nouser.nous_mock flows: embed-request, embed-result
|
||||
[ente] brahman.nouser_engine
|
||||
[data] src summary: 6 archivos en crates/core/brahman-handshake/src
|
||||
[data] graph summary: 7 archivos en crates/core/ente-zero/src/graph
|
||||
...
|
||||
|
||||
$ nouser attract --remote crates/core <archivo.rs>
|
||||
embed: remote
|
||||
🧲 0.9058 src ...
|
||||
|
||||
Mock log: "embed_file path=crates/modules/nouser/core/src/embed.rs"
|
||||
|
||||
Bug encontrado y corregido en el camino:
|
||||
- `ContextBias` tenía `#[serde(skip_serializing_if = ...)]` en sus
|
||||
campos. Postcard NO soporta skip-condicional (formato no
|
||||
self-describing): el serializer omitía bytes que el deserializer
|
||||
esperaba, rompiendo la wire de cualquier Card con
|
||||
`priority_contexts` poblada.
|
||||
- Fix: removidos los `skip_serializing_if` de `ContextBias`. JSON
|
||||
pretty ahora emite `{"pin_to": null, "priority_offset": 0}` en lugar
|
||||
de objeto vacío. Trade-off aceptado por compatibilidad de wire.
|
||||
- Test nuevo en brahman-card: `wirecard_postcard_with_priority_contexts`
|
||||
que ejercita el roundtrip completo postcard.
|
||||
|
||||
Tests acumulados: 75 (card 12 +1 nuevo, broker 15, handshake 9,
|
||||
card-wit 4, admin 0, nouser-card 7, nouser-core 20, nouser-nous 2).
|
||||
cargo check --workspace: 0 errores, 0 warnings.
|
||||
|
||||
Próximo natural: Phase D-2 — `real-nous` con un modelo ONNX/Llama de
|
||||
text-embedding. La infraestructura ya está lista: declara la misma
|
||||
Card con `priority_contexts.prod = { priority_offset: +1 }` y el
|
||||
swap es transparente para el consumer.
|
||||
|
||||
### feat(nouser): Phase C — pseudo-embeddings + atracción por centroide
|
||||
El "imán semántico" matemático del diseño Kairos, sin LLM. Cada
|
||||
archivo se proyecta a un vector 32-d derivado de sus metadatos; cada
|
||||
|
||||
Reference in New Issue
Block a user