pumuki 6.3.31 → 6.3.33

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.
@@ -7,7 +7,7 @@
7
7
  ## Estado actual
8
8
  - Plan activo: `docs/seguimiento-completo-validacion-ruralgo-03-03-2026.md`
9
9
  - Estado del plan: EN CURSO
10
- - Task activa (`🚧`): `P12.F2.T51` (publicar release con el hardening `#551` y cerrar trazabilidad final en canónico + master).
10
+ - Task activa (`🚧`): `P12.F2.T55` (publicar patch release del contrato de compatibilidad `doctor --deep`, issue `#565`).
11
11
 
12
12
  ## Historial resumido
13
13
  - No se mantienen MDs históricos de seguimiento en este repositorio.
@@ -1736,11 +1736,55 @@ Criterio de salida F5:
1736
1736
  - `npm run -s validation:contract-suite:enterprise -- --json`
1737
1737
  - `npm run -s validation:package-manifest`
1738
1738
 
1739
- - 🚧 `P12.F2.T51` Publicar release que incluya el hardening `#551` (suite contractual) y dejar trazabilidad final en canónico + master.
1739
+ - `P12.F2.T51` Publicar release que incluya el hardening `#551` (suite contractual) y dejar trazabilidad final en canónico + master.
1740
+ - cierre ejecutado:
1741
+ - rama release creada y mergeada: `release/6.3.31` -> `#555` (`https://github.com/SwiftEnProfundidad/ast-intelligence-hooks/pull/555`).
1742
+ - publicación npm completada: `pumuki@6.3.31`.
1743
+ - issue `#551` cerrada tras merge de `#553` y release publicada.
1744
+ - evidencia:
1745
+ - `npm publish --access public`
1746
+ - `npm view pumuki version` => `6.3.31`
1747
+ - `gh pr view 555 --json state,mergeCommit,url`
1748
+
1749
+ - ✅ `P12.F2.T52` Ejecutar siguiente iteración técnica post-release `6.3.31`: ampliar la suite contractual multi-repo con fixture adicional y cobertura de regresión.
1750
+ - cierre ejecutado:
1751
+ - issue creada y cerrada: `#557`.
1752
+ - rama técnica creada y mergeada: `feature/557-contract-suite-repeat-profile` -> `#558` (`https://github.com/SwiftEnProfundidad/ast-intelligence-hooks/pull/558`).
1753
+ - commit de merge en `develop`: `5f0302c`.
1754
+ - evidencia:
1755
+ - `npx --yes tsx@4.21.0 --test scripts/__tests__/enterprise-contract-suite-contract.test.ts scripts/__tests__/enterprise-contract-suite-args-lib.test.ts scripts/__tests__/enterprise-contract-suite-report-lib.test.ts`
1756
+ - `npm run -s typecheck`
1757
+ - `npm run -s validation:contract-suite:enterprise -- --json`
1758
+ - `npm run -s validation:tracking-single-active`
1759
+
1760
+ - ✅ `P12.F2.T53` Publicar patch release con la ampliación de suite contractual (`#557`) y dejar disponibilidad inmediata para consumidores.
1761
+ - cierre ejecutado:
1762
+ - rama release creada y mergeada: `release/6.3.32` -> `#560` (`https://github.com/SwiftEnProfundidad/ast-intelligence-hooks/pull/560`).
1763
+ - publicación npm completada: `pumuki@6.3.32`.
1764
+ - evidencia:
1765
+ - `npx --yes tsx@4.21.0 --test scripts/__tests__/enterprise-contract-suite-contract.test.ts scripts/__tests__/enterprise-contract-suite-args-lib.test.ts scripts/__tests__/enterprise-contract-suite-report-lib.test.ts`
1766
+ - `npm run -s typecheck`
1767
+ - `npm run -s validation:contract-suite:enterprise -- --json`
1768
+ - `npm run -s validation:package-manifest`
1769
+ - `npm publish --access public`
1770
+ - `npm view pumuki version` => `6.3.32`
1771
+
1772
+ - ✅ `P12.F2.T54` Ejecutar siguiente mejora estratégica: contrato explícito de compatibilidad (pumuki/openspec/hooks/adapters) con validación automática en `doctor`.
1773
+ - cierre ejecutado:
1774
+ - issue creada y cerrada: `#562`.
1775
+ - rama técnica creada y mergeada: `feature/562-doctor-deep-compatibility-contract` -> `#563` (`https://github.com/SwiftEnProfundidad/ast-intelligence-hooks/pull/563`).
1776
+ - commit de merge en `develop`: `a1df815`.
1777
+ - evidencia:
1778
+ - `npx --yes tsx@4.21.0 --test integrations/lifecycle/__tests__/doctor.test.ts integrations/lifecycle/__tests__/cli.test.ts`
1779
+ - `npm run -s typecheck`
1780
+ - `npm run -s validation:contract-suite:enterprise -- --json`
1781
+ - `npm run -s validation:tracking-single-active`
1782
+
1783
+ - 🚧 `P12.F2.T55` Publicar patch release con el contrato de compatibilidad de `doctor --deep` ya mergeado en `#563`.
1740
1784
  - salida esperada:
1741
- - versión npm publicada con el MVP de suite contractual multi-repo.
1742
- - canónico RuralGO y master plan alineados con refs de release.
1743
- - estado operativo preparado para siguiente bloque de mejoras.
1785
+ - issue de release creada con alcance/doD verificable (`#565`).
1786
+ - versión npm nueva publicada con el fix de `#562`.
1787
+ - trazabilidad cerrada en plan activo + registro maestro con evidencia de publicación.
1744
1788
 
1745
1789
  Criterio de salida F6:
1746
1790
  - veredicto final trazable y cierre administrativo completo.
@@ -6,6 +6,11 @@ import { getPumukiHooksStatus } from './hookManager';
6
6
  import { LifecycleGitService, type ILifecycleGitService } from './gitService';
7
7
  import { getCurrentPumukiVersion } from './packageInfo';
8
8
  import { readLifecycleState, type LifecycleState } from './state';
9
+ import {
10
+ detectOpenSpecInstallation,
11
+ evaluateOpenSpecCompatibility,
12
+ isOpenSpecProjectInitialized,
13
+ } from '../sdd/openSpecCli';
9
14
 
10
15
  export type DoctorIssueSeverity = 'warning' | 'error';
11
16
 
@@ -18,7 +23,8 @@ export type DoctorDeepCheckId =
18
23
  | 'upstream-readiness'
19
24
  | 'adapter-wiring'
20
25
  | 'policy-drift'
21
- | 'evidence-source-drift';
26
+ | 'evidence-source-drift'
27
+ | 'compatibility-contract';
22
28
 
23
29
  export type DoctorDeepCheck = {
24
30
  id: DoctorDeepCheckId;
@@ -33,6 +39,30 @@ export type DoctorDeepReport = {
33
39
  enabled: true;
34
40
  checks: ReadonlyArray<DoctorDeepCheck>;
35
41
  blocking: boolean;
42
+ contract: DoctorCompatibilityContract;
43
+ };
44
+
45
+ export type DoctorCompatibilityContract = {
46
+ overall: 'compatible' | 'incompatible';
47
+ pumuki: {
48
+ installed: boolean;
49
+ version: string;
50
+ };
51
+ openspec: {
52
+ required: boolean;
53
+ installed: boolean;
54
+ version: string | null;
55
+ minimumVersion: string;
56
+ compatible: boolean;
57
+ };
58
+ hooks: {
59
+ managed: boolean;
60
+ managedCount: number;
61
+ totalCount: number;
62
+ };
63
+ adapter: {
64
+ valid: boolean;
65
+ };
36
66
  };
37
67
 
38
68
  export type LifecycleDoctorReport = {
@@ -457,21 +487,128 @@ const evaluateEvidenceSourceDriftCheck = (params: {
457
487
  });
458
488
  };
459
489
 
490
+ const buildCompatibilityContract = (params: {
491
+ repoRoot: string;
492
+ lifecycleState: LifecycleState;
493
+ hookStatus: ReturnType<typeof getPumukiHooksStatus>;
494
+ adapterCheck: DoctorDeepCheck;
495
+ }): DoctorCompatibilityContract => {
496
+ const hooks = Object.values(params.hookStatus);
497
+ const managedCount = hooks.filter((entry) => entry.managedBlockPresent).length;
498
+ const totalCount = hooks.length;
499
+ const hooksManaged = totalCount > 0 && managedCount === totalCount;
500
+
501
+ const openSpecRequired = isOpenSpecProjectInitialized(params.repoRoot);
502
+ const openSpecInstalled = detectOpenSpecInstallation(params.repoRoot);
503
+ const openSpecCompatibility = evaluateOpenSpecCompatibility(openSpecInstalled);
504
+ const openSpecCompatible = openSpecRequired ? openSpecCompatibility.compatible : true;
505
+
506
+ const adapterValid = params.adapterCheck.status === 'pass';
507
+ const pumukiInstalled = params.lifecycleState.installed === 'true';
508
+ const overallCompatible =
509
+ pumukiInstalled && hooksManaged && adapterValid && openSpecCompatible;
510
+
511
+ return {
512
+ overall: overallCompatible ? 'compatible' : 'incompatible',
513
+ pumuki: {
514
+ installed: pumukiInstalled,
515
+ version: getCurrentPumukiVersion(),
516
+ },
517
+ openspec: {
518
+ required: openSpecRequired,
519
+ installed: openSpecInstalled.installed,
520
+ version: openSpecInstalled.version ?? null,
521
+ minimumVersion: openSpecCompatibility.minimumVersion,
522
+ compatible: openSpecCompatible,
523
+ },
524
+ hooks: {
525
+ managed: hooksManaged,
526
+ managedCount,
527
+ totalCount,
528
+ },
529
+ adapter: {
530
+ valid: adapterValid,
531
+ },
532
+ };
533
+ };
534
+
535
+ const evaluateCompatibilityContractCheck = (
536
+ contract: DoctorCompatibilityContract
537
+ ): DoctorDeepCheck => {
538
+ if (contract.overall === 'compatible') {
539
+ return buildDeepCheck({
540
+ id: 'compatibility-contract',
541
+ status: 'pass',
542
+ severity: 'info',
543
+ message: 'Compatibility contract is satisfied for pumuki/openspec/hooks/adapter.',
544
+ metadata: {
545
+ pumuki_installed: contract.pumuki.installed,
546
+ openspec_required: contract.openspec.required,
547
+ openspec_compatible: contract.openspec.compatible,
548
+ hooks_managed: contract.hooks.managed,
549
+ adapter_valid: contract.adapter.valid,
550
+ },
551
+ });
552
+ }
553
+
554
+ const remediation: string[] = [];
555
+ if (!contract.pumuki.installed) {
556
+ remediation.push('Run "pumuki install" to restore lifecycle state.');
557
+ }
558
+ if (!contract.hooks.managed) {
559
+ remediation.push('Regenerate managed hooks with "pumuki install".');
560
+ }
561
+ if (!contract.adapter.valid) {
562
+ remediation.push('Repair adapter wiring with "pumuki adapter install --agent=codex".');
563
+ }
564
+ if (contract.openspec.required && !contract.openspec.compatible) {
565
+ remediation.push(
566
+ `Install or upgrade OpenSpec to >= ${contract.openspec.minimumVersion} before enterprise validation.`
567
+ );
568
+ }
569
+
570
+ return buildDeepCheck({
571
+ id: 'compatibility-contract',
572
+ status: 'fail',
573
+ severity: 'warning',
574
+ message: 'Compatibility contract is not satisfied for one or more required components.',
575
+ remediation: remediation.join(' '),
576
+ metadata: {
577
+ pumuki_installed: contract.pumuki.installed,
578
+ openspec_required: contract.openspec.required,
579
+ openspec_compatible: contract.openspec.compatible,
580
+ hooks_managed: contract.hooks.managed,
581
+ adapter_valid: contract.adapter.valid,
582
+ },
583
+ });
584
+ };
585
+
460
586
  const buildDoctorDeepReport = (params: {
461
587
  git: ILifecycleGitService;
462
588
  repoRoot: string;
589
+ lifecycleState: LifecycleState;
590
+ hookStatus: ReturnType<typeof getPumukiHooksStatus>;
463
591
  }): DoctorDeepReport => {
592
+ const adapterCheck = evaluateAdapterWiringCheck(params.repoRoot);
593
+ const compatibilityContract = buildCompatibilityContract({
594
+ repoRoot: params.repoRoot,
595
+ lifecycleState: params.lifecycleState,
596
+ hookStatus: params.hookStatus,
597
+ adapterCheck,
598
+ });
599
+
464
600
  const checks: DoctorDeepCheck[] = [
465
601
  evaluateUpstreamReadinessCheck({
466
602
  git: params.git,
467
603
  repoRoot: params.repoRoot,
468
604
  }),
469
- evaluateAdapterWiringCheck(params.repoRoot),
605
+ adapterCheck,
470
606
  evaluatePolicyDriftCheck(params.repoRoot),
471
607
  evaluateEvidenceSourceDriftCheck({
472
608
  git: params.git,
473
609
  repoRoot: params.repoRoot,
474
610
  }),
611
+ evaluateCompatibilityContractCheck(compatibilityContract),
475
612
  ];
476
613
 
477
614
  return {
@@ -480,6 +617,7 @@ const buildDoctorDeepReport = (params: {
480
617
  blocking: checks.some(
481
618
  (check) => check.status === 'fail' && check.severity === 'error'
482
619
  ),
620
+ contract: compatibilityContract,
483
621
  };
484
622
  };
485
623
 
@@ -504,6 +642,8 @@ export const runLifecycleDoctor = (params?: {
504
642
  ? buildDoctorDeepReport({
505
643
  git,
506
644
  repoRoot,
645
+ lifecycleState,
646
+ hookStatus,
507
647
  })
508
648
  : undefined;
509
649
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.31",
3
+ "version": "6.3.33",
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": {
@@ -1,4 +1,4 @@
1
- export type EnterpriseContractProfileId = 'minimal' | 'block';
1
+ export type EnterpriseContractProfileId = 'minimal' | 'block' | 'minimal-repeat';
2
2
 
3
3
  export type EnterpriseContractProfileSpec = {
4
4
  id: EnterpriseContractProfileId;
@@ -29,3 +29,21 @@ export type EnterpriseContractSuiteOptions = {
29
29
  summaryPath: string;
30
30
  printJson: boolean;
31
31
  };
32
+
33
+ export const resolveEnterpriseContractProfiles = (): ReadonlyArray<EnterpriseContractProfileSpec> => [
34
+ {
35
+ id: 'minimal',
36
+ mode: 'minimal',
37
+ expectedExitCode: 1,
38
+ },
39
+ {
40
+ id: 'block',
41
+ mode: 'block',
42
+ expectedExitCode: 0,
43
+ },
44
+ {
45
+ id: 'minimal-repeat',
46
+ mode: 'minimal',
47
+ expectedExitCode: 1,
48
+ },
49
+ ];
@@ -8,27 +8,13 @@ import {
8
8
  renderEnterpriseContractSummary,
9
9
  } from './enterprise-contract-suite-report-lib';
10
10
  import type {
11
- EnterpriseContractProfileResult,
12
11
  EnterpriseContractProfileSpec,
12
+ EnterpriseContractProfileResult,
13
13
  } from './enterprise-contract-suite-contract';
14
+ import { resolveEnterpriseContractProfiles } from './enterprise-contract-suite-contract';
14
15
  import { ensureDirectory } from './package-install-smoke-file-lib';
15
16
  import { runCommand } from './package-install-smoke-command-lib';
16
17
 
17
- const PROFILE_SPECS: ReadonlyArray<EnterpriseContractProfileSpec> = [
18
- {
19
- id: 'minimal',
20
- mode: 'minimal',
21
- // The minimal fixture intentionally omits platform skill contracts to assert strict governance blocking.
22
- expectedExitCode: 1,
23
- },
24
- {
25
- id: 'block',
26
- mode: 'block',
27
- // The block fixture is expected to complete successfully as a deterministic BLOCK smoke scenario.
28
- expectedExitCode: 0,
29
- },
30
- ];
31
-
32
18
  const runProfile = (
33
19
  repoRoot: string,
34
20
  profile: EnterpriseContractProfileSpec
@@ -58,7 +44,9 @@ const writeTextFile = (repoRoot: string, relativePath: string, content: string):
58
44
 
59
45
  const main = (): number => {
60
46
  const options = parseEnterpriseContractSuiteArgs(process.argv.slice(2));
61
- const results = PROFILE_SPECS.map((profile) => runProfile(options.repoRoot, profile));
47
+ const results = resolveEnterpriseContractProfiles().map((profile) =>
48
+ runProfile(options.repoRoot, profile)
49
+ );
62
50
 
63
51
  const report = buildEnterpriseContractReport({
64
52
  repoRoot: options.repoRoot,