pumuki 6.3.110 → 6.3.111
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,12 +6,12 @@ This project follows [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
|
6
6
|
|
|
7
7
|
## [Unreleased]
|
|
8
8
|
|
|
9
|
-
## [6.3.
|
|
9
|
+
## [6.3.111] - 2026-04-23
|
|
10
10
|
|
|
11
11
|
### Fixed
|
|
12
12
|
|
|
13
|
-
-
|
|
14
|
-
- **
|
|
13
|
+
- **Alignment commands now respect the consumer runtime declaration:** `status`, `doctor` and the lifecycle helpers prepend the matching Node runtime switch when the consumer declares `volta`, `.nvmrc`, or `package.json.engines.node` and the current shell Node does not match.
|
|
14
|
+
- **Reproducible remediation stays repo-aware:** the suggested command keeps the consumer's runtime manager in the loop before the Pumuki install/alignment step, so fixes stay tied to the repo that is being audited.
|
|
15
15
|
|
|
16
16
|
## [6.3.102] - 2026-04-22
|
|
17
17
|
|
|
@@ -6,11 +6,10 @@ This file keeps only the operational highlights and rollout notes that matter wh
|
|
|
6
6
|
|
|
7
7
|
## 2026-04 (CLI stability and macOS notifications)
|
|
8
8
|
|
|
9
|
-
### 2026-04-23 (v6.3.
|
|
9
|
+
### 2026-04-23 (v6.3.111)
|
|
10
10
|
|
|
11
|
-
- **
|
|
12
|
-
- **
|
|
13
|
-
- **Rollout recomendado:** publicar `pumuki@6.3.110`, repin inmediato en `RuralGo` y revalidar `status` / `doctor` para cerrar `PUMUKI-INC-084`.
|
|
11
|
+
- **Runtime-aware remediation:** `alignmentCommand` now respects the consumer's declared Node runtime when the shell Node does not match, using `volta`, `.nvmrc`, or `package.json.engines.node` as the source of truth.
|
|
12
|
+
- **Rollout recommended:** publish `pumuki@6.3.111`, repin the active consumer, and revalidate `status` / `doctor` to confirm the consumer runtime is aligned before following the remediation command.
|
|
14
13
|
|
|
15
14
|
### 2026-04-22 (v6.3.102)
|
|
16
15
|
|
|
@@ -174,7 +174,7 @@ Interpretation contract:
|
|
|
174
174
|
- `consumerInstalled`: version installed in the consumer repository.
|
|
175
175
|
- `lifecycleInstalled`: version recorded in managed lifecycle metadata.
|
|
176
176
|
- `driftWarning`: compact human-readable explanation when those values diverge.
|
|
177
|
-
- `alignmentCommand`: exact remediation command to align dependency and lifecycle state with the current runtime version.
|
|
177
|
+
- `alignmentCommand`: exact remediation command to align dependency and lifecycle state with the current runtime version. When the consumer repo declares a Node runtime via `volta`, `.nvmrc`, or `package.json.engines.node`, this command prepends the matching runtime switch before the Pumuki install step.
|
|
178
178
|
- `pathExecutionHazard`: boolean flag raised when the repo root contains the platform `PATH` delimiter and `npx/npm exec` can fail to resolve `pumuki`.
|
|
179
179
|
- `pathExecutionWarning`: compact warning explaining why `PATH` resolution is unsafe in that repo.
|
|
180
180
|
- `pathExecutionWorkaroundCommand`: safe local-node entrypoint to use when `pathExecutionHazard=true`.
|
package/docs/product/USAGE.md
CHANGED
|
@@ -403,7 +403,7 @@ How to read it:
|
|
|
403
403
|
- `lifecycleInstalled`: version persisted in managed lifecycle state.
|
|
404
404
|
- `source`: source chosen to compute `effective`.
|
|
405
405
|
- `driftWarning`: compact explanation when those values diverge.
|
|
406
|
-
- `alignmentCommand`: exact command to align consumer dependency and lifecycle state with the current runtime.
|
|
406
|
+
- `alignmentCommand`: exact command to align consumer dependency and lifecycle state with the current runtime. If the consumer declares Node via `volta`, `.nvmrc`, or `package.json.engines.node`, the command prepends the matching runtime switch before the Pumuki install step.
|
|
407
407
|
- `pathExecutionHazard`: tells you whether the repo root itself can break `PATH`-based execution.
|
|
408
408
|
- `pathExecutionWarning`: compact explanation of that hazard.
|
|
409
409
|
- `pathExecutionWorkaroundCommand`: safe local-node entrypoint to use when `PATH` execution is unsafe.
|
|
@@ -49,15 +49,126 @@ const hasPathExecutionHazard = (repoRoot?: string): boolean =>
|
|
|
49
49
|
repoRoot.trim().length > 0 &&
|
|
50
50
|
repoRoot.includes(delimiter);
|
|
51
51
|
|
|
52
|
+
type ConsumerNodeRuntimeSpec = {
|
|
53
|
+
version: string;
|
|
54
|
+
source: 'volta' | '.nvmrc' | 'package.engines';
|
|
55
|
+
commandPrefix: 'volta' | 'nvm';
|
|
56
|
+
};
|
|
57
|
+
|
|
58
|
+
const normalizeNodeVersionToken = (value: string): string =>
|
|
59
|
+
value.trim().replace(/^node@/i, '').replace(/^v/i, '');
|
|
60
|
+
|
|
61
|
+
const extractNodeVersionToken = (value: string): string | null => {
|
|
62
|
+
const normalized = normalizeNodeVersionToken(value);
|
|
63
|
+
const exactVersion = normalized.match(/\d+\.\d+\.\d+/)?.[0];
|
|
64
|
+
if (exactVersion) {
|
|
65
|
+
return exactVersion;
|
|
66
|
+
}
|
|
67
|
+
const majorOnly = normalized.match(/^\d+$/)?.[0];
|
|
68
|
+
return majorOnly ?? null;
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
const isRecord = (value: unknown): value is Record<string, unknown> =>
|
|
72
|
+
typeof value === 'object' && value !== null && !Array.isArray(value);
|
|
73
|
+
|
|
74
|
+
const readNestedString = (
|
|
75
|
+
source: Record<string, unknown>,
|
|
76
|
+
path: ReadonlyArray<string>
|
|
77
|
+
): string | undefined => {
|
|
78
|
+
let cursor: unknown = source;
|
|
79
|
+
for (const segment of path) {
|
|
80
|
+
if (!isRecord(cursor)) {
|
|
81
|
+
return undefined;
|
|
82
|
+
}
|
|
83
|
+
cursor = cursor[segment];
|
|
84
|
+
}
|
|
85
|
+
return typeof cursor === 'string' && cursor.trim().length > 0 ? cursor.trim() : undefined;
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const readConsumerNodeRuntimeSpec = (repoRoot?: string): ConsumerNodeRuntimeSpec | null => {
|
|
89
|
+
if (typeof repoRoot !== 'string' || repoRoot.trim().length === 0) {
|
|
90
|
+
return null;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
const packageJsonPath = join(repoRoot, 'package.json');
|
|
94
|
+
if (existsSync(packageJsonPath)) {
|
|
95
|
+
try {
|
|
96
|
+
const parsed = JSON.parse(readFileSync(packageJsonPath, 'utf8')) as unknown;
|
|
97
|
+
if (isRecord(parsed)) {
|
|
98
|
+
const voltaNode = readNestedString(parsed, ['volta', 'node']);
|
|
99
|
+
const voltaVersion = voltaNode ? extractNodeVersionToken(voltaNode) : null;
|
|
100
|
+
if (voltaVersion) {
|
|
101
|
+
return {
|
|
102
|
+
version: voltaVersion,
|
|
103
|
+
source: 'volta',
|
|
104
|
+
commandPrefix: 'volta',
|
|
105
|
+
};
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
const enginesNode = readNestedString(parsed, ['engines', 'node']);
|
|
109
|
+
const enginesVersion = enginesNode ? extractNodeVersionToken(enginesNode) : null;
|
|
110
|
+
if (enginesVersion) {
|
|
111
|
+
return {
|
|
112
|
+
version: enginesVersion,
|
|
113
|
+
source: 'package.engines',
|
|
114
|
+
commandPrefix: 'nvm',
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
} catch {
|
|
119
|
+
return null;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const nvmrcPath = join(repoRoot, '.nvmrc');
|
|
124
|
+
if (existsSync(nvmrcPath)) {
|
|
125
|
+
try {
|
|
126
|
+
const nvmrcVersion = extractNodeVersionToken(readFileSync(nvmrcPath, 'utf8'));
|
|
127
|
+
if (nvmrcVersion) {
|
|
128
|
+
return {
|
|
129
|
+
version: nvmrcVersion,
|
|
130
|
+
source: '.nvmrc',
|
|
131
|
+
commandPrefix: 'nvm',
|
|
132
|
+
};
|
|
133
|
+
}
|
|
134
|
+
} catch {
|
|
135
|
+
return null;
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
return null;
|
|
140
|
+
};
|
|
141
|
+
|
|
142
|
+
const buildConsumerNodeAlignmentCommand = (repoRoot?: string): string | null => {
|
|
143
|
+
const runtimeSpec = readConsumerNodeRuntimeSpec(repoRoot);
|
|
144
|
+
if (!runtimeSpec) {
|
|
145
|
+
return null;
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
const currentNodeVersion = normalizeNodeVersionToken(process.version);
|
|
149
|
+
if (currentNodeVersion === runtimeSpec.version) {
|
|
150
|
+
return null;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
if (runtimeSpec.commandPrefix === 'volta') {
|
|
154
|
+
return `volta install node@${runtimeSpec.version} && volta pin node@${runtimeSpec.version}`;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
return `nvm install ${runtimeSpec.version} && nvm use ${runtimeSpec.version}`;
|
|
158
|
+
};
|
|
159
|
+
|
|
52
160
|
export const buildLifecycleAlignmentCommand = (
|
|
53
161
|
runtimeVersion: string,
|
|
54
162
|
repoRoot?: string
|
|
55
163
|
): string => {
|
|
164
|
+
const consumerNodeAlignmentCommand = buildConsumerNodeAlignmentCommand(repoRoot);
|
|
56
165
|
const installStep = `npm install --save-exact pumuki@${runtimeVersion}`;
|
|
57
166
|
const runStep = hasPathExecutionHazard(repoRoot)
|
|
58
167
|
? `${buildLocalPumukiCommand()} install`
|
|
59
168
|
: `npx --yes --package pumuki@${runtimeVersion} pumuki install`;
|
|
60
|
-
return
|
|
169
|
+
return [consumerNodeAlignmentCommand, installStep, runStep]
|
|
170
|
+
.filter((value): value is string => typeof value === 'string' && value.length > 0)
|
|
171
|
+
.join(' && ');
|
|
61
172
|
};
|
|
62
173
|
|
|
63
174
|
export const resolvePumukiVersionMetadata = (params?: { repoRoot?: string }): PumukiVersionMetadata => {
|
|
@@ -114,11 +225,17 @@ export const buildLifecycleVersionReport = (params?: {
|
|
|
114
225
|
const driftFromConsumerInstalled =
|
|
115
226
|
metadata.consumerInstalledVersion !== null &&
|
|
116
227
|
metadata.consumerInstalledVersion !== metadata.runtimeVersion;
|
|
228
|
+
const consumerNodeSpec = readConsumerNodeRuntimeSpec(params?.repoRoot);
|
|
229
|
+
const consumerNodeVersion = consumerNodeSpec?.version ?? null;
|
|
230
|
+
const currentNodeVersion = normalizeNodeVersionToken(process.version);
|
|
231
|
+
const driftFromConsumerNode =
|
|
232
|
+
consumerNodeVersion !== null && currentNodeVersion !== consumerNodeVersion;
|
|
117
233
|
const driftFromLifecycleInstalled =
|
|
118
234
|
lifecycleInstalled !== null && metadata.resolvedVersion !== lifecycleInstalled;
|
|
119
235
|
const driftTargets = [
|
|
120
236
|
driftFromRuntime ? `runtime=${metadata.runtimeVersion}` : null,
|
|
121
237
|
driftFromConsumerInstalled ? `consumer=${metadata.consumerInstalledVersion}` : null,
|
|
238
|
+
driftFromConsumerNode ? `node=${consumerNodeVersion}` : null,
|
|
122
239
|
driftFromLifecycleInstalled ? `lifecycle=${lifecycleInstalled}` : null,
|
|
123
240
|
].filter((value): value is string => value !== null);
|
|
124
241
|
const pathExecutionHazard = hasPathExecutionHazard(params?.repoRoot);
|
|
@@ -736,7 +736,7 @@ export const runLifecycleWatch = async (
|
|
|
736
736
|
driftFromRuntime,
|
|
737
737
|
driftWarning,
|
|
738
738
|
alignmentCommand: driftFromRuntime
|
|
739
|
-
? buildLifecycleAlignmentCommand(versionMetadata.runtimeVersion)
|
|
739
|
+
? buildLifecycleAlignmentCommand(versionMetadata.runtimeVersion, repoRoot)
|
|
740
740
|
: null,
|
|
741
741
|
},
|
|
742
742
|
stage,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.111",
|
|
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": {
|