Skip to content

feat(forge): M16 skills + M18 subagents in-process + fix read_file cap - #29

Open
turbillon50 wants to merge 3 commits into
mainfrom
claude/vforge-mvp-Lw6HY
Open

feat(forge): M16 skills + M18 subagents in-process + fix read_file cap#29
turbillon50 wants to merge 3 commits into
mainfrom
claude/vforge-mvp-Lw6HY

Conversation

@turbillon50

Copy link
Copy Markdown
Owner

Resumen

Tres avances en un PR. V ahora descubre skills relevantes, los aplica, y delega trabajo paralelo a sub-agentes especializados. Plus un bug fix crítico: V dejaba de ver archivos > 5KB.

M16 — Skills registry (commit 5925c1c)

V tiene un catálogo de 7 habilidades reusables que puede buscar por texto natural y "instalar" al vuelo:

Skill Ring Use case
repo-rescue 1 "este repo está roto, arréglalo"
new-project-bootstrap 1 "modo nuevo, arranca proyecto X"
dns-vercel-namecom 1 "apunta dominio.com a vercel"
github-pr-author 1 "haz un PR con esto en repo X"
vercel-deploy-debug 1 "el build está fallando"
code-review 0 "revisa este archivo / repo"
bulk-categorizer 1 "clasifica mis 52 repos"

Tools: skill_search(query, top_k) + skill_install(skill_id). Search por trigram ILIKE + tokenize ES+EN + stopwords. Cada query natural devuelve el skill correcto en top 1 (smoke contra Neon production con 6 queries PASS).

M18 light — Subagentes paralelos in-process (commit 02f0441)

V puede invocar N sub-agentes en una sola tool round → el dispatcher los corre con Promise.all. Smoke test 3 subagents en paralelo → speedup 2.48x (3.67s vs 9.1s serial), costo total $0.000442.

8 roles built-in con modelo optimizado:

Rol Modelo default Para qué
researcher Gemini 2.5 Flash Sintetizar info
reviewer Sonnet 4.6 Code review
coder Sonnet 4.6 Escribir código corto
tester Haiku 4.5 Predecir comportamiento
categorizer Gemini 2.5 Flash JSON estricto
summarizer Haiku 4.5 3-5 bullets
extractor Haiku 4.5 JSON desde texto
translator Gemini 2.5 Flash Traducir

Tools: spawn_subagent(role, task, model?, max_tokens?) + list_subagent_roles(). Persistencia automática a conversations + audit_events con session_id = parent + ':subagent:' + role para que el cost dashboard agregue.

Sin Trigger.dev todavía (M9 lo upgrade a durable). Si el SSE cierra, results se pierden. Suficiente para tareas < 60s totales.

Fix bug crítico: github_read_file cap

V reportó hoy: "Mi tool github_read_file trunca a 5KB y el repo tiene archivos de 58KB+. No puedo ver el código completo — estoy ciega en archivos grandes."

  • Default cap subido de 5KB → 50KB
  • Nuevo param max_bytes (hasta 500KB)
  • Nuevo param offset para paginar archivos enormes
  • Response devuelve total_bytes + next_offset para que V sepa cuándo seguir

Archivos

Archivo Líneas Estado
migrations/005_skills.sql +76 Aplicado a Neon
migrations/006_skills_builtin.sql +137 Aplicado a Neon
lib/forge/skills.ts +168 Nuevo
lib/forge/subagents.ts +233 Nuevo
lib/forge/tools.ts +222, -5 4 tools nuevas (skill_search, skill_install, spawn_subagent, list_subagent_roles) + fix read_file

Test plan

  • tsc --noEmit pasa
  • Skill search: 6 queries naturales devuelven skill correcto en top 1
  • Subagents: 3 en paralelo, speedup 2.48x, total cost $0.000442
  • CI build + lint (en curso)
  • Vercel preview build OK
  • Validar en producción: pedirle a V "modo rescate" + dale un repo, debe invocar skill_search → skill_install('repo-rescue') → tools

Lo que NO incluye

  • M9 Trigger.dev — los subagentes son in-process (no durables)
  • Embeddings — el skill_search usa ILIKE + trigram (suficiente para 7-20 skills)
  • M11 Clerk — sigue auth única
  • UI changes — todo es backend

Pendiente próxima tanda

  • M9 Trigger.dev para subagentes durables (necesario antes de "audita 52 repos" 2-3 min wall)
  • M4 anthropic-web-search via OpenRouter (web search general)
  • Bumpear seed migrations a un splitter robusto para que /api/admin/migrate las pueda reaplicar en preview/staging

https://claude.ai/code/session_01Parr3CGTU4ucH6xReyNJ2G


Generated by Claude Code

claude added 3 commits May 13, 2026 06:20
V ahora elige modelo según task kind y costo, cae automáticamente al
siguiente del cascade si el provider falla (402/429/5xx), y expone su
consumo en tiempo real. Cubre lo que Luis pidió: "mezclar gratuitas
con paga, que vea consumo en vForge en tiempo real, que se auto-analize
si OpenRouter va".

NUEVO:

lib/forge/models.ts (registry):
  Catálogo TS de 8 modelos OpenRouter con tier, kind, costo per 1M,
  context window, soporta tools, y fallback_chain ordenado por
  conveniencia. Source of truth para routing + costo.
  - Premium: anthropic/claude-opus-4.7
  - Balanced: anthropic/claude-sonnet-4.6, google/gemini-2.5-pro, openai/gpt-5
  - Cheap (paid): anthropic/claude-haiku-4.5, google/gemini-2.5-flash
  - Free: minimax/minimax-m2.5:free, google/gemma-4-31b-it:free
  normalizeSlug() resuelve los slugs versionados que devuelve OR
  (ej. 'anthropic/claude-4.6-sonnet-20260217' → 'anthropic/claude-sonnet-4.6').

lib/forge/routing.ts (policy):
  routeFor(task, { costPreference?, excludeSlugs?, forceSlug? }) →
  { primary, cascade, reason }. TASK_PREFERENCES table mapea kind →
  modelos preferidos en orden. costPreference: cheapest | balanced |
  premium | free-only. suggestTierForBudget() sugiere tier según
  saldo restante (M9.5 lo usará para self-throttle automático).

app/api/forge/cost/route.ts (NUEVO):
  GET /api/forge/cost?period=today|24h|this_month|last_7d|last_30d
  Agrega conversations.cost_usd + tokens + by_model + by_day +
  fallback_events count. Cero auth en MVP (Clerk M11).

app/api/admin/health/route.ts (NUEVO):
  GET /api/admin/health → { db, vault (con self-test del pepper),
  openrouter (balance, usage, latency, status) }. Responde 503 si
  alguno está roto. Activity dashboard + futura cron Trigger.dev.

MODIFICADO:

app/api/forge/run/route.ts:
  - Importa routeFor + estimateCostForModel + normalizeSlug.
  - Reemplaza LEGACY_MODEL_MAP por routeFor("chat-main", { forceSlug })
    cuando system_config.default_model está en la registry; si no,
    free-form override + cascade del task default.
  - Inner retry loop: try create() → si error 402/429/5xx + hay cascade
    siguiente, emit "model_fallback" event + retry con next slug.
    Non-recoverable bubble out.
  - audit_events.payload incluye cascade_tried, fallbacks[], routing_reason.
  - Cost calc unificado vía estimateCostForModel (elimina PRICING
    duplicado al final del archivo).
  - errorStatus() helper que extrae status code de OpenAI APIError o
    del prefix "402 ..." en err.message.

lib/forge/tools.ts:
  - import routeFor + MODELS.
  - Tool nueva: model_recommend(task, cost_preference?) → devuelve
    { primary, cascade, reason, primary_info }. Para que V tome
    decisiones de modelo informadas antes de openrouter_query.
  - Tool nueva: forge_cost_report(period?) → query agregado en
    conversations + audit_events; devuelve totales, by_model top 8,
    fallback_events count. Para que V responda "cuánto vas gastando"
    con datos reales, no inventados.

Smoke local en /api/forge/cost?period=this_month: $25.20 / 175 turns
across 3 models (Sonnet via OR $18.85, legacy claude-sonnet-4-6 $6.25,
MiniMax free $0.10). Health: db 57ms, vault round-trip OK,
OpenRouter balance $20 usage $19.61 latency 235ms.

NO cambia el contract SSE hacia el frontend. NO cambia tools existentes.
NO agrega deps.

https://claude.ai/code/session_01Parr3CGTU4ucH6xReyNJ2G
V ya puede descubrir y "instalar" habilidades reusables al vuelo. Cada
skill es un paquete autodescriptivo: system prompt fragment + lista de
tools requeridas + ring level + tags. Cuando Luis describe una tarea,
V invoca skill_search → skill_install y opera con instrucciones
específicas durante el resto del turno.

NUEVO:

migrations/005_skills.sql:
  - Tabla skills con id, name, description, system_prompt, required_tools,
    examples, ring_max, source, tags, invocation_count.
  - Tabla skill_invocations para audit (skill_id, session_id, outcome).
  - pg_trgm + índices GIN sobre name/description/tags para ILIKE rápido.
  - Sin embeddings (coherente con "solo OpenRouter" — OR no vende
    embeddings). Si el catálogo crece, agregamos pgvector + OpenAI
    text-embedding-3-small en M16.5.

migrations/006_skills_builtin.sql:
  Seeds: 7 skills cubriendo los flujos canónicos de vForge.
    - repo-rescue           (ring 1) protocolo RESCATE
    - new-project-bootstrap (ring 1) protocolo NUEVO
    - dns-vercel-namecom    (ring 1) apuntar dominio
    - github-pr-author      (ring 1) cambio en repo via PR
    - vercel-deploy-debug   (ring 1) diagnóstico build fallido
    - code-review           (ring 0) review sin escribir
    - bulk-categorizer      (ring 1) clasificar repos en masa

lib/forge/skills.ts:
  - tokenize(query): split en palabras + strip de acentos + stopwords
    ES+EN para que "rescatar" matche "rescate" y "vercel" matche
    "Vercel" sin importar acentos.
  - searchSkills(query, topK): WITH tokens AS (...) + score híbrido
    (tag exacto > name substring > tag substring > desc substring).
  - getSkillBody(id): full skill + bump invocation_count + insert en
    skill_invocations. Fire-and-forget para no bloquear.
  - listSkills() para futuros /modules dashboards.

lib/forge/tools.ts:
  - skill_search (Ring 0): { query, top_k } → top matches resumidos.
  - skill_install (Ring 0): { skill_id } → full body con
    system_prompt + required_tools + instrucciones explícitas para V.

Smoke test contra Neon production: los 6 queries naturales devuelven
el skill correcto en top 1 con scores 75-565.

NO cambia tools existentes. NO requiere deploy de Vercel para que las
migrations apliquen (ya las apliqué directo en Neon).

Pendiente próxima tanda: M18 subagentes paralelos in-process.

https://claude.ai/code/session_01Parr3CGTU4ucH6xReyNJ2G
…ile cap

V puede ahora despachar tareas a sub-agentes especializados que corren
en paralelo dentro del mismo turno. Sin Trigger.dev (M9 lo upgrade a
durable), pero suficiente para descargar 5-50 tareas cortas a la vez:
clasificar repos, sumarizar dumps, reviewer múltiples archivos.

NUEVO:

lib/forge/subagents.ts:
  8 roles built-in con system prompt + modelo default optimizado:
    - researcher    → google/gemini-2.5-flash
    - reviewer      → anthropic/claude-sonnet-4.6
    - coder         → anthropic/claude-sonnet-4.6
    - tester        → anthropic/claude-haiku-4.5
    - categorizer   → google/gemini-2.5-flash
    - summarizer    → anthropic/claude-haiku-4.5
    - extractor     → anthropic/claude-haiku-4.5
    - translator    → google/gemini-2.5-flash

  runSubagent({ role, task, model?, maxTokens?, signal? }) → llama
  openRouterAdapter.execute() con system prompt del rol. Devuelve
  { role, model, content, tokens_in, tokens_out, cost_usd,
    duration_ms, finish_reason }.

  recordSubagentRun() persiste a conversations + audit_events para
  que el cost dashboard agregue. Fire-and-forget. Cada run aparece
  con session_id = parent + ':subagent:' + role.

lib/forge/tools.ts:
  Tools nuevas (M18):
    - spawn_subagent(role, task, model?, max_tokens?) — Ring 0.
      V puede llamar N en paralelo en una sola tool round; el
      dispatcher las ejecuta con Promise.all (ya existente).
    - list_subagent_roles() — Ring 0. V consulta qué roles existen
      antes de spawn si no recuerda.

  Fix bug crítico (V reportó hoy):
    github_read_file YA NO trunca a 5KB. Default 50KB. max_bytes
    hasta 500KB. offset para paginar archivos enormes. Devuelve
    total_bytes + next_offset para que V sepa cuándo seguir leyendo
    el siguiente chunk. Resuelve "V ciega en archivos grandes" —
    tools.ts pesa 58KB, era invisible al modelo.

Smoke test PASS contra producción:
  3 subagents en paralelo (summarizer + categorizer + translator),
  wall-clock 3673ms vs serial sum 9100ms → speedup 2.48x.
  Total cost: \$0.000442 (Haiku + 2x Flash).

V puede ahora orquestar: "audita los 52 repos del catálogo" →
spawn_subagent('categorizer', ...) x52 en una sola round → resultados
en ~5-10s wall-clock vs ~4 minutos serial.

https://claude.ai/code/session_01Parr3CGTU4ucH6xReyNJ2G
@vercel

vercel Bot commented May 13, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
vforge Ready Ready Preview, Comment May 13, 2026 6:54am

Request Review

@turbillon50
turbillon50 marked this pull request as ready for review May 13, 2026 07:07

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 02f044196d

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment on lines +80 to +82
const cascade = isKnownSlug
? routing.cascade
: [configuredModel, ...routing.cascade];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P0 Badge Map legacy default_model slugs before building cascade

This path now prepends unknown system_config.default_model values directly into the model cascade, but seeded installs still use legacy values like claude-sonnet-4-6 (see existing migrations), which are not valid OpenRouter slugs. Because fallback only retries for 402/429/5xx, the first call fails with a non-recoverable 4xx and the chat turn aborts instead of reaching valid fallback models, effectively breaking default deployments until config is manually edited.

Useful? React with 👍 / 👎.

Comment on lines +43 to +45
case "this_month":
since = new Date(now.getUTCFullYear(), now.getUTCMonth(), 1);
break;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Compute this_month boundary in UTC consistently

this_month mixes UTC getters with the local-time Date(year, month, day) constructor, so in non-UTC runtimes the window starts at local midnight (shifted in UTC) instead of 00:00:00Z on day 1. That skews month-to-date spend/tokens by several hours and makes this period inconsistent with the explicit UTC handling already used for today.

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants