pumuki 6.3.71 → 6.3.73
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.md +269 -0
- package/CHANGELOG.md +686 -0
- package/README.md +32 -0
- package/VERSION +1 -1
- package/docs/README.md +7 -2
- package/docs/operations/RELEASE_NOTES.md +18 -0
- package/docs/product/USAGE.md +10 -0
- package/docs/tracking/plan-curso-pumuki-stack-my-architecture.md +62 -0
- package/integrations/gate/governanceActionCatalog.ts +230 -0
- package/integrations/git/GitService.ts +25 -0
- package/integrations/git/runPlatformGate.ts +9 -1
- package/integrations/git/runPlatformGateFacts.ts +1 -0
- package/integrations/git/runPlatformGateOutput.ts +36 -27
- package/integrations/lifecycle/adapter.templates.json +3 -0
- package/integrations/lifecycle/audit.ts +101 -0
- package/integrations/lifecycle/cli.ts +80 -8
- package/integrations/lifecycle/doctor.ts +64 -1
- package/integrations/lifecycle/governanceNextAction.ts +164 -0
- package/integrations/lifecycle/governanceObservationSnapshot.ts +288 -0
- package/integrations/lifecycle/index.ts +2 -0
- package/integrations/lifecycle/status.ts +29 -2
- package/integrations/mcp/autoExecuteAiStart.ts +86 -84
- package/integrations/mcp/preFlightCheck.ts +40 -3
- package/integrations/platform/detectPlatforms.ts +37 -0
- package/integrations/sdd/openSpecCli.ts +12 -3
- package/package.json +11 -1
- package/scripts/build-ruralgo-s1-evidence-pack.ts +85 -0
- package/scripts/consumer-postinstall-resolve-args.cjs +38 -0
- package/scripts/consumer-postinstall.cjs +10 -1
- package/scripts/framework-menu-consumer-preflight-render.ts +6 -0
- package/scripts/framework-menu-consumer-preflight-run.ts +19 -0
- package/scripts/framework-menu-consumer-preflight-types.ts +8 -0
- package/scripts/pumuki-full-surface-smoke-lib.ts +37 -0
- package/scripts/pumuki-full-surface-smoke.ts +261 -0
- package/scripts/pumuki-smoke-installed-wrapper.cjs +31 -0
- package/scripts/ruralgo-s1-evidence-pack-lib.ts +200 -0
package/README.md
CHANGED
|
@@ -12,6 +12,12 @@ Pumuki gives engineering teams one deterministic execution model across local de
|
|
|
12
12
|
|
|
13
13
|
`Facts -> Rules -> Gate -> .ai_evidence.json (v2.1)`
|
|
14
14
|
|
|
15
|
+
## Qué NO es Pumuki
|
|
16
|
+
|
|
17
|
+
- **No** es el producto de negocio de tu repositorio (la app, el marketplace, el servicio que entregas a usuarios): es **gobernanza y contrato de entrega** sobre el código.
|
|
18
|
+
- **No** sustituye tests de dominio, contratos de API ni E2E: el gate ayuda a **cumplir políticas y evidencias**; la calidad funcional la define tu equipo con pruebas y criterios de aceptación.
|
|
19
|
+
- **No** garantiza por sí solo “un producto excelente”: sin reglas de equipo, revisión humana y criterios claros, solo obtienes **cumplimiento de lo que configuraste**.
|
|
20
|
+
|
|
15
21
|
## Who This README Is For
|
|
16
22
|
|
|
17
23
|
| Profile | Use this path first |
|
|
@@ -20,6 +26,32 @@ Pumuki gives engineering teams one deterministic execution model across local de
|
|
|
20
26
|
| Framework maintainers (this repo) | [Framework Maintainer Flow](#framework-maintainer-flow-this-repo) |
|
|
21
27
|
| Platform/architecture owners | [Enterprise Operations Baseline](#enterprise-operations-baseline) |
|
|
22
28
|
|
|
29
|
+
## Rutas de adopción
|
|
30
|
+
|
|
31
|
+
Elige un perfil y profundiza en los enlaces; **no** repite aquí reglas largas (skills, GitFlow, políticas) — están en `AGENTS.md` y en la documentación enlazada.
|
|
32
|
+
|
|
33
|
+
| Perfil | Qué instalar / arrancar | Stages habituales | Opcional típico |
|
|
34
|
+
|--------|-------------------------|-------------------|-----------------|
|
|
35
|
+
| **Mínimo** | `npm install --save-exact pumuki` (en repos Git el `postinstall` puede ejecutar `pumuki install` para hooks y lifecycle). | Hooks Git: **PRE_COMMIT**, **PRE_PUSH**; cadena **PRE_WRITE** cuando el hook lo encadena (según versión y config). | Evidencia [`.ai_evidence.json` v2.1](docs/mcp/ai-evidence-v2.1-contract.md); reglas core embebidas. |
|
|
36
|
+
| **Estándar** | Lo anterior + flujo **OpenSpec/SDD** bajo `openspec/` según tu política. | Lo anterior + validación SDD por stage (`pumuki sdd validate --stage=…`). | Sesiones SDD, cambios versionados bajo `openspec/changes/`. |
|
|
37
|
+
| **Enterprise completo** | `pumuki bootstrap --enterprise` (o equivalente documentado) + `skills.lock.json` / reglas custom / [policy-as-code](docs/product/CONFIGURATION.md) donde aplique. | Lo anterior + **CI** (`pumuki-ci`) y comprobaciones de alineación (`doctor`, parity). | [Skills / MCP](docs/mcp/mcp-servers-overview.md), `pumuki doctor --parity`, notificaciones, [hard mode](docs/product/CONFIGURATION.md). |
|
|
38
|
+
|
|
39
|
+
Referencias canónicas (profundizar aquí): [Instalación](docs/product/INSTALLATION.md), [Uso y gates](docs/product/USAGE.md), [Configuración](docs/product/CONFIGURATION.md), [AGENTS.md](AGENTS.md) (contrato agentes/skills/GitFlow en repos que lo adopten), [índice de documentación](docs/README.md).
|
|
40
|
+
|
|
41
|
+
Formación opcional (curso **Pumuki** dentro del hub *Stack My Architecture*): [https://stack-my-architecture-hub.vercel.app/pumuki/](https://stack-my-architecture-hub.vercel.app/pumuki/) · seguimiento de la iniciativa en [docs/tracking/plan-curso-pumuki-stack-my-architecture.md](docs/tracking/plan-curso-pumuki-stack-my-architecture.md).
|
|
42
|
+
|
|
43
|
+
## Comandos esenciales
|
|
44
|
+
|
|
45
|
+
Cinco entradas que cubren el 80 % del día a día en un consumidor; el detalle está en los enlaces.
|
|
46
|
+
|
|
47
|
+
1. **`npx pumuki doctor --json`** — Versión efectiva, drift, lifecycle, parity y avisos (p. ej. `pathExecutionHazard`). Detalle: [API_REFERENCE](docs/product/API_REFERENCE.md), [USAGE](docs/product/USAGE.md).
|
|
48
|
+
2. **`npx pumuki status --json`** — Estado resumido del menú/lifecycle y alineación de versión. Detalle: [USAGE](docs/product/USAGE.md).
|
|
49
|
+
3. **`npx pumuki install`** (o deja que el `postinstall` lo ejecute en Git) — Hooks y lifecycle en el repo. Detalle: [INSTALLATION](docs/product/INSTALLATION.md).
|
|
50
|
+
4. **Gates locales** — `npx pumuki-pre-write`, `npx pumuki-pre-commit` (y `pumuki-pre-push` cuando toque push). Detalle: [USAGE](docs/product/USAGE.md), [Troubleshooting (USAGE)](docs/product/USAGE.md#troubleshooting).
|
|
51
|
+
5. **SDD por stage (enterprise)** — `npx pumuki sdd validate --stage=PRE_COMMIT` (u otro stage). Detalle: [USAGE](docs/product/USAGE.md), [INSTALLATION](docs/product/INSTALLATION.md#troubleshooting) si falla el bootstrap.
|
|
52
|
+
|
|
53
|
+
Si algo bloquea o el mensaje no es claro: [Troubleshooting](#troubleshooting) (más abajo en este README), [USAGE § Troubleshooting](docs/product/USAGE.md#troubleshooting) y [GitHub Issues](https://github.com/SwiftEnProfundidad/ast-intelligence-hooks/issues).
|
|
54
|
+
|
|
23
55
|
## 5-Minute Quick Start (Consumer)
|
|
24
56
|
|
|
25
57
|
Prerequisites:
|
package/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
v6.3.
|
|
1
|
+
v6.3.73
|
package/docs/README.md
CHANGED
|
@@ -4,6 +4,8 @@ Mapa corto y humano de la documentación oficial de Pumuki.
|
|
|
4
4
|
|
|
5
5
|
## Si buscas algo concreto
|
|
6
6
|
|
|
7
|
+
- Quiero límites del producto, perfil de adopción y comandos mínimos (sin leer todo el README largo):
|
|
8
|
+
- `README.md` (secciones **Qué NO es Pumuki**, **Rutas de adopción**, **Comandos esenciales**)
|
|
7
9
|
- Quiero instalar y arrancar Pumuki en un repo consumidor:
|
|
8
10
|
- `README.md`
|
|
9
11
|
- `docs/product/INSTALLATION.md`
|
|
@@ -35,6 +37,8 @@ Mapa corto y humano de la documentación oficial de Pumuki.
|
|
|
35
37
|
|
|
36
38
|
- Quiero saber en qué estamos ahora:
|
|
37
39
|
- `docs/tracking/plan-activo-de-trabajo.md`
|
|
40
|
+
- Quiero el seguimiento del curso Stack My Architecture (Pumuki), iniciativa formativa aparte del espejo operativo:
|
|
41
|
+
- `docs/tracking/plan-curso-pumuki-stack-my-architecture.md`
|
|
38
42
|
|
|
39
43
|
## Estructura oficial
|
|
40
44
|
|
|
@@ -62,8 +66,9 @@ Mapa corto y humano de la documentación oficial de Pumuki.
|
|
|
62
66
|
|
|
63
67
|
- `docs/tracking/`
|
|
64
68
|
- Seguimiento permitido y solo el imprescindible.
|
|
65
|
-
-
|
|
66
|
-
-
|
|
69
|
+
- Espejo operativo de producto y consumidores: `docs/tracking/plan-activo-de-trabajo.md` (unica fuente de verdad para ese ambito).
|
|
70
|
+
- Iniciativa formativa (curso Pumuki en Stack My Architecture): `docs/tracking/plan-curso-pumuki-stack-my-architecture.md` (no sustituye al plan activo).
|
|
71
|
+
- Regla hard: solo puede existir una tarea `🚧` en cada documento de seguimiento que lo use.
|
|
67
72
|
|
|
68
73
|
## Fuera de `docs/`
|
|
69
74
|
|
|
@@ -6,6 +6,24 @@ This file keeps only the operational highlights and rollout notes that matter wh
|
|
|
6
6
|
|
|
7
7
|
## 2026-04 (CLI stability and macOS notifications)
|
|
8
8
|
|
|
9
|
+
### 2026-04-14 (v6.3.73)
|
|
10
|
+
|
|
11
|
+
- **S1 governance console**: `status`, `doctor`, menú consumer, hooks y MCP comparten ya la misma semántica de governance (`governance truth`, `reason_code`, `instruction`, `next_action`).
|
|
12
|
+
- **RuralGo evidence pack**: nuevo `npm run validation:ruralgo-s1-evidence-pack -- --consumer-root <repo> --package-version <semver>` para preparar la validación real de `PUMUKI-INC-071/073/076`.
|
|
13
|
+
- **Sin regresión de 6.3.72**: esta release preserva `lifecycle audit`, `consumer postinstall resolve args`, `detectPlatforms` y `full surface smoke`, en vez de volver a una base `6.3.71`.
|
|
14
|
+
- **Rollout**: publicar `pumuki@6.3.73`, repinear primero RuralGo y ejecutar el evidence pack con la semver publicada antes de mover ningún `INC` a `FIXED`.
|
|
15
|
+
|
|
16
|
+
### 2026-04-11 (v6.3.72)
|
|
17
|
+
|
|
18
|
+
- **Tarball npm**: `package.json` → `files` incluye `AGENTS.md`, `CHANGELOG.md` y `docs/tracking/plan-curso-pumuki-stack-my-architecture.md` para lectura canónica vía npm / jsDelivr sin depender solo del repo Git.
|
|
19
|
+
- **`gate.blocked` (macOS)**: banner de Notification Center **y** modal por defecto (evita cero notificaciones si el modal no llega a mostrarse desde un hook); dedupe opcional: `PUMUKI_MACOS_GATE_BLOCKED_BANNER_DEDUPE=1`.
|
|
20
|
+
- **Modal Swift**: `NSAlert.runModal()` en lugar de panel flotante para que los botones del diálogo respondan de forma fiable.
|
|
21
|
+
- **Postinstall consumer**: por defecto `pumuki install --with-mcp --agent=repo` y fusión conservadora en `.pumuki/adapter.json` (`json-merge`); opt-out `PUMUKI_POSTINSTALL_SKIP_MCP=1`.
|
|
22
|
+
- **Validación local**: `smoke:pumuki-surface` / `smoke:pumuki-surface-installed` y `validation:local-merge-bar` (sin depender de minutos de Actions). Detalle en `docs/validation/README.md`.
|
|
23
|
+
- **Tests en macOS:** `integrations/lifecycle/__tests__/cli.test.ts` evita notificaciones reales del sistema (`PUMUKI_DISABLE_SYSTEM_NOTIFICATIONS` en hooks) para que `npm test` / la barra local no queden colgados en PRE_WRITE strict.
|
|
24
|
+
- **Menú / matriz consumer**: opciones motor `11–14`, matriz baseline alineada, vista classic opcional, etc. (ver `CHANGELOG.md`).
|
|
25
|
+
- **Rollout**: `pumuki@6.3.72`; `npm publish` cuando el tarball incluya lo anterior; luego `pumuki doctor --json` + repin en consumidores (p. ej. RuralGO).
|
|
26
|
+
|
|
9
27
|
### 2026-04-06 (v6.3.71)
|
|
10
28
|
|
|
11
29
|
- **Evidencia v2.1**: bloque `operational_hints` (`requires_second_pass`, resumen operativo, desglose por severidad de reglas). Alineado con PRE_COMMIT solo-docs + evidencia trackeada (INC-069) cuando no se re-stagea el JSON automáticamente.
|
package/docs/product/USAGE.md
CHANGED
|
@@ -14,6 +14,11 @@ Production operations baseline (SLA/SLO, incident response and alerting):
|
|
|
14
14
|
Visual walkthrough for menu Option 1 captures:
|
|
15
15
|
- `docs/operations/framework-menu-consumer-walkthrough.md`
|
|
16
16
|
|
|
17
|
+
Stack My Architecture (optional training hub; includes the dedicated Pumuki course):
|
|
18
|
+
|
|
19
|
+
- Public static site: `https://stack-my-architecture-hub.vercel.app/pumuki/`
|
|
20
|
+
- Initiative tracking in this repo: `docs/tracking/plan-curso-pumuki-stack-my-architecture.md`
|
|
21
|
+
|
|
17
22
|
## Prerequisites
|
|
18
23
|
|
|
19
24
|
- Node.js `>=18`
|
|
@@ -72,6 +77,8 @@ Platform activation:
|
|
|
72
77
|
|
|
73
78
|
Pumuki enforces OpenSpec policy/session before allowing normal gate execution.
|
|
74
79
|
|
|
80
|
+
OpenSpec CLI resolution is **repo-local only**: Pumuki runs `openspec` from **`node_modules/.bin`** in the repository under check. A binary named `openspec` elsewhere on your **`PATH`** (global install, another tool) is **not** used. Add **`@fission-ai/openspec`** to the consumer project (for example via `pumuki install` / `bootstrap`) so laptops and CI behave the same; otherwise you may see **`OPENSPEC_MISSING`** even when `openspec --version` succeeds in an interactive shell.
|
|
81
|
+
|
|
75
82
|
Minimal daily flow:
|
|
76
83
|
|
|
77
84
|
```bash
|
|
@@ -565,6 +572,7 @@ npx --yes tsx@4.21.0 scripts/reconcile-consumer-backlog-issues.ts \
|
|
|
565
572
|
|
|
566
573
|
OpenSpec integration behavior:
|
|
567
574
|
- `pumuki bootstrap --enterprise --agent=<name>` orquesta `install + adapter wiring + doctor --deep` en un solo paso.
|
|
575
|
+
- SDD/OpenSpec enforcement invokes the CLI only from **`{repo}/node_modules/.bin/openspec`** (no fallback to a generic `openspec` on `PATH`).
|
|
568
576
|
- `pumuki install` auto-bootstraps OpenSpec (`@fission-ai/openspec`) when missing/incompatible and scaffolds `openspec/` project baseline when absent.
|
|
569
577
|
- `pumuki install --with-mcp` adds adapter/MCP wiring bootstrap and prints MCP health summary on completion.
|
|
570
578
|
- `pumuki update --latest` migrates legacy `openspec` package to `@fission-ai/openspec` before hook reinstall.
|
|
@@ -806,6 +814,8 @@ npx --yes pumuki sdd status
|
|
|
806
814
|
npx --yes pumuki sdd validate --stage=PRE_COMMIT
|
|
807
815
|
```
|
|
808
816
|
|
|
817
|
+
If the gate reports **`OPENSPEC_MISSING`** but `openspec --version` works in the terminal, you are likely using a **global** OpenSpec install. Pumuki does not use that path; install the package in the repo (`npm install`, `pumuki install`, or `pumuki bootstrap`) so `node_modules/.bin/openspec` exists.
|
|
818
|
+
|
|
809
819
|
Open or refresh session if needed:
|
|
810
820
|
|
|
811
821
|
```bash
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# Seguimiento — Curso Pumuki (Stack My Architecture)
|
|
2
|
+
|
|
3
|
+
Iniciativa formativa: quinto curso del ecosistema Stack My Architecture. **No** sustituye el espejo operativo de producto en [`plan-activo-de-trabajo.md`](./plan-activo-de-trabajo.md).
|
|
4
|
+
|
|
5
|
+
## Leyenda
|
|
6
|
+
|
|
7
|
+
- ✅ Cerrado
|
|
8
|
+
- 🚧 En construccion (maximo 1)
|
|
9
|
+
- ⏳ Pendiente
|
|
10
|
+
- ⛔ Bloqueado
|
|
11
|
+
|
|
12
|
+
## Regla de uso
|
|
13
|
+
|
|
14
|
+
- Solo puede existir **una** tarea `🚧` a la vez en este documento.
|
|
15
|
+
- Actualizar estados al cerrar fases o al desbloquear dependencias.
|
|
16
|
+
- Repos objetivo: `stack-my-architecture-pumuki` (curso), `stack-my-architecture-hub` (publicación), enlaces en `stack-my-architecture-governance` y `stack-my-architecture-SDD`.
|
|
17
|
+
- Producto de referencia: repo `ast-intelligence-hooks` (paquete npm `pumuki`). Documentación canónica: `README.md`, `docs/product/USAGE.md`, `docs/product/INSTALLATION.md`.
|
|
18
|
+
|
|
19
|
+
## Contexto
|
|
20
|
+
|
|
21
|
+
- **Objetivo:** curso dedicado a Pumuki como capa de enforcement (`Facts → Rules → Gate → evidencia v2.1`) en repos reales, sin re-enseñar OpenSpec ni ADR (remite a cursos SDD y Governance).
|
|
22
|
+
- **`courseId` propuesto:** `stack-my-architecture-pumuki` (alinear con hub y progress sync).
|
|
23
|
+
- **Versión mínima `pumuki` (MVP):** `>= 6.3.71` (ajustar al publicar el curso si hay release posterior).
|
|
24
|
+
- **Lab de práctica:** variante o fork de **GovernanceKit** (Governance) o **HelpdeskSDD** (SDD); documentado en `00-preparacion/02-lab-governancekit-helpdesksdd.md` del repo del curso.
|
|
25
|
+
|
|
26
|
+
## Estado actual
|
|
27
|
+
|
|
28
|
+
- **Cierre local y release gate:** `build-hub.sh --mode strict` + smoke runtime en verde.
|
|
29
|
+
- **Origen en GitHub:** el repo **`stack-my-architecture-hub`** tiene en **`main`** la carpeta estática **`pumuki/`** y el pipeline `build-hub` que la genera (sincronizado con remoto; despliegue a producción con el workflow cuando toque).
|
|
30
|
+
- **Repo Pumuki (ramas):** la documentación del curso en este repositorio está integrada en **`develop`** (**PR #746**, merge `428f10d`). La rama **`main`** del producto va **muy por detrás** de `develop` (del orden de **~600** commits a fecha de integración del plan); promover `develop` → `main` es un **release de producto** aparte, no parte del cierre de este plan formativo.
|
|
31
|
+
- **GitHub Actions:** la org **no** dispone de cuota útil para Actions → el **Hub Production Release Gate** en CI **no** se usa como gate; publicación y comprobaciones **en local** con `./scripts/publish-architecture-stack.sh` en el repo del hub (Vercel CLI + mismos scripts).
|
|
32
|
+
- **Publicación Vercel:** deploy del proyecto `stack-my-architecture-hub` con verificación de rutas contra el alias **`https://stack-my-architecture-hub.vercel.app`** (incluye `/pumuki/` → 200). El script `publish-architecture-stack.sh` infiere la base desde `Aliased:` (o `SMA_PUBLISH_VERIFY_BASE_URL`) y escribe **`.runtime/publish-verify-base.url`** para alinear `post-deploy-checks.sh` con la URL verificada (localmente o cuando Actions vuelva a estar disponible).
|
|
33
|
+
- Si **`https://architecture-stack.vercel.app`** debe exponer el mismo árbol estático que el hub, sincroniza proyecto/CNAME según tu setup (nota emitida por el script al publicar).
|
|
34
|
+
|
|
35
|
+
## Prioridad ordenada (fases y tareas)
|
|
36
|
+
|
|
37
|
+
| Fase | Task | Estado | Notas |
|
|
38
|
+
|------|------|--------|--------|
|
|
39
|
+
| 0 | Crear repo `stack-my-architecture-pumuki` + README + estructura carpetas | ✅ | Repo bajo `stack-my-architecture/stack-my-architecture-pumuki` |
|
|
40
|
+
| 0 | Definir `courseId` y versión mínima `pumuki` | ✅ | `stack-my-architecture-pumuki`, `>= 6.3.71` |
|
|
41
|
+
| 0 | Elegir proyecto lab (GovernanceKit vs HelpdeskSDD) | ✅ | Documentado en preparación del curso |
|
|
42
|
+
| 1 | Redactar roadmap semanal/módulos (`01-roadmap/`) | ✅ | |
|
|
43
|
+
| 1 | Módulos 1–7 MVP (lecciones + enlaces USAGE/README Pumuki) | ✅ | `02-modulos/` + referencias npm/docs producto |
|
|
44
|
+
| 2 | Integración hub: ruta `/pumuki` + `build-hub.sh` + launcher | ✅ | `stack-hub --course pumuki`, assets desde ios parcheados |
|
|
45
|
+
| 2 | Assistant `courseId` + smoke | ✅ | `_hub-platform.js`, `hub-app.js`, README hub + ejemplo curl |
|
|
46
|
+
| 3 | Enlaces desde Governance y SDD | ✅ | Semana 8 checkpoint + SDD semana 8 |
|
|
47
|
+
| 3 | (Opcional) Anexo iOS/Android Arquitecto/Maestría | ✅ | `00-core-mobile/04-calidad-pr-ready.md` iOS y Android |
|
|
48
|
+
| 4 | Scripts validación curso + primera publicación | ✅ | Curso: validate + check-links; hub: publish strict + `/pumuki/` 200 en alias hub |
|
|
49
|
+
|
|
50
|
+
## Criterios de cierre por fase
|
|
51
|
+
|
|
52
|
+
- **Fase 0:** repo clonable, README con prerequisitos y convenciones, scripts mínimos ejecutables.
|
|
53
|
+
- **Fase 1:** siete módulos enlazados a docs oficiales Pumuki; roadmap con orden de lectura.
|
|
54
|
+
- **Fase 2:** `build-hub` genera ruta servible; `stack-hub --course pumuki` documentado.
|
|
55
|
+
- **Fase 3:** enlaces mergeados en repos Governance y SDD (y opcional iOS/Android).
|
|
56
|
+
- **Fase 4:** checklist publicación + versión `pumuki` fijada en lecciones y CHANGELOG del curso.
|
|
57
|
+
|
|
58
|
+
## Auditoría y release (Fase 4)
|
|
59
|
+
|
|
60
|
+
- Ejecutar en el repo del curso: `scripts/validate-course-structure.py`, `scripts/check-links.py`.
|
|
61
|
+
- Publicación hub: modo `strict` en `Hub Production Release Gate`; verificación de rutas incluye `/pumuki/` en `publish-architecture-stack.sh`.
|
|
62
|
+
- Tras cada release npm relevante de Pumuki, revisar versión mínima en `00-preparacion/` y en este plan.
|
|
@@ -0,0 +1,230 @@
|
|
|
1
|
+
import type { AiGateStage } from './evaluateAiGate';
|
|
2
|
+
|
|
3
|
+
export type GovernanceCatalogNextAction = {
|
|
4
|
+
kind: 'info' | 'run_command';
|
|
5
|
+
message: string;
|
|
6
|
+
command?: string;
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
export type GovernanceCatalogAction = {
|
|
10
|
+
reason_code: string;
|
|
11
|
+
instruction: string;
|
|
12
|
+
next_action: GovernanceCatalogNextAction;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
const PRE_WRITE_VALIDATE_COMMAND =
|
|
16
|
+
'npx --yes --package pumuki@latest pumuki sdd validate --stage=PRE_WRITE --json';
|
|
17
|
+
|
|
18
|
+
export const buildGovernanceValidateCommand = (stage: AiGateStage): string =>
|
|
19
|
+
PRE_WRITE_VALIDATE_COMMAND.replace('PRE_WRITE', stage);
|
|
20
|
+
|
|
21
|
+
export const buildGovernancePolicyReconcileCommand = (stage: AiGateStage): string =>
|
|
22
|
+
`npx --yes --package pumuki@latest pumuki policy reconcile --strict --json && ${buildGovernanceValidateCommand(stage)}`;
|
|
23
|
+
|
|
24
|
+
const buildFallbackAction = (code: string): GovernanceCatalogAction => ({
|
|
25
|
+
reason_code: code,
|
|
26
|
+
instruction: 'Corrige el bloqueante primario y vuelve a ejecutar la validación del stage actual.',
|
|
27
|
+
next_action: {
|
|
28
|
+
kind: 'info',
|
|
29
|
+
message: 'Corrige el bloqueante primario y vuelve a ejecutar el mismo comando.',
|
|
30
|
+
},
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
export const resolveGovernanceCatalogAction = (params: {
|
|
34
|
+
code: string;
|
|
35
|
+
stage?: AiGateStage;
|
|
36
|
+
fallback?: GovernanceCatalogAction;
|
|
37
|
+
}): GovernanceCatalogAction => {
|
|
38
|
+
const stage = params.stage ?? 'PRE_WRITE';
|
|
39
|
+
const validateCommand = buildGovernanceValidateCommand(stage);
|
|
40
|
+
switch (params.code) {
|
|
41
|
+
case 'READY':
|
|
42
|
+
return {
|
|
43
|
+
reason_code: 'READY',
|
|
44
|
+
instruction: 'Puedes continuar con la siguiente slice mínima y volver a validar al cerrar.',
|
|
45
|
+
next_action: {
|
|
46
|
+
kind: 'info',
|
|
47
|
+
message: 'Gate en verde. Continúa con la implementación.',
|
|
48
|
+
},
|
|
49
|
+
};
|
|
50
|
+
case 'EVIDENCE_INVALID_OR_CHAIN':
|
|
51
|
+
return {
|
|
52
|
+
reason_code: 'EVIDENCE_INVALID_OR_CHAIN',
|
|
53
|
+
instruction: 'Regenera la evidencia canónica antes de continuar.',
|
|
54
|
+
next_action: {
|
|
55
|
+
kind: 'run_command',
|
|
56
|
+
message: 'Regenera o corrige la evidencia canónica (.ai_evidence.json) y vuelve a validar governance.',
|
|
57
|
+
command: validateCommand,
|
|
58
|
+
},
|
|
59
|
+
};
|
|
60
|
+
case 'AI_GATE_BLOCKED':
|
|
61
|
+
return {
|
|
62
|
+
reason_code: 'AI_GATE_BLOCKED',
|
|
63
|
+
instruction: 'Corrige primero el bloqueo principal del gate antes de continuar.',
|
|
64
|
+
next_action: {
|
|
65
|
+
kind: 'run_command',
|
|
66
|
+
message: 'Revalida el stage tras corregir la evidencia y el bloqueo principal.',
|
|
67
|
+
command: validateCommand,
|
|
68
|
+
},
|
|
69
|
+
};
|
|
70
|
+
case 'SDD_SESSION_MISSING':
|
|
71
|
+
return {
|
|
72
|
+
reason_code: 'SDD_SESSION_MISSING',
|
|
73
|
+
instruction: 'Abre una sesión SDD válida antes de seguir trabajando.',
|
|
74
|
+
next_action: {
|
|
75
|
+
kind: 'run_command',
|
|
76
|
+
message: 'Abre la sesión SDD del cambio activo y vuelve a validar.',
|
|
77
|
+
command: 'npx --yes --package pumuki@latest pumuki sdd session --open --change=<id>',
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
case 'SDD_SESSION_INVALID':
|
|
81
|
+
case 'SDD_SESSION_INVALID_OR_EXPIRED':
|
|
82
|
+
return {
|
|
83
|
+
reason_code: 'SDD_SESSION_INVALID_OR_EXPIRED',
|
|
84
|
+
instruction: 'Refresca o reabre la sesión SDD antes de seguir trabajando.',
|
|
85
|
+
next_action: {
|
|
86
|
+
kind: 'run_command',
|
|
87
|
+
message: 'Refresca la sesión SDD y vuelve a validar governance.',
|
|
88
|
+
command: 'npx --yes --package pumuki@latest pumuki sdd session --refresh --ttl-minutes=90',
|
|
89
|
+
},
|
|
90
|
+
};
|
|
91
|
+
case 'PRE_PUSH_UPSTREAM_MISSING':
|
|
92
|
+
return {
|
|
93
|
+
reason_code: 'PRE_PUSH_UPSTREAM_MISSING',
|
|
94
|
+
instruction: 'Configura el upstream remoto antes de continuar con PRE_PUSH.',
|
|
95
|
+
next_action: {
|
|
96
|
+
kind: 'run_command',
|
|
97
|
+
message: 'Configura tracking remoto para la rama actual.',
|
|
98
|
+
command: 'git push --set-upstream origin <branch>',
|
|
99
|
+
},
|
|
100
|
+
};
|
|
101
|
+
case 'PRE_PUSH_UPSTREAM_MISALIGNED':
|
|
102
|
+
return {
|
|
103
|
+
reason_code: 'PRE_PUSH_UPSTREAM_MISALIGNED',
|
|
104
|
+
instruction: 'Alinea el upstream remoto con la rama actual antes de continuar.',
|
|
105
|
+
next_action: {
|
|
106
|
+
kind: 'run_command',
|
|
107
|
+
message: 'Reconfigura el upstream remoto de la rama actual.',
|
|
108
|
+
command: 'git branch --unset-upstream && git push --set-upstream origin <branch>',
|
|
109
|
+
},
|
|
110
|
+
};
|
|
111
|
+
case 'GITFLOW_PROTECTED_BRANCH':
|
|
112
|
+
case 'GITFLOW_PROTECTED_BRANCH_CONTEXT':
|
|
113
|
+
return {
|
|
114
|
+
reason_code: 'GITFLOW_PROTECTED_BRANCH_CONTEXT',
|
|
115
|
+
instruction: 'Sal de la rama protegida y mueve el trabajo a feature/* o refactor/*.',
|
|
116
|
+
next_action: {
|
|
117
|
+
kind: 'run_command',
|
|
118
|
+
message: 'Crea una rama válida de trabajo antes de seguir.',
|
|
119
|
+
command: 'git checkout -b feature/<descripcion-kebab-case>',
|
|
120
|
+
},
|
|
121
|
+
};
|
|
122
|
+
case 'POLICY_STAGE_NOT_STRICT':
|
|
123
|
+
return {
|
|
124
|
+
reason_code: 'POLICY_STAGE_NOT_STRICT',
|
|
125
|
+
instruction: 'Reconcilia policy/skills en modo estricto antes de seguir.',
|
|
126
|
+
next_action: {
|
|
127
|
+
kind: 'run_command',
|
|
128
|
+
message: 'Converge policy-as-code y revalida el stage actual.',
|
|
129
|
+
command: buildGovernancePolicyReconcileCommand(stage),
|
|
130
|
+
},
|
|
131
|
+
};
|
|
132
|
+
case 'SKILLS_CONTRACT_SURFACE_INCOMPLETE':
|
|
133
|
+
case 'EVIDENCE_SKILLS_CONTRACT_INCOMPLETE':
|
|
134
|
+
return {
|
|
135
|
+
reason_code: 'SKILLS_CONTRACT_SURFACE_INCOMPLETE',
|
|
136
|
+
instruction: 'Materializa el lock/sources de skills antes de dar governance efectiva.',
|
|
137
|
+
next_action: {
|
|
138
|
+
kind: 'run_command',
|
|
139
|
+
message: 'Reconcilia policy/skills y vuelve a validar governance.',
|
|
140
|
+
command: buildGovernancePolicyReconcileCommand(stage),
|
|
141
|
+
},
|
|
142
|
+
};
|
|
143
|
+
case 'ADAPTER_WIRING_MISSING':
|
|
144
|
+
return {
|
|
145
|
+
reason_code: 'ADAPTER_WIRING_MISSING',
|
|
146
|
+
instruction: 'Instala el adaptador canónico si quieres wiring explícito de IDE/MCP.',
|
|
147
|
+
next_action: {
|
|
148
|
+
kind: 'run_command',
|
|
149
|
+
message: 'Genera `.pumuki/adapter.json` desde la instalación canónica.',
|
|
150
|
+
command: 'npx --yes --package pumuki@latest pumuki install --with-mcp',
|
|
151
|
+
},
|
|
152
|
+
};
|
|
153
|
+
case 'EVIDENCE_STALE':
|
|
154
|
+
case 'EVIDENCE_BRANCH_MISMATCH':
|
|
155
|
+
case 'EVIDENCE_SNAPSHOT_WARN':
|
|
156
|
+
return {
|
|
157
|
+
reason_code: params.code === 'EVIDENCE_SNAPSHOT_WARN' ? 'EVIDENCE_SNAPSHOT_WARN' : 'EVIDENCE_STALE',
|
|
158
|
+
instruction: 'Refresca evidencia y revisa hallazgos WARN antes de continuar.',
|
|
159
|
+
next_action: {
|
|
160
|
+
kind: 'run_command',
|
|
161
|
+
message: 'Revalida el stage actual y revisa findings WARN.',
|
|
162
|
+
command: validateCommand,
|
|
163
|
+
},
|
|
164
|
+
};
|
|
165
|
+
case 'ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES_HIGH':
|
|
166
|
+
case 'EVIDENCE_ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES':
|
|
167
|
+
return {
|
|
168
|
+
reason_code: 'EVIDENCE_ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES',
|
|
169
|
+
instruction: 'Reconcilia policy/skills en modo estricto y revalida el stage actual.',
|
|
170
|
+
next_action: {
|
|
171
|
+
kind: 'run_command',
|
|
172
|
+
message: 'Converge policy-as-code y vuelve a validar cobertura de active_rule_ids para reglas activas.',
|
|
173
|
+
command: buildGovernancePolicyReconcileCommand(stage),
|
|
174
|
+
},
|
|
175
|
+
};
|
|
176
|
+
case 'EVIDENCE_PLATFORM_SKILLS_SCOPE_INCOMPLETE':
|
|
177
|
+
case 'EVIDENCE_PLATFORM_SKILLS_BUNDLES_MISSING':
|
|
178
|
+
return {
|
|
179
|
+
reason_code: params.code,
|
|
180
|
+
instruction: 'Completa cobertura de skills por plataforma y vuelve a validar.',
|
|
181
|
+
next_action: {
|
|
182
|
+
kind: 'run_command',
|
|
183
|
+
message: 'Completa bundles/prefijos de skills requeridos y revalida el stage actual.',
|
|
184
|
+
command: validateCommand,
|
|
185
|
+
},
|
|
186
|
+
};
|
|
187
|
+
case 'EVIDENCE_PLATFORM_CRITICAL_SKILLS_RULES_MISSING':
|
|
188
|
+
case 'EVIDENCE_CROSS_PLATFORM_CRITICAL_ENFORCEMENT_INCOMPLETE':
|
|
189
|
+
return {
|
|
190
|
+
reason_code: params.code,
|
|
191
|
+
instruction: 'Reconcilia policy/skills en modo estricto para enforcement crítico y revalida.',
|
|
192
|
+
next_action: {
|
|
193
|
+
kind: 'run_command',
|
|
194
|
+
message: 'Materializa reglas críticas de plataforma y vuelve a validar el stage actual.',
|
|
195
|
+
command: buildGovernancePolicyReconcileCommand(stage),
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
case 'EVIDENCE_PREWRITE_WORKTREE_OVER_LIMIT':
|
|
199
|
+
case 'EVIDENCE_PREWRITE_WORKTREE_WARN':
|
|
200
|
+
return {
|
|
201
|
+
reason_code: params.code,
|
|
202
|
+
instruction: 'Particiona el worktree en slices atómicos antes de continuar.',
|
|
203
|
+
next_action: {
|
|
204
|
+
kind: 'run_command',
|
|
205
|
+
message: 'Reduce el worktree pendiente y revalida el stage actual.',
|
|
206
|
+
command: `git status --short && git add -p && ${validateCommand}`,
|
|
207
|
+
},
|
|
208
|
+
};
|
|
209
|
+
case 'SKILLS_SKILLS_FRONTEND_NO_SOLID_VIOLATIONS':
|
|
210
|
+
return {
|
|
211
|
+
reason_code: 'SKILLS_SKILLS_FRONTEND_NO_SOLID_VIOLATIONS',
|
|
212
|
+
instruction: 'Aplica refactor incremental por componente/hook y vuelve a validar.',
|
|
213
|
+
next_action: {
|
|
214
|
+
kind: 'info',
|
|
215
|
+
message: 'Aplica refactor incremental: extrae 1 componente/hook por commit y vuelve a ejecutar el gate.',
|
|
216
|
+
},
|
|
217
|
+
};
|
|
218
|
+
case 'GOVERNANCE_ATTENTION':
|
|
219
|
+
return {
|
|
220
|
+
reason_code: 'GOVERNANCE_ATTENTION',
|
|
221
|
+
instruction: 'Revisa governance truth y corrige el primer hueco del contrato antes de continuar.',
|
|
222
|
+
next_action: {
|
|
223
|
+
kind: 'info',
|
|
224
|
+
message: 'Revisa governance truth, corrige el primer gap visible y vuelve a validar.',
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
default:
|
|
228
|
+
return params.fallback ?? buildFallbackAction(params.code);
|
|
229
|
+
}
|
|
230
|
+
};
|
|
@@ -9,6 +9,7 @@ export { parseNameStatus } from './gitDiffUtils';
|
|
|
9
9
|
export interface IGitService {
|
|
10
10
|
runGit(args: ReadonlyArray<string>, cwd?: string): string;
|
|
11
11
|
getStagedFacts(extensions: ReadonlyArray<string>): ReadonlyArray<Fact>;
|
|
12
|
+
getUnstagedFacts(extensions: ReadonlyArray<string>): ReadonlyArray<Fact>;
|
|
12
13
|
getRepoFacts(extensions: ReadonlyArray<string>): ReadonlyArray<Fact>;
|
|
13
14
|
getRepoAndStagedFacts(extensions: ReadonlyArray<string>): ReadonlyArray<Fact>;
|
|
14
15
|
getStagedAndUnstagedFacts(extensions: ReadonlyArray<string>): ReadonlyArray<Fact>;
|
|
@@ -44,6 +45,30 @@ export class GitService implements IGitService {
|
|
|
44
45
|
);
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
getUnstagedFacts(extensions: ReadonlyArray<string>): ReadonlyArray<Fact> {
|
|
49
|
+
const nameStatus = this.runGit(['diff', '--name-status']);
|
|
50
|
+
const changes = parseNameStatus(nameStatus).filter((change) =>
|
|
51
|
+
hasAllowedExtension(change.path, extensions)
|
|
52
|
+
);
|
|
53
|
+
const untrackedPaths = this.runGit(['ls-files', '--others', '--exclude-standard'])
|
|
54
|
+
.split('\n')
|
|
55
|
+
.map((line) => line.trim())
|
|
56
|
+
.filter((line) => line.length > 0)
|
|
57
|
+
.filter((path) => hasAllowedExtension(path, extensions));
|
|
58
|
+
const unstagedPaths = new Set(changes.map((change) => change.path));
|
|
59
|
+
const untrackedChanges = untrackedPaths
|
|
60
|
+
.filter((path) => !unstagedPaths.has(path))
|
|
61
|
+
.map((path) => ({
|
|
62
|
+
path,
|
|
63
|
+
changeType: 'added' as const,
|
|
64
|
+
}));
|
|
65
|
+
const mergedChanges = [...changes, ...untrackedChanges];
|
|
66
|
+
const repoRoot = this.resolveRepoRoot();
|
|
67
|
+
return buildFactsFromChanges(mergedChanges, 'git:unstaged', (filePath) =>
|
|
68
|
+
this.readWorkingTreeFile(repoRoot, filePath)
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
47
72
|
getRepoFacts(extensions: ReadonlyArray<string>): ReadonlyArray<Fact> {
|
|
48
73
|
const trackedFiles = this.runGit(['ls-files'])
|
|
49
74
|
.split('\n')
|
|
@@ -1372,7 +1372,15 @@ export async function runPlatformGate(params: {
|
|
|
1372
1372
|
|
|
1373
1373
|
if (gateOutcome === 'BLOCK') {
|
|
1374
1374
|
if (params.silent !== true) {
|
|
1375
|
-
|
|
1375
|
+
const renderStage =
|
|
1376
|
+
params.policy.stage === 'PRE_PUSH'
|
|
1377
|
+
? 'PRE_PUSH'
|
|
1378
|
+
: params.policy.stage === 'CI'
|
|
1379
|
+
? 'CI'
|
|
1380
|
+
: 'PRE_COMMIT';
|
|
1381
|
+
dependencies.printGateFindings(findingsWithWaiver, {
|
|
1382
|
+
stage: renderStage,
|
|
1383
|
+
});
|
|
1376
1384
|
}
|
|
1377
1385
|
return 1;
|
|
1378
1386
|
}
|
|
@@ -27,6 +27,7 @@ export type GateScope =
|
|
|
27
27
|
};
|
|
28
28
|
|
|
29
29
|
const DEFAULT_EXTENSIONS = ['.swift', '.ts', '.tsx', '.js', '.jsx', '.kt', '.kts'];
|
|
30
|
+
export const DEFAULT_FACT_FILE_EXTENSIONS = DEFAULT_EXTENSIONS;
|
|
30
31
|
|
|
31
32
|
export const countScannedFilesFromFacts = (facts: ReadonlyArray<Fact>): number => {
|
|
32
33
|
const contentPaths = new Set<string>();
|
|
@@ -1,27 +1,5 @@
|
|
|
1
1
|
import type { Finding } from '../../core/gate/Finding';
|
|
2
|
-
|
|
3
|
-
const BLOCK_NEXT_ACTION_BY_CODE: Readonly<Record<string, string>> = {
|
|
4
|
-
SDD_SESSION_MISSING:
|
|
5
|
-
'npx --yes --package pumuki@latest pumuki sdd session --open --change=<id>',
|
|
6
|
-
SDD_SESSION_INVALID:
|
|
7
|
-
'npx --yes --package pumuki@latest pumuki sdd session --refresh --ttl-minutes=90',
|
|
8
|
-
PRE_PUSH_UPSTREAM_MISSING:
|
|
9
|
-
'git push --set-upstream origin <branch>',
|
|
10
|
-
PRE_PUSH_UPSTREAM_MISALIGNED:
|
|
11
|
-
'git branch --unset-upstream && git push --set-upstream origin <branch>',
|
|
12
|
-
EVIDENCE_STALE:
|
|
13
|
-
'npx --yes --package pumuki@latest pumuki-pre-commit',
|
|
14
|
-
EVIDENCE_BRANCH_MISMATCH:
|
|
15
|
-
'npx --yes --package pumuki@latest pumuki-pre-commit',
|
|
16
|
-
GIT_ATOMICITY_TOO_MANY_FILES:
|
|
17
|
-
'git restore --staged . && separa cambios en commits más pequeños',
|
|
18
|
-
GIT_ATOMICITY_TOO_MANY_SCOPES:
|
|
19
|
-
'Revisa scope_files del bloqueo y aplica: git restore --staged . && git add <scope>/ && git commit -m "<tipo>: <scope>"',
|
|
20
|
-
ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES_HIGH:
|
|
21
|
-
'Reconcilia policy/skills y reintenta PRE_COMMIT: npx --yes --package pumuki@latest pumuki policy reconcile --strict --json && npx --yes --package pumuki@latest pumuki-pre-commit',
|
|
22
|
-
SKILLS_SKILLS_FRONTEND_NO_SOLID_VIOLATIONS:
|
|
23
|
-
'Aplica refactor incremental: extrae 1 componente/hook por commit y vuelve a ejecutar PRE_COMMIT.',
|
|
24
|
-
};
|
|
2
|
+
import { resolveGovernanceCatalogAction } from '../gate/governanceActionCatalog';
|
|
25
3
|
|
|
26
4
|
const severityWeight = (severity: string): number => {
|
|
27
5
|
switch (severity.toUpperCase()) {
|
|
@@ -94,18 +72,49 @@ const formatFinding = (finding: Finding): string => {
|
|
|
94
72
|
return `[${severity}] ${finding.ruleId}: ${finding.message} -> ${location}`;
|
|
95
73
|
};
|
|
96
74
|
|
|
97
|
-
|
|
75
|
+
const resolveAtomicityFallback = (code: string): string | null => {
|
|
76
|
+
switch (code) {
|
|
77
|
+
case 'GIT_ATOMICITY_TOO_MANY_FILES':
|
|
78
|
+
return 'git restore --staged . && separa cambios en commits más pequeños';
|
|
79
|
+
case 'GIT_ATOMICITY_TOO_MANY_SCOPES':
|
|
80
|
+
return 'Revisa scope_files del bloqueo y aplica: git restore --staged . && git add <scope>/ && git commit -m "<tipo>: <scope>"';
|
|
81
|
+
default:
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export const printGateFindings = (
|
|
87
|
+
findings: ReadonlyArray<Finding>,
|
|
88
|
+
params?: { stage?: 'PRE_COMMIT' | 'PRE_PUSH' | 'CI' }
|
|
89
|
+
): void => {
|
|
98
90
|
if (findings.length === 0) {
|
|
99
91
|
return;
|
|
100
92
|
}
|
|
101
93
|
const primary = resolvePrimaryFinding(findings);
|
|
102
|
-
const
|
|
103
|
-
|
|
104
|
-
|
|
94
|
+
const action = resolveGovernanceCatalogAction({
|
|
95
|
+
code: primary.code,
|
|
96
|
+
stage: params?.stage ?? 'PRE_COMMIT',
|
|
97
|
+
fallback: {
|
|
98
|
+
reason_code: primary.code,
|
|
99
|
+
instruction: 'Corrige el bloqueante primario y vuelve a ejecutar la validación del stage actual.',
|
|
100
|
+
next_action: {
|
|
101
|
+
kind: 'info',
|
|
102
|
+
message:
|
|
103
|
+
resolveAtomicityFallback(primary.code)
|
|
104
|
+
?? 'Corrige el bloqueante primario y vuelve a ejecutar el mismo comando.',
|
|
105
|
+
},
|
|
106
|
+
},
|
|
107
|
+
});
|
|
108
|
+
const nextAction = action.next_action.command ?? action.next_action.message;
|
|
105
109
|
process.stdout.write(
|
|
106
110
|
`[pumuki][block-summary] primary=${primary.code} severity=${primary.severity.toUpperCase()} rule=${primary.ruleId}\n`
|
|
107
111
|
);
|
|
112
|
+
process.stdout.write(`[pumuki][block-summary] reason_code=${action.reason_code}\n`);
|
|
113
|
+
process.stdout.write(`[pumuki][block-summary] instruction=${action.instruction}\n`);
|
|
108
114
|
process.stdout.write(`[pumuki][block-summary] next_action=${nextAction}\n`);
|
|
115
|
+
if (action.next_action.command) {
|
|
116
|
+
process.stdout.write(`[pumuki][block-summary] command=${action.next_action.command}\n`);
|
|
117
|
+
}
|
|
109
118
|
for (const finding of findings) {
|
|
110
119
|
process.stdout.write(`${formatFinding(finding)}\n`);
|
|
111
120
|
}
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"codex": [
|
|
3
3
|
{
|
|
4
4
|
"path": ".pumuki/adapter.json",
|
|
5
|
+
"mode": "json-merge",
|
|
5
6
|
"payload": {
|
|
6
7
|
"hooks": {
|
|
7
8
|
"pre_write": {
|
|
@@ -31,6 +32,7 @@
|
|
|
31
32
|
"repo": [
|
|
32
33
|
{
|
|
33
34
|
"path": ".pumuki/adapter.json",
|
|
35
|
+
"mode": "json-merge",
|
|
34
36
|
"payload": {
|
|
35
37
|
"hooks": {
|
|
36
38
|
"pre_write": {
|
|
@@ -143,6 +145,7 @@
|
|
|
143
145
|
},
|
|
144
146
|
{
|
|
145
147
|
"path": ".pumuki/adapter.json",
|
|
148
|
+
"mode": "json-merge",
|
|
146
149
|
"payload": {
|
|
147
150
|
"hooks": {
|
|
148
151
|
"pre_write": {
|