pumuki 6.3.140 → 6.3.141
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,6 +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.141] - 2026-05-05
|
|
10
|
+
|
|
11
|
+
### Fixed
|
|
12
|
+
|
|
13
|
+
- **PRE_PUSH en ramas actualizadas desde base:** el guard de atomicidad ignora commits heredados de `main`/`develop` y commits merge al validar trazabilidad y límites por commit, evitando bloqueos falsos en rollouts que solo resolvieron conflictos con la rama base.
|
|
14
|
+
|
|
9
15
|
## [6.3.140] - 2026-05-05
|
|
10
16
|
|
|
11
17
|
### Fixed
|
|
@@ -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-05 (v6.3.141)
|
|
8
|
+
|
|
9
|
+
- **PRE_PUSH sin falso bloqueo por historial base:** ramas de rollout que integran `main`/`develop` dejan de fallar por commits merge heredados como `Merge pull request ...`.
|
|
10
|
+
- **Flux/SAAS follow-up:** esta patch desbloquea el push de las resoluciones de conflicto de los PRs de repin abiertos tras `6.3.140`.
|
|
11
|
+
- **Rollout:** publicar `pumuki@6.3.141`, repinear primero RuralGo y repetir Flux/SAAS sin bypass.
|
|
12
|
+
|
|
7
13
|
### 2026-05-05 (v6.3.140)
|
|
8
14
|
|
|
9
15
|
- **PRE_PUSH compatible con ramas largas:** la atomicidad se valida por commit individual, no por diff agregado de rama.
|
|
@@ -32,6 +32,14 @@ const ATOMICITY_CONFIG_FILE = '.pumuki/git-atomicity.json';
|
|
|
32
32
|
const DEFAULT_COMMIT_PATTERN =
|
|
33
33
|
'^(feat|fix|chore|refactor|docs|test|perf|build|ci|revert)(\\([^)]+\\))?:\\s.+$';
|
|
34
34
|
const MANAGED_EVIDENCE_PATHS = new Set(['.ai_evidence.json', '.AI_EVIDENCE.json']);
|
|
35
|
+
const BASELINE_BRANCH_REFS = [
|
|
36
|
+
'origin/main',
|
|
37
|
+
'origin/develop',
|
|
38
|
+
'upstream/main',
|
|
39
|
+
'upstream/develop',
|
|
40
|
+
'main',
|
|
41
|
+
'develop',
|
|
42
|
+
];
|
|
35
43
|
|
|
36
44
|
const defaultConfig: GitAtomicityConfig = {
|
|
37
45
|
enabled: true,
|
|
@@ -252,33 +260,90 @@ const collectCommitSubjects = (params: {
|
|
|
252
260
|
fromRef?: string;
|
|
253
261
|
toRef?: string;
|
|
254
262
|
}): ReadonlyArray<string> => {
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
263
|
+
return collectCommitRecords(params)
|
|
264
|
+
.filter((record) => shouldEvaluateCommitRecord({ git: params.git, repoRoot: params.repoRoot, record }))
|
|
265
|
+
.map((record) => record.subject);
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
type CommitRecord = {
|
|
269
|
+
hash: string;
|
|
270
|
+
parents: ReadonlyArray<string>;
|
|
271
|
+
subject: string;
|
|
272
|
+
};
|
|
273
|
+
|
|
274
|
+
const parseCommitRecords = (value: string): ReadonlyArray<CommitRecord> =>
|
|
275
|
+
value
|
|
276
|
+
.split('\n')
|
|
277
|
+
.map((line) => line.trim())
|
|
278
|
+
.filter((line) => line.length > 0)
|
|
279
|
+
.map((line) => {
|
|
280
|
+
const [hash = '', parents = '', subject = ''] = line.split('\u0001');
|
|
281
|
+
return {
|
|
282
|
+
hash: hash.trim(),
|
|
283
|
+
parents: parents.split(' ').map((parent) => parent.trim()).filter((parent) => parent.length > 0),
|
|
284
|
+
subject: subject.trim(),
|
|
285
|
+
};
|
|
286
|
+
})
|
|
287
|
+
.filter((record) => record.hash.length > 0);
|
|
288
|
+
|
|
289
|
+
const isCommitReachableFromRef = (params: {
|
|
290
|
+
git: IGitService;
|
|
291
|
+
repoRoot: string;
|
|
292
|
+
commitHash: string;
|
|
293
|
+
ref: string;
|
|
294
|
+
}): boolean => {
|
|
258
295
|
try {
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
if (isUnresolvableRevisionError(error)) {
|
|
264
|
-
return [];
|
|
265
|
-
}
|
|
266
|
-
throw error;
|
|
296
|
+
params.git.runGit(['merge-base', '--is-ancestor', params.commitHash, params.ref], params.repoRoot);
|
|
297
|
+
return true;
|
|
298
|
+
} catch {
|
|
299
|
+
return false;
|
|
267
300
|
}
|
|
268
301
|
};
|
|
269
302
|
|
|
270
|
-
const
|
|
303
|
+
const isInheritedBaselineCommit = (params: {
|
|
304
|
+
git: IGitService;
|
|
305
|
+
repoRoot: string;
|
|
306
|
+
commitHash: string;
|
|
307
|
+
}): boolean =>
|
|
308
|
+
BASELINE_BRANCH_REFS.some((ref) =>
|
|
309
|
+
isCommitReachableFromRef({
|
|
310
|
+
git: params.git,
|
|
311
|
+
repoRoot: params.repoRoot,
|
|
312
|
+
commitHash: params.commitHash,
|
|
313
|
+
ref,
|
|
314
|
+
})
|
|
315
|
+
);
|
|
316
|
+
|
|
317
|
+
const shouldEvaluateCommitRecord = (params: {
|
|
318
|
+
git: IGitService;
|
|
319
|
+
repoRoot: string;
|
|
320
|
+
record: CommitRecord;
|
|
321
|
+
}): boolean => {
|
|
322
|
+
if (params.record.parents.length > 1) {
|
|
323
|
+
return false;
|
|
324
|
+
}
|
|
325
|
+
return !isInheritedBaselineCommit({
|
|
326
|
+
git: params.git,
|
|
327
|
+
repoRoot: params.repoRoot,
|
|
328
|
+
commitHash: params.record.hash,
|
|
329
|
+
});
|
|
330
|
+
};
|
|
331
|
+
|
|
332
|
+
const collectCommitRecords = (params: {
|
|
271
333
|
git: IGitService;
|
|
272
334
|
repoRoot: string;
|
|
273
335
|
fromRef?: string;
|
|
274
336
|
toRef?: string;
|
|
275
|
-
}): ReadonlyArray<
|
|
337
|
+
}): ReadonlyArray<CommitRecord> => {
|
|
276
338
|
if (!params.fromRef || !params.toRef) {
|
|
277
339
|
return [];
|
|
278
340
|
}
|
|
279
341
|
try {
|
|
280
|
-
return
|
|
281
|
-
params.git.runGit(
|
|
342
|
+
return parseCommitRecords(
|
|
343
|
+
params.git.runGit(
|
|
344
|
+
['log', '--format=%H%x01%P%x01%s', '--reverse', `${params.fromRef}..${params.toRef}`],
|
|
345
|
+
params.repoRoot
|
|
346
|
+
)
|
|
282
347
|
);
|
|
283
348
|
} catch (error) {
|
|
284
349
|
if (isUnresolvableRevisionError(error)) {
|
|
@@ -367,29 +432,29 @@ const buildPrePushCommitPathLimitViolations = (params: {
|
|
|
367
432
|
fromRef?: string;
|
|
368
433
|
toRef?: string;
|
|
369
434
|
}): GitAtomicityViolation[] | undefined => {
|
|
370
|
-
const
|
|
435
|
+
const commitRecords = collectCommitRecords({
|
|
371
436
|
git: params.git,
|
|
372
437
|
repoRoot: params.repoRoot,
|
|
373
438
|
fromRef: params.fromRef,
|
|
374
439
|
toRef: params.toRef,
|
|
375
|
-
});
|
|
376
|
-
if (
|
|
440
|
+
}).filter((record) => shouldEvaluateCommitRecord({ git: params.git, repoRoot: params.repoRoot, record }));
|
|
441
|
+
if (commitRecords.length === 0) {
|
|
377
442
|
return undefined;
|
|
378
443
|
}
|
|
379
444
|
|
|
380
445
|
const violations: GitAtomicityViolation[] = [];
|
|
381
|
-
for (const
|
|
446
|
+
for (const commitRecord of commitRecords) {
|
|
382
447
|
const changedPaths = collectCommitChangedPaths({
|
|
383
448
|
git: params.git,
|
|
384
449
|
repoRoot: params.repoRoot,
|
|
385
|
-
commitHash,
|
|
450
|
+
commitHash: commitRecord.hash,
|
|
386
451
|
}).filter((path) => !isManagedEvidencePath(path));
|
|
387
452
|
violations.push(
|
|
388
453
|
...buildPathLimitViolations({
|
|
389
454
|
changedPaths,
|
|
390
455
|
config: params.config,
|
|
391
456
|
stage: 'PRE_PUSH',
|
|
392
|
-
label: `commit=${
|
|
457
|
+
label: `commit=${commitRecord.hash.slice(0, 12)}`,
|
|
393
458
|
})
|
|
394
459
|
);
|
|
395
460
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pumuki",
|
|
3
|
-
"version": "6.3.
|
|
3
|
+
"version": "6.3.141",
|
|
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": {
|