pumuki 6.3.47 → 6.3.49
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/docs/RELEASE_NOTES.md
CHANGED
|
@@ -5,6 +5,39 @@ Detailed commit history remains available through Git history (`git log` / `git
|
|
|
5
5
|
|
|
6
6
|
## 2026-03 (enterprise hardening updates)
|
|
7
7
|
|
|
8
|
+
### 2026-03-05 (v6.3.49)
|
|
9
|
+
|
|
10
|
+
- Watch JSON contract clarity for staged scope:
|
|
11
|
+
- `lastTick.changed` now reflects real scoped file delta, not merely tick execution.
|
|
12
|
+
- In `scope=staged` with no staged files:
|
|
13
|
+
- `changed=false`
|
|
14
|
+
- `changedFiles=[]`
|
|
15
|
+
- `evaluatedFiles=[]`
|
|
16
|
+
- Operational impact:
|
|
17
|
+
- prevents false interpretation of activity in consumer diagnostics and backlog evidence.
|
|
18
|
+
- Validation evidence:
|
|
19
|
+
- `npx --yes tsx@4.21.0 --test integrations/lifecycle/__tests__/watch.test.ts` (`6 pass / 0 fail`)
|
|
20
|
+
- `npm run -s typecheck` (`PASS`)
|
|
21
|
+
- consumer smoke (Flux, local core bin): `watch --once --stage=PRE_COMMIT --scope=staged --json` -> `changed=false` with empty arrays.
|
|
22
|
+
|
|
23
|
+
### 2026-03-05 (v6.3.48)
|
|
24
|
+
|
|
25
|
+
- Anti-drift hardening for consumer validation flows:
|
|
26
|
+
- `pumuki watch` now applies manifest integrity guard and restores unexpected mutations to:
|
|
27
|
+
- `package.json`
|
|
28
|
+
- `package-lock.json`
|
|
29
|
+
- `pnpm-lock.yaml`
|
|
30
|
+
- `yarn.lock`
|
|
31
|
+
- If mutation is detected, watch blocks with `MANIFEST_MUTATION_DETECTED`.
|
|
32
|
+
- Hook hardening parity:
|
|
33
|
+
- `pre-commit` / `pre-push` manifest guard now covers npm + pnpm + yarn lockfiles (not only npm).
|
|
34
|
+
- Operational impact:
|
|
35
|
+
- avoids silent manifest/lockfile drift in consumers during validation loops unless upgrade is explicitly requested.
|
|
36
|
+
- Validation evidence:
|
|
37
|
+
- `npx --yes tsx@4.21.0 --test integrations/lifecycle/__tests__/watch.test.ts integrations/git/__tests__/stageRunners.test.ts` (`38 pass / 0 fail`)
|
|
38
|
+
- `npm run -s typecheck` (`PASS`)
|
|
39
|
+
- consumer smoke (Flux, local core bin): `watch --once --json` with hashes unchanged for `package.json` / `pnpm-lock.yaml`.
|
|
40
|
+
|
|
8
41
|
### 2026-03-05 (v6.3.47)
|
|
9
42
|
|
|
10
43
|
- Manifest integrity hardening in hook stages (`PRE_COMMIT` / `PRE_PUSH`):
|
|
@@ -2516,4 +2516,76 @@
|
|
|
2516
2516
|
- vigilancia:
|
|
2517
2517
|
- `npm run -s validation:backlog-watch:tick`.
|
|
2518
2518
|
|
|
2519
|
-
-
|
|
2519
|
+
- ✅ PUMUKI-187: Publicar corte con fix `#720`, actualizar consumers a la versión publicada y mover `PUMUKI-INC-063` de `🚧 REPORTED` a `✅ FIXED` con referencia de issue/commit/release.
|
|
2520
|
+
- Resultado (2026-03-05):
|
|
2521
|
+
- release publicada: `pumuki@6.3.47`.
|
|
2522
|
+
- rollout en consumers:
|
|
2523
|
+
- `R_GO`: upgrade a `pumuki@6.3.47` (con `npm_config_engine_strict=false` por restricción de engines del consumer), `PRE_WRITE/PRE_COMMIT/PRE_PUSH` en `RC=0`.
|
|
2524
|
+
- `SAAS`: upgrade a `pumuki@6.3.47`, validación local con binarios `node node_modules/pumuki/bin/*` (bloqueos existentes del repo por reglas/gate, no regresión de manifests).
|
|
2525
|
+
- `Flux_training`: upgrade a `pumuki@6.3.47`, `PRE_WRITE/PRE_COMMIT` en `RC=0` y `PRE_PUSH` bloqueado por atomicidad del propio worktree (`changed_files=720`), sin mutación de manifests.
|
|
2526
|
+
- verificación de no mutación de manifests:
|
|
2527
|
+
- `R_GO`: `package.json` y `package-lock.json` sin cambios de hash antes/después de `validate + pre-commit + pre-push`.
|
|
2528
|
+
- `SAAS`: `package.json` y `package-lock.json` sin cambios de hash antes/después de `validate + pre-commit + pre-push`.
|
|
2529
|
+
- `Flux_training`: `package.json` y `pnpm-lock.yaml` sin cambios de hash antes/después de `validate + pre-commit + pre-push`.
|
|
2530
|
+
- MD canónico RuralGo actualizado:
|
|
2531
|
+
- `PUMUKI-INC-063` -> `✅ FIXED (#720, release 6.3.47)`.
|
|
2532
|
+
- activos High reducidos a `PUMUKI-INC-064` como único foco.
|
|
2533
|
+
- Evidencia:
|
|
2534
|
+
- `npm publish --access public` -> `+ pumuki@6.3.47`.
|
|
2535
|
+
- `npm ls pumuki --depth=0` (`R_GO`/`SAAS`) y `pnpm list -D pumuki --depth 0` (`Flux_training`) -> `6.3.47`.
|
|
2536
|
+
- hashes before/after de manifests en los tres consumers.
|
|
2537
|
+
|
|
2538
|
+
- ✅ PUMUKI-188: Cerrar trazabilidad de RuralGo tras validación de `PUMUKI-INC-064` y ajustar foco activo al siguiente hallazgo neto real.
|
|
2539
|
+
- Resultado (2026-03-05):
|
|
2540
|
+
- MD canónico RuralGo quedó 100% cerrado:
|
|
2541
|
+
- `✅ Cerrados: 100`
|
|
2542
|
+
- `🚧/⏳/⛔: 0`.
|
|
2543
|
+
- `PUMUKI-INC-064` se consolidó en `✅ FIXED` con referencia de release `6.3.47` y evidencia de `PRE_PUSH=ALLOW` sin workaround manual de `skills.sources.json`/`skills.lock.json`.
|
|
2544
|
+
- `issue #720` cerrada tras validación del fix de mutación de manifests.
|
|
2545
|
+
- Evidencia:
|
|
2546
|
+
- `sed -n '1,60p' /Users/.../R_GO/docs/.../pumuki-integration-feedback.md` (estado cerrado 100/0).
|
|
2547
|
+
- `gh issue close 720 --repo SwiftEnProfundidad/ast-intelligence-hooks ...`.
|
|
2548
|
+
|
|
2549
|
+
- ✅ PUMUKI-189: Ejecutar siguiente bug prioritaria activa de Flux (`PUM-013`) sobre drift de dependencia en manifests durante validación y cerrar con fix + release + validación consumer.
|
|
2550
|
+
- Resultado (2026-03-05):
|
|
2551
|
+
- issue upstream `#722` cerrada tras validación real en consumer.
|
|
2552
|
+
- `PUM-013` actualizado a `✅ Cerrado` en el MD externo de Flux.
|
|
2553
|
+
- verificación de no-mutación confirmada:
|
|
2554
|
+
- `package.json` hash before/after sin cambios,
|
|
2555
|
+
- `pnpm-lock.yaml` hash before/after sin cambios,
|
|
2556
|
+
- `watch --once --json` en `ALLOW` (`gateExitCode=0`).
|
|
2557
|
+
- Evidencia:
|
|
2558
|
+
- `npx --yes --package pumuki@latest pumuki watch --once --stage=PRE_COMMIT --scope=staged --json`
|
|
2559
|
+
- `gh issue close 722 --repo SwiftEnProfundidad/ast-intelligence-hooks ...`
|
|
2560
|
+
- `/Users/juancarlosmerlosalbarracin/Developer/Projects/Flux_training/docs/BUGS_Y_MEJORAS_PUMUKI.md` (`PUM-013` -> `✅ Cerrado`).
|
|
2561
|
+
|
|
2562
|
+
- ✅ PUMUKI-190: Ejecutar vigilancia activa del backlog canónico de RuralGo y abrir/cerrar loop solo ante nuevos hallazgos netos reproducibles (`OPEN/REPORTED`), manteniendo SAAS/Flux en validación de no-regresión sin tocar código consumidor.
|
|
2563
|
+
- Resultado (2026-03-05):
|
|
2564
|
+
- tick fleet ejecutado sobre los 3 backlogs externos (`SAAS`, `RuralGo`, `Flux`) sin hallazgos netos.
|
|
2565
|
+
- `non_closed_total=0`, `action_required_targets=0`, `has_action_required=false`.
|
|
2566
|
+
- no se abren issues nuevas ni se requiere fix técnico en este ciclo.
|
|
2567
|
+
- Evidencia:
|
|
2568
|
+
- `npm run -s validation:backlog-watch:tick`
|
|
2569
|
+
- salida JSON: `targets=3`, `entries_scanned_total=142`, `non_closed_total=0`.
|
|
2570
|
+
|
|
2571
|
+
- ✅ PUMUKI-191: Mantener monitorización continua multi-consumer (tick periódico) y abrir ejecución técnica inmediata solo cuando `has_action_required=true`, actualizando en el mismo ciclo el MD externo afectado + este MD interno.
|
|
2572
|
+
- Resultado (2026-03-05):
|
|
2573
|
+
- tick fleet detectó hallazgo neto nuevo en Flux (`PUM-014`) con `has_action_required=true`.
|
|
2574
|
+
- issue upstream creada: `#723`.
|
|
2575
|
+
- MD externo Flux actualizado a estado activo (`PUM-014` -> `🚧 En construccion (#723)`).
|
|
2576
|
+
- Evidencia:
|
|
2577
|
+
- `npm run -s validation:backlog-watch:tick` (run_id `819f019e-36ce-405f-ba24-3cb1372a2021`)
|
|
2578
|
+
- `gh issue create --repo SwiftEnProfundidad/ast-intelligence-hooks ...` -> `#723`
|
|
2579
|
+
- `/Users/juancarlosmerlosalbarracin/Developer/Projects/Flux_training/docs/BUGS_Y_MEJORAS_PUMUKI.md` actualizado.
|
|
2580
|
+
|
|
2581
|
+
- 🚧 PUMUKI-192: Ejecutar fix de `PUM-014/#723` en `watch --json` para alinear `lastTick.changed` con delta real de archivos del scope, validar en tests y preparar cierre de leyenda externa.
|
|
2582
|
+
- Avance (2026-03-05):
|
|
2583
|
+
- fix aplicado en `integrations/lifecycle/watch.ts` (`changed` ahora depende del delta real del scope).
|
|
2584
|
+
- regresión añadida/actualizada en `integrations/lifecycle/__tests__/watch.test.ts`.
|
|
2585
|
+
- smoke en Flux con binario local del core:
|
|
2586
|
+
- `changed=false`, `changedFiles=[]`, `evaluatedFiles=[]`, `gateOutcome=ALLOW`.
|
|
2587
|
+
- issue `#723` actualizada con evidencia técnica.
|
|
2588
|
+
- Pendiente para cierre:
|
|
2589
|
+
- publicar corte con este fix,
|
|
2590
|
+
- validar en Flux con `npx --yes --package pumuki@latest ...`,
|
|
2591
|
+
- mover `PUM-014` de `🚧` a `✅` y cerrar `#723`.
|
|
@@ -241,7 +241,12 @@ const shouldRetryAfterPolicyReconcile = (params: {
|
|
|
241
241
|
|
|
242
242
|
type HookStage = 'PRE_COMMIT' | 'PRE_PUSH';
|
|
243
243
|
type HookPolicyTrace = NonNullable<ReturnType<typeof resolvePolicyForStage>['trace']>;
|
|
244
|
-
const MANIFEST_GUARD_FILES = [
|
|
244
|
+
const MANIFEST_GUARD_FILES = [
|
|
245
|
+
'package.json',
|
|
246
|
+
'package-lock.json',
|
|
247
|
+
'pnpm-lock.yaml',
|
|
248
|
+
'yarn.lock',
|
|
249
|
+
] as const;
|
|
245
250
|
|
|
246
251
|
type ManifestGuardEntry = {
|
|
247
252
|
relativePath: (typeof MANIFEST_GUARD_FILES)[number];
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { createHash } from 'node:crypto';
|
|
2
|
+
import { existsSync, readFileSync, unlinkSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { join } from 'node:path';
|
|
2
4
|
import { setTimeout as sleepTimer } from 'node:timers/promises';
|
|
3
5
|
import { isSeverityAtLeast, type Severity } from '../../core/rules/Severity';
|
|
4
6
|
import type { GateScope } from '../git/runPlatformGateFacts';
|
|
@@ -125,6 +127,8 @@ const BLOCKED_REMEDIATION_BY_CODE: Readonly<Record<string, string>> = {
|
|
|
125
127
|
SDD_SESSION_INVALID: 'Refresca la sesión SDD y vuelve a intentar.',
|
|
126
128
|
OPENSPEC_MISSING: 'Instala OpenSpec y reintenta la validación.',
|
|
127
129
|
MCP_ENTERPRISE_RECEIPT_MISSING: 'Genera el receipt enterprise de MCP antes de continuar.',
|
|
130
|
+
MANIFEST_MUTATION_DETECTED:
|
|
131
|
+
'Validación no debe mutar package.json/lockfiles. Revisa wiring y realiza upgrades solo con comando explícito.',
|
|
128
132
|
};
|
|
129
133
|
|
|
130
134
|
const WATCH_POLICY_RECONCILE_CODES = new Set<string>([
|
|
@@ -142,6 +146,61 @@ const THRESHOLD_TO_SEVERITY: Record<LifecycleWatchSeverityThreshold, Severity> =
|
|
|
142
146
|
low: 'INFO',
|
|
143
147
|
};
|
|
144
148
|
|
|
149
|
+
const WATCH_MANIFEST_GUARD_FILES = [
|
|
150
|
+
'package.json',
|
|
151
|
+
'package-lock.json',
|
|
152
|
+
'pnpm-lock.yaml',
|
|
153
|
+
'yarn.lock',
|
|
154
|
+
] as const;
|
|
155
|
+
|
|
156
|
+
type WatchManifestGuardEntry = {
|
|
157
|
+
relativePath: (typeof WATCH_MANIFEST_GUARD_FILES)[number];
|
|
158
|
+
absolutePath: string;
|
|
159
|
+
existed: boolean;
|
|
160
|
+
contents: string;
|
|
161
|
+
};
|
|
162
|
+
|
|
163
|
+
const captureWatchManifestGuardSnapshot = (
|
|
164
|
+
repoRoot: string
|
|
165
|
+
): Array<WatchManifestGuardEntry> =>
|
|
166
|
+
WATCH_MANIFEST_GUARD_FILES.map((relativePath) => {
|
|
167
|
+
const absolutePath = join(repoRoot, relativePath);
|
|
168
|
+
const existed = existsSync(absolutePath);
|
|
169
|
+
return {
|
|
170
|
+
relativePath,
|
|
171
|
+
absolutePath,
|
|
172
|
+
existed,
|
|
173
|
+
contents: existed ? readFileSync(absolutePath, 'utf8') : '',
|
|
174
|
+
};
|
|
175
|
+
});
|
|
176
|
+
|
|
177
|
+
const restoreWatchManifestGuardSnapshot = (
|
|
178
|
+
snapshot: ReadonlyArray<WatchManifestGuardEntry>
|
|
179
|
+
): Array<string> => {
|
|
180
|
+
const mutated: Array<string> = [];
|
|
181
|
+
for (const entry of snapshot) {
|
|
182
|
+
const existsNow = existsSync(entry.absolutePath);
|
|
183
|
+
if (entry.existed) {
|
|
184
|
+
if (!existsNow) {
|
|
185
|
+
writeFileSync(entry.absolutePath, entry.contents, 'utf8');
|
|
186
|
+
mutated.push(entry.relativePath);
|
|
187
|
+
continue;
|
|
188
|
+
}
|
|
189
|
+
const current = readFileSync(entry.absolutePath, 'utf8');
|
|
190
|
+
if (current !== entry.contents) {
|
|
191
|
+
writeFileSync(entry.absolutePath, entry.contents, 'utf8');
|
|
192
|
+
mutated.push(entry.relativePath);
|
|
193
|
+
}
|
|
194
|
+
continue;
|
|
195
|
+
}
|
|
196
|
+
if (existsNow) {
|
|
197
|
+
unlinkSync(entry.absolutePath);
|
|
198
|
+
mutated.push(entry.relativePath);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return Array.from(new Set(mutated));
|
|
202
|
+
};
|
|
203
|
+
|
|
145
204
|
const toGateScope = (scope: LifecycleWatchScope): GateScope => {
|
|
146
205
|
if (scope === 'staged') {
|
|
147
206
|
return { kind: 'staged' };
|
|
@@ -314,6 +373,7 @@ export const runLifecycleWatch = async (
|
|
|
314
373
|
});
|
|
315
374
|
const changedFiles = collectChangedFilesFromFacts(facts);
|
|
316
375
|
const evaluatedFiles = collectEvaluatedFilesFromFacts(facts);
|
|
376
|
+
const scopeHasFileDelta = changedFiles.length > 0 || evaluatedFiles.length > 0;
|
|
317
377
|
const runEvaluation = async (): Promise<{
|
|
318
378
|
gateExitCode: number;
|
|
319
379
|
evidence: AiEvidenceV2_1 | undefined;
|
|
@@ -322,21 +382,52 @@ export const runLifecycleWatch = async (
|
|
|
322
382
|
gateOutcome: 'BLOCK' | 'WARN' | 'ALLOW' | 'NO_EVIDENCE';
|
|
323
383
|
topCodes: ReadonlyArray<string>;
|
|
324
384
|
}> => {
|
|
325
|
-
const
|
|
385
|
+
const manifestSnapshot = captureWatchManifestGuardSnapshot(repoRoot);
|
|
386
|
+
let gateExitCode = await activeDependencies.runPlatformGate({
|
|
326
387
|
policy: resolvedPolicy.policy,
|
|
327
388
|
policyTrace: resolvedPolicy.trace,
|
|
328
389
|
scope: gateScope,
|
|
329
390
|
silent: true,
|
|
330
391
|
});
|
|
331
392
|
const evidence = activeDependencies.readEvidence(repoRoot);
|
|
332
|
-
const
|
|
333
|
-
const
|
|
393
|
+
const allFindingsBase = evidence?.snapshot.findings ?? [];
|
|
394
|
+
const matchedFindingsBase = allFindingsBase.filter((finding) =>
|
|
334
395
|
isSeverityAtLeast(finding.severity, thresholdSeverity)
|
|
335
396
|
);
|
|
397
|
+
const manifestMutations = restoreWatchManifestGuardSnapshot(manifestSnapshot);
|
|
398
|
+
const manifestMutationFinding: SnapshotFinding | null =
|
|
399
|
+
manifestMutations.length > 0
|
|
400
|
+
? {
|
|
401
|
+
ruleId: 'governance.manifest.no-silent-mutation',
|
|
402
|
+
severity: 'ERROR',
|
|
403
|
+
code: 'MANIFEST_MUTATION_DETECTED',
|
|
404
|
+
message:
|
|
405
|
+
`Unexpected manifest mutation detected during watch and reverted: ${manifestMutations.join(', ')}.`,
|
|
406
|
+
file: manifestMutations[0] ?? 'package.json',
|
|
407
|
+
matchedBy: 'LifecycleWatch',
|
|
408
|
+
source: 'skills.backend.runtime-hygiene',
|
|
409
|
+
}
|
|
410
|
+
: null;
|
|
411
|
+
const allFindings = manifestMutationFinding
|
|
412
|
+
? [...allFindingsBase, manifestMutationFinding]
|
|
413
|
+
: allFindingsBase;
|
|
414
|
+
const matchedFindings = manifestMutationFinding
|
|
415
|
+
? [...matchedFindingsBase, manifestMutationFinding]
|
|
416
|
+
: matchedFindingsBase;
|
|
336
417
|
const rawGateOutcome =
|
|
337
418
|
evidence?.snapshot.outcome ??
|
|
338
419
|
(gateExitCode !== 0 ? 'BLOCK' : 'NO_EVIDENCE');
|
|
339
|
-
const gateOutcome =
|
|
420
|
+
const gateOutcome = manifestMutationFinding
|
|
421
|
+
? 'BLOCK'
|
|
422
|
+
: rawGateOutcome === 'PASS'
|
|
423
|
+
? 'ALLOW'
|
|
424
|
+
: rawGateOutcome;
|
|
425
|
+
if (manifestMutationFinding) {
|
|
426
|
+
gateExitCode = 1;
|
|
427
|
+
process.stderr.write(
|
|
428
|
+
`[pumuki][watch-manifest-guard] unexpected manifest mutation detected and reverted: ${manifestMutations.join(', ')}\n`
|
|
429
|
+
);
|
|
430
|
+
}
|
|
340
431
|
const topCodes = toTopCodes(matchedFindings);
|
|
341
432
|
return {
|
|
342
433
|
gateExitCode,
|
|
@@ -440,7 +531,7 @@ export const runLifecycleWatch = async (
|
|
|
440
531
|
|
|
441
532
|
lastTick = {
|
|
442
533
|
tick: ticks,
|
|
443
|
-
changed,
|
|
534
|
+
changed: scopeHasFileDelta,
|
|
444
535
|
evaluated: true,
|
|
445
536
|
stage,
|
|
446
537
|
scope,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.49",
|
|
4
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.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|