Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,10 @@ Este catálogo explica cada gap: problema, propósito, evidencia, criterios de c
- **Criticality:** P2 · **Complexity:** M
- **Proposed fix:** Adaptador que define actividad+artefacto esperado, aplica rulesets/skills del tenant, resuelve autorización, invoca Cowork/Claude y captura la evidencia de ejecución para el gate — sobre los puertos de GT-383…394.
- **Acceptance criteria:**
- [ ] Una actividad acotada se ejecuta vía el adaptador con permisos/plan/aprobación y captura de evidencia.
- [ ] El ejecutor es reemplazable (cumple el contrato de ejecución del agent-runtime).
- [ ] Una actividad acotada se ejecuta vía el adaptador con permisos/plan/aprobación y captura de evidencia. _(el adaptador es acotado —rechaza tools fuera del catálogo— y el envelope del runtime (approval/policy/trace) lo gobierna; la ejecución viva contra Claude/Cowork requiere el `CoworkClient` real —conector/infra)_
- [x] El ejecutor es reemplazable (cumple el contrato de ejecución del agent-runtime). _(`CoworkAgentEngineAdapter implements IAgentEnginePort`, drop-in como stub/hermes/swarms)_
- **Dependencies:** GT-387, GT-441.
- **Status:** `PENDING`
- **Status:** `IN-PROGRESS`

#### GT-532

Expand Down
6 changes: 3 additions & 3 deletions reference/core/control-center/gaps/gap-reference-catalog.md
Original file line number Diff line number Diff line change
Expand Up @@ -382,10 +382,10 @@ This catalog explains each gap: problem, purpose, evidence, closure criteria, an
- **Criticality:** P2 · **Complexity:** M
- **Proposed fix:** Adapter that defines activity+expected artifact, applies tenant rulesets/skills, resolves authorization, invokes Cowork/Claude and captures execution evidence for the gate — over the GT-383…394 ports.
- **Acceptance criteria:**
- [ ] A bounded activity runs via the adapter with permissions/plan/approval and evidence capture.
- [ ] The executor is replaceable (satisfies the agent-runtime execution contract).
- [ ] A bounded activity runs via the adapter with permissions/plan/approval and evidence capture. _(the adapter is bounded —rejects out-of-catalog tools— and the runtime envelope (approval/policy/trace) governs it; live execution against Claude/Cowork needs the real `CoworkClient` —connector/infra)_
- [x] The executor is replaceable (satisfies the agent-runtime execution contract). _(`CoworkAgentEngineAdapter implements IAgentEnginePort`, drop-in like stub/hermes/swarms)_
- **Dependencies:** GT-387, GT-441.
- **Status:** `PENDING`
- **Status:** `IN-PROGRESS`

#### GT-532

Expand Down
4 changes: 2 additions & 2 deletions reference/core/control-center/gaps/gap-tracking.es.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida
| [`GT-528`](./gap-reference-catalog.es.md#gt-528) | **[Wedge · eje 2] Ingesta de DSL Structurizr / C4 → ADR ejecutable.** Convertir modelos Structurizr/C4 (intención de arquitectura, hoy prosa/diagrama) en reglas `enforce:` verificables contra el código real (§13.2). Fix: parser del DSL + mapeo a `NormalizedRule.enforce`; complementa GT-516. **EN-PROGRESO (`c4-compiler.ts`):** aterrizó el compilador — `compileC4ToBoundaryRules(model)` transforma un `C4Model` normalizado (elementos con `path`/`importPrefix` + relaciones permitidas) en `EditBoundaryRule` de GT-526, derivando el denylist desde el allowlist del modelo (un elemento solo puede depender de lo que declara; el resto queda prohibido), con `ruleId` `C4-<id>`, ADR y severidad. **El diagrama C4 se vuelve ejecutable** y se enchufa al gate edit-time (GT-526) y al PR/CI. Verificado end-to-end: un edit de `src/domain` que importa `src/infrastructure` → bloqueado; core-domain 933/933 (+5), tsc limpio. **Pendiente (ingesta):** parsear el `.dsl` crudo de Structurizr (o su export JSON) al `C4Model` normalizado. | `Evolith Core` | Cross | P2 | M | `EN-PROGRESO` |
| [`GT-529`](./gap-reference-catalog.es.md#gt-529) | **[Surround · eje 1] Contrato ACL + referencia de integración Jira Enterprise.** Mapear ideas/epics/stories/aprobaciones/releases de Jira a artefactos Evolith preservando origen/identidad/timestamps/linaje, con salvaguardas de transición (completar un workflow de Jira no autoriza una transición de fase). §8.3 / §12. Fix: ACL de sistemas de trabajo externos + guía de integración. **EN-PROGRESO (`domain/external-work-acl.ts`):** aterrizó el ACL puro — `CanonicalWorkItem` con `WorkItemProvenance` (source/externalId/externalKey/url/created/updated), `parseJiraIssue`/`parseJiraIssues` (mapea issues de Jira preservando procedencia; rechaza sin `id` en vez de fabricar identidad), `mapJiraIssueType` (Epic/Story/Task/Version→kind canónico). **Salvaguarda de transición (§9-6):** `authorizesPhaseTransition: false` por contrato + `externalWorkAuthorizesTransition`⇒`false` (completar un workflow de Jira NO autoriza un phase gate). Verificado: core-domain 939/939 (+6), tsc limpio. **Pendiente (conector/infra + doc):** fetch read-only de la Jira REST API + la guía de integración documentada. | `Evolith Core` | Cross | P1 | L | `EN-PROGRESO` |
| [`GT-530`](./gap-reference-catalog.es.md#gt-530) | **[Surround · eje 1] Adaptador Langfuse → evidencia canónica.** Mapear traces/evaluaciones/costo/latencia/versión-de-prompt/tool-calls de Langfuse al modelo de evidencia de Evolith, para no reconstruir una plataforma de telemetría LLM. §8.1 / §12. Fix: `LangfuseEvidenceAdapter` vía puerto de observabilidad. **EN-PROGRESO (`domain/observability-evidence.ts`):** aterrizó el mapper puro + forma portable — `ObservabilityEvidence` (traceId/model/promptVersion/costUsd/latencyMs/totalTokens/toolCalls/evaluations/url, provider-neutral §9-5), `mapLangfuseTrace` (agrega costo/tokens/latencia de las observaciones, toma model/prompt de la 1ª GENERATION, colecta tool-calls distintos, mapea scores→evaluations; trace sin id⇒null) y el puerto `IObservabilityEvidenceSource`. Verificado: core-domain 945/945 (+6), tsc limpio. **Pendiente (conector/infra):** el fetch read-only de la Langfuse API detrás del puerto. | `Evolith Core` | Cross | P2 | L | `EN-PROGRESO` |
| [`GT-531`](./gap-reference-catalog.es.md#gt-531) | **[Surround · eje 1] Adaptador Cowork/Claude como ejecutor gobernado acotado.** Ejecutor de actividades con permisos/planes/aprobaciones/captura de evidencia, tratando a Claude como uno de varios ejecutores reemplazables (§8.2, §9). Extiende el épico agent-runtime GT-383…394 (HITL GT-441 / adapters GT-438). | `agent-runtime` | Cross | P2 | M | `PENDIENTE` |
| [`GT-531`](./gap-reference-catalog.es.md#gt-531) | **[Surround · eje 1] Adaptador Cowork/Claude como ejecutor gobernado acotado.** Ejecutor de actividades con permisos/planes/aprobaciones/captura de evidencia, tratando a Claude como uno de varios ejecutores reemplazables (§8.2, §9). Extiende el épico agent-runtime GT-383…394 (HITL GT-441 / adapters GT-438). **EN-PROGRESO (`cowork-agent.adapter.ts`):** aterrizó el `CoworkAgentEngineAdapter` — implementa el mismo `IAgentEnginePort` que stub/hermes/swarms (Claude Cowork como ejecutor **reemplazable**), y es **acotado**: nunca propone una herramienta fuera del catálogo de skills gobernado (una propuesta de Cowork/LLM a una capacidad inexistente se rechaza en vez de inventarse). El envelope del runtime (approval GT-441 / policy / trace) ya lo gobierna; la llamada viva a Claude va detrás de `CoworkClient` inyectable (sin cliente = determinista, como el stub). Verificado: agent-runtime 92/92, tsc limpio, surface-freeze GT-388 actualizado. **Pendiente (conector/infra):** el `CoworkClient` real contra la Claude/Cowork API. | `agent-runtime` | Cross | P2 | M | `EN-PROGRESO` |
| [`GT-532`](./gap-reference-catalog.es.md#gt-532) | **[Surround · eje 1] Vistas ejecutivas de portafolio + adaptadores marketplace + paquetes de gobernanza por tenant.** Mejora de adopción empresarial y escala de ecosistema (§12 P2); mayormente Tracker (plano de captura de valor enterprise). | `Tracker` | Cross | P3 | XL | `PENDIENTE` |
| [`GT-486`](./gap-reference-catalog.es.md#gt-486) | **el CLI no emitió un envelope ADR-0073 parseable para sdlc-status.** La salida no pudo parsearse en un envelope { success, data\|error, meta }. (Auto-detectado por el agente de pruebas exploratorias en la operación `sdlc-status`.) | `Evolith CLI` | Cross | P2 | S | `COMPLETADO` |
| [`GT-487`](./gap-reference-catalog.es.md#gt-487) | **el CLI no emitió un envelope ADR-0073 parseable para sdlc-handoff.** La salida no pudo parsearse en un envelope { success, data\|error, meta }. (Auto-detectado por el agente de pruebas exploratorias en la operación `sdlc-handoff`.) | `Evolith CLI` | Cross | P2 | S | `COMPLETADO` |
Expand Down Expand Up @@ -547,7 +547,7 @@ Este tablero es la única fuente de verdad para deuda técnica, gaps, oportunida
| [`GT-246`](./gap-reference-catalog.es.md#gt-246) | Implementar experimentos Chaos Mesh/Litmus | `QA` | Cross | P3 | L | `COMPLETADO` |


**Progreso:** 496 / 532 completados · 19 en progreso · 15 pendientes · 2 diferido
**Progreso:** 496 / 532 completados · 20 en progreso · 14 pendientes · 2 diferido

**Oleada 2026-06-23 (auditoría profunda de Winston III):** Añadidos 14 gaps nuevos `GT-212`…`GT-225` del Winston Audit Playbook que cubren: higiene de estado ADR (GT-212), metadata + presupuestos operativos + corpus de guías por topología (GT-213, GT-217, GT-219), observabilidad + OpenAPI en controladores REST (GT-214, GT-215), paridad de input-schemas OPA + densidad de tests por topología (GT-216, GT-222), plantillas de rollback + on-call de Fase 05 (GT-218), cobertura de ramas CLI + paridad de envelope --format + limpieza de skip-list (GT-220, GT-224, GT-225), audit logging HTTP de MCP (GT-221), y tests e2e de paridad cross-surface (GT-223).

Expand Down
4 changes: 2 additions & 2 deletions reference/core/control-center/gaps/gap-tracking.md
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ This board is the single source of truth for technical debt, gaps, opportunities
| [`GT-528`](./gap-reference-catalog.md#gt-528) | **[Wedge · axis 2] Structurizr / C4 DSL ingestion → executable ADR.** Turn Structurizr/C4 models (architecture intent, today prose/diagram) into `enforce:` rules verifiable against real code (§13.2). Fix: DSL parser + mapping to `NormalizedRule.enforce`; complements GT-516. **IN-PROGRESS (`c4-compiler.ts`):** landed the compiler — `compileC4ToBoundaryRules(model)` turns a normalized `C4Model` (elements with `path`/`importPrefix` + allowed relationships) into GT-526 `EditBoundaryRule`s, deriving the denylist from the model's allowlist (an element may only depend on what it declares; everything else is forbidden), with `ruleId` `C4-<id>`, ADR and severity. **The C4 diagram becomes executable** and feeds the edit-time gate (GT-526) and PR/CI. Verified end-to-end: a `src/domain` edit importing `src/infrastructure` → blocked; core-domain 933/933 (+5), tsc clean. **Remaining (ingestion):** parse the raw Structurizr `.dsl` (or its JSON export) into the normalized `C4Model`. | `Evolith Core` | Cross | P2 | M | `IN-PROGRESS` |
| [`GT-529`](./gap-reference-catalog.md#gt-529) | **[Surround · axis 1] ACL contract + Jira Enterprise integration reference.** Map Jira ideas/epics/stories/approvals/releases to Evolith artifacts preserving origin/identity/timestamps/lineage, with transition safeguards (completing a Jira workflow does not authorize a phase transition). §8.3 / §12. Fix: external work-system ACL + integration guide. **IN-PROGRESS (`domain/external-work-acl.ts`):** landed the pure ACL — `CanonicalWorkItem` with `WorkItemProvenance` (source/externalId/externalKey/url/created/updated), `parseJiraIssue`/`parseJiraIssues` (maps Jira issues preserving provenance; rejects a missing `id` rather than fabricating identity), `mapJiraIssueType` (Epic/Story/Task/Version→canonical kind). **Transition safeguard (§9-6):** `authorizesPhaseTransition: false` by contract + `externalWorkAuthorizesTransition`⇒`false` (completing a Jira workflow does NOT authorize a phase gate). Verified: core-domain 939/939 (+6), tsc clean. **Remaining (connector/infra + doc):** the read-only Jira REST API fetch + the documented integration guide. | `Evolith Core` | Cross | P1 | L | `IN-PROGRESS` |
| [`GT-530`](./gap-reference-catalog.md#gt-530) | **[Surround · axis 1] Langfuse adapter → canonical evidence.** Map Langfuse traces/evaluations/cost/latency/prompt-version/tool-calls to Evolith's evidence model, to avoid rebuilding an LLM telemetry platform. §8.1 / §12. Fix: `LangfuseEvidenceAdapter` via the observability port. **IN-PROGRESS (`domain/observability-evidence.ts`):** landed the pure mapper + portable shape — `ObservabilityEvidence` (traceId/model/promptVersion/costUsd/latencyMs/totalTokens/toolCalls/evaluations/url, provider-neutral §9-5), `mapLangfuseTrace` (aggregates cost/tokens/latency across observations, takes model/prompt from the first GENERATION, collects distinct tool-calls, maps scores→evaluations; a trace with no id⇒null) and the `IObservabilityEvidenceSource` port. Verified: core-domain 945/945 (+6), tsc clean. **Remaining (connector/infra):** the read-only Langfuse API fetch behind the port. | `Evolith Core` | Cross | P2 | L | `IN-PROGRESS` |
| [`GT-531`](./gap-reference-catalog.md#gt-531) | **[Surround · axis 1] Cowork/Claude adapter as a bounded governed executor.** Activity executor with permissions/plans/approvals/evidence capture, treating Claude as one of several replaceable executors (§8.2, §9). Extends the agent-runtime epic GT-383…394 (HITL GT-441 / adapters GT-438). | `agent-runtime` | Cross | P2 | M | `PENDING` |
| [`GT-531`](./gap-reference-catalog.md#gt-531) | **[Surround · axis 1] Cowork/Claude adapter as a bounded governed executor.** Activity executor with permissions/plans/approvals/evidence capture, treating Claude as one of several replaceable executors (§8.2, §9). Extends the agent-runtime epic GT-383…394 (HITL GT-441 / adapters GT-438). **IN-PROGRESS (`cowork-agent.adapter.ts`):** landed `CoworkAgentEngineAdapter` — implements the same `IAgentEnginePort` as stub/hermes/swarms (Claude Cowork as a **replaceable** executor), and is **bounded**: it never proposes a tool outside the governed skill catalog (a Cowork/LLM proposal for a non-existent capability is rejected, not invented). The runtime envelope (approval GT-441 / policy / trace) already governs it; the live Claude call sits behind an injectable `CoworkClient` (no client = deterministic, like the stub). Verified: agent-runtime 92/92, tsc clean, GT-388 surface-freeze updated. **Remaining (connector/infra):** the real `CoworkClient` against the Claude/Cowork API. | `agent-runtime` | Cross | P2 | M | `IN-PROGRESS` |
| [`GT-532`](./gap-reference-catalog.md#gt-532) | **[Surround · axis 1] Executive portfolio views + marketplace adapters + per-tenant governance packages.** Enterprise-adoption and ecosystem-scale improvement (§12 P2); mostly Tracker (enterprise value-capture plane). | `Tracker` | Cross | P3 | XL | `PENDING` |
| [`GT-486`](./gap-reference-catalog.md#gt-486) | **cli did not emit a parseable ADR-0073 envelope for sdlc-status.** Output could not be parsed into an { success, data\|error, meta } envelope. (Auto-detected by the exploratory test agent on operation `sdlc-status`.) | `Evolith CLI` | Cross | P2 | S | `DONE` |
| [`GT-487`](./gap-reference-catalog.md#gt-487) | **cli did not emit a parseable ADR-0073 envelope for sdlc-handoff.** Output could not be parsed into an { success, data\|error, meta } envelope. (Auto-detected by the exploratory test agent on operation `sdlc-handoff`.) | `Evolith CLI` | Cross | P2 | S | `DONE` |
Expand Down Expand Up @@ -547,7 +547,7 @@ This board is the single source of truth for technical debt, gaps, opportunities
| [`GT-246`](./gap-reference-catalog.md#gt-246) | Implement Chaos Mesh/Litmus experiments | `QA` | Cross | P3 | L | `DONE` |


**Progress:** 496 / 532 done · 19 in progress · 15 pending · 2 deferred
**Progress:** 496 / 532 done · 20 in progress · 14 pending · 2 deferred

**Wave 2026-06-23 (Winston deep audit III):** Added 14 new gaps `GT-212`…`GT-225` from the Winston Audit Playbook covering: ADR status hygiene (GT-212), topology manifest metadata + operational budgets + guidance corpus (GT-213, GT-217, GT-219), REST controller observability + OpenAPI (GT-214, GT-215), OPA input-schema parity + per-topology test density (GT-216, GT-222), SDLC Phase 05 rollback + on-call templates (GT-218), CLI branch coverage + envelope format coverage + skip-list cleanup (GT-220, GT-224, GT-225), MCP HTTP audit logging (GT-221), and cross-surface parity e2e tests (GT-223).

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import { CoworkAgentEngineAdapter, type CoworkClient } from '../adapters/engine/cowork-agent.adapter';
import type { AgentRuntimeRequest } from '../../domain/contracts/agent-runtime-request';
import type { SkillDescriptor } from '../../domain/contracts/capability';

describe('CoworkAgentEngineAdapter (GT-531 — bounded, replaceable governed executor)', () => {
const skills: SkillDescriptor[] = [
{ id: 'foo', description: 'Does foo', intents: ['foo'], type: 'effect', handler: jest.fn() } as unknown as SkillDescriptor,
{ id: 'bar', description: 'Does bar', intents: ['bar'], type: 'effect', handler: jest.fn() } as unknown as SkillDescriptor,
];

const request: AgentRuntimeRequest = {
intent: 'do the thing',
context: { tenantId: 'tenant-1', productId: 'prod-1', initiativeId: 'init-1', phase: 'build', gate: 'f2' },
};

it('proposes a tool the Cowork client selected WHEN it is in the governed catalog', async () => {
const client: CoworkClient = {
propose: jest.fn().mockResolvedValue({ tool: 'foo', arguments: { a: 1 }, rationale: 'Cowork picked foo.' }),
};
const plan = await new CoworkAgentEngineAdapter({ client }).plan(request, skills);
expect(plan).toEqual({ engine: 'cowork', proposedTool: 'foo', proposedArguments: { a: 1 }, rationale: 'Cowork picked foo.' });
});

it('REJECTS a tool outside the catalog — bounded executor never invents a capability', async () => {
const client: CoworkClient = {
propose: jest.fn().mockResolvedValue({ tool: 'delete-everything', rationale: 'trust me' }),
};
const plan = await new CoworkAgentEngineAdapter({ client }).plan(request, skills);
expect(plan.proposedTool).toBeUndefined();
expect(plan.engine).toBe('cowork');
expect(plan.rationale).toMatch(/not in the governed skill catalog — rejected/);
expect(plan.recommendations).toEqual(["Try 'foo': Does foo", "Try 'bar': Does bar"]);
});

it('is deterministic with NO client wired (no external call), like the stub', async () => {
const plan = await new CoworkAgentEngineAdapter().plan(request, skills);
expect(plan.proposedTool).toBeUndefined();
expect(plan.engine).toBe('cowork');
expect(plan.recommendations).toHaveLength(2);
});

it('treats Cowork as replaceable — same IAgentEnginePort as stub/hermes/swarms', () => {
const adapter = new CoworkAgentEngineAdapter();
expect(typeof adapter.plan).toBe('function');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ const ADAPTERS_SURFACE = [
'AutoApprovalAdapter',
'ChatApprovalAdapter',
'CliCommunicationGatewayAdapter',
'COWORK_ENGINE',
'CoworkAgentEngineAdapter',
'CompositeTrackerTraceAdapter',
'DEFAULT_SKILLS',
'DenyByDefaultApprovalAdapter',
Expand Down
Loading