pumuki 6.3.52 → 6.3.53
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/README.md +11 -0
- package/integrations/config/skillsCustomRules.ts +4 -0
- package/integrations/evidence/repoState.ts +2 -0
- package/integrations/evidence/schema.ts +1 -0
- package/integrations/gate/evaluateAiGate.ts +3 -1
- package/integrations/lifecycle/cli.ts +6 -0
- package/integrations/lifecycle/packageInfo.ts +6 -0
- package/integrations/lifecycle/watch.ts +29 -3
- package/integrations/mcp/autoExecuteAiStart.ts +3 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -34,6 +34,7 @@ Install and bootstrap:
|
|
|
34
34
|
npm install --save-exact pumuki
|
|
35
35
|
npx --yes pumuki bootstrap --enterprise --agent=codex
|
|
36
36
|
npx --yes pumuki status
|
|
37
|
+
npx --yes pumuki doctor --json
|
|
37
38
|
```
|
|
38
39
|
|
|
39
40
|
Fallback (equivalent in pasos separados):
|
|
@@ -80,6 +81,16 @@ Expected behavior:
|
|
|
80
81
|
- `PRE_PUSH`: blocks if branch has no upstream tracking reference.
|
|
81
82
|
- `CI`: requires a valid diff range context (not `HEAD..HEAD` with ambiguous range).
|
|
82
83
|
|
|
84
|
+
Version drift quick check:
|
|
85
|
+
|
|
86
|
+
- `status --json` and `doctor --json` expose `version.effective`, `version.runtime`, `version.consumerInstalled`, `version.lifecycleInstalled`, `version.driftWarning`, and `version.alignmentCommand`.
|
|
87
|
+
- If `driftWarning` is not `null`, align the consumer with:
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm install --save-exact pumuki@6.3.52
|
|
91
|
+
npx --yes pumuki update --latest
|
|
92
|
+
```
|
|
93
|
+
|
|
83
94
|
## Why Pumuki
|
|
84
95
|
|
|
85
96
|
Modern teams need fast feedback with strict governance. Pumuki combines:
|
|
@@ -173,6 +173,10 @@ const computeBundleHash = (rules: ReadonlyArray<SkillsCompiledRule>): string =>
|
|
|
173
173
|
confidence: rule.confidence ?? null,
|
|
174
174
|
locked: rule.locked ?? false,
|
|
175
175
|
evaluationMode: rule.evaluationMode ?? null,
|
|
176
|
+
ast_node_ids:
|
|
177
|
+
rule.astNodeIds && rule.astNodeIds.length > 0
|
|
178
|
+
? [...new Set(rule.astNodeIds)].sort()
|
|
179
|
+
: null,
|
|
176
180
|
origin: rule.origin ?? null,
|
|
177
181
|
sourceSkill: rule.sourceSkill,
|
|
178
182
|
sourcePath: rule.sourcePath,
|
|
@@ -128,6 +128,7 @@ export const captureRepoState = (repoRoot: string): RepoState => {
|
|
|
128
128
|
const statusLines = toStatusLines(safeRunGit(repoRoot, ['status', '--short']) ?? '');
|
|
129
129
|
const staged = statusLines.filter((line) => line[0] && line[0] !== '?' && line[0] !== ' ').length;
|
|
130
130
|
const unstaged = statusLines.filter((line) => line[1] && line[1] !== ' ').length;
|
|
131
|
+
const pendingChanges = statusLines.length;
|
|
131
132
|
const { ahead, behind } = toAheadBehind(repoRoot, upstream);
|
|
132
133
|
const lifecycle = readLifecycleStatusSafe(repoRoot);
|
|
133
134
|
const versionMetadata = resolvePumukiVersionMetadata({ repoRoot });
|
|
@@ -146,6 +147,7 @@ export const captureRepoState = (repoRoot: string): RepoState => {
|
|
|
146
147
|
dirty: statusLines.length > 0,
|
|
147
148
|
staged: toCount(staged),
|
|
148
149
|
unstaged: toCount(unstaged),
|
|
150
|
+
pending_changes: toCount(pendingChanges),
|
|
149
151
|
},
|
|
150
152
|
lifecycle: {
|
|
151
153
|
installed: lifecycle.lifecycleState.installed === 'true',
|
|
@@ -770,7 +770,9 @@ const collectPreWriteCoherenceViolations = (params: {
|
|
|
770
770
|
}
|
|
771
771
|
|
|
772
772
|
if (params.preWriteWorktreeHygiene.enabled && params.repoState.git.available) {
|
|
773
|
-
const pendingChanges =
|
|
773
|
+
const pendingChanges =
|
|
774
|
+
params.repoState.git.pending_changes
|
|
775
|
+
?? (params.repoState.git.staged + params.repoState.git.unstaged);
|
|
774
776
|
if (pendingChanges >= params.preWriteWorktreeHygiene.blockThreshold) {
|
|
775
777
|
violations.push(
|
|
776
778
|
toErrorViolation(
|
|
@@ -1492,6 +1492,9 @@ const printDoctorReport = (
|
|
|
1492
1492
|
);
|
|
1493
1493
|
if (report.version.driftWarning) {
|
|
1494
1494
|
writeInfo(`[pumuki] version drift: ${report.version.driftWarning}`);
|
|
1495
|
+
if (report.version.alignmentCommand) {
|
|
1496
|
+
writeInfo(`[pumuki] version remediation: ${report.version.alignmentCommand}`);
|
|
1497
|
+
}
|
|
1495
1498
|
}
|
|
1496
1499
|
writeInfo(
|
|
1497
1500
|
`[pumuki] hooks path: ${report.hooksDirectory} (${report.hooksDirectoryResolution})`
|
|
@@ -2119,6 +2122,9 @@ export const runLifecycleCli = async (
|
|
|
2119
2122
|
);
|
|
2120
2123
|
if (status.version.driftWarning) {
|
|
2121
2124
|
writeInfo(`[pumuki] version drift: ${status.version.driftWarning}`);
|
|
2125
|
+
if (status.version.alignmentCommand) {
|
|
2126
|
+
writeInfo(`[pumuki] version remediation: ${status.version.alignmentCommand}`);
|
|
2127
|
+
}
|
|
2122
2128
|
}
|
|
2123
2129
|
writeInfo(`[pumuki] lifecycle installed: ${status.lifecycleState.installed ?? 'false'}`);
|
|
2124
2130
|
writeInfo(
|
|
@@ -33,8 +33,12 @@ export type LifecycleVersionReport = {
|
|
|
33
33
|
driftFromRuntime: boolean;
|
|
34
34
|
driftFromLifecycleInstalled: boolean;
|
|
35
35
|
driftWarning: string | null;
|
|
36
|
+
alignmentCommand: string | null;
|
|
36
37
|
};
|
|
37
38
|
|
|
39
|
+
export const buildLifecycleAlignmentCommand = (runtimeVersion: string): string =>
|
|
40
|
+
`npm install --save-exact pumuki@${runtimeVersion} && npx --yes --package pumuki@${runtimeVersion} pumuki install`;
|
|
41
|
+
|
|
38
42
|
export const resolvePumukiVersionMetadata = (params?: { repoRoot?: string }): PumukiVersionMetadata => {
|
|
39
43
|
const runtimeVersion = packageJson.version;
|
|
40
44
|
const repoRoot = params?.repoRoot;
|
|
@@ -92,5 +96,7 @@ export const buildLifecycleVersionReport = (params?: {
|
|
|
92
96
|
driftTargets.length > 0
|
|
93
97
|
? `Version drift detectado: effective=${metadata.resolvedVersion} ${driftTargets.join(' ')}.`
|
|
94
98
|
: null,
|
|
99
|
+
alignmentCommand:
|
|
100
|
+
driftTargets.length > 0 ? buildLifecycleAlignmentCommand(metadata.runtimeVersion) : null,
|
|
95
101
|
};
|
|
96
102
|
};
|
|
@@ -9,7 +9,7 @@ import { resolveFactsForGateScope } from '../git/runPlatformGateFacts';
|
|
|
9
9
|
import { resolvePolicyForStage, type ResolvedStagePolicy } from '../gate/stagePolicies';
|
|
10
10
|
import { readEvidence } from '../evidence/readEvidence';
|
|
11
11
|
import type { AiEvidenceV2_1, SnapshotFinding } from '../evidence/schema';
|
|
12
|
-
import { GitService } from '../git/GitService';
|
|
12
|
+
import { GitService, type IGitService } from '../git/GitService';
|
|
13
13
|
import type { Fact } from '../../core/facts/Fact';
|
|
14
14
|
import { ensureRuntimeArtifactsIgnored } from './artifacts';
|
|
15
15
|
import {
|
|
@@ -17,7 +17,11 @@ import {
|
|
|
17
17
|
emitGateBlockedNotification,
|
|
18
18
|
} from '../notifications/emitAuditSummaryNotification';
|
|
19
19
|
import { runPolicyReconcile } from './policyReconcile';
|
|
20
|
-
import {
|
|
20
|
+
import {
|
|
21
|
+
buildLifecycleAlignmentCommand,
|
|
22
|
+
resolvePumukiVersionMetadata,
|
|
23
|
+
type PumukiVersionMetadata,
|
|
24
|
+
} from './packageInfo';
|
|
21
25
|
|
|
22
26
|
export type LifecycleWatchStage = 'PRE_COMMIT' | 'PRE_PUSH' | 'CI';
|
|
23
27
|
export type LifecycleWatchScope = 'workingTree' | 'staged' | 'repoAndStaged' | 'repo';
|
|
@@ -59,6 +63,7 @@ export type LifecycleWatchResult = {
|
|
|
59
63
|
source: PumukiVersionMetadata['source'];
|
|
60
64
|
driftFromRuntime: boolean;
|
|
61
65
|
driftWarning: string | null;
|
|
66
|
+
alignmentCommand: string | null;
|
|
62
67
|
};
|
|
63
68
|
stage: LifecycleWatchStage;
|
|
64
69
|
scope: LifecycleWatchScope;
|
|
@@ -91,6 +96,20 @@ type LifecycleWatchDependencies = {
|
|
|
91
96
|
|
|
92
97
|
const defaultGitService = new GitService();
|
|
93
98
|
|
|
99
|
+
class RepoScopedGitService extends GitService implements IGitService {
|
|
100
|
+
constructor(private readonly repoRoot: string) {
|
|
101
|
+
super();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
override runGit(args: ReadonlyArray<string>, cwd?: string): string {
|
|
105
|
+
return super.runGit(args, cwd ?? this.repoRoot);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
override resolveRepoRoot(): string {
|
|
109
|
+
return this.repoRoot;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
94
113
|
const defaultDependencies: LifecycleWatchDependencies = {
|
|
95
114
|
resolveRepoRoot: () => defaultGitService.resolveRepoRoot(),
|
|
96
115
|
readChangeToken: (repoRoot) =>
|
|
@@ -301,6 +320,7 @@ export const runLifecycleWatch = async (
|
|
|
301
320
|
...dependencies,
|
|
302
321
|
};
|
|
303
322
|
const repoRoot = params?.repoRoot ?? activeDependencies.resolveRepoRoot();
|
|
323
|
+
const repoGitService = new RepoScopedGitService(repoRoot);
|
|
304
324
|
const versionMetadata = activeDependencies.resolvePumukiVersionMetadata({ repoRoot });
|
|
305
325
|
const driftFromRuntime = versionMetadata.resolvedVersion !== versionMetadata.runtimeVersion;
|
|
306
326
|
const driftWarning = driftFromRuntime
|
|
@@ -368,7 +388,7 @@ export const runLifecycleWatch = async (
|
|
|
368
388
|
const gateScope = toGateScope(scope);
|
|
369
389
|
const facts = await activeDependencies.resolveFactsForGateScope({
|
|
370
390
|
scope: gateScope,
|
|
371
|
-
git:
|
|
391
|
+
git: repoGitService,
|
|
372
392
|
});
|
|
373
393
|
const changedFiles = collectChangedFilesFromFacts(facts);
|
|
374
394
|
const evaluatedFiles = collectEvaluatedFilesFromFacts(facts);
|
|
@@ -389,6 +409,9 @@ export const runLifecycleWatch = async (
|
|
|
389
409
|
policyTrace: resolvedPolicy.trace,
|
|
390
410
|
scope: gateScope,
|
|
391
411
|
silent: true,
|
|
412
|
+
services: {
|
|
413
|
+
git: repoGitService,
|
|
414
|
+
},
|
|
392
415
|
});
|
|
393
416
|
const evidence = activeDependencies.readEvidence(repoRoot);
|
|
394
417
|
const allFindingsBase = evidence?.snapshot.findings ?? [];
|
|
@@ -566,6 +589,9 @@ export const runLifecycleWatch = async (
|
|
|
566
589
|
source: versionMetadata.source,
|
|
567
590
|
driftFromRuntime,
|
|
568
591
|
driftWarning,
|
|
592
|
+
alignmentCommand: driftFromRuntime
|
|
593
|
+
? buildLifecycleAlignmentCommand(versionMetadata.runtimeVersion)
|
|
594
|
+
: null,
|
|
569
595
|
},
|
|
570
596
|
stage,
|
|
571
597
|
scope,
|
|
@@ -31,6 +31,7 @@ const toHumanMessage = (params: {
|
|
|
31
31
|
const isEvidenceCode = (code: string): boolean =>
|
|
32
32
|
code === 'EVIDENCE_MISSING'
|
|
33
33
|
|| code === 'EVIDENCE_INVALID'
|
|
34
|
+
|| code === 'EVIDENCE_CHAIN_INVALID'
|
|
34
35
|
|| code === 'EVIDENCE_STALE'
|
|
35
36
|
|| code === 'EVIDENCE_ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES'
|
|
36
37
|
|| code === 'EVIDENCE_SKILLS_CONTRACT_INCOMPLETE'
|
|
@@ -67,10 +68,11 @@ const nextActionFromViolation = (
|
|
|
67
68
|
switch (violation.code) {
|
|
68
69
|
case 'EVIDENCE_MISSING':
|
|
69
70
|
case 'EVIDENCE_INVALID':
|
|
71
|
+
case 'EVIDENCE_CHAIN_INVALID':
|
|
70
72
|
case 'EVIDENCE_STALE':
|
|
71
73
|
return {
|
|
72
74
|
kind: 'run_command',
|
|
73
|
-
message: '
|
|
75
|
+
message: 'Regenera o refresca evidencia y vuelve a evaluar PRE_WRITE.',
|
|
74
76
|
command: 'npx --yes --package pumuki@latest pumuki sdd validate --stage=PRE_WRITE --json',
|
|
75
77
|
};
|
|
76
78
|
case 'EVIDENCE_ACTIVE_RULE_IDS_EMPTY_FOR_CODE_CHANGES':
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.53",
|
|
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": {
|