Configuración y extensión
El motor de Atlantis vive en un solo archivo, atlantis.mjs, y se adapta a cada proyecto sin forkearlo. La pieza central es CONFIG: si la corrida trae args.config (un objeto), el motor lo usa; si no, cae al DEFAULT_CONFIG definido en el propio archivo. atlantis.config.example.mjs solo documenta la forma del bloque: nunca se importa en runtime.
Un gotcha clave: el harness puede entregar args como string JSON aunque pases un objeto. Por eso el motor normaliza primero: si el string empieza con { o [, intenta JSON.parse. Sin esa normalización, campos como dryRun se pierden en silencio y un ensayo se convierte en corrida real.
El script corre en el sandbox de la tool Workflow: sin filesystem ni builtins de Node en el top-level. Un import top-level rompe la carga, así que readline se carga lazy (await import('readline')) y solo cuando hay una TTY real.
Para extender sin fork: guard.when acepta una función (solo para configs en proceso) o un objeto declarativo como anyLaneProfileIn con la lista de perfiles, porque las funciones no sobreviven JSON.stringify al viajar por args.config. CONFIG.guardInstructions (claves run y dryRun) agrega instrucciones a todos los guards. Así Firulapp vendorea el motor sin modificarlo. El CLI atlantis-cli.mjs ofrece doctor, init <repo>, share-agents, share-memory y status.