Imported from IDUCDEV/IDUCDEV-Asistente-Busqueda-Empleo-Clientes (
AGENTS.md). Install upstream withnpx skills add IDUCDEV/IDUCDEV-Asistente-Busqueda-Empleo-Clientes. Copyright stays with the author.
AGENTS.md — Guía para agentes de IA en este repositorio
Repositorio del Asistente IDUCDEV: un agente delegado para buscar
empleo (Flutter/Dart remoto LATAM) y clientes (VE + empresas Flutter),
usando skills de openCode y un "cerebro" en estado/.
Reglas de oro
- NUNCA hardcodear rutas. La raíz se resuelve con
estado/config.py(vía el marcador.iducdev-rooto la envIDUCDEV_PROJECT_DIR). Usa rutas relativas a la raíz en comandos y docs; en Python, importafrom config import PROJECT_DIR, OUTPUT_DIRS, RESOURCES_DIR, .... - CONSULTA SIEMPRE el centro de recursos. Antes de ejecutar cualquier
skill, lee
recursos/INDICE.md: ahí está cada recurso de entrada y la salida esperada de cada skill. Los recursos de entrada (CV base, reglas ATS, guías) NO se modifican: los actualiza el humano. - NUNCA repetir trabajo. Todo lo visto queda en
estado/historial.json(categorías + claves normalizadas). Consulta antes de mostrar, registra después. - Entrada única: la skill
asistente-empleo-clienteses la puerta de entrada. La ronda CLI se delega conestado/orquestador.py. - Toda salida de una skill va a
resultados/<carpeta-de-la-skill>/. Nunca sacar resultados a la raíz ni arecursos/. - No commitear a menos que el usuario lo pida explícitamente.
Mapa del repo
recursos/ # CENTRO DE RECURSOS (entrada, lo mantiene el humano)
INDICE.md # mapa maestro: recursos + salidas (CONSULTAR SIEMPRE)
cv/ # base-isaac-urdaneta.md + CVs canónicos (ES/EN) + PDFs
guias/ # cv-reglas-ats.md, linkedin.md
resultados/ # SALIDAS de las skills (se regeneran, ignoradas por git)
vacantes/ # ← job-search
vacantes-web/ # ← hidden-jobs-web (mobile.career, YC, X, site:boards.*)
vacantes-workana/ # ← workana-search
vacantes-ocultas/ # ← linkedin-hidden-jobs
clientes-potenciales/# ← prospectar-clientes
empresas-target/ # ← flutter-employers
mensajes-outreach/ # ← linkedin-outreach (empleo)
mensajes-clientes/ # ← contactar-clientes (genera) → enviar-clientes (envía)
propuestas-workana/ # ← aplicar-workana (genera) → enviar-workana (postula)
cv/ # ← cv-apply (CV + carta + PDF)
informes/ # ← orquestador (resumen diario)
estado/
config.py # fuente única de rutas (IMPORTANTE)
tracker.py # helper historial: Historial, normalize_*, vacancy_key
historial.json # dedup central ("no repitas esto")
tareas.json # bandeja de entrada (acción + vencimiento)
rondas.json # bitácora de rondas (fases + conteos)
cola_envios.json # cola de envíos a clientes (contactar → enviar)
cola_envios.py # CLI cola: add, pendientes, enviados-hoy, marcar
empresas_registry.json # registro de empresas (versionado) ← flutter-employers
empresas_cache.json # cache de sondeo ATS (TTL 24 h, se regenera)
enviar_email.py # envío SMTP (Gmail app password, desde .env)
orquestador.py # CLI: ronda, registrar, estado, marcar, tareas, informe, reset
.env # credenciales SMTP + límites (NO commitear; ver .env.example)
.opencode/
skills/ # las skills del asistente (proyecto-only)
command/ # comandos /ronda /estado /nuevo /enviar
informes/ (ya no — ahora resultados/informes/)
El cerebro (estado/)
orquestador.py ronda [--empleos|--clientes]→ correjob_search.pyyworkana_search.py, anota las fases enrondas.jsony regenera el informe diario enresultados/informes/. Las fases de navegador (hidden-jobs, prospectar, empresas) se registran conorquestador.py registrar <fase> <archivo> --nuevas N.- Búsqueda de empleo en 2 carriles:
job_search.py(sin navegador, 12 fuentes agregadoras) →resultados/vacantes/.--dry-runno escribe nada.empresas_search.py(tableros directos Greenhouse/Ashby/Lever) →resultados/empresas-target/. Resuelveats+slugdesde lacareers_urldel registro y cachea 24 h (empresas_cache.json). Un tablero que responde vacío se marcatablero_vacio, nunca "sin vacantes": suele ser slug equivocado.hidden-jobs-webcubre lo no parseable (mobile.career, YC, X,site:boards.*) y da de alta empresas enempresas_registry.json.
orquestador.py estadoexpone historial + bandeja + vencidos (pendientes y seguimientos).seguimientoscrea tareas automáticas D+3 (outreach y clientes) y D+7 (aplicaciones) desde el historial.marcar <cat> <key> <estado>actualiza el historial y crea la tarea de seguimiento correspondiente.reset [--yes]vacía el estado para reempezar desde cero: historial, tareas y rondas. Pide confirmación salvo--yes(no tocaresultados/).- Flujo de contacto a clientes (2 skills):
contactar-clientesgenera el mensaje y lo encola (cola_envios.py add, leaden_cola);enviar-clientesenvía uno por uno (muestra cada mensaje, lo valida con el usuario: ok/modificar/saltar/parar; email SMTP automático, WhatsApp Web con navegador, LinkedIn semi) y solo tras envío efectivo marcaorquestador.py marcar clientes <clave> contactado(crea el D+3). Límite diarioENVIO_MAX_DIA(default 12) y pausa 15-35s entre WhatsApp. - Flujo de postulación Workana (2 skills):
aplicar-workanagenera la propuesta (solois_flutter: true, sin automatizaciones, presupuesto ≥ USD 500) y la encola (cola_envios.py add --canal workana, proyectoen_proceso);enviar-workanaenvía uno por uno (muestra la propuesta, la valida el usuario: ok/modificar/saltar/parar; abre la URL del proyecto, pega título + propuesta en el formulario de postulación y el usuario pulsa enviar) y solo tras postulación efectiva marcaorquestador.py marcar proyectos_workana <key> applied(crea el D+7,SEGUIMIENTO_DIAS["proyectos_workana"]). Mismo cupoENVIO_MAX_DIAcompartido con clientes.
Ciclo de vida del estado (historial.json)
nuevo → revisado → en_proceso → aplicado/enviado → respuesta/descartado
tracker.py vencidos <dias> lista items en enviado/applied/contactado sin
actualizar hace > N días (para no dejar contacts sin follow-up).
Validación tras tocar código
python3 -m py_compile estado/*.py .opencode/skills/*/*.py
python3 estado/tracker.py stats
python3 estado/orquestador.py estado
python3 estado/cola_envios.py pendientes
Otras notas
- Abrir el navegador siempre con autorización previa del usuario
(WhatsApp Web y LinkedIn de
enviar-clientesincluidos). - Credenciales SMTP y límites de envío viven en
.env(gitignored); la plantilla es.env.example. Nunca mencionar las credenciales al usuario, ni commitear.env. - Los scripts
job-searchyworkana-searchresuelven la raíz caminando hacia arriba y volcandoestado/ensys.path; no dependen de variables de entorno ni del cwd. - El proyecto está pensado para renombrarse a una carpeta con la raíz limpia
(
.iducdev-roothace que funcione desde cualquier ubicación).
