Handoff: random words in TypeScript, /create and Dart, and what is left

The alphabet of each list and the strength of the words in Go (27a75ee),
the fix of TestGenerate (96d8992), TypeScript 0.5.0-dev with the lists
vendored and /create offering random words (012cd74 to 4057607), and Dart
(a770d4d to fcc7780). What is left depends on the author: the review of
the Spanish list or the corpus of Leipzig, and the EFF list.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
main
dev 9 hours ago
parent 44bb8332a7
commit 17b07f7c1a

@ -1,6 +1,6 @@
# Handoff DateKeys
*Estado al 7 de octubre de 2026 por la noche. Lo que pasó hasta aquí, sesión a sesión, está en [HANDOFF_historial.md](HANDOFF_historial.md).*
*Estado al 7 de octubre de 2026 por la tarde. Lo que pasó hasta aquí, sesión a sesión, está en [HANDOFF_historial.md](HANDOFF_historial.md).*
Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude.
@ -15,26 +15,33 @@ Sirve para retomar sin contexto previo, sea una persona o una sesión de Claude.
| Repo | Rama y commit | Tags | Qué es |
|---|---|---|---|
| `datekeys-go` | `v0.15` en `c49c67c`; `main` en `fe50885` | `spec-v0.15` en `fe50885`, y los de las versiones anteriores | Spec v0.15 aprobada, implementación de referencia, `testdata` compartido; `c49c67c` añade las palabras al azar |
| `App` (`datekeys-ts`) | `v0.10` y `main` en `7650418` | `v0.4.0` en `7650418`, `v0.3.0`, `v0.2.0`, `v0.1.0` | Librería TypeScript 0.4.0, de la spec 0.15, y páginas `/inspect` y `/create` |
| `datekeys-dart` | `v0.15` en `faa2c4c` | ninguno | Librería Dart completa, de la spec 0.15; las ramas `v0.11` a `v0.14` se quedan atrás |
| `datekeys-go` | `v0.15` en `96d8992`; `main` en `fe50885` | `spec-v0.15` en `fe50885`, y los de las versiones anteriores | Spec v0.15 aprobada, implementación de referencia, `testdata` compartido; `c49c67c` añade las palabras al azar, `27a75ee` el alfabeto de cada lista y la fuerza de las palabras, y `96d8992` arregla `TestGenerate` |
| `App` (`datekeys-ts`) | `v0.10` en `4057607`; `main` en `7650418` | `v0.4.0` en `7650418`, `v0.3.0`, `v0.2.0`, `v0.1.0` | Librería TypeScript `0.5.0-dev`, de la spec 0.15, y páginas `/inspect` y `/create`, con las palabras al azar; la última publicada es la 0.4.0 |
| `datekeys-dart` | `v0.15` en `fcc7780` | ninguno | Librería Dart completa, de la spec 0.15, con las palabras al azar; las ramas `v0.11` a `v0.14` se quedan atrás |
| `docs` | `main` | — | Este repo |
| `web` | `main` en `f2b8a38` | — | Landing de datekeys.com, sin remoto |
- **Spec:** la v0.15 está aprobada desde el 7-10, con SHA-256 `45105e693be4187af4dd30f4d254402612587b6427c746f5d29f07a541c1e3f3`. Es la recuperación a largo plazo: el objeto release, los archivos y servicios de caché que guardan todas las rondas, el release en la mano en el paso 9.c (opción B: no se compara con el reloj) y el anexo de recuperación del §79. No cambia ningún formato de `.dkc` ni de `.dkk`. No hay ningún borrador abierto. Las versiones aprobadas y sus SHA-256 están en `datekeys-go/spec/README.md`.
- **El fichero `.dkr` se descartó** antes de aprobar (7-10). El autor no lo había aprobado conscientemente, y no tiene sentido: al crear la cápsula no hay release que guardar, y cuando llega la ronda la cápsula ya se abre. El objeto release no tiene extensión propia; sale de un archivo o de un servicio de caché. El §76 lo registra.
- **Las tres implementaciones** coinciden en todos los vectores compartidos de `datekeys-go/testdata` en `fe50885`, 142 ficheros. Gates el 7-10:
- Go: `scripts/check.sh` entero en `fe50885`, con el anexo de recuperación abriendo fixtures sin código de DateKeys, y `scripts/fuzz.sh 20s` en `fe50885` con sus 27 objetivos, sin fallos;
- TypeScript: `npm run verify` en `7650418`, con 8 106 pruebas;
- Dart: `tool/check.sh` en `faa2c4c`, con 2 211 pruebas en la VM y 694 en Node.
- **Palabras al azar (7-10, después de cerrar la v0.15):** `datekeys-go` `c49c67c` añade `wordkey.Generate`, `List` y `CheckList`, y `datekeys encrypt -new-words FICHERO [-dic es] [-word-count 7]`. Es el SHOULD de §38.1 de ofrecer palabras generadas; no cambia ningún formato ni la derivación. `scripts/check.sh` pasa entero. La lista española, `wordkey/lists/es.txt` (7 776 palabras, SHA-256 `ff77b487…34fe`), es un **borrador sin revisar**, CC BY-SA 4.0, sacado de las frecuencias de subtítulos de FrequencyWords filtradas con el diccionario de LibreOffice; el método está en `wordkey/lists/README.md` y el script en [wordlists/build_es.py](wordlists/build_es.py).
- **Las tres implementaciones** coinciden en todos los vectores compartidos de `datekeys-go/testdata` en `fe50885`, 142 ficheros, los mismos que en `27a75ee`, de donde TypeScript y Dart copian hoy `testdata` y `wordlists`. Gates el 7-10:
- Go: `scripts/check.sh` entero en `fe50885`, con el anexo de recuperación abriendo fixtures sin código de DateKeys, y `scripts/fuzz.sh 20s` en `fe50885` con sus 27 objetivos, sin fallos; `scripts/check.sh` entero otra vez en `27a75ee` y en `96d8992`;
- TypeScript: `npm run verify` en `323d920`, con 8 119 pruebas, y `npm run check` y el build en `4057607`;
- Dart: `tool/check.sh` en `fcc7780`, con 2 230 pruebas en la VM y 705 en Node.
- **Palabras al azar (7-10, después de cerrar la v0.15):** es el SHOULD de §38.1 de ofrecer palabras generadas; no cambia ningún formato ni la derivación.
- Go: `c49c67c` añade `wordkey.Generate`, `List` y `CheckList`, y `datekeys encrypt -new-words FICHERO [-dic es] [-word-count 7]`. `27a75ee` hace que `CheckList(lang, words)` compruebe cada palabra contra el alfabeto de su idioma, que da el código y no la lista (para `es`, de la `a` a la `z`, `á`, `é`, `í`, `ó`, `ú`, `ü` y `ñ`, en minúscula y NFC): una letra cirílica que parece latina, una mayúscula, una cifra o el retorno de carro de un fichero CRLF dejarían la cápsula sin abrir. También añade `Bits`, la fuerza de lo sorteado, que `encrypt` muestra (90 bits para 7 de 7 776). `scripts/check.sh` pasa entero en los dos.
- TypeScript (`0.5.0-dev`, de `012cd74` a `4057607`): `scripts/sync-testdata.mjs` copia del mismo commit de Go `wordkey/lists` en `wordlists/`, con su `SOURCE.json` (`testdata` y `wordlists` en `27a75ee`, cuyo `testdata` es el del tag). `wordlist.ts` hace lo de Go, con sus textos: `readWordList` solo acepta una lista con el SHA-256 fijado para su idioma, `checkWordList`, `generateWords` y `wordBits`. `/create` ofrece palabras al azar por defecto tras una casilla, con su fuerza y «Otras palabras», y deja escribir las propias con el aviso de que son más débiles; `licenses.txt` lleva la licencia de la lista. `npm run verify` pasa con 8 119 pruebas, y el flujo se comprobó en el navegador sobre el build de producción.
- En `/create` apareció y se corrigió un fallo de la 0.4.0 (`4057607`): el efecto que comprueba las rutas se relanzaba sin fin (`effect_update_depth_exceeded`) en cuanto había un fichero, un comentario o un autor.
- `wordBits` de TypeScript usa `Math.log2`, que puede diferir del `math.Log2` de Go en el último bit; la página muestra los bits truncados, como la CLI, así que no se nota.
- Dart (`a770d4d` a `fcc7780`, de un agente Opus en un worktree, revisado contra Go): `tool/sync_testdata.dart` copia también `wordlists/`, y `lib/src/wordlist.dart` hace lo mismo que Go, exportado desde `lib/datekeys.dart`. Sus vectores (`test/vectors/wordlist_vectors.json`) los genera Go con `tool/wordlist_go_vectors.go`: `List`, `CheckList` en 83 listas, el veredicto de cada punto de código de los planos 0, 1 y 14, `Generate` en 51 casos con los mismos bytes que Go, y `Bits` bit a bit (porta el `math.Log2` de Go).
- El agente de Dart vio que `TestGenerate` de Go no probaba nada: su semilla solo daba dos índices, las dos llamadas acababan en `EOF` y el test comparaba dos resultados vacíos. Está arreglado en `96d8992`.
- La lista española, `wordkey/lists/es.txt` (7 776 palabras, SHA-256 `ff77b487…34fe`), es un **borrador sin revisar**, CC BY-SA 4.0, sacado de las frecuencias de subtítulos de FrequencyWords filtradas con el diccionario de LibreOffice; el método está en `wordkey/lists/README.md` y el script en [wordlists/build_es.py](wordlists/build_es.py). Cumple el alfabeto tal cual.
- **La revisión externa:** el paquete de [revision_externa/](revision_externa/NOTA_PARA_EL_AUTOR.md) está al día con la v0.15. Su nota dice qué decidió el autor y qué falta: elegir revisor, alcance y presupuesto, el NDA, los bundles y el envío.
---
## Qué queda
La recuperación a largo plazo quedó hecha con la v0.15 (7-10). **Para empezar mañana**, la recomendación de la sesión del 7-10: llevar las palabras al azar a TypeScript y a `/create` (Librerías, primer punto), y, si la web de Leipzig ha vuelto, rehacer la lista española con su corpus.
La recuperación a largo plazo quedó hecha con la v0.15, y las palabras al azar en las tres librerías y en `/create` (7-10). **Para empezar mañana**, lo que depende del autor en ellas: la revisión de la lista española por alguien que hable español, o rehacerla con el corpus de Leipzig si su web ha vuelto, y el permiso para descargar la lista inglesa de la EFF. Sin eso, lo siguiente es el segundo punto de «Librerías y clientes»: las recomendaciones de la v0.14 y la v0.15 al SDK oficial.
### Protocolo
@ -48,13 +55,12 @@ La recuperación a largo plazo quedó hecha con la v0.15 (7-10). **Para empezar
### Librerías y clientes
- **Las palabras al azar en el resto** (§38.1). Go ya las tiene (`c49c67c`). Falta:
- `Generate` en TypeScript y Dart, con la misma lista, su SHA-256 y `CheckList`; los dos copian la lista de `datekeys-go`, como el `testdata`;
- que `/create` ofrezca por defecto palabras generadas, con su aviso de que las elegidas son más débiles;
- la lista inglesa de la EFF (7 776 palabras, CC BY): descargarla necesita permiso del autor. Con ella, `-dic` pasa a `en` por defecto, como decidió el autor;
- la lista española definitiva: el autor espera a que vuelva la web de la Universidad de Leipzig (el 7-10 daba un error de servidor), cuyos corpus de unos 256 idiomas se descargan con CC BY. El script sirve cambiando la fuente de frecuencias. Su web bloquea a los agentes (Anubis): descarga el autor. Cada lista la revisa alguien que hable el idioma antes de fijar su hash;
- el servicio `words.datekeys.com`, cuando haya sitio propio: ver las decisiones.
- **la app no se fía de ninguna lista, tampoco de las de DateKeys** (el autor, 7-10: un empleado malicioso podría servir una lista con las mismas 6 palabras). `CheckList` ya rechaza menos de 2 048 palabras, repetidas tras normalizar, invisibles y cortas. Falta: un alfabeto por idioma (para el español, a–z con tildes, ü y ñ), porque una palabra con letras cirílicas que parecen latinas pasa y deja la cápsula sin abrir; la misma validación en TypeScript, Dart y la app; y que la app enseñe la fuerza calculada con la lista cargada. Quizá como regla del SDK en la versión siguiente del spec (§38.1). El riesgo de fondo es la app misma, que puede cambiar el generador: §59, builds reproducibles y releases firmadas.
- **Las palabras al azar** (§38.1) están en Go, TypeScript, `/create` y Dart, con el SHA-256 fijado de cada lista, el alfabeto de su idioma y la fuerza calculada con la lista cargada (ver «Estado»). Ninguna lista se da por buena, tampoco las de DateKeys (el autor, 7-10: un empleado malicioso podría servir una lista con las mismas 6 palabras). Falta:
- la lista inglesa de la EFF (7 776 palabras, CC BY): descargarla necesita permiso del autor. Con ella, `-dic` pasa a `en` por defecto, como decidió el autor, y hay que fijar el alfabeto de `en` en las tres librerías;
- la lista española definitiva: el autor espera a que vuelva la web de la Universidad de Leipzig (el 7-10 daba un error de servidor), cuyos corpus de unos 256 idiomas se descargan con CC BY. El script sirve cambiando la fuente de frecuencias. Su web bloquea a los agentes (Anubis): descarga el autor. Cada lista la revisa alguien que hable el idioma antes de fijar su hash. En el borrador hay nombres propios, préstamos y palabras malsonantes, como «claudia», «green», «sport» o «cojonudo»: que los mire quien la revise, con `descartes.txt` delante;
- los dados de quien desconfíe (decisión del 7-10): cinco tiradas, de 11111 a 66666, son una posición de la lista ordenada, porque 7 776 = 6⁵. No están en ninguna librería ni en `/create`;
- el servicio `words.datekeys.com`, cuando haya sitio propio: ver las decisiones;
- quizá el alfabeto por idioma como regla del SDK en la versión siguiente del spec (§38.1). El riesgo de fondo es la app misma, que puede cambiar el generador: §59, builds reproducibles y releases firmadas.
- **Las recomendaciones de la v0.14 y la v0.15 al SDK oficial**, que no aplican ni `/create` ni la CLI de Go:
- recomendar `time_and_key` para horizontes largos (§7.6);
- avisar del estado de un perfil (§71);
@ -124,8 +130,9 @@ La recuperación a largo plazo quedó hecha con la v0.15 (7-10). **Para empezar
- los heredocs de Bash rompen las barras invertidas, `\n` incluido;
- la herramienta Write quita los espacios de final de línea (los saltos de Markdown del §77) y convierte `\uXXXX` en caracteres;
- para cambios con barras o espacios exactos, un script de Python escrito con Write que use `chr(92)`, o la herramienta Edit;
- en Windows, `write_text` de Python escribe CRLF: abre con `newline=''` o escribe bytes, o `gofmt` y los hashes fallan;
- `cd` en Bash mueve el directorio de la sesión: usa `( cd … )` o `git -C`.
- **Vista previa de la página:** la configuración `inspector-dev-app` de `.claude/launch.json` arranca `App`, mientras la carpeta no se renombre. No pares el servidor mientras el autor lo usa. `vite.config.ts` prepara las dependencias que se cargan bajo demanda (`optimizeDeps.include`), para que la primera apertura no recargue la página.
- **Vista previa de la página:** la configuración `inspector-dev-app` de `.claude/launch.json` arranca `App`, mientras la carpeta no se renombre, e `inspector-preview-app` sirve su build de producción (`npm run build` antes, y reiniciarla tras cada build: si no, los chunks nuevos dan 404 y la página no se hidrata). No pares el servidor mientras el autor lo usa. `vite.config.ts` prepara las dependencias que se cargan bajo demanda (`optimizeDeps.include`), para que la primera apertura no recargue la página.
- **Fuzzing:** usa `FUZZ_PARALLEL=4`. Un «context deadline exceeded» sin entrada que falle es del motor de Go, no del código; se vuelve a pasar.
- **Disco:** C: está casi lleno con las cachés de Go y Dart; los temporales van en `G:\tmp`, y nunca se borra con comodines.

@ -11,8 +11,8 @@ Para retomar el trabajo, lee [HANDOFF.md](HANDOFF.md): el estado de cada repo, l
| Carpeta | Qué es | Remoto |
|---|---|---|
| `datekeys-go/` | Especificación del protocolo (`spec/`), CDDL, testdata compartido e implementación de referencia en Go: librería y CLI | `go/DateKeys` |
| `datekeys-ts/` | Implementación en TypeScript y páginas `/inspect` y `/create`; la carpeta sigue llamándose `App`. Versión `0.4.0` (tag `v0.4.0`), de la especificación 0.15 | `go/DateKeys-App` |
| `datekeys-dart/` | Librería Dart para la app Flutter, según [PLAN_dart.md](PLAN_dart.md). Rama `v0.15`: todas las etapas hechas, de la 0 a la 7, con `testdata/` en el tag `spec-v0.15`. La app Flutter está archivada desde el 6-10 | `go/dateKeys-dart`, desde el 6-10 |
| `datekeys-ts/` | Implementación en TypeScript y páginas `/inspect` y `/create`; la carpeta sigue llamándose `App`. Versión `0.4.0` (tag `v0.4.0`), de la especificación 0.15; en desarrollo, la `0.5.0`, con las palabras al azar | `go/DateKeys-App` |
| `datekeys-dart/` | Librería Dart para la app Flutter, según [PLAN_dart.md](PLAN_dart.md). Rama `v0.15`: todas las etapas hechas, de la 0 a la 7, y las palabras al azar, con `testdata/` y `wordlists/` en `27a75ee` de `datekeys-go`, cuyo `testdata` es el del tag `spec-v0.15`. La app Flutter está archivada desde el 6-10 | `go/dateKeys-dart`, desde el 6-10 |
| `web/` | Landing de datekeys.com, con `api/enquiry.php` | ninguno |
| `docs/` | Este repositorio | `go/datekeys-doc`, desde el 6-10 |
| `brand/` | Logos | no es un repo |
@ -30,7 +30,7 @@ Para retomar el trabajo, lee [HANDOFF.md](HANDOFF.md): el estado de cada repo, l
- **Spec:** en español, estilo RFC 2119. Todo cambio normativo se registra en §76 con su caso reproducible, y se actualiza el SHA-256 de `spec/README.md`. Una versión cerrada con tag no cambia: el cambio siguiente abre una versión nueva.
- **Idioma:** la spec y los documentos de este repo, en español. Código, comentarios y mensajes de commit, en inglés.
- **Commits** con `Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>`.
- **Testdata:** `datekeys-ts/testdata` solo se actualiza desde `datekeys-go`, con `scripts/sync-testdata.mjs`, y `datekeys-dart/testdata` con `tool/sync_testdata.dart`. En ninguno de los dos se generan fixtures. En `datekeys-ts`, una guarda falla si aparece un fichero de `testdata` que ningún test ejecuta.
- **Testdata:** `datekeys-ts/testdata` solo se actualiza desde `datekeys-go`, con `scripts/sync-testdata.mjs`, y `datekeys-dart/testdata` con `tool/sync_testdata.dart`. En ninguno de los dos se generan fixtures. Los dos scripts copian también, del mismo commit, las listas de palabras de `wordkey/lists` en `wordlists/`. En `datekeys-ts`, una guarda falla si aparece un fichero de `testdata` que ningún test ejecuta.
- **Textos de error:** si cambia un texto de error de Go en los pasos 1 a 8, el TypeScript lo sigue. Hoy coinciden byte a byte.
- **Precedencia de errores (§69.1):** trama; tipo y versión; perfil CBOR y CDDL; campos con código propio, en orden de clave. Entre objetos decide el orden de pasos de §63.
- **Subagentes** de Claude con `model: "opus"`.

Loading…
Cancel
Save

Powered by TurnKey Linux.