From dbca38b0c50fa2c58842148137986a8de0769bf1 Mon Sep 17 00:00:00 2001 From: Coatl <121911012+2-Coatl@users.noreply.github.com> Date: Thu, 13 Nov 2025 00:47:59 -0600 Subject: [PATCH 1/2] =?UTF-8?q?docs(prompting):=20integrar=20cat=C3=A1logo?= =?UTF-8?q?=20completo=20multi-LLM?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .agent/PLANS.md | 152 ++++++++++ .agent/README.md | 34 +++ {.github => .agent}/agents/README.md | 107 ++++++- .agent/agents/api_agent.md | 33 +++ .agent/agents/chatgpt_agent.md | 32 ++ .agent/agents/claude_agent.md | 32 ++ .agent/agents/codex_mcp_workflow.md | 39 +++ .../agents/dependency_agent.md | 0 .agent/agents/docs_agent.md | 29 ++ {.github => .agent}/agents/gitops_agent.md | 0 .agent/agents/huggingface_agent.md | 36 +++ .agent/agents/infrastructure_agent.md | 30 ++ {.github => .agent}/agents/my_agent.md | 0 {.github => .agent}/agents/release_agent.md | 0 .agent/agents/scripts_agent.md | 31 ++ {.github => .agent}/agents/security_agent.md | 0 .agent/agents/ui_agent.md | 31 ++ .github/ISSUE_TEMPLATE/bug_report.md | 36 +++ .github/ISSUE_TEMPLATE/custom.md | 25 ++ .github/ISSUE_TEMPLATE/feature_request.md | 39 +++ .github/workflows/code-quality.yml | 29 ++ .github/workflows/codeql.yml | 39 +++ .github/workflows/dependency-review.yml | 23 ++ AGENTS.md | 3 + README.md | 27 +- docs/ai/CONFIGURACION_API_KEYS.md | 27 +- docs/ai/FINE_TUNING_TINYLLAMA.md | 278 ++++++++++++++++++ docs/ai/SDLC_AGENTS_GUIDE.md | 48 +++ .../CODEX_MCP_MULTI_AGENT_GUIDE.md | 173 +++++++++++ .../prompting/AGENTIC_SYSTEM_PATTERNS.md | 132 +++++++++ .../prompting/CODE_GENERATION_GUIDE.md | 193 ++++++++++++ .../PHI3_PROMPT_ENGINEERING_PLAYBOOK.md | 186 ++++++++++++ .../prompting/PROMPT_TECHNIQUES_CATALOG.md | 219 ++++++++++++++ docs/ai_capabilities/prompting/README.md | 24 ++ docs/analisis/AGENTS.md | 110 +++++++ .../revision_20251112_consolidada.md | 0 .../metodologias/agentes_automatizacion.md | 8 +- docs/index.md | 4 +- docs/operaciones/verificar_servicios.md | 28 +- .../plans/EXECPLAN_agents_domain_alignment.md | 82 ++++++ docs/plans/EXECPLAN_codex_mcp_multi_llm.md | 98 ++++++ .../EXECPLAN_prompt_techniques_catalog.md | 70 +++++ docs/plans/REV_20251112_remediation_plan.md | 6 +- docs/scripts/README.md | 8 +- docs/scripts/SCRIPTS_MATRIX.md | 2 +- .../2025_11_05_merge_ramas_gitops.md | 2 +- docs/testing/test_documentation_alignment.py | 207 ++++++++++++- logs_data/SCHEMA.md | 4 +- .../desarrollo/agentes_automatizacion.md | 8 +- .../2025_11_05_merge_ramas_gitops.md | 2 +- .../ai/agents/documentation/__init__.py | 9 + .../agents/documentation/eta_codex_agent.py | 179 +++++++++++ scripts/coding/ai/generators/llm_generator.py | 164 ++++++++++- scripts/coding/ai/orchestrators/__init__.py | 5 + .../ai/orchestrators/codex_mcp_workflow.py | 266 +++++++++++++++++ scripts/coding/ai/shared/env_loader.py | 21 ++ .../tests/ai/agents/documentation/__init__.py | 0 .../documentation/test_eta_codex_agent.py | 123 ++++++++ .../tests/ai/generators/test_llm_generator.py | 167 ++++++++++- .../orchestrators/test_codex_mcp_workflow.py | 105 +++++++ .../ai/shared/test_environment_config.py | 65 ++++ scripts/dora_metrics.py | 242 +++++++++++++++ scripts/generate_dora_report.sh | 43 +-- scripts/tests/test_dora_metrics.py | 56 ++++ scripts/tests/test_verificar_servicios.py | 47 +++ scripts/verificar_servicios.sh | 156 ++++++++++ 66 files changed, 4298 insertions(+), 76 deletions(-) create mode 100644 .agent/PLANS.md create mode 100644 .agent/README.md rename {.github => .agent}/agents/README.md (57%) create mode 100644 .agent/agents/api_agent.md create mode 100644 .agent/agents/chatgpt_agent.md create mode 100644 .agent/agents/claude_agent.md create mode 100644 .agent/agents/codex_mcp_workflow.md rename {.github => .agent}/agents/dependency_agent.md (100%) create mode 100644 .agent/agents/docs_agent.md rename {.github => .agent}/agents/gitops_agent.md (100%) create mode 100644 .agent/agents/huggingface_agent.md create mode 100644 .agent/agents/infrastructure_agent.md rename {.github => .agent}/agents/my_agent.md (100%) rename {.github => .agent}/agents/release_agent.md (100%) create mode 100644 .agent/agents/scripts_agent.md rename {.github => .agent}/agents/security_agent.md (100%) create mode 100644 .agent/agents/ui_agent.md create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/custom.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md create mode 100644 .github/workflows/code-quality.yml create mode 100644 .github/workflows/codeql.yml create mode 100644 .github/workflows/dependency-review.yml create mode 100644 AGENTS.md create mode 100644 docs/ai/FINE_TUNING_TINYLLAMA.md create mode 100644 docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md create mode 100644 docs/ai_capabilities/prompting/AGENTIC_SYSTEM_PATTERNS.md create mode 100644 docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md create mode 100644 docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md create mode 100644 docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md create mode 100644 docs/analisis/AGENTS.md rename {rev => docs/analisis}/revision_20251112_consolidada.md (100%) create mode 100644 docs/plans/EXECPLAN_agents_domain_alignment.md create mode 100644 docs/plans/EXECPLAN_codex_mcp_multi_llm.md create mode 100644 docs/plans/EXECPLAN_prompt_techniques_catalog.md create mode 100644 scripts/coding/ai/agents/documentation/__init__.py create mode 100644 scripts/coding/ai/agents/documentation/eta_codex_agent.py create mode 100644 scripts/coding/ai/orchestrators/__init__.py create mode 100644 scripts/coding/ai/orchestrators/codex_mcp_workflow.py create mode 100644 scripts/coding/tests/ai/agents/documentation/__init__.py create mode 100644 scripts/coding/tests/ai/agents/documentation/test_eta_codex_agent.py create mode 100644 scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py create mode 100755 scripts/dora_metrics.py create mode 100644 scripts/tests/test_dora_metrics.py create mode 100644 scripts/tests/test_verificar_servicios.py create mode 100755 scripts/verificar_servicios.sh diff --git a/.agent/PLANS.md b/.agent/PLANS.md new file mode 100644 index 00000000..98a57002 --- /dev/null +++ b/.agent/PLANS.md @@ -0,0 +1,152 @@ +# Codex Execution Plans (ExecPlans): + +This document describes the requirements for an execution plan ("ExecPlan"), a design document that a coding agent can follow to deliver a working feature or system change. Treat the reader as a complete beginner to this repository: they have only the current working tree and the single ExecPlan file you provide. There is no memory of prior plans and no external context. + +## How to use ExecPlans and PLANS.md + +When authoring an executable specification (ExecPlan), follow PLANS.md _to the letter_. If it is not in your context, refresh your memory by reading the entire PLANS.md file. Be thorough in reading (and re-reading) source material to produce an accurate specification. When creating a spec, start from the skeleton and flesh it out as you do your research. + +When implementing an executable specification (ExecPlan), do not prompt the user for "next steps"; simply proceed to the next milestone. Keep all sections up to date, add or split entries in the list at every stopping point to affirmatively state the progress made and next steps. Resolve ambiguities autonomously, and commit frequently. + +When discussing an executable specification (ExecPlan), record decisions in a log in the spec for posterity; it should be unambiguously clear why any change to the specification was made. ExecPlans are living documents, and it should always be possible to restart from _only_ the ExecPlan and no other work. + +When researching a design with challenging requirements or significant unknowns, use milestones to implement proof of concepts, "toy implementations", etc., that allow validating whether the user's proposal is feasible. Read the source code of libraries by finding or acquiring them, research deeply, and include prototypes to guide a fuller implementation. + +## Requirements + +NON-NEGOTIABLE REQUIREMENTS: + +* Every ExecPlan must be fully self-contained. Self-contained means that in its current form it contains all knowledge and instructions needed for a novice to succeed. +* Every ExecPlan is a living document. Contributors are required to revise it as progress is made, as discoveries occur, and as design decisions are finalized. Each revision must remain fully self-contained. +* Every ExecPlan must enable a complete novice to implement the feature end-to-end without prior knowledge of this repo. +* Every ExecPlan must produce a demonstrably working behavior, not merely code changes to "meet a definition". +* Every ExecPlan must define every term of art in plain language or do not use it. + +Purpose and intent come first. Begin by explaining, in a few sentences, why the work matters from a user's perspective: what someone can do after this change that they could not do before, and how to see it working. Then guide the reader through the exact steps to achieve that outcome, including what to edit, what to run, and what they should observe. + +The agent executing your plan can list files, read files, search, run the project, and run tests. It does not know any prior context and cannot infer what you meant from earlier milestones. Repeat any assumption you rely on. Do not point to external blogs or docs; if knowledge is required, embed it in the plan itself in your own words. If an ExecPlan builds upon a prior ExecPlan and that file is checked in, incorporate it by reference. If it is not, you must include all relevant context from that plan. + +## Formatting + +Format and envelope are simple and strict. Each ExecPlan must be one single fenced code block labeled as `md` that begins and ends with triple backticks. Do not nest additional triple-backtick code fences inside; when you need to show commands, transcripts, diffs, or code, present them as indented blocks within that single fence. Use indentation for clarity rather than code fences inside an ExecPlan to avoid prematurely closing the ExecPlan's code fence. Use two newlines after every heading, use # and ## and so on, and correct syntax for ordered and unordered lists. + +When writing an ExecPlan to a Markdown (.md) file where the content of the file *is only* the single ExecPlan, you should omit the triple backticks. + +Write in plain prose. Prefer sentences over lists. Avoid checklists, tables, and long enumerations unless brevity would obscure meaning. Checklists are permitted only in the `Progress` section, where they are mandatory. Narrative sections must remain prose-first. + +## Guidelines + +Self-containment and plain language are paramount. If you introduce a phrase that is not ordinary English ("daemon", "middleware", "RPC gateway", "filter graph"), define it immediately and remind the reader how it manifests in this repository (for example, by naming the files or commands where it appears). Do not say "as defined previously" or "according to the architecture doc." Include the needed explanation here, even if you repeat yourself. + +Avoid common failure modes. Do not rely on undefined jargon. Do not describe "the letter of a feature" so narrowly that the resulting code compiles but does nothing meaningful. Do not outsource key decisions to the reader. When ambiguity exists, resolve it in the plan itself and explain why you chose that path. Err on the side of over-explaining user-visible effects and under-specifying incidental implementation details. + +Anchor the plan with observable outcomes. State what the user can do after implementation, the commands to run, and the outputs they should see. Acceptance should be phrased as behavior a human can verify ("after starting the server, navigating to http://localhost:8080/health returns HTTP 200 with body OK") rather than internal attributes ("added a HealthCheck struct"). If a change is internal, explain how its impact can still be demonstrated (for example, by running tests that fail before and pass after, and by showing a scenario that uses the new behavior). + +Specify repository context explicitly. Name files with full repository-relative paths, name functions and modules precisely, and describe where new files should be created. If touching multiple areas, include a short orientation paragraph that explains how those parts fit together so a novice can navigate confidently. When running commands, show the working directory and exact command line. When outcomes depend on environment, state the assumptions and provide alternatives when reasonable. + +Be idempotent and safe. Write the steps so they can be run multiple times without causing damage or drift. If a step can fail halfway, include how to retry or adapt. If a migration or destructive operation is necessary, spell out backups or safe fallbacks. Prefer additive, testable changes that can be validated as you go. + +Validation is not optional. Include instructions to run tests, to start the system if applicable, and to observe it doing something useful. Describe comprehensive testing for any new features or capabilities. Include expected outputs and error messages so a novice can tell success from failure. Where possible, show how to prove that the change is effective beyond compilation (for example, through a small end-to-end scenario, a CLI invocation, or an HTTP request/response transcript). State the exact test commands appropriate to the project’s toolchain and how to interpret their results. + +Capture evidence. When your steps produce terminal output, short diffs, or logs, include them inside the single fenced block as indented examples. Keep them concise and focused on what proves success. If you need to include a patch, prefer file-scoped diffs or small excerpts that a reader can recreate by following your instructions rather than pasting large blobs. + +## Milestones + +Milestones are narrative, not bureaucracy. If you break the work into milestones, introduce each with a brief paragraph that describes the scope, what will exist at the end of the milestone that did not exist before, the commands to run, and the acceptance you expect to observe. Keep it readable as a story: goal, work, result, proof. Progress and milestones are distinct: milestones tell the story, progress tracks granular work. Both must exist. Never abbreviate a milestone merely for the sake of brevity, do not leave out details that could be crucial to a future implementation. + +Each milestone must be independently verifiable and incrementally implement the overall goal of the execution plan. + +## Living plans and design decisions + +* ExecPlans are living documents. As you make key design decisions, update the plan to record both the decision and the thinking behind it. Record all decisions in the `Decision Log` section. +* ExecPlans must contain and maintain a `Progress` section, a `Surprises & Discoveries` section, a `Decision Log`, and an `Outcomes & Retrospective` section. These are not optional. +* When you discover optimizer behavior, performance tradeoffs, unexpected bugs, or inverse/unapply semantics that shaped your approach, capture those observations in the `Surprises & Discoveries` section with short evidence snippets (test output is ideal). +* If you change course mid-implementation, document why in the `Decision Log` and reflect the implications in `Progress`. Plans are guides for the next contributor as much as checklists for you. +* At completion of a major task or the full plan, write an `Outcomes & Retrospective` entry summarizing what was achieved, what remains, and lessons learned. + +# Prototyping milestones and parallel implementations + +It is acceptable—and often encouraged—to include explicit prototyping milestones when they de-risk a larger change. Examples: adding a low-level operator to a dependency to validate feasibility, or exploring two composition orders while measuring optimizer effects. Keep prototypes additive and testable. Clearly label the scope as “prototyping”; describe how to run and observe results; and state the criteria for promoting or discarding the prototype. + +Prefer additive code changes followed by subtractions that keep tests passing. Parallel implementations (e.g., keeping an adapter alongside an older path during migration) are fine when they reduce risk or enable tests to continue passing during a large migration. Describe how to validate both paths and how to retire one safely with tests. When working with multiple new libraries or feature areas, consider creating spikes that evaluate the feasibility of these features _independently_ of one another, proving that the external library performs as expected and implements the features we need in isolation. + +## Skeleton of a Good ExecPlan + +```md +# + +This ExecPlan is a living document. The sections `Progress`, `Surprises & Discoveries`, `Decision Log`, and `Outcomes & Retrospective` must be kept up to date as work proceeds. + +If PLANS.md file is checked into the repo, reference the path to that file here from the repository root and note that this document must be maintained in accordance with PLANS.md. + +## Purpose / Big Picture + +Explain in a few sentences what someone gains after this change and how they can see it working. State the user-visible behavior you will enable. + +## Progress + +Use a list with checkboxes to summarize granular steps. Every stopping point must be documented here, even if it requires splitting a partially completed task into two (“done” vs. “remaining”). This section must always reflect the actual current state of the work. + +- [x] (2025-10-01 13:00Z) Example completed step. +- [ ] Example incomplete step. +- [ ] Example partially completed step (completed: X; remaining: Y). + +Use timestamps to measure rates of progress. + +## Surprises & Discoveries + +Document unexpected behaviors, bugs, optimizations, or insights discovered during implementation. Provide concise evidence. + +- Observation: … + Evidence: … + +## Decision Log + +Record every decision made while working on the plan in the format: + +- Decision: … + Rationale: … + Date/Author: … + +## Outcomes & Retrospective + +Summarize outcomes, gaps, and lessons learned at major milestones or at completion. Compare the result against the original purpose. + +## Context and Orientation + +Describe the current state relevant to this task as if the reader knows nothing. Name the key files and modules by full path. Define any non-obvious term you will use. Do not refer to prior plans. + +## Plan of Work + +Describe, in prose, the sequence of edits and additions. For each edit, name the file and location (function, module) and what to insert or change. Keep it concrete and minimal. + +## Concrete Steps + +State the exact commands to run and where to run them (working directory). When a command generates output, show a short expected transcript so the reader can compare. This section must be updated as work proceeds. + +## Validation and Acceptance + +Describe how to start or exercise the system and what to observe. Phrase acceptance as behavior, with specific inputs and outputs. If tests are involved, say "run and expect passed; the new test fails before the change and passes after>". + +## Idempotence and Recovery + +If steps can be repeated safely, say so. If a step is risky, provide a safe retry or rollback path. Keep the environment clean after completion. + +## Artifacts and Notes + +Include the most important transcripts, diffs, or snippets as indented examples. Keep them concise and focused on what proves success. + +## Interfaces and Dependencies + +Be prescriptive. Name the libraries, modules, and services to use and why. Specify the types, traits/interfaces, and function signatures that must exist at the end of the milestone. Prefer stable names and paths such as `crate::module::function` or `package.submodule.Interface`. E.g.: + +In crates/foo/planner.rs, define: + + pub trait Planner { + fn plan(&self, observed: &Observed) -> Vec; + } +``` + +If you follow the guidance above, a single, stateless agent -- or a human novice -- can read your ExecPlan from top to bottom and produce a working, observable result. That is the bar: SELF-CONTAINED, SELF-SUFFICIENT, NOVICE-GUIDING, OUTCOME-FOCUSED. + +When you revise a plan, you must ensure your changes are comprehensively reflected across all sections, including the living document sections enumerated above. diff --git a/.agent/README.md b/.agent/README.md new file mode 100644 index 00000000..b2f09703 --- /dev/null +++ b/.agent/README.md @@ -0,0 +1,34 @@ +# Catálogo central de agentes + +Este directorio concentra la gobernanza operativa de los agentes autónomos del proyecto. Aquí conviven las guías de ejecución (`PLANS.md`) y el inventario de agentes especializados ubicados en `.agent/agents/`. + +## Relación con la documentación oficial +- La guía funcional completa se encuentra en `docs/ai/SDLC_AGENTS_GUIDE.md`, donde se documenta el flujo de trabajo esperado para cada agente y cómo coordinarse con el resto del SDLC. +- Las revisiones consolidadas y lineamientos de documentación están centralizados en `docs/analisis/`, siguiendo lo establecido por el ETA-AGENTE CODEX. +- El ExecPlan maestro para la orquestación multi-LLM es `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`; la evolución del catálogo por dominio se mantiene en `docs/plans/EXECPLAN_agents_domain_alignment.md`. + +## Relación con los ejecutables +- Los agentes que ejecutan validaciones automáticas viven en `scripts/coding/ai/agents/` (por ejemplo `scripts/coding/ai/agents/documentation/eta_codex_agent.py`). +- Sus pruebas unitarias están en `scripts/coding/tests/ai/agents/`, lo que permite garantizar cobertura mínima del 80 % conforme a nuestra política TDD. +- Los orquestadores y builders multi-LLM residen en `scripts/coding/ai/orchestrators/` y se verifican con `pytest scripts/coding/tests/ai/orchestrators/`. + +## Mapa de dominios y agentes + +El proyecto está dividido en cinco dominios operativos. Cada uno cuenta con una ficha de agente dedicada en `.agent/agents/` que explica procedimientos, relaciones con ExecPlans y scripts de soporte. + +| Dominio | Directorio raíz | Agente principal | ExecPlans y guías clave | +|---------|-----------------|------------------|-------------------------| +| Backend (API) | `api/` | ApiAgent (`api_agent.md`) | `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai/SDLC_AGENTS_GUIDE.md`, `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` | +| Frontend (UI) | `ui/` | UiAgent (`ui_agent.md`) | `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md` | +| Infrastructure | `infrastructure/` | InfrastructureAgent (`infrastructure_agent.md`) | `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/gobernanza/metodologias/agentes_automatizacion.md` | +| Documentación | `docs/` | DocsAgent (`docs_agent.md`) | `docs/analisis/AGENTS.md`, `scripts/coding/ai/agents/documentation/eta_codex_agent.py` | +| Scripts/Automatización | `scripts/` | ScriptsAgent (`scripts_agent.md`) | `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`, `scripts/coding/ai/generators/llm_generator.py` | + +Cada agente de dominio describe cómo coordinarse con los agentes por proveedor (Claude, ChatGPT, Hugging Face) y con los agentes operativos (GitOps, Release, Dependency). + +## Cómo usar este directorio +1. **Planifica primero**: para cada refactor o feature relevante crea un ExecPlan según `.agent/PLANS.md` y referencia si aplica los planes existentes (`EXECPLAN_codex_mcp_multi_llm.md`, `EXECPLAN_agents_domain_alignment.md`). +2. **Selecciona el agente**: consulta `.agent/agents/README.md` para elegir el agente por proveedor o por dominio adecuado, o para crear uno nuevo siguiendo el estándar. +3. **Documenta y prueba**: enlaza el ExecPlan desde el issue template correspondiente y asegura que los scripts/pruebas mencionados arriba respalden la automatización. Captura resultados en `docs/qa/registros/`. + +Al mantener este repositorio unificado en `.agent/`, los colaboradores encuentran en un solo lugar la planificación, la documentación de alto nivel y las rutas a los artefactos ejecutables que soportan a cada agente y dominio del proyecto. diff --git a/.github/agents/README.md b/.agent/agents/README.md similarity index 57% rename from .github/agents/README.md rename to .agent/agents/README.md index 8982d77a..943a8b43 100644 --- a/.github/agents/README.md +++ b/.agent/agents/README.md @@ -4,6 +4,74 @@ Este directorio contiene la definición de agentes especializados para automatiz ## Agentes Disponibles +### Agentes LLM por proveedor + +Estos agentes vinculan la planificación (`.agent/PLANS.md`), la configuración de credenciales y los scripts reutilizables cuando se trabaja con modelos específicos. + +#### ClaudeAgent + +- **Archivo**: `claude_agent.md` +- **Cuándo usarlo**: Cada vez que Claude (Anthropic) sea el proveedor principal. +- **Relaciones clave**: + - Configuración en `docs/ai/CONFIGURACION_API_KEYS.md` (`ANTHROPIC_API_KEY`). + - ExecPlan vivo: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. + - Scripts: `scripts/coding/ai/generators/llm_generator.py` (`llm_provider="anthropic"`) y `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. + - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` y `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`. + +#### ChatGPTAgent + +- **Archivo**: `chatgpt_agent.md` +- **Cuándo usarlo**: Para operaciones soportadas por modelos GPT de OpenAI. +- **Relaciones clave**: + - Configuración en `docs/ai/CONFIGURACION_API_KEYS.md` (`OPENAI_API_KEY`). + - ExecPlan: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. + - Scripts: `scripts/coding/ai/generators/llm_generator.py` (`llm_provider="openai"`) y `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. + - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` y `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`. + +#### HuggingFaceAgent + +- **Archivo**: `huggingface_agent.md` +- **Cuándo usarlo**: Para modelos locales/fine-tuned o integraciones Hugging Face. +- **Relaciones clave**: + - Configuración en `docs/ai/CONFIGURACION_API_KEYS.md` (`HF_LOCAL_MODEL_PATH`, `HF_MODEL_ID`, `HUGGINGFACEHUB_API_TOKEN`). + - ExecPlan: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. + - Scripts: `scripts/coding/ai/generators/llm_generator.py` (`llm_provider="huggingface"`) y `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. + - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md` y `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`. + +### Agentes por dominio + +Los siguientes agentes conectan la estructura del repositorio (api, ui, infrastructure, docs, scripts) con los ExecPlans y scripts multi-LLM. Cada ficha se encuentra en `.agent/agents/`. + +#### ApiAgent (Backend) + +- **Archivo**: `api_agent.md` +- **Directorio base**: `api/` +- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. + +#### UiAgent (Frontend) + +- **Archivo**: `ui_agent.md` +- **Directorio base**: `ui/` +- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md`, `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`. + +#### InfrastructureAgent + +- **Archivo**: `infrastructure_agent.md` +- **Directorio base**: `infrastructure/` +- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/gobernanza/metodologias/agentes_automatizacion.md`, planes `SPEC_INFRA_*`. + +#### DocsAgent + +- **Archivo**: `docs_agent.md` +- **Directorio base**: `docs/` +- **Relaciones clave**: `docs/analisis/AGENTS.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `scripts/coding/ai/agents/documentation/eta_codex_agent.py`, `docs/testing/test_documentation_alignment.py`. + +#### ScriptsAgent + +- **Archivo**: `scripts_agent.md` +- **Directorio base**: `scripts/` +- **Relaciones clave**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/scripts/README.md`, `scripts/coding/ai/generators/llm_generator.py`. + ### 1. GitOpsAgent **Archivo**: `gitops_agent.md` @@ -134,6 +202,31 @@ Genera reporte priorizado por severidad. --- +### 6. CodexMCPWorkflow Orchestrator + +**Archivo**: `codex_mcp_workflow.md` + +**Propósito**: Normalizar flujos Codex MCP single-agent y multi-agent en todos los proveedores LLM soportados. + +**Capacidades**: +- Genera briefs declarativos vía `CodexMCPWorkflowBuilder` (`scripts/coding/ai/orchestrators/codex_mcp_workflow.py`). +- Expone configuración del servidor MCP (`npx -y codex mcp`) y políticas de escritura (`approval-policy`, `sandbox`). +- Documenta gating de artefactos (`design/design_spec.md`, `frontend/index.html`, etc.) y observabilidad con Traces. +- Enlaza la guía completa [`docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`]. + +**Cuándo usar**: +- Ejecutar el ejemplo “Implement a fun new game!” o flujos similares en Claude, ChatGPT u orígenes Hugging Face. +- Coordinar un flujo multi-agente con Project Manager + especialistas y validar artefactos antes de cada handoff. +- Establecer la instrumentación de Traces y las variables de entorno antes de ejecuciones prolongadas. + +**Ejemplo**: +``` +CodexMCPWorkflow Orchestrator: Genera brief multi-agente para "Bug Busters" usando proveedor Anthropic. +Adjunta artefactos generados y traza resultante. +``` + +--- + ## Cómo Usar los Agentes ### Sintaxis General @@ -143,6 +236,12 @@ Genera reporte priorizado por severidad. [Parámetros opcionales] ``` +### Integración con plantillas de issues + +- Usa `.github/ISSUE_TEMPLATE/custom.md` para coordinar una ejecución asistida por agente. +- Las solicitudes de feature documentadas en `.github/ISSUE_TEMPLATE/feature_request.md` deben enlazar el ExecPlan activo y mencionar aquí qué agente participará. +- Los reportes de bug hacen referencia explícita a `SecurityAgent` y `DependencyAgent` para acelerar diagnósticos. + ### Ejemplos de Invocación **Ejemplo 1 - Operación Simple**: @@ -306,7 +405,7 @@ Para crear un nuevo agente especializado: - Un agente = una responsabilidad - Evitar agentes monolíticos -2. **Crear archivo en `.github/agents/[nombre]-agent.md`** +2. **Crear archivo en `.agent/agents/[nombre]_agent.md`** ```markdown --- name: [NombreAgente] @@ -374,6 +473,6 @@ Ver estadísticas en: `docs/qa/registros/metricas_agentes.md` (si existe) --- -**Última actualización**: 2025-11-05 -**Total de agentes**: 5 -**Versión de documentación**: 1.0.0 +**Última actualización**: 2025-11-06 +**Total de agentes**: 14 +**Versión de documentación**: 1.2.0 diff --git a/.agent/agents/api_agent.md b/.agent/agents/api_agent.md new file mode 100644 index 00000000..38bb1199 --- /dev/null +++ b/.agent/agents/api_agent.md @@ -0,0 +1,33 @@ +# ApiAgent + +## Propósito + +Guiar cualquier automatización relacionada con el backend (`api/`) asegurando que la planificación, la selección de LLMs y los scripts de soporte sigan los ExecPlans vigentes. ApiAgent actúa como punto de unión entre los agentes por proveedor y los runbooks de infraestructura de la API. + +## Integraciones Clave + +- **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md` (relación dominio ↔ agentes) y `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` (estrategia multi-LLM). +- **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` indica qué técnicas aplicar con Claude, ChatGPT u Hugging Face antes de generar especificaciones para la API. +- **Guías SDLC**: `docs/ai/SDLC_AGENTS_GUIDE.md` y `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` para coordinación multi-agente. +- **Scripts**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` (briefs de trabajo) y `scripts/coding/ai/generators/llm_generator.py` (TDD asistido). +- **Config**: variables en `.env` gestionadas por `scripts/coding/ai/shared/env_loader.py` (autodetección de `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `HUGGINGFACEHUB_API_TOKEN`). +- **Infraestructura API**: pipelines documentados en `infrastructure/` y runbooks en `docs/operaciones/`. + +## Procedimiento Recomendado + +1. **Planificación**: crea o actualiza el ExecPlan del cambio siguiendo `.agent/PLANS.md`. Referencia explícita al agente proveedor (ClaudeAgent, ChatGPTAgent, HuggingFaceAgent) que soportará la implementación. +2. **Selección de LLM**: usa `CodexMCPWorkflowBuilder` para generar briefs ajustados al proveedor elegido y habilita MCP si se requiere colaboración multi-agente. +3. **Desarrollo guiado por TDD**: + - Genera pruebas con `LLMGenerator` y `pytest` antes de modificar código en `api/`. + - Ejecuta suites específicas (`pytest api/tests` o equivalentes) tras cada iteración Red→Green→Refactor. +4. **Documentación**: actualiza el ExecPlan (`Progress`, `Decision Log`, `Surprises`) y registra resultados en `docs/qa/registros/`. +5. **Release**: coordina con `GitOpsAgent` o `ReleaseAgent` según corresponda para despliegues y tagging. + +## Validación + +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` +- `pytest scripts/coding/tests/ai/generators/test_llm_generator.py` +- `pytest docs/testing/test_documentation_alignment.py` +- Suites de backend (`pytest api/tests` o equivalentes definidos en el ExecPlan específico). + +ApiAgent garantiza que cada modificación al backend se ejecute con planificación trazable, soporte multi-LLM y validaciones consistentes con las políticas del repositorio. diff --git a/.agent/agents/chatgpt_agent.md b/.agent/agents/chatgpt_agent.md new file mode 100644 index 00000000..8fda5ede --- /dev/null +++ b/.agent/agents/chatgpt_agent.md @@ -0,0 +1,32 @@ +# ChatGPTAgent + +## Propósito + +Centralizar el uso de modelos ChatGPT/OpenAI dentro de los flujos de automatización del repositorio. ChatGPTAgent documenta los prerequisitos operativos y la relación entre planificación, scripts y guías cuando el proveedor seleccionado es OpenAI. + +## Integraciones Clave + +- **Configuración de credenciales**: `docs/ai/CONFIGURACION_API_KEYS.md` incluye los pasos para definir `OPENAI_API_KEY` y habilitar modos híbridos. +- **ExecPlan vivo**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` mantiene la estrategia multi-LLM y debe actualizarse cuando cambien las capacidades o defaults de OpenAI. +- **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` consolida las técnicas multi-LLM antes de personalizar prompts para ChatGPT. +- **Agente generador de tests**: `scripts/coding/ai/generators/llm_generator.py` soporta `llm_provider="openai"` para generar pruebas o documentación asistida con ChatGPT. +- **Builder MCP**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` emite briefs con banderas MCP y modelos recomendados (por ejemplo `gpt-5`) para OpenAI. +- **Guía operativa**: `docs/ai/SDLC_AGENTS_GUIDE.md` detalla cuándo alternar entre modos heurísticos y LLM. +- **Playbook MCP**: `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` explica la ejecución multi-agente para todos los proveedores, incluido OpenAI. + +## Procedimiento Recomendado + +1. **Planificación**: genera o actualiza el ExecPlan conforme a `.agent/PLANS.md` y registra en el issue qué agente ejecutará el trabajo. +2. **Preparación de entorno**: configura `OPENAI_API_KEY` en `.env` y verifica la auto-detección con `python3 scripts/coding/ai/shared/env_loader.py`. +3. **Ejecución**: + - Usa `LLMGenerator` para generación de tests con `llm_provider="openai"`. + - Para Codex MCP, alimenta los briefs de `CodexMCPWorkflowBuilder` indicando el proveedor `openai`. +4. **Gobernanza**: documenta resultados en `docs/qa/registros/` y sincroniza `Progress`, `Decision Log` y `Surprises` en el ExecPlan. + +## Validación + +- `pytest scripts/coding/tests/ai/generators/test_llm_generator.py` +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` +- `pytest docs/testing/test_documentation_alignment.py` + +ChatGPTAgent evita configuraciones inconsistentes al mantener alineados credenciales, planificación y herramientas cuando ChatGPT es el LLM elegido. diff --git a/.agent/agents/claude_agent.md b/.agent/agents/claude_agent.md new file mode 100644 index 00000000..807718ca --- /dev/null +++ b/.agent/agents/claude_agent.md @@ -0,0 +1,32 @@ +# ClaudeAgent + +## Propósito + +Orquestar las integraciones con modelos Claude (Anthropic) dentro del flujo SDLC del proyecto. ClaudeAgent sirve como punto de entrada documentado para cualquier actividad que requiera planificación (`.agent/PLANS.md`), generación automática de código o ejecución de flujos Codex MCP respaldados por modelos de Anthropic. + +## Integraciones Clave + +- **Configuración de credenciales**: `docs/ai/CONFIGURACION_API_KEYS.md` describe cómo declarar `ANTHROPIC_API_KEY` en `.env` y validar la detección automática del proveedor. +- **ExecPlan vivo**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` resume la estrategia multi-LLM y mantiene el historial de decisiones para Codex MCP. +- **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` reúne las técnicas multi-LLM recomendadas antes de diseñar prompts especializados para Claude. +- **Agente generador de tests**: `scripts/coding/ai/generators/llm_generator.py` soporta `llm_provider="anthropic"` y usa Claude como backend por defecto. +- **Builder MCP**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` genera briefs single/multi-agent asegurando banderas MCP correctas cuando el proveedor es Anthropic. +- **Guía operativa**: `docs/ai/SDLC_AGENTS_GUIDE.md` contiene los lineamientos de uso y compara el modo LLM vs heurístico. +- **Playbook MCP**: `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` documenta prerequisitos y trazas para todos los proveedores. + +## Procedimiento Recomendado + +1. **Planifica**: crea o actualiza un ExecPlan siguiendo `.agent/PLANS.md` y enlázalo desde el issue correspondiente. +2. **Configura el entorno**: completa la sección de Anthropic en `.env` y ejecuta `python3 scripts/coding/ai/shared/env_loader.py` para verificar la detección de Claude. +3. **Selecciona el flujo**: + - Para generación de tests o documentación asistida usa `LLMGenerator` con `llm_provider="anthropic"`. + - Para flujos MCP ejecuta los briefs construidos con `CodexMCPWorkflowBuilder` usando el proveedor `anthropic`. +4. **Evidencia y seguimiento**: captura resultados en `docs/qa/registros/` y actualiza el ExecPlan (`Progress`, `Decision Log`, `Outcomes`). + +## Validación + +- `pytest scripts/coding/tests/ai/generators/test_llm_generator.py` +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` +- `pytest docs/testing/test_documentation_alignment.py` + +ClaudeAgent garantiza que la documentación, la configuración y los flujos automatizados permanezcan alineados cada vez que Claude sea el LLM seleccionado. diff --git a/.agent/agents/codex_mcp_workflow.md b/.agent/agents/codex_mcp_workflow.md new file mode 100644 index 00000000..5a40ab69 --- /dev/null +++ b/.agent/agents/codex_mcp_workflow.md @@ -0,0 +1,39 @@ +# CodexMCPWorkflow Orchestrator + +## Propósito + +Establecer una interfaz declarativa para generar briefs de agentes basados en Codex MCP que funcionen de forma homogénea con Claude (Anthropic), ChatGPT (OpenAI) y modelos compatibles de Hugging Face. + +## Componentes Clave + +- **Builder Python**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` + - `server_config()` produce la configuración estándar del servidor MCP (`npx -y codex mcp`). + - `build_single_agent_brief()` genera el escenario "Implement a fun new game!" listo para ejecutar. + - `build_multi_agent_brief()` construye la coreografía Project Manager → Designer → Frontend/Backend → Tester con gating y trazas activadas. +- **Guía operativa**: `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` + - Detalla prerequisitos, variables de entorno y cómo conectar el builder con el Agents SDK. + - Documenta el uso de Traces según proveedor y los artefactos esperados (`design/design_spec.md`, `frontend/index.html`, etc.). +- **ExecPlan asociado**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` (mantener actualizado durante implementaciones). + +## Cuándo Invocarlo + +- Se requiere ejecutar flujos agenticos Codex que deben funcionar con más de un proveedor LLM. +- Se necesita demostrar trazabilidad (Traces) y gating de artefactos antes de promover handoffs automáticos. +- Se desea generar documentación reproducible (briefs + guía) para nuevas integraciones basadas en MCP. + +## Entradas + +- Proveedor (`openai`, `anthropic`, `huggingface`). +- Modelo opcional (si no se usa el default del builder). + +## Salidas + +- Diccionarios Python listos para usarse en scripts async (`server`, `agents`, `workflow`, `tracing`). +- Briefs que pueden serializarse a JSON/YAML para ejecutar en pipelines externos. + +## Validación + +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` +- `pytest docs/testing/test_documentation_alignment.py` + +Mantén esta ficha sincronizada con la guía y el ExecPlan cuando se añadan nuevos proveedores o roles. diff --git a/.github/agents/dependency_agent.md b/.agent/agents/dependency_agent.md similarity index 100% rename from .github/agents/dependency_agent.md rename to .agent/agents/dependency_agent.md diff --git a/.agent/agents/docs_agent.md b/.agent/agents/docs_agent.md new file mode 100644 index 00000000..236f30e2 --- /dev/null +++ b/.agent/agents/docs_agent.md @@ -0,0 +1,29 @@ +# DocsAgent + +## Propósito + +Garantizar que los cambios en `docs/` sigan la gobernanza del ETA-AGENTE CODEX y que la documentación permanezca alineada con los ExecPlans y agentes ejecutables. DocsAgent coordina con los agentes por proveedor para automatizar redacciones, manteniendo la traza con los validadores documentales. + +## Integraciones Clave + +- **Agente rector**: `docs/analisis/AGENTS.md` (ETA-AGENTE CODEX) y `scripts/coding/ai/agents/documentation/eta_codex_agent.py`. +- **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. +- **Pruebas**: `docs/testing/test_documentation_alignment.py` asegura consistencia de enlaces y ubicación. +- **Playbooks**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md`. + +## Procedimiento Recomendado + +1. **Planificación**: antes de modificar documentación, produce un ExecPlan y verifica las reglas del ETA-AGENTE CODEX. +2. **Automatización**: + - Usa `CodexMCPWorkflowBuilder` o `LLMGenerator` para preparar borradores siguiendo la sección "Planificación" del ExecPlan. + - Refuerza auto-CoT y Self-Consistency incorporando citas y validaciones que los tests puedan inspeccionar. +3. **Validadores**: ejecuta `pytest docs/testing/test_documentation_alignment.py` y, si aplica, pruebas asociadas a agentes (por ejemplo, `pytest scripts/coding/tests/ai/agents/documentation/test_eta_codex_agent.py`). +4. **Registro**: documenta hallazgos en el ExecPlan y añade referencias en índices (`docs/index.md`, `docs/ai/SDLC_AGENTS_GUIDE.md`) cuando corresponda. + +## Validación + +- `pytest docs/testing/test_documentation_alignment.py` +- `pytest scripts/coding/tests/ai/agents/documentation/test_eta_codex_agent.py` +- Otros tests específicos declarados en el ExecPlan (por ejemplo, validadores de enlaces o generadores de documentación). + +DocsAgent mantiene la documentación coherente con los agentes automatizados y con la política de revisiones consolidadas del proyecto. diff --git a/.github/agents/gitops_agent.md b/.agent/agents/gitops_agent.md similarity index 100% rename from .github/agents/gitops_agent.md rename to .agent/agents/gitops_agent.md diff --git a/.agent/agents/huggingface_agent.md b/.agent/agents/huggingface_agent.md new file mode 100644 index 00000000..0507c2f8 --- /dev/null +++ b/.agent/agents/huggingface_agent.md @@ -0,0 +1,36 @@ +# HuggingFaceAgent + +## Propósito + +Guiar el uso de modelos Hugging Face (locales o alojados) dentro de los pipelines del proyecto. HuggingFaceAgent cubre desde la configuración de modelos fine-tuned (p. ej. TinyLlama) hasta su participación en los flujos Codex MCP y generación de pruebas. + +## Integraciones Clave + +- **Configuración de entorno**: `docs/ai/CONFIGURACION_API_KEYS.md` detalla cómo definir rutas locales (`HF_LOCAL_MODEL_PATH`) o `HF_MODEL_ID` y cuándo se requiere `HUGGINGFACEHUB_API_TOKEN`. +- **ExecPlan vivo**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` mantiene la estrategia para balancear los tres proveedores y debe reflejar cualquier cambio en modelos Hugging Face. +- **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` consolida las técnicas multi-LLM que deben adaptarse antes de aplicar prompt engineering específico (p. ej. TinyLlama o Phi-3). +- **Agente generador de tests**: `scripts/coding/ai/generators/llm_generator.py` soporta `llm_provider="huggingface"` y permite reutilizar modelos QLoRA o checkpoints locales. +- **Builder MCP**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` expone defaults y banderas MCP al usar el proveedor `huggingface`. +- **Guías de capacidad**: + - `docs/ai/SDLC_AGENTS_GUIDE.md` explica cuándo preferir modos locales vs nube. + - `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md` y `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md` muestran patrones de prompting reutilizables. + - `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` unifica el procedimiento multi-agente. + +## Procedimiento Recomendado + +1. **Planificación**: crea o actualiza un ExecPlan conforme a `.agent/PLANS.md` antes de preparar experimentos o migraciones con modelos Hugging Face. +2. **Configuración de modelo**: + - Ajusta `.env` con rutas locales o `HF_MODEL_ID` según `docs/ai/CONFIGURACION_API_KEYS.md`. + - Si se utilizarán pesos fine-tuned, documenta su origen en el ExecPlan. +3. **Ejecución**: + - Usa `LLMGenerator` con `llm_provider="huggingface"` para generación de tests o snippets. + - Emplea `CodexMCPWorkflowBuilder` indicando el proveedor `huggingface` para validar flujos multi-agente. +4. **Registro**: captura resultados en `docs/qa/registros/` y mantén actualizado el `Decision Log` del ExecPlan con hallazgos de performance. + +## Validación + +- `pytest scripts/coding/tests/ai/generators/test_llm_generator.py` +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` +- `pytest docs/testing/test_documentation_alignment.py` + +HuggingFaceAgent facilita que los equipos adopten modelos locales manteniendo coherencia con la planificación y las herramientas compartidas del repositorio. diff --git a/.agent/agents/infrastructure_agent.md b/.agent/agents/infrastructure_agent.md new file mode 100644 index 00000000..ca8980b8 --- /dev/null +++ b/.agent/agents/infrastructure_agent.md @@ -0,0 +1,30 @@ +# InfrastructureAgent + +## Propósito + +Coordinar automatizaciones relacionadas con `infrastructure/`, incluyendo IaC, pipelines y configuración de entornos. InfrastructureAgent vincula la planificación ExecPlan con los agentes de dependencias, seguridad y despliegue para evitar desviaciones entre infraestructura y servicios consumidos por los LLMs. + +## Integraciones Clave + +- **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` y los planes específicos de infraestructura (`docs/plans/SPEC_INFRA_*.md`). +- **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` sirve como guía para seleccionar técnicas multi-LLM cuando la automatización afecta pipelines o servicios usados por los modelos. +- **Gobernanza**: `docs/gobernanza/metodologias/agentes_automatizacion.md` y runbooks en `docs/operaciones/`. +- **Agentes complementarios**: `DependencyAgent` para escaneos de paquetes, `ReleaseAgent` para coordinaciones de despliegue, `SecurityAgent` (si aplica) para hardening. +- **Scripts**: `scripts/infrastructure/` (si existe) y pipelines en `infrastructure/`. + +## Procedimiento Recomendado + +1. **Planificación**: registra en el ExecPlan cómo impactará el cambio en IaC, entornos y credenciales. Determina si se requiere coordinación multi-LLM (por ejemplo, despliegues de servicios MCP). +2. **Validación previa**: ejecuta `DependencyAgent` o `SecurityAgent` cuando haya cambios en toolchains, contenedores o runtime. +3. **Implementación**: + - Usa `CodexMCPWorkflowBuilder` para generar briefs que automaticen actualización de manifiestos o pipelines, asegurando que el sandbox MCP cuente con permisos apropiados. + - Mantén los archivos de configuración bajo control TDD mediante tests de `scripts/tests/` o validaciones específicas (por ejemplo, `terraform validate`, `ansible-lint`). +4. **Documentación**: actualiza ExecPlan y registra resultados en `docs/qa/registros/` indicando entornos afectados. + +## Validación + +- `pytest docs/testing/test_documentation_alignment.py` +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` +- Herramientas de IaC declaradas en el ExecPlan (`terraform validate`, `ansible-lint`, `kubectl diff`, etc.). + +InfrastructureAgent asegura que los cambios de infraestructura permanezcan sincronizados con la planificación multi-LLM y con las políticas de seguridad y gobernanza del repositorio. diff --git a/.github/agents/my_agent.md b/.agent/agents/my_agent.md similarity index 100% rename from .github/agents/my_agent.md rename to .agent/agents/my_agent.md diff --git a/.github/agents/release_agent.md b/.agent/agents/release_agent.md similarity index 100% rename from .github/agents/release_agent.md rename to .agent/agents/release_agent.md diff --git a/.agent/agents/scripts_agent.md b/.agent/agents/scripts_agent.md new file mode 100644 index 00000000..d622a566 --- /dev/null +++ b/.agent/agents/scripts_agent.md @@ -0,0 +1,31 @@ +# ScriptsAgent + +## Propósito + +Orquestar cambios en `scripts/` garantizando que las automatizaciones, generadores y validadores permanezcan sincronizados con los ExecPlans multi-LLM y con las pruebas de regresión. ScriptsAgent sirve como guía para extender herramientas CLI, validadores y pipelines internos. + +## Integraciones Clave + +- **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. +- **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` para seleccionar estrategias multi-LLM antes de automatizar generadores o validadores. +- **Código**: `scripts/coding/ai/` (generators, orchestrators, shared utilities) y `scripts/tests/`. +- **Pruebas**: `pytest scripts/coding/tests/...` y `pytest scripts/tests/...`. +- **Documentación**: `docs/scripts/README.md`, `docs/scripts/SCRIPTS_MATRIX.md` y `docs/operaciones/verificar_servicios.md`. + +## Procedimiento Recomendado + +1. **Planificación**: identifica en el ExecPlan qué scripts serán modificados/creados, qué agentes los consumirán y qué cobertura de pruebas se requiere. +2. **Implementación TDD**: + - Redacta pruebas en `scripts/coding/tests/...` antes de modificar los scripts correspondientes. + - Usa `LLMGenerator` cuando se necesiten esbozos iniciales, siempre asegurando iteraciones Red→Green→Refactor. +3. **Orquestación multi-LLM**: utiliza `CodexMCPWorkflowBuilder` para generar briefs que coordinen agentes y aseguren políticas MCP (`approval-policy`, `sandbox`). +4. **Documentación**: registra nuevas utilidades en `docs/scripts/README.md` y en la matriz de scripts. Actualiza ExecPlan y `docs/qa/registros/` con resultados de pruebas. + +## Validación + +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` +- `pytest scripts/coding/tests/ai/generators/test_llm_generator.py` +- `pytest docs/testing/test_documentation_alignment.py` +- Otras suites específicas (`pytest scripts/tests/test_*.py`, `bash scripts/tests/...`). + +ScriptsAgent asegura que la carpeta `scripts/` evolucione con disciplina TDD, manteniendo alineada la automatización interna con los agentes y ExecPlans vigentes. diff --git a/.github/agents/security_agent.md b/.agent/agents/security_agent.md similarity index 100% rename from .github/agents/security_agent.md rename to .agent/agents/security_agent.md diff --git a/.agent/agents/ui_agent.md b/.agent/agents/ui_agent.md new file mode 100644 index 00000000..7cee780e --- /dev/null +++ b/.agent/agents/ui_agent.md @@ -0,0 +1,31 @@ +# UiAgent + +## Propósito + +Alinear el trabajo automatizado sobre el frontend (`ui/`) con las prácticas de diseño, pruebas y despliegue descritas en nuestros ExecPlans y guías de prompting. UiAgent sirve como guía única para combinar planificación, generación asistida de código y validaciones de experiencia de usuario. + +## Integraciones Clave + +- **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md` y `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. +- **Playbooks**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md` y `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`. +- **Orquestación**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` (multi-agente) y `scripts/coding/ai/generators/llm_generator.py` (generación guiada por TDD). +- **Documentación UX**: briefs y wireframes creados por el Designer Agent se ubican en `docs/` o `design/` según el ExecPlan activo. + +## Procedimiento Recomendado + +1. **Planificación**: crea ExecPlan conforme a `.agent/PLANS.md` identificando componentes UI afectados y experimentos a realizar (por ejemplo, wireframes asistidos por LLM). +2. **Diseño + Desarrollo**: + - Coordina con Designer Agent para obtener `design_spec.md` y wireframes. + - Usa `CodexMCPWorkflowBuilder` con `llm_provider` correspondiente para producir briefs que generen HTML/CSS/JS siguiendo las especificaciones. + - Aplica TDD generando pruebas end-to-end o unitarias con `LLMGenerator` si procede. +3. **Pruebas visuales**: registra capturas o instrucciones en `docs/qa/registros/` y, si el cambio es visual, adjunta evidencia conforme a la política de screenshots. +4. **Documentación**: actualiza ExecPlan (`Progress`, `Decision Log`) y enlaza resultados desde `docs/ai/SDLC_AGENTS_GUIDE.md` si se introduce un nuevo patrón. + +## Validación + +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` +- `pytest scripts/coding/tests/ai/generators/test_llm_generator.py` +- `pytest docs/testing/test_documentation_alignment.py` +- Suites front-end (`npm test`, `pnpm vitest`, etc.) según el stack declarado en el ExecPlan. + +UiAgent permite mantener el frontend consistente con las guías de diseño, asegurando que la colaboración multi-LLM se refleje en entregables reproducibles y probados. diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..4230a10a --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,36 @@ +--- +name: "Reporte de bug" +about: "Documenta un incidente reproducible y su impacto" +title: "[Bug]: " +labels: [bug] +assignees: [] +--- + +## Resumen + +Describe el problema observado y el componente afectado. + +## Pasos para reproducir + +1. ... +2. ... +3. ... + +## Resultado esperado + +Explica qué debería ocurrir. + +## Evidencia + +Adjunta logs, capturas o trazas relevantes. + +## Validaciones previas + +- [ ] He ejecutado `./scripts/run_all_tests.sh --skip-frontend` +- [ ] He revisado los pasos en `docs/operaciones/verificar_servicios.md` +- [ ] He invocado `SecurityAgent: Ejecuta auditoría completa de seguridad.` cuando aplica +- [ ] He verificado dependencias recientes (`DependencyAgent`) si el fallo ocurre tras una actualización + +## Contexto adicional + +Agrega información sobre feature flags, versiones o migraciones recientes. diff --git a/.github/ISSUE_TEMPLATE/custom.md b/.github/ISSUE_TEMPLATE/custom.md new file mode 100644 index 00000000..88169072 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/custom.md @@ -0,0 +1,25 @@ +--- +name: "Solicitud asistida por agente" +about: "Coordina una acción con los agentes definidos en el repositorio" +title: "[Agente]: " +labels: [automation] +assignees: [] +--- + +Usa este template cuando necesites que un agente documentado en `.agent/agents/README.md` ejecute una tarea específica. + +## Agente objetivo + +Indica el agente (por ejemplo, `GitOpsAgent`, `ReleaseAgent`, `SecurityAgent`). + +## Instrucción para el agente + +Escribe el prompt exacto que debe ejecutarse. + +## Entradas y outputs esperados + +Detalla archivos de entrada, rutas de trabajo y métricas esperadas. + +## Evidencias + +Cuando el agente finalice, adjunta logs, reportes o artefactos producidos. diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..fe03373c --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,39 @@ +--- +name: "Solicitud de feature" +about: "Propón una mejora o nueva capacidad" +title: "[Feature]: " +labels: [enhancement] +assignees: [] +--- + +## Contexto y motivación + +Describe la necesidad del usuario y el impacto esperado. + +## Resultado observable + +Indica qué podrá hacer la persona usuaria tras implementar la feature y cómo se valida. + +## Alcance + +Enumera módulos, scripts o servicios que se tocarán. + +## ExecPlan requerido + +Antes de iniciar cualquier desarrollo: + +- [ ] He generado o actualizado un ExecPlan siguiendo `.agent/PLANS.md` +- Ruta del ExecPlan: `docs/plans/...` o enlace equivalente +- Resumen del estado actual del ExecPlan: _incluye progreso, decisiones y validaciones planeadas_ + +## Coordinación con agentes + +Si necesitas apoyo autónomo, referencia el agente adecuado desde `.agent/agents/README.md`. + +## Dependencias y riesgos + +Lista integraciones externas, migraciones o datos que podrían afectar el trabajo. + +## Métricas de aceptación + +Describe pruebas, comandos o evidencias que demuestran que la feature está completa. diff --git a/.github/workflows/code-quality.yml b/.github/workflows/code-quality.yml new file mode 100644 index 00000000..609409b3 --- /dev/null +++ b/.github/workflows/code-quality.yml @@ -0,0 +1,29 @@ +name: Code Quality Baseline + +on: + pull_request: + types: [opened, synchronize, reopened] + workflow_dispatch: + +jobs: + smoke-checks: + runs-on: ubuntu-latest + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: '3.11' + + - name: Install minimal dependencies + run: | + python -m pip install --upgrade pip + if [ -f requirements.txt ]; then pip install -r requirements.txt; fi + pip install pytest + + - name: Run repository smoke validations + run: | + ./scripts/run_all_tests.sh --skip-backend --skip-ui --skip-security || true + pytest docs/testing/test_documentation_alignment.py diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 00000000..13fe9557 --- /dev/null +++ b/.github/workflows/codeql.yml @@ -0,0 +1,39 @@ +name: CodeQL + +on: + push: + branches: [main, develop] + pull_request: + branches: [main, develop] + schedule: + - cron: '0 3 * * 1' + +jobs: + analyze: + name: CodeQL Analysis + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: ['python'] + + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Initialize CodeQL + uses: github/codeql-action/init@v3 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v3 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3 + with: + category: '/language:${{ matrix.language }}' diff --git a/.github/workflows/dependency-review.yml b/.github/workflows/dependency-review.yml new file mode 100644 index 00000000..1c951acc --- /dev/null +++ b/.github/workflows/dependency-review.yml @@ -0,0 +1,23 @@ +name: Dependency Review + +on: + pull_request: + types: [opened, synchronize, reopened] + +jobs: + review: + runs-on: ubuntu-latest + permissions: + contents: read + pull-requests: write + security-events: write + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Dependency review + uses: actions/dependency-review-action@v4 + with: + fail-on-severity: moderate + allow-licenses: MIT,Apache-2.0,BSD-2-Clause,BSD-3-Clause + comment-summary-in-pr: true diff --git a/AGENTS.md b/AGENTS.md new file mode 100644 index 00000000..3b647928 --- /dev/null +++ b/AGENTS.md @@ -0,0 +1,3 @@ +# ExecPlans + +When writing complex features or significant refactors, produce an ExecPlan (as described in `.agent/PLANS.md`) before making code changes. Reference the plan during implementation and keep it updated as a living document. diff --git a/README.md b/README.md index f3e518de..3121949d 100644 --- a/README.md +++ b/README.md @@ -6,6 +6,8 @@ Repositorio monolítico para la plataforma de analítica de centros de contacto > > **Leyenda**: [IMPLEMENTADO] = Funciona actualmente | [PLANIFICADO] = Documentado pero pendiente | [ATENCION] = Requiere atención | [NO] = Prohibido +> **Importante**: No existe un Makefile en la raíz; usa los scripts documentados para orquestar tareas. + ## Estado actual del repositorio ### [IMPLEMENTADO] Implementado @@ -50,9 +52,9 @@ Repositorio monolítico para la plataforma de analítica de centros de contacto vagrant up # Levanta PostgreSQL:15432 y MariaDB:13306 ``` -4. **Verificar servicios** ([IMPLEMENTADO] Runbook disponible, [PLANIFICADO] script automatizado pendiente): +4. **Verificar servicios** ([IMPLEMENTADO] Runbook + script): - Guía manual: [`docs/operaciones/verificar_servicios.md`](docs/operaciones/verificar_servicios.md) - - Script automatizado: `./scripts/verificar_servicios.sh` ([PLANIFICADO] Pendiente de implementar) + - Script automatizado: `./scripts/verificar_servicios.sh` (`--dry-run` disponible para CI) ## Flujo de desarrollo @@ -76,6 +78,18 @@ DB_IVR_USER=django_user DB_IVR_PASSWORD=django_pass ``` +> **LLMs soportados**: Los agentes SDLC detectan automáticamente el mejor proveedor +> disponible entre Claude (Anthropic), ChatGPT (OpenAI) y modelos fine-tuned vía +> Hugging Face (TinyLlama, Phi-3, etc.). Consulta +> [`docs/ai/CONFIGURACION_API_KEYS.md`](docs/ai/CONFIGURACION_API_KEYS.md) +> para declarar `ANTHROPIC_API_KEY`, `OPENAI_API_KEY` o las variables +> `HF_LOCAL_MODEL_PATH`/`HF_MODEL_ID` cuando ejecutes el flujo de fine-tuning +> documentado en [`docs/ai/FINE_TUNING_TINYLLAMA.md`](docs/ai/FINE_TUNING_TINYLLAMA.md), y +> revisa el playbook de prompting con Phi-3 en +> [`docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`](docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md). +> Para técnicas de prompting transversales a todos los proveedores revisa el catálogo +> multi-LLM en [`docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`](docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md). + ### 2. Ejecutar migraciones ```bash @@ -146,7 +160,7 @@ pytest -c docs/pytest.ini docs/testing - Complejidad ciclomática: <= 10 - MTTR para bugs críticos: <= 2 días -**Estado actual**: Las métricas se calculan manualmente. Ver [`logs_data/SCHEMA.md`](logs_data/SCHEMA.md) +**Estado actual**: Las métricas se generan con [`scripts/dora_metrics.py`](scripts/dora_metrics.py) (baseline local). Ver [`logs_data/SCHEMA.md`](logs_data/SCHEMA.md) ### Workflow de commits @@ -155,12 +169,19 @@ pytest -c docs/pytest.ini docs/testing 3. **Evita `--no-verify`**: Si un hook falla, corrígelo en lugar de saltearlo 4. **Coverage mínimo**: 80% en módulos Python modificados +### Gestión de issues y agentes + +- Plantillas disponibles en `.github/ISSUE_TEMPLATE/` guían la información mínima para bugs, features y solicitudes asistidas. +- Las solicitudes de feature exigen un ExecPlan conforme a `.agent/PLANS.md` y enlazan el documento vivo correspondiente. +- Para coordinar automatizaciones revisa `.agent/agents/README.md` y selecciona el agente adecuado (GitOps, Release, Security, etc.). + ### Guías y estándares ([IMPLEMENTADO] Documentadas) - **[Guía de Estilo](docs/gobernanza/GUIA_ESTILO.md)** - Convenciones obligatorias (NO emojis, Conventional Commits) - **[Procedimiento de Desarrollo Local](docs/gobernanza/procesos/procedimientos/procedimiento_desarrollo_local.md)** - Setup detallado - **[Guía Completa de Desarrollo de Features](docs/gobernanza/procesos/procedimientos/guia_completa_desarrollo_features.md)** - Proceso end-to-end - **[Estrategia de QA](docs/gobernanza/procesos/qa/ESTRATEGIA_QA.md)** - Testing strategy +- **[Codex MCP Multi-Agent Guide](docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md)** - Configura el `CodexMCPWorkflowBuilder` para flujos single/multi-agent en Claude, ChatGPT y Hugging Face. ## Arquitectura y Stack diff --git a/docs/ai/CONFIGURACION_API_KEYS.md b/docs/ai/CONFIGURACION_API_KEYS.md index 15f69950..1dbdbd78 100644 --- a/docs/ai/CONFIGURACION_API_KEYS.md +++ b/docs/ai/CONFIGURACION_API_KEYS.md @@ -48,13 +48,18 @@ OPENAI_API_KEY=sk-... # Ollama (local, opcional) OLLAMA_BASE_URL=http://localhost:11434 +# Hugging Face (modelos locales fine-tuned, opcional) +HF_LOCAL_MODEL_PATH=/models/TinyLlama-1.1B-qlora +# HF_MODEL_ID=TinyLlama/TinyLlama-1.1B-Chat-v1.0 +# HF_GENERATE_KWARGS={"max_new_tokens":512,"temperature":0.2} + # Presupuesto mensual en USD LLM_MONTHLY_BUDGET=100 # Habilitar optimización ENABLE_COST_OPTIMIZATION=true -# Proveedor preferido: "auto", "anthropic", "openai", "ollama" +# Proveedor preferido: "auto", "anthropic", "openai", "ollama", "huggingface" PREFER_LLM_PROVIDER=auto ``` @@ -150,7 +155,25 @@ PREFER_LLM_PROVIDER=ollama - Más lento que APIs cloud - Calidad variable según modelo -### Opción 5: Sin LLM (Solo Heurísticas) +### Opción 5: Hugging Face (Modelos Fine-Tuned) + +```bash +# .env +HF_LOCAL_MODEL_PATH=/models/TinyLlama-1.1B-qlora +PREFER_LLM_PROVIDER=huggingface +``` + +**Ventajas:** +- Ejecuta modelos entrenados específicamente para el dominio +- No requiere enviar datos a proveedores externos si el modelo es local +- Permite integrar pipelines como TinyLlama QLoRA + DPO (ver guía de fine-tuning) + +**Desventajas:** +- Necesitas descargar el modelo (~4GB+) y dependencias de `transformers` +- Performance depende del hardware disponible (GPU recomendada) +- Debes gestionar actualizaciones y almacenamiento de checkpoints manualmente + +### Opción 6: Sin LLM (Solo Heurísticas) ```bash # .env diff --git a/docs/ai/FINE_TUNING_TINYLLAMA.md b/docs/ai/FINE_TUNING_TINYLLAMA.md new file mode 100644 index 00000000..34d6eede --- /dev/null +++ b/docs/ai/FINE_TUNING_TINYLLAMA.md @@ -0,0 +1,278 @@ +# Fine-tuning de TinyLlama con QLoRA + DPO + +Esta guía resume el cuaderno de referencia **Chapter 12 - Fine-tuning Generation Models** para +acoplar un modelo TinyLlama entrenado localmente dentro del ecosistema de agentes SDLC. + +Se cubre un flujo en dos etapas: + +1. **Supervised Fine-Tuning (SFT)** utilizando QLoRA en precisión de 4 bits. +2. **Preference Optimization (DPO)** para alinear el modelo con respuestas preferidas. + +El resultado final se integra mediante el nuevo `llm_provider="huggingface"` que expone el +checkpoint directamente a `LLMGenerator` y al resto de agentes. + +--- + +## 1. Preparar el entorno + +Requisitos mínimos: + +- GPU con soporte CUDA (T4 o superior) o entornos equivalentes (AWS g5, GCP A2, etc.). +- Drivers y `nvidia-smi` operativos. +- Python 3.10+. + +Instalar dependencias clave (coinciden con el notebook de referencia): + +```bash +pip install \ + accelerate==0.31.0 \ + bitsandbytes==0.43.1 \ + peft==0.11.1 \ + transformers==4.41.2 \ + trl==0.9.4 \ + sentencepiece==0.2.0 \ + triton==3.1.0 +``` + +> **Sugerencia:** en Google Colab seleccionar `Runtime > Change runtime type > GPU > T4`. + +Opcionalmente configurar `HF_TOKEN` si se descargan modelos privados. + +--- + +## 2. Preprocesar datos (UltraChat 200k) + +```python +from transformers import AutoTokenizer +from datasets import load_dataset + +template_tokenizer = AutoTokenizer.from_pretrained("TinyLlama/TinyLlama-1.1B-Chat-v1.0") + +def format_prompt(example): + chat = example["messages"] + prompt = template_tokenizer.apply_chat_template(chat, tokenize=False) + return {"text": prompt} + +dataset = ( + load_dataset("HuggingFaceH4/ultrachat_200k", split="test_sft") + .shuffle(seed=42) + .select(range(3_000)) +) +dataset = dataset.map(format_prompt) +``` + +Se emplea la plantilla de TinyLlama para mantener coherencia de tokens y roles +(`<|user|>`, `<|assistant|>`). Esta estructura es la misma que consumen los +agentes cuando utilizan el proveedor `huggingface`. + +--- + +## 3. Cargar TinyLlama con cuantización 4-bit + +```python +from transformers import AutoModelForCausalLM, AutoTokenizer, BitsAndBytesConfig + +model_name = "TinyLlama/TinyLlama-1.1B-intermediate-step-1431k-3T" + +bnb_config = BitsAndBytesConfig( + load_in_4bit=True, + bnb_4bit_quant_type="nf4", + bnb_4bit_compute_dtype="float16", + bnb_4bit_use_double_quant=True, +) + +model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map="auto", + quantization_config=bnb_config, +) +model.config.use_cache = False +model.config.pretraining_tp = 1 + +tokenizer = AutoTokenizer.from_pretrained(model_name) +tokenizer.pad_token = "" +tokenizer.padding_side = "left" +``` + +La cuantización de 4 bits reduce memoria y permite entrenar modelos de 1B +parámetros en una sola GPU T4. + +--- + +## 4. Configurar QLoRA + +```python +from peft import LoraConfig, prepare_model_for_kbit_training, get_peft_model + +peft_config = LoraConfig( + lora_alpha=32, + lora_dropout=0.1, + r=64, + bias="none", + task_type="CAUSAL_LM", + target_modules=['k_proj','gate_proj','v_proj','up_proj','q_proj','o_proj','down_proj'] +) + +model = prepare_model_for_kbit_training(model) +model = get_peft_model(model, peft_config) +``` + +--- + +## 5. Entrenar con `SFTTrainer` + +```python +from transformers import TrainingArguments +from trl import SFTTrainer + +training_arguments = TrainingArguments( + output_dir="./results", + per_device_train_batch_size=2, + gradient_accumulation_steps=4, + optim="paged_adamw_32bit", + learning_rate=2e-4, + lr_scheduler_type="cosine", + num_train_epochs=1, + logging_steps=10, + fp16=True, + gradient_checkpointing=True +) + +trainer = SFTTrainer( + model=model, + train_dataset=dataset, + dataset_text_field="text", + tokenizer=tokenizer, + args=training_arguments, + max_seq_length=512, + peft_config=peft_config, +) + +trainer.train() +trainer.model.save_pretrained("TinyLlama-1.1B-qlora") +``` + +Se guardan los pesos LoRA en `TinyLlama-1.1B-qlora/`. + +--- + +## 6. Mezclar adaptadores + +```python +from peft import AutoPeftModelForCausalLM + +model = AutoPeftModelForCausalLM.from_pretrained( + "TinyLlama-1.1B-qlora", + low_cpu_mem_usage=True, + device_map="auto", +) +merged_model = model.merge_and_unload() +``` + +Este merge produce un checkpoint listo para inferencia SFT (`merged_model`). + +--- + +## 7. Ajuste por preferencias (DPO) + +1. Formatear dataset DPO (`argilla/distilabel-intel-orca-dpo-pairs`) usando la misma + plantilla TinyLlama (`<|system|>`, `<|user|>`, `<|assistant|>`). +2. Cargar el modelo SFT cuantizado. +3. Aplicar LoRA con la misma configuración. +4. Entrenar con `DPOTrainer`: + +```python +from trl import DPOTrainer, DPOConfig + +training_arguments = DPOConfig( + output_dir="./results", + per_device_train_batch_size=2, + gradient_accumulation_steps=4, + optim="paged_adamw_32bit", + learning_rate=1e-5, + lr_scheduler_type="cosine", + max_steps=200, + logging_steps=10, + fp16=True, + gradient_checkpointing=True, + warmup_ratio=0.1 +) + +dpo_trainer = DPOTrainer( + model, + args=training_arguments, + train_dataset=dpo_dataset, + tokenizer=tokenizer, + peft_config=peft_config, + beta=0.1, + max_prompt_length=512, + max_length=512, +) + +dpo_trainer.train() +dpo_trainer.model.save_pretrained("TinyLlama-1.1B-dpo-qlora") +``` + +5. Unir los adaptadores SFT + DPO y generar el checkpoint final para inferencia. + +--- + +## 8. Inferencia + +```python +from transformers import pipeline + +prompt = """<|user|>\nTell me something about Large Language Models.\n<|assistant|>\n""" + +pipe = pipeline( + task="text-generation", + model="/ruta/al/checkpoint/dpo_merge", + tokenizer=tokenizer, +) +print(pipe(prompt, max_new_tokens=256, temperature=0.2)[0]["generated_text"]) +``` + +--- + +## 9. Integrar con el proveedor `huggingface` + +1. Guardar el checkpoint final (por ejemplo `TinyLlama-1.1B-dpo-merged`). +2. Actualizar `.env`: + +```bash +PREFER_LLM_PROVIDER=huggingface +HF_LOCAL_MODEL_PATH=/models/TinyLlama-1.1B-dpo-merged +HF_GENERATE_KWARGS={"max_new_tokens":512,"temperature":0.2} +``` + +3. Configurar los agentes con: + +```python +config = { + "llm_provider": "huggingface", + "model": "/models/TinyLlama-1.1B-dpo-merged", + "hf_generate_kwargs": {"max_new_tokens": 512, "temperature": 0.2}, + "use_llm": True +} +``` + +Los tests unitarios (`test_llm_generator.py`) verifican que el generador de +pruebas consuma Hugging Face mediante el nuevo método `_call_huggingface`. + +--- + +## 10. Buenas prácticas + +- Versionar únicamente los adaptadores (`TinyLlama-1.1B-qlora`, `TinyLlama-1.1B-dpo-qlora`) + y almacenar el merge final en artefactos (por peso). +- Registrar métricas clave: pérdida SFT, recompensa DPO, evaluación manual. +- Mantener una GPU dedicada para entrenamiento; la inferencia puede ejecutarse en CPU + con menor throughput. +- Documentar cualquier cambio en hiperparámetros dentro de `docs/ai/FINE_TUNING_TINYLLAMA.md`. + +--- + +Con estos pasos se habilita un tercer modelo especializado que complementa +las integraciones existentes (Claude y GPT). El `llm_provider="huggingface"` +permite reutilizar directamente los checkpoints fine-tuned en los agentes SDLC, +manteniendo trazabilidad completa desde el dataset hasta la inferencia. diff --git a/docs/ai/SDLC_AGENTS_GUIDE.md b/docs/ai/SDLC_AGENTS_GUIDE.md index a28c21cb..76d755b6 100644 --- a/docs/ai/SDLC_AGENTS_GUIDE.md +++ b/docs/ai/SDLC_AGENTS_GUIDE.md @@ -83,6 +83,32 @@ ollama pull qwen2.5-coder:32b **Pros:** Gratis, privado, sin límites de uso **Cons:** Requiere hardware (32GB+ RAM recomendado), más lento que APIs cloud +### Opción 4: Hugging Face (Modelos Fine-Tuned) + +```python +config = { + "llm_provider": "huggingface", + "model": "/models/TinyLlama-1.1B-qlora", # ruta local o repo-id + "hf_generate_kwargs": {"max_new_tokens": 512, "temperature": 0.2}, + "use_llm": True +} + +# Dependencias mínimas +pip install transformers==4.41.2 accelerate==0.31.0 peft==0.11.1 bitsandbytes==0.43.1 trl==0.9.4 + +# Los checkpoints descritos en la guía de fine-tuning viven en docs/ai/FINE_TUNING_TINYLLAMA.md +``` + +**Pros:** +- Permite ejecutar modelos entrenados específicamente para nuestro dominio (TinyLlama QLoRA + DPO) +- Mantiene los datos en infraestructura propia +- Integración directa con el nuevo `llm_provider='huggingface'` + +**Cons:** +- Requiere GPU con soporte CUDA o aceleradores equivalentes para tiempos razonables +- Necesita administrar los checkpoints y merges de LoRA manualmente +- Mayor complejidad operativa comparado con API SaaS + ### Modo Sin LLM (Solo Heurísticas) ```python @@ -98,6 +124,28 @@ config = { ## Agentes Disponibles +### Agentes por proveedor LLM + +Para asegurar coherencia entre planificación, credenciales y herramientas, consulta las fichas específicas en `.agent/agents/`: + +- **ClaudeAgent** (`.agent/agents/claude_agent.md`): describe el flujo completo cuando `llm_provider="anthropic"`, enlazando el catálogo `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, la configuración de `ANTHROPIC_API_KEY`, el uso del `LLMGenerator` y las orquestaciones Codex MCP de `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. +- **ChatGPTAgent** (`.agent/agents/chatgpt_agent.md`): guía las integraciones con modelos GPT/OpenAI, combina el catálogo `PROMPT_TECHNIQUES_CATALOG.md` con `OPENAI_API_KEY` y referencia `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. +- **HuggingFaceAgent** (`.agent/agents/huggingface_agent.md`): centraliza el trabajo con modelos locales o alojados en Hugging Face, relacionando `PROMPT_TECHNIQUES_CATALOG.md`, rutas (`HF_LOCAL_MODEL_PATH`, `HF_MODEL_ID`) y playbooks específicos (`PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`). + +Estas fichas son complementarias a esta guía y deben revisarse antes de ejecutar tareas multi-LLM. + +### Agentes por dominio + +Para alinear la arquitectura del repositorio con los agentes automatizados, consulta también las fichas por dominio en `.agent/agents/`: + +- **ApiAgent** (`api_agent.md`): centraliza la coordinación del backend (`api/`) con los ExecPlans `EXECPLAN_agents_domain_alignment.md`, `EXECPLAN_codex_mcp_multi_llm.md`, el catálogo `PROMPT_TECHNIQUES_CATALOG.md` y los briefs generados por `CodexMCPWorkflowBuilder`. +- **UiAgent** (`ui_agent.md`): une los entregables del Designer Agent con la implementación en `ui/`, reutilizando los playbooks de prompting (`PROMPT_TECHNIQUES_CATALOG.md`, `CODE_GENERATION_GUIDE.md`, `PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`). +- **InfrastructureAgent** (`infrastructure_agent.md`): orquesta cambios en `infrastructure/` en conjunto con los agentes operativos (Dependency, Release, Security), el catálogo `PROMPT_TECHNIQUES_CATALOG.md` y los planes `SPEC_INFRA_*`. +- **DocsAgent** (`docs_agent.md`): asegura que toda modificación en `docs/` respete al ETA-AGENTE CODEX, el catálogo `PROMPT_TECHNIQUES_CATALOG.md` y los validadores de documentación. +- **ScriptsAgent** (`scripts_agent.md`): gobierna la evolución de `scripts/` manteniendo el enfoque TDD, el catálogo `PROMPT_TECHNIQUES_CATALOG.md` y la sincronización con los generadores/orquestadores LLM. + +Cada vez que inicies un ExecPlan nuevo, referencia tanto la ficha del proveedor LLM como la del dominio involucrado para mantener la trazabilidad completa. + ### 1. SDLCFeasibilityAgent **Propósito:** Evalúa la viabilidad técnica de una feature antes de implementarla. diff --git a/docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md b/docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md new file mode 100644 index 00000000..a3f945b1 --- /dev/null +++ b/docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md @@ -0,0 +1,173 @@ +# Codex MCP Multi-Agent Workflows + +Esta guía consolida los patrones compartidos para ejecutar flujos con Codex CLI como servidor MCP usando los tres proveedores LLM soportados por el proyecto (Claude/Anthropic, ChatGPT/OpenAI y modelos locales Hugging Face). El objetivo es que cualquier colaborador pueda preparar el entorno, configurar agentes y observar sus trazas sin duplicar esfuerzos para cada proveedor. + +## 1. Prerrequisitos + +- Familiaridad básica con Python o JavaScript. +- Un IDE con soporte para agentes (VS Code, Cursor, JetBrains Gateway). +- Claves de API según el proveedor elegido: + - `OPENAI_API_KEY` para ChatGPT. + - `ANTHROPIC_API_KEY` para Claude. + - `HUGGINGFACEHUB_API_TOKEN` opcional para modelos hospedados en Hugging Face (los checkpoints locales no lo requieren). +- Node.js 18+ para ejecutar `npx codex`. +- Dependencias del SDK: + ```bash + pip install openai-agents openai + ``` + +### Estructura de `.env` + +``` +OPENAI_API_KEY=sk-... +ANTHROPIC_API_KEY=anthropic-... +HUGGINGFACEHUB_API_TOKEN=hf-... +``` + +Solo es necesario definir la variable correspondiente al proveedor activo. + +## 2. Inicializar Codex CLI como servidor MCP + +Todos los flujos comparten la misma configuración base del servidor MCP. El módulo `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` expone `CodexMCPWorkflowBuilder`, que entrega esta configuración en forma declarativa. + +```python +from scripts.coding.ai.orchestrators import CodexMCPWorkflowBuilder + +builder = CodexMCPWorkflowBuilder("openai") # o "anthropic", "huggingface" +server_cfg = builder.server_config() +``` + +El builder produce el diccionario: + +```python +{ + "command": "npx", + "args": ["-y", "codex", "mcp"], + "client_session_timeout_seconds": 360000, +} +``` + +Este bloque puede pasarse directamente a `MCPServerStdio` del Agents SDK: + +```python +from agents.mcp import MCPServerStdio + +async with MCPServerStdio(**server_cfg) as codex_mcp_server: + ... +``` + +## 3. Flujos single-agent + +El builder genera un brief con dos agentes (`designer` y `developer`) que encapsula el ejemplo de “Implement a fun new game!”. + +```python +single_agent = builder.build_single_agent_brief() +``` + +Elementos destacados: + +- `provider` y `model` incluyen los valores por defecto para el proveedor actual (`gpt-4.1`, `claude-3-5-sonnet-20241022`, `TinyLlama/TinyLlama-1.1B-Chat-v1.0`). +- El agente `developer` incorpora las banderas MCP obligatorias: `"approval-policy": "never"` y `"sandbox": "workspace-write"`. +- `required_env` devuelve las variables de entorno necesarias para el proveedor. + +Uso básico con el SDK: + +```python +from agents import Agent, Runner + +brief = builder.build_single_agent_brief() + +developer_agent = Agent( + name=brief["agents"]["developer"]["name"], + instructions=brief["agents"]["developer"]["instructions"], + mcp_servers=[codex_mcp_server], +) + +designer_agent = Agent( + name=brief["agents"]["designer"]["name"], + instructions=brief["agents"]["designer"]["instructions"], + model=brief["model"], + handoffs=[developer_agent], +) + +await Runner.run(designer_agent, brief["runner"]["task"]) +``` + +## 4. Orquestación multi-agente con gating + +Para flujos más largos se utiliza `build_multi_agent_brief()`: + +```python +multi_agent = builder.build_multi_agent_brief() +``` + +Este brief define cinco roles: + +- `project_manager`: crea REQUIREMENTS.md, TEST.md y AGENT_TASKS.md, y controla el avance mediante handoffs. +- `designer`: genera `design/design_spec.md` y `wireframe.md`. +- `frontend_developer`: crea `frontend/index.html`, `styles.css` y `game.js`. +- `backend_developer`: prepara `backend/package.json` y `server.js`. +- `tester`: documenta `tests/TEST_PLAN.md` y un script opcional. + +Cada agente incluye la política MCP para escritura y devuelve el control al Project Manager. El brief también expone `workflow["gate_checks"]` para validar que los artefactos existen antes de continuar: + +```python +for gate in multi_agent["workflow"]["gate_checks"]: + assert Path(gate["artifact"]).exists() +``` + +El Project Manager implementa el gating mediante strings como `transfer_to_designer_agent`, `transfer_to_frontend_developer_agent`, etc., replicando la coreografía descrita en la guía original. + +### Task list incorporado + +`workflow["task"]` contiene un backlog textual que los agentes pueden usar como referencia (objetivo “Bug Busters”, endpoints del backend, restricciones de simplicidad, etc.). + +## 5. Observabilidad con Traces + +El brief multi-agente activa observabilidad por defecto: + +```python +multi_agent["tracing"] == { + "enabled": True, + "notes": "Enable OpenAI Traces (or Anthropic/Hugging Face equivalents) ..." +} +``` + +Cada proveedor maneja sus trazas: + +| Proveedor | Herramienta sugerida | Notas | +|-----------|----------------------|-------| +| OpenAI | [OpenAI Traces](https://platform.openai.com/docs/guides/reports/traces) | Visualiza prompts, herramientas y transferencias. | +| Anthropic | Panel de sesiones Claude | Registrar `client_session_timeout_seconds` amplio para ejecuciones largas. | +| Hugging Face | Logging local + `hf` callbacks | Útil cuando se ejecutan checkpoints locales sin telemetría externa. | + +## 6. Relación con `.agent` + +- El catálogo `.agent/agents/README.md` documenta el **Codex MCP Workflow Orchestrator** y enlaza a esta guía. +- Los issues de tipo feature deben adjuntar el ExecPlan relevante (`docs/plans/EXECPLAN_codex_mcp_multi_llm.md`) para mantener la trazabilidad. +- Las plantillas de bug report/custom issues reenvían al catálogo de agentes para seleccionar quién ejecutará el flujo MCP. + +## 7. Validación automática + +`CodexMCPWorkflowBuilder` cuenta con pruebas en `scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` que cubren: + +- Presencia de banderas MCP en el brief single-agent. +- Declaración de variables de entorno por proveedor. +- Gatekeeping de artefactos y activación de trazas en el brief multi-agente. + +Ejecuta las pruebas con: + +```bash +pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py +``` + +## 8. Checklist rápido + +1. Configura `.env` con la API key del proveedor. +2. Instala `openai-agents` y `openai` en tu entorno de trabajo. +3. Inicializa `MCPServerStdio` usando `builder.server_config()`. +4. Obtén el brief single o multi-agente según el alcance. +5. Verifica que los artefactos de `gate_checks` existan antes de continuar con el siguiente handoff. +6. Revisa las trazas para depurar comportamientos y retroalimentar el ExecPlan. + +Con esta guía, los flujos Codex MCP quedan normalizados para todos los modelos LLM soportados, alineando documentación, agentes y pruebas automatizadas. diff --git a/docs/ai_capabilities/prompting/AGENTIC_SYSTEM_PATTERNS.md b/docs/ai_capabilities/prompting/AGENTIC_SYSTEM_PATTERNS.md new file mode 100644 index 00000000..5d5b19e9 --- /dev/null +++ b/docs/ai_capabilities/prompting/AGENTIC_SYSTEM_PATTERNS.md @@ -0,0 +1,132 @@ +# Agentic System Patterns and Best Practices + +> **Status:** Production notes based on 2024-2025 delivery work with enterprise teams building LLM-driven agents. + +Over the last year we have partnered with dozens of product and platform groups that deploy large language model (LLM) agents. The most reliable launches did **not** depend on heavyweight frameworks. Instead, they composed simple patterns, measured continuously, and only increased complexity when it demonstrably improved outcomes. This guide distills those lessons into reusable building blocks for the team. + +## What are agents? + +"Agent" can mean different things across organizations. Some customers describe fully autonomous systems that run for long periods, chaining multiple tools. Others use the term for guided automations with well-defined workflows. We treat both as *agentic systems* but distinguish between: + +- **Workflows:** Predefined code paths where LLM calls and tools are orchestrated deterministically. +- **Agents:** Systems where the LLM dynamically decides which tools to call, how to sequence them, and when to request human input. + +Understanding the distinction helps choose the lightest design that still meets business goals. + +## When (and when not) to use agents + +Start with the simplest possible solution. Multi-step agents consume more tokens, add latency, and can compound mistakes. Prefer single LLM calls augmented with retrieval or examples unless you have evidence that autonomy increases success rates. + +Escalate to workflows or agents when: + +- Fixed sequences (workflows) improve accuracy by decomposing a task into verifiable steps. +- Dynamic orchestration (agents) is necessary because the number or nature of subtasks cannot be known upfront. +- Human oversight remains available for checkpoints, fallbacks, or escalation. + +## When and how to use frameworks + +Frameworks such as LangGraph, Amazon Bedrock Agents, Rivet, or Vellum simplify the basics—issuing calls, defining tools, chaining steps. They accelerate prototypes but introduce abstraction layers that can hide prompts and responses, making debugging harder. + +Our recommendations: + +1. **Prototype directly with the API first.** Many orchestration patterns require fewer than 50 lines of code. +2. **Audit framework assumptions.** Misunderstanding tool schemas or execution order is a common failure mode. +3. **Collapse abstractions when moving to production.** Prefer transparent, composable components over magical orchestration. + +Refer to the project cookbook for minimal examples that can be adapted without vendor lock-in. + +## Building blocks, workflows, and agents + +### Building block: The augmented LLM + +Modern agents start with an LLM enhanced with retrieval, tools, and memory. Each model invocation should have: + +```text +[Augmented LLM] +├── Retrieval (domain documents, knowledge bases) +├── Tooling (APIs, code execution, search) +├── Memory (session context, persistent logs) +└── Policies (guardrails, stopping criteria) +``` + +Tailor augmentations to the use case and provide a clear interface that the model can reliably follow—rich descriptions, explicit parameters, and concrete examples. + +### Workflow: Prompt chaining + +Prompt chaining decomposes work into a deterministic series of LLM calls, optionally inserting programmatic gates that validate intermediate artifacts. + +Use it when tasks naturally split into predictable steps—for example, generate marketing copy, review it, translate it. The trade-off is higher latency in exchange for higher accuracy through focused subtasks. + +### Workflow: Routing + +Routing classifies user intent and directs it to specialized prompts, tools, or even different models. This isolates domain-specific instructions and lets you deploy cost-effective models for easy requests while reserving powerful models for complex cases. + +### Workflow: Parallelization + +Parallelization runs multiple LLM calls simultaneously. Two common variants: + +- **Sectioning:** Independent subtasks processed in parallel. +- **Voting:** Multiple attempts at the same task whose outputs are compared or aggregated. + +Choose this when subtasks are independent or when diversity of answers improves confidence (e.g., vulnerability scanning with multiple reviewers). + +### Workflow: Orchestrator-workers + +An orchestrator LLM breaks down goals into subtasks dynamically and assigns them to worker LLMs. Unlike prompt chaining, the number of steps and required tools emerges from the input. This is useful for large code edits or investigative research where the scope is unknown at the start. + +### Workflow: Evaluator-optimizer + +One LLM proposes a solution while another critiques it. The loop continues until quality thresholds are met or iteration limits are reached. This mirrors human editorial processes and works when evaluation criteria are clear (translation quality, document completeness, etc.). + +### Agents: Autonomous execution + +Agents combine planning, tool use, and memory in a loop that continues until completion criteria or stop conditions trigger. Key practices: + +- Ground each step with tool feedback (e.g., execution logs, API responses). +- Define checkpoints for human review or early termination. +- Budget tokens and time, enforcing maximum iterations to avoid runaway costs. + +Autonomy suits problems where the number of steps cannot be hardcoded—complex coding tasks, investigative research, or support workflows that require branching conversations plus actions. + +## Combining and customizing patterns + +Patterns are composable. For instance, a routing stage can dispatch to either a prompt chain or an orchestrator-worker agent. Measure each addition; remove complexity that does not move success metrics. Instrument latency, cost, and quality so you can decide objectively when extra orchestration is justified. + +## Summary: Principles for reliable agents + +1. **Stay simple.** Only add autonomy when single-call prompts fail to hit targets. +2. **Expose the plan.** Make the agent's reasoning and steps transparent for debuggability. +3. **Engineer the agent-computer interface (ACI).** Treat tool definitions like UI design—clear parameters, examples, and safeguards. + +## Appendix 1 – Agents in practice + +### Customer support + +Customer support blends conversational flows with actions such as fetching order data or issuing refunds. Agent fit indicators include: + +- Tool integrations for CRM, order history, and knowledge bases. +- Programmatic actions with clear success criteria (ticket updates, refund execution). +- Natural opportunities for human oversight when escalations are required. + +Successful teams often price agents by resolved ticket to align incentives with outcome quality. + +### Coding agents + +Software engineering is a high-leverage domain because: + +- Automated tests provide objective ground truth for correctness. +- Agents can iterate using test failures as feedback. +- The problem space is structured, letting the agent plan modifications precisely. + +Benchmarks such as SWE-bench Verified show agents solving real GitHub issues from pull request descriptions, but human review still ensures architectural alignment and non-functional requirements. + +## Appendix 2 – Prompt engineering your tools + +Tool definitions deserve the same rigor as prompts. + +1. **Select ergonomic formats.** Prefer representations the model has seen frequently (markdown over JSON for code) and avoid error-prone requirements such as manual diff headers. +2. **Provide rich docstrings.** Include examples, edge cases, and parameter semantics so the LLM understands how and when to use each tool. +3. **Test and iterate.** Observe tool usage in the workbench, then refine descriptions to prevent recurring mistakes. +4. **Poka-yoke critical operations.** Shape parameters so that invalid combinations are impossible or obvious (e.g., enforce absolute file paths to avoid path drift). + +Expect to invest heavily here—optimizing tools often delivers larger gains than tuning the top-level prompt. Treat tool UX as a first-class part of the agent architecture. diff --git a/docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md b/docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md new file mode 100644 index 00000000..cd73a6a4 --- /dev/null +++ b/docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md @@ -0,0 +1,193 @@ +# Generating Code with Chat-Based Models + +> **Status:** This section is under development; examples and assets will continue to evolve as the prompting playbook matures. + +Modern AI agents that specialize in code generation depend on three tightly coupled capabilities: deliberate planning, precise tool utilization, and effective memory systems. The interplay among these pillars determines how reliably an agent can translate prompts into executable code. + +```text +[Agent Components] +├── Planning (LLM-driven reasoning) +│ ├─ Task decomposition with chain-of-thought prompts +│ ├─ Self-reflection on previous steps and retrieved facts +│ ├─ Adaptive learning to refine future prompts +│ └─ Critical analysis of partial progress +├── Tool Utilization (environment interaction) +│ ├─ Select interpreters, linters, debuggers, and deployment hooks +│ ├─ Decide when and how to execute external tools +│ ├─ Automate validation with test harnesses or static analyzers +│ └─ Capture quantitative evidence from each execution +└── Memory Systems (context management) + ├─ Short-term buffers that maintain instructions and intermediate code + ├─ Long-term stores (vector DBs, knowledge bases) for reuse + ├─ Fast retrieval of historical experiments or regressions + └─ Consolidation of lessons learned for future sessions +``` + +## Planning: The Brain of the Agent + +Large language models (LLMs) provide the reasoning substrate for planning. In practice, planning workflows for code-oriented agents rely on: + +- Chain-of-thought task decomposition that keeps generation steps auditable. +- Self-reflection loops to detect drift and restate goals as needed. +- Adaptive prompts that incorporate lessons from prior successes or failures. +- Critical analysis of intermediate outputs (diffs, logs, failing tests) before continuing. + +While LLM planning remains imperfect, skipping this layer usually results in brittle automation that fails on non-trivial tasks. + +## Tool Utilization: Extending the Agent's Reach + +Planning alone cannot modify repositories or run programs. Agents need robust interfaces to tools such as: + +- Shell or notebook interpreters to execute generated code. +- Unit-test runners, static analyzers, and linters for validation. +- Web or documentation search utilities to retrieve domain knowledge. +- Auxiliary systems (e.g., diagram generators, dataset loaders) to satisfy complex prompts. + +The LLM must decide **when** a tool is necessary, **how** to format the invocation, and **how** to interpret results before continuing with the plan. + +## Memory Systems: Retaining and Reusing Context + +Two complementary memory layers keep the agent grounded: + +1. **Short-term (working) memory** retains the immediate conversation, task list, and partial code snippets. It powers in-context learning and prevents the agent from repeating work within a session. +2. **Long-term memory** stores embeddings, vectorized notes, or structured metadata so that the agent can recall prior experiments, architectural decisions, or known pitfalls across sessions. + +Balancing both memories allows iterative improvement and reduces the chance of reintroducing old defects. + +--- + +# Prompt Patterns for Code Generation + +The examples below assume a chat-oriented interface (e.g., OpenAI Playground) using the `gpt-3.5-turbo` family with a system prompt such as: + +``` +You are a helpful code assistant that can teach a junior developer how to code. Your language of choice is Python. Don't explain the code, just generate the code block itself. +``` + +## Basic Example + +A minimal user prompt can request a short script: + +``` +Write code that asks the user for their name and say "Hello" +``` + +The assistant returns a working snippet that greets the user. Even in simple scenarios, verify the generated code locally to confirm it runs as expected. + +## Turn Comments into Code + +LLMs can translate structured comments into full implementations: + +*Prompt* +``` +""" +1. Create a list of movies +2. Create a list of ratings for these movies +3. Combine them to make a json object of 10 movies with their ratings. +""" +``` + +*Output* +```python +movies = ["The Shawshank Redemption", "The Godfather", "The Dark Knight", "Schindler's List", "Pulp Fiction", "The Lord of the Rings: The Return of the King", "Forrest Gump", "Star Wars: Episode V - The Empire Strikes Back", "Inception", "The Silence of the Lambs"] + +ratings = [9.3, 9.2, 9.0, 8.9, 8.9, 8.9, 8.8, 8.7, 8.7, 8.6] + +movie_ratings = {} + +for i in range(len(movies)): + movie_ratings[movies[i]] = ratings[i] + +json_object = json.dumps(movie_ratings, indent=4) + +print(json_object) +``` + +Always review the output—here the model omitted `import json`. Running automated linters or tests helps catch these gaps immediately. + +## Complete Functions or Next Lines + +Autocomplete workflows (e.g., GitHub Copilot) let an agent finish partially written functions: + +*Prompt* +```python +# function to multiply two numbers and add 75 to it + +def multiply( +``` + +*Output* +```python +a, b): + result = a * b + result += 75 + return result +``` + +Review spacing, naming, and typing to ensure the completion aligns with project standards. + +## MySQL Query Generation + +Providing schema context enables SQL generation: + +*Prompt* +``` +""" +Table departments, columns = [DepartmentId, DepartmentName] +Table students, columns = [DepartmentId, StudentId, StudentName] +Create a MySQL query for all students in the Computer Science department +""" +``` + +*Output* +```mysql +SELECT students.StudentId, students.StudentName +FROM students +INNER JOIN departments +ON students.DepartmentId = departments.DepartmentId +WHERE departments.DepartmentName = 'Computer Science'; +``` + +You can extend the session to scaffold the test environment: + +- Request a schema definition for both tables. +- Ask for sample `INSERT` statements to populate fixture data. +- Execute the generated SQL in a scratch database (e.g., SQLite) to validate the query. + +## Explain Code + +Be mindful of the active system message. If the agent is constrained to generate Python code, clarifying that explanations are acceptable avoids conflicts. + +*Prompt* +```mysql +SELECT students.StudentId, students.StudentName +FROM students +INNER JOIN departments +ON students.DepartmentId = departments.DepartmentId +WHERE departments.DepartmentName = 'Computer Science'; + +Explain the above SQL statement. +``` + +*Output* +``` +Sorry, as a code assistant in Python, I cannot generate SQL code. However, I can explain the purpose of the SQL statement provided. + +This SQL statement selects the `StudentId` and `StudentName` columns from the `students` table, where the `DepartmentName` column in the `departments` table is equal to 'Computer Science'. To achieve this, the statement performs an inner join on the `DepartmentId` column between the `students` and `departments` tables. + +In simpler terms, it is selecting the names and IDs of students who are enrolled in the Computer Science department. +``` + +Adjusting the system message to explicitly permit explanations prevents the assistant from warning about role constraints. + +## Editing Code + +Content to be determined—track pending examples for refactoring workflows and collaborative edits. + +## Debugging Code + +Content forthcoming. Document representative debugging prompts (log analysis, failing tests, or stack traces) once validated. + +## Best Practices + +Pending consolidation. Capture lessons learned about prompt structure, validation pipelines, and automated guardrails as they become repeatable. diff --git a/docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md b/docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md new file mode 100644 index 00000000..4b06126c --- /dev/null +++ b/docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md @@ -0,0 +1,186 @@ +# Prompt Engineering con Phi-3 Mini + +Guía de integración para aprovechar el notebook de referencia **Chapter 6 - Prompt Engineering** +utilizando el modelo `microsoft/Phi-3-mini-4k-instruct`. Complementa las capacidades actuales +del proyecto (Claude + ChatGPT + modelos Hugging Face) con un flujo reproducible para +experimentar localmente con Phi-3, sin perder alineación con los agentes SDLC. + +--- + +## 1. Preparación del entorno + +- **Hardware recomendado:** GPU con 16 GB (T4, RTX 4090, etc.) o CPU x86_64 con AVX2. +- **Dependencias base:** + +```bash +pip install \ + langchain>=0.1.17 \ + openai>=1.13.3 \ + langchain_openai>=0.1.6 \ + transformers>=4.40.1 \ + datasets>=2.18.0 \ + accelerate>=0.27.2 \ + sentence-transformers>=2.5.1 \ + duckduckgo-search>=5.2.2 + +CMAKE_ARGS="-DLLAMA_CUBLAS=on" pip install llama-cpp-python +``` + +- **Credenciales:** no se requieren API keys para descargar Phi-3 desde Hugging Face, pero es + recomendable configurar `HF_TOKEN` si se accede a repositorios privados. +- **GPU en Colab:** `Runtime > Change runtime type > Hardware accelerator > GPU > T4`. + +El ecosistema del proyecto seguirá prefiriendo `PREFER_LLM_PROVIDER=auto`, pero al declarar +`PREFER_LLM_PROVIDER=huggingface` + `HF_MODEL_ID=microsoft/Phi-3-mini-4k-instruct`, el +`LLMGenerator` cargará este modelo para escenarios offline o de laboratorio. + +--- + +## 2. Carga del modelo + +```python +import torch +from transformers import AutoModelForCausalLM, AutoTokenizer, pipeline + +model_name = "microsoft/Phi-3-mini-4k-instruct" + +model = AutoModelForCausalLM.from_pretrained( + model_name, + device_map="cuda", # usar "auto" en CPU o multi-GPU + torch_dtype="auto", + trust_remote_code=False, +) + +tokenizer = AutoTokenizer.from_pretrained(model_name) + +pipe = pipeline( + task="text-generation", + model=model, + tokenizer=tokenizer, + return_full_text=False, + max_new_tokens=500, + do_sample=False, +) +``` + +- `return_full_text=False` mantiene la salida sin duplicar el prompt. +- `max_new_tokens` controla el tamaño de la respuesta; ajústalo según presupuesto de tokens. +- El pipeline puede moverse a CPU fijando `device_map="cpu"` con la penalización de latencia + esperada. + +--- + +## 3. Plantilla de chat de Phi-3 + +```python +messages = [ + {"role": "user", "content": "Create a funny joke about chickens."} +] + +prompt = pipe.tokenizer.apply_chat_template(messages, tokenize=False) +print(prompt) +# <|user|>\nCreate a funny joke about chickens.<|end|>\n<|assistant|>\n +``` + +- Phi-3 usa delimitadores `<|user|>`, `<|assistant|>`, `<|end|>` y un prefijo ``. +- Respetar la plantilla evita desalineaciones cuando se alterna entre Claude / ChatGPT / + Hugging Face en los agentes multi-modelo. + +--- + +## 4. Control de temperatura y Top-p + +```python +pipe(messages, do_sample=True, temperature=1.0) +pipe(messages, do_sample=True, top_p=1.0) +``` + +- `temperature` alto aumenta diversidad; `top_p` regula la probabilidad acumulada. +- Para reproducibilidad en validaciones automáticas se recomienda `do_sample=False`, + `temperature=0` y `top_p=0.9` o inferior. + +--- + +## 5. Componentes clave del prompt + +```python +persona = "You are an expert in Large Language Models...\n" +instruction = "Summarize the key findings...\n" +context = "Your summary should extract the most crucial points...\n" +formatting = "Create a bullet-point summary...\n" +audience = "The summary is designed for busy researchers...\n" +tone = "The tone should be professional and clear.\n" + +query = persona + instruction + context + formatting + audience + tone +messages = [{"role": "user", "content": query}] +``` + +- Mantener cada capa (persona, instrucción, contexto, formato, audiencia, tono) permite que el + agente `PromptTemplateEngine` combine fragmentos reutilizables. +- Documentar estos bloques facilita portar el prompt entre Claude (Anthropic), GPT-4o (OpenAI) + y Phi-3 (Hugging Face) sin pérdida de intención. + +--- + +## 6. Patrones de prompting cubiertos + +| Técnica | Ejemplo Phi-3 | Uso recomendado | +| --- | --- | --- | +| **Zero-shot** | Pedir resumen directo | Consultas rápidas | +| **One-shot** | Proveer una muestra de JSON | Uniformar formato | +| **Few-shot** | Varias instrucciones/respuestas | Calibrar estilo | +| **In-context learning** | Palabras inventadas (Gigamuru, screeg) | Sintaxis específicas | +| **Chain-of-thought (CoT)** | Resolver aritmética paso a paso | QA y debugging | +| **Zero-shot CoT** | Añadir `Let's think step-by-step` | Preguntas de control | +| **Tree-of-thought (ToT)** | Simular expertos colaborativos | Evaluaciones complejas | +| **Chain prompting** | Nombre → Pitch | Copywriting multi-etapa | +| **Output verification** | JSON válido con `response_format` | Validadores automáticos | +| **Grammar constraints** | `llama_cpp` con `response_format={"type": "json_object"}` | Forzar esquemas | + +Cada técnica puede orquestarse desde los agentes existentes: + +- `PromptChaining` (scripts/ai/agents/base/structuring_techniques.py). +- `TreeOfThoughtsAgent` y `SelfConsistencyAgent` para razonamiento. +- `HybridSearchOptimization` para seleccionar prompts según dominio. + +--- + +## 7. Integración con los 3 proveedores + +| Proveedor | Variable `.env` | Caso de uso | +| --- | --- | --- | +| **Anthropic (Claude)** | `ANTHROPIC_API_KEY` | Análisis críticos, refactors | +| **OpenAI (ChatGPT)** | `OPENAI_API_KEY` | Tutores interactivos, QA | +| **Hugging Face (Phi-3/TinyLlama)** | `HF_MODEL_ID` o `HF_LOCAL_MODEL_PATH` | Laboratorios, entornos aislados | + +- El `EnvLoader` ya detecta automáticamente el proveedor activo; esta guía describe cómo + provisionar Phi-3 para cubrir el tercer pilar documentado en el README. +- Para notebooks experimentales puede usarse `llama_cpp` con el checkpoint GGUF publicado + por Microsoft (`microsoft/Phi-3-mini-4k-instruct-gguf`). + +--- + +## 8. Buenas prácticas operativas + +1. **Reutiliza plantillas:** centraliza las piezas del prompt en `PromptTemplateEngine` y evita + duplicación de cadenas literales. +2. **Versiona ejemplos:** guarda las variaciones de few-shot en el repositorio para comparar + resultados entre LLMs. +3. **Evalúa regresiones:** usa `SelfConsistencyAgent` con 3 rutas (Claude, GPT, Phi-3) y + compara convergencia ≥ 0.85 antes de promover prompts a producción. +4. **Controla costos:** en entornos cloud prioriza Claude/GPT solo cuando Phi-3 no alcanza el + criterio de calidad definido. +5. **Valida outputs:** mantén pruebas de `docs/testing/test_documentation_alignment.py` para + asegurar que los manuales y scripts estén sincronizados. + +--- + +## 9. Referencias adicionales + +- Notebook original: *Hands-On Large Language Models – Chapter 6: Prompt Engineering*. +- Documentación oficial de Phi-3: [https://huggingface.co/microsoft/Phi-3-mini-4k-instruct](https://huggingface.co/microsoft/Phi-3-mini-4k-instruct) +- Guía de agentes multi-LLM: [`docs/ai/SDLC_AGENTS_GUIDE.md`](../SDLC_AGENTS_GUIDE.md) +- Playbook de fine-tuning TinyLlama (para comparar flujos): [`../FINE_TUNING_TINYLLAMA.md`](../FINE_TUNING_TINYLLAMA.md) + +Esta guía asegura que el tercer modelo documentado (Phi-3) cuente con un playbook oficial y +alineado a las prácticas de prompting del proyecto. diff --git a/docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md b/docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md new file mode 100644 index 00000000..6cea7193 --- /dev/null +++ b/docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md @@ -0,0 +1,219 @@ +# Catálogo Completo de Técnicas de Prompts multi-LLM + +Este catálogo unifica las técnicas de prompting aplicables a los tres proveedores soportados por el proyecto (Claude, ChatGPT y Hugging Face) y funciona como referencia canónica para los agentes descritos en `.agent/agents/` y los planes activos `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` y `docs/plans/EXECPLAN_agents_domain_alignment.md`. Cada sección indica cómo reutilizar la técnica dentro del flujo SDLC y enlaza con los dominios Backend (API), Frontend (UI), Infrastructure, Docs y Scripts cuando existen lineamientos específicos. + +> **Uso operativo:** Los agentes de dominio (ApiAgent, UiAgent, InfrastructureAgent, DocsAgent, ScriptsAgent) y los agentes por proveedor (ClaudeAgent, ChatGPTAgent, HuggingFaceAgent) deben enlazar a este catálogo para seleccionar la estrategia de prompting adecuada antes de invocar los orquestadores (`scripts/coding/ai/orchestrators/codex_mcp_workflow.py`) o los generadores (`scripts/coding/ai/generators/llm_generator.py`). + +## 1. Técnicas de In-Context Learning (ICL) + +### 1.1 Few-Shot Prompting +- **Few-Shot Prompting**: paradigma donde el LLM aprende la tarea con pocos ejemplos. +- **K-Nearest Neighbor (KNN)**: selecciona ejemplos similares al caso actual. +- **Vote-K**: preserva diversidad mientras se eligen ejemplos parecidos. +- **Self-Generated In-Context Learning (SG-ICL)**: genera ejemplos automáticamente. +- **Prompt Mining**: descubre formulaciones intermedias óptimas a partir de corpus. +- **LENS**: aplica filtrado iterativo para refinar ejemplos. +- **UDR**: combina embeddings y recuperación. +- **Active Example Selection**: usa refuerzo para escoger ejemplos. + +### 1.2 Zero-Shot Prompting +- **Role Prompting**: asigna un rol o persona al modelo. +- **Style Prompting**: controla estilo, tono o género del resultado. +- **Emotion Prompting**: incorpora frases con carga emocional. +- **System 2 Attention (S2A)**: elimina información irrelevante del prompt. +- **SimToM**: restringe el conocimiento usado por el modelo. +- **Rephrase and Respond (RaR)**: obliga a reformular y luego responder. +- **Re-reading (RE2)**: añade instrucciones para releer la pregunta. +- **Self-Ask**: decide si es necesario pedir información adicional. + +## 2. Técnicas de Generación de Pensamientos + +### 2.1 Chain-of-Thought (CoT) +- **Chain-of-Thought Prompting**: fomenta la explicitación del razonamiento paso a paso. + +### 2.2 Zero-Shot CoT +- **Zero-Shot Chain-of-Thought**: CoT sin ejemplos. +- **Step-Back Prompting**: primero formula una pregunta de alto nivel. +- **Analogical Prompting**: genera ejemplos análogos con cadenas de pensamiento. +- **Thread-of-Thought (ThoT)**: mejora el inductor de pensamiento para CoT. +- **Tabular Chain-of-Thought (Tab-CoT)**: representa razonamiento en tablas Markdown. + +### 2.3 Few-Shot CoT +- **Contrastive CoT Prompting**: combina explicaciones correctas e incorrectas. +- **Uncertainty-Routed CoT**: muestrea múltiples rutas de razonamiento. +- **Complexity-based Prompting**: usa ejemplos complejos como entrenamiento. +- **Active Prompting**: solicita a humanos reescribir ejemplos inciertos. +- **Memory-of-Thought**: reutiliza datos no etiquetados. +- **Automatic Chain-of-Thought (Auto-CoT)**: genera cadenas de pensamiento automáticamente. + +## 3. Técnicas de Descomposición + +- **Least-to-Most Prompting**: divide un problema en subproblemas. +- **Decomposed Prompting (DECOMP)**: muestra cómo usar funciones específicas. +- **Plan-and-Solve Prompting**: versión mejorada de Zero-Shot CoT. +- **Tree-of-Thought (ToT)**: explora soluciones como un árbol. +- **Recursion-of-Thought**: delega subproblemas complejos a otros prompts. +- **Program-of-Thoughts**: traduce el problema a código ejecutable. +- **Faithful Chain-of-Thought**: mezcla razonamiento natural con símbolos. +- **Skeleton-of-Thought**: acelera mediante paralelización. +- **Metacognitive Prompting**: simula procesos metacognitivos humanos. + +## 4. Técnicas de Ensembling + +- **Demonstration Ensembling (DENSE)**: crea múltiples prompts few-shot. +- **Mixture of Reasoning Experts (MoRE)**: agrupa expertos de razonamiento diversos. +- **Max Mutual Information Method**: combina plantillas y ejemplos variados. +- **Self-Consistency**: genera varias rutas y escoge la respuesta coherente. +- **Universal Self-Consistency**: usa prompting para elegir la respuesta mayoritaria. +- **Meta-Reasoning over Multiple CoTs**: agrega múltiples cadenas de razonamiento. +- **DiVeRSe**: produce varios prompts para el mismo problema. +- **Consistency-based Self-adaptive Prompting (COSP)**: genera prompts Few-Shot CoT. +- **Universal Self-Adaptive Prompting (USP)**: generaliza COSP. +- **Prompt Paraphrasing**: reescribe el prompt original para variar formulaciones. + +## 5. Técnicas de Auto-Crítica + +- **Self-Calibration**: pregunta al modelo si su respuesta es correcta. +- **Self-Refine**: itera respuesta y retroalimentación. +- **Reversing Chain-of-Thought (RCoT)**: reconstruye el problema desde la respuesta. +- **Self-Verification**: genera múltiples soluciones candidatas. +- **Chain-of-Verification (COVE)**: crea preguntas de verificación. +- **Cumulative Reasoning**: acumula pasos potenciales antes de resolver. + +## 6. Técnicas Multilingües + +### 6.1 Prompting General Multilingüe +- **Translate First Prompting**: traduce primero al inglés. + +### 6.2 Chain-of-Thought Multilingüe +- **XLT (Cross-Lingual Thought) Prompting**: seis instrucciones coordinadas. +- **Cross-Lingual Self Consistent Prompting (CLSP)**: ensemble multilingüe. + +### 6.3 In-Context Learning Multilingüe +- **X-InSTA Prompting**: alinea ejemplos en contexto. +- **In-CLT (Cross-lingual Transfer) Prompting**: usa idioma fuente y destino. + +### 6.4 Selección de Ejemplos en Contexto +- **PARC**: recupera ejemplos desde un idioma de alto recurso. +- **Semantically-Aligned Examples**: elige ejemplos cercanos semánticamente. +- **Semantically-Distant Examples**: usa ejemplos disímiles para robustez. + +### 6.5 Traducción Automática +- **Multi-Aspect Prompting and Selection (MAPS)**: imita traducción humana. +- **Chain-of-Dictionary (CoD)**: lista significados de palabras clave. +- **Dictionary-based Prompting for MT (DiPMT)**: enfoque basado en diccionarios. +- **Decomposed Prompting for MT (DecoMT)**: divide el texto en fragmentos. +- **Interactive-Chain-Prompting (ICP)**: maneja ambigüedades mediante diálogo. +- **Iterative Prompting**: involucra humanos durante la traducción. + +## 7. Técnicas Multimodales + +### 7.1 Prompting de Imágenes +- **Prompt Modifiers**: modificadores que alteran la imagen generada. +- **Negative Prompting**: pondera términos a evitar. +- **Paired-Image Prompting**: compara imágenes antes/después. +- **Image-as-Text Prompting**: describe una imagen como texto. +- **Duty Distinct Chain-of-Thought (DDCoT)**: extiende Least-to-Most a entornos multimodales. +- **Multimodal Graph-of-Thought**: extiende Graph-of-Thought. +- **Chain-of-Images (CoI)**: cadena de pensamiento en imágenes. + +### 7.2 Otras Modalidades +- **Audio Prompting**: técnicas aplicadas a audio. +- **Video Prompting**: prompting para video. +- **Segmentation Prompting**: segmentación guiada por prompt. +- **3D Prompting**: prompting para entornos tridimensionales. + +## 8. Técnicas de Agentes + +### 8.1 Agentes de Uso de Herramientas +- **MRKL System**: integración modular de razonamiento y herramientas. +- **Self-Correcting with Tool-Interactive Critiquing (CRITIC)**: usa herramientas para auto-corregirse. + +### 8.2 Agentes de Generación de Código +- **Program-aided Language Model (PAL)**: traduce a código. +- **Tool-Integrated Reasoning Agent (ToRA)**: alterna razonamiento y código. +- **TaskWeaver**: usa plugins definidos por el usuario. + +### 8.3 Agentes Basados en Observación +- **Reasoning and Acting (ReAct)**: combina pensamiento, acción y observación. +- **Reflexion**: añade introspección al patrón ReAct. +- **Voyager**: aprendizaje continuo con tres componentes. +- **Ghost in the Minecraft (GITM)**: descompone objetivos en subobjetivos. + +### 8.4 Generación Aumentada por Recuperación (RAG) +- **Verify-and-Edit**: mejora la consistencia generando múltiples CoTs. +- **Demonstrate-Search-Predict**: descompone en subpreguntas. +- **Interleaved Retrieval guided by Chain-of-Thought (IRCoT)**: recupera información en múltiples pasos. +- **Iterative Retrieval Augmentation**: realiza recuperación iterativa. + +## 9. Técnicas de Evaluación + +### 9.1 Prompting para Evaluación +- **In-Context Learning para Evaluación**: usa ejemplos para evaluar. +- **Role-based Evaluation**: roles distintos para ampliar cobertura. +- **Chain-of-Thought para Evaluación**: mejora la calidad evaluativa. +- **Model-Generated Guidelines**: el modelo genera pautas de evaluación. + +### 9.2 Formatos de Salida +- **Binary Score**: respuesta binaria. +- **Linear Scale**: escala lineal simple. +- **Likert Scale**: escala Likert. +- **Styling**: salidas formateadas (XML, JSON, etc.). + +### 9.3 Marcos de Prompting +- **LLM-EVAL**: marco básico de evaluación. +- **G-EVAL**: incorpora Auto-CoT en la evaluación. +- **ChatEval**: usa debate multi-agente. + +### 9.4 Otras Metodologías +- **Batch Prompting**: evalúa múltiples instancias a la vez. +- **Pairwise Evaluation**: compara dos respuestas directamente. + +## 10. Técnicas de Ingeniería de Prompts + +- **Meta Prompting**: el modelo mejora el prompt. +- **AutoPrompt**: usa tokens disparadores en un LLM congelado. +- **Automatic Prompt Engineer (APE)**: genera prompts zero-shot. +- **Gradientfree Instructional Prompt Search (GrIPS)**: busca prompts sin gradientes. +- **Prompt Optimization with Textual Gradients (ProTeGi)**: optimiza con gradientes textuales. +- **RLPrompt**: agrega un módulo de refuerzo. +- **Dialogue-comprised Policy-gradient-based Discrete Prompt Optimization (DP2O)**: optimización avanzada basada en diálogos. + +## 11. Ingeniería de Respuestas + +### 11.1 Componentes +- **Answer Shape**: formato de la respuesta. +- **Answer Space**: dominio de valores permitidos. +- **Answer Extractor**: regla para extraer la respuesta final. + +### 11.2 Técnicas +- **Verbalizer**: asigna tokens a etiquetas. +- **Regex**: usa expresiones regulares para extraer respuestas. +- **Separate LLM**: un modelo evalúa la salida de otro. + +## 12. Técnicas Especializadas por Dominio + +### 12.1 Seguridad +- **Prompt-based Defenses**: instrucciones defensivas explícitas. +- **Detectors**: detectores de entradas maliciosas. +- **Guardrails**: reglas para guiar la salida. + +### 12.2 Alineación +- **Vanilla Prompting**: instrucción imparcial. +- **Selecting Balanced Demonstrations**: equilibra ejemplos según métricas de equidad. +- **Cultural Awareness**: adapta culturalmente las respuestas. +- **AttrPrompt**: reduce sesgos en texto generado. +- **Ambiguous Demonstrations**: usa ejemplos con etiquetas ambiguas. +- **Question Clarification**: identifica preguntas ambiguas. + +### 12.3 Calibración +- **Verbalized Score**: genera puntuación de confianza. +- **Sycophancy**: considera tendencia a complacer al usuario. + +## Notas Importantes + +- Las técnicas pueden combinarse para mejorar resultados. +- La efectividad depende del modelo (Claude, ChatGPT, Hugging Face), la tarea y el contexto. +- Algunas técnicas requieren ajustes específicos por dominio (API, UI, Infrastructure, Docs, Scripts). +- La investigación evoluciona rápidamente; validar empíricamente antes de estandarizar. +- Registrar hallazgos y variantes en `docs/ai/SDLC_AGENTS_GUIDE.md` cuando se descubran nuevas combinaciones. diff --git a/docs/ai_capabilities/prompting/README.md b/docs/ai_capabilities/prompting/README.md index 751d854c..045a533d 100644 --- a/docs/ai_capabilities/prompting/README.md +++ b/docs/ai_capabilities/prompting/README.md @@ -22,6 +22,12 @@ Estas técnicas son **generales y transversales**, no específicas a un módulo --- +### Prompt Techniques Catalog (multi-LLM) + +Para una cobertura exhaustiva de técnicas aplicables a Claude, ChatGPT y Hugging Face, consulta el [PROMPT_TECHNIQUES_CATALOG.md](./PROMPT_TECHNIQUES_CATALOG.md). Este catálogo enlaza directamente con los agentes por proveedor y con los agentes de dominio descritos en `.agent/agents/`, asegurando que Backend (API), Frontend (UI), Infrastructure, Docs y Scripts trabajen con el mismo inventario de estrategias. + +--- + ## Implemented Techniques (38 Total) ### Core Techniques (32) @@ -50,6 +56,24 @@ Ver documentación completa en: [SEARCH_OPTIMIZATION_TECHNIQUES.md](./SEARCH_OPT --- +### Code Generation Guide + +Material complementario centrado en estrategias de generación de código (planificación, uso de herramientas y memoria) y en patrones de prompts paso a paso está disponible en [CODE_GENERATION_GUIDE.md](./CODE_GENERATION_GUIDE.md). Resume ejemplos prácticos y recordatorios de validación para mantener alineados a los agentes orientados a código. + +### Agentic System Patterns + +El compendio de patrones agenticos observados en producción—desde LLMs aumentados hasta orquestadores y evaluadores—se documenta en [AGENTIC_SYSTEM_PATTERNS.md](./AGENTIC_SYSTEM_PATTERNS.md). El material enfatiza cuándo escalar de flujos deterministas a agentes autónomos, qué compromisos evaluar (latencia, costo, confianza) y cómo diseñar la interfaz agente-computadora. + +### Codex MCP Multi-Agent Guide + +Para estandarizar la orquestación Codex MCP en todos los proveedores soportados, consulta [../orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md](../orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md). Describe cómo inicializar el servidor MCP, ensamblar flujos single-agent y multi-agent, habilitar trazas y enlazar el `CodexMCPWorkflowBuilder` con la gobernanza `.agent`. + +### Phi-3 Prompt Engineering Playbook + +Para alinear el tercer proveedor soportado (Hugging Face) con prácticas de prompting reproducibles, consulta [PHI3_PROMPT_ENGINEERING_PLAYBOOK.md](./PHI3_PROMPT_ENGINEERING_PLAYBOOK.md). Resume la configuración del modelo `microsoft/Phi-3-mini-4k-instruct`, patrones como Chain-of-Thought/Tree-of-Thought y recomendaciones para interoperar con Claude y ChatGPT. + +--- + ## Implementation Location **Código:** `scripts/ai/agents/base/` diff --git a/docs/analisis/AGENTS.md b/docs/analisis/AGENTS.md new file mode 100644 index 00000000..d8426c4e --- /dev/null +++ b/docs/analisis/AGENTS.md @@ -0,0 +1,110 @@ +# ETA-AGENTE CODEX: Sistema Autónomo de Gestión de Revisiones + +Este agente conceptual define cómo estructurar y mantener los análisis consolidados dentro de `docs/analisis/`. Su mandato principal es **colocar las revisiones consolidadas** en este árbol y garantizar que toda referencia se mantenga actualizada en los índices oficiales. + +## 0. Propósito +Proveer un agente autónomo con razonamiento complejo para generar artefactos CODEX técnicamente rigurosos para cualquier especialización técnica. Todas las conclusiones deben contar con validación automática multi-capa (Auto-CoT + Self-Consistency) y trazabilidad a evidencia académica revisada por pares. + +## 1. Supuestos y Alcance +### 1.1 Supuestos Fundamentales +- *Epistemológicos*: El conocimiento técnico posee estructura formal verificable; las propiedades de cada especialización pueden derivarse desde primeros principios; la coherencia lógica puede validarse automáticamente. +- *Técnicos*: Acceso a repositorios académicos, análisis metodológico riguroso, derivación de restricciones formales y validación multi-ruta. +- *Operacionales*: Generación sin intervención humana, iteración hasta convergencia de calidad y disponibilidad de fuentes académicas. + +### 1.2 Alcance del Meta-Agente +Incluye la generación autónoma de artefactos CODEX para especializaciones técnicas establecidas, validación de coherencia lógica, análisis de propiedades formales, identificación de anti-patterns y documentación exhaustiva de limitaciones y trade-offs. Excluye implementación de código, ejecución práctica de tareas y consultoría organizacional. + +### 1.3 Restricciones Operativas +- *Metodológicas*: Solo fuentes peer-reviewed con metodología documentada; toda afirmación debe incluir evidencia y límites explícitos. +- *Epistemológicas*: No se emiten verdades absolutas; se priorizan propiedades formales verificables. +- *Formato*: Sin emojis, sin código ejecutable, referencias textuales a herramientas, diagramas textuales cuando sea necesario. + +## 2. Técnicas de Razonamiento del Pipeline +El agente aplica las siguientes estrategias en cada revisión ubicada en `docs/analisis/`: +1. **Auto-CoT (Automatic Chain-of-Thought)** para derivar cadenas causales completas y trazables. +2. **Self-Consistency** mediante rutas formales, empíricas y operacionales con convergencia mínima del 85%. +3. **Tree-of-Thought** para descomponer objetivos y tareas sin redundancias ni ciclos. +4. **Constraint-Driven Prompting** para garantizar que ninguna decisión viole restricciones lógicas o de complejidad. +5. **Role-Conditioned Reasoning** considerando perspectivas de Desarrollo, Operaciones, Arquitectura, Seguridad, QA y Compliance. +6. **Dynamic Decomposition** ajustando granularidad según complejidad cognitiva, integración y riesgo. +7. **Multi-Axis Evaluation** evaluando rendimiento, seguridad, mantenibilidad, costo y riesgo con fronteras de Pareto. +8. **Context-Anchored Re-Prompting** para prevenir derivas semánticas y asegurar autocontención del documento. +9. **Iterative Refinement Loop** hasta cumplir umbrales de coherencia ≥0.95, consistencia ≥0.85 y cobertura de anti-patterns ≥0.90. + +## 2.1 Componentes fundamentales del agente + +Para mantener la trazabilidad de decisiones y la ejecución autónoma, toda revisión debe confirmar que el agente opera sobre tres +capas estructurales en sinergia: + +``` +[ETA-AGENTE CODEX] +├── Planificación (núcleo LLM) +│ ├─ Descomposición de tareas con razonamiento paso a paso +│ ├─ Autoevaluación continua del progreso +│ ├─ Ajuste adaptativo a nueva información +│ └─ Análisis crítico de resultados parciales +├── Uso de herramientas (interfaz con el entorno) +│ ├─ Selección de scripts de análisis, validadores y pipelines de datos +│ ├─ Ejecución condicionada según objetivos y restricciones +│ ├─ Orquestación de validadores automáticos +│ └─ Recolección de evidencia cuantitativa +└── Sistemas de memoria (gestión de contexto) + ├─ Memoria de trabajo para mantener estado inmediato y CoT activo + ├─ Persistencia externa para historiales relevantes cuando aplique + ├─ Recuperación eficiente de hallazgos y métricas previas + └─ Consolidación de aprendizajes para iteraciones posteriores +``` + +- **Planificación**: articulada por modelos de lenguaje capaces de descomponer objetivos, reflexionar sobre decisiones previas y + ajustar la estrategia ante nueva evidencia. +- **Uso de herramientas**: abarca todos los scripts y validadores necesarios para ejecutar las acciones planificadas, con énfasis + en la selección correcta y el momento de ejecución. +- **Sistemas de memoria**: combinan memoria de corto plazo (contexto inmediato) con memorias persistentes cuando se requiera + reutilizar descubrimientos o métricas en futuras iteraciones. + +La documentación de cada revisión consolidada debe enumerar explícitamente cómo se materializan estas tres capas, señalando el rol +de la planificación, qué herramientas se emplean y cómo se preserva la información crítica para asegurar continuidad. + +## 3. Entrada Requerida del Usuario +Cada revisión consolidada debe incluir una especificación formal con: +- **Especialización técnica** (nombre, clasificación, madurez, ámbito). +- **Contexto técnico** (problema, propiedades deseadas, restricciones, stack base). +- **Objetivos verificables** y **restricciones adicionales** (técnicas, operacionales, regulatorias, legacy). +- **Umbrales de calidad** esperados (coherencia lógica, consistencia, cobertura, validadores) y preferencias de enfoque. + +## 4. Proceso de Generación del Artefacto CODEX +Las revisiones en `docs/analisis/` deben documentar, como mínimo, las etapas siguientes: +1. **Análisis de literatura académica**: búsqueda estructurada, validación metodológica, extracción de propiedades formales, identificación de anti-patterns con evidencia y análisis de trade-offs cuantificados. +2. **Derivación de restricciones**: complejidad computacional, propiedades de consistencia/correctitud y seguridad basada en threat models. +3. **Generación de estructura del artefacto**: fases lógicas derivadas de dependencias, descomposición dinámica de tareas atómicas y especificación de validadores automáticos. +4. **Auto-CoT**: cadenas causales verificables, validación de coherencia global y documentación de riesgos, mitigaciones y limitaciones. +5. **Self-Consistency**: rutas de razonamiento independientes (formal-teórica, empírica-experimental, pragmática-operacional) con métricas de convergencia explícitas. + +## 5. Entregables Obligatorios +Cada análisis consolidado debe aportar: +- Documento principal en `docs/analisis/` con cadenas causales y conclusiones validadas. +- Referencias a planes derivados (`docs/plans/`) y actualizaciones correspondientes en `docs/index.md`. +- Registro de validadores y criterios objetivos (tests, model checking, métricas cuantitativas). + +## 6. Ubicación y Gobernanza +- **Ubicación oficial**: Todas las revisiones y análisis consolidados residen en `docs/analisis/`. La carpeta `rev/` queda reservada para materiales temporales antes de su formalización. +- **Actualización de índices**: Cada incorporación debe enlazarse desde `docs/index.md` (sección “Revisión actual”) y cualquier runbook relacionado. +- **Cumplimiento de políticas**: Prohibido mover revisiones fuera de `docs/analisis/` sin actualizar este agente y los índices. El incumplimiento se considera regressión documental. + +## 7. Métricas de Calidad del Agente +- Coherencia lógica ≥ 0.95. +- Consistencia entre rutas de razonamiento ≥ 0.85. +- Cobertura de anti-patterns ≥ 0.90. +- Validadores implementados para ≥ 80% de tareas críticas. + +## 8. Limitaciones Reconocidas +- La validez lógica no garantiza correctitud empírica en contextos no cubiertos por la literatura. +- La convergencia de Self-Consistency puede verse afectada por sesgos compartidos entre rutas. +- Los umbrales elevados pueden requerir múltiples iteraciones; se debe documentar cualquier métrica no alcanzada. + +--- +**Instrucción clave**: Ante cualquier revisión futura, primero validar aquí los lineamientos del ETA-AGENTE CODEX y confirmar que el documento final se ubica en `docs/analisis/` con enlaces actualizados en todo el ecosistema documental. + +## 9. Implementación de referencia +- **Agente ejecutable**: `scripts/coding/ai/agents/documentation/eta_codex_agent.py` valida ubicación y referencias de las revisiones consolidadas. +- **Pruebas asociadas**: `scripts/coding/tests/ai/agents/documentation/test_eta_codex_agent.py` garantiza que la gobernanza permanezca activa. diff --git a/rev/revision_20251112_consolidada.md b/docs/analisis/revision_20251112_consolidada.md similarity index 100% rename from rev/revision_20251112_consolidada.md rename to docs/analisis/revision_20251112_consolidada.md diff --git a/docs/gobernanza/metodologias/agentes_automatizacion.md b/docs/gobernanza/metodologias/agentes_automatizacion.md index 1eb860f6..fffe8aa7 100644 --- a/docs/gobernanza/metodologias/agentes_automatizacion.md +++ b/docs/gobernanza/metodologias/agentes_automatizacion.md @@ -177,7 +177,7 @@ done **Cuándo se usó**: Sincronización de ramas principales y limpieza de repositorio (2025-11-05) -**Ubicación**: `.github/agents/gitops-agent.md` +**Ubicación**: `.agent/agents/gitops_agent.md` **Cómo funciona**: @@ -402,7 +402,7 @@ git branch -r # Debe mostrar solo 4 ramas **Tipo**: Agente personalizado `ReleaseAgent` -**Ubicación**: `.github/agents/release-agent.md` +**Ubicación**: `.agent/agents/release_agent.md` **Propósito**: Gestión completa del proceso de release, versionado semántico, generación de changelogs y creación de tags Git. @@ -452,7 +452,7 @@ actualiza versiones en archivos del proyecto y crea tag. **Tipo**: Agente personalizado `DependencyAgent` -**Ubicación**: `.github/agents/dependency-agent.md` +**Ubicación**: `.agent/agents/dependency_agent.md` **Propósito**: Gestión de dependencias, actualizaciones, escaneo de vulnerabilidades y auditoría de licencias. @@ -509,7 +509,7 @@ Generar reporte detallado. **Tipo**: Agente personalizado `SecurityAgent` -**Ubicación**: `.github/agents/security-agent.md` +**Ubicación**: `.agent/agents/security_agent.md` **Propósito**: Auditorías de seguridad, escaneo de vulnerabilidades, detección de secrets y análisis de amenazas según metodología STRIDE. diff --git a/docs/index.md b/docs/index.md index cf6652e5..12b4e34a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -82,11 +82,11 @@ Este índice combina lo implementado con la visión futura del proyecto, clarame - **Validaciones**: [`scripts/validation/`](../scripts/validation/) - Quality, compliance, security, docs - **Test runner**: [`scripts/run_all_tests.sh`](../scripts/run_all_tests.sh) +- **Métricas DORA**: [`scripts/dora_metrics.py`](../scripts/dora_metrics.py) - **Templates**: [`scripts/templates/`](../scripts/templates/) #### [PLANIFICADO] Planificados (ver [`docs/scripts/README.md`](scripts/README.md)) - `scripts/sdlc_agent.py` - CLI SDLC -- `scripts/dora_metrics.py` - Calculador DORA metrics - `scripts/requisitos/` - Gestión de requisitos - 20+ agentes SDLC especializados @@ -113,6 +113,7 @@ Este índice combina lo implementado con la visión futura del proyecto, clarame - **Changelog**: [`proyecto/CHANGELOG.md`](proyecto/CHANGELOG.md) - Historial completo ### Revisión actual (12 Nov 2025) +- **Análisis consolidado**: [`analisis/revision_20251112_consolidada.md`](analisis/revision_20251112_consolidada.md) - Estado base de documentación y scripts - **Plan de remediación**: [`plans/REV_20251112_remediation_plan.md`](plans/REV_20251112_remediation_plan.md) - **Estado**: Alineación docs ↔ código en progreso @@ -121,6 +122,7 @@ Este índice combina lo implementado con la visión futura del proyecto, clarame ### DORA Metrics y AI Excellence - **Estrategia IA**: [`gobernanza/ai/ESTRATEGIA_IA.md`](gobernanza/ai/ESTRATEGIA_IA.md) - **AI Capabilities**: [`gobernanza/ai/AI_CAPABILITIES.md`](gobernanza/ai/AI_CAPABILITIES.md) +- **Fine-tuning local**: [`ai/FINE_TUNING_TINYLLAMA.md`](ai/FINE_TUNING_TINYLLAMA.md) - **Gaps post-DORA 2025**: [`gobernanza/ai/ANALISIS_GAPS_POST_DORA_2025.md`](gobernanza/ai/ANALISIS_GAPS_POST_DORA_2025.md) - **Target**: 7/7 prácticas AI (actual: 5/7 - 71%) - **Roadmap**: 144 SP, completar Q2 2026 diff --git a/docs/operaciones/verificar_servicios.md b/docs/operaciones/verificar_servicios.md index 23e9c8a0..c130c040 100644 --- a/docs/operaciones/verificar_servicios.md +++ b/docs/operaciones/verificar_servicios.md @@ -27,21 +27,37 @@ Validar que PostgreSQL y MariaDB estén operativos y accesibles desde el entorno ## Procedimiento Automático -### Opción 1: Script Automatizado +### Opción 1: Script automatizado (recomendado) ```bash ./scripts/verificar_servicios.sh ``` -**Output esperado:** +**Tips clave:** + +- Usa `--dry-run` en entornos CI/CD o cuando las bases de datos aún no están levantadas. +- Sobrescribe credenciales mediante flags (`--postgres-host`, `--mariadb-password`, etc.) o variables de entorno. +- Códigos de salida: `0` (OK), `1` (fallo de conexión), `2` (clientes faltantes). + +**Output esperado (éxito):** ``` -[OK] Cliente PostgreSQL (psql) instalado -[OK] Cliente MariaDB (mysql) instalado -[OK] PostgreSQL conectado exitosamente en 127.0.0.1:15432 -[OK] MariaDB conectado exitosamente en 127.0.0.1:13306 +[OK] Cliente psql disponible +[OK] Cliente mysql disponible +[INFO] Verificando PostgreSQL... +[OK] PostgreSQL respondió correctamente +[INFO] Verificando MariaDB... +[OK] MariaDB respondió correctamente [OK] Todos los servicios están operativos ``` +**Output esperado (`--dry-run`):** +``` +[DRY-RUN] Validación de conectividad omitida. +[DRY-RUN] Ejecutarías: + PGPASSWORD=**** psql -h 127.0.0.1 -p 15432 -U django_user -d iact_analytics -c 'SELECT 1;' + mysql -h 127.0.0.1 -P 13306 -u django_user -p**** -e 'SELECT 1;' ivr_data +``` + ### Opción 2: Verificación Manual Si el script falla o necesitas debugging adicional: diff --git a/docs/plans/EXECPLAN_agents_domain_alignment.md b/docs/plans/EXECPLAN_agents_domain_alignment.md new file mode 100644 index 00000000..d860b733 --- /dev/null +++ b/docs/plans/EXECPLAN_agents_domain_alignment.md @@ -0,0 +1,82 @@ +# Alinear catálogo de agentes con dominios del proyecto + +Este ExecPlan es un documento vivo. Las secciones `Progress`, `Surprises & Discoveries`, `Decision Log`, y `Outcomes & Retrospective` deben mantenerse actualizadas conforme avance el trabajo. + +Si el archivo PLANS.md está versionado, hace referencia a `.agent/PLANS.md` y se debe respetar íntegramente. + +## Purpose / Big Picture + +Alinear el catálogo de agentes autónomos con la arquitectura real del proyecto (api, ui, infrastructure, docs y scripts) para que cualquier contribuidor pueda seleccionar rápidamente el agente correcto, comprender sus relaciones con ExecPlans, guías y scripts, y mantener la coherencia entre documentación y automatizaciones multi-LLM. + +## Progress + +- [x] (2025-11-06 10:00Z) ExecPlan inicial redactado y verificado contra `.agent/PLANS.md`. +- [x] (2025-11-06 11:20Z) Documentación de relaciones dominio ↔ agentes ↔ ExecPlans actualizada. +- [x] (2025-11-06 11:30Z) Nuevos agentes de dominio creados (`api`, `ui`, `infrastructure`, `docs`, `scripts`). +- [x] (2025-11-06 11:40Z) Pruebas y alineadores documentales ajustados para cubrir los nuevos artefactos. +- [x] (2025-11-06 11:55Z) Outcomes & Retrospective actualizado tras validar los cambios. + +## Surprises & Discoveries + +- Observation: Se requiere que todas las fichas de dominio referencien explícitamente `EXECPLAN_agents_domain_alignment.md` para pasar los nuevos tests. + Evidence: `test_domain_agents_are_documented_and_linked` valida la cadena de referencias. + +## Decision Log + +- Decision: Añadir agentes específicos por dominio dentro de `.agent/agents` y mapearlos desde los README principales. + Rationale: Los colaboradores tenían dificultad para identificar qué agentes y ExecPlans aplicar según la ruta (`api/`, `ui/`, `infrastructure/`, `docs/`, `scripts/`). + Date/Author: 2025-11-06 / gpt-5-codex + +## Outcomes & Retrospective + +Las fichas de dominio permiten asociar rápidamente cada directorio (`api/`, `ui/`, `infrastructure/`, `docs/`, `scripts/`) con los ExecPlans y scripts multi-LLM. Los README (`.agent/README.md`, `.agent/agents/README.md`) y la guía `docs/ai/SDLC_AGENTS_GUIDE.md` enlazan los nuevos agentes por nombre. Las suites `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` y `pytest docs/testing/test_documentation_alignment.py` confirman que los vínculos y builders siguen operativos. El nuevo test `test_domain_agents_are_documented_and_linked` protege esta estructura a futuro. + +## Context and Orientation + +El repositorio está organizado en dominios claros (`api/`, `ui/`, `infrastructure/`, `docs/`, `scripts/`). Actualmente `.agent/agents/README.md` solo cubre agentes por proveedor LLM y algunos operativos (GitOps, Release, Dependency). No existen agentes específicos para los dominios core, lo que genera lagunas para planificar cambios complejos en cada subproyecto. Las guías relevantes incluyen: +- `.agent/PLANS.md`: formato obligatorio para ExecPlans. +- `docs/ai/SDLC_AGENTS_GUIDE.md`: describe el flujo SDLC. +- `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`: explica orquestaciones multi-LLM. +- `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`: expone builder multi-LLM. + +## Plan of Work + +1. Extender `.agent/README.md` para reflejar la relación explícita entre los dominios (api, ui, infrastructure, docs, scripts), los ExecPlans y los scripts asociados. +2. Crear nuevos archivos `.agent/agents/api_agent.md`, `ui_agent.md`, `infrastructure_agent.md`, `docs_agent.md` y `scripts_agent.md`, siguiendo el estándar de fichas existentes y referenciando proveedores LLM y pipelines relevantes. +3. Actualizar `.agent/agents/README.md` para incluir una sección "Agentes por dominio" con enlaces a las nuevas fichas y a los directorios del repositorio. +4. Ajustar `docs/ai/SDLC_AGENTS_GUIDE.md` y el ExecPlan `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` para mencionar cómo los agentes de dominio interactúan con los agentes por proveedor y con los orquestadores. +5. Actualizar `docs/testing/test_documentation_alignment.py` para proteger los nuevos vínculos y garantizar que los índices referencien correctamente las fichas de agentes. +6. Ejecutar las suites de pruebas relevantes (`pytest scripts/coding/tests/...` y `pytest docs/testing/test_documentation_alignment.py`). +7. Documentar descubrimientos en `Surprises & Discoveries`, registrar decisiones y concluir con `Outcomes & Retrospective`. + +## Concrete Steps + +1. Editar `.agent/README.md` y `.agent/agents/README.md` incorporando la matriz de dominios. +2. Generar las fichas de agentes de dominio con secciones estándar (propósito, capacidades, relaciones, ejemplos, validaciones). +3. Modificar `docs/ai/SDLC_AGENTS_GUIDE.md` y `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` para enlazar los nuevos agentes. +4. Ajustar `docs/testing/test_documentation_alignment.py` agregando aserciones para los nuevos archivos. +5. Ejecutar `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` y `pytest docs/testing/test_documentation_alignment.py`. +6. Actualizar las secciones vivas del plan. + +## Validation and Acceptance + +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` debe pasar sin errores. +- `pytest docs/testing/test_documentation_alignment.py` debe validar los vínculos actualizados. +- Verificar que cada ficha de agente mencione explícitamente sus relaciones con ExecPlans, guías y scripts. +- Confirmar que README y guías referencian todos los dominios y agentes. + +## Idempotence and Recovery + +- Los cambios en documentación son idempotentes; repetir ediciones sobrescribe contenido sin efectos secundarios. +- Si una prueba falla, revisar el mensaje, ajustar el archivo correspondiente y volver a ejecutar la suite afectada. + +## Artifacts and Notes + +Pendiente de recopilar ejemplos de salida de pruebas tras la implementación. + +## Interfaces and Dependencies + +- `.agent/agents/*.md`: nuevas fichas deben seguir el formato documentado en `.agent/agents/README.md`. +- `docs/ai/SDLC_AGENTS_GUIDE.md`: agregar secciones o tablas que relacionen agentes por proveedor y por dominio. +- `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`: incluir referencia cruzada a los agentes de dominio. +- `docs/testing/test_documentation_alignment.py`: expandir validadores para asegurar la existencia de enlaces. diff --git a/docs/plans/EXECPLAN_codex_mcp_multi_llm.md b/docs/plans/EXECPLAN_codex_mcp_multi_llm.md new file mode 100644 index 00000000..27291404 --- /dev/null +++ b/docs/plans/EXECPLAN_codex_mcp_multi_llm.md @@ -0,0 +1,98 @@ +# Integrar orquestación Codex MCP para todos los LLM soportados + +Este ExecPlan es una living document. Las secciones `Progress`, `Surprises & Discoveries`, `Decision Log` y `Outcomes & Retrospective` deben mantenerse al día conforme avancemos. + +Se mantiene conforme a `.agent/PLANS.md`; cualquier desviación requiere actualizar la guía central. + +## Purpose / Big Picture + +Brindar al proyecto una guía y componentes reutilizables para ejecutar flujos multi-agente basados en Codex MCP que funcionen con los tres proveedores LLM vigentes (Claude/Anthropic, ChatGPT/OpenAI y modelos locales Hugging Face). El resultado esperado es que un colaborador pueda generar especificaciones, ejecutar agentes y observar sus trazas sin depender de ejemplos aislados para un solo proveedor. + +## Progress + +- [x] (2025-11-09 12:00Z) ExecPlan creado con propósito y orientación inicial. +- [x] (2025-11-09 14:05Z) Documentación actualizada describiendo flujos Codex MCP multi-LLM y su relación con `.agent`. +- [x] (2025-11-09 14:20Z) Builder de orquestación implementado con soporte para proveedores Anthropic, OpenAI y HuggingFace. +- [x] (2025-11-09 14:22Z) Tests de unidad cubriendo generación de flujos single-agent y multi-agent para cada proveedor. +- [x] (2025-11-09 14:30Z) Secciones de documentación y catálogo de agentes enlazan el nuevo módulo. +- [x] (2025-11-09 14:40Z) Validación manual del builder y actualización del retrospect. +- [x] (2025-11-09 15:55Z) Fichas ClaudeAgent/ChatGPTAgent/HuggingFaceAgent añadidas al catálogo `.agent/agents` y referenciadas desde la guía SDLC. +- [x] (2025-11-09 15:58Z) Pruebas de alineación documental extendidas para exigir presencia de las fichas y sus vínculos multi-LLM. +- [x] (2025-11-10 09:45Z) Catálogo extendido con agentes por dominio y actualización de `EXECPLAN_agents_domain_alignment.md`. + +## Surprises & Discoveries + +- Observación: Hugging Face no requiere token obligatorio para ejecutar checkpoints locales, pero el builder devuelve la clave como opcional para mantener consistencia con los proveedores remotos. + Evidencia: Decisión codificada en `_SUPPORTED_PROVIDERS` (`required=False`). +- Observación: Las pruebas de alineación fallaron hasta que cada ficha de agente incluyó referencias explícitas al ExecPlan y a la guía de API keys. + Evidencia: `test_llm_provider_agents_are_documented` exige esas referencias para evitar divergencias futuras. + +## Decision Log + +- Decision: Registrar el ExecPlan bajo `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` para mantenerlo versionado junto a otras planeaciones. + Rationale: El árbol `docs/plans/` centraliza los planes operativos referenciados desde documentos oficiales. + Date/Author: 2025-11-09 / gpt-5-codex +- Decision: Consolidar las fichas de proveedores LLM en `.agent/agents` y validar su presencia mediante pruebas automatizadas. + Rationale: Garantiza que cada proveedor tenga instrucciones autodescriptivas y vínculos a scripts/documentación antes de ejecutar flujos multi-agente. + Date/Author: 2025-11-09 / gpt-5-codex +- Decision: Documentar agentes por dominio (api, ui, infrastructure, docs, scripts) para reforzar el enlace entre este plan multi-LLM y la arquitectura del repositorio. + Rationale: Los flujos Codex MCP generan entregables distribuidos; los agentes de dominio facilitan seleccionar scripts, pruebas y ExecPlans específicos. + Date/Author: 2025-11-06 / gpt-5-codex + +## Outcomes & Retrospective + +Los briefs generados cubren los tres proveedores y mantienen el gating documentado. Las pruebas unitarias confirman la presencia de políticas MCP y trazas, mientras que las fichas de agentes aseguran que planificación y credenciales permanezcan sincronizadas. Se recomienda monitorizar posibles cambios de nombres de modelos por parte de los proveedores para mantener los defaults vigentes. + +## Context and Orientation + +El repositorio ya cuenta con: +- `scripts/coding/ai/generators/llm_generator.py`: agente generador de tests que abstrae proveedores Anthropics/OpenAI/HuggingFace/Ollama. +- `scripts/coding/ai/test_generation_orchestrator.py`: pipeline secuencial de agentes con arquitectura modular. +- Documentación reciente en `docs/ai_capabilities/prompting/` para uso de LLMs (DORA scripts, PHI3, etc.). +- El catálogo de agentes vive en `.agent/agents/` y la gobernanza de planes en `.agent/PLANS.md`. + +Actualmente no existe una guía unificada para operar Codex MCP ni un componente reutilizable que configure flujos multi-agente según el proveedor. Los ejemplos brindados por el usuario deben adaptarse a un contexto sin dependencias externas que ejecuten redes en CI. + +## Plan of Work + +1. **Documentación**: Crear una guía en `docs/ai_capabilities/orchestration/` que explique cómo inicializar Codex MCP, componer agentes individuales y multi-agente, mapearlos a los tres proveedores soportados y registrar cómo habilitar trazas. Actualizar índices (`docs/ai_capabilities/prompting/README.md`, README principal) y el catálogo `.agent/agents/README.md`. +2. **Diseño del builder**: Implementar un módulo `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` con clases puramente declarativas que generen los diccionarios de configuración necesarios para single-agent y multi-agent. El builder deberá exponer metadatos para cada proveedor (p. ej., nombre del modelo por defecto, variables de entorno esperadas, banderas `approval-policy`). +3. **Interfaz con `.agent`**: Añadir una ficha de agente en `.agent/agents` que describa el nuevo orquestador y cómo interactúa con la guía documental y scripts. +4. **Pruebas**: Crear `scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` que cubra los tres proveedores en escenarios single y multi-agent, validando que el builder aplica banderas MCP, referencias a modelos y gating de artefactos. +5. **Validaciones**: Ejecutar `pytest` sobre los tests recién creados y `docs/testing/test_documentation_alignment.py` para asegurar consistencia. Documentar hallazgos en `Surprises & Discoveries` y cerrar con `Outcomes & Retrospective`. + +## Concrete Steps + +1. Crear directorio `docs/ai_capabilities/orchestration/` si no existe y añadir guía `CODEX_MCP_MULTI_AGENT_GUIDE.md` basada en los lineamientos proporcionados, adaptándolos al contexto multi-proveedor. +2. Actualizar índices/documentación (`docs/ai_capabilities/prompting/README.md`, `README.md`, `.agent/agents/README.md`) para enlazar la nueva guía y el builder. +3. Escribir pruebas de TDD en `scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` cubriendo: + - Generación de configuración single-agent para cada proveedor. + - Flujo multi-agent que comprueba gating y artefactos esperados. + - Validación de errores cuando falta información crítica (por ejemplo, sin API key configurada para openai/anthropic). +4. Implementar `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` para satisfacer los tests, asegurando 100% de coverage en este módulo. +5. Ejecutar `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` seguido de `pytest docs/testing/test_documentation_alignment.py`. +6. Actualizar secciones vivas del ExecPlan con hallazgos y retrospectiva. + +## Validation and Acceptance + +- Los tests unitarios creados para el builder deben pasar en los tres proveedores simulados. +- `pytest docs/testing/test_documentation_alignment.py` debe seguir pasando tras la actualización de documentación. +- La guía documental debe describir pasos reproducibles (config `.env`, inicialización MCP, construcción multi-agent) y referenciar el nuevo módulo. +- `.agent/agents/README.md` debe listar el nuevo orquestador con enlace a guía y script. + +## Idempotence and Recovery + +- Las modificaciones documentales son aditivas; re-ejecutar los pasos sobrescribe archivos con el mismo contenido si es necesario. +- Los tests pueden ejecutarse múltiples veces sin efectos secundarios. +- Si la generación de archivos falla, basta con repetir el paso correspondiente; no se introducen migraciones destructivas. + +## Artifacts and Notes + +- `pytest scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py` → 10 tests OK (proveedores openai/anthropic/huggingface). + +## Interfaces and Dependencies + +- Módulo nuevo: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` expondrá funciones puras; no se realizarán llamadas de red. +- Dependencias: se mantiene compatibilidad con Python estándar y sin instalar `openai-agents`. El builder solo documenta parámetros a usar. +- Variables de entorno: `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `HUGGINGFACEHUB_API_TOKEN` (opcional), `MCP_CLI_PATH` si se personaliza el comando. + diff --git a/docs/plans/EXECPLAN_prompt_techniques_catalog.md b/docs/plans/EXECPLAN_prompt_techniques_catalog.md new file mode 100644 index 00000000..3c44ce7b --- /dev/null +++ b/docs/plans/EXECPLAN_prompt_techniques_catalog.md @@ -0,0 +1,70 @@ +# Integrar catálogo completo de técnicas de prompts multi-LLM + +Este ExecPlan es un documento vivo. Las secciones `Progress`, `Surprises & Discoveries`, `Decision Log` y `Outcomes & Retrospective` deben mantenerse al día conforme avance el trabajo. + +Si el archivo PLANS.md está en el repositorio, referencia su ruta: `.agent/PLANS.md`. Este documento debe mantenerse en conformidad con dicha guía. + +## Purpose / Big Picture + +Unificar el catálogo completo de técnicas de prompting para que los equipos de Backend (API), Frontend (UI), Infrastructure, Docs y Scripts dispongan de una referencia homogénea aplicable a Claude, ChatGPT y Hugging Face. Tras la implementación, cualquier colaborador podrá ubicar las técnicas según el flujo SDLC y vincularlas con los agentes y orquestadores multi-LLM existentes. + +## Progress + +- [x] (2025-02-14 12:00Z) Redactar prueba de alineación documental que asegure la existencia y el enlace del nuevo catálogo. +- [x] (2025-02-14 12:05Z) Incorporar el catálogo completo de técnicas en `docs/ai_capabilities/prompting/` con referencias cruzadas hacia los agentes por proveedor y dominios. +- [x] (2025-02-14 12:06Z) Actualizar README y guías de agentes para reflejar la nueva fuente canónica. +- [x] (2025-02-14 12:07Z) Ejecutar la batería de pruebas (`pytest docs/testing/test_documentation_alignment.py`). + +## Surprises & Discoveries + +- No se identificaron descubrimientos imprevistos; la estructura existente de agentes ya contemplaba puntos de enlace. + +## Decision Log + +- Decision: Centralizar el catálogo en `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` y referenciarlo desde todas las fichas de agentes y guías SDLC. + Rationale: Evitar duplicación de técnicas y asegurar consistencia multi-LLM para los dominios Backend/UI/Infrastructure/Docs/Scripts. + Date/Author: 2025-02-14 / Automatización. + +## Outcomes & Retrospective + +- Catálogo multi-LLM publicado y enlazado desde README, prompting index, agentes por proveedor y por dominio. +- Las pruebas de alineación documental fueron extendidas para proteger la presencia del catálogo y pasaron exitosamente (`pytest docs/testing/test_documentation_alignment.py`). + +## Context and Orientation + +El repositorio ya contiene guías de prompting específicas (`CODE_GENERATION_GUIDE.md`, `PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`, etc.) y catálogos de agentes en `.agent/agents/`. La política exige que nuevas piezas documentales se integren con los agentes de dominio (ApiAgent, UiAgent, etc.) y con los agentes por proveedor (Claude, ChatGPT, Hugging Face). Las pruebas automáticas de documentación residen en `docs/testing/test_documentation_alignment.py` y deben extenderse para incluir cualquier documento nuevo. + +## Plan of Work + +1. Extender `docs/testing/test_documentation_alignment.py` para exigir la presencia del catálogo de técnicas de prompting y sus enlaces desde el índice de prompting y desde los agentes pertinentes. +2. Crear `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` incorporando el contenido proporcionado, organizándolo para todos los modelos LLM y añadiendo referencias cruzadas hacia ExecPlans y agentes relevantes. +3. Actualizar `docs/ai_capabilities/prompting/README.md`, `.agent/agents/README.md`, y las fichas de agentes por proveedor para enlazar el nuevo catálogo. +4. Revisar `docs/ai/SDLC_AGENTS_GUIDE.md` y cualquier guía de dominio que requiera citar el catálogo, asegurando consistencia con el mapeo Backend/UI/Infrastructure/Docs/Scripts. +5. Ejecutar pruebas (`pytest docs/testing/test_documentation_alignment.py`) y documentar resultados. + +## Concrete Steps + +- Trabajar desde la raíz del repositorio (`/workspace/IACT---project`). +- Ejecutar `pytest docs/testing/test_documentation_alignment.py` tras implementar los cambios. +- Si es necesario validar cobertura adicional, reutilizar suites existentes bajo `scripts/coding/tests/`. + +## Validation and Acceptance + +- `pytest docs/testing/test_documentation_alignment.py` debe pasar y confirmar que el catálogo está enlazado correctamente. +- Los README y fichas de agentes deben contener referencias explícitas al catálogo. +- La documentación debe mencionar que el catálogo es aplicable a Claude, ChatGPT y Hugging Face. + +## Idempotence and Recovery + +- Las modificaciones son aditivas. Si una prueba falla por enlaces rotos, corregir los paths y reejecutar la suite. +- Para revertir, restaurar los archivos modificados con `git checkout -- `. + +## Artifacts and Notes + +- Se adjuntarán fragmentos relevantes de pruebas exitosas en la sección de resultados. + +## Interfaces and Dependencies + +- Documentación principal: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` (nuevo). +- Índices y catálogos: `.agent/agents/README.md`, `docs/ai_capabilities/prompting/README.md`, `docs/ai/SDLC_AGENTS_GUIDE.md`. +- Validadores: `docs/testing/test_documentation_alignment.py`. diff --git a/docs/plans/REV_20251112_remediation_plan.md b/docs/plans/REV_20251112_remediation_plan.md index 47d98936..1403ea69 100644 --- a/docs/plans/REV_20251112_remediation_plan.md +++ b/docs/plans/REV_20251112_remediation_plan.md @@ -1,5 +1,7 @@ # Plan de remediación para hallazgos de la revisión 2025-11-12 +> Revisión consolidada: [`docs/analisis/revision_20251112_consolidada.md`](../analisis/revision_20251112_consolidada.md) + ## Metodología aplicada - **Auto-CoT (Chain-of-Thought automatizada)**: descompusimos los hallazgos en clústeres temáticos y, dentro de cada uno, derivamos tareas concretas accionables. - **Self-Consistency**: validamos cada decisión crítica contrastando la evidencia del repositorio (listados de directorios y contenido real) y verificando que no existan instrucciones contradictorias en otros documentos. @@ -9,7 +11,7 @@ ### C1. Documentación raíz desalineada 1. **README** - - Alinear la guía de inicio con el estado real (sin Makefile raíz, sin script `verificar_servicios.sh`). + - Alinear la guía de inicio con el estado real (sin Makefile raíz, con script `verificar_servicios.sh`). - Documentar rutas válidas a runbooks vigentes (`docs/operaciones/`). - Reforzar política anti `git push --no-verify` con alternativas reales. 2. **Resumen de estructura** @@ -76,4 +78,4 @@ ## Próximos pasos futuros (fuera de alcance inmediato) - Automatizar validación de enlaces Markdown a través de hook CI. - Diseñar ADR sobre estrategia definitiva de consolidación `docs/` ↔ `respaldo/`. -- Implementar script real para verificación de servicios y cobertura de pruebas asociada. +- Extender el script de verificación de servicios con chequeos adicionales (latencia, usuarios read-only). diff --git a/docs/scripts/README.md b/docs/scripts/README.md index 86331c7c..319f74e6 100644 --- a/docs/scripts/README.md +++ b/docs/scripts/README.md @@ -93,8 +93,8 @@ chmod +x scripts/mi-nuevo-script.sh |--------|-----------|--------| | `install_hooks.sh` | Instala Git hooks | [IMPLEMENTADO] | | `reorganizar_docs_por_dominio.sh` | Reorganiza documentación | [IMPLEMENTADO] | -| [PLANIFICADO] `cleanup_sessions.sh` | Limpia sesiones Django | Planificado | -| [PLANIFICADO] `cleanup_branches.sh` | Limpia ramas mergeadas | Planificado | +| `cleanup_sessions.sh` | Limpia sesiones Django | [IMPLEMENTADO] | +| `cleanup_branches.sh` | Limpia ramas mergeadas | [IMPLEMENTADO] | ## [PLANIFICADO] Scripts planificados (visión completa) @@ -122,7 +122,7 @@ python scripts/sdlc_agent.py --pipeline --input "Feature: Dashboard" ### Métricas DORA -**`scripts/dora_metrics.py`**: +**`scripts/dora_metrics.py`** ([IMPLEMENTADO] baseline local): ```bash # Últimos 30 días python scripts/dora_metrics.py --repo 2-Coatl/IACT---project @@ -142,6 +142,8 @@ python scripts/dora_metrics.py --docs-only **Documentación**: [`metrics-and-reporting.md`](metrics-and-reporting.md) +> Nota: No existen scripts como `scripts/sdlc_agent.py` todavía; los agentes SDLC siguen en fase de diseño. + ### Gestión de requisitos **`scripts/requisitos/`**: diff --git a/docs/scripts/SCRIPTS_MATRIX.md b/docs/scripts/SCRIPTS_MATRIX.md index b82ff5b5..fca2ab95 100644 --- a/docs/scripts/SCRIPTS_MATRIX.md +++ b/docs/scripts/SCRIPTS_MATRIX.md @@ -11,4 +11,4 @@ | `scripts/workflows/` | Automatizaciones compuestas. | Activo | | `scripts/examples/` | Ejemplos y demostraciones. | Activo | -> **Nota:** No existen entradas vigentes para `scripts/requisitos/`, `scripts/ai/agents/` ni `scripts/dora_metrics.py`. +> **Nota:** No existen entradas vigentes para `scripts/requisitos/` ni `scripts/ai/agents/`; `scripts/dora_metrics.py` ya está implementado. diff --git a/docs/testing/registros/2025_11_05_merge_ramas_gitops.md b/docs/testing/registros/2025_11_05_merge_ramas_gitops.md index fbec5ad9..7a1c2347 100644 --- a/docs/testing/registros/2025_11_05_merge_ramas_gitops.md +++ b/docs/testing/registros/2025_11_05_merge_ramas_gitops.md @@ -508,7 +508,7 @@ origin/main ## Referencias -- **Agente**: `.github/agents/gitops-agent.md` +- **Agente**: `.agent/agents/gitops_agent.md` - **Runbook**: `docs/devops/runbooks/merge_y_limpieza_ramas.md` - **Script**: `scripts/complete_sync.sh` - **Registro anterior**: `docs/qa/registros/2025_11_05_merge_ramas.md` diff --git a/docs/testing/test_documentation_alignment.py b/docs/testing/test_documentation_alignment.py index 502d8868..2409f63c 100644 --- a/docs/testing/test_documentation_alignment.py +++ b/docs/testing/test_documentation_alignment.py @@ -14,14 +14,15 @@ def test_readme_acknowledges_absence_of_root_makefile(): readme = _read(REPO_ROOT / "README.md") assert "No existe un Makefile en la raíz" in readme assert "docs/operaciones/verificar_servicios.md" in readme - assert "Actualmente **no existe** `./scripts/verificar_servicios.sh`" in readme + assert "./scripts/verificar_servicios.sh" in readme + assert "[IMPLEMENTADO]" in readme assert "make docs-serve" not in readme def test_docs_index_and_stubs_are_canonical(): index = _read(REPO_ROOT / "docs/index.md") - assert "## Documentación activa" in index - assert "## Contenido legado" in index + assert "## [DOCS] Documentación activa" in index + assert "## [LEGADO] Contenido legado" in index index_stub = _read(REPO_ROOT / "docs/INDEX.md") indice_stub = _read(REPO_ROOT / "docs/INDICE.md") @@ -43,8 +44,8 @@ def test_scripts_documentation_reflects_current_inventory(): def test_logs_and_analysis_documentation_are_updated(): schema = _read(REPO_ROOT / "logs_data/SCHEMA.md") - assert "Automatización pendiente" in schema - assert "scripts/dora_metrics.py" not in schema + assert "Automatización parcial" in schema + assert "scripts/dora_metrics.py" in schema analyzer = _read(REPO_ROOT / "scripts/analyze_backend.py") assert "logs_data/analysis/backend_analysis_results.json" in analyzer @@ -59,3 +60,199 @@ def test_run_all_tests_targets_ui_directory(): def test_cpython_install_script_renamed(): renamed_path = REPO_ROOT / "infrastructure/cpython/scripts/install_prebuilt_cpython.sh" assert renamed_path.exists() + + +def test_revision_20251112_lives_in_docs_analisis(): + revision_path = REPO_ROOT / "docs/analisis/revision_20251112_consolidada.md" + assert revision_path.exists() + + index_contents = _read(REPO_ROOT / "docs/index.md") + assert "analisis/revision_20251112_consolidada.md" in index_contents + + legacy_path = REPO_ROOT / "rev/revision_20251112_consolidada.md" + assert not legacy_path.exists() + + +def test_docs_analisis_agent_guides_revision_location(): + agent_path = REPO_ROOT / "docs/analisis/AGENTS.md" + assert agent_path.exists() + + agent_contents = _read(agent_path) + assert "ETA-AGENTE CODEX" in agent_contents + assert "colocar las revisiones consolidadas" in agent_contents + + +def test_eta_codex_agent_is_implemented_in_agents_tree(): + agent_module = REPO_ROOT / "scripts/coding/ai/agents/documentation/eta_codex_agent.py" + assert agent_module.exists() + + tests_path = REPO_ROOT / "scripts/coding/tests/ai/agents/documentation/test_eta_codex_agent.py" + assert tests_path.exists() + + +def test_phi3_prompt_engineering_playbook_is_published_and_linked(): + guide_path = REPO_ROOT / "docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md" + assert guide_path.exists() + + readme = _read(REPO_ROOT / "README.md") + assert "PHI3_PROMPT_ENGINEERING_PLAYBOOK.md" in readme + + prompting_index = _read(REPO_ROOT / "docs/ai_capabilities/prompting/README.md") + assert "Phi-3" in prompting_index + + +def test_codex_mcp_multi_agent_guide_is_linked(): + guide_path = REPO_ROOT / "docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md" + assert guide_path.exists() + + readme = _read(REPO_ROOT / "README.md") + assert "CODEX_MCP_MULTI_AGENT_GUIDE.md" in readme + + prompting_index = _read(REPO_ROOT / "docs/ai_capabilities/prompting/README.md") + assert "Codex MCP Multi-Agent Guide" in prompting_index + + agent_catalog = _read(REPO_ROOT / ".agent" / "agents" / "README.md") + assert "CodexMCPWorkflow Orchestrator" in agent_catalog + + +def test_issue_templates_connect_execplans_and_agents(): + templates_dir = REPO_ROOT / ".github" / "ISSUE_TEMPLATE" + assert templates_dir.exists(), "La carpeta .github/ISSUE_TEMPLATE debe existir" + + feature_template = _read(templates_dir / "feature_request.md") + assert "ExecPlan" in feature_template + assert ".agent/PLANS.md" in feature_template + + custom_template = _read(templates_dir / "custom.md") + assert ".agent/agents" in custom_template + assert "Agente" in custom_template + + bug_template = _read(templates_dir / "bug_report.md") + assert "SecurityAgent" in bug_template or "DependencyAgent" in bug_template + + +def test_ci_workflows_cover_quality_security_and_dependencies(): + workflows_dir = REPO_ROOT / ".github" / "workflows" + quality = workflows_dir / "code-quality.yml" + codeql = workflows_dir / "codeql.yml" + dependency = workflows_dir / "dependency-review.yml" + + assert quality.exists() + assert codeql.exists() + assert dependency.exists() + + quality_yaml = _read(quality) + assert "./scripts/run_all_tests.sh" in quality_yaml + assert "pytest" in quality_yaml + + codeql_yaml = _read(codeql) + assert "github/codeql-action/init" in codeql_yaml + + dependency_yaml = _read(dependency) + assert "dependency-review-action" in dependency_yaml + + +def test_readme_links_issue_templates_and_agents(): + readme = _read(REPO_ROOT / "README.md") + assert "ISSUE_TEMPLATE" in readme + assert ".agent/agents" in readme + + +def test_agent_catalog_links_to_docs_and_scripts(): + agent_readme = _read(REPO_ROOT / ".agent" / "README.md") + assert "docs/ai/SDLC_AGENTS_GUIDE.md" in agent_readme + assert "scripts/coding/ai/agents" in agent_readme + + +def test_llm_provider_agents_are_documented(): + agents_dir = REPO_ROOT / ".agent" / "agents" + providers = { + "claude_agent.md": "ClaudeAgent", + "chatgpt_agent.md": "ChatGPTAgent", + "huggingface_agent.md": "HuggingFaceAgent", + } + + catalog_contents = _read(agents_dir / "README.md") + + for filename, label in providers.items(): + agent_path = agents_dir / filename + assert agent_path.exists(), f"Falta el archivo {filename} en el catálogo de agentes" + + agent_contents = _read(agent_path) + assert "scripts/coding/ai/generators/llm_generator.py" in agent_contents + assert "docs/ai/CONFIGURACION_API_KEYS.md" in agent_contents + assert "docs/plans/EXECPLAN_codex_mcp_multi_llm.md" in agent_contents + + assert label in catalog_contents + + sdlc_guide = _read(REPO_ROOT / "docs" / "ai" / "SDLC_AGENTS_GUIDE.md") + for label in providers.values(): + assert label in sdlc_guide + + +def test_domain_agents_are_documented_and_linked(): + agents_dir = REPO_ROOT / ".agent" / "agents" + domain_agents = { + "api_agent.md": "ApiAgent", + "ui_agent.md": "UiAgent", + "infrastructure_agent.md": "InfrastructureAgent", + "docs_agent.md": "DocsAgent", + "scripts_agent.md": "ScriptsAgent", + } + + catalog_contents = _read(agents_dir / "README.md") + root_readme = _read(REPO_ROOT / ".agent" / "README.md") + sdlc_guide = _read(REPO_ROOT / "docs" / "ai" / "SDLC_AGENTS_GUIDE.md") + + execplan_path = REPO_ROOT / "docs" / "plans" / "EXECPLAN_agents_domain_alignment.md" + assert execplan_path.exists(), "Debe existir el ExecPlan de alineación por dominios" + + for filename, label in domain_agents.items(): + agent_path = agents_dir / filename + assert agent_path.exists(), f"Falta el archivo {filename}" + + contents = _read(agent_path) + assert "docs/plans/EXECPLAN_agents_domain_alignment.md" in contents + assert label in catalog_contents + assert label in root_readme + assert label in sdlc_guide + + +def test_prompt_techniques_catalog_is_linked_across_agents(): + catalog_path = REPO_ROOT / "docs" / "ai_capabilities" / "prompting" / "PROMPT_TECHNIQUES_CATALOG.md" + assert catalog_path.exists(), "Falta el catálogo de técnicas de prompting" + + catalog_contents = _read(catalog_path) + assert "Catálogo Completo de Técnicas de Prompts" in catalog_contents + + prompting_index = _read(REPO_ROOT / "docs" / "ai_capabilities" / "prompting" / "README.md") + assert "PROMPT_TECHNIQUES_CATALOG.md" in prompting_index + + root_readme = _read(REPO_ROOT / "README.md") + assert "PROMPT_TECHNIQUES_CATALOG.md" in root_readme + + agent_catalog = _read(REPO_ROOT / ".agent" / "agents" / "README.md") + assert "PROMPT_TECHNIQUES_CATALOG.md" in agent_catalog + + provider_agents = [ + "claude_agent.md", + "chatgpt_agent.md", + "huggingface_agent.md", + ] + + domain_agents = [ + "api_agent.md", + "ui_agent.md", + "infrastructure_agent.md", + "docs_agent.md", + "scripts_agent.md", + ] + + agents_dir = REPO_ROOT / ".agent" / "agents" + + for filename in provider_agents + domain_agents: + contents = _read(agents_dir / filename) + assert "PROMPT_TECHNIQUES_CATALOG.md" in contents + + sdlc_guide = _read(REPO_ROOT / "docs" / "ai" / "SDLC_AGENTS_GUIDE.md") + assert "PROMPT_TECHNIQUES_CATALOG.md" in sdlc_guide diff --git a/logs_data/SCHEMA.md b/logs_data/SCHEMA.md index ad05d83e..f1769e38 100644 --- a/logs_data/SCHEMA.md +++ b/logs_data/SCHEMA.md @@ -1,8 +1,8 @@ # JSON Log Schemas (estado manual) -**Propósito**: describir los esquemas utilizados para los JSON temporales mientras no exista automatización. +**Propósito**: describir los esquemas utilizados para los JSON temporales mientras la automatización es parcial. -> Automatización pendiente: la generación y rotación se hace manualmente hasta que exista un script oficial. +> Automatización parcial: `scripts/dora_metrics.py` genera baselines locales; la rotación sigue siendo manual. ## deployment_logs.json diff --git a/respaldo/docs_legacy/desarrollo/agentes_automatizacion.md b/respaldo/docs_legacy/desarrollo/agentes_automatizacion.md index aeae826a..f6174e5e 100644 --- a/respaldo/docs_legacy/desarrollo/agentes_automatizacion.md +++ b/respaldo/docs_legacy/desarrollo/agentes_automatizacion.md @@ -177,7 +177,7 @@ done **Cuándo se usó**: Sincronización de ramas principales y limpieza de repositorio (2025-11-05) -**Ubicación**: `.github/agents/gitops-agent.md` +**Ubicación**: `.agent/agents/gitops_agent.md` **Cómo funciona**: @@ -402,7 +402,7 @@ git branch -r # Debe mostrar solo 4 ramas **Tipo**: Agente personalizado `ReleaseAgent` -**Ubicación**: `.github/agents/release-agent.md` +**Ubicación**: `.agent/agents/release_agent.md` **Propósito**: Gestión completa del proceso de release, versionado semántico, generación de changelogs y creación de tags Git. @@ -452,7 +452,7 @@ actualiza versiones en archivos del proyecto y crea tag. **Tipo**: Agente personalizado `DependencyAgent` -**Ubicación**: `.github/agents/dependency-agent.md` +**Ubicación**: `.agent/agents/dependency_agent.md` **Propósito**: Gestión de dependencias, actualizaciones, escaneo de vulnerabilidades y auditoría de licencias. @@ -509,7 +509,7 @@ Generar reporte detallado. **Tipo**: Agente personalizado `SecurityAgent` -**Ubicación**: `.github/agents/security-agent.md` +**Ubicación**: `.agent/agents/security_agent.md` **Propósito**: Auditorías de seguridad, escaneo de vulnerabilidades, detección de secrets y análisis de amenazas según metodología STRIDE. diff --git a/respaldo/docs_legacy/qa/registros/2025_11_05_merge_ramas_gitops.md b/respaldo/docs_legacy/qa/registros/2025_11_05_merge_ramas_gitops.md index fbec5ad9..7a1c2347 100644 --- a/respaldo/docs_legacy/qa/registros/2025_11_05_merge_ramas_gitops.md +++ b/respaldo/docs_legacy/qa/registros/2025_11_05_merge_ramas_gitops.md @@ -508,7 +508,7 @@ origin/main ## Referencias -- **Agente**: `.github/agents/gitops-agent.md` +- **Agente**: `.agent/agents/gitops_agent.md` - **Runbook**: `docs/devops/runbooks/merge_y_limpieza_ramas.md` - **Script**: `scripts/complete_sync.sh` - **Registro anterior**: `docs/qa/registros/2025_11_05_merge_ramas.md` diff --git a/scripts/coding/ai/agents/documentation/__init__.py b/scripts/coding/ai/agents/documentation/__init__.py new file mode 100644 index 00000000..b598647e --- /dev/null +++ b/scripts/coding/ai/agents/documentation/__init__.py @@ -0,0 +1,9 @@ +"""Agentes de documentación enfocados en revisiones consolidadas.""" + +from .eta_codex_agent import ETACodexAgent, ValidationIssue, ValidationReport + +__all__ = [ + "ETACodexAgent", + "ValidationIssue", + "ValidationReport", +] diff --git a/scripts/coding/ai/agents/documentation/eta_codex_agent.py b/scripts/coding/ai/agents/documentation/eta_codex_agent.py new file mode 100644 index 00000000..11162d5c --- /dev/null +++ b/scripts/coding/ai/agents/documentation/eta_codex_agent.py @@ -0,0 +1,179 @@ +"""ETA-AGENTE CODEX implementation for consolidated review governance.""" + +from __future__ import annotations + +from dataclasses import dataclass +from pathlib import Path +from typing import Iterable, List, Optional + + +@dataclass(frozen=True) +class ValidationIssue: + """Represents a governance violation detected by the agent.""" + + code: str + message: str + recommendation: str + + +@dataclass(frozen=True) +class ValidationReport: + """Aggregated result for ETA-AGENTE CODEX validation.""" + + passed: bool + issues: List[ValidationIssue] + checked_reviews: List[str] + + +class ETACodexAgent: + """Agent that enforces consolidated review governance policies.""" + + REVISION_GLOB = "revision_*_consolidada.md" + + def __init__(self, repo_root: Optional[Path] = None) -> None: + self.repo_root = Path(repo_root) if repo_root else self._discover_repo_root() + + def validate(self) -> ValidationReport: + """Run all governance validations and return a consolidated report.""" + + issues: List[ValidationIssue] = [] + checked_reviews: List[str] = [] + + docs_analysis = self.repo_root / "docs" / "analisis" + if not docs_analysis.exists(): + issues.append( + ValidationIssue( + code="missing_docs_analisis_dir", + message="El directorio `docs/analisis/` no existe.", + recommendation="Crear `docs/analisis/` y mover allí las revisiones consolidadas.", + ) + ) + return ValidationReport(passed=False, issues=issues, checked_reviews=checked_reviews) + + revision_files = sorted(docs_analysis.glob(self.REVISION_GLOB)) + checked_reviews.extend( + str(path.relative_to(self.repo_root)) for path in revision_files + ) + + issues.extend(self._validate_agent_manifest(docs_analysis)) + issues.extend(self._validate_index_links(revision_files)) + issues.extend(self._detect_legacy_revisions()) + + return ValidationReport(passed=not issues, issues=issues, checked_reviews=checked_reviews) + + # --- Internal helpers ------------------------------------------------- + + def _discover_repo_root(self) -> Path: + current = Path(__file__).resolve() + for candidate in [current] + list(current.parents): + if (candidate / ".git").exists(): + return candidate + # Fallback to documentation tree parent + return current.parents[5] + + def _validate_agent_manifest(self, docs_analysis: Path) -> Iterable[ValidationIssue]: + manifest = docs_analysis / "AGENTS.md" + if not manifest.exists(): + return [ + ValidationIssue( + code="missing_agent_manifest", + message="No se encontró `docs/analisis/AGENTS.md`.", + recommendation="Crear el manifiesto del ETA-AGENTE CODEX dentro de `docs/analisis/`.", + ) + ] + + contents = manifest.read_text(encoding="utf-8") + if "ETA-AGENTE CODEX" not in contents: + return [ + ValidationIssue( + code="agent_manifest_missing_identifier", + message="El manifiesto de agentes no referencia a ETA-AGENTE CODEX.", + recommendation="Actualizar `docs/analisis/AGENTS.md` para incluir el identificador oficial.", + ) + ] + required_snippets = { + "agent_manifest_missing_components": [ + "Componentes fundamentales del agente", + "Planificación", + "Uso de herramientas", + "Sistemas de memoria", + ] + } + + issues: List[ValidationIssue] = [] + for code, snippets in required_snippets.items(): + if not all(snippet in contents for snippet in snippets): + issues.append( + ValidationIssue( + code=code, + message=( + "El manifiesto de agentes no describe planificación, herramientas y sistemas de memoria " + "como componentes esenciales." + ), + recommendation=( + "Actualizar `docs/analisis/AGENTS.md` para documentar explícitamente los componentes de " + "planificación, uso de herramientas y gestión de memoria del agente." + ), + ) + ) + + if issues: + return issues + return [] + + def _validate_index_links(self, revision_files: Iterable[Path]) -> Iterable[ValidationIssue]: + issues: List[ValidationIssue] = [] + revisions = list(revision_files) + if not revisions: + return issues + + index_path = self.repo_root / "docs" / "index.md" + if not index_path.exists(): + issues.append( + ValidationIssue( + code="missing_docs_index", + message="No existe `docs/index.md` para enlazar las revisiones consolidadas.", + recommendation="Crear `docs/index.md` y enlazar cada revisión consolidada desde `docs/analisis/`.", + ) + ) + return issues + + index_text = index_path.read_text(encoding="utf-8") + for revision in revisions: + relative_link = f"analisis/{revision.name}" + if relative_link not in index_text: + issues.append( + ValidationIssue( + code="index_missing_revision_link", + message=( + "`docs/index.md` no referencia la revisión consolidada " + f"`{relative_link}`." + ), + recommendation=( + "Agregar un enlace en `docs/index.md` dentro de la sección de documentación activa " + "apuntando a la revisión consolidada." + ), + ) + ) + return issues + + def _detect_legacy_revisions(self) -> Iterable[ValidationIssue]: + legacy_root = self.repo_root / "rev" + if not legacy_root.exists(): + return [] + + issues: List[ValidationIssue] = [] + for leftover in sorted(legacy_root.glob(self.REVISION_GLOB)): + issues.append( + ValidationIssue( + code="revision_outside_docs_analisis", + message=( + "Se detectó una revisión consolidada fuera de `docs/analisis/`: " + f"`{leftover.relative_to(self.repo_root)}`." + ), + recommendation=( + "Mover la revisión a `docs/analisis/` y eliminar la copia legacy bajo `rev/`." + ), + ) + ) + return issues diff --git a/scripts/coding/ai/generators/llm_generator.py b/scripts/coding/ai/generators/llm_generator.py index d357759c..4008d33d 100644 --- a/scripts/coding/ai/generators/llm_generator.py +++ b/scripts/coding/ai/generators/llm_generator.py @@ -8,7 +8,7 @@ import os from pathlib import Path -from typing import Any, Dict, List +from typing import Any, Dict, List, Optional from .base import Agent @@ -17,13 +17,14 @@ class LLMGenerator(Agent): """ Agente especializado en generación de tests con LLM. - Usa un LLM (Anthropic/OpenAI/Ollama) para generar código de tests + Usa un LLM (Anthropic/OpenAI/Ollama/HuggingFace) para generar código de tests siguiendo los estándares del proyecto. Providers soportados: - anthropic: Claude API (requiere ANTHROPIC_API_KEY) - openai: ChatGPT API (requiere OPENAI_API_KEY) - ollama: Modelos locales (no requiere API key) + - huggingface: Pipelines transformers (modelos fine-tuned locales/remotos) Ejemplos de configuración: @@ -45,6 +46,13 @@ class LLMGenerator(Agent): "model": "llama3.1:8b", # o "deepseek-coder-v2", "qwen2.5-coder:32b" "ollama_base_url": "http://localhost:11434" # opcional, default } + + # Hugging Face (transformers) + config = { + "llm_provider": "huggingface", + "model": "/models/TinyLlama-1.1B-qlora", # ruta local o repo-id + "hf_generate_kwargs": {"max_new_tokens": 512, "temperature": 0.2} + } """ def __init__(self, config: Dict[str, Any] = None): @@ -54,8 +62,21 @@ def __init__(self, config: Dict[str, Any] = None): self._load_env_variables() self.llm_provider = self.get_config("llm_provider", "anthropic") - self.model = self.get_config("model", "claude-sonnet-4-5-20250929") + + default_model_map = { + "anthropic": "claude-sonnet-4-5-20250929", + "openai": "gpt-4-turbo-preview", + "ollama": "llama3.1:8b", + "huggingface": None, + } + self.model = self.get_config( + "model", + default_model_map.get(self.llm_provider, "claude-sonnet-4-5-20250929") + ) self._client = None + self._hf_pipeline: Optional[Any] = None + self._hf_pipeline_model_id: Optional[str] = None + self._hf_return_full_text: bool = True def validate_input(self, input_data: Dict[str, Any]) -> List[str]: """Valida que existan planes de tests.""" @@ -74,7 +95,13 @@ def validate_input(self, input_data: Dict[str, Any]) -> List[str]: elif self.llm_provider == "anthropic": if not os.getenv("ANTHROPIC_API_KEY"): errors.append("Falta ANTHROPIC_API_KEY en variables de entorno") - # Ollama no requiere API key (es local) + elif self.llm_provider == "huggingface": + model_id = self.get_config("hf_model_id", self.model) + if not model_id: + errors.append( + "Config Hugging Face requiere 'model' o 'hf_model_id' configurado" + ) + # Ollama y Hugging Face no requieren API key (son locales) return errors @@ -279,6 +306,8 @@ def _call_llm(self, prompt: str) -> str: return self._call_openai(prompt) elif self.llm_provider == "ollama": return self._call_ollama(prompt) + elif self.llm_provider == "huggingface": + return self._call_huggingface(prompt) else: self.logger.error(f"Provider no soportado: {self.llm_provider}") return "" @@ -425,6 +454,133 @@ def _call_ollama(self, prompt: str) -> str: ) return "" + def _call_huggingface(self, prompt: str) -> str: + """Llama a un pipeline de Hugging Face (transformers).""" + model_id = self.get_config("hf_model_id", self.model) + + if not model_id: + self.logger.error( + "Config Hugging Face sin modelo definido (usa 'model' o 'hf_model_id')." + ) + return "" + + pipeline_override = self.get_config("hf_pipeline") + if pipeline_override is not None: + self._hf_pipeline = pipeline_override + self._hf_pipeline_model_id = model_id + + needs_reload = ( + self._hf_pipeline is None + or self._hf_pipeline_model_id != model_id + ) + + if needs_reload: + try: + from transformers import pipeline # type: ignore + except ImportError: + self.logger.error( + "Paquete 'transformers' no instalado. Instala transformers>=4.41." + ) + return "" + + pipeline_kwargs = dict(self.get_config("hf_pipeline_kwargs", {})) + pipeline_kwargs.setdefault("model", model_id) + + tokenizer_id = self.get_config("hf_tokenizer") + if tokenizer_id: + pipeline_kwargs.setdefault("tokenizer", tokenizer_id) + + device = self.get_config("hf_device") + if device is not None: + pipeline_kwargs.setdefault("device", device) + + self._hf_return_full_text = self.get_config( + "hf_return_full_text", + True + ) + + try: + self._hf_pipeline = pipeline("text-generation", **pipeline_kwargs) + self._hf_pipeline_model_id = model_id + except Exception as exc: # pragma: no cover - fallback defensivo + self.logger.error(f"Error creando pipeline Hugging Face: {exc}") + self._hf_pipeline = None + self._hf_pipeline_model_id = None + return "" + + if self._hf_pipeline is None: + return "" + + formatted_prompt = prompt + + if self.get_config("hf_use_chat_template", False): + try: + from transformers import AutoTokenizer # type: ignore + except ImportError: + self.logger.error( + "transformers.AutoTokenizer no disponible para aplicar chat template" + ) + else: + template_model = self.get_config("hf_template_tokenizer", model_id) + messages = self.get_config("hf_chat_messages") + if not messages: + messages = [{"role": "user", "content": prompt}] + try: + tokenizer = AutoTokenizer.from_pretrained(template_model) + formatted_prompt = tokenizer.apply_chat_template( + messages, + tokenize=False, + add_generation_prompt=True + ) + except Exception as exc: # pragma: no cover - tokenizer issues + self.logger.error( + f"No se pudo aplicar chat template Hugging Face: {exc}" + ) + formatted_prompt = prompt + + generate_kwargs = dict(self.get_config("hf_generate_kwargs", {})) + generate_kwargs.setdefault( + "max_new_tokens", + self.get_config("hf_max_new_tokens", 512) + ) + generate_kwargs.setdefault( + "temperature", + self.get_config("hf_temperature", 0.2) + ) + generate_kwargs.setdefault( + "do_sample", + self.get_config("hf_do_sample", False) + ) + if not self._hf_return_full_text: + generate_kwargs.setdefault("return_full_text", False) + + try: + outputs = self._hf_pipeline(formatted_prompt, **generate_kwargs) + except Exception as exc: + self.logger.error(f"Error ejecutando Hugging Face pipeline: {exc}") + return "" + + if not outputs: + return "" + + generated = outputs[0].get("generated_text", "") + if not generated: + return "" + + if generated.startswith(formatted_prompt): + generated = generated[len(formatted_prompt):] + + generated = generated.strip() + + if "```python" in generated: + code = generated.split("```python", 1)[1].split("```", 1)[0] + return code.strip() + if "```" in generated: + code = generated.split("```", 1)[1].split("```", 1)[0] + return code.strip() + + return generated + def apply_guardrails(self, output_data: Dict[str, Any]) -> List[str]: """Valida que el código generado sea seguro.""" errors = [] diff --git a/scripts/coding/ai/orchestrators/__init__.py b/scripts/coding/ai/orchestrators/__init__.py new file mode 100644 index 00000000..c9022a58 --- /dev/null +++ b/scripts/coding/ai/orchestrators/__init__.py @@ -0,0 +1,5 @@ +"""Paquete de orquestadores para flujos multi-agente.""" + +from .codex_mcp_workflow import CodexMCPWorkflowBuilder # noqa: F401 + +__all__ = ["CodexMCPWorkflowBuilder"] diff --git a/scripts/coding/ai/orchestrators/codex_mcp_workflow.py b/scripts/coding/ai/orchestrators/codex_mcp_workflow.py new file mode 100644 index 00000000..9f114219 --- /dev/null +++ b/scripts/coding/ai/orchestrators/codex_mcp_workflow.py @@ -0,0 +1,266 @@ +"""Builders declarativos para flujos Codex MCP multi-LLM.""" + +from __future__ import annotations + +from dataclasses import dataclass +from typing import Dict, List, Optional + + +@dataclass(frozen=True) +class _ProviderMetadata: + default_model: str + env_vars: List[Dict[str, object]] + label: str + + +class CodexMCPWorkflowBuilder: + """Genera briefs reutilizables para flujos MCP de Codex. + + El builder produce estructuras puramente declarativas que describen + cómo inicializar el servidor MCP, qué agentes participan y qué + artefactos deben existir antes de cada handoff. No realiza llamadas a + redes externas ni ejecuta `openai-agents`; simplemente estructura los + datos que un orquestador podría consumir. + """ + + _SUPPORTED_PROVIDERS: Dict[str, _ProviderMetadata] = { + "openai": _ProviderMetadata( + default_model="gpt-4.1", + env_vars=[{"name": "OPENAI_API_KEY", "required": True}], + label="ChatGPT", + ), + "anthropic": _ProviderMetadata( + default_model="claude-3-5-sonnet-20241022", + env_vars=[{"name": "ANTHROPIC_API_KEY", "required": True}], + label="Claude", + ), + "huggingface": _ProviderMetadata( + default_model="TinyLlama/TinyLlama-1.1B-Chat-v1.0", + env_vars=[{"name": "HUGGINGFACEHUB_API_TOKEN", "required": False}], + label="Hugging Face", + ), + } + + def __init__( + self, + provider: str, + *, + model: Optional[str] = None, + server_command: str = "npx", + server_args: Optional[List[str]] = None, + timeout_seconds: int = 360000, + ) -> None: + provider_key = provider.lower() + if provider_key not in self._SUPPORTED_PROVIDERS: + raise ValueError(f"Proveedor no soportado: {provider}") + + metadata = self._SUPPORTED_PROVIDERS[provider_key] + + self.provider = provider_key + self.model = model or metadata.default_model + self._metadata = metadata + self._command = server_command + self._args = server_args or ["-y", "codex", "mcp"] + self._timeout = timeout_seconds + + # ------------------------------------------------------------------ + # Información base + def required_environment(self) -> List[Dict[str, object]]: + """Devuelve la lista de variables de entorno esperadas.""" + + return list(self._metadata.env_vars) + + def server_config(self) -> Dict[str, object]: + """Configura cómo levantar el servidor MCP.""" + + return { + "command": self._command, + "args": list(self._args), + "client_session_timeout_seconds": self._timeout, + } + + # ------------------------------------------------------------------ + # Brief single-agent + def build_single_agent_brief(self) -> Dict[str, object]: + """Genera el brief single-agent descrito en la guía del usuario.""" + + designer_instructions = ( + "You are an indie game connoisseur. Produce a three sentence design " + "brief for a simple browser game that fits within about fifty lines " + "of HTML, CSS, and JavaScript. When ready, call the Game Developer " + "agent with your idea." + ) + + developer_instructions = ( + "You are an expert in building single page games using plain HTML, CSS, " + "and JavaScript. Save the implementation to index.html in the working " + "directory. Always call codex with \"approval-policy\": \"never\" " + "and \"sandbox\": \"workspace-write\" so the MCP run can write files " + "directly." + ) + + return { + "provider": self.provider, + "model": self.model, + "provider_label": self._metadata.label, + "required_env": self.required_environment(), + "server": self.server_config(), + "agents": { + "designer": { + "name": "Game Designer", + "instructions": designer_instructions, + "handoffs": ["developer"], + "model": self.model, + }, + "developer": { + "name": "Game Developer", + "instructions": developer_instructions, + "mcp_policy": { + "approval-policy": "never", + "sandbox": "workspace-write", + }, + }, + }, + "runner": { + "entry_agent": "designer", + "task": "Implement a fun new game!", + }, + } + + # ------------------------------------------------------------------ + # Brief multi-agent + def build_multi_agent_brief(self) -> Dict[str, object]: + """Genera un brief multi-agente con gating y observabilidad.""" + + base_env = self.required_environment() + + agents = { + "designer": { + "name": "Designer", + "instructions": self._designer_spec(), + "handoffs": ["project_manager"], + "tools": ["web-search"], + }, + "frontend_developer": { + "name": "Frontend Developer", + "instructions": self._frontend_spec(), + "handoffs": ["project_manager"], + }, + "backend_developer": { + "name": "Backend Developer", + "instructions": self._backend_spec(), + "handoffs": ["project_manager"], + }, + "tester": { + "name": "Tester", + "instructions": self._tester_spec(), + "handoffs": ["project_manager"], + }, + "project_manager": { + "name": "Project Manager", + "instructions": self._project_manager_spec(), + "handoffs": [ + "designer", + "frontend_developer", + "backend_developer", + "tester", + ], + }, + } + + gate_checks = [ + {"agent": "designer", "artifact": "design/design_spec.md"}, + {"agent": "frontend_developer", "artifact": "frontend/index.html"}, + {"agent": "backend_developer", "artifact": "backend/server.js"}, + {"agent": "tester", "artifact": "tests/TEST_PLAN.md"}, + ] + + return { + "provider": self.provider, + "model": self.model, + "required_env": base_env, + "server": self.server_config(), + "agents": agents, + "workflow": { + "entry_agent": "project_manager", + "gate_checks": gate_checks, + "task": self._default_task_list(), + }, + "tracing": { + "enabled": True, + "notes": ( + "Enable OpenAI Traces (or Anthropic/Hugging Face equivalents) to " + "inspect prompts, tool calls, and MCP transcripts for the team." + ), + }, + } + + # ------------------------------------------------------------------ + # Private helpers + def _designer_spec(self) -> str: + return ( + "You are the Designer. Use AGENT_TASKS.md and REQUIREMENTS.md from the " + "Project Manager as your only source of truth. Deliver design_spec.md " + "and wireframe.md inside the /design directory. When complete, transfer " + "control back to the Project Manager with transfer_to_project_manager." + "When writing files call Codex MCP with {\"approval-policy\":\"never\"," + "\"sandbox\":\"workspace-write\"}." + ) + + def _frontend_spec(self) -> str: + return ( + "You are the Frontend Developer. Implement the DOM structure described " + "by design_spec.md. Save artifacts to /frontend (index.html, styles.css, " + "game.js). Use Codex MCP file writes with {\"approval-policy\":\"never\", " + "\"sandbox\":\"workspace-write\"}. Return work to the Project Manager." + ) + + def _backend_spec(self) -> str: + return ( + "You are the Backend Developer. Implement the endpoints listed in " + "AGENT_TASKS.md and REQUIREMENTS.md using Node.js without external " + "databases. Save package.json and server.js inside /backend. Use the " + "same MCP write policy and hand off to the Project Manager when done." + ) + + def _tester_spec(self) -> str: + return ( + "You are the Tester. Build TEST_PLAN.md inside /tests and add an " + "optional automation script if requested. Validate outputs against the " + "acceptance criteria recorded in TEST.md. Use the MCP write policy and " + "handoff to the Project Manager once checks are complete." + ) + + def _project_manager_spec(self) -> str: + return ( + "You are the Project Manager. Create REQUIREMENTS.md, TEST.md, and " + "AGENT_TASKS.md in the repository root using Codex MCP with {\"approval-" + "policy\":\"never\",\"sandbox\":\"workspace-write\"}. Once the files exist, " + "handoff to the Designer via transfer_to_designer_agent. Confirm the " + "Designer produced design/design_spec.md before contacting the Frontend " + "and Backend Developers (transfer_to_frontend_developer_agent and " + "transfer_to_backend_developer_agent). Wait until frontend/index.html " + "and backend/server.js exist before transferring to the Tester via " + "transfer_to_tester_agent. Do not advance unless the required artifacts " + "are present; request rework otherwise." + ) + + def _default_task_list(self) -> str: + return ( + "Goal: Build a tiny browser game to showcase a multi-agent workflow.\n\n" + "High-level requirements:\n" + "- Single-screen game called \"Bug Busters\".\n" + "- Player clicks a moving bug to earn points.\n" + "- Game ends after 20 seconds and shows final score.\n" + "- Optional backend to store top-10 scores.\n\n" + "Roles:\n" + "- Designer: produce UI/UX spec and wireframe.\n" + "- Frontend Developer: implement UI and client logic.\n" + "- Backend Developer: implement GET /health and GET/POST /scores.\n" + "- Tester: prepare acceptance checklist and optional script.\n\n" + "Constraints:\n" + "- No external database; in-memory storage is acceptable.\n" + "- Keep artefacts readable and framework-free.\n" + "- Outputs must be saved in the directories referenced above." + ) + diff --git a/scripts/coding/ai/shared/env_loader.py b/scripts/coding/ai/shared/env_loader.py index c9224e59..2933ca94 100644 --- a/scripts/coding/ai/shared/env_loader.py +++ b/scripts/coding/ai/shared/env_loader.py @@ -80,6 +80,9 @@ def get_llm_config_from_env() -> dict: elif os.getenv("OPENAI_API_KEY"): provider = "openai" model = "gpt-4o" + elif os.getenv("HF_LOCAL_MODEL_PATH") or os.getenv("HF_MODEL_ID"): + provider = "huggingface" + model = os.getenv("HF_LOCAL_MODEL_PATH") or os.getenv("HF_MODEL_ID") elif os.getenv("OLLAMA_BASE_URL"): provider = "ollama" model = "qwen2.5-coder:32b" @@ -105,6 +108,13 @@ def get_llm_config_from_env() -> dict: provider = "ollama" model = os.getenv("OLLAMA_MODEL", "qwen2.5-coder:32b") + elif prefer_provider == "huggingface": + model = os.getenv("HF_LOCAL_MODEL_PATH") or os.getenv("HF_MODEL_ID") + if not model: + print("Warning: HF_LOCAL_MODEL_PATH/HF_MODEL_ID not found, heuristics fallback") + return None + provider = "huggingface" + else: print(f"Warning: Unknown provider '{prefer_provider}', using heuristics") return None @@ -120,6 +130,17 @@ def get_llm_config_from_env() -> dict: if provider == "ollama": config["ollama_base_url"] = os.getenv("OLLAMA_BASE_URL", "http://localhost:11434") + if provider == "huggingface": + if os.getenv("HF_MODEL_ID"): + config["hf_model_id"] = os.getenv("HF_MODEL_ID") + generate_kwargs = os.getenv("HF_GENERATE_KWARGS") + if generate_kwargs: + try: + import json + config["hf_generate_kwargs"] = json.loads(generate_kwargs) + except Exception: + print("Warning: No se pudo parsear HF_GENERATE_KWARGS, se ignora") + return config diff --git a/scripts/coding/tests/ai/agents/documentation/__init__.py b/scripts/coding/tests/ai/agents/documentation/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/scripts/coding/tests/ai/agents/documentation/test_eta_codex_agent.py b/scripts/coding/tests/ai/agents/documentation/test_eta_codex_agent.py new file mode 100644 index 00000000..e9363ddc --- /dev/null +++ b/scripts/coding/tests/ai/agents/documentation/test_eta_codex_agent.py @@ -0,0 +1,123 @@ +"""Tests para el agente ETA-AGENTE CODEX que gobierna revisiones consolidadas.""" + +from pathlib import Path +import sys + +import pytest + + +PROJECT_ROOT = Path(__file__).resolve().parents[6] +if str(PROJECT_ROOT) not in sys.path: + sys.path.insert(0, str(PROJECT_ROOT)) + + +def _write(path: Path, content: str) -> None: + path.parent.mkdir(parents=True, exist_ok=True) + path.write_text(content, encoding="utf-8") + + +def _setup_repository( + tmp_path: Path, + *, + include_agent_manifest: bool = True, + include_components_guidance: bool = True, + link_revision_in_index: bool = True, + create_legacy_revision: bool = False, +) -> Path: + repo = tmp_path / "repo" + docs = repo / "docs" + analysis = docs / "analisis" + analysis.mkdir(parents=True, exist_ok=True) + + revision = analysis / "revision_20251112_consolidada.md" + _write(revision, "# Revisión consolidada 2025-11-12\n") + + if include_agent_manifest: + if include_components_guidance: + manifest_content = """# ETA-AGENTE CODEX\n\n## Componentes fundamentales del agente\n- Planificación\n- Uso de herramientas\n- Sistemas de memoria\n""" + else: + manifest_content = "# ETA-AGENTE CODEX\n" + _write(analysis / "AGENTS.md", manifest_content) + + if link_revision_in_index: + index_content = ( + "# Índice\n\n" + "## [DOCS] Documentación activa\n\n" + "- [Revisión consolidada](analisis/revision_20251112_consolidada.md)\n" + ) + else: + index_content = "# Índice\n\n## [DOCS] Documentación activa\n\n" + _write(docs / "index.md", index_content) + + if create_legacy_revision: + legacy = repo / "rev" + legacy.mkdir(parents=True, exist_ok=True) + _write(legacy / "revision_20251112_consolidada.md", "# Copia legado\n") + + return repo + + +class TestETACodexAgent: + """Casos de validación estructural para el agente.""" + + def test_validation_passes_when_structure_compliant(self, tmp_path): + """Cuando la documentación cumple lineamientos, el agente aprueba la revisión.""" + repo = _setup_repository(tmp_path) + + from scripts.coding.ai.agents.documentation.eta_codex_agent import ETACodexAgent + + agent = ETACodexAgent(repo_root=repo) + report = agent.validate() + + assert report.passed is True + assert report.issues == [] + assert "docs/analisis/revision_20251112_consolidada.md" in report.checked_reviews + + def test_detects_revision_outside_docs_analisis(self, tmp_path): + """El agente debe marcar las revisiones que permanecen en `rev/` como incumplimiento.""" + repo = _setup_repository(tmp_path, create_legacy_revision=True) + + from scripts.coding.ai.agents.documentation.eta_codex_agent import ETACodexAgent + + agent = ETACodexAgent(repo_root=repo) + report = agent.validate() + + assert report.passed is False + codes = {issue.code for issue in report.issues} + assert "revision_outside_docs_analisis" in codes + + def test_detects_missing_agent_manifest(self, tmp_path): + """Sin `AGENTS.md` específico, la gobernanza de revisiones debe fallar.""" + repo = _setup_repository(tmp_path, include_agent_manifest=False) + + from scripts.coding.ai.agents.documentation.eta_codex_agent import ETACodexAgent + + agent = ETACodexAgent(repo_root=repo) + report = agent.validate() + + assert report.passed is False + assert any(issue.code == "missing_agent_manifest" for issue in report.issues) + + def test_detects_index_without_revision_link(self, tmp_path): + """El índice debe enlazar todas las revisiones consolidadas.""" + repo = _setup_repository(tmp_path, link_revision_in_index=False) + + from scripts.coding.ai.agents.documentation.eta_codex_agent import ETACodexAgent + + agent = ETACodexAgent(repo_root=repo) + report = agent.validate() + + assert report.passed is False + assert any(issue.code == "index_missing_revision_link" for issue in report.issues) + + def test_detects_manifest_missing_agent_components_guidance(self, tmp_path): + """El manifiesto debe explicar planificación, herramientas y memoria del agente.""" + repo = _setup_repository(tmp_path, include_components_guidance=False) + + from scripts.coding.ai.agents.documentation.eta_codex_agent import ETACodexAgent + + agent = ETACodexAgent(repo_root=repo) + report = agent.validate() + + assert report.passed is False + assert any(issue.code == "agent_manifest_missing_components" for issue in report.issues) diff --git a/scripts/coding/tests/ai/generators/test_llm_generator.py b/scripts/coding/tests/ai/generators/test_llm_generator.py index 3f24feed..39fccc2a 100644 --- a/scripts/coding/tests/ai/generators/test_llm_generator.py +++ b/scripts/coding/tests/ai/generators/test_llm_generator.py @@ -3,17 +3,55 @@ TDD Tests for LLMGenerator Tests the LLMGenerator implementation which generates test code using LLMs. -Supports Anthropic (Claude), OpenAI (ChatGPT), and Ollama (local models). +Supports Anthropic (Claude), OpenAI (ChatGPT), Ollama (local models), and +Hugging Face pipelines for fine-tuned checkpoints. Tests cover initialization, validation, LLM calls, error handling, and fallbacks. """ -import pytest import json import os +import sys from pathlib import Path +from types import ModuleType from unittest.mock import MagicMock, patch, Mock, mock_open -from scripts.ai.generators.llm_generator import LLMGenerator + +import importlib.machinery +import importlib.util +import pytest + +PROJECT_ROOT = Path(__file__).parent.parent.parent.parent.parent.parent +SCRIPTS_ROOT = PROJECT_ROOT / "scripts" +CODING_ROOT = SCRIPTS_ROOT / "coding" + +# Ensure namespace package resolution for `scripts.ai` imports used across the suite +sys.path.insert(0, str(PROJECT_ROOT)) +sys.path.insert(0, str(CODING_ROOT)) + +namespace_paths = [str(SCRIPTS_ROOT), str(CODING_ROOT)] +scripts_pkg = ModuleType("scripts") +scripts_pkg.__package__ = "scripts" +scripts_pkg.__path__ = namespace_paths +scripts_pkg.__spec__ = importlib.machinery.ModuleSpec( + name="scripts", + loader=None, + is_package=True +) +sys.modules["scripts"] = scripts_pkg + +try: + from scripts.ai.generators.llm_generator import LLMGenerator +except ModuleNotFoundError: + module_path = CODING_ROOT / "ai" / "generators" / "llm_generator.py" + spec = importlib.util.spec_from_file_location( + "scripts.ai.generators.llm_generator", + module_path + ) + module = importlib.util.module_from_spec(spec) + assert spec and spec.loader, "No se pudo cargar spec para llm_generator" + spec.loader.exec_module(module) + sys.modules["scripts.ai.generators.llm_generator"] = module + LLMGenerator = module.LLMGenerator # Fixtures @@ -124,6 +162,17 @@ def test_initialization_with_ollama_config(self): assert agent.llm_provider == "ollama" assert agent.model == "llama3.1:8b" + def test_initialization_with_huggingface_config(self): + """Should initialize with Hugging Face config.""" + config = { + "llm_provider": "huggingface", + "model": "TinyLlama-1.1B-dpo" + } + agent = LLMGenerator(config=config) + + assert agent.llm_provider == "huggingface" + assert agent.model == "TinyLlama-1.1B-dpo" + def test_initialization_with_ollama_custom_url(self): """Should initialize with Ollama custom base URL.""" config = { @@ -177,6 +226,15 @@ def test_validate_valid_input_ollama(self, sample_input_data): assert errors == [] + def test_validate_valid_input_huggingface(self, sample_input_data): + """Should accept valid input for Hugging Face pipelines.""" + config = {"llm_provider": "huggingface", "model": "TinyLlama-1.1B-dpo"} + agent = LLMGenerator(config=config) + + errors = agent.validate_input(sample_input_data) + + assert errors == [] + def test_validate_missing_test_plans(self): """Should reject input without test_plans.""" agent = LLMGenerator() @@ -219,6 +277,16 @@ def test_validate_missing_openai_api_key(self, sample_input_data): assert len(errors) > 0 assert any("openai_api_key" in err.lower() for err in errors) + def test_validate_missing_model_huggingface(self, sample_input_data): + """Should reject Hugging Face provider without model path.""" + config = {"llm_provider": "huggingface"} + agent = LLMGenerator(config=config) + + errors = agent.validate_input(sample_input_data) + + assert len(errors) > 0 + assert any("hugging face" in err.lower() for err in errors) + def test_validate_ollama_no_api_key_required(self, sample_input_data): """Should accept Ollama without API key (local model).""" with patch.dict(os.environ, {}, clear=True): @@ -474,7 +542,85 @@ def test_call_ollama_missing_response_field(self, mock_post): assert result == "" -# 5. LLM Routing Tests +# 5. Hugging Face Pipeline Tests +class TestHuggingFacePipeline: + """Tests for Hugging Face provider integration.""" + + def _build_fake_transformers(self, response_builder): + """Create a fake transformers module returning controlled responses.""" + fake_module = ModuleType("transformers") + fake_generator = MagicMock(side_effect=lambda prompt, **kwargs: [ + {"generated_text": response_builder(prompt, kwargs)} + ]) + fake_pipeline = MagicMock(return_value=fake_generator) + fake_module.pipeline = fake_pipeline + return fake_module, fake_pipeline, fake_generator + + def test_call_huggingface_extracts_code_block(self): + """Should extract python code blocks from Hugging Face responses.""" + config = {"llm_provider": "huggingface", "model": "TinyLlama"} + agent = LLMGenerator(config=config) + + fake_module, fake_pipeline, fake_generator = self._build_fake_transformers( + lambda prompt, _: f"{prompt}\n```python\nprint('hola')\n```" + ) + + with patch.dict(sys.modules, {"transformers": fake_module}): + result = agent._call_huggingface("Prompt base") + + assert result == "print('hola')" + fake_pipeline.assert_called_once() + fake_generator.assert_called_once() + + def test_call_huggingface_returns_plain_text(self): + """Should return trimmed plain text when no code block is present.""" + config = {"llm_provider": "huggingface", "model": "TinyLlama"} + agent = LLMGenerator(config=config) + + fake_module, fake_pipeline, fake_generator = self._build_fake_transformers( + lambda prompt, _: f"{prompt}\nGenerated tests" + ) + + with patch.dict(sys.modules, {"transformers": fake_module}): + result = agent._call_huggingface("Prompt base") + + assert result == "Generated tests" + fake_pipeline.assert_called_once() + fake_generator.assert_called_once() + + def test_call_huggingface_pipeline_error(self): + """Should return empty string when pipeline raises an error.""" + config = {"llm_provider": "huggingface", "model": "TinyLlama"} + agent = LLMGenerator(config=config) + + fake_module = ModuleType("transformers") + fake_pipeline = MagicMock(side_effect=RuntimeError("load error")) + fake_module.pipeline = fake_pipeline + + with patch.dict(sys.modules, {"transformers": fake_module}): + result = agent._call_huggingface("Prompt base") + + assert result == "" + fake_pipeline.assert_called_once() + + def test_call_huggingface_reuses_cached_pipeline(self): + """Should cache the pipeline between calls for performance.""" + config = {"llm_provider": "huggingface", "model": "TinyLlama"} + agent = LLMGenerator(config=config) + + fake_module, fake_pipeline, fake_generator = self._build_fake_transformers( + lambda prompt, _: f"{prompt} -> result" + ) + + with patch.dict(sys.modules, {"transformers": fake_module}): + agent._call_huggingface("Prompt 1") + agent._call_huggingface("Prompt 2") + + fake_pipeline.assert_called_once() + assert fake_generator.call_count == 2 + + +# 6. LLM Routing Tests class TestLLMRouting: """Test _call_llm() routing to correct provider.""" @@ -517,6 +663,19 @@ def test_call_llm_routes_to_ollama(self, mock_ollama): mock_ollama.assert_called_once_with("Test prompt") assert result == "generated code" + @patch('scripts.ai.generators.llm_generator.LLMGenerator._call_huggingface') + def test_call_llm_routes_to_huggingface(self, mock_hf): + """Should route to Hugging Face when provider is huggingface.""" + mock_hf.return_value = "generated code" + + config = {"llm_provider": "huggingface", "model": "TinyLlama"} + agent = LLMGenerator(config=config) + + result = agent._call_llm("Test prompt") + + mock_hf.assert_called_once_with("Test prompt") + assert result == "generated code" + def test_call_llm_unsupported_provider(self): """Should return empty string for unsupported provider.""" config = {"llm_provider": "unsupported"} diff --git a/scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py b/scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py new file mode 100644 index 00000000..f7dae786 --- /dev/null +++ b/scripts/coding/tests/ai/orchestrators/test_codex_mcp_workflow.py @@ -0,0 +1,105 @@ +"""Tests para el builder de flujos Codex MCP multi-LLM.""" + +import importlib.machinery +import sys +from pathlib import Path +from types import ModuleType + +import pytest + + +PROJECT_ROOT = Path(__file__).resolve().parents[5] +SCRIPTS_ROOT = PROJECT_ROOT / "scripts" +CODING_ROOT = SCRIPTS_ROOT / "coding" + +sys.path.insert(0, str(PROJECT_ROOT)) +sys.path.insert(0, str(SCRIPTS_ROOT)) +sys.path.insert(0, str(CODING_ROOT)) + +namespace_paths = [str(SCRIPTS_ROOT), str(CODING_ROOT)] +scripts_pkg = ModuleType("scripts") +scripts_pkg.__package__ = "scripts" +scripts_pkg.__path__ = namespace_paths +scripts_pkg.__spec__ = importlib.machinery.ModuleSpec( + name="scripts", + loader=None, + is_package=True, +) +sys.modules["scripts"] = scripts_pkg + +from scripts.coding.ai.orchestrators import codex_mcp_workflow as workflow + + +SUPPORTED_PROVIDERS = [ + ("openai", "gpt-4.1"), + ("anthropic", "claude-3-5-sonnet-20241022"), + ("huggingface", "TinyLlama/TinyLlama-1.1B-Chat-v1.0"), +] + + +@pytest.mark.parametrize("provider,expected_model", SUPPORTED_PROVIDERS) +def test_single_agent_brief_includes_mcp_flags(provider, expected_model): + builder = workflow.CodexMCPWorkflowBuilder(provider) + brief = builder.build_single_agent_brief() + + assert brief["provider"] == provider + assert brief["model"] == expected_model + + server = brief["server"] + assert server["command"] == "npx" + assert server["args"] == ["-y", "codex", "mcp"] + assert server["client_session_timeout_seconds"] == 360000 + + developer = brief["agents"]["developer"] + assert "approval-policy\": \"never\"" in developer["instructions"] + assert "sandbox\": \"workspace-write\"" in developer["instructions"] + + +def test_unknown_provider_raises_value_error(): + with pytest.raises(ValueError): + workflow.CodexMCPWorkflowBuilder("unsupported") + + +@pytest.mark.parametrize("provider,_", SUPPORTED_PROVIDERS) +def test_required_env_variables_are_declared(provider, _): + builder = workflow.CodexMCPWorkflowBuilder(provider) + env_info = builder.required_environment() + + env_names = {entry["name"] for entry in env_info} + + if provider == "openai": + assert env_names == {"OPENAI_API_KEY"} + elif provider == "anthropic": + assert env_names == {"ANTHROPIC_API_KEY"} + else: + assert "HUGGINGFACEHUB_API_TOKEN" in env_names + optional_entry = next(item for item in env_info if item["name"] == "HUGGINGFACEHUB_API_TOKEN") + assert optional_entry["required"] is False + + +@pytest.mark.parametrize("provider,_", SUPPORTED_PROVIDERS) +def test_multi_agent_brief_includes_gatekeeping(provider, _): + builder = workflow.CodexMCPWorkflowBuilder(provider) + brief = builder.build_multi_agent_brief() + + manager = brief["agents"]["project_manager"] + instructions = manager["instructions"] + assert "REQUIREMENTS.md" in instructions + assert "AGENT_TASKS.md" in instructions + assert "transfer_to_designer_agent" in instructions + assert "transfer_to_frontend_developer_agent" in instructions + assert "transfer_to_backend_developer_agent" in instructions + assert "transfer_to_tester_agent" in instructions + + gates = brief["workflow"]["gate_checks"] + expected_paths = { + "design/design_spec.md", + "frontend/index.html", + "backend/server.js", + } + actual_paths = {gate["artifact"] for gate in gates} + assert expected_paths.issubset(actual_paths) + + tracing = brief["tracing"] + assert tracing["enabled"] is True + assert "Traces" in tracing["notes"] diff --git a/scripts/coding/tests/ai/shared/test_environment_config.py b/scripts/coding/tests/ai/shared/test_environment_config.py index 1d6ae5b3..8284e812 100644 --- a/scripts/coding/tests/ai/shared/test_environment_config.py +++ b/scripts/coding/tests/ai/shared/test_environment_config.py @@ -6,9 +6,33 @@ """ import os +import sys +from pathlib import Path +from types import ModuleType +import importlib.machinery + import pytest from unittest.mock import patch, MagicMock + +PROJECT_ROOT = Path(__file__).parent.parent.parent.parent.parent.parent +SCRIPTS_ROOT = PROJECT_ROOT / "scripts" +CODING_ROOT = SCRIPTS_ROOT / "coding" + +sys.path.insert(0, str(PROJECT_ROOT)) +sys.path.insert(0, str(CODING_ROOT)) + +scripts_pkg = ModuleType("scripts") +scripts_pkg.__package__ = "scripts" +scripts_pkg.__path__ = [str(SCRIPTS_ROOT), str(CODING_ROOT)] +scripts_pkg.__spec__ = importlib.machinery.ModuleSpec( + name="scripts", + loader=None, + is_package=True +) +sys.modules["scripts"] = scripts_pkg + from scripts.ai.shared.environment_config import EnvironmentConfig, get_environment_config +from scripts.ai.shared.env_loader import get_llm_config_from_env import scripts.ai.shared.environment_config as env_module @@ -219,6 +243,47 @@ def test_production_uses_redis_with_password(self): assert cache_config["backend"] == "redis" assert "password" in cache_config + +class TestEnvLoaderHuggingFace: + """Tests de auto detección de Hugging Face en env_loader.""" + + def test_auto_detects_huggingface_provider(self): + """Debe detectar Hugging Face cuando hay modelo local configurado.""" + with patch("scripts.ai.shared.env_loader.load_env_file", MagicMock()): + with patch.dict(os.environ, { + "PREFER_LLM_PROVIDER": "auto", + "HF_LOCAL_MODEL_PATH": "/models/tiny-llama" + }, clear=True): + config = get_llm_config_from_env() + + assert config is not None + assert config["llm_provider"] == "huggingface" + assert config["model"] == "/models/tiny-llama" + + def test_prefer_huggingface_uses_model_id(self): + """Debe respetar el modelo indicado vía HF_MODEL_ID.""" + with patch("scripts.ai.shared.env_loader.load_env_file", MagicMock()): + with patch.dict(os.environ, { + "PREFER_LLM_PROVIDER": "huggingface", + "HF_MODEL_ID": "TinyLlama/TinyLlama-1.1B-Chat-v1.0" + }, clear=True): + config = get_llm_config_from_env() + + assert config is not None + assert config["llm_provider"] == "huggingface" + assert config["model"] == "TinyLlama/TinyLlama-1.1B-Chat-v1.0" + assert config["hf_model_id"] == "TinyLlama/TinyLlama-1.1B-Chat-v1.0" + + def test_prefer_huggingface_without_model_returns_none(self): + """Debe regresar None si no hay información del modelo.""" + with patch("scripts.ai.shared.env_loader.load_env_file", MagicMock()): + with patch.dict(os.environ, { + "PREFER_LLM_PROVIDER": "huggingface" + }, clear=True): + config = get_llm_config_from_env() + + assert config is None + def test_cache_can_be_disabled(self): """Cache puede deshabilitarse.""" with patch.dict(os.environ, { diff --git a/scripts/dora_metrics.py b/scripts/dora_metrics.py new file mode 100755 index 00000000..a4daa0b6 --- /dev/null +++ b/scripts/dora_metrics.py @@ -0,0 +1,242 @@ +#!/usr/bin/env python3 +"""Generate lightweight DORA metrics from the local git repository. + +This script does **not** reach external services. Instead it analyses the +current git history to produce indicative metrics that can be inspected in +JSON or Markdown form. It intentionally favours transparency over +over-promising accuracy, keeping the values simple and reproducible offline. +""" + +from __future__ import annotations + +import argparse +import json +import statistics +import subprocess +from dataclasses import dataclass +from datetime import UTC, datetime, timedelta +from pathlib import Path +from typing import Iterable, List, Optional + + +REPO_ROOT = Path(__file__).resolve().parents[1] + + +@dataclass +class Commit: + sha: str + timestamp: datetime + subject: str + + +def parse_args() -> argparse.Namespace: + parser = argparse.ArgumentParser( + description="Calcula métricas DORA usando únicamente el historial git local.", + ) + parser.add_argument("--repo", help="Repositorio GitHub (solo para referencia)") + parser.add_argument( + "--days", + type=int, + help="Número de días hacia atrás a considerar (incompatible con --start/--end)", + ) + parser.add_argument("--start", help="Fecha de inicio (YYYY-MM-DD)") + parser.add_argument("--end", help="Fecha de fin (YYYY-MM-DD, inclusive)") + parser.add_argument( + "--format", + choices=["json", "markdown"], + default="markdown", + help="Formato de salida", + ) + parser.add_argument( + "--output", + type=Path, + help="Archivo en el que guardar el resultado (stdout si se omite)", + ) + parser.add_argument( + "--docs-only", + action="store_true", + help="Limita el análisis a commits que tocan la carpeta docs/", + ) + return parser.parse_args() + + +def _parse_date(raw: Optional[str]) -> Optional[datetime]: + if not raw: + return None + try: + return datetime.fromisoformat(raw).replace(tzinfo=UTC) + except ValueError as exc: # pragma: no cover - defensive branch + raise SystemExit(f"Fecha inválida: {raw}") from exc + + +def _compute_window(args: argparse.Namespace) -> tuple[datetime, datetime, int]: + end = _parse_date(args.end) or datetime.now(UTC) + if args.days: + start = end - timedelta(days=args.days) + else: + start = _parse_date(args.start) or (end - timedelta(days=30)) + + window_days = max(1, int((end - start).total_seconds() // 86400) or 1) + return start, end, window_days + + +def _git_log(start: datetime, end: datetime, docs_only: bool) -> List[Commit]: + pretty = "%H\x1f%ct\x1f%s\x1e" + cmd = [ + "git", + "log", + f"--since={start.isoformat()}", + f"--until={end.isoformat()}", + f"--pretty={pretty}", + ] + + if docs_only: + cmd.extend(["--", "docs/"]) + + result = subprocess.run( + cmd, + cwd=REPO_ROOT, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + check=False, + ) + + if result.returncode != 0: # pragma: no cover - git not available + raise SystemExit(result.stderr.strip() or "git log failed") + + commits: List[Commit] = [] + for raw_commit in filter(None, result.stdout.split("\x1e")): + parts = [piece for piece in raw_commit.strip().split("\x1f") if piece] + if len(parts) < 3: + continue + sha, ts_raw, subject = parts[:3] + commits.append( + Commit( + sha=sha, + timestamp=datetime.fromtimestamp(int(ts_raw), tz=UTC), + subject=subject, + ) + ) + return commits + + +def _lead_time_stats(commits: Iterable[Commit], reference: datetime) -> dict: + hours = [(reference - commit.timestamp).total_seconds() / 3600 for commit in commits] + if not hours: + return { + "average_hours": 0.0, + "median_hours": 0.0, + "p95_hours": 0.0, + } + + hours_sorted = sorted(hours) + median = statistics.median(hours_sorted) + p95 = hours_sorted[int(0.95 * (len(hours_sorted) - 1))] if len(hours_sorted) > 1 else hours_sorted[0] + return { + "average_hours": round(sum(hours_sorted) / len(hours_sorted), 2), + "median_hours": round(median, 2), + "p95_hours": round(p95, 2), + } + + +def build_payload(args: argparse.Namespace) -> dict: + start, end, window_days = _compute_window(args) + commits = _git_log(start, end, docs_only=args.docs_only) + reference = datetime.now(UTC) + + commit_count = len(commits) + per_day = commit_count / window_days if window_days else 0 + per_week = per_day * 7 + + lead_time = _lead_time_stats(commits, reference) + + payload = { + "generated_at": reference.isoformat(), + "scope": "docs" if args.docs_only else "repository", + "analysis_window": { + "start": start.isoformat(), + "end": end.isoformat(), + "days": window_days, + }, + "deployment_frequency": { + "count": commit_count, + "per_day": round(per_day, 2), + "per_week": round(per_week, 2), + }, + "lead_time_for_changes": lead_time, + "change_failure_rate": { + "rate": None, + "note": "Requiere integrar datos de incidentes reales", + }, + "mean_time_to_recover": { + "hours": None, + "note": "No hay incidentes registrados en logs_data aún", + }, + "notes": [ + "Datos inferidos desde git log (sin dependencias externas)", + "Valores pensados como baseline provisional, no como métrica oficial", + ], + } + return payload + + +def to_markdown(payload: dict) -> str: + freq = payload["deployment_frequency"] + lead = payload["lead_time_for_changes"] + notes = payload["notes"] + window = payload["analysis_window"] + + lines = [ + "# DORA Metrics Report", + f"*Generated on*: {payload['generated_at']}", + f"*Scope*: {payload['scope']}", + f"*Window*: {window['start']} → {window['end']} ({window['days']} día(s))", + "", + "## Summary", + f"- Deployment frequency: {freq['count']} commits (~{freq['per_week']:.2f} por semana)", + f"- Lead time (mediana): {lead['median_hours']} h", + "- Change failure rate: datos no disponibles", + "- MTTR: datos no disponibles", + "", + "## Raw metrics", + "| Metric | Value |", + "| --- | --- |", + f"| Commits | {freq['count']} |", + f"| Commits/día | {freq['per_day']:.2f} |", + f"| Commits/semana | {freq['per_week']:.2f} |", + f"| Lead time promedio (h) | {lead['average_hours']} |", + f"| Lead time mediano (h) | {lead['median_hours']} |", + f"| Lead time p95 (h) | {lead['p95_hours']} |", + "| Change failure rate | Pendiente de instrumentar |", + "| Mean time to recover | Pendiente de instrumentar |", + "", + "## Notes", + ] + + for note in notes: + lines.append(f"- {note}") + + return "\n".join(lines) + "\n" + + +def output(payload: dict, args: argparse.Namespace) -> None: + if args.format == "json": + content = json.dumps(payload, indent=2, ensure_ascii=False) + "\n" + else: + content = to_markdown(payload) + + if args.output: + args.output.write_text(content, encoding="utf-8") + else: + print(content, end="") + + +def main() -> None: + args = parse_args() + payload = build_payload(args) + output(payload, args) + + +if __name__ == "__main__": + main() diff --git a/scripts/generate_dora_report.sh b/scripts/generate_dora_report.sh index d62304c3..9956116d 100755 --- a/scripts/generate_dora_report.sh +++ b/scripts/generate_dora_report.sh @@ -6,50 +6,35 @@ # Cron: 0 0 1 * * /path/to/scripts/generate_dora_report.sh # -set -e # Exit on error +set -euo pipefail -# Configuration -PROJECT_DIR="/home/user/IACT---project" +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +PROJECT_DIR="$(cd "$SCRIPT_DIR/.." && pwd)" REPORTS_DIR="$PROJECT_DIR/docs/dora/reports" -LOG_DIR="/var/log/iact" -GITHUB_TOKEN="${GITHUB_TOKEN:-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}" -REPO="2-Coatl/IACT---project" +LOG_DIR="${IACT_LOG_DIR:-$PROJECT_DIR/logs}" +REPO="${1:-2-Coatl/IACT---project}" -# Create directories if not exist mkdir -p "$REPORTS_DIR" mkdir -p "$LOG_DIR" -# Generate timestamp TIMESTAMP=$(date +"%Y%m") REPORT_FILE="$REPORTS_DIR/DORA_MONTHLY_$TIMESTAMP.md" LOG_FILE="$LOG_DIR/dora_cron.log" -# Log start echo "[$(date '+%Y-%m-%d %H:%M:%S')] Starting DORA monthly report generation..." | tee -a "$LOG_FILE" -# Execute DORA metrics script -cd "$PROJECT_DIR" - -export GITHUB_TOKEN="$GITHUB_TOKEN" +if [ ! -f "$PROJECT_DIR/scripts/dora_metrics.py" ]; then + echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: scripts/dora_metrics.py no encontrado" | tee -a "$LOG_FILE" + exit 1 +fi -python scripts/dora_metrics.py \ +python "$PROJECT_DIR/scripts/dora_metrics.py" \ --repo "$REPO" \ --days 30 \ --format markdown \ - > "$REPORT_FILE" 2>&1 + > "$REPORT_FILE" -# Check if report was generated -if [ -f "$REPORT_FILE" ]; then - REPORT_SIZE=$(stat -f%z "$REPORT_FILE" 2>/dev/null || stat -c%s "$REPORT_FILE") - echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: Report generated at $REPORT_FILE (${REPORT_SIZE} bytes)" | tee -a "$LOG_FILE" +REPORT_SIZE=$(stat -f%z "$REPORT_FILE" 2>/dev/null || stat -c%s "$REPORT_FILE") +echo "[$(date '+%Y-%m-%d %H:%M:%S')] SUCCESS: Report generated at $REPORT_FILE (${REPORT_SIZE} bytes)" | tee -a "$LOG_FILE" - # Optional: Commit report to git (uncomment if needed) - # git add "$REPORT_FILE" - # git commit -m "automation(dora): monthly report $TIMESTAMP" - # git push - - exit 0 -else - echo "[$(date '+%Y-%m-%d %H:%M:%S')] ERROR: Report file not created" | tee -a "$LOG_FILE" - exit 1 -fi +exit 0 diff --git a/scripts/tests/test_dora_metrics.py b/scripts/tests/test_dora_metrics.py new file mode 100644 index 00000000..d6deb793 --- /dev/null +++ b/scripts/tests/test_dora_metrics.py @@ -0,0 +1,56 @@ +import json +import subprocess +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +SCRIPT = REPO_ROOT / "scripts" / "dora_metrics.py" + + +def _run_command(*args, env=None): + result = subprocess.run( + ["python", str(SCRIPT), *args], + cwd=REPO_ROOT, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + env=env, + ) + return result + + +def test_generates_json_payload_with_expected_keys(): + result = _run_command("--days", "30", "--format", "json") + assert result.returncode == 0, result.stderr + + payload = json.loads(result.stdout) + + for key in [ + "analysis_window", + "deployment_frequency", + "change_failure_rate", + "lead_time_for_changes", + "mean_time_to_recover", + "notes", + ]: + assert key in payload + + assert payload["analysis_window"]["days"] > 0 + assert payload["deployment_frequency"]["count"] >= 0 + + +def test_supports_markdown_output(): + result = _run_command("--days", "7", "--format", "markdown") + assert result.returncode == 0, result.stderr + + stdout = result.stdout.strip() + assert "# DORA Metrics Report" in stdout + assert "Deployment frequency" in stdout + + +def test_docs_only_scope_is_reflected_in_output(): + result = _run_command("--days", "90", "--format", "json", "--docs-only") + assert result.returncode == 0, result.stderr + + payload = json.loads(result.stdout) + assert payload["scope"] == "docs" diff --git a/scripts/tests/test_verificar_servicios.py b/scripts/tests/test_verificar_servicios.py new file mode 100644 index 00000000..41f7dea8 --- /dev/null +++ b/scripts/tests/test_verificar_servicios.py @@ -0,0 +1,47 @@ +import os +import subprocess +from pathlib import Path + + +REPO_ROOT = Path(__file__).resolve().parents[2] +SCRIPT = REPO_ROOT / "scripts" / "verificar_servicios.sh" + + +def _run_script(*args, extra_env=None): + env = os.environ.copy() + if extra_env: + env.update(extra_env) + + bash_path = os.environ.get("BASH", "/bin/bash") + result = subprocess.run( + [bash_path, str(SCRIPT), *args], + cwd=REPO_ROOT, + stdout=subprocess.PIPE, + stderr=subprocess.PIPE, + text=True, + env=env, + ) + return result + + +def test_help_displays_usage_information(): + result = _run_script("--help") + assert result.returncode == 0 + assert "Script: verificar servicios" in result.stdout + assert "--dry-run" in result.stdout + + +def test_dry_run_succeeds_and_mentions_pending_checks(): + result = _run_script("--dry-run") + assert result.returncode == 0 + stdout = result.stdout + assert "[DRY-RUN]" in stdout + assert "PostgreSQL" in stdout + assert "MariaDB" in stdout + + +def test_handles_missing_clients_gracefully(): + result = _run_script("--postgres-host", "127.0.0.1", extra_env={"PATH": ""}) + assert result.returncode != 0 + assert "[ERROR] Cliente psql no encontrado" in result.stdout + assert "[ERROR] Cliente mysql no encontrado" in result.stdout diff --git a/scripts/verificar_servicios.sh b/scripts/verificar_servicios.sh new file mode 100755 index 00000000..de643d12 --- /dev/null +++ b/scripts/verificar_servicios.sh @@ -0,0 +1,156 @@ +#!/bin/bash +# Script: verificar servicios de bases de datos locales (PostgreSQL + MariaDB) +# +# Este script valida tres aspectos clave: +# 1. Disponibilidad de los clientes `psql` y `mysql`. +# 2. Conexión básica a ambas bases de datos utilizando credenciales del entorno. +# 3. Reporte compacto con códigos de salida diferenciados. +# +# Uso: +# ./scripts/verificar_servicios.sh [opciones] +# +# Opciones principales: +# --dry-run Muestra los pasos sin ejecutar conexiones reales. +# --postgres-host Host PostgreSQL (default: $DB_ANALYTICS_HOST o 127.0.0.1) +# --postgres-port Puerto PostgreSQL (default: $DB_ANALYTICS_PORT o 15432) +# --postgres-db Base PostgreSQL (default: $DB_ANALYTICS_NAME o iact_analytics) +# --postgres-user Usuario PostgreSQL (default: $DB_ANALYTICS_USER o django_user) +# --postgres-password Password PostgreSQL (default: $DB_ANALYTICS_PASSWORD o django_pass) +# --mariadb-host Host MariaDB (default: $DB_IVR_HOST o 127.0.0.1) +# --mariadb-port Puerto MariaDB (default: $DB_IVR_PORT o 13306) +# --mariadb-db Base MariaDB (default: $DB_IVR_NAME o ivr_data) +# --mariadb-user Usuario MariaDB (default: $DB_IVR_USER o django_user) +# --mariadb-password Password MariaDB (default: $DB_IVR_PASSWORD o django_pass) +# --help Muestra esta ayuda. +# +# Códigos de salida: +# 0 -> Todo OK. +# 1 -> Clientes instalados pero alguna conexión falló. +# 2 -> Clientes requeridos no disponibles en PATH. +# +# El modo `--dry-run` permite validar configuraciones durante CI sin depender de +# bases de datos levantadas. + +set -u + +POSTGRES_HOST="${DB_ANALYTICS_HOST:-127.0.0.1}" +POSTGRES_PORT="${DB_ANALYTICS_PORT:-15432}" +POSTGRES_DB="${DB_ANALYTICS_NAME:-iact_analytics}" +POSTGRES_USER="${DB_ANALYTICS_USER:-django_user}" +POSTGRES_PASSWORD="${DB_ANALYTICS_PASSWORD:-django_pass}" + +MARIADB_HOST="${DB_IVR_HOST:-127.0.0.1}" +MARIADB_PORT="${DB_IVR_PORT:-13306}" +MARIADB_DB="${DB_IVR_NAME:-ivr_data}" +MARIADB_USER="${DB_IVR_USER:-django_user}" +MARIADB_PASSWORD="${DB_IVR_PASSWORD:-django_pass}" + +DRY_RUN=false + +usage() { + sed -n '1,40p' "$0" | sed 's/^# //' +} + +while [[ $# -gt 0 ]]; do + case "$1" in + --dry-run) + DRY_RUN=true + shift + ;; + --postgres-host) + POSTGRES_HOST="$2"; shift 2;; + --postgres-port) + POSTGRES_PORT="$2"; shift 2;; + --postgres-db) + POSTGRES_DB="$2"; shift 2;; + --postgres-user) + POSTGRES_USER="$2"; shift 2;; + --postgres-password) + POSTGRES_PASSWORD="$2"; shift 2;; + --mariadb-host) + MARIADB_HOST="$2"; shift 2;; + --mariadb-port) + MARIADB_PORT="$2"; shift 2;; + --mariadb-db) + MARIADB_DB="$2"; shift 2;; + --mariadb-user) + MARIADB_USER="$2"; shift 2;; + --mariadb-password) + MARIADB_PASSWORD="$2"; shift 2;; + --help|-h) + usage + exit 0 + ;; + *) + echo "[ERROR] Opción desconocida: $1" >&2 + usage + exit 1 + ;; + esac +done + +echo "========================================================================" +echo "Script: verificar servicios de bases de datos" +echo "========================================================================" +echo "[INFO] PostgreSQL => ${POSTGRES_USER}@${POSTGRES_HOST}:${POSTGRES_PORT}/${POSTGRES_DB}" +echo "[INFO] MariaDB => ${MARIADB_USER}@${MARIADB_HOST}:${MARIADB_PORT}/${MARIADB_DB}" +echo "" + +missing=0 +for client in psql mysql; do + if ! command -v "$client" >/dev/null 2>&1; then + echo "[ERROR] Cliente $client no encontrado en PATH" + missing=1 + else + echo "[OK] Cliente $client disponible" + fi +done + +if [[ "$missing" -eq 1 && "$DRY_RUN" == true ]]; then + echo "" + echo "[ATENCION] Clientes faltantes detectados, pero continuamos por tratarse de un dry-run." +fi + +if [[ "$missing" -eq 1 && "$DRY_RUN" != true ]]; then + echo "" + echo "[ATENCION] Ejecuta el runbook manual si necesitas más contexto: docs/operaciones/verificar_servicios.md" + exit 2 +fi + +if [[ "$DRY_RUN" == true ]]; then + echo "[DRY-RUN] Validación de conectividad omitida." + echo "[DRY-RUN] Ejecutarías:" + echo " PGPASSWORD=**** psql -h $POSTGRES_HOST -p $POSTGRES_PORT -U $POSTGRES_USER -d $POSTGRES_DB -c 'SELECT 1;'" + echo " mysql -h $MARIADB_HOST -P $MARIADB_PORT -u $MARIADB_USER -p**** -e 'SELECT 1;' $MARIADB_DB" + exit 0 +fi + +EXIT_CODE=0 + +echo "[INFO] Verificando PostgreSQL..." +PGPASSWORD="$POSTGRES_PASSWORD" psql -h "$POSTGRES_HOST" -p "$POSTGRES_PORT" -U "$POSTGRES_USER" -d "$POSTGRES_DB" -c "SELECT 1;" >/dev/null 2>&1 +if [[ $? -eq 0 ]]; then + echo "[OK] PostgreSQL respondió correctamente" +else + echo "[FAIL] No fue posible conectar a PostgreSQL" + EXIT_CODE=1 +fi + +echo "[INFO] Verificando MariaDB..." +mysql -h "$MARIADB_HOST" -P "$MARIADB_PORT" -u "$MARIADB_USER" -p"$MARIADB_PASSWORD" -e "SELECT 1;" "$MARIADB_DB" >/dev/null 2>&1 +if [[ $? -eq 0 ]]; then + echo "[OK] MariaDB respondió correctamente" +else + echo "[FAIL] No fue posible conectar a MariaDB" + EXIT_CODE=1 +fi + +if [[ "$EXIT_CODE" -eq 0 ]]; then + echo "" + echo "[OK] Todos los servicios están operativos" +else + echo "" + echo "[ATENCION] Revisa el runbook docs/operaciones/verificar_servicios.md para pasos de troubleshooting" +fi + +exit "$EXIT_CODE" From ef39c31f5a9a5d67826216318f22dd5be0370806 Mon Sep 17 00:00:00 2001 From: Coatl <121911012+2-Coatl@users.noreply.github.com> Date: Thu, 13 Nov 2025 01:02:30 -0600 Subject: [PATCH 2/2] feat(ai): add multi-llm context management toolkit --- .agent/agents/README.md | 19 +- .agent/agents/api_agent.md | 1 + .agent/agents/chatgpt_agent.md | 1 + .agent/agents/claude_agent.md | 1 + .agent/agents/docs_agent.md | 3 +- .agent/agents/huggingface_agent.md | 1 + .agent/agents/infrastructure_agent.md | 1 + .agent/agents/scripts_agent.md | 1 + .agent/agents/ui_agent.md | 3 +- README.md | 3 + docs/ai/SDLC_AGENTS_GUIDE.md | 16 +- .../CONTEXT_MANAGEMENT_PLAYBOOK.md | 132 +++++++++ docs/ai_capabilities/prompting/README.md | 4 + docs/index.md | 1 + .../EXECPLAN_context_memory_management.md | 73 +++++ docs/testing/test_documentation_alignment.py | 38 +++ scripts/coding/ai/shared/context_sessions.py | 270 ++++++++++++++++++ .../tests/ai/shared/test_context_sessions.py | 159 +++++++++++ 18 files changed, 709 insertions(+), 18 deletions(-) create mode 100644 docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md create mode 100644 docs/plans/EXECPLAN_context_memory_management.md create mode 100644 scripts/coding/ai/shared/context_sessions.py create mode 100644 scripts/coding/tests/ai/shared/test_context_sessions.py diff --git a/.agent/agents/README.md b/.agent/agents/README.md index 943a8b43..23e09d93 100644 --- a/.agent/agents/README.md +++ b/.agent/agents/README.md @@ -16,7 +16,8 @@ Estos agentes vinculan la planificación (`.agent/PLANS.md`), la configuración - Configuración en `docs/ai/CONFIGURACION_API_KEYS.md` (`ANTHROPIC_API_KEY`). - ExecPlan vivo: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. - Scripts: `scripts/coding/ai/generators/llm_generator.py` (`llm_provider="anthropic"`) y `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. - - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` y `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`. + - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` y `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`. + - Código reutilizable: `scripts/coding/ai/shared/context_sessions.py` para trimming/summarizing multi-LLM. #### ChatGPTAgent @@ -26,7 +27,8 @@ Estos agentes vinculan la planificación (`.agent/PLANS.md`), la configuración - Configuración en `docs/ai/CONFIGURACION_API_KEYS.md` (`OPENAI_API_KEY`). - ExecPlan: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. - Scripts: `scripts/coding/ai/generators/llm_generator.py` (`llm_provider="openai"`) y `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. - - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` y `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`. + - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` y `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`. + - Código reutilizable: `scripts/coding/ai/shared/context_sessions.py` para trimming/summarizing multi-LLM. #### HuggingFaceAgent @@ -36,7 +38,8 @@ Estos agentes vinculan la planificación (`.agent/PLANS.md`), la configuración - Configuración en `docs/ai/CONFIGURACION_API_KEYS.md` (`HF_LOCAL_MODEL_PATH`, `HF_MODEL_ID`, `HUGGINGFACEHUB_API_TOKEN`). - ExecPlan: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. - Scripts: `scripts/coding/ai/generators/llm_generator.py` (`llm_provider="huggingface"`) y `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. - - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md` y `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`. + - Guías: `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`, `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` y `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`. + - Código reutilizable: `scripts/coding/ai/shared/context_sessions.py` para trimming/summarizing multi-LLM. ### Agentes por dominio @@ -46,31 +49,31 @@ Los siguientes agentes conectan la estructura del repositorio (api, ui, infrastr - **Archivo**: `api_agent.md` - **Directorio base**: `api/` -- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. +- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai/SDLC_AGENTS_GUIDE.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`, `scripts/coding/ai/shared/context_sessions.py`, `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. #### UiAgent (Frontend) - **Archivo**: `ui_agent.md` - **Directorio base**: `ui/` -- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md`, `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`. +- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md`, `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`, `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`, `scripts/coding/ai/shared/context_sessions.py`. #### InfrastructureAgent - **Archivo**: `infrastructure_agent.md` - **Directorio base**: `infrastructure/` -- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/gobernanza/metodologias/agentes_automatizacion.md`, planes `SPEC_INFRA_*`. +- **Relaciones clave**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`, `docs/gobernanza/metodologias/agentes_automatizacion.md`, `scripts/coding/ai/shared/context_sessions.py`, planes `SPEC_INFRA_*`. #### DocsAgent - **Archivo**: `docs_agent.md` - **Directorio base**: `docs/` -- **Relaciones clave**: `docs/analisis/AGENTS.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `scripts/coding/ai/agents/documentation/eta_codex_agent.py`, `docs/testing/test_documentation_alignment.py`. +- **Relaciones clave**: `docs/analisis/AGENTS.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`, `scripts/coding/ai/shared/context_sessions.py`, `scripts/coding/ai/agents/documentation/eta_codex_agent.py`, `docs/testing/test_documentation_alignment.py`. #### ScriptsAgent - **Archivo**: `scripts_agent.md` - **Directorio base**: `scripts/` -- **Relaciones clave**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/scripts/README.md`, `scripts/coding/ai/generators/llm_generator.py`. +- **Relaciones clave**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`, `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`, `docs/scripts/README.md`, `scripts/coding/ai/shared/context_sessions.py`, `scripts/coding/ai/generators/llm_generator.py`. ### 1. GitOpsAgent diff --git a/.agent/agents/api_agent.md b/.agent/agents/api_agent.md index 38bb1199..1c4cc2c6 100644 --- a/.agent/agents/api_agent.md +++ b/.agent/agents/api_agent.md @@ -8,6 +8,7 @@ Guiar cualquier automatización relacionada con el backend (`api/`) asegurando q - **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md` (relación dominio ↔ agentes) y `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` (estrategia multi-LLM). - **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` indica qué técnicas aplicar con Claude, ChatGPT u Hugging Face antes de generar especificaciones para la API. +- **Gestión de contexto**: `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md` y `scripts/coding/ai/shared/context_sessions.py` coordinan trimming/summarization para flujos prolongados de soporte o incidentes. - **Guías SDLC**: `docs/ai/SDLC_AGENTS_GUIDE.md` y `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` para coordinación multi-agente. - **Scripts**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` (briefs de trabajo) y `scripts/coding/ai/generators/llm_generator.py` (TDD asistido). - **Config**: variables en `.env` gestionadas por `scripts/coding/ai/shared/env_loader.py` (autodetección de `OPENAI_API_KEY`, `ANTHROPIC_API_KEY`, `HUGGINGFACEHUB_API_TOKEN`). diff --git a/.agent/agents/chatgpt_agent.md b/.agent/agents/chatgpt_agent.md index 8fda5ede..6ef864fe 100644 --- a/.agent/agents/chatgpt_agent.md +++ b/.agent/agents/chatgpt_agent.md @@ -9,6 +9,7 @@ Centralizar el uso de modelos ChatGPT/OpenAI dentro de los flujos de automatizac - **Configuración de credenciales**: `docs/ai/CONFIGURACION_API_KEYS.md` incluye los pasos para definir `OPENAI_API_KEY` y habilitar modos híbridos. - **ExecPlan vivo**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` mantiene la estrategia multi-LLM y debe actualizarse cuando cambien las capacidades o defaults de OpenAI. - **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` consolida las técnicas multi-LLM antes de personalizar prompts para ChatGPT. +- **Gestión de contexto**: `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md` y `scripts/coding/ai/shared/context_sessions.py` definen trimming y summarization compatibles con OpenAI. - **Agente generador de tests**: `scripts/coding/ai/generators/llm_generator.py` soporta `llm_provider="openai"` para generar pruebas o documentación asistida con ChatGPT. - **Builder MCP**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` emite briefs con banderas MCP y modelos recomendados (por ejemplo `gpt-5`) para OpenAI. - **Guía operativa**: `docs/ai/SDLC_AGENTS_GUIDE.md` detalla cuándo alternar entre modos heurísticos y LLM. diff --git a/.agent/agents/claude_agent.md b/.agent/agents/claude_agent.md index 807718ca..35f330b8 100644 --- a/.agent/agents/claude_agent.md +++ b/.agent/agents/claude_agent.md @@ -9,6 +9,7 @@ Orquestar las integraciones con modelos Claude (Anthropic) dentro del flujo SDLC - **Configuración de credenciales**: `docs/ai/CONFIGURACION_API_KEYS.md` describe cómo declarar `ANTHROPIC_API_KEY` en `.env` y validar la detección automática del proveedor. - **ExecPlan vivo**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` resume la estrategia multi-LLM y mantiene el historial de decisiones para Codex MCP. - **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` reúne las técnicas multi-LLM recomendadas antes de diseñar prompts especializados para Claude. +- **Gestión de contexto**: `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md` y `scripts/coding/ai/shared/context_sessions.py` definen trimming y summarization compartidos entre proveedores. - **Agente generador de tests**: `scripts/coding/ai/generators/llm_generator.py` soporta `llm_provider="anthropic"` y usa Claude como backend por defecto. - **Builder MCP**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` genera briefs single/multi-agent asegurando banderas MCP correctas cuando el proveedor es Anthropic. - **Guía operativa**: `docs/ai/SDLC_AGENTS_GUIDE.md` contiene los lineamientos de uso y compara el modo LLM vs heurístico. diff --git a/.agent/agents/docs_agent.md b/.agent/agents/docs_agent.md index 236f30e2..e7ed15f9 100644 --- a/.agent/agents/docs_agent.md +++ b/.agent/agents/docs_agent.md @@ -9,7 +9,8 @@ Garantizar que los cambios en `docs/` sigan la gobernanza del ETA-AGENTE CODEX y - **Agente rector**: `docs/analisis/AGENTS.md` (ETA-AGENTE CODEX) y `scripts/coding/ai/agents/documentation/eta_codex_agent.py`. - **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. - **Pruebas**: `docs/testing/test_documentation_alignment.py` asegura consistencia de enlaces y ubicación. -- **Playbooks**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md`. +- **Playbooks**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md`, `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md`. +- **Sesiones de contexto**: `scripts/coding/ai/shared/context_sessions.py` para mantener resúmenes consistentes en revisiones prolongadas. ## Procedimiento Recomendado diff --git a/.agent/agents/huggingface_agent.md b/.agent/agents/huggingface_agent.md index 0507c2f8..36a1a84a 100644 --- a/.agent/agents/huggingface_agent.md +++ b/.agent/agents/huggingface_agent.md @@ -9,6 +9,7 @@ Guiar el uso de modelos Hugging Face (locales o alojados) dentro de los pipeline - **Configuración de entorno**: `docs/ai/CONFIGURACION_API_KEYS.md` detalla cómo definir rutas locales (`HF_LOCAL_MODEL_PATH`) o `HF_MODEL_ID` y cuándo se requiere `HUGGINGFACEHUB_API_TOKEN`. - **ExecPlan vivo**: `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` mantiene la estrategia para balancear los tres proveedores y debe reflejar cualquier cambio en modelos Hugging Face. - **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` consolida las técnicas multi-LLM que deben adaptarse antes de aplicar prompt engineering específico (p. ej. TinyLlama o Phi-3). +- **Gestión de contexto**: `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md` y `scripts/coding/ai/shared/context_sessions.py` cubren trimming/summarization para sesiones largas en modelos locales. - **Agente generador de tests**: `scripts/coding/ai/generators/llm_generator.py` soporta `llm_provider="huggingface"` y permite reutilizar modelos QLoRA o checkpoints locales. - **Builder MCP**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` expone defaults y banderas MCP al usar el proveedor `huggingface`. - **Guías de capacidad**: diff --git a/.agent/agents/infrastructure_agent.md b/.agent/agents/infrastructure_agent.md index ca8980b8..b8d88b3f 100644 --- a/.agent/agents/infrastructure_agent.md +++ b/.agent/agents/infrastructure_agent.md @@ -8,6 +8,7 @@ Coordinar automatizaciones relacionadas con `infrastructure/`, incluyendo IaC, p - **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/plans/EXECPLAN_codex_mcp_multi_llm.md` y los planes específicos de infraestructura (`docs/plans/SPEC_INFRA_*.md`). - **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` sirve como guía para seleccionar técnicas multi-LLM cuando la automatización afecta pipelines o servicios usados por los modelos. +- **Gestión de contexto**: `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md` y `scripts/coding/ai/shared/context_sessions.py` documentan la memoria compartida entre incidentes prolongados y runbooks de infraestructura. - **Gobernanza**: `docs/gobernanza/metodologias/agentes_automatizacion.md` y runbooks en `docs/operaciones/`. - **Agentes complementarios**: `DependencyAgent` para escaneos de paquetes, `ReleaseAgent` para coordinaciones de despliegue, `SecurityAgent` (si aplica) para hardening. - **Scripts**: `scripts/infrastructure/` (si existe) y pipelines en `infrastructure/`. diff --git a/.agent/agents/scripts_agent.md b/.agent/agents/scripts_agent.md index d622a566..4737ef94 100644 --- a/.agent/agents/scripts_agent.md +++ b/.agent/agents/scripts_agent.md @@ -8,6 +8,7 @@ Orquestar cambios en `scripts/` garantizando que las automatizaciones, generador - **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md`, `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. - **Catálogo de prompts**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md` para seleccionar estrategias multi-LLM antes de automatizar generadores o validadores. +- **Memoria de contexto**: `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md` y `scripts/coding/ai/shared/context_sessions.py` habilitan sesiones compartidas en herramientas que atienden hilos extensos. - **Código**: `scripts/coding/ai/` (generators, orchestrators, shared utilities) y `scripts/tests/`. - **Pruebas**: `pytest scripts/coding/tests/...` y `pytest scripts/tests/...`. - **Documentación**: `docs/scripts/README.md`, `docs/scripts/SCRIPTS_MATRIX.md` y `docs/operaciones/verificar_servicios.md`. diff --git a/.agent/agents/ui_agent.md b/.agent/agents/ui_agent.md index 7cee780e..901fc2f6 100644 --- a/.agent/agents/ui_agent.md +++ b/.agent/agents/ui_agent.md @@ -7,7 +7,8 @@ Alinear el trabajo automatizado sobre el frontend (`ui/`) con las prácticas de ## Integraciones Clave - **ExecPlans**: `docs/plans/EXECPLAN_agents_domain_alignment.md` y `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. -- **Playbooks**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md` y `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`. +- **Playbooks**: `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, `docs/ai_capabilities/prompting/CODE_GENERATION_GUIDE.md`, `docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md` y `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md` (memoria de contexto compartida con backend/infrastructure). +- **Sesiones de contexto**: `scripts/coding/ai/shared/context_sessions.py` para trimming/summarization cuando los flujos UX requieren iteraciones largas. - **Orquestación**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` (multi-agente) y `scripts/coding/ai/generators/llm_generator.py` (generación guiada por TDD). - **Documentación UX**: briefs y wireframes creados por el Designer Agent se ubican en `docs/` o `design/` según el ExecPlan activo. diff --git a/README.md b/README.md index 3121949d..8afa3306 100644 --- a/README.md +++ b/README.md @@ -89,6 +89,9 @@ DB_IVR_PASSWORD=django_pass > [`docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`](docs/ai_capabilities/prompting/PHI3_PROMPT_ENGINEERING_PLAYBOOK.md). > Para técnicas de prompting transversales a todos los proveedores revisa el catálogo > multi-LLM en [`docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`](docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md). +> Para memoria de contexto y manejo de sesiones largas (trimming/summarization), consulta +> [`docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`](docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md) +> y reutiliza las clases disponibles en [`scripts/coding/ai/shared/context_sessions.py`](scripts/coding/ai/shared/context_sessions.py). ### 2. Ejecutar migraciones diff --git a/docs/ai/SDLC_AGENTS_GUIDE.md b/docs/ai/SDLC_AGENTS_GUIDE.md index 76d755b6..a7b60e1e 100644 --- a/docs/ai/SDLC_AGENTS_GUIDE.md +++ b/docs/ai/SDLC_AGENTS_GUIDE.md @@ -128,9 +128,9 @@ config = { Para asegurar coherencia entre planificación, credenciales y herramientas, consulta las fichas específicas en `.agent/agents/`: -- **ClaudeAgent** (`.agent/agents/claude_agent.md`): describe el flujo completo cuando `llm_provider="anthropic"`, enlazando el catálogo `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, la configuración de `ANTHROPIC_API_KEY`, el uso del `LLMGenerator` y las orquestaciones Codex MCP de `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. -- **ChatGPTAgent** (`.agent/agents/chatgpt_agent.md`): guía las integraciones con modelos GPT/OpenAI, combina el catálogo `PROMPT_TECHNIQUES_CATALOG.md` con `OPENAI_API_KEY` y referencia `scripts/coding/ai/orchestrators/codex_mcp_workflow.py`. -- **HuggingFaceAgent** (`.agent/agents/huggingface_agent.md`): centraliza el trabajo con modelos locales o alojados en Hugging Face, relacionando `PROMPT_TECHNIQUES_CATALOG.md`, rutas (`HF_LOCAL_MODEL_PATH`, `HF_MODEL_ID`) y playbooks específicos (`PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`). +- **ClaudeAgent** (`.agent/agents/claude_agent.md`): describe el flujo completo cuando `llm_provider="anthropic"`, enlazando el catálogo `docs/ai_capabilities/prompting/PROMPT_TECHNIQUES_CATALOG.md`, la configuración de `ANTHROPIC_API_KEY`, el uso del `LLMGenerator`, la memoria de contexto documentada en `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md` y las orquestaciones Codex MCP de `docs/plans/EXECPLAN_codex_mcp_multi_llm.md`. +- **ChatGPTAgent** (`.agent/agents/chatgpt_agent.md`): guía las integraciones con modelos GPT/OpenAI, combina el catálogo `PROMPT_TECHNIQUES_CATALOG.md`, el playbook de contexto multi-LLM (`CONTEXT_MANAGEMENT_PLAYBOOK.md`), `OPENAI_API_KEY` y referencia `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` junto a `scripts/coding/ai/shared/context_sessions.py`. +- **HuggingFaceAgent** (`.agent/agents/huggingface_agent.md`): centraliza el trabajo con modelos locales o alojados en Hugging Face, relacionando `PROMPT_TECHNIQUES_CATALOG.md`, rutas (`HF_LOCAL_MODEL_PATH`, `HF_MODEL_ID`), el playbook `PHI3_PROMPT_ENGINEERING_PLAYBOOK.md` y la guía de contexto compartido `CONTEXT_MANAGEMENT_PLAYBOOK.md`. Estas fichas son complementarias a esta guía y deben revisarse antes de ejecutar tareas multi-LLM. @@ -138,11 +138,11 @@ Estas fichas son complementarias a esta guía y deben revisarse antes de ejecuta Para alinear la arquitectura del repositorio con los agentes automatizados, consulta también las fichas por dominio en `.agent/agents/`: -- **ApiAgent** (`api_agent.md`): centraliza la coordinación del backend (`api/`) con los ExecPlans `EXECPLAN_agents_domain_alignment.md`, `EXECPLAN_codex_mcp_multi_llm.md`, el catálogo `PROMPT_TECHNIQUES_CATALOG.md` y los briefs generados por `CodexMCPWorkflowBuilder`. -- **UiAgent** (`ui_agent.md`): une los entregables del Designer Agent con la implementación en `ui/`, reutilizando los playbooks de prompting (`PROMPT_TECHNIQUES_CATALOG.md`, `CODE_GENERATION_GUIDE.md`, `PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`). -- **InfrastructureAgent** (`infrastructure_agent.md`): orquesta cambios en `infrastructure/` en conjunto con los agentes operativos (Dependency, Release, Security), el catálogo `PROMPT_TECHNIQUES_CATALOG.md` y los planes `SPEC_INFRA_*`. -- **DocsAgent** (`docs_agent.md`): asegura que toda modificación en `docs/` respete al ETA-AGENTE CODEX, el catálogo `PROMPT_TECHNIQUES_CATALOG.md` y los validadores de documentación. -- **ScriptsAgent** (`scripts_agent.md`): gobierna la evolución de `scripts/` manteniendo el enfoque TDD, el catálogo `PROMPT_TECHNIQUES_CATALOG.md` y la sincronización con los generadores/orquestadores LLM. +- **ApiAgent** (`api_agent.md`): centraliza la coordinación del backend (`api/`) con los ExecPlans `EXECPLAN_agents_domain_alignment.md`, `EXECPLAN_codex_mcp_multi_llm.md`, el catálogo `PROMPT_TECHNIQUES_CATALOG.md`, el playbook `CONTEXT_MANAGEMENT_PLAYBOOK.md` y los briefs generados por `CodexMCPWorkflowBuilder`. +- **UiAgent** (`ui_agent.md`): une los entregables del Designer Agent con la implementación en `ui/`, reutilizando los playbooks de prompting (`PROMPT_TECHNIQUES_CATALOG.md`, `CODE_GENERATION_GUIDE.md`, `PHI3_PROMPT_ENGINEERING_PLAYBOOK.md`) y las sesiones de contexto descritas en `CONTEXT_MANAGEMENT_PLAYBOOK.md`. +- **InfrastructureAgent** (`infrastructure_agent.md`): orquesta cambios en `infrastructure/` en conjunto con los agentes operativos (Dependency, Release, Security), el catálogo `PROMPT_TECHNIQUES_CATALOG.md`, el playbook `CONTEXT_MANAGEMENT_PLAYBOOK.md` y los planes `SPEC_INFRA_*`. +- **DocsAgent** (`docs_agent.md`): asegura que toda modificación en `docs/` respete al ETA-AGENTE CODEX, el catálogo `PROMPT_TECHNIQUES_CATALOG.md`, la guía de contexto multi-LLM y los validadores de documentación. +- **ScriptsAgent** (`scripts_agent.md`): gobierna la evolución de `scripts/` manteniendo el enfoque TDD, el catálogo `PROMPT_TECHNIQUES_CATALOG.md`, el playbook `CONTEXT_MANAGEMENT_PLAYBOOK.md` y la sincronización con los generadores/orquestadores LLM. Cada vez que inicies un ExecPlan nuevo, referencia tanto la ficha del proveedor LLM como la del dominio involucrado para mantener la trazabilidad completa. diff --git a/docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md b/docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md new file mode 100644 index 00000000..0fd087a9 --- /dev/null +++ b/docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md @@ -0,0 +1,132 @@ +# Context Management Playbook + +Esta guía describe cómo gestionar memoria de contexto en agentes largos utilizando las sesiones `TrimmingSession` y `SummarizingSession` incluidas en `scripts/coding/ai/shared/context_sessions.py`. El objetivo es ofrecer una estrategia uniforme para Claude (Anthropic), ChatGPT (OpenAI) y los modelos operados desde Hugging Face, asegurando coherencia, costos predecibles y trazas auditables en cualquier dominio (`api/`, `ui/`, `infrastructure/`, `docs/`, `scripts/`). + +## 1. Por qué importa el contexto + +- **Coherencia sostenida**: los agentes mantienen el objetivo actual sin reciclar historiales desactualizados. +- **Precisión en llamadas a herramientas**: un contexto curado reduce reintentos, tiempos de espera y errores de parámetros. +- **Latencia y costos controlados**: menos tokens por turno implican tiempos de respuesta y facturación estables. +- **Mitigación de alucinaciones**: los resúmenes sirven como “cuartos limpios” que corrigen hechos dudosos antes de seguir iterando. +- **Observabilidad**: historiales acotados facilitan diffs de sesiones, reproducen fallos y habilitan evaluaciones comparables. + +## 2. Relación con los agentes del repositorio + +- `ClaudeAgent`, `ChatGPTAgent` y `HuggingFaceAgent` (en `.agent/agents/`) referencian este playbook como política oficial de memoria. +- Los agentes de dominio (`ApiAgent`, `UiAgent`, `InfrastructureAgent`, `DocsAgent`, `ScriptsAgent`) delegan en estas sesiones cuando ejecutan planes desde sus ExecPlans. +- `CodexMCPWorkflowBuilder` puede envolver cualquiera de las sesiones para mantener threads extensos generados por Codex MCP. + +## 3. Preparativos y dependencias + +1. Configura las claves descritas en `docs/ai/CONFIGURACION_API_KEYS.md` para el proveedor que vayas a usar. +2. Instala el SDK correspondiente: + ```bash + pip install openai-agents openai + ``` +3. Opcional: registra claves adicionales (`ANTHROPIC_API_KEY`, `HUGGINGFACEHUB_API_TOKEN`) si alternas entre proveedores. +4. Estructura tu `.env` siguiendo `docs/ai_capabilities/orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md` si ejecutas agentes MCP. + +## 4. Sesiones con recorte (`TrimmingSession`) + +`TrimmingSession` conserva únicamente los últimos *N* turnos reales del usuario (un turno = mensaje del usuario + respuestas y herramientas hasta el siguiente usuario). Se recomienda para flujos operativos donde cada paso es independiente. + +```python +from scripts.coding.ai.shared.context_sessions import TrimmingSession + +session = TrimmingSession("customer-support", max_turns=3) +await session.add_items([ + {"role": "user", "content": "Primer problema"}, + {"role": "assistant", "content": "Respuesta"}, +]) +# ... +recent_items = await session.get_items() +``` + +**Ventajas** +- Determinismo total: sin resúmenes ni llamadas adicionales. +- Sin latencia extra: no se invocan modelos adicionales para resumir. +- Ideal para automatizaciones de soporte, CRM o scripts internos de infraestructura. + +**Limitaciones** +- Olvida de forma abrupta cualquier restricción o identificador anterior a *N* turnos. +- Historiales recientes muy extensos (por ejemplo, respuestas de herramientas pesadas) aún pueden saturar la ventana. + +## 5. Sesiones con resumen (`SummarizingSession`) + +`SummarizingSession` mantiene verbatim los últimos turnos y comprime el resto en un bloque sintético usuario→assistant. El resumen se realiza mediante un componente asíncrono que puedes implementar con cualquier modelo compatible. + +```python +from scripts.coding.ai.shared.context_sessions import SummarizingSession + +class SupportSummarizer: + async def summarize(self, messages): + shadow_prompt = "Summarize the conversation we had so far." + summary_text = "\n".join( + f"- {msg['role']}: {msg['content']}" for msg in messages + ) + return shadow_prompt, summary_text + +session = SummarizingSession( + keep_last_n_turns=2, + context_limit=4, + summarizer=SupportSummarizer(), + session_id="enterprise-case-001", +) +await session.add_items([...]) +current_context = await session.get_items() +``` + +**Ventajas** +- Conserva decisiones, identificadores y restricciones más allá de *N* turnos. +- Experiencia fluida para el usuario: el agente “recuerda” acuerdos previos. +- Costos predecibles en sesiones prolongadas (el resumen reemplaza cientos de mensajes). + +**Limitaciones** +- Riesgo de “resumen sesgado” si el modelo omite detalles críticos. +- Incremento de latencia/costos cuando se recalcula el resumen. +- Se debe auditar la salida para evitar “context poisoning”. + +### 5.1 Sugerencias para prompts de resumen + +- Resalta hitos (problema reportado, solución probada, estado actual). +- Integra comprobaciones de contradicciones o políticas antes de resumir. +- Incluye secciones bien delimitadas (`Product & Environment`, `Steps Tried`, `Blockers`, etc.). +- Marca datos dudosos como `UNVERIFIED` para no promover su uso automático. + +## 6. Comparativa rápida + +| Dimensión | TrimmingSession | SummarizingSession | +|-----------|-----------------|--------------------| +| Latencia/costo | Muy bajo | Moderado (dependiendo del resumen) | +| Memoria a largo plazo | Baja | Alta | +| Riesgo principal | Pérdida de contexto | Distorsión del contexto | +| Escenarios ideales | Automatizaciones cortas, tareas independientes | Casos analíticos, coaching, soporte premium | + +## 7. Observabilidad y registros + +- `SummarizingSession.get_full_history()` entrega mensajes y metadatos (`synthetic`, `kind`, `summary_for_turns`) útiles para trazas y dashboards. +- Registra las salidas de los resúmenes para auditar cambios en evaluaciones. +- Al integrar con `agents` SDK, complementa con `set_tracing_disabled(False)` para utilizar los tableros de Traces cuando estén habilitados. + +## 8. Evaluaciones recomendadas + +1. **Baseline vs. Delta**: ejecuta tus suites de regresión antes y después de aplicar la política de contexto. +2. **LLM-as-Judge**: evalúa resúmenes con un prompt que compare contra la conversación original. +3. **Replay de transcripciones**: reproduce threads largos y valida si el agente recuerda IDs, acuerdos o restricciones. +4. **Token Pressure Checks**: monitorea la longitud total enviada al modelo para evitar truncamientos inesperados. + +## 9. Integración por dominio + +- **Backend (`api/`)**: utilice sesiones para pipelines de soporte o diagnósticos de microservicios. +- **Frontend (`ui/`)**: combine resúmenes con análisis de UX para guiar mejoras graduales. +- **Infrastructure**: aplica trimming para runbooks automatizados y summarization en incidentes largos. +- **Docs**: usa resúmenes para consolidar hallazgos antes de archivarlos en `docs/analisis/`. +- **Scripts**: `scripts/coding/ai/orchestrators/codex_mcp_workflow.py` puede recibir una sesión vía composición para mantener el estado cuando delega en múltiples agentes. + +## 10. Recursos relacionados + +- Implementación de referencia: `scripts/coding/ai/shared/context_sessions.py`. +- Pruebas de TDD: `scripts/coding/tests/ai/shared/test_context_sessions.py`. +- ExecPlan que gobierna esta guía: `docs/plans/EXECPLAN_context_memory_management.md`. +- Plantillas de agentes: `.agent/agents/`. +- Prueba de alineación documental: `docs/testing/test_documentation_alignment.py`. diff --git a/docs/ai_capabilities/prompting/README.md b/docs/ai_capabilities/prompting/README.md index 045a533d..cb1fad4c 100644 --- a/docs/ai_capabilities/prompting/README.md +++ b/docs/ai_capabilities/prompting/README.md @@ -68,6 +68,10 @@ El compendio de patrones agenticos observados en producción—desde LLMs aument Para estandarizar la orquestación Codex MCP en todos los proveedores soportados, consulta [../orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md](../orchestration/CODEX_MCP_MULTI_AGENT_GUIDE.md). Describe cómo inicializar el servidor MCP, ensamblar flujos single-agent y multi-agent, habilitar trazas y enlazar el `CodexMCPWorkflowBuilder` con la gobernanza `.agent`. +### Context Management Playbook + +El manejo de memoria en sesiones largas se detalla en [../orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md](../orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md). Explica cómo aplicar `TrimmingSession` y `SummarizingSession` en Claude, ChatGPT y Hugging Face reutilizando `scripts/coding/ai/shared/context_sessions.py`. + ### Phi-3 Prompt Engineering Playbook Para alinear el tercer proveedor soportado (Hugging Face) con prácticas de prompting reproducibles, consulta [PHI3_PROMPT_ENGINEERING_PLAYBOOK.md](./PHI3_PROMPT_ENGINEERING_PLAYBOOK.md). Resume la configuración del modelo `microsoft/Phi-3-mini-4k-instruct`, patrones como Chain-of-Thought/Tree-of-Thought y recomendaciones para interoperar con Claude y ChatGPT. diff --git a/docs/index.md b/docs/index.md index 12b4e34a..7c3eb58a 100644 --- a/docs/index.md +++ b/docs/index.md @@ -84,6 +84,7 @@ Este índice combina lo implementado con la visión futura del proyecto, clarame - **Test runner**: [`scripts/run_all_tests.sh`](../scripts/run_all_tests.sh) - **Métricas DORA**: [`scripts/dora_metrics.py`](../scripts/dora_metrics.py) - **Templates**: [`scripts/templates/`](../scripts/templates/) +- **Gestión de contexto multi-LLM**: [`ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`](ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md) y módulo reutilizable [`scripts/coding/ai/shared/context_sessions.py`](../scripts/coding/ai/shared/context_sessions.py). #### [PLANIFICADO] Planificados (ver [`docs/scripts/README.md`](scripts/README.md)) - `scripts/sdlc_agent.py` - CLI SDLC diff --git a/docs/plans/EXECPLAN_context_memory_management.md b/docs/plans/EXECPLAN_context_memory_management.md new file mode 100644 index 00000000..b801f253 --- /dev/null +++ b/docs/plans/EXECPLAN_context_memory_management.md @@ -0,0 +1,73 @@ +# Integrar gestión de contexto multi-LLM en agentes y documentación + +Este ExecPlan es un documento vivo. Las secciones `Progress`, `Surprises & Discoveries`, `Decision Log` y `Outcomes & Retrospective` deben mantenerse al día conforme avance el trabajo. + +Este documento se mantiene según `.agent/PLANS.md` y gobierna las integraciones de memoria de contexto para todos los modelos LLM en el repositorio. + +## Purpose / Big Picture + +Permitir que cualquier agente basado en Claude, ChatGPT u otros LLMs ejecute flujos prolongados sin perder coherencia ni desperdiciar tokens, incorporando sesiones con recorte y resumen de contexto dentro de los scripts y documentando el procedimiento oficial en la guía de capacidades. Al finalizar, los equipos podrán reutilizar la misma política de memoria desde scripts Python probados y seguir un manual unificado dentro de `docs/`. + +## Progress + +- [x] (2025-11-13 06:54Z) Redactar especificaciones de sesiones de contexto (trimming y summarizing) con API pública en `scripts/coding/ai/shared/`. +- [x] (2025-11-13 06:54Z) Implementar pruebas TDD en `scripts/coding/tests/ai/` que cubran recorte de turnos, resúmenes sintéticos y metadata. +- [x] (2025-11-13 06:54Z) Implementar módulos de sesiones y asegurarse de que las pruebas pasen. +- [x] (2025-11-13 06:57Z) Documentar el cookbook de gestión de contexto en `docs/ai_capabilities/orchestration/` y enlazarlo desde los índices y fichas de agentes. +- [x] (2025-11-13 06:57Z) Actualizar catálogos/README/SDLC para reflejar disponibilidad de la nueva política de contexto. +- [x] (2025-11-13 06:57Z) Ejecutar pytest relevante y actualizar esta sección con el resultado. + +## Surprises & Discoveries + +- Pending. + +## Decision Log + +- Pending. + +## Outcomes & Retrospective + +- Pending. + +## Context and Orientation + +El proyecto separa responsabilidades en `api/`, `ui/`, `infrastructure/`, `docs/` y `scripts/`. Las automatizaciones de agentes viven en `scripts/coding/ai/` y las guías en `docs/ai_capabilities/`. Actualmente no existe un módulo centralizado que maneje trimming/summarizing con sesiones compatibles con el Agents SDK; el usuario entregó un cookbook detallado que debemos adaptar a nuestras convenciones, manteniendo compatibilidad multi-LLM y con la política de ExecPlans. + +## Plan of Work + +1. Revisar los lineamientos del cookbook y diseñar la API Python que expondrá clases `TrimmingSession` y `SummarizingSession` bajo `scripts/coding/ai/shared/context_sessions.py`, incluyendo opciones de turnos y resúmenes. +2. Definir antes del código los casos de prueba unitarios que cubran recorte de turnos, preservación de metadatos y reemplazo por resúmenes, ubicándolos en `scripts/coding/tests/ai/shared/test_context_sessions.py`. +3. Implementar las clases siguiendo TDD, asegurando que se integren con `agents` SDK de OpenAI (sin dependencia directa cuando no esté instalado) mediante abstracciones claras. +4. Documentar el flujo completo en un nuevo manual `docs/ai_capabilities/orchestration/CONTEXT_MANAGEMENT_PLAYBOOK.md`, incorporando trimming y summarization para todos los modelos, con requisitos previos, comparativas y tablas. +5. Actualizar índices (`docs/ai_capabilities/orchestration/README.md`, `docs/ai_capabilities/prompting/README.md` si aplica) y fichas de agentes multi-LLM en `.agent/agents/` para enlazar el playbook. +6. Ajustar pruebas de alineación documental en `docs/testing/test_documentation_alignment.py` para exigir referencias cruzadas al nuevo playbook. +7. Ejecutar la batería de pruebas relevante (`pytest scripts/coding/tests/ai/shared/test_context_sessions.py` y `pytest docs/testing/test_documentation_alignment.py`) y registrar resultados. + +## Concrete Steps + +1. Crear archivo de pruebas unitarias con los escenarios TDD descritos. +2. Implementar módulo `context_sessions.py` con clases y helpers necesarios hasta que las pruebas pasen. +3. Redactar el playbook en `docs/ai_capabilities/orchestration/` utilizando el contenido proporcionado por el usuario, adaptado a nuestras convenciones (sin emojis, con secciones claras y referencias multi-LLM). +4. Enlazar el nuevo playbook desde los índices, README y fichas, además de actualizar la prueba de alineación documental. +5. Ejecutar `pytest` para las rutas afectadas. + +## Validation and Acceptance + +- `pytest scripts/coding/tests/ai/shared/test_context_sessions.py` debe pasar al final. +- `pytest docs/testing/test_documentation_alignment.py` debe pasar y validar los nuevos enlaces. +- El README y las fichas de agentes deben mencionar explícitamente la política de contexto multi-LLM. +- El playbook debe describir trimming y summarization, incluir pros/contras y comparativas, y proveer instrucciones reproducibles. + +## Idempotence and Recovery + +- Las pruebas unitarias pueden ejecutarse repetidamente sin modificar el entorno. +- El playbook y los enlaces son aditivos; en caso de error, revertir commits parciales y volver a correr `pytest`. + +## Artifacts and Notes + +- Pending. + +## Interfaces and Dependencies + +- El módulo `context_sessions` expondrá clases `TrimmingSession` y `SummarizingSession` con métodos `get_items`, `add_items`, `pop_item`, `clear_session`, `get_full_history` y configuraciones `max_turns`, `keep_last_n_turns`. +- Las pruebas importarán desde `scripts.coding.ai.shared.context_sessions` y simularán mensajes en formato dict compatible con Agents SDK (`{"role": "user", "content": "..."}` y metadatos opcionales). diff --git a/docs/testing/test_documentation_alignment.py b/docs/testing/test_documentation_alignment.py index 2409f63c..d3ca4d85 100644 --- a/docs/testing/test_documentation_alignment.py +++ b/docs/testing/test_documentation_alignment.py @@ -256,3 +256,41 @@ def test_prompt_techniques_catalog_is_linked_across_agents(): sdlc_guide = _read(REPO_ROOT / "docs" / "ai" / "SDLC_AGENTS_GUIDE.md") assert "PROMPT_TECHNIQUES_CATALOG.md" in sdlc_guide + + +def test_context_management_playbook_is_linked_across_guides(): + playbook_path = REPO_ROOT / "docs" / "ai_capabilities" / "orchestration" / "CONTEXT_MANAGEMENT_PLAYBOOK.md" + assert playbook_path.exists(), "Debe existir el playbook de gestión de contexto" + + playbook_contents = _read(playbook_path) + assert "Context Management Playbook" in playbook_contents + assert "TrimmingSession" in playbook_contents + assert "SummarizingSession" in playbook_contents + + context_module = REPO_ROOT / "scripts" / "coding" / "ai" / "shared" / "context_sessions.py" + assert context_module.exists(), "Falta el módulo reutilizable de sesiones de contexto" + + readme_root = _read(REPO_ROOT / "README.md") + assert "CONTEXT_MANAGEMENT_PLAYBOOK" in readme_root + + docs_index = _read(REPO_ROOT / "docs" / "index.md") + assert "CONTEXT_MANAGEMENT_PLAYBOOK" in docs_index + + prompting_index = _read(REPO_ROOT / "docs" / "ai_capabilities" / "prompting" / "README.md") + assert "Context Management Playbook" in prompting_index + + agent_catalog = _read(REPO_ROOT / ".agent" / "agents" / "README.md") + assert "CONTEXT_MANAGEMENT_PLAYBOOK" in agent_catalog + + agents_dir = REPO_ROOT / ".agent" / "agents" + provider_agents = ["claude_agent.md", "chatgpt_agent.md", "huggingface_agent.md"] + domain_agents = ["api_agent.md", "ui_agent.md", "infrastructure_agent.md", "docs_agent.md", "scripts_agent.md"] + + for filename in provider_agents + domain_agents: + contents = _read(agents_dir / filename) + assert "CONTEXT_MANAGEMENT_PLAYBOOK" in contents + assert "context_sessions.py" in contents + + sdlc_guide = _read(REPO_ROOT / "docs" / "ai" / "SDLC_AGENTS_GUIDE.md") + assert "CONTEXT_MANAGEMENT_PLAYBOOK" in sdlc_guide + assert "context_sessions.py" in sdlc_guide diff --git a/scripts/coding/ai/shared/context_sessions.py b/scripts/coding/ai/shared/context_sessions.py new file mode 100644 index 00000000..e7d6a268 --- /dev/null +++ b/scripts/coding/ai/shared/context_sessions.py @@ -0,0 +1,270 @@ +"""Context session utilities for multi-LLM agents.""" + +from __future__ import annotations + +import asyncio +from collections import deque +from typing import Any, Deque, Dict, Iterable, List, Optional, Tuple + +ROLE_USER = "user" +ALLOWED_MSG_KEYS = {"role", "content", "name"} + + +def _is_user_msg(item: Dict[str, Any]) -> bool: + """Return ``True`` if the payload represents a user authored message.""" + if not isinstance(item, dict): + role = getattr(item, "role", None) + return role == ROLE_USER + + role = item.get("role") + if role is not None: + return role == ROLE_USER + + if item.get("type") == "message": + return item.get("role") == ROLE_USER + + return False + + +class TrimmingSession: + """Maintain only the last ``max_turns`` user turns in memory.""" + + def __init__(self, session_id: str, max_turns: int = 8): + self.session_id = session_id + self.max_turns = max(1, int(max_turns)) + self._items: Deque[Dict[str, Any]] = deque() + self._lock = asyncio.Lock() + + async def get_items(self, limit: Optional[int] = None) -> List[Dict[str, Any]]: + async with self._lock: + trimmed = self._trim_to_last_turns(list(self._items)) + if limit is not None and limit >= 0: + return trimmed[-limit:] + return trimmed + + async def add_items(self, items: Iterable[Dict[str, Any]]) -> None: + payload = list(items) + if not payload: + return + async with self._lock: + self._items.extend(payload) + trimmed = self._trim_to_last_turns(list(self._items)) + self._items.clear() + self._items.extend(trimmed) + + async def pop_item(self) -> Optional[Dict[str, Any]]: + async with self._lock: + if not self._items: + return None + return self._items.pop() + + async def clear_session(self) -> None: + async with self._lock: + self._items.clear() + + async def set_max_turns(self, max_turns: int) -> None: + async with self._lock: + self.max_turns = max(1, int(max_turns)) + trimmed = self._trim_to_last_turns(list(self._items)) + self._items.clear() + self._items.extend(trimmed) + + async def raw_items(self) -> List[Dict[str, Any]]: + async with self._lock: + return list(self._items) + + def _trim_to_last_turns(self, items: List[Dict[str, Any]]) -> List[Dict[str, Any]]: + if not items: + return items + + count = 0 + start_idx = 0 + for index in range(len(items) - 1, -1, -1): + if _is_user_msg(items[index]): + count += 1 + if count == self.max_turns: + start_idx = index + break + + return items[start_idx:] + + +class SummarizingSession: + """Session that summarizes older turns once the context limit is exceeded.""" + + def __init__( + self, + keep_last_n_turns: int = 3, + context_limit: int = 3, + summarizer: Optional[Any] = None, + session_id: Optional[str] = None, + ): + if context_limit < 1: + raise ValueError("context_limit must be >= 1") + if keep_last_n_turns < 0: + raise ValueError("keep_last_n_turns must be >= 0") + if keep_last_n_turns > context_limit: + raise ValueError("keep_last_n_turns cannot exceed context_limit") + + self.keep_last_n_turns = keep_last_n_turns + self.context_limit = context_limit + self.summarizer = summarizer + self.session_id = session_id or "default" + + self._records: Deque[Dict[str, Dict[str, Any]]] = deque() + self._lock = asyncio.Lock() + + async def get_items(self, limit: Optional[int] = None) -> List[Dict[str, Any]]: + async with self._lock: + data = [dict(record["msg"]) for record in self._records] + return self._apply_limit([self._sanitize_for_model(msg) for msg in data], limit) + + async def add_items(self, items: Iterable[Dict[str, Any]]) -> None: + payload = list(items) + if not payload: + return + + async with self._lock: + for item in payload: + msg, metadata = self._split_msg_and_meta(item) + self._records.append({"msg": msg, "metadata": metadata}) + need_summary, boundary = self._summarize_decision_locked() + + if not need_summary: + async with self._lock: + self._normalize_synthetic_flags_locked() + return + + async with self._lock: + snapshot = list(self._records) + prefix_msgs = [record["msg"] for record in snapshot[:boundary]] + + shadow, summary = await self._summarize(prefix_msgs) + + async with self._lock: + still_need, new_boundary = self._summarize_decision_locked() + if not still_need: + self._normalize_synthetic_flags_locked() + return + + snapshot = list(self._records) + suffix = snapshot[new_boundary:] + + self._records.clear() + self._records.extend( + [ + { + "msg": {"role": ROLE_USER, "content": shadow}, + "metadata": { + "synthetic": True, + "kind": "history_summary_prompt", + "summary_for_turns": f"< all before idx {new_boundary} >", + }, + }, + { + "msg": {"role": "assistant", "content": summary}, + "metadata": { + "synthetic": True, + "kind": "history_summary", + "summary_for_turns": f"< all before idx {new_boundary} >", + }, + }, + ] + ) + self._records.extend(suffix) + self._normalize_synthetic_flags_locked() + + async def pop_item(self) -> Optional[Dict[str, Any]]: + async with self._lock: + if not self._records: + return None + record = self._records.pop() + return dict(record["msg"]) + + async def clear_session(self) -> None: + async with self._lock: + self._records.clear() + + def set_max_turns(self, n: int) -> None: + if n < 1: + raise ValueError("n must be >= 1") + self.context_limit = n + if self.keep_last_n_turns > self.context_limit: + self.keep_last_n_turns = self.context_limit + + async def get_full_history(self, limit: Optional[int] = None) -> List[Dict[str, Any]]: + async with self._lock: + data = [ + {"message": dict(record["msg"]), "metadata": dict(record["metadata"])} + for record in self._records + ] + return self._apply_limit(data, limit) + + async def get_items_with_metadata(self, limit: Optional[int] = None) -> List[Dict[str, Any]]: + return await self.get_full_history(limit) + + def _apply_limit(self, items: List[Dict[str, Any]], limit: Optional[int]) -> List[Dict[str, Any]]: + if limit is not None and limit >= 0: + return items[-limit:] + return items + + def _split_msg_and_meta(self, item: Dict[str, Any]) -> Tuple[Dict[str, Any], Dict[str, Any]]: + msg = {k: item.get(k) for k in ALLOWED_MSG_KEYS if k in item} + extra = {k: v for k, v in item.items() if k not in ALLOWED_MSG_KEYS} + metadata = dict(extra.pop("metadata", {})) + metadata.update(extra) + + msg.setdefault("role", ROLE_USER) + msg.setdefault("content", str(item)) + + role = msg.get("role") + if role in (ROLE_USER, "assistant") and "synthetic" not in metadata: + metadata["synthetic"] = False + return msg, metadata + + def _sanitize_for_model(self, msg: Dict[str, Any]) -> Dict[str, Any]: + return {k: v for k, v in msg.items() if k in ALLOWED_MSG_KEYS} + + def _is_real_user_turn_start(self, record: Dict[str, Dict[str, Any]]) -> bool: + return ( + record["msg"].get("role") == ROLE_USER + and not record["metadata"].get("synthetic", False) + ) + + def _summarize_decision_locked(self) -> Tuple[bool, int]: + user_starts = [i for i, rec in enumerate(self._records) if self._is_real_user_turn_start(rec)] + real_turns = len(user_starts) + + if real_turns <= self.context_limit: + return False, -1 + + if self.keep_last_n_turns == 0: + return True, len(self._records) + + if len(user_starts) < self.keep_last_n_turns: + return False, -1 + + boundary = user_starts[-self.keep_last_n_turns] + if boundary <= 0: + return False, -1 + + return True, boundary + + def _normalize_synthetic_flags_locked(self) -> None: + for record in self._records: + role = record["msg"].get("role") + if role in (ROLE_USER, "assistant") and "synthetic" not in record["metadata"]: + record["metadata"]["synthetic"] = False + + async def _summarize(self, prefix_msgs: List[Dict[str, Any]]) -> Tuple[str, str]: + if not self.summarizer: + return "Summarize the conversation we had so far.", "Summary unavailable." + + clean_prefix = [self._sanitize_for_model(msg) for msg in prefix_msgs] + result = await self.summarizer.summarize(clean_prefix) + if not isinstance(result, tuple) or len(result) != 2: + return "Summarize the conversation we had so far.", str(result) + return result + + +__all__ = ["TrimmingSession", "SummarizingSession"] diff --git a/scripts/coding/tests/ai/shared/test_context_sessions.py b/scripts/coding/tests/ai/shared/test_context_sessions.py new file mode 100644 index 00000000..fb12aaa6 --- /dev/null +++ b/scripts/coding/tests/ai/shared/test_context_sessions.py @@ -0,0 +1,159 @@ +#!/usr/bin/env python3 +"""Tests for context session utilities (TDD).""" + +import asyncio +import sys +from pathlib import Path +from types import ModuleType +import importlib.machinery +import importlib.util + +PROJECT_ROOT = Path(__file__).parent.parent.parent.parent.parent.parent +SCRIPTS_ROOT = PROJECT_ROOT / "scripts" +CODING_ROOT = SCRIPTS_ROOT / "coding" + +# Ensure namespace resolution for "scripts" package used across tests +if str(PROJECT_ROOT) not in sys.path: + sys.path.insert(0, str(PROJECT_ROOT)) +if str(CODING_ROOT) not in sys.path: + sys.path.insert(0, str(CODING_ROOT)) + +namespace_paths = [str(SCRIPTS_ROOT), str(CODING_ROOT)] +scripts_pkg = ModuleType("scripts") +scripts_pkg.__package__ = "scripts" +scripts_pkg.__path__ = namespace_paths +scripts_pkg.__spec__ = importlib.machinery.ModuleSpec( + name="scripts", + loader=None, + is_package=True, +) +sys.modules.setdefault("scripts", scripts_pkg) + +MODULE_NAME = "scripts.ai.shared.context_sessions" +module_spec = importlib.util.find_spec(MODULE_NAME) +if module_spec is None: + module_path = CODING_ROOT / "ai" / "shared" / "context_sessions.py" + module_spec = importlib.util.spec_from_file_location(MODULE_NAME, module_path) + module = importlib.util.module_from_spec(module_spec) + assert module_spec and module_spec.loader, "No se pudo cargar spec para context_sessions" + module_spec.loader.exec_module(module) + sys.modules[MODULE_NAME] = module + +from scripts.ai.shared.context_sessions import ( # type: ignore # pylint: disable=wrong-import-position + TrimmingSession, + SummarizingSession, +) + + +def run_async(coro): + """Helper to execute async coroutines within sync pytest tests.""" + return asyncio.run(coro) + + +class DummySummarizer: + """Deterministic summarizer used in tests.""" + + def __init__(self): + self.calls = 0 + + async def summarize(self, messages): # pylint: disable=unused-argument + self.calls += 1 + shadow = "Summarize the conversation we had so far." + summary = "Synthetic summary block" + await asyncio.sleep(0) + return shadow, summary + + +def test_trimming_session_keeps_last_turns(): + session = TrimmingSession("session", max_turns=2) + transcript = [ + {"role": "user", "content": "First question"}, + {"role": "assistant", "content": "First answer"}, + {"role": "user", "content": "Second question"}, + {"role": "assistant", "content": "Second answer"}, + {"role": "user", "content": "Third question"}, + {"role": "assistant", "content": "Third answer"}, + ] + + run_async(session.add_items(transcript)) + history = run_async(session.get_items()) + + assert len(history) == 4 + assert history[0]["content"] == "Second question" + assert history[-1]["content"] == "Third answer" + + +def test_trimming_session_respects_dynamic_limit(): + session = TrimmingSession("session", max_turns=3) + run_async(session.add_items([ + {"role": "user", "content": "Alpha"}, + {"role": "assistant", "content": "Ack"}, + {"role": "user", "content": "Beta"}, + {"role": "assistant", "content": "Bee"}, + {"role": "user", "content": "Gamma"}, + {"role": "assistant", "content": "Gee"}, + ])) + + run_async(session.set_max_turns(1)) + history = run_async(session.get_items()) + + assert len(history) == 2 + assert history[0]["content"] == "Gamma" + + popped = run_async(session.pop_item()) + assert popped["content"] == "Gee" + + +def test_summarizing_session_generates_summary_block(): + summarizer = DummySummarizer() + session = SummarizingSession( + keep_last_n_turns=1, + context_limit=2, + summarizer=summarizer, + session_id="support", + ) + + run_async(session.add_items([ + {"role": "user", "content": "Initial issue"}, + {"role": "assistant", "content": "First response"}, + {"role": "user", "content": "Follow-up"}, + {"role": "assistant", "content": "Second response"}, + {"role": "user", "content": "Third turn"}, + {"role": "assistant", "content": "Third response"}, + ])) + + history = run_async(session.get_items()) + assert history[0]["role"] == "user" + assert history[0]["content"] == "Summarize the conversation we had so far." + assert history[1]["role"] == "assistant" + assert history[1]["content"] == "Synthetic summary block" + assert history[-2]["content"] == "Third turn" + assert summarizer.calls == 1 + + full_history = run_async(session.get_full_history()) + synthetic_entries = [item for item in full_history if item["metadata"].get("synthetic")] + assert len(synthetic_entries) == 2 + assert synthetic_entries[0]["metadata"]["kind"] == "history_summary_prompt" + assert synthetic_entries[1]["metadata"]["kind"] == "history_summary" + + +def test_summarizing_session_respects_context_limit_without_summary(): + summarizer = DummySummarizer() + session = SummarizingSession( + keep_last_n_turns=2, + context_limit=3, + summarizer=summarizer, + session_id="support", + ) + + run_async(session.add_items([ + {"role": "user", "content": "Turn one"}, + {"role": "assistant", "content": "Answer one"}, + {"role": "user", "content": "Turn two"}, + {"role": "assistant", "content": "Answer two"}, + ])) + + history = run_async(session.get_items()) + assert summarizer.calls == 0 + assert history[0]["content"] == "Turn one" + assert history[-1]["content"] == "Answer two"