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 +7 -0
- package/README.md +161 -342
- package/assets/readme/current/01-menu-consumer-real.png +0 -0
- package/assets/readme/current/02-option1-audit-block-real.png +0 -0
- package/assets/readme/current/03-option5-pattern-checks-real.png +0 -0
- package/core/facts/detectors/typescript/index.ts +34 -17
- package/core/facts/extractHeuristicFacts.ts +1 -0
- package/docs/operations/RELEASE_NOTES.md +6 -0
- package/integrations/lifecycle/bootstrapManifest.ts +12 -2
- package/integrations/lifecycle/governanceObservationSnapshot.ts +2 -5
- package/integrations/lifecycle/install.ts +21 -0
- package/integrations/mcp/alignedPlatformGate.ts +6 -2
- package/package.json +2 -2
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/
|
|
3
|
+
<img src="assets/logo_banner.png" alt="Pumuki" width="100%" />
|
|
4
4
|
|
|
5
5
|
[](https://www.npmjs.com/package/pumuki)
|
|
6
6
|
[](https://github.com/SwiftEnProfundidad/ast-intelligence-hooks/actions/workflows/ci.yml)
|
|
7
7
|
[](LICENSE)
|
|
8
8
|
|
|
9
|
-
Enterprise
|
|
9
|
+
Enterprise AST Intelligence and delivery gate for AI-assisted engineering teams.
|
|
10
10
|
|
|
11
|
-
Pumuki
|
|
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
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
|
|
20
|
+
## What Pumuki Does
|
|
32
21
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
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
|
-
|
|
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
|
-
|
|
36
|
+
## Real Output
|
|
42
37
|
|
|
43
|
-
|
|
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
|
-
|
|
42
|
+

|
|
46
43
|
|
|
47
|
-
|
|
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
|
+

|
|
52
45
|
|
|
53
|
-
|
|
46
|
+

|
|
54
47
|
|
|
55
|
-
|
|
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
|
-
##
|
|
52
|
+
## Quick Start
|
|
58
53
|
|
|
59
|
-
|
|
54
|
+
Requirements:
|
|
60
55
|
|
|
61
56
|
- Node.js `>= 18`
|
|
62
57
|
- npm `>= 9`
|
|
63
|
-
- Git repository
|
|
58
|
+
- A Git repository
|
|
64
59
|
|
|
65
|
-
Install
|
|
60
|
+
Install Pumuki in a consumer repository:
|
|
66
61
|
|
|
67
62
|
```bash
|
|
68
|
-
npm install --save-exact pumuki
|
|
69
|
-
npx --yes pumuki
|
|
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
|
-
|
|
75
|
-
|
|
76
|
-
Fallback (equivalent in pasos separados):
|
|
69
|
+
Run the local gates directly:
|
|
77
70
|
|
|
78
71
|
```bash
|
|
79
|
-
npx --yes pumuki
|
|
80
|
-
npx --yes pumuki
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
96
|
-
npx --yes pumuki
|
|
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
|
-
|
|
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
|
-
|
|
230
|
-
|
|
231
|
-
|
|
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
|
-
|
|
236
|
-
|
|
237
|
-
|
|
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
|
|
253
|
-
npm
|
|
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
|
-
|
|
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
|
-

|
|
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
|
-

|
|
303
|
-
|
|
304
|
-
### Capture 3 — Archived v2 Full-Audit Final Summary (BLOCK)
|
|
305
|
-
|
|
306
|
-

|
|
307
|
-
|
|
308
|
-
### Capture 4 — Archived v2 Full-Audit Pre-flight (PASS scenario)
|
|
309
|
-
|
|
310
|
-

|
|
311
|
-
|
|
312
|
-
### Capture 5 — Archived v2 Full-Audit Final Summary (PASS)
|
|
313
|
-
|
|
314
|
-

|
|
315
|
-
|
|
316
|
-
### Capture 6 — Menu Status After PASS Run
|
|
317
|
-
|
|
318
|
-

|
|
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.
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -340,7 +340,10 @@ type AstNodeWithAncestors = {
|
|
|
340
340
|
ancestors: readonly AstNode[];
|
|
341
341
|
};
|
|
342
342
|
|
|
343
|
-
const toPositiveLine = (node:
|
|
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 =
|
|
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
|
-
]
|
|
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
|
-
|
|
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
|
|
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
|
|
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
|
-
]
|
|
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
|
-
]
|
|
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
|
|
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,
|
|
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'}
|
|
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'}
|
|
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
|
|
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.
|
|
4
|
-
"description": "Enterprise
|
|
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",
|