ppcos 1.0.3 → 1.0.5

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.
@@ -105,6 +105,75 @@ function migrateSettingsDenyRules(clientDir) {
105
105
  }
106
106
  }
107
107
 
108
+ /**
109
+ * One-time migration: merge hooks config into settings.local.json
110
+ * Adds missing hook events without touching existing ones
111
+ */
112
+ function migrateSettingsHooks(clientDir) {
113
+ const settingsPath = join(clientDir, '.claude', 'settings.local.json');
114
+ if (!existsSync(settingsPath)) return;
115
+
116
+ const requiredHooks = {
117
+ SessionStart: [
118
+ {
119
+ matcher: 'startup|resume|clear',
120
+ hooks: [
121
+ {
122
+ type: 'command',
123
+ command: '.claude/hooks/session-context-check.sh',
124
+ timeout: 30,
125
+ statusMessage: 'Checking context freshness...'
126
+ }
127
+ ]
128
+ }
129
+ ],
130
+ Stop: [
131
+ {
132
+ hooks: [
133
+ {
134
+ type: 'command',
135
+ command: '.claude/hooks/stop-memory-check.sh',
136
+ timeout: 10,
137
+ statusMessage: 'Checking memory log...'
138
+ }
139
+ ]
140
+ }
141
+ ],
142
+ PostCompact: [
143
+ {
144
+ hooks: [
145
+ {
146
+ type: 'command',
147
+ command: '.claude/hooks/post-compact-reminder.sh',
148
+ timeout: 30,
149
+ statusMessage: 'Restoring context after compaction...'
150
+ }
151
+ ]
152
+ }
153
+ ]
154
+ };
155
+
156
+ try {
157
+ const settings = JSON.parse(readFileSync(settingsPath, 'utf8'));
158
+ if (!settings.hooks) settings.hooks = {};
159
+
160
+ const added = [];
161
+ for (const [event, config] of Object.entries(requiredHooks)) {
162
+ if (!settings.hooks[event]) {
163
+ settings.hooks[event] = config;
164
+ added.push(event);
165
+ }
166
+ }
167
+
168
+ if (added.length === 0) return;
169
+
170
+ writeFileSync(settingsPath, JSON.stringify(settings, null, 2) + '\n');
171
+ logger.info(` Added ${added.length} hook${added.length !== 1 ? 's' : ''} to settings.local.json (${added.join(', ')})`);
172
+ } catch {
173
+ // Don't fail update over migration
174
+ }
175
+ }
176
+
108
177
  /**
109
178
  * One-time migration: normalize backslash manifest keys to forward slashes.
110
179
  * On Windows, getAllFiles() returned backslash paths which were stored as manifest keys.
@@ -311,6 +380,7 @@ async function updateClient(clientName, basePathOrOptions = {}, options = {}) {
311
380
  // Migrations for existing clients
312
381
  await ensureMemoryFolder(clientDir);
313
382
  migrateSettingsDenyRules(clientDir);
383
+ migrateSettingsHooks(clientDir);
314
384
  migrateManifestKeys(manifest);
315
385
  migrateConfigManagedTypes(manifest);
316
386
 
@@ -2,8 +2,8 @@
2
2
  * File system helper utilities
3
3
  */
4
4
 
5
- import { readdir, stat, mkdir, copyFile, access } from 'node:fs/promises';
6
- import { readdirSync, statSync, mkdirSync, copyFileSync, existsSync } from 'node:fs';
5
+ import { readdir, stat, mkdir, copyFile, access, chmod } from 'node:fs/promises';
6
+ import { readdirSync, statSync, mkdirSync, copyFileSync, existsSync, chmodSync } from 'node:fs';
7
7
  import { join, relative, dirname } from 'node:path';
8
8
  import { constants } from 'node:fs';
9
9
 
@@ -83,6 +83,8 @@ export async function copyFileWithDirs(src, dest) {
83
83
  const destDir = dirname(dest);
84
84
  await mkdir(destDir, { recursive: true });
85
85
  await copyFile(src, dest);
86
+ const srcStats = await stat(src);
87
+ await chmod(dest, srcStats.mode);
86
88
  }
87
89
 
88
90
  /**
@@ -96,6 +98,8 @@ export function copyFileWithDirsSync(src, dest) {
96
98
  mkdirSync(destDir, { recursive: true });
97
99
  }
98
100
  copyFileSync(src, dest);
101
+ const srcStats = statSync(src);
102
+ chmodSync(dest, srcStats.mode);
99
103
  }
100
104
 
101
105
  /**
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ppcos",
3
- "version": "1.0.3",
3
+ "version": "1.0.5",
4
4
  "description": "CLI tool to manage Google Ads AI workflow skills and agents for Claude Code",
5
5
  "type": "module",
6
6
  "bin": {