¿Qué hace begin?
Oriéntate en un código base en una sola pasada, a partir de evidencia, sin deambular.
El fallo que esto busca prevenir: un agente abre un repositorio, hace grep de una palabra que suena plausible, lee tres archivos que casualmente coinciden, y reporta un resumen de arquitectura seguro que describe el 4% del sistema. begin reemplaza la adivinanza sobre dónde está el código importante con medición de dónde está, y luego lee solo lo que la medición señaló.
El contrato
- Nada se recuerda. Todo se deriva. La importancia proviene de un PageRank sobre el grafo de importaciones real; la complejidad, de puntos de decisión contados; el enfoque, de git y el registro de PRs. Si no puedes señalar un archivo:línea o un commit, no lo digas.
- Cada afirmación está anclada. Cada declaración en
BEGIN.mdcitaruta:línea, un commit, o un número de PR. Una frase sin anclaje es una suposición, y las suposiciones son lo que esta habilidad existe para eliminar. - Dos capas, una de ellas viva.
.begin/es salida de máquina, regenerada y autoignorada.BEGIN.mdes prosa que escribiste, comprometiste y sellaste con el commit del que se derivó. Un hook post-commit re-deriva la capa de máquina e informa qué secciones de prosa el código ha superado. Nada en esta habilidad edita jamás un archivo rastreado —.begin/lleva su propio.gitignore, por lo que el del repositorio no se toca. - Los proxies se nombran como proxies.
complexityProxyes un conteo de puntos de decisión, no un análisis. El anidamiento se mide a partir de la indentación. Dilo; no conviertas un proxy en un hecho. - Una medición degradada se anuncia, nunca se usa en silencio. El escaneo imprime un bloque
[!WARNING]para un clon superficial, una ventana de actividad muerta, archivos omitidos, un lenguaje que no puede analizar en absoluto, o una resolución fallida para uno que sí puede. Lee ese bloque antes de la tabla y repite lo que dice en BEGIN.md. Una clasificación construida sobre un grafo roto se ve exactamente igual que una buena — ese es el peligro total.
Ejecútalo
S=~/.claude/skills/begin/scripts
bash $S/recon.sh # quién/qué/cuándo: PRs, tus commits, ediciones en vivo, documentación
node $S/scan.mjs # estructura: grafo de importaciones, puntos calientes, superficie->motor
Ambos escriben en .begin/ e imprimen un resumen. Ejecútalos desde cualquier lugar del repositorio — el escaneo se ancla a la raíz del repositorio. recon.sh se degrada limpiamente sin gh, sin red y sin remoto, pero requiere node (la redacción es obligatoria). Mediciones en caché caliente: 259 archivos 0.24s · 3,384 archivos 1.9s · 2,809 archivos 1.9s · 1,819 archivos 2.5s · 1,397 archivos 3.5s. El conteo de archivos no predice el tiempo; el contenido sí.
Indicadores que vale la pena conocer:
--since "90 days ago"— ventana de actividad (ambos scripts usan 90 por defecto).--top 40— cuántos puntos calientes imprimir (por defecto 25).--author "..."— una expresión regular. Rara vez lo necesitas: por defecto usauser.namedel repositorio, yrecon.shrecurre al autor más activo del repositorio y lo dice cuando no tienes commits allí. Ese es el caso normal en un repositorio que acabas de clonar.--exclude 'examples/**,site/**'— mantiene los árboles de proveedores y los sitios de documentación fuera del conteo de superficie. Los patrones están anclados en ambos extremos, y el número de archivos eliminados se imprime, porque una exclusión silenciosa aparece más tarde como un borde faltante.--root DIR— escanea un repositorio diferente.
El orden de las operaciones — síguelo exactamente
Hacer esto fuera de orden es cómo un agente termina leyendo los archivos equivocados.
1. Reconocimiento antes que estructura
Ejecuta recon.sh primero. Responde "¿qué ha estado haciendo esta persona?" — ediciones sin comprometer, commits de rama vs. main, los últimos ~20 PRs fusionados con sus cuerpos, y qué cambió cada uno. Ese es el enfoque previo. Lee .begin/recon.md completamente; es breve.
El diff sin comprometer suele ser la información más útil del repositorio — es la pregunta que el usuario tiene actualmente. Recon señala tres cosas al respecto: cuando el árbol está limpio lo dice explícitamente (en lugar de omitir la sección y dejarte buscando), cuando el diff es solo archivos de bloqueo y salida de compilación te dice que no gastes tu primera lectura allí, y cuando tu checkout está detrás de origin dice por cuántos commits y nombra los archivos de PRs recientes que no están en tu árbol.
Ese último punto es una condición previa, no una advertencia. Si recon informa que estás detrás, el paso 3.2 más abajo no es seguro: las listas de archivos de PR describen código que no tienes. O haz git pull primero o salta el paso de lectura de PRs y di en BEGIN.md que lo hiciste.
2. Estructura en segundo lugar
Ejecuta scan.mjs y lee .begin/scan.md, comenzando por cualquier bloque [!WARNING]. Entonces tienes, medido en lugar de asumido:
- Superficies — cada lugar donde un humano o un llamador toca realmente el sistema, agrupado por tipo (
web-page,ui-component,http-route,cli-command,mcp-tool,worker,public-api,migration, másexample,configytestque son superficies pero no producto). Este es el extremo de UI del mapa. - Puntos calientes — clasificados, con una columna
whyque nombra el término que puso cada archivo allí:depended-on,churn,complexorecent. Un archivo en la cima porchurnes un animal diferente de uno en la cima pordepended-on; la columna te dice qué conversación tener. - Rutas superficie → motor — la cadena de importación literal desde un endpoint o un botón hasta la parte difícil, calculada por BFS. Una ruta que cruza un borde perezoso
await import()está etiquetada como tal, porque se resuelve en tiempo de llamada en lugar de tiempo de carga. - Grupos de ciclos de importación — conjuntos fuertemente conectados sobre bordes de valor estático, con un bucle dirigido real recorrido. Los bordes de solo tipo y perezosos (
await import(...)) están excluidos, porque ninguno forma un ciclo de inicialización real. - Archivos inalcanzables — código muerto o una superficie que las heurísticas pasaron por alto. Decide cuál y dilo.
2.5. Lee el mapa que el repositorio ya escribió para ti
Antes de abrir cualquier punto caliente, verifica si hay AGENTS.md, CLAUDE.md, ARCHITECTURE.md o READMEs por directorio — recon.md los enumera. Un repositorio que incluye un mapa de subsistemas te entrega en treinta líneas lo que el escaneo infiere en dos segundos y la prosa tarda una hora en reconstruir. Lee esos primero, luego usa el escaneo para verificarlos: la documentación se vuelve obsoleta, el grafo no.
3. Lee solo lo que la medición señaló
Lee, en este orden, y detente:
- El diff sin comprometer y los commits de la rama actual (lo que están haciendo ahora).
- Los archivos cambiados por los 3–5 PRs fusionados más recientes (lo que acaban de decidir).
- Los 8–15 puntos calientes principales de
scan.md. - Para cada uno de los 3 principales, recorre su superficie
reachedViahacia adentro, para que puedas indicar la ruta completa desde la acción del usuario hasta el motor. README, la documentación orientada al agente del paso 2.5, y cualquier documento cuyo encabezado coincida con un punto caliente.
No abras archivos fuera de este conjunto en una primera pasada. Si algo parece faltar, eso es un hallazgo para reportar, no una licencia para navegar.
4. Verifica antes de escribir
La tabla es un conjunto de pistas, no una conclusión. Antes de que cada afirmación entre en BEGIN.md:
- Abre el archivo y confirma que la línea que estás a punto de citar dice lo que crees.
- Para una ruta superficie → motor, confirma que la importación realmente existe en el código fuente.
- Para cualquier cosa sobre comportamiento, prefiere un test que lo demuestre sobre una función que parezca hacerlo.
greplas rutas calientes en busca de fallos tragados —catch {},.catch(() => {}),as any,as never, retornos descartados. Los errores viven donde se tiran excepciones, y estos son el elemento de mayor valor que puedes devolver desde el primer día.- Dedica al menos una pasada a intentar falsificar tu afirmación principal, no a confirmarla. Las frases más valiosas en un buen BEGIN.md son las que contradicen el escaneo.
Si el escaneo se equivoca en algo, dílo en BEGIN.md y corrígelo. Un archivo que el grafo considera muerto pero que en realidad se alcanza a través de HTTP o una cola es lo más útil que puedes registrar, porque nadie más lo encontrará de nuevo. Declara dichos puntos de entrada en .begin/surfaces.txt (una ruta por línea, opcionalmente ruta<TAB>tipo) y la próxima ejecución los tratará como superficies.
5. Escribe BEGIN.md
Usa references/BEGIN-template.md, y lee references/EXAMPLE-BEGIN.md primero para calibrarte — es uno real, no una maqueta. Estructura, en orden:
- Qué hace este sistema en un párrafo — en los términos del usuario, no del código.
- El mecanismo fundamental — primeros principios. ¿Cuál es la transformación central? ¿Cuál es la única idea que hace que el resto sea obvio? ¿Qué falla sin ella?
- Superficies → motor — una tabla con las rutas de
scan.md, cada fila verificada. Si ninguna fila cruza un límite de proceso o red, dilo explícitamente: en un repositorio con múltiples lenguajes, la costura real suele ser una llamada HTTP o de cola que ningún grafo de importaciones puede ver. - Las partes complejas, clasificadas — hallazgo primero, medición al final. Cada entrada necesita una trampa que cite un
archivo:líneaque no esté ya en su línea de medición. Una entrada para la que no puedas dar eso es una que realmente no leíste: elimínala. - Decisiones y por qué — cada una vinculada a su PR o commit, con el razonamiento del cuerpo del PR. Esto es lo que hace que el documento sea un grafo de conocimiento en lugar de un recorrido de código.
- Dónde lo dejaste — o, en un repositorio que no posees, quién es el dueño y dónde está creciendo: los autores activos, qué están añadiendo los PRs abiertos más recientes, cuál leer primero.
- Lo que la capa de máquina no pudo ver aquí — y preguntas abiertas, incluyendo la única suposición que hace el trabajo de carga más pesado. Nunca omitas esto.
También registra cómo ejecutarlo y verificarlo (los scripts que recon.md extrajo de package.json) y un glosario para cualquier palabra que este repositorio sobrecargue. Ambos son lo que un recién llegado necesita primero y lo que todo recorrido de código olvida.
Enlaza de forma cruzada con anclas [[wiki-style]]. Sella cada sección:
<!-- begin:section id="ingestion" sha="0055f01" files="src/adapter.ts,src/identity.ts" -->
sha = git rev-parse --short HEAD en el momento en que derivaste la sección (no el commit que luego añade BEGIN.md). files = los archivos en los que se basan las afirmaciones de la sección; globs como src/engine/** funcionan. Una sección con ningún files=, o un files= que nombra una ruta que no existe, nunca puede volverse obsoleta y se reporta como no verificable — que es el fallo que esta habilidad existe para prevenir, así que asegúrate de que las rutas sean correctas.
6. Hazlo vivo
bash $S/install-hook.sh # post-commit; --pre-push para el otro disparador
El hook re-ejecuta el escaneo e imprime un aviso de una línea nombrando cuántas secciones quedaron obsoletas, con detalle en .begin/stale.md. Respeta core.hooksPath (husky) y los worktrees de git, se añade a un hook existente sin corromperlo, se niega a añadirse a un hook que no sea de shell, y nunca toca un archivo rastreado. Elimínalo con --uninstall, que extrae solo su propio bloque.
/begin update
Cuando el usuario regrese a un repositorio que ya tiene un BEGIN.md:
node $S/refresh.mjs && cat .begin/stale.md
Reescribe solo las secciones obsoletas, vuelve a ejecutar recon.sh para refrescar la sección 6, y re-sella cada sección reescrita con el nuevo sha de HEAD. Deja las secciones actuales byte-idénticas — una actualización que reescribe todo destruye tanto la sensación del lector de lo que cambió como la utilidad del historial de git.
Si aún no hay BEGIN.md, /begin update es solo /begin: escribe uno.
Informe
Un párrafo corto: el mecanismo fundamental, el archivo o los dos archivos que más importan y por qué, dónde lo dejó el usuario, y lo único que no pudiste verificar. Los detalles viven en BEGIN.md, no en la respuesta.
Termina con lo que no verificaste. Una pasada de begin que afirma cobertura completa está mintiendo.
Límites conocidos — indícalos, no los disfraces
- El grafo de importaciones es estático. Un
import('./x')literal se resuelve (y se marca como perezoso); unimport(expr)calculado, un contenedor DI o un registro indexado por cadena no produce ningún borde, por lo que dicho archivo puede parecer inalcanzable mientras es fundamental. En un repositorio con múltiples lenguajes, la costura frontend↔backend es una llamada HTTP o WebSocket y es invisible por construcción. El escaneo marca los archivos inalcanzables precisamente para que un humano pueda juzgar. - Resolución completa de JS/TS y Python —
pathsde tsconfig (cada configuración en el árbol, no solo la raíz),extends,referencesde proyecto,./x.js→x.tsde NodeNext, e importaciones absolutas, relativas y de submódulos de Python contra raíces inferidas (medido con ~98% de recuperación y precisión contra una verdad de campo deastde CPython). Go, Rust, Ruby, Java, Kotlin, Swift, PHP, C# y C/C++ no aportan ningún borde. En tal repositorio, cada archivo muestra importancia en el mínimo y aparece "inalcanzable"; el escaneo advierte, y debes repetir esa advertencia en lugar de reportar un grafo vacío como un hallazgo. complexityProxycuenta puntos de decisión por lenguaje, en código con comentarios y cadenas de una línea eliminados. Los archivos de marcado y esquema obtienen 0 por diseño; los archivos de proveedor, minimizados y generados se detectan y clasifican por separado. Los literales de plantilla de varias líneas todavía se cuentan, por lo que un archivo con muchas plantillas se ve un poco caliente.- La actividad está limitada por
--since, y un clon superficial o fresco no tiene ninguna — el escaneo lo dice en voz alta. Un archivo reescrito una vez hace dos años todavía obtiene una puntuación cercana a cero y aún puede ser el archivo más importante del repositorio.
Pruebas
node $S/test-scan.mjs # grafo, ciclos, superficies, alcanzabilidad, Python
node $S/test-scan.mjs --mutate pyDotDot # ...y demuestra que las aserciones pueden volverse rojas
bash $S/test-living.sh # obsolescencia, hooks, limpieza del árbol
node $S/redact.mjs --self-test # secretos detectados Y texto limpio sin daños
Cada aserción existe porque ese error fue real y se envió una vez. Mutaciones: alias, jsToTs, valueCycle, typeCycle, pyAbsolute, pyDotDot — cada una debe volver su aserción roja, y CI falla si una no lo hace.