@sylphx/flow 1.4.2 → 1.4.4

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
@@ -1,5 +1,15 @@
1
1
  # @sylphx/flow
2
2
 
3
+ ## 1.4.3
4
+
5
+ ### Patch Changes
6
+
7
+ - Fix sync not actually updating files (CRITICAL):
8
+ - Installation was comparing content and skipping writes
9
+ - Even after deletion, files weren't updated if content "matched"
10
+ - Add force mode that always overwrites during sync
11
+ - Sync now properly updates all files regardless of content
12
+
3
13
  ## 1.4.2
4
14
 
5
15
  ### Patch Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sylphx/flow",
3
- "version": "1.4.2",
3
+ "version": "1.4.4",
4
4
  "description": "AI-powered development workflow automation with autonomous loop mode and smart configuration",
5
5
  "type": "module",
6
6
  "bin": {
@@ -168,7 +168,12 @@ export async function installComponents(
168
168
  if (target.setupAgents && options.agents !== false) {
169
169
  const agentSpinner = quiet ? null : ora({ text: 'Installing agents', color: 'cyan' }).start();
170
170
  try {
171
- const agentResult = await target.setupAgents(process.cwd(), { ...options, quiet: true });
171
+ // DEBUG: Log force flag
172
+ if (!quiet && options.clear) {
173
+ console.log(`[DEBUG] Installing agents with force=${options.clear}`);
174
+ }
175
+
176
+ const agentResult = await target.setupAgents(process.cwd(), { ...options, quiet: true, force: options.clear });
172
177
  result.installed.agents = agentResult.count;
173
178
 
174
179
  if (agentSpinner) {
@@ -188,7 +193,7 @@ export async function installComponents(
188
193
  if (target.setupOutputStyles && options.outputStyles !== false) {
189
194
  const stylesSpinner = quiet ? null : ora({ text: 'Installing output styles', color: 'cyan' }).start();
190
195
  try {
191
- const stylesResult = await target.setupOutputStyles(process.cwd(), { ...options, quiet: true });
196
+ const stylesResult = await target.setupOutputStyles(process.cwd(), { ...options, quiet: true, force: options.clear });
192
197
  result.installed.outputStyles = stylesResult.count;
193
198
 
194
199
  if (stylesSpinner) {
@@ -216,7 +221,7 @@ export async function installComponents(
216
221
  if (target.setupRules && options.rules !== false) {
217
222
  const rulesSpinner = quiet ? null : ora({ text: 'Installing rules', color: 'cyan' }).start();
218
223
  try {
219
- const rulesResult = await target.setupRules(process.cwd(), { ...options, quiet: true });
224
+ const rulesResult = await target.setupRules(process.cwd(), { ...options, quiet: true, force: options.clear });
220
225
  result.installed.rules = rulesResult.count;
221
226
 
222
227
  if (rulesSpinner) {
@@ -247,7 +252,12 @@ export async function installComponents(
247
252
  color: 'cyan',
248
253
  }).start();
249
254
  try {
250
- const commandsResult = await target.setupSlashCommands(process.cwd(), { ...options, quiet: true });
255
+ // DEBUG: Log force flag
256
+ if (!quiet && options.clear) {
257
+ console.log(`[DEBUG] Installing slash commands with force=${options.clear}`);
258
+ }
259
+
260
+ const commandsResult = await target.setupSlashCommands(process.cwd(), { ...options, quiet: true, force: options.clear });
251
261
  result.installed.slashCommands = commandsResult.count;
252
262
 
253
263
  if (commandsSpinner) {
@@ -15,6 +15,8 @@ export interface InstallOptions extends CommonOptions {
15
15
  flatten?: boolean;
16
16
  /** Show progress messages */
17
17
  showProgress?: boolean;
18
+ /** Force overwrite without checking content (for sync) */
19
+ force?: boolean;
18
20
  }
19
21
 
20
22
  export type FileTransformFn = (content: string, sourcePath?: string) => Promise<string>;
@@ -122,22 +124,49 @@ export async function installToDirectory(
122
124
  let content = fs.readFileSync(sourcePath, 'utf8');
123
125
  content = await transform(content, file);
124
126
 
125
- const localProcessed = localInfo ? await transform(localInfo.content, file) : '';
126
- const contentChanged = !localInfo || localProcessed !== content;
127
+ // DEBUG: Log installation details
128
+ if (options.force && !options.quiet) {
129
+ console.log(
130
+ `[DEBUG] Installing ${file} - force=${options.force}, exists=${!!localInfo}, path=${targetPath}`
131
+ );
132
+ }
127
133
 
128
- if (contentChanged) {
134
+ // Force mode: always overwrite without checking
135
+ if (options.force) {
129
136
  fs.writeFileSync(targetPath, content, 'utf8');
137
+
138
+ // DEBUG: Verify write
139
+ if (!options.quiet) {
140
+ const written = fs.existsSync(targetPath);
141
+ if (!written) {
142
+ console.warn(`[DEBUG] Failed to write: ${targetPath}`);
143
+ }
144
+ }
145
+
130
146
  results.push({
131
147
  file,
132
148
  status: localInfo ? 'updated' : 'added',
133
149
  action: localInfo ? 'Updated' : 'Created',
134
150
  });
135
151
  } else {
136
- results.push({
137
- file,
138
- status: 'current',
139
- action: 'Already current',
140
- });
152
+ // Normal mode: check if content changed
153
+ const localProcessed = localInfo ? await transform(localInfo.content, file) : '';
154
+ const contentChanged = !localInfo || localProcessed !== content;
155
+
156
+ if (contentChanged) {
157
+ fs.writeFileSync(targetPath, content, 'utf8');
158
+ results.push({
159
+ file,
160
+ status: localInfo ? 'updated' : 'added',
161
+ action: localInfo ? 'Updated' : 'Created',
162
+ });
163
+ } else {
164
+ results.push({
165
+ file,
166
+ status: 'current',
167
+ action: 'Already current',
168
+ });
169
+ }
141
170
  }
142
171
  });
143
172
 
@@ -388,12 +388,25 @@ export async function executeSyncDelete(
388
388
  // Delete Flow templates
389
389
  for (const file of flowFiles) {
390
390
  try {
391
+ const existsBefore = fs.existsSync(file);
392
+ if (!existsBefore) {
393
+ console.log(chalk.dim(` ⊘ Already deleted: ${path.basename(file)}`));
394
+ continue;
395
+ }
396
+
391
397
  await fs.promises.unlink(file);
392
- console.log(chalk.dim(` ✓ Deleted: ${path.basename(file)}`));
393
- templatesDeleted++;
398
+
399
+ // Verify deletion
400
+ const existsAfter = fs.existsSync(file);
401
+ if (existsAfter) {
402
+ console.warn(chalk.yellow(` ⚠ File still exists after deletion: ${path.basename(file)}`));
403
+ } else {
404
+ console.log(chalk.dim(` ✓ Deleted: ${path.basename(file)}`));
405
+ templatesDeleted++;
406
+ }
394
407
  } catch (error) {
395
408
  if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
396
- console.warn(chalk.yellow(` ⚠ Failed to delete: ${path.basename(file)}`));
409
+ console.warn(chalk.yellow(` ⚠ Failed to delete: ${path.basename(file)} - ${error}`));
397
410
  }
398
411
  }
399
412
  }