pumuki 6.3.88 → 6.3.89

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.
@@ -1,3 +1,8 @@
1
+ ## 2026-04-20 (v6.3.89)
2
+ - **Aislamiento por worktree**: `pumuki install` detecta worktrees sin `core.hooksPath` explícito y fija un `core.hooksPath` local a `.pumuki/git-hooks`, evitando que los hooks gestionados se escriban en `.git/hooks` del checkout principal compartido.
3
+ - **Rollback limpio**: `pumuki uninstall` retira ese `core.hooksPath` solo si fue creado por Pumuki para el worktree.
4
+ - **Rollout recomendado**: publicar `pumuki@6.3.89`, repin inmediato en `Flux_training` y repetir la repro de worktree (`install`, `bootstrap-manifest`, `status --json`, checksums de hooks en checkout principal).
5
+
1
6
  ## 2026-04-20 (v6.3.87)
2
7
  - Cierra el segundo tramo de PUM-026: si PRE_WRITE solo arregla el receipt MCP y el gate pasa a verde, fuerza un refresh de paridad contra PRE_COMMIT antes del veredicto final.
3
8
  - Rollout recomendado: actualizar Flux_training y repetir la repro mínima de validate/pre-commit/.ai_evidence.
@@ -27,6 +27,81 @@ export type PumukiHooksDirectoryResolution = {
27
27
  };
28
28
 
29
29
  const HOOK_FILE_MODE = 0o755;
30
+ const PUMUKI_WORKTREE_HOOKS_PATH = '.pumuki/git-hooks';
31
+
32
+ const readLocalGitConfigValue = (repoRoot: string, key: string): string | null => {
33
+ try {
34
+ const value = execFileSync('git', ['config', '--local', '--get', key], {
35
+ cwd: repoRoot,
36
+ encoding: 'utf8',
37
+ stdio: ['ignore', 'pipe', 'ignore'],
38
+ }).trim();
39
+ return value.length > 0 ? value : null;
40
+ } catch {
41
+ return null;
42
+ }
43
+ };
44
+
45
+ const writeLocalGitConfigValue = (repoRoot: string, key: string, value: string): void => {
46
+ execFileSync('git', ['config', '--local', key, value], {
47
+ cwd: repoRoot,
48
+ stdio: ['ignore', 'ignore', 'ignore'],
49
+ });
50
+ };
51
+
52
+ const unsetLocalGitConfigValue = (repoRoot: string, key: string): void => {
53
+ try {
54
+ execFileSync('git', ['config', '--local', '--unset-all', key], {
55
+ cwd: repoRoot,
56
+ stdio: ['ignore', 'ignore', 'ignore'],
57
+ });
58
+ } catch {
59
+ // noop
60
+ }
61
+ };
62
+
63
+ const isWorktreeCheckout = (repoRoot: string): boolean => {
64
+ try {
65
+ const gitPointer = readFileSync(join(repoRoot, '.git'), 'utf8').trim();
66
+ return /^gitdir:\s+/i.test(gitPointer);
67
+ } catch {
68
+ return false;
69
+ }
70
+ };
71
+
72
+ const isPumukiManagedWorktreeHooksPath = (repoRoot: string, hooksPath: string): boolean => {
73
+ const normalizedHooksPath = hooksPath.trim();
74
+ return (
75
+ normalizedHooksPath === PUMUKI_WORKTREE_HOOKS_PATH ||
76
+ normalizedHooksPath === resolve(repoRoot, PUMUKI_WORKTREE_HOOKS_PATH)
77
+ );
78
+ };
79
+
80
+ const ensureWorktreeLocalHooksPath = (repoRoot: string): void => {
81
+ if (!isWorktreeCheckout(repoRoot)) {
82
+ return;
83
+ }
84
+
85
+ const currentHooksPath = readLocalGitConfigValue(repoRoot, 'core.hooksPath');
86
+ if (currentHooksPath) {
87
+ return;
88
+ }
89
+
90
+ writeLocalGitConfigValue(repoRoot, 'core.hooksPath', PUMUKI_WORKTREE_HOOKS_PATH);
91
+ };
92
+
93
+ const clearWorktreeLocalHooksPath = (repoRoot: string): void => {
94
+ if (!isWorktreeCheckout(repoRoot)) {
95
+ return;
96
+ }
97
+
98
+ const currentHooksPath = readLocalGitConfigValue(repoRoot, 'core.hooksPath');
99
+ if (!currentHooksPath || !isPumukiManagedWorktreeHooksPath(repoRoot, currentHooksPath)) {
100
+ return;
101
+ }
102
+
103
+ unsetLocalGitConfigValue(repoRoot, 'core.hooksPath');
104
+ };
30
105
 
31
106
  const resolveGitPath = (repoRoot: string, gitPathTarget: string): string | null => {
32
107
  try {
@@ -137,6 +212,7 @@ const ensureHooksDirectory = (repoRoot: string): void => {
137
212
  };
138
213
 
139
214
  export const installPumukiHooks = (repoRoot: string): HookInstallResult => {
215
+ ensureWorktreeLocalHooksPath(repoRoot);
140
216
  ensureHooksDirectory(repoRoot);
141
217
  const changedHooks: PumukiManagedHook[] = [];
142
218
 
@@ -180,6 +256,7 @@ export const uninstallPumukiHooks = (repoRoot: string): HookUninstallResult => {
180
256
  changedHooks.push(hook);
181
257
  }
182
258
 
259
+ clearWorktreeLocalHooksPath(repoRoot);
183
260
  return { changedHooks };
184
261
  };
185
262
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pumuki",
3
- "version": "6.3.88",
3
+ "version": "6.3.89",
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": {