gemstack-ai 1.0.1 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.agents/rules/01-gemstack-core.md +15 -0
- package/.agents/rules/02-gemstack-constitution.md +12 -1
- package/.agents/skills/gemstack-handoff/SKILL.md +2 -1
- package/.agents/skills/gemstack-plan/SKILL.md +2 -1
- package/.agents/skills/gemstack-review/SKILL.md +7 -5
- package/.agents/skills/gemstack-ship/SKILL.md +5 -0
- package/.agents/skills/gemstack-spec/SKILL.md +3 -2
- package/.agents/skills/gemstack-tasks/SKILL.md +4 -3
- package/.gemstack/state.json +20 -2
- package/CHANGELOG.md +52 -0
- package/MANUAL.md +4 -4
- package/README.md +36 -8
- package/RELEASE_NOTES.md +105 -0
- package/assets/logo.jpg +0 -0
- package/docs/architecture-consistency.md +144 -0
- package/gemstack-ai-1.1.2.tgz +0 -0
- package/handoff.md +27 -40
- package/package.json +3 -2
- package/scripts/ci/smoke-cli.js +1 -0
- package/specs/006-architecture-consistency-engine/.gemstack.json +9 -0
- package/specs/006-architecture-consistency-engine/plan.md +319 -0
- package/specs/006-architecture-consistency-engine/spec.md +179 -0
- package/specs/006-architecture-consistency-engine/tasks.md +532 -0
- package/specs/templates/plan.md +11 -0
- package/specs/templates/spec.md +17 -0
- package/specs/templates/tasks.md +1 -0
- package/src/cli.js +9 -4
- package/src/commands/verify.js +311 -0
- package/src/lib/contracts.js +388 -0
- package/src/lib/findings.js +227 -0
- package/src/lib/hasher.js +103 -0
- package/src/lib/state.js +143 -0
- package/src/mcp-server.js +1 -1
- package/template/.agents/rules/01-gemstack-core.md +15 -0
- package/template/.agents/rules/02-gemstack-constitution.md +12 -1
- package/template/.agents/skills/gemstack-handoff/SKILL.md +2 -1
- package/template/.agents/skills/gemstack-plan/SKILL.md +2 -1
- package/template/.agents/skills/gemstack-review/SKILL.md +7 -5
- package/template/.agents/skills/gemstack-ship/SKILL.md +5 -0
- package/template/.agents/skills/gemstack-spec/SKILL.md +3 -2
- package/template/.agents/skills/gemstack-tasks/SKILL.md +4 -3
- package/template/docs/architecture-consistency.md +144 -0
- package/template/specs/templates/plan.md +11 -0
- package/template/specs/templates/spec.md +17 -0
- package/template/specs/templates/tasks.md +1 -0
- package/gemstack-ai-1.0.1.tgz +0 -0
package/handoff.md
CHANGED
|
@@ -1,45 +1,32 @@
|
|
|
1
|
-
# Gemstack Handoff
|
|
1
|
+
# Gemstack Handoff
|
|
2
2
|
|
|
3
|
-
##
|
|
4
|
-
Gemstack
|
|
3
|
+
## 1. Objetivo
|
|
4
|
+
Evolucionar Gemstack incorporando el feedback de producción real de proyectos activos:
|
|
5
|
+
1. Eliminar falsos positivos silenciosos en test runners en Windows/monorepos (Zero Silent Failures).
|
|
6
|
+
2. Ruteo semántico por intención (Intent-Based Routing) para interacción natural sin requerir `/comando`.
|
|
7
|
+
3. Sincronización automática del ciclo de vida en `.gemstack/state.json` al entregar (`/ship`) o documentar (`/handoff`).
|
|
8
|
+
4. Comando unificado `gemstack verify` (alias `audit`) para auditoría integral en un solo paso.
|
|
5
9
|
|
|
6
|
-
## Estado
|
|
7
|
-
|
|
8
|
-
|
|
10
|
+
## 2. Estado actual
|
|
11
|
+
- **Upgrade A (Consistency Core & Phase Freezing)**: CERRADO Y LIBERADO como v1.1.0 (`GEMSTACK UPGRADE A SHIPPED / DONE — ARCHITECTURE CLOSED`).
|
|
12
|
+
- 17/17 tareas completadas, 25/25 tests canónicos P1 pasando (33/33 físicos), 0 bloqueadores.
|
|
13
|
+
- Reglas `01-gemstack-core.md`, `02-gemstack-constitution.md`, plantillas y skills actualizados y sincronizados en `template/`.
|
|
14
|
+
- Motor de consistencia integrado en `gemstack verify` (Paso 4/5).
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
- Skill `gemstack-dashboard` (`/dashboard`) creado para leer el estado del proyecto y renderizar un widget HTML interactivo con el progreso de `tasks.md`.
|
|
20
|
-
5. **Servidor Nativo MCP (Model Context Protocol):**
|
|
21
|
-
- Implementado en `src/mcp-server.js`. Gemstack ahora actúa como un servidor MCP accesible vía `npx gemstack mcp`, exponiendo el SDD del proyecto a clientes IA externos mediante JSON-RPC sobre stdio.
|
|
22
|
-
6. **Package Version:**
|
|
23
|
-
- El archivo `package.json` fue ascendido a `v1.0.0`.
|
|
16
|
+
## 3. Archivos y cambios
|
|
17
|
+
- `src/lib/contracts.js`: Parser column-0 fenced, esquemas de 6 contratos, resolución de herencia y detección de contradicciones.
|
|
18
|
+
- `src/lib/hasher.js`: Hashing canónico SHA-256 (64 hex lowercase) con normalización CRLF->LF y rechazo de BOM UTF-8.
|
|
19
|
+
- `src/lib/findings.js`: Fingerprints canónicos SHA-256 de 64 caracteres, display token de 12 caracteres y excepciones con `contextHash`.
|
|
20
|
+
- `src/lib/state.js`: Persistencia atómica de `state.json` (solo operativo) y sidecar histórico `.gemstack.json`.
|
|
21
|
+
- `src/commands/verify.js`: Paso 4/5 de consistencia arquitectónica y hashes congelados.
|
|
22
|
+
- `tests/`: 5 suites unitarias (`contracts.test.js`, `hasher.test.js`, `findings.test.js`, `init.test.js`, `verify.test.js`).
|
|
23
|
+
- `docs/architecture-consistency.md`: Referencia técnica integral de consistencia y congelamiento de fases.
|
|
24
|
+
- `CHANGELOG.md`, `README.md`, `RELEASE_NOTES.md`, `package.json`: Versión v1.1.0 documentada y preparada para release.
|
|
24
25
|
|
|
25
|
-
##
|
|
26
|
-
-
|
|
27
|
-
-
|
|
28
|
-
- Evolución de `gemstack-cso` para revisar infraestructura.
|
|
29
|
-
- Nuevo script `src/commands/hooks.js` y vinculación en `cli.js` e `init.js`.
|
|
30
|
-
- Nuevo script `src/commands/install.js`.
|
|
31
|
-
- Creación del Skill `gemstack-dashboard` y actualización de `.agents/rules/01-gemstack-core.md`.
|
|
32
|
-
- Nuevo servidor `src/mcp-server.js` y vinculación CLI.
|
|
33
|
-
- Todos los archivos `.agents/` nuevos fueron replicados en la carpeta `template/`.
|
|
34
|
-
- Actualización mayor de `README.md` documentando todas las capacidades "v1.0".
|
|
26
|
+
## 4. Intentos fallidos
|
|
27
|
+
- Se confirmó en proyectos reales que scripts de prueba con sintaxis `2>nul` en `package.json` provocan que PowerShell/Bash enmascaren errores y retornen código de salida 0 con 0 tests ejecutados. Ahora esto es detectado como error por `gemstack verify` y prohibido en la Constitución.
|
|
28
|
+
- **2026-09-11**: En el reporte de Upgrade A, se produjo un drift en la nomenclatura y categorización de la matriz P1 canónica (mencionando A04-A06, D03-D04, E03 y sugiriendo incorrectamente merge de múltiples bloques). Se restauró la correlación canónica estricta de 25 tests P1 aprobados (A=3, B=8, C=4, D=2, E=2, F=2, G=2, H=2) y la regla estricta de parser de 2+ bloques -> CONTRACT_PARSE_ERROR.
|
|
35
29
|
|
|
36
|
-
##
|
|
37
|
-
1.
|
|
38
|
-
2.
|
|
39
|
-
3. **Mantenimiento del Servidor MCP:** Actualmente el servidor MCP expone 2 herramientas (`get_current_tasks`, `get_security_rules`). En futuras iteraciones se podrían agregar herramientas de mutación (escribir specs a través de MCP).
|
|
40
|
-
|
|
41
|
-
## Archivos Críticos a Tener en Cuenta
|
|
42
|
-
- `src/cli.js`: El cerebro del enrutador de comandos.
|
|
43
|
-
- `src/commands/*.js`: Cada comando de la CLI está encapsulado de forma nativa.
|
|
44
|
-
- `template/`: Esta carpeta *debe* contener un espejo exacto de `.agents/`, `.gemstack/`, `docs/` y `specs/`. ¡Nunca modifiques reglas locales sin actualizarlas en el `template/`!
|
|
45
|
-
- `scripts/ci/*.js`: Toda la validación CI depende de scripts cero-dependencias escritos en Node.
|
|
30
|
+
## 5. Próximos pasos
|
|
31
|
+
1. Validar el nuevo ruteo semántico en sesiones de desarrollo reales.
|
|
32
|
+
2. Considerar `npx gemstack verify` en los hooks o pipelines de CI de proyectos que consumen Gemstack.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "gemstack-ai",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "Agentic Spec-Driven Development framework for Gemini/Antigravity",
|
|
5
5
|
"main": "src/cli.js",
|
|
6
6
|
"bin": {
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"node": ">=18.18.0"
|
|
11
11
|
},
|
|
12
12
|
"scripts": {
|
|
13
|
-
"test": "node --test tests/init.test.js",
|
|
13
|
+
"test": "node --test tests/contracts.test.js tests/hasher.test.js tests/findings.test.js tests/init.test.js tests/verify.test.js",
|
|
14
|
+
"gemstack:verify": "node src/cli.js verify",
|
|
14
15
|
"pack:dry": "npm pack --dry-run",
|
|
15
16
|
"ci:frontmatter": "node scripts/ci/check-frontmatter.js",
|
|
16
17
|
"ci:template": "node scripts/ci/check-template-clean.js",
|
package/scripts/ci/smoke-cli.js
CHANGED
|
@@ -24,6 +24,7 @@ runSafe(`node "${path.join(rootDir, 'src/cli.js')}" show gemstack-handoff`, root
|
|
|
24
24
|
runSafe(`node "${path.join(rootDir, 'src/cli.js')}" init --dry-run --target "${tmpDir}"`, tmpDir);
|
|
25
25
|
runSafe(`node "${path.join(rootDir, 'src/cli.js')}" init --yes --target "${tmpDir}"`, tmpDir);
|
|
26
26
|
runSafe(`node "${path.join(rootDir, 'src/cli.js')}" doctor --target "${tmpDir}"`, tmpDir);
|
|
27
|
+
runSafe(`node "${path.join(rootDir, 'src/cli.js')}" verify --target "${tmpDir}"`, tmpDir);
|
|
27
28
|
runSafe(`node "${path.join(rootDir, 'src/cli.js')}" update --dry-run --target "${tmpDir}"`, tmpDir);
|
|
28
29
|
|
|
29
30
|
fs.rmSync(tmpDir, { recursive: true, force: true });
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"phase_hashes": {
|
|
3
|
+
"spec": "f5d423eaf508b06b663b39f467fba1d9ceff6db21f01e427500ad739a90c5be8",
|
|
4
|
+
"plan": "1ce0e58863427905022a6294f8683b9f508d72b171379c78807db19862c75004",
|
|
5
|
+
"tasks": "dfad2484ad112e26ef906ea851b12cf6ea090d6faf244a6fbd2650baee8e0d98"
|
|
6
|
+
},
|
|
7
|
+
"historical_findings": [],
|
|
8
|
+
"accepted_exceptions": []
|
|
9
|
+
}
|
|
@@ -0,0 +1,319 @@
|
|
|
1
|
+
# Plan de Implementación: Architecture Consistency Engine & Phase Freezing (Upgrade A)
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `006-architecture-consistency-engine`
|
|
4
|
+
**Spec**: [`specs/006-architecture-consistency-engine/spec.md`](file:///c:/CODES/Gemstack/specs/006-architecture-consistency-engine/spec.md)
|
|
5
|
+
**Lifecycle Status**: `PLAN_COMPLETE`
|
|
6
|
+
**Stop Reason**: `PLAN_COMPLETE_AWAITING_REVIEW`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Resumen y Contexto Técnico
|
|
11
|
+
|
|
12
|
+
El objetivo de este plan es diseñar la arquitectura técnica para **Upgrade A**, transformando la especificación congelada en módulos de Node.js nativos sin dependencias externas (*Zero-Dependency Core*).
|
|
13
|
+
|
|
14
|
+
### Restricciones Arquitectónicas Inmutables
|
|
15
|
+
- **Runtime**: Node.js >= 18.18.0 nativo.
|
|
16
|
+
- **Dependencias**: Cero paquetes npm de terceros (uso exclusivo de `crypto`, `fs`, `path`, `assert`, `node:test`).
|
|
17
|
+
- **Compatibilidad**: Modo `LEGACY` transparente para specs previas (001 a 005) y retrocompatibilidad binaria de `.gemstack/state.json`.
|
|
18
|
+
- **Multiplataforma**: Soporte idéntico en Windows (CRLF, backslashes), Linux y macOS.
|
|
19
|
+
|
|
20
|
+
---
|
|
21
|
+
|
|
22
|
+
## 2. Constitution Check (Phase -1 Gates)
|
|
23
|
+
|
|
24
|
+
### Simplicity Gate (Article VII)
|
|
25
|
+
- [x] **¿Se usan el mínimo número de carpetas/archivos posibles?** Sí: 4 librerías modulares en `src/lib/` (`hasher.js`, `contracts.js`, `findings.js`, `state.js`) y extensión quirúrgica de `src/commands/verify.js`.
|
|
26
|
+
- [x] **¿No hay abstracciones prematuras?** Sí: No se crea un framework de AST ni compiladores genéricos; parsing directo de bloques JSON delimitados.
|
|
27
|
+
|
|
28
|
+
### Anti-Abstraction Gate (Article VIII)
|
|
29
|
+
- [x] **¿Se usan las APIs nativas del framework sin wrappers innecesarios?** Sí: `crypto.createHash('sha256')`, `fs.writeFileSync`, `path.relative`.
|
|
30
|
+
|
|
31
|
+
### Test-First Imperative & Zero Silent Failures (Article III)
|
|
32
|
+
- [x] **¿El plan incluye la creación de tests antes que el código fuente?** Sí: Matriz P1 de 25 tests estructurados en `tests/contracts.test.js`, `tests/hasher.test.js`, `tests/findings.test.js` y regresión en `tests/verify.test.js`.
|
|
33
|
+
- [x] **¿Cero falsos positivos silenciosos?** Sí: Pruebas unitarias nativas sin `2>nul`.
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 3. Diseño Detallado de Arquitectura y Módulos
|
|
38
|
+
|
|
39
|
+
```text
|
|
40
|
+
c:\CODES\Gemstack\
|
|
41
|
+
├── src\
|
|
42
|
+
│ ├── lib\
|
|
43
|
+
│ │ ├── hasher.js <-- [NUEVO] Normalización LF, detección BOM y SHA-256
|
|
44
|
+
│ │ ├── contracts.js <-- [NUEVO] Parser ```gemstack-contracts, normalizador, comparador
|
|
45
|
+
│ │ ├── findings.js <-- [NUEVO] Fingerprints, deltas consolidados y anti-loop
|
|
46
|
+
│ │ └── state.js <-- [NUEVO] Lector/escritor atómico (tmp + rename) para state.json
|
|
47
|
+
│ └── commands\
|
|
48
|
+
│ └── verify.js <-- [MODIFICAR] Incorporar paso 4: Consistencia y Hashes de Fase
|
|
49
|
+
├── tests\
|
|
50
|
+
│ ├── contracts.test.js <-- [NUEVO] Tests categorías A y B (Parsing, Enums, Identity, Boundary, Herencia)
|
|
51
|
+
│ ├── hasher.test.js <-- [NUEVO] Tests categoría C (Freeze, CRLF/LF, Detección de mutación)
|
|
52
|
+
│ └── findings.test.js <-- [NUEVO] Tests categorías D, E, F y G (Fingerprints, Anti-loop, Legacy, Windows)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
### 3.1 Módulo `src/lib/hasher.js`
|
|
58
|
+
|
|
59
|
+
#### Responsabilidad
|
|
60
|
+
Calcular hashes deterministas de artefactos markdown garantizando invariancia de plataforma (Windows vs POSIX).
|
|
61
|
+
|
|
62
|
+
#### Algoritmo de Hashing
|
|
63
|
+
1. Leer buffer o string UTF-8.
|
|
64
|
+
2. Comprobar presencia de UTF-8 BOM (`0xEF, 0xBB, 0xBF` o `\uFEFF`). Si existe, rechazar con error `CONTRACT_PARSE_ERROR: BOM detected in phase artifact`.
|
|
65
|
+
3. Normalizar saltos de línea: reemplazar `\r\n` por `\n` y cualquier `\r` suelto por `\n`.
|
|
66
|
+
4. Calcular SHA-256 sobre los bytes UTF-8 resultantes.
|
|
67
|
+
5. Retornar digest hexadecimal en minúsculas (64 caracteres).
|
|
68
|
+
|
|
69
|
+
#### Funciones Exportadas
|
|
70
|
+
- `normalizeContent(content: string): string`
|
|
71
|
+
- `hashArtifact(content: string): string`
|
|
72
|
+
- `hashFile(filePath: string): string`
|
|
73
|
+
|
|
74
|
+
---
|
|
75
|
+
|
|
76
|
+
### 3.2 Módulo `src/lib/contracts.js`
|
|
77
|
+
|
|
78
|
+
#### Responsabilidad
|
|
79
|
+
Localizar, extraer, validar, normalizar y comparar contratos declarados en artefactos de fase.
|
|
80
|
+
|
|
81
|
+
#### Delimitador Canónico y Reglas de Parsing
|
|
82
|
+
- **Delimitador**:
|
|
83
|
+
````markdown
|
|
84
|
+
```gemstack-contracts
|
|
85
|
+
[
|
|
86
|
+
...
|
|
87
|
+
]
|
|
88
|
+
```
|
|
89
|
+
````
|
|
90
|
+
- **Regla de Bloque Único**: Se permite **exactamente un bloque** `gemstack-contracts` por artefacto. Si se detectan dos o más bloques, emite `CONTRACT_PARSE_ERROR: Multiple gemstack-contracts blocks detected`.
|
|
91
|
+
- **Bloque Vacío**: `[]` es válido y representa 0 contratos declarados.
|
|
92
|
+
- **Sin Bloque**: Retorna `null` (activa modo `LEGACY`).
|
|
93
|
+
|
|
94
|
+
#### Esquemas Exactos de Contratos
|
|
95
|
+
|
|
96
|
+
1. **`ENUM_SET`**:
|
|
97
|
+
```json
|
|
98
|
+
{
|
|
99
|
+
"id": "job-status",
|
|
100
|
+
"type": "ENUM_SET",
|
|
101
|
+
"values": ["QUEUED", "PROCESSING", "COMPLETED", "FAILED"],
|
|
102
|
+
"description": "Opcional"
|
|
103
|
+
}
|
|
104
|
+
```
|
|
105
|
+
*Normalización:* Trim a cada string; rechazar miembros vacíos o duplicados. Comparación insensible al orden (`values.slice().sort()`).
|
|
106
|
+
|
|
107
|
+
2. **`IDENTITY_TUPLE`**:
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"id": "publication-identity",
|
|
111
|
+
"type": "IDENTITY_TUPLE",
|
|
112
|
+
"values": ["workspaceId", "recordingId", "languageTag", "kind"]
|
|
113
|
+
}
|
|
114
|
+
```
|
|
115
|
+
*Normalización:* Trim a cada string; rechazar duplicados. Comparación es un conjunto semántico de miembros exactos (`order-insensitive`, `duplicate-sensitive`, `exact-member-sensitive`).
|
|
116
|
+
|
|
117
|
+
3. **`PROVENANCE_RULE`**:
|
|
118
|
+
```json
|
|
119
|
+
{
|
|
120
|
+
"id": "caption-provenance",
|
|
121
|
+
"type": "PROVENANCE_RULE",
|
|
122
|
+
"entity": "CaptionAsset",
|
|
123
|
+
"values": ["parentRecordingAssetId", "sourceMediaAssetType", "sourceRecordingExportAssetId"]
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
*Normalización:* Requiere `entity` (string no vacío) y lista de campos requeridos exactos.
|
|
127
|
+
|
|
128
|
+
4. **`BOOLEAN_INVARIANT`**:
|
|
129
|
+
```json
|
|
130
|
+
{
|
|
131
|
+
"id": "zero-dependency-core",
|
|
132
|
+
"type": "BOOLEAN_INVARIANT",
|
|
133
|
+
"value": true
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
*Normalización:* `value` debe ser estrictamente tipo booleano (`typeof value === 'boolean'`). Se rechazan `"true"` o `"false"` como strings.
|
|
137
|
+
|
|
138
|
+
5. **`BOUNDARY`**:
|
|
139
|
+
```json
|
|
140
|
+
{
|
|
141
|
+
"id": "eventalus-sync-dependency",
|
|
142
|
+
"type": "BOUNDARY",
|
|
143
|
+
"value": "FORBIDDEN"
|
|
144
|
+
}
|
|
145
|
+
```
|
|
146
|
+
*Valores permitidos:* Exclusivamente `"FORBIDDEN"` y `"REQUIRED"`. Comparación estricta de string (`FORBIDDEN` vs `FORBIDDEN` ➔ `PASS`; `REQUIRED` vs `REQUIRED` ➔ `PASS`; `FORBIDDEN` vs `REQUIRED` o viceversa ➔ `FROZEN_CONTRACT_VIOLATION`).
|
|
147
|
+
|
|
148
|
+
6. **`ROADMAP_LIMIT`**:
|
|
149
|
+
```json
|
|
150
|
+
{
|
|
151
|
+
"id": "final-planned-mvp",
|
|
152
|
+
"type": "ROADMAP_LIMIT",
|
|
153
|
+
"value": 18
|
|
154
|
+
}
|
|
155
|
+
```
|
|
156
|
+
*Normalización:* Escalar JSON (`number` o `string`). No hay coerción de tipo.
|
|
157
|
+
|
|
158
|
+
#### Algoritmo de Herencia y Comparación
|
|
159
|
+
```text
|
|
160
|
+
effectiveSpecRegistry = spec contracts
|
|
161
|
+
effectivePlanRegistry = effectiveSpecRegistry + additive plan contracts
|
|
162
|
+
effectiveTasksRegistry = effectivePlanRegistry + additive tasks contracts
|
|
163
|
+
```
|
|
164
|
+
- Si un contrato de `spec.md` no se repite en `plan.md` ➔ `PASS` (heredado implícitamente, no requiere duplicación).
|
|
165
|
+
- Si se re-declara con valor normalizado idéntico ➔ `PASS`.
|
|
166
|
+
- Si se re-declara con valor diferente ➔ emite `FROZEN_CONTRACT_VIOLATION` (`BLOCKER`).
|
|
167
|
+
- Si `plan.md` introduce un ID nuevo ➔ clasificado como aditivo ➔ `PASS`.
|
|
168
|
+
|
|
169
|
+
---
|
|
170
|
+
|
|
171
|
+
### 3.3 Módulo `src/lib/findings.js`
|
|
172
|
+
|
|
173
|
+
#### Responsabilidad
|
|
174
|
+
Gestión determinista de hallazgos, generación de huellas digitales (*fingerprints*), cálculo de deltas consolidados y supresión anti-loop.
|
|
175
|
+
|
|
176
|
+
#### Granularidad de Hallazgos
|
|
177
|
+
Para cada comparación de contrato, se genera **un único hallazgo consolidado** por `(contractId, phase, violationType)`.
|
|
178
|
+
El payload del hallazgo incluye:
|
|
179
|
+
```json
|
|
180
|
+
{
|
|
181
|
+
"fingerprint": "c1f...",
|
|
182
|
+
"code": "FROZEN_CONTRACT_VIOLATION",
|
|
183
|
+
"severity": "BLOCKER",
|
|
184
|
+
"contractId": "transcription-job-status",
|
|
185
|
+
"phase": "plan",
|
|
186
|
+
"location": "specs/006-architecture-consistency-engine/plan.md",
|
|
187
|
+
"delta": {
|
|
188
|
+
"expected": ["COMPLETED", "FAILED", "PROCESSING", "QUEUED"],
|
|
189
|
+
"observed": ["CANCELLED", "COMPLETED", "FAILED", "PROCESSING", "QUEUED"],
|
|
190
|
+
"missing": [],
|
|
191
|
+
"added": ["CANCELLED"]
|
|
192
|
+
},
|
|
193
|
+
"status": "OPEN"
|
|
194
|
+
}
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### Huella Digital (*Fingerprint*) Canónica vs Display
|
|
198
|
+
```javascript
|
|
199
|
+
function createFingerprint(finding) {
|
|
200
|
+
const raw = JSON.stringify({
|
|
201
|
+
code: finding.code,
|
|
202
|
+
contractId: finding.contractId ?? null,
|
|
203
|
+
phase: finding.phase,
|
|
204
|
+
location: finding.location ? finding.location.replace(/\\/g, '/') : null
|
|
205
|
+
});
|
|
206
|
+
return crypto.createHash('sha256').update(raw, 'utf8').digest('hex');
|
|
207
|
+
}
|
|
208
|
+
```
|
|
209
|
+
- **Fingerprint Canónico (Identidad)**: Digest SHA-256 completo en hexadecimal en minúsculas de **64 caracteres**. Es la clave inmutable utilizada para persistencia, seguimiento de excepciones y motor anti-loop. **Nunca se trunca** en el almacenamiento.
|
|
210
|
+
- **Display Fingerprint (Cosmético)**: Si se requiere para legibilidad en salida CLI, se puede derivar una representación corta visual (`displayFingerprint = fingerprint.slice(0, 12)`), pero jamás se usa como identidad ni como clave en `.gemstack.json`.
|
|
211
|
+
|
|
212
|
+
#### Context Hash y Anti-Loop
|
|
213
|
+
```javascript
|
|
214
|
+
function computeContextHash(upstreamHash, currentHash, contractNormalized) {
|
|
215
|
+
return crypto.createHash('sha256')
|
|
216
|
+
.update(`${upstreamHash || ''}:${currentHash || ''}:${JSON.stringify(contractNormalized || {})}`)
|
|
217
|
+
.digest('hex');
|
|
218
|
+
}
|
|
219
|
+
```
|
|
220
|
+
- **`RESOLVED`**: Significa que el defecto fue corregido en el código/artefacto. Si el validador vuelve a correr y la violación persiste, el hallazgo se reactiva automáticamente.
|
|
221
|
+
- **`ACCEPTED_EXCEPTION`**: Requiere `approvedByHuman = true`. Suprime el bloqueo si `contextHash` permanece idéntico. Si el artefacto involucrado cambia, la excepción vuelve a requerir revisión.
|
|
222
|
+
- **`SUPERSEDED`**: Ocurre cuando una enmienda oficial a la especificación vuelve obsoleto un hallazgo previo.
|
|
223
|
+
|
|
224
|
+
#### Almacenamiento Persistente
|
|
225
|
+
Para evitar sobrecargar `state.json` con listas ilimitadas de hallazgos, se almacenan en un sidecar por feature:
|
|
226
|
+
`specs/<feature>/.gemstack.json`
|
|
227
|
+
Contiene:
|
|
228
|
+
```json
|
|
229
|
+
{
|
|
230
|
+
"feature": "006-architecture-consistency-engine",
|
|
231
|
+
"phase_hashes": { "spec": "...", "plan": "...", "tasks": "..." },
|
|
232
|
+
"accepted_exceptions": [],
|
|
233
|
+
"resolved_findings": []
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
---
|
|
238
|
+
|
|
239
|
+
### 3.4 Módulo `src/lib/state.js`
|
|
240
|
+
|
|
241
|
+
#### Responsabilidad
|
|
242
|
+
Operaciones de lectura y escritura atómica sobre `.gemstack/state.json`.
|
|
243
|
+
|
|
244
|
+
#### Algoritmo de Escritura Atómica (Planificado para `src/lib/state.js`)
|
|
245
|
+
1. Resolver ruta absoluta con `fssafe.resolveSafe(targetDir, '.gemstack/state.json')`.
|
|
246
|
+
2. Escribir primero en archivo temporal adyacente: `.gemstack/state.json.tmp.<pid>.<timestamp>`.
|
|
247
|
+
3. Renombrar atómicamente (`fs.renameSync`) sobre `.gemstack/state.json`.
|
|
248
|
+
4. En Windows, si existe bloqueo temporal transitorio, realizar reintento controlado (3 intentos con backoff de 50ms).
|
|
249
|
+
|
|
250
|
+
---
|
|
251
|
+
|
|
252
|
+
## 4. Integración en `src/commands/verify.js`
|
|
253
|
+
|
|
254
|
+
El verificador actual de 4 pasos se expande a 5 pasos limpios:
|
|
255
|
+
|
|
256
|
+
```text
|
|
257
|
+
[INFO] --- 1/5 Verificación Estructural (Archivos Base) ---
|
|
258
|
+
[INFO] --- 2/5 Verificación de Memoria e Integridad de Handoff ---
|
|
259
|
+
[INFO] --- 3/5 Verificación de Estado Local (.gemstack/state.json) ---
|
|
260
|
+
[INFO] --- 4/5 Consistencia Arquitectónica y Hashes de Fase (Upgrade A) ---
|
|
261
|
+
[INFO] --- 5/5 Verificación de Seguridad y Test Runners ---
|
|
262
|
+
```
|
|
263
|
+
|
|
264
|
+
### Lógica del Paso 4 en `verify.js`
|
|
265
|
+
1. Leer `.gemstack/state.json`. Obtener `active_spec`.
|
|
266
|
+
2. Si `active_spec` es nulo o no existe: reportar `[OK] Sin spec activa (verificación de contratos omitida)` y continuar.
|
|
267
|
+
3. Si `specs/<active_spec>/spec.md` existe:
|
|
268
|
+
- Extraer bloques `gemstack-contracts`. Si no tiene bloques, marcar `[INFO] Modo LEGACY (sin contratos estructurados)` y continuar.
|
|
269
|
+
- Si tiene `phase_hashes.spec` en `state.json` o sidecar:
|
|
270
|
+
- Calcular hash actual de `spec.md`.
|
|
271
|
+
- Si difiere del hash congelado: emitir error crítico `FROZEN_ARTIFACT_CHANGED`.
|
|
272
|
+
4. Si existe `plan.md`:
|
|
273
|
+
- Validar herencia de contratos de `spec.md` contra `plan.md`.
|
|
274
|
+
- Reportar hallazgos de contradicciones (`ENUM_SET`, `IDENTITY_TUPLE`, `PROVENANCE_RULE`, `BOUNDARY`, `BOOLEAN_INVARIANT`, `ROADMAP_LIMIT`).
|
|
275
|
+
- Aplicar supresión anti-loop sobre hallazgos con `ACCEPTED_EXCEPTION` válidos.
|
|
276
|
+
5. Si hay bloqueadores abiertos (`open_blockers > 0`): incrementar `totalErrors`.
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## 5. Mapeo de Trazabilidad de Pruebas P1 (Exact Mechanical Total = 25)
|
|
281
|
+
|
|
282
|
+
| ID | Categoría | Módulo Responsable | Aserción Técnica |
|
|
283
|
+
|---|---|---|---|
|
|
284
|
+
| `TEST-CONSISTENCY-A01` | Parsing | `src/lib/contracts.js` | Extracción correcta de array JSON dentro de ````gemstack-contracts. |
|
|
285
|
+
| `TEST-CONSISTENCY-A02` | Parsing | `src/lib/contracts.js` | Emisión de `CONTRACT_PARSE_ERROR` ante JSON malformado o múltiples bloques. |
|
|
286
|
+
| `TEST-CONSISTENCY-A03` | Parsing | `src/lib/contracts.js` | Emisión de `CONTRACT_DUPLICATE_ID` si dos contratos repiten `id`. |
|
|
287
|
+
| `TEST-CONSISTENCY-B01` | Cross-Phase | `src/lib/contracts.js` | `ENUM_SET`: detecta miembro extra no aprobado (ej. `PURGED`) ➔ `BLOCKED`. |
|
|
288
|
+
| `TEST-CONSISTENCY-B02` | Cross-Phase | `src/lib/contracts.js` | `ENUM_SET`: valida ordenación normalizada (`[A,B,C]` == `[C,B,A]`) ➔ `PASS`. |
|
|
289
|
+
| `TEST-CONSISTENCY-B03` | Cross-Phase | `src/lib/contracts.js` | `IDENTITY_TUPLE`: detecta dimensión faltante (omite `kind`) ➔ `BLOCKED`. |
|
|
290
|
+
| `TEST-CONSISTENCY-B04` | Cross-Phase | `src/lib/contracts.js` | `IDENTITY_TUPLE`: valida permutación de dimensiones idénticas ➔ `PASS`. |
|
|
291
|
+
| `TEST-CONSISTENCY-B05` | Cross-Phase | `src/lib/contracts.js` | `PROVENANCE_RULE`: bloquea si entidad pierde campo de procedencia ➔ `BLOCKED`. |
|
|
292
|
+
| `TEST-CONSISTENCY-B06` | Cross-Phase | `src/lib/contracts.js` | `BOOLEAN_INVARIANT` & `ROADMAP_LIMIT`: contradicciones directas ➔ `BLOCKED`. |
|
|
293
|
+
| `TEST-CONSISTENCY-B07` | Cross-Phase | `src/lib/contracts.js` | `BOUNDARY`: valores estrictos `FORBIDDEN` y `REQUIRED`; detecta contradicción explícita (`FORBIDDEN` vs `REQUIRED` ➔ `BLOCKED`) y valida equivalencia como `PASS`. |
|
|
294
|
+
| `TEST-CONSISTENCY-B08` | Cross-Phase | `src/lib/contracts.js` | Herencia: PLAN hereda SPEC y agrega compatibles sin duplicación ➔ `PASS`. |
|
|
295
|
+
| `TEST-CONSISTENCY-C01` | Hashes | `src/lib/hasher.js` | Genera SHA-256 de 64 caracteres de `spec.md`. |
|
|
296
|
+
| `TEST-CONSISTENCY-C02` | Hashes | `src/lib/hasher.js` | Detecta mutación no autorizada de artefacto congelado ➔ `FROZEN_ARTIFACT_CHANGED`. |
|
|
297
|
+
| `TEST-CONSISTENCY-C03` | Hashes | `src/commands/verify.js`| Comprueba que `verify` valida contra hashes guardados sin mutarlos. |
|
|
298
|
+
| `TEST-CONSISTENCY-C04` | Hashes | `src/lib/hasher.js` | Normalización CRLF a LF produce idéntico hash en Windows y POSIX. |
|
|
299
|
+
| `TEST-CONSISTENCY-D01` | Fingerprints | `src/lib/findings.js` | Genera fingerprint determinista canónico de 64 caracteres hex SHA-256 con location relativa (/) inmune a colisiones; valida formato de display separado. |
|
|
300
|
+
| `TEST-CONSISTENCY-D02` | Anti-Loop | `src/lib/findings.js` | Si el defecto persiste, no se suprime como RESOLVED; si se arregla, queda limpio. |
|
|
301
|
+
| `TEST-CONSISTENCY-E01` | Excepciones | `src/lib/findings.js` | `ACCEPTED_EXCEPTION` suprime el bloqueo en `verify` si contextHash coincide. |
|
|
302
|
+
| `TEST-CONSISTENCY-E02` | Excepciones | `src/lib/findings.js` | Mutación de artefacto relevante reactiva la excepción para re-evaluación. |
|
|
303
|
+
| `TEST-CONSISTENCY-F01` | Legacy | `src/commands/verify.js`| Feature sin bloques de contratos opera en modo `LEGACY` sin errores. |
|
|
304
|
+
| `TEST-CONSISTENCY-F02` | Legacy | `src/lib/state.js` | `state.json` versión 0.1 sin campos de Upgrade A se lee sin fallas. |
|
|
305
|
+
| `TEST-CONSISTENCY-G01` | Windows | `src/lib/hasher.js` | Resuelve rutas con separadores `\` y normaliza internamente a `/`. |
|
|
306
|
+
| `TEST-CONSISTENCY-G02` | Windows | `src/lib/state.js` | Escritura atómica previene corrupción de archivos en Windows. |
|
|
307
|
+
| `TEST-CONSISTENCY-H01` | Regresión | Integration | `npm run gemstack:verify` mantiene todas las validaciones de salud intactas. |
|
|
308
|
+
| `TEST-CONSISTENCY-H02` | Regresión | Integration | Las suites previas (`tests/init.test.js`, `tests/verify.test.js`) pasan al 100%. |
|
|
309
|
+
|
|
310
|
+
**Total Mecánico de Tests P1**: **25**
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
## 6. Procedimiento de Dogfooding y Bootstrap
|
|
315
|
+
|
|
316
|
+
Dado que la especificación `specs/006-architecture-consistency-engine/spec.md` ya declaró formalmente sus 5 contratos congelados (`zero-dependency-core`, `upgrade-a-contract-types`, etc.), el procedimiento de validación interna se ejecutará en 3 etapas:
|
|
317
|
+
1. **Fase Bootstrap**: Los nuevos módulos `contracts.js`, `hasher.js`, `findings.js` se implementan y prueban con `node --test`.
|
|
318
|
+
2. **Auto-Freeze de Feature 006**: Se congela el hash formal de `specs/006-architecture-consistency-engine/spec.md` en `.gemstack/state.json`.
|
|
319
|
+
3. **Auto-Verificación**: Se ejecuta `node src/cli.js verify` contra el propio repositorio de Gemstack para certificar que el motor parsea y valida sus propios contratos con `PASS`.
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Especificación de Funcionalidad: Architecture Consistency Engine & Phase Freezing (Upgrade A)
|
|
2
|
+
|
|
3
|
+
**Feature Branch**: `006-architecture-consistency-engine`
|
|
4
|
+
**Feature Slug**: `specs/006-architecture-consistency-engine/`
|
|
5
|
+
**Lifecycle Status**: `SPEC_COMPLETE`
|
|
6
|
+
**Stop Reason**: `SPEC_COMPLETE_AWAITING_REVIEW`
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## 1. Contexto y Objetivos (Upgrade A)
|
|
11
|
+
|
|
12
|
+
El framework Gemstack opera como un motor de disciplina para desarrollo con IA basado en Spec-Driven Development (SDD):
|
|
13
|
+
`SPEC → PLAN → TASKS → IMPLEMENT → QA / REVIEW → SHIP → HANDOFF`.
|
|
14
|
+
|
|
15
|
+
El objetivo de **Upgrade A** es incorporar una capa determinista de **detección de desviaciones arquitectónicas (Architecture Drift)** y **congelamiento de fases (Phase Freezing)** sin alterar el flujo existente, sin rediseñar el core y sin agregar dependencias externas (preservando el principio Zero-Dependency Node.js).
|
|
16
|
+
|
|
17
|
+
### Dogfooding & Bootstrap Contracts
|
|
18
|
+
Esta especificación define formalmente sus propios contratos congelados (`gemstack-contracts`), los cuales operan en modo auto-hospedado (*bootstrap mode*) y serán validados por el propio motor una vez implementado:
|
|
19
|
+
|
|
20
|
+
```gemstack-contracts
|
|
21
|
+
[
|
|
22
|
+
{
|
|
23
|
+
"id": "zero-dependency-core",
|
|
24
|
+
"type": "BOOLEAN_INVARIANT",
|
|
25
|
+
"value": true,
|
|
26
|
+
"description": "El runtime de Gemstack debe mantener cero dependencias externas de producción en Node.js."
|
|
27
|
+
},
|
|
28
|
+
{
|
|
29
|
+
"id": "upgrade-a-contract-types",
|
|
30
|
+
"type": "ENUM_SET",
|
|
31
|
+
"values": [
|
|
32
|
+
"ENUM_SET",
|
|
33
|
+
"IDENTITY_TUPLE",
|
|
34
|
+
"PROVENANCE_RULE",
|
|
35
|
+
"BOOLEAN_INVARIANT",
|
|
36
|
+
"BOUNDARY",
|
|
37
|
+
"ROADMAP_LIMIT"
|
|
38
|
+
],
|
|
39
|
+
"description": "Tipos de contrato deterministas soportados canónicamente en Upgrade A."
|
|
40
|
+
},
|
|
41
|
+
{
|
|
42
|
+
"id": "verify-does-not-mutate-hashes",
|
|
43
|
+
"type": "BOOLEAN_INVARIANT",
|
|
44
|
+
"value": true,
|
|
45
|
+
"description": "El comando gemstack verify valida contra hashes congelados pero nunca actualiza ni sobreescribe los hashes de fase."
|
|
46
|
+
},
|
|
47
|
+
{
|
|
48
|
+
"id": "contract-amendment-requires-human-approval",
|
|
49
|
+
"type": "BOOLEAN_INVARIANT",
|
|
50
|
+
"value": true,
|
|
51
|
+
"description": "Cualquier enmienda a un contrato congelado o artefacto inmutable requiere aprobación humana explícita."
|
|
52
|
+
},
|
|
53
|
+
{
|
|
54
|
+
"id": "legacy-mode-supported",
|
|
55
|
+
"type": "BOOLEAN_INVARIANT",
|
|
56
|
+
"value": true,
|
|
57
|
+
"description": "Features sin bloques de contratos operan en modo legacy sin romper compatibilidad ni generar falsos bloqueos."
|
|
58
|
+
}
|
|
59
|
+
]
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
---
|
|
63
|
+
|
|
64
|
+
## 2. User Scenarios & Testing (MVP)
|
|
65
|
+
|
|
66
|
+
### User Story 1 — Detección Determinista de Contradicciones Arquitectónicas (P1)
|
|
67
|
+
Como desarrollador o revisor técnico, quiero que Gemstack bloquee el avance de fase si un PLAN o TASKS introduce valores en enums no aprobados, altera tuplas de identidad o descarta campos de procedencia definidos en SPEC.
|
|
68
|
+
**Test Independiente**: `TEST-CONSISTENCY-B01`, `TEST-CONSISTENCY-B02`, `TEST-CONSISTENCY-B03`.
|
|
69
|
+
|
|
70
|
+
### User Story 2 — Congelamiento y Detección de Mutación de Artefactos (P1)
|
|
71
|
+
Como arquitecto de software, quiero que cada artefacto aprobado (`spec.md`, `plan.md`, `tasks.md`) quede sellado con un hash criptográfico SHA-256 en `.gemstack/state.json`, de modo que cualquier mutación posterior sin enmienda formal detenga el avance con `FROZEN_ARTIFACT_CHANGED`.
|
|
72
|
+
**Test Independiente**: `TEST-CONSISTENCY-C01`, `TEST-CONSISTENCY-C02`, `TEST-CONSISTENCY-C03`.
|
|
73
|
+
|
|
74
|
+
### User Story 3 — Anti-Loop y Huella Digital de Hallazgos (P1)
|
|
75
|
+
Como agente de IA y usuario humano, quiero que los hallazgos tengan una huella determinista (*fingerprint*) y que las observaciones resueltas o aceptadas como excepción no se reabran indefinidamente si el artefacto no ha mutado.
|
|
76
|
+
**Test Independiente**: `TEST-CONSISTENCY-D01`, `TEST-CONSISTENCY-E01`.
|
|
77
|
+
|
|
78
|
+
### User Story 4 — Compatibilidad Transparente con Proyectos Legados (P1)
|
|
79
|
+
Como usuario con especificaciones existentes (001 a 005), quiero que `gemstack verify` y el flujo SDD sigan funcionando con total normalidad sin requerir migración obligatoria.
|
|
80
|
+
**Test Independiente**: `TEST-CONSISTENCY-F01`.
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## 3. Requerimientos Funcionales
|
|
85
|
+
|
|
86
|
+
### RF-001: Sintaxis Canónica de Declaración (`gemstack-contracts`)
|
|
87
|
+
- Los contratos congelados se declaran exclusivamente dentro de bloques delimitados ````gemstack-contracts ... ```` en formato JSON en el artefacto de fase (`spec.md` o `plan.md`).
|
|
88
|
+
- La prosa libre fuera del bloque NO se convierte implícitamente en contrato determinista.
|
|
89
|
+
|
|
90
|
+
### RF-002: Tipos de Contrato Soportados en Upgrade A
|
|
91
|
+
1. **`ENUM_SET`**: Conjunto de valores discretos. La comparación es insensible al orden (`normalizeSort`). Los duplicados son inválidos. Bloquea si aparecen miembros nuevos o faltan miembros aprobados.
|
|
92
|
+
2. **`IDENTITY_TUPLE`**: Conjunto semántico de dimensiones de identidad (*semantic set of identity dimensions*). La comparación es insensible al orden (*order-insensitive*), sensible a duplicados (*duplicate-sensitive*) y sensible a miembros exactos (*exact-member-sensitive*). Por ejemplo, `[w, r, l, k]` vs `[k, l, r, w]` ➔ `PASS`; `[w, r, l, k]` vs `[w, r, l]` ➔ `BLOCKED`; `[w, r, l, k]` vs `[w, r, l, k, x]` ➔ `BLOCKED`. El orden original de declaración se preserva exclusivamente para renderizado, visualización de diffs y legibilidad humana, no como semántica arquitectónica de orden en Upgrade A.
|
|
93
|
+
3. **`PROVENANCE_RULE`**: Lista de campos obligatorios para trazabilidad/linaje entre entidades. Bloquea si una entidad posterior omite un campo de procedencia congelado.
|
|
94
|
+
4. **`BOOLEAN_INVARIANT`**: Invariante booleano estricto (`true`/`false`). Bloquea cualquier contradicción directa.
|
|
95
|
+
5. **`BOUNDARY`**: Límites de aislamiento o dependencias arquitectónicas explícitas (ej. `FORBIDDEN` vs `REQUIRED`). Bloquea deterministamente contradicciones explícitas (ej. SPEC declara `FORBIDDEN` y PLAN declara `REQUIRED` ➔ `FROZEN_CONTRACT_VIOLATION`), mientras que declaraciones equivalentes resultan en `PASS`.
|
|
96
|
+
6. **`ROADMAP_LIMIT`**: Límite numérico o escalar inmutable (ej. `FINAL_PLANNED_MVP = 18`).
|
|
97
|
+
|
|
98
|
+
### RF-003: Modelo de Herencia de Contratos y Extensión Aditiva
|
|
99
|
+
- `spec.md` es la raíz y declara los contratos base.
|
|
100
|
+
- `plan.md` hereda automáticamente todos los contratos de `spec.md` y puede añadir nuevos contratos aditivos y compatibles específicos de arquitectura técnica sin requerir duplicar los bloques de contratos heredados.
|
|
101
|
+
- `tasks.md` hereda el registro consolidado (`spec.md` + `plan.md`).
|
|
102
|
+
- El validador distingue extensiones **aditivas no conflictivas** (`PASS`) de **contradicciones o mutaciones no aprobadas** (`BLOCKED`).
|
|
103
|
+
|
|
104
|
+
### RF-004: Hashing Determinista y Normalización CRLF/LF
|
|
105
|
+
- El hash de fase (`specHash`, `planHash`, `tasksHash`) se calcula usando SHA-256 sobre el contenido del archivo con saltos de línea normalizados a LF (`\r\n` ➔ `\n`) y codificación UTF-8.
|
|
106
|
+
- Esto garantiza idéntico hash en Windows, macOS y Linux.
|
|
107
|
+
- `gemstack verify` NUNCA actualiza los hashes de fase; solo la acción formal de freeze/aprobación lo hace.
|
|
108
|
+
|
|
109
|
+
### RF-005: Enmienda Formal de Contratos (`ContractAmendment`)
|
|
110
|
+
- Si la arquitectura cambia legítimamente, se requiere aprobación humana explícita.
|
|
111
|
+
- Al aprobar una enmienda en `spec.md`, el hash de `spec.md` se actualiza y las fases subsiguientes (`plan.md`, `tasks.md`) se marcan como `REQUIRES_REVIEW`.
|
|
112
|
+
|
|
113
|
+
### RF-006: Huellas Digitales (*Fingerprints*), Granularidad y Anti-Loop
|
|
114
|
+
- **Regla de granularidad de hallazgos:** Para una comparación de contratos se genera un único hallazgo consolidado por `contractId + phase + violationType`, conteniendo el delta normalizado completo (ej. miembros faltantes y agregados consolidados en un único hallazgo).
|
|
115
|
+
- **Huella determinista (*fingerprint*):** Cada hallazgo genera un hash: `SHA256(violationType + contractId + phase + normalizedLocation)`. No incluye texto volátil ni timestamps.
|
|
116
|
+
- **Anti-Loop:** Si un hallazgo tiene estado `RESOLVED` o `ACCEPTED_EXCEPTION` y el hash del artefacto no ha cambiado, no se vuelve a generar el bloqueo.
|
|
117
|
+
|
|
118
|
+
### RF-007: Extensiones Aditivas a `.gemstack/state.json`
|
|
119
|
+
- Se preservan todos los campos existentes de `state.json`.
|
|
120
|
+
- Se añade opcionalmente la sección de hashes y consistencia:
|
|
121
|
+
```json
|
|
122
|
+
{
|
|
123
|
+
"phase_hashes": {
|
|
124
|
+
"spec": "<sha256-or-null>",
|
|
125
|
+
"plan": "<sha256-or-null>",
|
|
126
|
+
"tasks": "<sha256-or-null>"
|
|
127
|
+
},
|
|
128
|
+
"consistency": {
|
|
129
|
+
"status": "PASS | BLOCKED | LEGACY",
|
|
130
|
+
"open_blockers": 0
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
```
|
|
134
|
+
|
|
135
|
+
---
|
|
136
|
+
|
|
137
|
+
## 4. Criterios de Éxito y Matriz de Aceptación P1 (Exact Mechanical Count = 25)
|
|
138
|
+
|
|
139
|
+
| ID de Prueba | Categoría | Capa de Ejecución | Aserción de Aceptación |
|
|
140
|
+
|---|---|---|---|
|
|
141
|
+
| `TEST-CONSISTENCY-A01` | A — Parsing | Unit (Node) | Parsea correctamente bloques válidos `gemstack-contracts` en JSON. |
|
|
142
|
+
| `TEST-CONSISTENCY-A02` | A — Parsing | Unit (Node) | Emite `CONTRACT_PARSE_ERROR` si el bloque JSON es sintácticamente inválido. |
|
|
143
|
+
| `TEST-CONSISTENCY-A03` | A — Parsing | Unit (Node) | Bloquea con `CONTRACT_DUPLICATE_ID` si dos contratos comparten el mismo `id`. |
|
|
144
|
+
| `TEST-CONSISTENCY-B01` | B — Cross-Phase | Unit (Node) | `ENUM_SET`: detecta adición no aprobada (ej. `PURGED`) y emite `BLOCKED`. |
|
|
145
|
+
| `TEST-CONSISTENCY-B02` | B — Cross-Phase | Unit (Node) | `ENUM_SET`: valida ordenación normalizada (`[A,B,C]` == `[C,B,A]`) como `PASS`. |
|
|
146
|
+
| `TEST-CONSISTENCY-B03` | B — Cross-Phase | Unit (Node) | `IDENTITY_TUPLE`: detecta dimensión faltante (omisión de `kind`) y emite `BLOCKED`. |
|
|
147
|
+
| `TEST-CONSISTENCY-B04` | B — Cross-Phase | Unit (Node) | `IDENTITY_TUPLE`: valida tupla equivalente en orden permutado como `PASS`. |
|
|
148
|
+
| `TEST-CONSISTENCY-B05` | B — Cross-Phase | Unit (Node) | `PROVENANCE_RULE`: bloquea si entidad posterior omite campo de procedencia requerido. |
|
|
149
|
+
| `TEST-CONSISTENCY-B06` | B — Cross-Phase | Unit (Node) | `BOOLEAN_INVARIANT` & `ROADMAP_LIMIT`: bloquea contradicción directa (`true` vs `false`, `18` vs `20`). |
|
|
150
|
+
| `TEST-CONSISTENCY-B07` | B — Cross-Phase | Unit (Node) | `BOUNDARY`: valores estrictos `FORBIDDEN` y `REQUIRED`; detecta contradicción explícita (`FORBIDDEN` vs `REQUIRED` ➔ `BLOCKED`) y valida equivalencia como `PASS`. |
|
|
151
|
+
| `TEST-CONSISTENCY-B08` | B — Cross-Phase | Unit (Node) | Herencia y extensión aditiva: PLAN hereda contratos de SPEC y agrega compatibles sin duplicación; TASKS hereda SPEC + PLAN como `PASS`. |
|
|
152
|
+
| `TEST-CONSISTENCY-C01` | C — Freeze & Hashes | Unit (Node) | Almacena `specHash` SHA-256 al congelar la fase SPEC. |
|
|
153
|
+
| `TEST-CONSISTENCY-C02` | C — Freeze & Hashes | Unit (Node) | Detecta mutación no autorizada de `spec.md` con `FROZEN_ARTIFACT_CHANGED`. |
|
|
154
|
+
| `TEST-CONSISTENCY-C03` | C — Freeze & Hashes | Unit (Node) | `verify` valida contra hashes almacenados y NO los reescribe silenciosamente. |
|
|
155
|
+
| `TEST-CONSISTENCY-C04` | C — Freeze & Hashes | Unit (Node) | Normalización CRLF/LF produce idéntico hash en Windows y POSIX. |
|
|
156
|
+
| `TEST-CONSISTENCY-D01` | D — Fingerprints | Unit (Node) | Genera fingerprint determinista canónico de 64 caracteres hex SHA-256 con location relativa (/) inmune a colisiones; valida formato de display separado. |
|
|
157
|
+
| `TEST-CONSISTENCY-D02` | D — Anti-Loop | Unit (Node) | Hallazgo en estado `RESOLVED` con hash de artefacto sin cambios no se reabre. |
|
|
158
|
+
| `TEST-CONSISTENCY-E01` | E — Excepciones | Unit (Node) | `ACCEPTED_EXCEPTION` aprobado por humano suprime el bloqueo en `verify`. |
|
|
159
|
+
| `TEST-CONSISTENCY-E02` | E — Excepciones | Unit (Node) | Modificación del artefacto relevante reabre la excepción para nueva revisión. |
|
|
160
|
+
| `TEST-CONSISTENCY-F01` | F — Legacy | Unit (Node) | Feature sin bloque `gemstack-contracts` opera en modo `LEGACY` sin error. |
|
|
161
|
+
| `TEST-CONSISTENCY-F02` | F — Legacy | Unit (Node) | Proyecto con `state.json` versión previa inicializa campos faltantes de forma segura. |
|
|
162
|
+
| `TEST-CONSISTENCY-G01` | G — Windows | Unit (Node) | Manejo de rutas con barras invertidas (`\`) normalizadas de forma segura en Windows. |
|
|
163
|
+
| `TEST-CONSISTENCY-G02` | G — Windows | Unit (Node) | Operaciones de lectura y hashing atómicas sin colisión de descriptores de archivo. |
|
|
164
|
+
| `TEST-CONSISTENCY-H01` | H — Regression | Integration | `npm run gemstack:verify` mantiene todas las validaciones estructurales existentes intactas. |
|
|
165
|
+
| `TEST-CONSISTENCY-H02` | H — Regression | Integration | Las suites previas (`tests/init.test.js`, `tests/verify.test.js`) continúan pasando al 100%. |
|
|
166
|
+
|
|
167
|
+
---
|
|
168
|
+
|
|
169
|
+
## 5. Non-Goals Explícitos (Fuera de Alcance en Upgrade A)
|
|
170
|
+
|
|
171
|
+
- **NO** cálculo mecánico de matrices de prueba P1 ni conteo aritmético de tests (Upgrade B).
|
|
172
|
+
- **NO** trazabilidad tarea ↔ test (Upgrade B).
|
|
173
|
+
- **NO** manifiesto `closure.json` ni puertas de comandos canónicos (Upgrade B).
|
|
174
|
+
- **NO** `BillableActionGate` ni libro de costos de proveedores (Upgrade C).
|
|
175
|
+
- **NO** `ProviderCapabilityGate` ni adaptadores fail-closed (Upgrade C).
|
|
176
|
+
- **NO** generador de cápsulas de contexto (`context-capsule.json`) (Upgrade D).
|
|
177
|
+
- **NO** ejecutores de bases de datos o runners de migraciones.
|
|
178
|
+
- **NO** frameworks de AST o paquetes npm externos (Zero-Dependency estricto).
|
|
179
|
+
- **NO** herramientas de gestión de proyectos genéricos (Kanban, time tracking).
|