Communitygithub.com

moonbeautiful/autumn-recruiting-radar

Skill de recopilación de información de reclutamiento de otoño (秋招) para campus en China.

¿Qué es autumn-recruiting-radar?

Este skill está diseñado para recopilar de manera sistemática información sobre reclutamiento de otoño (秋招) en China, incluyendo pasantías y conversión de pasantías a tiempo completo. Primero confirma las preferencias del usuario (año de graduación, puesto objetivo, ciudad, tipo de reclutamiento y tipo de empresa), luego descubre puestos en tiempo real desde fuentes públicas como páginas agregadoras, rankings y sitios de empleo universitarios. Prioriza la verificación en los sitios oficiales de las empresas y utiliza scripts deterministas para realizar coincidencias, deduplicación entre fuentes, detección de cambios y reconocimiento de fechas límite. El resultado es una lista concisa de puestos nuevos o modificados que se entrega directamente en la conversación, sin necesidad de archivos externos. Soporta múltiples plataformas (Trae, Claude, etc.) y es completamente portable para cualquier usuario que clone el repositorio.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add moonbeautiful/autumn-recruiting-radar

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Recopilación de Información de Reclutamiento de Otoño (秋招)

Skill de recopilación de información para reclutamiento de campus (校招), pasantías y conversión de pasantías a tiempo completo en China. Primero confirma las preferencias de búsqueda de empleo, luego descubre puestos desde fuentes públicas, prioriza la verificación en los sitios web oficiales de las empresas y finalmente utiliza scripts deterministas para realizar la coincidencia, deduplicación entre fuentes, detección de cambios y reconocimiento de fechas límite, y devuelve la lista de puestos directamente en la conversación actual.

Entorno de Ejecución (Código Abierto y Portable)

Este Skill está diseñado para distribución de código abierto. Cualquier persona puede clonarlo en su propia computadora e instalarlo, por lo que debe cumplir con:

  • Multiplataforma: Todos los scripts son Python 3.8+ con biblioteca estándar, y funcionan en Windows / macOS / Linux; no usan rutas absolutas ni dependen de comandos específicos del sistema como osascript o launchd.

  • Multi-modelo / Multi-cliente: El descubrimiento de puestos solo utiliza "la capacidad de búsqueda en red / lectura de páginas web integrada en el cliente anfitrión", sin instalar herramientas adicionales, sin controlar el navegador del usuario y sin generar costos adicionales.

  • Solo dos caminos:

    1. El cliente tiene búsqueda en segundo plano / lectura de páginas web (Trae, Claude y otros clientes de IA principales lo tienen incorporado) → Recopila puestos directamente en segundo plano, sin intervención del usuario;
    2. El cliente no tiene capacidad de conexión a la red → Muestra al usuario el siguiente mensaje fijo y se detiene, nunca inventa puestos, empresas, enlaces o fechas límite de memoria.

    Mensaje fijo cuando la conexión a la red no está disponible:

    El cliente actual no tiene capacidad de búsqueda en línea disponible. No puedo obtener información de puestos en tiempo real. Por favor, ejecute esta skill nuevamente en un cliente de IA que admita conexión a la red.

  • Independientemente de qué camino obtenga los puestos, el resultado se escribe uniformemente en runtime/inbox/jobs-input.json, y el procesamiento posterior es completamente idéntico.

Límites de Configuración

Antes de comenzar, lea completamente:

  • configuration.md: Límites de configuración modificable por el usuario, configuración del proyecto y estado de ejecución;
  • data-contract.md: Campos de entrada y salida de puestos;
  • source-strategy.md: Prioridad de fuentes, proceso de descubrimiento y verificación.

No permita que el usuario modifique config/project.json. Las preferencias del usuario solo se escriben en runtime/user-preferences.json; el estado del programa solo se escribe en runtime/state/.

Paso 0: Inicialización

Primero ejecute:

SKILL_DIR=$(cd "$(dirname "SKILL.md")" && pwd)
python3 "$SKILL_DIR/scripts/bootstrap.py"

Lea runtime/user-preferences.json. Si onboarded no es true, solo pregunte los cinco ítems aún no definidos:

  1. Año de graduación;
  2. Puesto objetivo;
  3. Ciudad objetivo;
  4. Solo reclutamiento de campus, o también pasantías y conversión de pasantías;
  5. Qué tipo de empresa busca (usando discovery.company_type_options: Internet grandes empresas / AI unicornios·empresas de modelos grandes / Verticales·empresas del sector / Todos), y si tiene preferencias adicionales de empresas / sectores.

Escriba las respuestas en runtime/user-preferences.json:

  • Ciudad como array vacío significa todo el país;
  • El tipo de empresa (ítem 5) se utiliza en el Paso 1 para generar la "cola de empresas" y decidir a quién buscar primero; la lista específica se obtiene en tiempo real durante la ejecución, no está fija, y el usuario no necesita saber qué empresas existen;
  • Las preferencias de empresas y sectores se utilizan por defecto para sumar puntos en la clasificación, no como filtro estricto;
  • No se pide al usuario que complete una lista de palabras clave, el Agente genera role_keywords basándose en el objetivo en lenguaje natural; por ejemplo, "producto AI" debería cubrir nombres comunes como Gerente de Producto de Aplicaciones AI, Gerente de Producto de Modelos Grandes AI, Gerente de Producto de Agente AI, Gerente de Producto AIGC y Gerente de Producto (dirección AI);
  • Una vez completado, establezca onboarded en true y resuma la configuración al usuario.

Al preguntar sobre el tipo de empresa, mantenga un tono neutral consistente con las otras preguntas: explique que la lista específica de empresas es buscada en tiempo real por el asistente durante la ejecución, el usuario solo necesita seleccionar una categoría general, sin necesidad de enumerar empresas.

Sobre si activar las "notificaciones de actualización", pregunte después de obtener el primer resultado (ver Paso 5), no indague durante la inicialización.

Paso 1: Descubrimiento de Puestos (Por Fases + Entrega en Streaming)

Lea config/project.json (especialmente la sección discovery) y references/source-strategy.md.

Principio fundamental: El usuario no espera a que "todo esté buscado", sino "el próximo puesto al que pueda postularse". Por lo tanto, siempre entregue a medida que busca, nunca calcule todo primero y luego entregue. Consulte source-strategy.md para el "descubrimiento en streaming por fases".

El descubrimiento se divide en dos pasos:

1a. Primero descubra la "cola de empresas" (en tiempo real, uno por muchos a la vez)

  • El tipo de empresa es seleccionado por el usuario en el Paso 0 (Internet grandes empresas / AI unicornios·empresas de modelos grandes / Verticales·empresas del sector / Todos); la lista no está fija.
  • Utilice páginas de pistas de platform como agregadores / rankings / sitios de empleo universitarios que "pueden traer docenas de empresas a la vez", y busque en tiempo real un lote de "nombre de empresa que está contratando + pista de puesto", obteniendo una cola ordenada (por ejemplo: ByteDance → Alibaba → Tencent → ...).
  • La ordenación puede usar discovery.employer_anchors para que las empresas conocidas salgan primero; employer_anchors es solo un ancla de ordenación y un respaldo ocasional, la lista real se basa en esta búsqueda.
  • Este lote de pistas en sí mismo puede devolverse al usuario como una "versión preliminar (pendiente de verificación)", sin desperdiciar.

1b. Luego, según la cola, "empresa por empresa" verifique y complete (en streaming, una vez buscada una empresa, entregue esa empresa)

  • Siga el orden de la cola, procese concurrentemente no más de discovery.stream.max_concurrent_lookups empresas a la vez;
  • Dentro de cada empresa, primero los puestos "más recientes / en contratación" (in_hiring_first), los existentes después;
  • Cada vez que termine de buscar una empresa, agregue los puestos de esa empresa a la conversación actual (deliver_per_company), no espere a que termine toda la cola;
  • La primera oleada entrega first_batch_max_companies empresas (por defecto 3), para que el usuario vea algo en segundos;
  • Una sola ejecución maneja como máximo max_companies_per_run empresas y como máximo max_per_company puestos por empresa, para evitar descontrol;
  • Después de entregar un lote, si ask_before_long_tail es verdadero, pregunte "¿Quiere continuar buscando AI unicornios / verticales y otras empresas de larga cola?"; si el usuario dice "continuar", expanda; si dice "suficiente", deténgase inmediatamente y organice los resultados obtenidos;
  • Las empresas no buscadas en la cola se guardan para la próxima vez, no se descartan.

Los puestos candidatos deben cumplir con data-contract.md: source_tier solo puede ser official, official_wechat o platform; las páginas de agregación / enlaces de medios son rechazadas directamente por el script y solo pueden ser usadas como "pistas". La salida en streaming se escribe uniformemente (se puede agregar varias veces):

runtime/inbox/jobs-input.json

Prohíba adivinar la fecha de publicación o la fecha límite; si la página no las indica claramente, escriba unknown. Si una fuente falla o está vacía, regístrelo fielmente, no intente repetidamente evitar las restricciones de acceso.

Paso 2: Verificación Oficial

Para los puestos descubiertos de fuentes no oficiales, priorice la búsqueda de la página de detalles del sitio web oficial de reclutamiento de la empresa:

  • Si encuentra la página de detalles oficial: establezca esta como fuente principal, escriba la página agregadora original en alternate_sources;
  • Si solo encuentra la cuenta oficial de WeChat de la empresa: el nivel de fuente se escribe como official_wechat;
  • Si no puede encontrar una página oficial: conserve el nivel de fuente real, no lo disfrace como oficial;
  • Si la página oficial está claramente cerrada, fuera de línea o ha detenido la contratación: source_status se escribe como closed;
  • Si la página aún permite postularse: source_status se escribe como open;
  • Si no se puede determinar: escriba unknown.

Cada vez, verifique en profundidad un máximo de 5 nuevas empresas para evitar costos descontrolados.

Paso 3: Coincidencia, Deduplicación y Detección de Cambios

Ejecute:

python3 "$SKILL_DIR/scripts/radar.py" run \
  --input "$SKILL_DIR/runtime/inbox/jobs-input.json" \
  --preferences "$SKILL_DIR/runtime/user-preferences.json" \
  --project-config "$SKILL_DIR/config/project.json" \
  --state-dir "$SKILL_DIR/runtime/state"

El programa debe encargarse de:

  • Coincidir por año de graduación, puesto, ciudad y tipo de reclutamiento;
  • Las preferencias de empresa y sector solo suman puntos;
  • Deduplicación entre fuentes para la misma empresa, mismo puesto, misma ciudad, mismo año de graduación y mismo tipo de reclutamiento;
  • Priorizar fuentes oficiales, conservar fuentes más débiles como evidencia de respaldo;
  • Comparar campos estables para identificar new, changed, seen;
  • Generar changed_fields específicos;
  • Cuando la fecha límite es anterior a la fecha de ejecución, o la página oficial indica claramente que está cerrada, marcar como expired;
  • Los puestos vencidos se archivan, no se envían;
  • fetched_at no participa en la determinación de cambios.

Paso 4: Responder Directamente en el Chat

El script produce por defecto una lista de chat concisa que solo incluye puestos nuevos o modificados que aún no han vencido. Devuelva la salida completa del script en la conversación actual, no solo indique la ruta del archivo ni pida al usuario que abra un informe.

Archivos de estado interno:

runtime/state/
├── jobs.json
├── jobs.csv
├── seen.json
├── expired.json
├── rejected.json
├── daily/YYYY-MM-DD.md
└── outbox/YYYY-MM-DD.md

La lista de chat debe incluir:

  • Empresa;
  • Nombre del puesto;
  • Ciudad;
  • Tipo de reclutamiento;
  • Salario y beneficios;
  • Fecha de publicación;
  • Fecha límite;
  • Palabras clave del puesto (extraídas de los requisitos del puesto);
  • Aspectos destacados del puesto;
  • Enlace de postulación;
  • Fuente de información;
  • Estado y campos de cambio.

daily/ es una instantánea de auditoría interna; outbox/ es una copia interna de la lista de chat actual. El usuario no necesita abrir estos archivos. Los puestos seen, expired y duplicados del mismo lote no deben ser repetidos.

Paso 5: Después de Procesar los Resultados, Preguntar si se Activan las Notificaciones de Actualización

Después de la primera ejecución, cuando se haya entregado la lista de puestos al usuario, pregunte: "¿Me permite notificarle cuando haya puestos nuevos o cambios?"

  • Si el usuario no lo permite: establezca schedule.notify_on_update en false (valor predeterminado), termine, no haga nada adicional;
  • Si el usuario lo permite: establezca schedule.notify_on_update en true y, según el Paso 6, organice las ejecuciones periódicas posteriores.

El usuario puede cambiar de opinión en cualquier momento: si dice "no quiero notificaciones", cambie notify_on_update de nuevo a false, y aunque haya nuevos puestos o cambios, no se enviarán activamente; si dice "reactivar notificaciones", cámbielo de nuevo a true. Es un interruptor que se puede activar y desactivar repetidamente, no una configuración única.

Paso 6: Notificaciones Periódicas (Solo cuando notify_on_update sea true)

El significado de la notificación periódica es simple: cada cierto tiempo, hacer que el Agente vuelva a ejecutar este Skill (volver a recopilar → deduplicar → comparar con el estado histórico).

  • Si en esta ejecución hay puestos "nuevos" o "modificados", envíe la lista a la conversación actual;
  • Si no hay ningún cambio nuevo, no envíe nada, manténgase en silencio, no moleste al usuario.

Solo depende de "volver a ejecutar + comparar con el estado histórico", no utiliza ventanas emergentes del sistema, correos electrónicos ni Webhooks. "Quién desencadena la re-ejecución" se divide en dos niveles, desde lo general hasta lo mejorado:

6.1 Nivel Predeterminado (Para Todos, Configuración Cero, Multiplataforma y Multimodelo)

Cualquier persona que clone este Skill utiliza este nivel por defecto, sin depender de ningún temporizador:

  1. Actualización incremental al iniciar la conversación (este es el "recolector diario" universal): Cuando este Skill se activa en una sesión y notify_on_update es true y ha pasado un día desde la última ejecución, el Agente automáticamente utiliza la búsqueda en red integrada del anfitrión para volver a recopilar las empresas que le interesan al usuario (como ByteDance, Alibaba) → deduplicar → comparar con el estado histórico → solo enviar los puestos nuevos/modificados al usuario, sin actualizaciones permanece en silencio. El usuario no necesita decir "verifica" cada vez, ni necesita configurar ningún comando en segundo plano. Dado que el usuario abre su cliente de IA todos los días, la tarea de "descubrir nuevos puestos" que requiere conexión a la red ocurre naturalmente en la primera conversación del día — esta es la única forma de recopilación que es de configuración cero, sin costo y no vinculada a un dispositivo para todos los usuarios de GitHub.
  2. Activación por parte del usuario: El usuario puede decir "verifica / mira si hay nuevos" en cualquier momento, y se vuelve a ejecutar de inmediato.
  3. Añada --heartbeat a la entrada diaria, sin actualizaciones sin salida, solo con actualizaciones se responde con la lista:
python3 "$SKILL_DIR/scripts/run_daily.py" \
  --project-config "$SKILL_DIR/config/project.json" --heartbeat

Cuando notify_on_update es true, run_daily.py incluye automáticamente el latido, no es necesario agregar el parámetro manualmente.

6.2 Nivel Mejorado Opcional: Ejecución Programada por el Anfitrión / Sistema ("Notificaciones Automáticas a una Hora Fija Cada Día")

Cuando el usuario quiere explícitamente "notificaciones automáticas a una hora fija cada día", implemente según la siguiente prioridad y explique honestamente los costos:

  1. Priorice el uso de la capacidad de temporización o recordatorio integrada del Agente / Cliente anfitrión (si la tiene) para que ejecute este Skill a la hora indicada, es lo más sencillo y no requiere tocar el sistema.
  2. Si el anfitrión no tiene capacidad de temporización, use el script multiplataforma scripts/schedule_task.py para registrar una tarea programada nativa del sistema operativo (macOS launchd / Linux cron / Programador de tareas de Windows). Al ejecutarse, genera la configuración según el sistema del usuario y la hora seleccionada, sin rutas fijas ni vinculación al dispositivo del mantenedor:
# Vista previa primero (por defecto print, no modifica el sistema, seguro):
python3 "$SKILL_DIR/scripts/schedule_task.py" --action print --time 08:00
# Una vez que el usuario confirma, se instala realmente (modificará esta máquina):
python3 "$SKILL_DIR/scripts/schedule_task.py" --action install --time 08:00
# Ver / desinstalar:
python3 "$SKILL_DIR/scripts/schedule_task.py" --action status
python3 "$SKILL_DIR/scripts/schedule_task.py" --action remove

Antes de instalar, primero debe mostrar una vista previa con print y obtener el consentimiento del usuario; después del consentimiento, escriba la hora seleccionada por el usuario en schedule.time y establezca schedule.enabled en true.

Debe explicar claramente al usuario dos limitaciones reales (no ocultarlas, no exagerarlas como "24 horas en la nube"):

  • La computadora debe estar encendida: La tarea programada del sistema solo se activa a la hora indicada si la computadora está encendida; si está apagada / en hibernación, no se ejecutará y no se recuperará.
  • La tarea programada en sí misma no "vuelve a buscar puestos en la red": run_daily.py por defecto solo vuelve a procesar las entradas existentes (deduplicación, cambios, archivo de vencidos), por lo tanto collector.command en config/project.json debe mantenerse vacío por defecto y debe permanecer vacío (la razón está en la command_note de ese campo). Esto no es un defecto: el verdadero descubrimiento de nuevos puestos lo realiza el "recolector automático al iniciar la conversación" del nivel 6.1, que es de configuración cero y sin costo para todos los usuarios. No existe un comando de red en segundo plano que sea "a la vez universal, gratuito y ejecutable para todos los usuarios de GitHub", así que no intente fijar collector.command para que la tarea programada busque nuevos puestos.
  1. Si el anfitrión no admite temporización y el usuario no quiere usar tareas del sistema, vuelva al nivel predeterminado: dígale al usuario "La próxima vez que me use, se actualizará automáticamente de forma incremental, o puede decir 'verifica' en cualquier momento", nunca use una tarea programada del sistema local para hacerse pasar por una notificación automática en la nube.

Validación

bash "$SKILL_DIR/scripts/validate_skill.sh"

La validación debe demostrar:

  1. La primera ejecución produce puestos nuevos;
  2. La misma entrada ejecutada nuevamente no envía puestos duplicados;
  3. Los puestos duplicados entre fuentes solo conservan la fuente más fuerte;
  4. Cuando los campos cambian, se genera changed y los campos de cambio específicos;
  5. La entrada con cambios ejecutada nuevamente se convierte en seen;
  6. Los puestos con fecha límite clara y fecha vencida entran en expired;
  7. Los puestos vencidos no aparecen en la lista de chat;
  8. Ciudad, tipo de reclutamiento, fecha de publicación, fecha límite, fuente y aspectos destacados aparecen en la lista de chat;
  9. El comando predeterminado genera directamente la lista de chat, JSON solo se usa para pruebas automatizadas.

Seguridad y Autenticidad

  • Solo acceda a páginas públicas, no extraiga contenido detrás de inicio de sesión, interno o interfaces no públicas;
  • No almacene cookies, contraseñas de cuentas, información privada de contactos de reclutamiento;
  • No evite CAPTCHAs, anti-scraping o restricciones de acceso;
  • Fechas desconocidas escriba unknown, no adivine;
  • El estado interno y la lista de chat conservan el nombre de la fuente, el nivel, el enlace y la hora de la extracción;
  • Todos los puestos deben ser verificados nuevamente en el sitio web oficial de reclutamiento de la empresa antes de postularse.

Skills relacionados