pumuki 6.3.169 → 6.3.170

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/CHANGELOG.md CHANGED
@@ -6,6 +6,13 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
6
6
 
7
7
  ## [Unreleased]
8
8
 
9
+ ## [6.3.170] - 2026-05-07
10
+
11
+ ### Fixed
12
+
13
+ - **npm README entrypoint:** published package metadata now uses the real premium README with current menu/audit captures, explicit hook/CI enforcement boundaries, MCP stdio binary names, and clear AUTO vs DECLARATIVE skills coverage.
14
+ - **Release typecheck:** restored `npm run typecheck` on the published line by tightening TypeScript detector node typing and null-safe lifecycle/MCP helpers without changing detector semantics.
15
+
9
16
  ## [6.3.169] - 2026-05-06
10
17
 
11
18
  ### Fixed
package/README.md CHANGED
@@ -1,394 +1,213 @@
1
1
  # Pumuki
2
2
 
3
- <img src="assets/logo.png" alt="Pumuki" width="100%" />
3
+ <img src="assets/logo_banner.png" alt="Pumuki" width="100%" />
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/pumuki?color=1d4ed8)](https://www.npmjs.com/package/pumuki)
6
6
  [![CI](https://github.com/SwiftEnProfundidad/ast-intelligence-hooks/actions/workflows/ci.yml/badge.svg)](https://github.com/SwiftEnProfundidad/ast-intelligence-hooks/actions/workflows/ci.yml)
7
7
  [![License](https://img.shields.io/badge/license-MIT-16a34a)](LICENSE)
8
8
 
9
- Enterprise governance framework for AI-assisted software delivery.
9
+ Enterprise AST Intelligence and delivery gate for AI-assisted engineering teams.
10
10
 
11
- Pumuki gives engineering teams one deterministic execution model across local development, hooks, and CI:
11
+ Pumuki is a deterministic governance layer for Git repositories. It turns code,
12
+ repository state, skills, and SDD evidence into facts; evaluates AST-backed
13
+ rules by stage; blocks or allows work; and writes auditable evidence that humans,
14
+ hooks, CI, and agents can inspect.
12
15
 
13
- `Facts -> Rules -> Gate -> .ai_evidence.json (v2.1)`
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
-
21
- ## Who This README Is For
22
-
23
- | Profile | Use this path first |
24
- |---|---|
25
- | Consumer repository team | [5-Minute Quick Start (Consumer)](#5-minute-quick-start-consumer) |
26
- | Framework maintainers (this repo) | [Framework Maintainer Flow](#framework-maintainer-flow-this-repo) |
27
- | Platform/architecture owners | [Enterprise Operations Baseline](#enterprise-operations-baseline) |
28
-
29
- ## Rutas de adopción
16
+ ```text
17
+ Git scope -> facts -> AST Intelligence rules -> gate -> .ai_evidence.json
18
+ ```
30
19
 
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.
20
+ ## What Pumuki Does
32
21
 
33
- | Perfil | Qué instalar / arrancar | Stages habituales | Opcional típico |
34
- |--------|-------------------------|-------------------|-----------------|
35
- | **Mínimo** | `npm install --save-exact pumuki` (en repos Git el `postinstall` ejecuta baseline `pumuki install`; `--with-mcp --agent=repo` es opt-in con `PUMUKI_POSTINSTALL_WITH_MCP=1` o `PUMUKI_POSTINSTALL_MCP_AGENT=repo`). | 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). |
22
+ Pumuki gives a team one governance model across local development, hooks, CI,
23
+ CLI, menu UI, and MCP surfaces. The hard enforcement path remains Git hooks and
24
+ CI; CLI, menu, and MCP expose the same product state, stage runners, and
25
+ diagnostic contract for operation:
38
26
 
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).
27
+ | Capability | What it means in practice |
28
+ | --- | --- |
29
+ | Git hook governance | Managed `pre-commit` and `pre-push` hooks run the same stage gate engine exposed by the CLI runners. Managed hooks chain `pumuki-pre-write` first unless explicitly disabled with `PUMUKI_SKIP_CHAINED_PRE_WRITE=1`. |
30
+ | AST Intelligence | Rules are evaluated from extracted facts and AST/text nodes, not from a README promise. Findings include severity, rule id, stage, file, line, and remediation context. |
31
+ | Skills enforcement | iOS, Android, backend, frontend, and common governance skills are compiled into deterministic rule coverage. AUTO rules block through detectors; declarative rules remain visible as contracts and are not silently claimed as semantic enforcement. |
32
+ | Evidence contract | `.ai_evidence.json` records stage, outcome, policy metadata, rule coverage, findings, and operational hints for follow-up automation. |
33
+ | SDD/OpenSpec flow | Enterprise repos can require SDD sessions, change folders, and stage validation before writes, commits, pushes, or CI. |
34
+ | Agent-ready context | `.pumuki/adapter.json` and MCP stdio commands (`pumuki-mcp-enterprise-stdio`, `pumuki-mcp-evidence-stdio`) expose the same product truth to Codex, Claude, Cursor, Windsurf, OpenCode, and other clients without making the baseline IDE-dependent. |
40
35
 
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).
36
+ ## Real Output
42
37
 
43
- ## Comandos esenciales
38
+ These captures were generated from `pumuki@6.3.169` against a temporary Git
39
+ fixture containing a real TypeScript file with `any` and `console.log`. They are
40
+ not mockups.
44
41
 
45
- Cinco entradas que cubren el 80 % del día a día en un consumidor; el detalle está en los enlaces.
42
+ ![Pumuki consumer menu - real capture](assets/readme/current/01-menu-consumer-real.png)
46
43
 
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.
44
+ ![Pumuki full audit block - real capture](assets/readme/current/02-option1-audit-block-real.png)
52
45
 
53
- **Desarrollo en este repo (sin depender de GitHub Actions):** barra mínima antes de merge o publicar — `npm run -s validation:local-merge-bar` (`typecheck` + smoke de superficie CLI + `npm test`). Detalle del smoke: [docs/validation/README.md](docs/validation/README.md).
46
+ ![Pumuki pattern checks - real capture](assets/readme/current/03-option5-pattern-checks-real.png)
54
47
 
55
- 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).
48
+ Older menu walkthrough captures are still kept in
49
+ [`assets/readme/menu-option1/`](assets/readme/menu-option1/) and documented in
50
+ [`docs/operations/framework-menu-consumer-walkthrough.md`](docs/operations/framework-menu-consumer-walkthrough.md).
56
51
 
57
- ## 5-Minute Quick Start (Consumer)
52
+ ## Quick Start
58
53
 
59
- Prerequisites:
54
+ Requirements:
60
55
 
61
56
  - Node.js `>= 18`
62
57
  - npm `>= 9`
63
- - Git repository
58
+ - A Git repository
64
59
 
65
- Install and bootstrap:
60
+ Install Pumuki in a consumer repository:
66
61
 
67
62
  ```bash
68
- npm install --save-exact pumuki
69
- npx --yes pumuki bootstrap --enterprise --agent=codex
70
- npx --yes pumuki status
63
+ npm install --save-dev --save-exact pumuki
64
+ npx --yes pumuki status --json
71
65
  npx --yes pumuki doctor --json
66
+ npx --yes pumuki audit --stage=PRE_COMMIT --json
72
67
  ```
73
68
 
74
- Desde **6.3.63**, `npm install` en la raíz de un repo **Git** dispara un `postinstall` que ejecuta baseline **`pumuki install`** (hooks `pre-commit` / `pre-push`, lifecycle, merge de **`.pumuki/adapter.json`** con comandos MCP stdio, sin rutas de IDE salvo opt-in). El wiring MCP no va activado por defecto; para activarlo en postinstall usa `PUMUKI_POSTINSTALL_WITH_MCP=1` o `PUMUKI_POSTINSTALL_MCP_AGENT=repo/cursor/claude/codex`. **Pumuki no depende de ningún IDE** para el baseline. Opt-out del postinstall: `PUMUKI_SKIP_POSTINSTALL=1`. Ficheros de IDE en postinstall: `PUMUKI_POSTINSTALL_MCP_AGENT=cursor|claude|codex` o comando manual / `bootstrap`. Desde **6.3.68**, cada hook gestionado ejecuta **`pumuki-pre-write` antes** de `pumuki-pre-commit` / `pumuki-pre-push` (stage **PRE_WRITE** vía Git). Saltar solo PRE_WRITE en hooks: `PUMUKI_SKIP_CHAINED_PRE_WRITE=1`. Desde **6.3.69**, esos mismos hooks aplican también **git-flow en ramas protegidas** (`GITFLOW_PROTECTED_BRANCH`) e **higiene de worktree** (`PUMUKI_PREWRITE_WORKTREE_*` / códigos `EVIDENCE_PREWRITE_WORKTREE_*`) cuando la evidencia es válida; el **modal macOS** de bloqueo (Desactivar / Silenciar 30 min / Mantener activas) queda **activo por defecto** si las notificaciones están habilitadas (`"blockedDialogEnabled": false` o `PUMUKI_MACOS_BLOCKED_DIALOG=0` para apagarlo). Desactivar el postinstall: `PUMUKI_SKIP_POSTINSTALL=1`. En CI suele saltarse solo (`CI=true`). En **6.3.64+**, las notificaciones del sistema en plataformas sin banner nativo se reflejan en **stderr** por defecto (`PUMUKI_DISABLE_STDERR_NOTIFICATIONS=1` para silenciarlas). En **6.3.69+**, un `gate.blocked` en macOS también deja una copia en **stderr** por defecto (`PUMUKI_DISABLE_GATE_BLOCKED_STDERR_MIRROR=1` para desactivar solo eso). Desde **6.3.70**, si **`.ai_evidence.json` está versionado** y **PRE_PUSH** no bloquea, ese archivo **no se reescribe** en el push (compatibilidad con **pre-commit** como hook de **pre-push**); para forzar escritura: `PUMUKI_PRE_PUSH_ALWAYS_WRITE_TRACKED_EVIDENCE=1`. Con modal de bloqueo activo, el panel interactivo prioriza foco/clics y se evita el banner duplicado.
75
-
76
- Fallback (equivalent in pasos separados):
69
+ Run the local gates directly:
77
70
 
78
71
  ```bash
79
- npx --yes pumuki install --with-mcp --agent=codex
80
- npx --yes pumuki doctor --deep --json
72
+ npx --yes pumuki-pre-write
73
+ npx --yes pumuki-pre-commit
74
+ npx --yes pumuki-pre-push
75
+ npx --yes pumuki-ci
81
76
  ```
82
77
 
83
- OpenSpec/SDD baseline:
78
+ `pumuki-pre-push` is the same binary used by the managed Git hook. Running it
79
+ manually is useful for diagnostics, but the full signal depends on a real branch
80
+ and pre-push context.
84
81
 
85
- ```bash
86
- npx --yes pumuki sdd status
87
- mkdir -p openspec/changes/<change-id>
88
- npx --yes pumuki sdd session --open --change=<change-id>
89
- npx --yes pumuki sdd validate --stage=PRE_COMMIT
90
- ```
91
-
92
- Optional loop runner session (local, deterministic):
82
+ Bootstrap an enterprise repo with SDD/OpenSpec and agent context:
93
83
 
94
84
  ```bash
95
- npx --yes pumuki loop run --objective="stabilize gate before commit" --max-attempts=3 --json
96
- npx --yes pumuki loop list --json
97
- ```
98
-
99
- Run local gates:
100
-
101
- ```bash
102
- npx --yes --package pumuki@latest pumuki-pre-write
103
- npx --yes --package pumuki@latest pumuki-pre-commit
104
- ```
105
-
106
- Run push/CI gates (requires proper git context):
107
-
108
- ```bash
109
- git push --set-upstream origin <branch>
110
- npx --yes --package pumuki@latest pumuki-pre-push
111
- npx --yes --package pumuki@latest pumuki-ci
112
- ```
113
-
114
- Expected behavior:
115
-
116
- - `PRE_WRITE` and `PRE_COMMIT`: should pass when SDD session is valid and rules are satisfied.
117
- - `PRE_PUSH`: blocks if branch has no upstream tracking reference.
118
- - `CI`: requires a valid diff range context (not `HEAD..HEAD` with ambiguous range).
119
-
120
- Version drift quick check:
121
-
122
- - `status --json` and `doctor --json` expose `version.effective`, `version.runtime`, `version.consumerInstalled`, `version.lifecycleInstalled`, `version.driftWarning`, `version.alignmentCommand`, `version.pathExecutionHazard`, `version.pathExecutionWarning`, and `version.pathExecutionWorkaroundCommand`.
123
- - If `driftWarning` is not `null`, prefer the exact command already exposed in `version.alignmentCommand`.
124
- - If `pathExecutionHazard` is `true`, avoid `npx/npm exec` for the install step and use the safe local workaround reported by Pumuki, for example:
125
-
126
- ```bash
127
- node ./node_modules/pumuki/bin/pumuki.js install
128
- ```
129
-
130
- ## Why Pumuki
131
-
132
- Modern teams need fast feedback with strict governance. Pumuki combines:
133
-
134
- - Deterministic enforcement per stage (`PRE_WRITE`, `PRE_COMMIT`, `PRE_PUSH`, `CI`).
135
- - A single evidence contract (`.ai_evidence.json`, v2.1) for auditability and automation.
136
- - Multi-platform governance (iOS, Android, Backend, Frontend).
137
- - Unified skills engine with deterministic precedence (`core -> repo -> custom`).
138
- - Mandatory OpenSpec/SDD checks for enterprise change control.
139
- - Unified CLI plus optional MCP servers for agent-driven workflows.
140
-
141
- ## Enterprise Execution Model
142
-
143
- Each execution follows the same pipeline:
144
-
145
- 1. Facts extraction from staged/range/repo scope.
146
- 2. Rule evaluation by platform and stage policy.
147
- 3. Gate decision (`PASS`, `WARN`, `BLOCK`) with deterministic thresholds.
148
- 4. Evidence emission (`.ai_evidence.json`) with findings, metadata, and coverage telemetry.
149
-
150
- Rules resolution order:
151
-
152
- 1. Core rules (embedded package snapshot).
153
- 2. Repo rules (`skills.lock.json`), optional.
154
- 3. Custom rules (`.pumuki/custom-rules.json`), optional.
155
-
156
- Conflict policy:
157
-
158
- - `custom > repo > core` (last writer wins by `ruleId`).
159
- - Platform rules activate only for detected platforms.
160
- - `generic/text` rules remain available as cross-platform governance guards.
161
-
162
- Rule modes:
163
-
164
- - `AUTO`: mapped to deterministic detectors/heuristics.
165
- - `DECLARATIVE`: valid only when explicitly declared in lock/custom payload (no silent fallback for rules extracted from skills markdown).
166
-
167
- ## Core Capabilities
168
-
169
- 1. Deterministic stage gates with consistent exit semantics.
170
- 2. Evidence v2.1 with rules coverage enforcement and stable ordering.
171
- 3. Unified skills rules engine (core + repo + custom).
172
- 4. Unified AI gate behavior across CLI and MCP surfaces.
173
- 5. Mandatory OpenSpec/SDD policy checks.
174
- 6. Interactive menu UX (consumer + advanced modes).
175
- 7. Hard mode policy hardening (`.pumuki/hard-mode.json` + env overrides).
176
- 8. Lifecycle commands for install/update/diagnostics/teardown.
177
- 9. Provider-agnostic adapter scaffolding (`codex`, `claude`, `cursor`, `windsurf`, `opencode`).
178
- 10. Optional MCP servers for evidence and enterprise context.
179
-
180
- ## Policy-as-Code (Enterprise)
181
-
182
- Pumuki supports a signed and versioned stage-policy contract at:
183
-
184
- - `.pumuki/policy-as-code.json`
185
-
186
- Minimal contract:
187
-
188
- ```json
189
- {
190
- "version": "1.0",
191
- "source": "default",
192
- "expires_at": "2026-12-31T23:59:59.000Z",
193
- "signatures": {
194
- "PRE_COMMIT": "<sha256-hex>",
195
- "PRE_PUSH": "<sha256-hex>",
196
- "CI": "<sha256-hex>"
197
- }
198
- }
85
+ npx --yes pumuki bootstrap --enterprise --agent=codex
86
+ npx --yes pumuki sdd session --open --change=<change-id>
87
+ npx --yes pumuki sdd validate --stage=PRE_WRITE --json
88
+ npx --yes pumuki policy reconcile --strict --apply --json
199
89
  ```
200
90
 
201
- Runtime behavior:
202
-
203
- - If the contract is missing, Pumuki computes deterministic local metadata and still emits `policy_version`, `policy_signature`, and `policy_source`.
204
- - If present, the contract is validated against active runtime policy for source/stage/signature.
205
- - Validation states are emitted as `valid`, `invalid`, `expired`, or `unknown-source`.
206
- - `PUMUKI_POLICY_STRICT=1` turns non-valid states into blocking findings (`governance.policy-as-code.invalid`).
207
-
208
- Operational fallback:
209
-
210
- - Keep strict mode disabled while bootstrapping a repo without a canonical contract.
211
- - Enable strict mode once contract generation/signatures are part of your baseline pipeline.
212
-
213
- ## Telemetry Export (Enterprise)
214
-
215
- Pumuki can export structured gate telemetry with a stable event schema (`telemetry_event_v1`) for SIEM/observability pipelines.
216
-
217
- Default behavior remains unchanged: telemetry export is disabled unless explicitly configured.
218
-
219
- Enable one or both outputs:
220
-
221
- - `PUMUKI_TELEMETRY_JSONL_PATH`: local JSONL target (absolute or repo-relative path)
222
- - `PUMUKI_TELEMETRY_OTEL_ENDPOINT`: OTLP HTTP logs endpoint (`/v1/logs`)
223
- - `PUMUKI_TELEMETRY_OTEL_SERVICE_NAME`: optional OTel service name (default: `pumuki`)
224
- - `PUMUKI_TELEMETRY_OTEL_TIMEOUT_MS`: optional OTel timeout in ms (default: `1500`)
225
-
226
- Example:
91
+ Install or refresh the IDE-neutral adapter contract:
227
92
 
228
93
  ```bash
229
- export PUMUKI_TELEMETRY_JSONL_PATH=".pumuki/artifacts/gate-telemetry.jsonl"
230
- export PUMUKI_TELEMETRY_OTEL_ENDPOINT="https://otel.example/v1/logs"
231
- export PUMUKI_TELEMETRY_OTEL_SERVICE_NAME="pumuki-enterprise"
232
- npx --yes --package pumuki@latest pumuki-pre-commit
94
+ npx --yes pumuki install
95
+ npx --yes pumuki adapter install --agent=codex --dry-run
96
+ npx --yes pumuki adapter install --agent=codex
233
97
  ```
234
98
 
235
- Each event captures deterministic stage/outcome/policy/repo context per gate execution.
236
-
237
- ## Framework Maintainer Flow (This Repo)
99
+ ## Stage Model
100
+
101
+ | Stage | Typical scope | Main use |
102
+ | --- | --- | --- |
103
+ | `PRE_WRITE` | Current working intent and SDD state | Stop invalid work before it becomes a commit candidate. |
104
+ | `PRE_COMMIT` | Staged diff plus required evidence | Block any staged violation before it enters history. |
105
+ | `PRE_PUSH` | Branch range and repository policy | Catch branch, range, governance, and evidence drift before sharing. |
106
+ | `CI` | CI diff range | Re-run the same policy contract outside the developer machine. |
107
+ | `audit` | Explicit repo/index/staged scope | Produce an operator-readable report without pretending it is a hook. |
108
+
109
+ Managed Git hooks run `PRE_WRITE` before `PRE_COMMIT` or `PRE_PUSH`. The opt-out
110
+ for that chaining is explicit: `PUMUKI_SKIP_CHAINED_PRE_WRITE=1`.
111
+
112
+ ## Skills And Platforms
113
+
114
+ Pumuki is multi-platform by design. The default enterprise skill surface has two
115
+ layers:
116
+
117
+ - platform rule bundles compiled into `skills.lock.json`
118
+ - operating contract skills shipped with Pumuki and consumed through
119
+ `AGENTS.md` / `vendor/skills`
120
+
121
+ The platform rule surface covers:
122
+
123
+ - `ios-enterprise-rules`
124
+ - `swift-concurrency`
125
+ - `swiftui-expert-skill`
126
+ - `swift-testing-expert`
127
+ - `core-data-expert`
128
+ - `android-enterprise-rules`
129
+ - `backend-enterprise-rules`
130
+ - `frontend-enterprise-rules`
131
+
132
+ Rule coverage is intentionally explicit:
133
+
134
+ - `AUTO` means a rule has a deterministic detector or mapped heuristic.
135
+ - `DECLARATIVE` means the rule is a contract from a skill source, but it is not
136
+ counted as semantic AST enforcement unless a detector exists.
137
+ - Unsupported or incomplete active-rule coverage can fail closed under strict
138
+ enterprise policy, because false confidence is worse than a noisy block.
139
+
140
+ `enterprise-operating-system` is the operating contract skill for project mode,
141
+ tracking, evidence, GitFlow, and STOP/GO discipline. It is shipped as a skill
142
+ contract, not as a per-file detector bundle.
143
+
144
+ ## Evidence And Adapters
145
+
146
+ Pumuki writes and reads `.ai_evidence.json` as the shared audit artifact for:
147
+
148
+ - gate outcome (`ALLOW`, `WARN`, `BLOCK`)
149
+ - stage and policy metadata
150
+ - finding counts by severity
151
+ - rule ids, file paths, line numbers, and categories
152
+ - active skill coverage
153
+ - operational hints and next actions
154
+
155
+ When repository safety checks pass, `pumuki install` keeps the baseline
156
+ IDE-agnostic. Pumuki installs managed Git hooks and ensures
157
+ `.pumuki/adapter.json` with canonical commands for MCP stdio and agent clients.
158
+ IDE-specific files such as `.cursor/mcp.json` remain opt-in.
159
+
160
+ ## Command Map
161
+
162
+ | Command | Purpose |
163
+ | --- | --- |
164
+ | `pumuki status --json` | Fast repository, lifecycle, version, and governance snapshot. |
165
+ | `pumuki doctor --json` | Deeper diagnostics for install drift, hook state, parity, and hazards. |
166
+ | `pumuki audit --stage=<stage> --json` | Run AST/rule analysis for a selected stage or scope. |
167
+ | `pumuki install` | Install or reconcile the managed baseline in a Git repository. |
168
+ | `pumuki bootstrap --enterprise` | Bootstrap enterprise SDD, policy, adapter, and lifecycle context. |
169
+ | `pumuki sdd validate --stage=<stage>` | Validate SDD/OpenSpec policy for the stage. |
170
+ | `pumuki policy reconcile --strict --apply` | Reconcile policy state and evidence expectations. |
171
+ | `pumuki-pre-write` | Stage runner for write-time governance. |
172
+ | `pumuki-pre-commit` | Stage runner for commit-time governance. |
173
+ | `pumuki-pre-push` | Stage runner for push-time governance. |
174
+ | `pumuki-ci` | CI runner for the same enterprise gate contract. |
175
+ | `pumuki-framework` / `ast-hooks` | Interactive terminal menu for operators and maintainers. |
176
+
177
+ ## What Pumuki Is Not
178
+
179
+ Pumuki is not the business product in your repository. It does not replace unit
180
+ tests, domain acceptance tests, API contracts, threat modeling, or human review.
181
+ It enforces the governance contract that the repository declares and the rules
182
+ that Pumuki can prove through facts, AST Intelligence, skills, and evidence.
183
+
184
+ It is also not IDE magic. MCP servers and adapter files give agents a canonical
185
+ way to ask for context and gate state, but Git hooks and CI remain the hard
186
+ enforcement path.
187
+
188
+ ## Documentation
189
+
190
+ - [Installation](docs/product/INSTALLATION.md)
191
+ - [Usage](docs/product/USAGE.md)
192
+ - [Configuration](docs/product/CONFIGURATION.md)
193
+ - [API reference](docs/product/API_REFERENCE.md)
194
+ - [MCP servers](docs/mcp/mcp-servers-overview.md)
195
+ - [Evidence v2.1 contract](docs/mcp/ai-evidence-v2.1-contract.md)
196
+ - [Validation index](docs/validation/README.md)
197
+ - [Documentation index](docs/README.md)
198
+
199
+ ## Maintainer Flow
238
200
 
239
201
  Use this only when working in the Pumuki framework repository itself:
240
202
 
241
203
  ```bash
242
204
  npm run framework:menu
243
- PUMUKI_MENU_UI_V2=1 npm run framework:menu
244
205
  PUMUKI_MENU_MODE=advanced npm run framework:menu
245
- ```
246
-
247
- Skills engine operations:
248
-
249
- ```bash
250
206
  npm run skills:compile
251
207
  npm run skills:lock:check
252
- npm run skills:import:custom
253
- npm run skills:import:custom -- --source <absolute-path-to-SKILL.md> --source <second-absolute-path-to-SKILL.md>
254
- ```
255
-
256
- Adapter scaffolding:
257
-
258
- ```bash
259
- npx --yes pumuki adapter install --agent=codex --dry-run
260
- npx --yes pumuki adapter install --agent=cursor
261
- npm run adapter:install -- --agent=claude
262
- ```
263
-
264
- Operational matrix/canary:
265
-
266
- ```bash
267
- node --import tsx -e "const mod = await import('./scripts/framework-menu-matrix-runner-lib.ts'); const report = await mod.default.runConsumerMenuMatrix({ repoRoot: process.cwd() }); console.log(JSON.stringify(report, null, 2));"
268
- node --import tsx -e "const mod = await import('./scripts/framework-menu-matrix-canary-lib.ts'); const report = await mod.default.runConsumerMenuCanary({ repoRoot: process.cwd() }); console.log(JSON.stringify(report, null, 2));"
208
+ npm run -s validation:local-merge-bar
209
+ npm pack --dry-run
269
210
  ```
270
211
 
271
- Legacy parity report (strict comparator):
272
-
273
- ```bash
274
- node --import tsx scripts/build-legacy-parity-report.ts --legacy=<legacy-evidence-path> --enterprise=<enterprise-evidence-path> --out=<output-path>
275
- ```
276
-
277
- ## Command Paths
278
-
279
- Use these docs instead of treating `README.md` as the full command manual:
280
-
281
- - Installation and bootstrap:
282
- - `docs/product/INSTALLATION.md`
283
- - Daily usage, gates, menu, lifecycle, SDD and troubleshooting:
284
- - `docs/product/USAGE.md`
285
- - Operator-focused short playbook:
286
- - `PUMUKI.md`
287
- - Validation runbooks and framework-only diagnostics:
288
- - `docs/validation/README.md`
289
-
290
- ## Menu Walkthrough and Screenshots
291
-
292
- ### Capture 1 — Consumer Menu (archived v2)
293
-
294
- ![Consumer Menu archived v2](assets/readme/menu-option1/01-menu-consumer-v2.png)
295
-
296
- Canonical consumer legacy reference:
297
-
298
- - Git tag `v0-legacy-last`, `scripts/hooks-system/infrastructure/shell/orchestrators/audit-orchestrator.sh`
299
-
300
- ### Capture 2 — Archived v2 Full-Audit Pre-flight (BLOCK context)
301
-
302
- ![Archived v2 Full-Audit Pre-flight Block](assets/readme/menu-option1/02-option1-preflight-block.png)
303
-
304
- ### Capture 3 — Archived v2 Full-Audit Final Summary (BLOCK)
305
-
306
- ![Archived v2 Full-Audit Final Summary Block](assets/readme/menu-option1/03-option1-final-summary-block.png)
307
-
308
- ### Capture 4 — Archived v2 Full-Audit Pre-flight (PASS scenario)
309
-
310
- ![Archived v2 Full-Audit Pre-flight Pass Scenario](assets/readme/menu-option1/04-option1-preflight-pass.png)
311
-
312
- ### Capture 5 — Archived v2 Full-Audit Final Summary (PASS)
313
-
314
- ![Archived v2 Full-Audit Final Summary Pass](assets/readme/menu-option1/05-option1-final-summary-pass.png)
315
-
316
- ### Capture 6 — Menu Status After PASS Run
317
-
318
- ![Menu After Pass Run](assets/readme/menu-option1/06-menu-after-run-pass.png)
319
-
320
- Extended annotated walkthrough:
321
-
322
- - `docs/operations/framework-menu-consumer-walkthrough.md`
323
-
324
- ## Enterprise Operations Baseline
325
-
326
- Pumuki production SaaS operation baseline is defined in:
327
-
328
- - `docs/operations/production-operations-policy.md`
329
-
330
- Highlights:
331
-
332
- - Minimum SLO/SLA targets for ingestion availability, latency, freshness, and isolation.
333
- - Severity model (`SEV1/SEV2/SEV3`) with response and RCA expectations.
334
- - Mandatory controls for tenant/repo isolation, auth policy, idempotency, and auditing.
335
- - Go-live checklist and rollback requirements.
336
-
337
- ## Troubleshooting
338
-
339
- - `OpenSpec change "<id>" not found`: ensure `openspec/changes/<id>` exists before opening session.
340
- - `SDD_SESSION_MISSING`: open and validate session first.
341
- - `pre-push blocked: branch has no upstream`: run `git push --set-upstream origin <branch>`.
342
- - `Missing required argument --repo` / `--repo-path`: pass required flags for validation scripts.
343
- - Legacy parity report usage requires `--legacy=<path>` and `--enterprise=<path>` (equals form).
344
- - If menu v2 rendering fails, Pumuki falls back to classic UI.
345
-
346
- ## Documentation Index
347
-
348
- - Installation: `docs/product/INSTALLATION.md`
349
- - Usage: `docs/product/USAGE.md`
350
- - Backlog tooling quick nav (incluye snippet terminal): `docs/product/USAGE.md#backlog-tooling`
351
- - Backlog reasons shared module: `docs/product/USAGE.md#backlog-reasons`
352
- - Testing: `docs/product/TESTING.md`
353
- - API reference: `docs/product/API_REFERENCE.md`
354
- - Architecture: `docs/product/ARCHITECTURE.md`
355
- - Configuration: `docs/product/CONFIGURATION.md`
356
- - Code standards: `docs/governance/CODE_STANDARDS.md`
357
- - Branch protection: `docs/governance/BRANCH_PROTECTION_GUIDE.md`
358
- - MCP servers: `docs/mcp/mcp-servers-overview.md`
359
- - MCP evidence server: `docs/mcp/evidence-context-server.md`
360
- - MCP consumption: `docs/mcp/agent-context-consumption.md`
361
- - Evidence schema v2.1: `docs/mcp/ai-evidence-v2.1-contract.md`
362
- - Operations policy (SLA/SLO): `docs/operations/production-operations-policy.md`
363
- - Release notes: `docs/operations/RELEASE_NOTES.md`
364
- - Changelog: `CHANGELOG.md`
365
-
366
- ## Collaboration
367
-
368
- Contributions are welcome. For high-quality collaboration:
369
-
370
- 1. Read `docs/governance/CONTRIBUTING.md` and `docs/governance/CODE_STANDARDS.md`.
371
- 2. Create a dedicated branch per change.
372
- 3. Keep scope focused and include deterministic evidence when relevant.
373
- 4. Before opening a PR, run at least:
374
- - `npm run typecheck`
375
- - `npm run -s test:backlog-tooling`
376
- - `npm run test:operational-memory`
377
- - `npm run test:saas-ingestion`
378
- 5. Open a PR with clear problem statement, approach, and validation evidence.
379
-
380
- ## Support and Security
381
-
382
- - Functional/usage issues: open a GitHub issue with reproducible steps.
383
- - Enterprise diagnostics: include generated reports from `.audit-reports` when applicable.
384
- - Security-sensitive findings: use GitHub Security Advisories for coordinated disclosure.
385
-
386
- ## License
387
-
388
- MIT. See `LICENSE`.
389
-
390
- ## If Pumuki Helped You
391
-
392
- If this project was useful for your team, please consider leaving a GitHub star:
393
-
394
- [Star Pumuki on GitHub](https://github.com/SwiftEnProfundidad/ast-intelligence-hooks)
212
+ Before publishing, validate the local package, inspect the tarball contents, and
213
+ verify the published README through the npm package page or registry metadata.
@@ -340,7 +340,10 @@ type AstNodeWithAncestors = {
340
340
  ancestors: readonly AstNode[];
341
341
  };
342
342
 
343
- const toPositiveLine = (node: AstNode): number | null => {
343
+ const toPositiveLine = (node: unknown): number | null => {
344
+ if (!isObject(node)) {
345
+ return null;
346
+ }
344
347
  const loc = node.loc;
345
348
  if (!isObject(loc)) {
346
349
  return null;
@@ -745,15 +748,18 @@ const toSemanticMemberNode = (
745
748
  };
746
749
  };
747
750
 
748
- const toSingleLineArray = (line: number | null): readonly number[] | undefined => {
751
+ const toSingleLineArray = (line: number | null | undefined): readonly number[] | undefined => {
749
752
  return typeof line === 'number' ? [line] : undefined;
750
753
  };
751
754
 
752
755
  const dedupeSemanticNodes = (
753
- nodes: ReadonlyArray<TypeScriptSemanticNode>
756
+ nodes: ReadonlyArray<TypeScriptSemanticNode | undefined>
754
757
  ): readonly TypeScriptSemanticNode[] => {
755
758
  const unique = new Map<string, TypeScriptSemanticNode>();
756
759
  for (const node of nodes) {
760
+ if (!node) {
761
+ continue;
762
+ }
757
763
  const key = `${node.kind}:${node.name}:${(node.lines ?? []).join(',')}`;
758
764
  if (!unique.has(key)) {
759
765
  unique.set(key, node);
@@ -3355,7 +3361,10 @@ const buildDtoBoundaryMatch = (node: unknown): TypeScriptDtoBoundaryMatch | unde
3355
3361
 
3356
3362
  const classNode = match.node;
3357
3363
  const className = methodNameFromNode(classNode.id);
3358
- const classBody = isObject(classNode.body) && classNode.body.type === 'ClassBody' ? classNode.body.body : [];
3364
+ const classBody =
3365
+ isObject(classNode.body) && classNode.body.type === 'ClassBody' && Array.isArray(classNode.body.body)
3366
+ ? classNode.body.body
3367
+ : [];
3359
3368
  const classLine = toPositiveLine(classNode);
3360
3369
 
3361
3370
  const propertyEntries = classBody.filter((member) => {
@@ -3725,12 +3734,12 @@ const buildBackendTransactionsMatch = (
3725
3734
  return undefined;
3726
3735
  }
3727
3736
 
3728
- const ownerNode = semanticOwnerFromAncestors(match.ancestors) ?? {
3737
+ const ownerNode: TypeScriptSemanticNode = semanticOwnerFromAncestors(match.ancestors) ?? {
3729
3738
  kind: 'member',
3730
3739
  name: `${boundaryObjectName}.${boundaryName}`,
3731
3740
  lines: toSingleLineArray(callLine),
3732
3741
  };
3733
- const primaryNode =
3742
+ const primaryNode: TypeScriptSemanticNode =
3734
3743
  ownerNode.kind === 'class' || ownerNode.kind === 'member'
3735
3744
  ? ownerNode
3736
3745
  : {
@@ -4154,7 +4163,7 @@ const buildRateLimitingThrottlerMatch = (
4154
4163
  ...(calleeName === 'Throttle'
4155
4164
  ? [
4156
4165
  {
4157
- kind: 'member',
4166
+ kind: 'member' as const,
4158
4167
  name: '@nestjs/throttler',
4159
4168
  lines: toSingleLineArray(callLine),
4160
4169
  },
@@ -4163,7 +4172,7 @@ const buildRateLimitingThrottlerMatch = (
4163
4172
  ...(calleeName === 'UseGuards'
4164
4173
  ? [
4165
4174
  {
4166
- kind: 'member',
4175
+ kind: 'member' as const,
4167
4176
  name: 'ThrottlerGuard',
4168
4177
  lines: toSingleLineArray(callLine),
4169
4178
  },
@@ -4172,7 +4181,7 @@ const buildRateLimitingThrottlerMatch = (
4172
4181
  ...(calleeName === 'forRoot' || calleeName === 'forRootAsync'
4173
4182
  ? [
4174
4183
  {
4175
- kind: 'member',
4184
+ kind: 'member' as const,
4176
4185
  name: 'ThrottlerModule',
4177
4186
  lines: toSingleLineArray(callLine),
4178
4187
  },
@@ -4557,7 +4566,7 @@ const buildCallbackHellPatternMatch = (
4557
4566
  lines: toSingleLineArray(toPositiveLine(nestedCall)),
4558
4567
  }
4559
4568
  : undefined,
4560
- ].filter((entry): entry is TypeScriptSemanticNode => entry !== undefined)
4569
+ ]
4561
4570
  );
4562
4571
  const lines = sortedUniqueLines([
4563
4572
  ...(primaryNode.lines ?? []),
@@ -5046,7 +5055,12 @@ const buildEnvDefaultFallbackPatternMatch = (
5046
5055
  if (value.operator !== '||' && value.operator !== '??') {
5047
5056
  return false;
5048
5057
  }
5049
- return typeof memberExpressionPropertyName(value.left) === 'string' && isProcessEnvBaseAccess(value.left.object);
5058
+ const leftNode = value.left;
5059
+ return (
5060
+ isObject(leftNode) &&
5061
+ typeof memberExpressionPropertyName(leftNode) === 'string' &&
5062
+ isProcessEnvBaseAccess(leftNode.object)
5063
+ );
5050
5064
  }
5051
5065
 
5052
5066
  if (value.type !== 'AssignmentPattern') {
@@ -5493,6 +5507,7 @@ const buildProductionMockMatch = (
5493
5507
  return (
5494
5508
  isObject(objectNode) &&
5495
5509
  objectNode.type === 'Identifier' &&
5510
+ typeof objectNode.name === 'string' &&
5496
5511
  productionMockLibraryPattern.test(objectNode.name) &&
5497
5512
  isObject(propertyNode) &&
5498
5513
  propertyNode.type === 'Identifier' &&
@@ -5649,7 +5664,7 @@ const buildExceptionFilterMatch = (
5649
5664
  return methodNameFromNode(expression) === 'Catch';
5650
5665
  });
5651
5666
 
5652
- const primaryNode = {
5667
+ const primaryNode: TypeScriptSemanticNode = {
5653
5668
  kind: 'class',
5654
5669
  name: className,
5655
5670
  lines: typeof classLine === 'number' ? [classLine] : [],
@@ -5664,7 +5679,7 @@ const buildExceptionFilterMatch = (
5664
5679
  ...(hasCatchDecorator
5665
5680
  ? [
5666
5681
  {
5667
- kind: 'member',
5682
+ kind: 'member' as const,
5668
5683
  name: '@Catch',
5669
5684
  lines: typeof classLine === 'number' ? [classLine] : [],
5670
5685
  },
@@ -5740,7 +5755,8 @@ const buildGuardMatch = (node: unknown): TypeScriptGuardMatch | undefined => {
5740
5755
  ? classOrMemberNode.lines[0]
5741
5756
  : toPositiveLine(classOrMemberNode ?? decoratorNode);
5742
5757
  const decoratorLine = toPositiveLine(decoratorNode);
5743
- const guardArgument = expression.arguments.find((argument) => methodNameFromNode(argument) === 'JwtAuthGuard');
5758
+ const expressionArguments = Array.isArray(expression.arguments) ? expression.arguments : [];
5759
+ const guardArgument = expressionArguments.find((argument) => methodNameFromNode(argument) === 'JwtAuthGuard');
5744
5760
  const guardLine = toPositiveLine(guardArgument) ?? decoratorLine;
5745
5761
  const ownerName =
5746
5762
  classOrMemberNode?.kind === 'class' || classOrMemberNode?.kind === 'member'
@@ -5845,7 +5861,8 @@ const buildInterceptorMatch = (node: unknown): TypeScriptInterceptorMatch | unde
5845
5861
  ? classOrMemberNode.lines[0]
5846
5862
  : toPositiveLine(classOrMemberNode ?? decoratorNode);
5847
5863
  const decoratorLine = toPositiveLine(decoratorNode);
5848
- const interceptorArgument = expression.arguments.find((argument) => {
5864
+ const expressionArguments = Array.isArray(expression.arguments) ? expression.arguments : [];
5865
+ const interceptorArgument = expressionArguments.find((argument) => {
5849
5866
  const name = interceptorNameFromNode(argument);
5850
5867
  return typeof name === 'string' && /Interceptor$/u.test(name);
5851
5868
  });
@@ -6174,7 +6191,7 @@ const buildReactClassComponentMatch = (
6174
6191
  lines: toSingleLineArray(reactImportInfo.importLines[0]),
6175
6192
  }
6176
6193
  : undefined,
6177
- ].filter((entry): entry is TypeScriptSemanticNode => entry !== undefined));
6194
+ ]);
6178
6195
 
6179
6196
  const lines = sortedUniqueLines([
6180
6197
  ...(typeof classLine === 'number' ? [classLine] : []),
@@ -6367,7 +6384,7 @@ const buildSingletonPatternMatch = (
6367
6384
  lines: toSingleLineArray(toPositiveLine(singletonFactoryMethodMember)),
6368
6385
  }
6369
6386
  : undefined,
6370
- ].filter((entry): entry is TypeScriptSemanticNode => entry !== undefined)
6387
+ ]
6371
6388
  );
6372
6389
 
6373
6390
  const lines = sortedUniqueLines([
@@ -460,6 +460,7 @@ type ASTDetectorRegistryEntry = {
460
460
  readonly code: string;
461
461
  readonly message: string;
462
462
  readonly pathCheck?: (path: string) => boolean;
463
+ readonly excludePaths?: ReadonlyArray<(path: string) => boolean>;
463
464
  readonly includeTestPaths?: boolean;
464
465
  };
465
466
 
@@ -4,6 +4,12 @@ This file tracks the active deterministic framework line used in this repository
4
4
  Canonical release chronology lives in `CHANGELOG.md`.
5
5
  This file keeps only the operational highlights and rollout notes that matter while running the framework.
6
6
 
7
+ ### 2026-05-07 (v6.3.170)
8
+
9
+ - **npm README entrypoint:** la ficha pública de npm pasa a mostrar el README premium real, con capturas actuales de menú/auditoría, límites explícitos de hooks/CI, binarios MCP stdio y cobertura AUTO vs DECLARATIVE de skills.
10
+ - **Release typecheck:** la línea publicada recupera `npm run typecheck` con fixes conservadores en detectores TypeScript y helpers lifecycle/MCP, sin cambiar semántica de detección.
11
+ - **Rollout:** publicar `pumuki@6.3.170` para sustituir el README antiguo visible en `pumuki@6.3.169` sin degradar la línea de paquete ya publicada.
12
+
7
13
  ### 2026-05-05 (v6.3.150)
8
14
 
9
15
  - **RuralGo PUMUKI-INC-061:** las notificaciones de bloqueo ya recomiendan `policy reconcile --strict --apply --json` cuando la remediación real requiere converger policy-as-code.
@@ -1,5 +1,6 @@
1
1
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
2
2
  import { dirname, join } from 'node:path'
3
+ import type { AiGateStage } from '../gate/evaluateAiGate'
3
4
  import { getPumukiHooksStatus, resolvePumukiHooksDirectory } from './hookManager'
4
5
  import { LifecycleGitService, type ILifecycleGitService } from './gitService'
5
6
  import {
@@ -15,6 +16,15 @@ import { readLifecycleState } from './state'
15
16
 
16
17
  export const BOOTSTRAP_MANIFEST_RELATIVE_PATH = '.pumuki/bootstrap-manifest.json'
17
18
 
19
+ const JSON_PRETTY_PRINT_SPACES = 2
20
+
21
+ const toAiGateStage = (stage: string | undefined): AiGateStage => {
22
+ if (stage === 'PRE_WRITE' || stage === 'PRE_COMMIT' || stage === 'PRE_PUSH' || stage === 'CI') {
23
+ return stage
24
+ }
25
+ return 'PRE_WRITE'
26
+ }
27
+
18
28
  type AdapterCommandContract = {
19
29
  path: string
20
30
  present: boolean
@@ -174,7 +184,7 @@ export const buildLifecycleBootstrapManifest = (params: {
174
184
  })
175
185
  const governanceNextAction = readGovernanceNextAction({
176
186
  repoRoot,
177
- stage: governanceObservation.evidence.snapshot_stage ?? 'PRE_WRITE',
187
+ stage: toAiGateStage(governanceObservation.evidence.snapshot_stage),
178
188
  governanceObservation,
179
189
  })
180
190
  const hooksDirectory = resolvePumukiHooksDirectory(repoRoot)
@@ -223,7 +233,7 @@ export const buildLifecycleBootstrapManifest = (params: {
223
233
  }
224
234
 
225
235
  const serializeManifest = (manifest: LifecycleBootstrapManifest): string =>
226
- `${JSON.stringify(manifest, null, 2)}\n`
236
+ `${JSON.stringify(manifest, null, JSON_PRETTY_PRINT_SPACES)}\n`
227
237
 
228
238
  export const writeLifecycleBootstrapManifest = (params: {
229
239
  repoRoot: string
@@ -10,7 +10,6 @@ import type { ILifecycleGitService } from './gitService';
10
10
  import { LifecycleGitService } from './gitService';
11
11
  import type { LifecyclePolicyValidationSnapshot } from './policyValidationSnapshot';
12
12
  import { writeInfo } from './cliOutputs';
13
- import { formatTrackingActionableContext } from './trackingState';
14
13
 
15
14
  const DEFAULT_PROTECTED_BRANCHES = new Set(['main', 'master', 'develop', 'dev']);
16
15
  const STRICT_ENV_VALUE = 'strict';
@@ -206,9 +205,8 @@ const buildHints = (
206
205
  hints.push(`Falta el tracking canónico declarado (${tracking.canonical_path ?? 'sin resolver'}).`);
207
206
  }
208
207
  if (tracking.enforced && tracking.single_in_progress_valid === false) {
209
- const actionableContext = formatTrackingActionableContext(tracking);
210
208
  hints.push(
211
- `El tracking canónico debe dejar exactamente una 🚧 (actual=${tracking.in_progress_count ?? 'n/a'}${actionableContext ? `, ${actionableContext}` : ''}).`
209
+ `El tracking canónico debe dejar exactamente una 🚧 (actual=${tracking.in_progress_count ?? 'n/a'}).`
212
210
  );
213
211
  }
214
212
  hints.push('SDD/OpenSpec: usa PUMUKI_EXPERIMENTAL_SDD=advisory|strict cuando el loop SDD esté activo.');
@@ -351,9 +349,8 @@ export const buildGovernanceObservationSummaryLines = (
351
349
  lines.push(`Attention: ${snapshot.attention_codes.join(', ')}`);
352
350
  }
353
351
  if (snapshot.tracking.enforced && snapshot.tracking.single_in_progress_valid === false) {
354
- const actionableContext = formatTrackingActionableContext(snapshot.tracking);
355
352
  lines.push(
356
- `Tracking: canonical=${snapshot.tracking.canonical_path ?? 'unknown'} in_progress_count=${snapshot.tracking.in_progress_count ?? 'n/a'}${actionableContext ? ` ${actionableContext}` : ''}`
353
+ `Tracking: canonical=${snapshot.tracking.canonical_path ?? 'unknown'} in_progress_count=${snapshot.tracking.in_progress_count ?? 'n/a'}`
357
354
  );
358
355
  }
359
356
  return lines;
@@ -13,6 +13,7 @@ import { createEmptyEvaluationMetrics } from '../evidence/evaluationMetrics';
13
13
  import { readOpenSpecManagedArtifacts, writeLifecycleState } from './state';
14
14
  import { ensureRuntimeArtifactsIgnored } from './artifacts';
15
15
  import { runLifecycleAdapterInstall } from './adapter';
16
+ import { writeLifecycleBootstrapManifest } from './bootstrapManifest';
16
17
  import { runPolicyReconcile } from './policyReconcile';
17
18
  import { emitGateBlockedNotification } from '../notifications/emitAuditSummaryNotification';
18
19
 
@@ -20,6 +21,10 @@ export type LifecycleInstallResult = {
20
21
  repoRoot: string;
21
22
  version: string;
22
23
  changedHooks: ReadonlyArray<string>;
24
+ bootstrapManifest: {
25
+ path: string;
26
+ changed: boolean;
27
+ };
23
28
  openSpecBootstrap?: OpenSpecBootstrapResult;
24
29
  degradedDoctorBypass?: boolean;
25
30
  };
@@ -127,10 +132,18 @@ export const runLifecycleInstall = (params?: {
127
132
  });
128
133
  ensureRepoBaselineAdapter(report.repoRoot);
129
134
  materializeStrictPolicyAsCode(report.repoRoot);
135
+ const bootstrapManifest = writeLifecycleBootstrapManifest({
136
+ git,
137
+ repoRoot: report.repoRoot,
138
+ });
130
139
  return {
131
140
  repoRoot: report.repoRoot,
132
141
  version,
133
142
  changedHooks,
143
+ bootstrapManifest: {
144
+ path: bootstrapManifest.path,
145
+ changed: bootstrapManifest.changed,
146
+ },
134
147
  openSpecBootstrap: undefined,
135
148
  degradedDoctorBypass: true,
136
149
  };
@@ -179,11 +192,19 @@ export const runLifecycleInstall = (params?: {
179
192
  });
180
193
  ensureRepoBaselineAdapter(report.repoRoot);
181
194
  materializeStrictPolicyAsCode(report.repoRoot);
195
+ const bootstrapManifest = writeLifecycleBootstrapManifest({
196
+ git,
197
+ repoRoot: report.repoRoot,
198
+ });
182
199
 
183
200
  return {
184
201
  repoRoot: report.repoRoot,
185
202
  version,
186
203
  changedHooks,
204
+ bootstrapManifest: {
205
+ path: bootstrapManifest.path,
206
+ changed: bootstrapManifest.changed,
207
+ },
187
208
  openSpecBootstrap,
188
209
  };
189
210
  };
@@ -52,10 +52,14 @@ const resolvePrePushBootstrapBaseRefInRepo = (repoRoot: string): string => {
52
52
  continue;
53
53
  }
54
54
  try {
55
- const changedFiles = runGit(
55
+ const diffOutput = runGit(
56
56
  repoRoot,
57
57
  ['diff', '--name-only', '--diff-filter=ACMR', `${candidate}..HEAD`]
58
- )
58
+ );
59
+ if (diffOutput === null) {
60
+ continue;
61
+ }
62
+ const changedFiles = diffOutput
59
63
  .split('\n')
60
64
  .map((line) => line.trim())
61
65
  .filter((line) => line.length > 0).length;
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.169",
4
- "description": "Enterprise-grade AST Intelligence System with multi-platform support (iOS, Android, Backend, Frontend) and Feature-First + DDD + Clean Architecture enforcement. Includes dynamic violations API for intelligent querying.",
3
+ "version": "6.3.170",
4
+ "description": "Enterprise AST Intelligence and delivery gate for AI-assisted teams: Git hooks, SDD/OpenSpec, skills enforcement, MCP context, and audit evidence for iOS, Android, backend, and frontend repositories.",
5
5
  "main": "index.js",
6
6
  "bin": {
7
7
  "pumuki": "bin/pumuki.js",