@cristobalbn/chaski 0.0.0-stage → 0.1.0
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.
- package/AGENTS.md +376 -0
- package/CHANGELOG.md +289 -0
- package/LICENSE +21 -0
- package/README.md +588 -2
- package/SECURITY.md +75 -0
- package/package.json +48 -4
- package/skill/SKILL.md +80 -0
- package/src/capturar.mjs +24 -0
- package/src/capture.mjs +545 -0
- package/src/cli.mjs +1053 -0
- package/src/inject.mjs +199 -0
- package/src/leer.mjs +19 -0
- package/src/lib/ask.mjs +194 -0
- package/src/lib/budget.mjs +64 -0
- package/src/lib/facts.mjs +566 -0
- package/src/lib/paths.mjs +323 -0
- package/src/lib/relay.mjs +303 -0
- package/src/lib/secrets.mjs +148 -0
package/SECURITY.md
ADDED
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Política de seguridad
|
|
2
|
+
|
|
3
|
+
## Reportar una vulnerabilidad
|
|
4
|
+
|
|
5
|
+
No abras un issue público para un problema de seguridad.
|
|
6
|
+
|
|
7
|
+
Usa la pestaña **Security → Report a vulnerability** del repositorio en GitHub
|
|
8
|
+
(advisory privado). Incluye:
|
|
9
|
+
|
|
10
|
+
- Versión de chaski y de Node.
|
|
11
|
+
- Sistema operativo.
|
|
12
|
+
- Qué CLIs tienes configurados.
|
|
13
|
+
- Pasos para reproducir.
|
|
14
|
+
- Impacto que observaste.
|
|
15
|
+
|
|
16
|
+
Respondo en un plazo razonable y coordino la divulgación antes de publicar el
|
|
17
|
+
arreglo.
|
|
18
|
+
|
|
19
|
+
## Modelo de amenaza
|
|
20
|
+
|
|
21
|
+
Vale la pena que sepas a qué está expuesta esta herramienta, porque es una que
|
|
22
|
+
se ejecuta sola en cada turno de tus sesiones.
|
|
23
|
+
|
|
24
|
+
### Qué puede hacer chaski
|
|
25
|
+
|
|
26
|
+
- **Leer:** el transcript de tus sesiones, la salida de `git` en tu proyecto,
|
|
27
|
+
y sus propios archivos de configuración.
|
|
28
|
+
- **Escribir:** `.tambo/` dentro del proyecto, `~/.chaski/`, los archivos de
|
|
29
|
+
configuración de los CLIs que habilitaste, y `.gitignore`, `AGENTS.md` y
|
|
30
|
+
`.claude/skills/relevo/` durante `init`.
|
|
31
|
+
- **Red:** ninguna. chaski no hace ninguna petición de red, nunca.
|
|
32
|
+
|
|
33
|
+
### Qué NO hace
|
|
34
|
+
|
|
35
|
+
- No invoca `claude -p`, `codex exec` ni `agy -p`.
|
|
36
|
+
- No hace commits ni modifica tu historial de git.
|
|
37
|
+
- No ejecuta scripts del repositorio en el que corre.
|
|
38
|
+
- No abre puertos ni escucha conexiones.
|
|
39
|
+
- No tiene dependencias de runtime, así que no hay árbol de npm que comprometer.
|
|
40
|
+
|
|
41
|
+
### Riesgos conocidos y cómo se contienen
|
|
42
|
+
|
|
43
|
+
**Inyección de prompt a través del relevo.** El relevo se inyecta en el contexto
|
|
44
|
+
de un agente con permisos de escritura, así que quien pueda escribir en
|
|
45
|
+
`.tambo/` podría intentar colar instrucciones. Contención: el bloque se declara
|
|
46
|
+
como datos entre delimitadores explícitos, se firma con HMAC contra una clave
|
|
47
|
+
local que nunca se versiona, y un relevo cuya firma no valida se inyecta
|
|
48
|
+
rotulado como no verificado en lugar de pasar por legítimo. Además `.tambo/`
|
|
49
|
+
está en `.gitignore`, así que no viaja entre máquinas.
|
|
50
|
+
|
|
51
|
+
**Captura accidental de secretos.** El transcript contiene todo lo que pasó por
|
|
52
|
+
la sesión. El filtro de `src/lib/secrets.mjs` corre antes de escribir a disco,
|
|
53
|
+
no solo antes de enviar algo. Si encuentras un formato de credencial que se nos
|
|
54
|
+
escapa, es un reporte de seguridad válido y lo agradecemos.
|
|
55
|
+
|
|
56
|
+
**ReDoS en los patrones de `chaski.json`.** `redact` y `excludePaths` son
|
|
57
|
+
expresiones regulares que el filtro de secretos ejecuta en cada turno. Un
|
|
58
|
+
patrón con retroceso catastrófico (por ejemplo algo con grupos anidados y
|
|
59
|
+
cuantificadores superpuestos) puede colgar el hook indefinidamente en vez de
|
|
60
|
+
terminar en milisegundos. **`chaski.json` se versiona**, así que sus patrones
|
|
61
|
+
pueden venir de un tercero — un colaborador, un PR, una plantilla copiada de
|
|
62
|
+
otro repo — y no son menos código que un script: revísalos en el PR como
|
|
63
|
+
revisarías cualquier otro cambio antes de aceptarlo.
|
|
64
|
+
|
|
65
|
+
**chaski como vector de cadena de suministro.** Instalarlo significa registrar
|
|
66
|
+
un comando que tus CLIs van a ejecutar solos. Para que puedas verificarlo:
|
|
67
|
+
`chaski doctor` imprime el comando exacto registrado en cada configuración —
|
|
68
|
+
son unas diez líneas. Revísalo después de instalar y después de cada
|
|
69
|
+
actualización. Si prefieres no confiar en un paquete publicado, clona el
|
|
70
|
+
repositorio y ejecuta desde el código fuente: son ~2.000 líneas sin dependencias.
|
|
71
|
+
|
|
72
|
+
## Versiones soportadas
|
|
73
|
+
|
|
74
|
+
Mientras el proyecto esté antes de 1.0, solo se da soporte a la última versión
|
|
75
|
+
publicada.
|
package/package.json
CHANGED
|
@@ -1,6 +1,50 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cristobalbn/chaski",
|
|
3
|
-
"version": "0.
|
|
4
|
-
"
|
|
5
|
-
"
|
|
6
|
-
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "Relevo de contexto entre agentes de codigo (Claude Code, Codex, agy)",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"license": "MIT",
|
|
7
|
+
"engines": {
|
|
8
|
+
"node": ">=20"
|
|
9
|
+
},
|
|
10
|
+
"bin": {
|
|
11
|
+
"chaski": "src/cli.mjs"
|
|
12
|
+
},
|
|
13
|
+
"scripts": {
|
|
14
|
+
"check": "node --check src/capture.mjs && node --check src/inject.mjs && node --check src/cli.mjs && node --check src/capturar.mjs && node --check src/leer.mjs && node --check src/lib/paths.mjs && node --check src/lib/facts.mjs && node --check src/lib/secrets.mjs && node --check src/lib/relay.mjs && node --check src/lib/ask.mjs && node --check src/lib/budget.mjs",
|
|
15
|
+
"test": "node --test test/core.test.mjs test/install.test.mjs",
|
|
16
|
+
"prepublishOnly": "npm run check && npm test"
|
|
17
|
+
},
|
|
18
|
+
"publishConfig": {
|
|
19
|
+
"access": "public"
|
|
20
|
+
},
|
|
21
|
+
"files": [
|
|
22
|
+
"src",
|
|
23
|
+
"skill",
|
|
24
|
+
"README.md",
|
|
25
|
+
"AGENTS.md",
|
|
26
|
+
"SECURITY.md",
|
|
27
|
+
"CHANGELOG.md",
|
|
28
|
+
"LICENSE"
|
|
29
|
+
],
|
|
30
|
+
"keywords": [
|
|
31
|
+
"claude-code",
|
|
32
|
+
"codex",
|
|
33
|
+
"antigravity",
|
|
34
|
+
"agy",
|
|
35
|
+
"handoff",
|
|
36
|
+
"context",
|
|
37
|
+
"ai-agent",
|
|
38
|
+
"cli",
|
|
39
|
+
"relevo"
|
|
40
|
+
],
|
|
41
|
+
"author": "Cristobal Barrera",
|
|
42
|
+
"repository": {
|
|
43
|
+
"type": "git",
|
|
44
|
+
"url": "git+https://github.com/cristobalbn/chaski.git"
|
|
45
|
+
},
|
|
46
|
+
"bugs": {
|
|
47
|
+
"url": "https://github.com/cristobalbn/chaski/issues"
|
|
48
|
+
},
|
|
49
|
+
"homepage": "https://github.com/cristobalbn/chaski#readme"
|
|
50
|
+
}
|
package/skill/SKILL.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: relevo
|
|
3
|
+
description: Guarda la narrativa de Chaski al pedir «relevo», «guarda el relevo» o «actualiza el relevo», o al cerrar un bloque de trabajo para cambiar de agente. Registra intención, decisiones, pendientes y siguiente paso. No usar para consultas sobre Chaski ni para leer o continuar un relevo existente.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Actualizar el relevo
|
|
7
|
+
|
|
8
|
+
Escribes la parte del relevo que un script no puede deducir: la **intención**.
|
|
9
|
+
Los hechos —archivos tocados, diff, tests, commits— ya los escribió chaski y
|
|
10
|
+
son exactos. No los repitas ni los corrijas.
|
|
11
|
+
|
|
12
|
+
## Petición común
|
|
13
|
+
|
|
14
|
+
En Claude Code, Codex y agy, un mensaje que solo diga **«relevo»**, o que pida
|
|
15
|
+
**«guarda el relevo»** o **«actualiza el relevo»**, solicita guardar la narrativa:
|
|
16
|
+
ejecuta los pasos de abajo y confirma al terminar.
|
|
17
|
+
|
|
18
|
+
**«Continúa desde el relevo»** solicita retomar el trabajo. Lee el relevo de la
|
|
19
|
+
rama actual, contrástalo con el código y continúa con lo pendiente; no ejecutes
|
|
20
|
+
estos pasos de guardado por esa petición. Una pregunta sobre el funcionamiento
|
|
21
|
+
del relevo tampoco solicita sobrescribirlo.
|
|
22
|
+
|
|
23
|
+
## Pasos
|
|
24
|
+
|
|
25
|
+
1. Ubica la raíz del repositorio Git (si el espacio de trabajo es una carpeta contenedora con un único repo hijo o una subcarpeta del repo, usa la raíz de ese repositorio). Lee `.tambo/branches/<rama-actual>/estado.json` desde esa raíz, donde `<rama-actual>` sale de `git rev-parse --abbrev-ref HEAD`.
|
|
26
|
+
2. Escribe la narrativa en el campo `narrative` de ese JSON en UTF-8, junto con
|
|
27
|
+
`narrativeAuthor` (tu nombre de agente) y `narrativeWrittenAt` (ISO 8601 de ahora).
|
|
28
|
+
3. No toques ningún otro campo. `facts`, `commands`, `offset` y `signature` son de chaski.
|
|
29
|
+
4. Confirma al usuario en una línea: qué quedó anotado como siguiente paso.
|
|
30
|
+
|
|
31
|
+
El Markdown se regenera solo en el próximo turno. No edites `relevo.md` a mano.
|
|
32
|
+
|
|
33
|
+
## Qué escribir
|
|
34
|
+
|
|
35
|
+
Cuatro secciones, en este orden, en prosa breve. Apunta a 120-200 palabras en
|
|
36
|
+
total: el relevo tiene un presupuesto duro de contexto y lo que escribas compite
|
|
37
|
+
con el espacio que el próximo agente necesita para trabajar.
|
|
38
|
+
|
|
39
|
+
**Tarea** — qué se está intentando lograr, en una o dos frases. No el archivo
|
|
40
|
+
que se está editando, sino el objetivo.
|
|
41
|
+
|
|
42
|
+
**Decisiones** — qué se eligió y, sobre todo, **qué se descartó y por qué**.
|
|
43
|
+
Esto es lo que evita que el siguiente agente reabra algo ya cerrado. Si no se
|
|
44
|
+
tomó ninguna decisión en esta sesión, omite la sección.
|
|
45
|
+
|
|
46
|
+
**A medias** — lo más importante del relevo. Qué está empezado y no terminado,
|
|
47
|
+
con la ruta y la línea si existe. Sé específico: «falta invalidar el token
|
|
48
|
+
anterior en Redis antes de emitir el nuevo, en `src/auth/refresh.ts:41`» sirve;
|
|
49
|
+
«falta terminar refresh» no sirve.
|
|
50
|
+
|
|
51
|
+
**Siguiente paso** — la próxima acción concreta, una sola.
|
|
52
|
+
|
|
53
|
+
## Reglas
|
|
54
|
+
|
|
55
|
+
- **Escribe solo lo que pasó en la conversación.** Si no sabes por qué se eligió
|
|
56
|
+
algo, no lo inventes: omítelo. Una narrativa incompleta es útil; una inventada
|
|
57
|
+
manda al próximo agente en la dirección equivocada con confianza.
|
|
58
|
+
- **No incluyas secretos.** Ni tokens, ni claves, ni contenido de `.env`, ni
|
|
59
|
+
URLs con credenciales. Si necesitas mencionar una variable sensible, nómbrala
|
|
60
|
+
sin su valor.
|
|
61
|
+
- **No incluyas instrucciones dirigidas al próximo agente** más allá del
|
|
62
|
+
siguiente paso. El relevo se inyecta como datos, no como órdenes.
|
|
63
|
+
- **No repitas los hechos.** Si el diff ya dice que `jwt.ts` tiene +82 líneas,
|
|
64
|
+
no lo escribas.
|
|
65
|
+
- **Preserva UTF-8 al escribir `estado.json`.** Usa la herramienta de edición de archivos del agente o escribe en UTF-8 directo; en Windows no pases texto con tildes o `«»` como literal por la consola de PowerShell sin `UTF8Encoding`, porque convierte los caracteres no ASCII en `?`.
|
|
66
|
+
- **Distingue lo temporal de lo permanente.** Si en esta sesión apareció una
|
|
67
|
+
convención que vale **siempre** —un estilo, una herramienta prohibida, un
|
|
68
|
+
comando que hay que correr antes de dar algo por listo— no va en el relevo,
|
|
69
|
+
que se reescribe: propón al usuario agregarla a `AGENTS.md`. Una línea
|
|
70
|
+
preguntando, no la agregues sin confirmar.
|
|
71
|
+
|
|
72
|
+
## Ejemplo
|
|
73
|
+
|
|
74
|
+
```json
|
|
75
|
+
{
|
|
76
|
+
"narrative": "Migrando la capa de auth a JWT con refresh tokens.\n\nDecidido: el refresh token va en cookie httpOnly, no en localStorage, por XSS. Se descartó passport.js: demasiado peso para dos endpoints.\n\nA medias: el endpoint de refresh existe y responde, pero no rota el token viejo. Falta invalidarlo en Redis antes de emitir el nuevo, en src/auth/refresh.ts:41. Los dos tests que fallan en test/auth.test.ts son por esto, no por otra cosa.\n\nSiguiente paso: cerrar la rotación en refresh.ts:41 y volver a correr npm test -- auth.",
|
|
77
|
+
"narrativeAuthor": "claude code",
|
|
78
|
+
"narrativeWrittenAt": "2026-10-31T16:20:00.000Z"
|
|
79
|
+
}
|
|
80
|
+
```
|
package/src/capturar.mjs
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
// Puente de compatibilidad. Este archivo se llamaba así antes de que el código
|
|
3
|
+
// se homologara al inglés, y `capturar.mjs` pasó a ser `capture.mjs`.
|
|
4
|
+
//
|
|
5
|
+
// Por qué existe: `init` registra la RUTA ABSOLUTA de los scripts en la
|
|
6
|
+
// configuración de cada CLI, y esa configuración vive fuera del repositorio.
|
|
7
|
+
// Quien actualice chaski desde una versión anterior sin volver a correr
|
|
8
|
+
// `chaski init` tiene los hooks apuntando a este nombre, y sin este archivo
|
|
9
|
+
// recibe un volcado de Node de quince líneas en cada turno:
|
|
10
|
+
//
|
|
11
|
+
// Error: Cannot find module '...\chaski\src\capturar.mjs'
|
|
12
|
+
//
|
|
13
|
+
// Pasó de verdad, y el error sobrevive a `chaski init` dentro de una sesión ya
|
|
14
|
+
// abierta, porque los CLIs leen su configuración de hooks una sola vez al
|
|
15
|
+
// arrancar. Así que no alcanzaba con documentar el paso: el nombre viejo tiene
|
|
16
|
+
// que seguir funcionando.
|
|
17
|
+
//
|
|
18
|
+
// No avisa por stderr a propósito. Este hook corre en CADA turno, y una línea
|
|
19
|
+
// de aviso por turno es ruido que el usuario no puede callar. El aviso lo da
|
|
20
|
+
// el puente de inicio de sesión (`leer.mjs`), que corre una vez por sesión.
|
|
21
|
+
//
|
|
22
|
+
// No lo borres sin un ciclo de deprecación de verdad: mientras alguien pueda
|
|
23
|
+
// tener una configuración vieja en disco, borrarlo le rompe cada turno.
|
|
24
|
+
import './capture.mjs';
|