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
2 changes: 1 addition & 1 deletion .claude-plugin/plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ospec-workflow",
"description": "Spec-Driven Development workflow for VS Code Agent Customization with OpenSpec, strict TDD, phase agents, skills, hooks, and verification contracts.",
"version": "2.53.1",
"version": "2.54.0",
"author": {
"name": "Manuel Michael Retamozo García"
},
Expand Down
2 changes: 1 addition & 1 deletion .plugin.json
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"name": "ospec-workflow",
"description": "Spec-Driven Development workflow for VS Code Agent Customization with OpenSpec, strict TDD, phase agents, skills, hooks, and verification contracts.",
"version": "2.53.1",
"version": "2.54.0",
"author": {
"name": "Manuel Michael Retamozo García"
},
Expand Down
22 changes: 21 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,26 @@ All notable changes to this project are documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

## [2.54.0] - 2026-08-28

### Security
- **Autoridad y binding exacto de RunnerReceipt (`runner-receipt/v1`)**:
- Nuevo contrato kernel `ospec://schemas/kernel/runner-receipt/v1` con `receipt_id` content-addressed y `evidence_id` obligatorio.
- `verifyCandidate` rechaza DTOs caller-owned `runner_receipts`/`receipts` (`UNTRUSTED_RUNNER_RECEIPT`) y solo consume un canal opaco `runnerReceiptChannel` emitido por el runtime.
- Se elimina matching por posición/nodo y fallback de role a `node.kind`; Candidate, Evidence y nodo deben coincidir exactamente (`INVALID_RUNNER_RECEIPT` / `RUNNER_RECEIPT_BINDING_MISMATCH`).
- `outcome: failed` con tokens satisfechos falla con `INVALID_RUNNER_RECEIPT`.
- **Cronología y replay fail-closed completos**:
- Strategies temporales exigen `run_id` único no vacío, ordinales estrictos y `previous_evidence_id` en cada transición posterior a la raíz.
- Replay exige bytes o `observation_blob_id` content-addressed resoluble, más el canal de receipts; sin material de observación retorna `GRAPH_DIVERGENCE`.

### Changed
- K6b permanece `revise` pendiente de terminal review objetivo; K6c sigue `blocked-by-K6b-terminal-review`.
- Dominios `independent-verification`, `assurance-graph` y `kernel-contract-schemas` enrolados en el baseline (skip) y reconciliados contra `a476b9a`.
- ADR `docs/adr/adr-20260828-014-runner-receipt-authority-binding.md`. Specs `independent-verification`, `assurance-graph` y `kernel-contract-schemas`.
- Remediación directa post-v2.53.1, documentada con `sdd-baseline` (skip) y `sdd-reconcile`. Verificación: focused K6b 115 pass; `npm test` PASS. Archivado en `openspec/changes/archive/2026-08-28-k6b-receipt-binding-and-replay-finalization/`.

## [2.53.1] - 2026-08-28

### Security
Expand All @@ -26,7 +46,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- `validateReplayRecords` recomputa `digestRawBytes` y `computeEvidenceId(record, bytes)` validando igualdad exacta contra `record.digest` y `record.evidence_id`.
- Revalidación obligatoria de procedencia mediante `evaluateProvenanceSufficiency(record, { requireRuntime: true })`, fallando con `GRAPH_DIVERGENCE` ante adulteración de digest, id o insuficiencia de provenance.
- ADRs `docs/adr/adr-20260828-010` a `013`. Specs `independent-verification` y `assurance-graph`.
- Cierre definitivo de los hallazgos B1, B2, B3 y H1 de K6b. Archivado en `openspec/changes/archive/2026-08-28-k6b-trusted-evidence-replay-closure/`.
- Cierre declarado originalmente para B1, B2, B3 y H1. El review terminal post-release reabrió receipt authority/binding, causalidad completa y replay sin material; ver errata del verify report. Archivado en `openspec/changes/archive/2026-08-28-k6b-trusted-evidence-replay-closure/`.

## [2.53.0] - 2026-08-28

Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# ADR-002: Derivación autoritativa de satisfacción desde Runner Receipts

- Status: proposed
- Status: superseded by ADR-005
- Change: k6b-trusted-evidence-replay-closure
- Date: 2026-08-28

## Context
El verificador independiente permitía un fallback de copia ciega de `node.required_evidence` hacia `evidence_requirements_satisfied` cuando el payload no declaraba cobertura, aprobando obligaciones críticas sin que un recibo de ejecución hubiera atestiguado la prueba efectiva.

## Decision
Derivar `evidence_requirements_satisfied` en `verifyCandidate` exclusivamente a partir de runner receipts confiables (`receipts` / `runner_receipts`) emitidos por el harness de ejecución. Se prohíbe explícitamente la copia automática o por defecto de `node.required_evidence`; si no hay recibo que lo atestigüe, el conjunto de satisfacción es vacío y la obligación MUST falla con `UNFULFILLED_MUST`.
Derivar `evidence_requirements_satisfied` en `verifyCandidate` exclusivamente a partir de runner receipts emitidos por el harness de ejecución. Se prohíbe explícitamente la copia automática o por defecto de `node.required_evidence`; si no hay recibo que lo atestigüe, el conjunto de satisfacción es vacío y la obligación MUST falla con `UNFULFILLED_MUST`.

La decisión original no definió cómo demostrar la autoridad del receipt ni su binding exacto a Evidence. ADR-005 sustituye esa parte con `runner-receipt/v1` y un canal opaco; conserva la prohibición de blind copy.

## Alternatives
- Mantener la copia por defecto de `node.required_evidence` cuando no se especifica satisfacción — rechazado: genera falsos positivos donde la mera existencia de un archivo da por probada una obligación.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# ADR-003: Cronología causal estricta mediante execution_sequence

- Status: proposed
- Status: accepted
- Change: k6b-trusted-evidence-replay-closure
- Date: 2026-08-28

## Context
Las estrategias temporales (`strict-tdd`, `bug`, `refactor`) recurrían al orden posicional de los elementos en el array JSON de `rawEvidence` para evaluar la secuencia cronológica, lo que permitía simular TDD o refactorizaciones invirtiendo el orden de las evidencias en el array sin atestación causal.

## Decision
Exigir obligatoriamente en `assertRoleOrder` un objeto `execution_sequence` válido (`run_id` consistente, `ordinal` monotónico creciente y encadenamiento `previous_evidence_id`) para cada evidencia en estrategias `strict-tdd`, `bug` y `refactor`. Se prohíbe de forma tajante el fallback a índices de array JSON, fallando inmediatamente con `STRATEGY_SEQUENCE_VIOLATION` ante ausencia o violación de orden.
Exigir obligatoriamente en `assertRoleOrder` un `execution_sequence` emitido por el receipt confiable para cada transición temporal de `strict-tdd`, `bug` y `refactor`. Todos los eventos usan un `run_id` no vacío y consistente; los ordinales son enteros positivos, únicos y crecientes; cada evento posterior a la raíz declara `previous_evidence_id` igual al EvidenceId inmediatamente anterior. Se prohíbe el fallback a índices del array JSON y se falla con `STRATEGY_SEQUENCE_VIOLATION` ante ausencia o violación causal.

## Alternatives
- Mantener el índice de array como fallback si falta `execution_sequence` — rechazado: la posición en un array JSON no tiene valor criptográfico ni atestación temporal.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# ADR-004: Replay criptográficamente íntegro en Assurance Graph

- Status: proposed
- Status: accepted
- Change: k6b-trusted-evidence-replay-closure
- Date: 2026-08-28

## Context
La validación en `replayAssuranceGraph` (`validateReplayRecords`) omitía la recomputación de `computeEvidenceId` y la invocación de `evaluateProvenanceSufficiency` durante la revalidación de evidencias, lo que permitía persistir o reproducir grafos con identificadores desfasados o procedencias débiles sin detección.

## Decision
Extender `validateReplayRecords` para recomputar exhaustivamente el digest de bytes con `digestRawBytes(bytes)`, recomputar `computeEvidenceId(record, bytes)`, contrastar ambos contra `record.digest` y `record.evidence_id`, y ejecutar `evaluateProvenanceSufficiency(record)`. Cualquier discrepancia, mutación de bytes o insuficiencia de procedencia detona inmediatamente un fallo `GRAPH_DIVERGENCE`.
Extender `validateReplayRecords` para exigir bytes inline o un `observation_blob_id` content-addressed resoluble, recomputar exhaustivamente el digest con `digestRawBytes(bytes)`, recomputar `computeEvidenceId(record, bytes)`, contrastar ambos contra `record.digest` y `record.evidence_id`, y ejecutar `evaluateProvenanceSufficiency(record)`. La ausencia de material de observación, una referencia no resoluble, cualquier discrepancia, mutación de bytes o insuficiencia de procedencia detona inmediatamente `GRAPH_DIVERGENCE`; no existe modo de replay criptográfico parcial.

## Alternatives
- Revalidar únicamente la conformidad sintáctica contra el esquema JSON — rechazado: no detecta sustitución de hashes ni inconsistencias en identificadores derivados.
Expand Down
23 changes: 23 additions & 0 deletions docs/adr/adr-20260828-014-runner-receipt-authority-binding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# ADR-005: Autoridad y binding exacto de RunnerReceipt

- Status: accepted
- Change: k6b-receipt-binding-and-replay-finalization
- Date: 2026-08-28

## Context
`verifyCandidate` aceptaba `runner_receipts` como DTOs ordinarios del mismo caller que aportaba `rawEvidence`. Además, un receipt sin `evidence_id` podía asociarse por nodo o posición. Mover las aserciones semánticas fuera de `rawEvidence` no establecía por sí solo una frontera de confianza.

## Decision
Introducir `runner-receipt/v1` con `receipt_id` content-addressed, `candidate_id`, `evidence_id` obligatorio, `node_id`, `role`, `satisfied_tokens`, `outcome`, `issuer_id`, `transport` y secuencia temporal cuando aplique. El verifier solo consume receipts desde un `runnerReceiptChannel` opaco registrado en un `WeakMap` privado del runtime; copiar sus campos públicos no reproduce la capacidad.

Rechazar propiedades caller-owned `receipts` y `runner_receipts`, recomputar `receipt_id`, validar issuer/transport contra el canal y exigir igualdad exacta de Evidence, Candidate y nodo. No se permite matching por posición, por nodo ni fallback de role a `node.kind`. `outcome: failed` con tokens satisfechos es un receipt inválido.

## Alternatives
- Confiar en `issuer_id` y `transport` como strings del DTO: rechazado porque el caller puede copiarlos.
- Firmar receipts con PKI: rechazado por no existir un trust root operativo y por ser desproporcionado para una frontera in-process.
- Mantener matching por índice dentro del verifier: rechazado porque no demuestra `R proves E`.

## Consequences
- Facilita: cada claim semántico queda ligado content-addressed a una Evidence concreta y a una capacidad de runtime no serializable.
- Dificulta: runners y tests deben emitir receipts completos mediante el canal; los DTOs legacy fallan cerrados y deben regenerarse.
- Reversibilidad: Media; relajar el canal o `evidence_id` reabriría la frontera de confianza cerrada por K6b.
22 changes: 18 additions & 4 deletions docs/architecture/harness-evolution.md
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
# Arquitectura objetivo — harness gobernado por kernel, grafo y evidencia

> **Autoridad:** fuente conceptual y estratégica del harness (responsabilidades y límites).
> **Corte documental:** v2.53.0, 2026-08-28 (estado alineado al roadmap; la dirección conceptual no cambia).
> **Estado verificado:** O3, O4+O5/O4.1, O4.2, O6A, O2B, **K1**, **K2**, **K2.1**, **K2a**, **K3**, **`k3-readiness-remediation`**, **K4a**, **K5**, **K6a**, **K4b** y **K6b** están cerrados. OpenSpec/Git/Candidate siguen siendo la única autoridad semántica; el Assurance Graph es proyección. **K6c** queda `next-eligible`.
> **Corte documental:** v2.54.0, 2026-08-28 (estado alineado al roadmap; la dirección conceptual no cambia).
> **Estado verificado:** O3, O4+O5/O4.1, O4.2, O6A, O2B, **K1**, **K2**, **K2.1**, **K2a**, **K3**, **`k3-readiness-remediation`**, **K4a**, **K5**, **K6a** y **K4b** están cerrados. **K6b** permanece `revise` con remediación focal implementada y terminal review pendiente; **K6c** está `blocked`. OpenSpec/Git/Candidate siguen siendo la única autoridad semántica; el Assurance Graph es proyección.
> **Roadmap:** orden, estado operativo y done criteria viven en [`../roadmaps/harness-evolution.md`](../roadmaps/harness-evolution.md).
> **Precedencia documental:** ante diferencias de **orden o estado**, prevalece el roadmap; ante diferencias **conceptuales**, reconciliar antes de iniciar el slice.
> **Investigación no normativa:** la trazabilidad completa P0–P27 vive en [`research/harness-kernel-graph-evidence-roadmap-fusion.md`](research/harness-kernel-graph-evidence-roadmap-fusion.md). La proporcionalidad de proceso y el programa de changes viven en [`research/proportional-process-and-change-program.md`](research/proportional-process-and-change-program.md).
Expand All @@ -21,7 +21,7 @@ Sin duplicar el backlog: solo responsabilidades y límites alineados al roadmap

| Tema | Decisión arquitectónica |
| --- | --- |
| Estado | K1+K2+K2.1+K2a+K3+`k3-readiness-remediation`+K4a+K5+K6a+K4b+K6b `done`; **K6c** `next-eligible` |
| Estado | K1+K2+K2.1+K2a+K3+`k3-readiness-remediation`+K4a+K5+K6a+K4b `done`; **K6b** `revise`; **K6c** `blocked-by-K6b-terminal-review` |
| Dos grafos | **Execution Graph** (trabajo) ≠ **Assurance Graph** (fiabilidad / evidencia; no “prueba formal”) |
| Identidades | `SourceSnapshotId` / `WorkOrderId` / `WorkResultId` / `CandidateId` (sin IDs nuevos por ahora) |
| Relación Candidate | Inicial: `exact` / `changed` / `ambiguous` / `unknown`; `compatible-base-advance` experimental hasta K9 |
Expand All @@ -30,6 +30,7 @@ Sin duplicar el backlog: solo responsabilidades y límites alineados al roadmap
| Policy | `PolicySnapshot` digiere bundle/classifier/compiler/runtime/`effectiveRules` |
| Cierre | `ArchiveTransactionReceipt` ≠ `CandidateEvaluationAttestation` ≠ `DeliveryAuthorization` |
| Schemas de cierre | `receipt/v1` (K1, envelope legacy genérico) permanece; K8 y K10-delivery introducen schemas propios — no reutilizar `receipt/v1` como contrato canónico |
| Receipt de ejecución | K6b usa `runner-receipt/v1`, content-addressed y Evidence-bound; solo un canal opaco de runtime concede autoridad. Strings issuer/transport no bastan. |
| Host | Seis targets; **K2a** = Headless Conformance Host + un adapter real + CapabilityProof; **K11a** expande a los cinco restantes |
| Obligations | **K4a:** Obligation Manifest como vista determinista del Graph (no tercer grafo) |
| Compile vs execute | **K4a** compila; **K6a** ejecuta (primitives); **K4b** orquesta Repair shadow; **K3** identifica |
Expand All @@ -54,6 +55,19 @@ Añade límites; **no** mueve next-eligible, no reabre `done` y no crea un slice
| Contexto | Prompt de worker/fase efímero; contrato, candidate, budgets, findings y evidencia persistentes. Compact/sesión nueva no resetea linaje. `/sdd-continue {nombre}` reanuda un change; no una cola. |
| Rechazado | `architect-agent`, fase `architecture`, ruta `epic`, pipeline de cinco agentes, agentes espejo `*-cheap`, milestone paralelo. |

### Corte correctivo 2026-08-28 (fronteras K6b)

El review terminal de v2.53.1 no cambia la dirección del kernel, pero obliga a materializar dos interfaces que antes eran solo intención arquitectónica.

| Tema | Decisión arquitectónica |
| --- | --- |
| RunnerReceipt | DTO caller-owned ≠ autoridad. `runner-receipt/v1` requiere EvidenceId y receipt_id; el verifier solo lo acepta desde una capacidad opaca registrada por el runtime. |
| Matching | Solo igualdad de `evidence_id`, `candidate_id` y `node_id`; no posición, no nodo como fallback, no `node.kind` como role. |
| Outcome | Un receipt fallido puede probar RED, pero no declarar `satisfied_tokens`. |
| Chronology | Un run no vacío, ordinales únicos y cada transición enlaza el EvidenceId inmediatamente anterior. |
| Replay | Cada Evidence lleva bytes inline o blob CAS resoluble. Sin material no hay recomputación criptográfica y el replay falla con `GRAPH_DIVERGENCE`. |
| Gate | K6b sigue `revise`; K6c no comienza hasta terminal review objetivo de estas garantías. |

## Ruta rápida

1. [Modelo de autoridad](#modelo-de-autoridad).
Expand Down Expand Up @@ -855,7 +869,7 @@ Repositorios fixture reciben 10–30 cambios consecutivos. Se miden duplicación
8. ~~K5: budgets (incl. autoridad/efectos) / failure / recovery~~ — hecho: archivado y publicado en v2.45.13 (remediaciones v2.45.7→v2.45.13).
9. ~~K6a: primitivas de ejecución aislada (`CreateWorkspace`…`DisposeWorkspace`); no conoce Repair~~ — hecho: archivado y publicado en v2.46.7; frontera de procesos cerrada en v2.47.1; endurecimiento de frontera (política inmutable, fs mutante, live-identity, `worker_threads`) en v2.47.2.
10. ~~K4b: orquesta Repair shadow (consume K6a; freeze Candidate vía K3)~~ — hecho: publicado en v2.48.0; corrección en v2.48.1; invariantes de integración en v2.48.2; cierre mode-only/baseline en v2.48.3.
11. ~~K6b: verifier + provenance + Assurance Graph (proyección)~~ — publicado en v2.50.0; integridad semántica B1–B3/H1–H3 cerrada en v2.52.0. K6c ChallengePlan queda `next-eligible`; K6d complexity delta sigue pendiente.
11. K6b: verifier + provenance + Assurance Graph (proyección) — publicado desde v2.50.0 y endurecido hasta v2.53.1; reabierto como `revise` por receipt authority/binding, causal chain y replay material obligatorio. Remediación focal implementada; terminal review pendiente. K6c permanece bloqueado.
12. K7: ReviewAdapter + ReviewReducer + lineage; K8: CandidateEvaluationAttestation (emisión CAS).
13. K9: shadow/replay/A-B; promoción de **un** profile (checkpoints intermedios ya validados).
14. K10-delivery: DeliveryAuthorization **solo** del profile promovido; relación Candidate por etapas; resto fixed/deferred.
Expand Down
Loading