@thiagodiogo/pscode 2.3.0 → 2.4.0

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.
Files changed (31) hide show
  1. package/dist/core/init.d.ts +0 -2
  2. package/dist/core/init.js +7 -77
  3. package/dist/core/profile-sync-drift.js +1 -15
  4. package/dist/core/profiles.d.ts +1 -1
  5. package/dist/core/profiles.js +0 -13
  6. package/dist/core/shared/index.d.ts +1 -0
  7. package/dist/core/shared/index.js +1 -0
  8. package/dist/core/shared/prune-orphans.d.ts +39 -0
  9. package/dist/core/shared/prune-orphans.js +149 -0
  10. package/dist/core/shared/skill-generation.js +2 -14
  11. package/dist/core/shared/tool-detection.d.ts +2 -2
  12. package/dist/core/shared/tool-detection.js +1 -13
  13. package/dist/core/templates/skill-templates.d.ts +1 -7
  14. package/dist/core/templates/skill-templates.js +1 -7
  15. package/dist/core/templates/workflows/{archive-change.d.ts → complete-change.d.ts} +1 -1
  16. package/dist/core/templates/workflows/{archive-change.js → complete-change.js} +2 -2
  17. package/dist/core/update.d.ts +0 -20
  18. package/dist/core/update.js +29 -115
  19. package/package.json +1 -1
  20. package/dist/core/templates/workflows/bulk-archive-change.d.ts +0 -10
  21. package/dist/core/templates/workflows/bulk-archive-change.js +0 -491
  22. package/dist/core/templates/workflows/continue-change.d.ts +0 -10
  23. package/dist/core/templates/workflows/continue-change.js +0 -233
  24. package/dist/core/templates/workflows/ff-change.d.ts +0 -10
  25. package/dist/core/templates/workflows/ff-change.js +0 -199
  26. package/dist/core/templates/workflows/new-change.d.ts +0 -10
  27. package/dist/core/templates/workflows/new-change.js +0 -142
  28. package/dist/core/templates/workflows/onboard.d.ts +0 -10
  29. package/dist/core/templates/workflows/onboard.js +0 -606
  30. package/dist/core/templates/workflows/verify-change.d.ts +0 -10
  31. package/dist/core/templates/workflows/verify-change.js +0 -337
@@ -7,19 +7,18 @@
7
7
  import path from 'path';
8
8
  import chalk from 'chalk';
9
9
  import ora from 'ora';
10
- import * as fs from 'fs';
11
10
  import { createRequire } from 'module';
12
11
  import { FileSystemUtils } from '../utils/file-system.js';
13
12
  import { transformToHyphenCommands } from '../utils/command-references.js';
14
13
  import { AI_TOOLS, PSCODE_DIR_NAME } from './config.js';
15
14
  import { generateCommands, CommandAdapterRegistry, } from './command-generation/index.js';
16
- import { getToolVersionStatus, getSkillTemplates, getCommandContents, generateSkillContent, getToolsWithSkillsDir, } from './shared/index.js';
15
+ import { getToolVersionStatus, getSkillTemplates, getCommandContents, generateSkillContent, getToolsWithSkillsDir, pruneOrphans, pruneOrphansForTool, } from './shared/index.js';
17
16
  import { detectLegacyArtifacts, cleanupLegacyArtifacts, formatCleanupSummary, formatDetectionSummary, getToolsFromLegacyArtifacts, } from './legacy-cleanup.js';
18
17
  import { isInteractive } from '../utils/interactive.js';
19
18
  import { getGlobalConfig } from './global-config.js';
20
- import { getProfileWorkflows, isValidProfile, DEFAULT_PROFILE, ALL_WORKFLOWS } from './profiles.js';
19
+ import { getProfileWorkflows, isValidProfile, DEFAULT_PROFILE } from './profiles.js';
21
20
  import { getAvailableTools } from './available-tools.js';
22
- import { WORKFLOW_TO_SKILL_DIR, getCommandConfiguredTools, getConfiguredToolsForProfileSync, getToolsNeedingProfileSync, } from './profile-sync-drift.js';
21
+ import { getCommandConfiguredTools, getConfiguredToolsForProfileSync, getToolsNeedingProfileSync, } from './profile-sync-drift.js';
23
22
  import { scanInstalledWorkflows as scanInstalledWorkflowsShared, migrateIfNeeded as migrateIfNeededShared, } from './migration.js';
24
23
  const require = createRequire(import.meta.url);
25
24
  const { version: PSCODE_VERSION } = require('../../package.json');
@@ -91,6 +90,15 @@ export class UpdateCommand {
91
90
  if (!this.force && toolsToUpdateSet.size === 0) {
92
91
  // All tools are up to date
93
92
  this.displayUpToDateMessage(toolStatuses);
93
+ // Even when up to date, prune orphan artifacts (e.g. skills/commands of
94
+ // workflows deleted or renamed in a previous version) by filesystem scan.
95
+ const pruned = pruneOrphans(resolvedProjectPath, configuredTools, desiredWorkflows, delivery);
96
+ if (pruned.removedSkillDirs > 0) {
97
+ console.log(chalk.dim(`Removed: ${pruned.removedSkillDirs} orphan skill directories`));
98
+ }
99
+ if (pruned.removedCommandFiles > 0) {
100
+ console.log(chalk.dim(`Removed: ${pruned.removedCommandFiles} orphan command files`));
101
+ }
94
102
  // Still check for new tool directories and extra workflows
95
103
  this.detectNewTools(resolvedProjectPath, configuredTools);
96
104
  this.displayExtraWorkflowsNote(resolvedProjectPath, configuredTools, desiredWorkflows);
@@ -132,11 +140,6 @@ export class UpdateCommand {
132
140
  const skillContent = generateSkillContent(template, PSCODE_VERSION, transformer);
133
141
  await FileSystemUtils.writeFile(skillFile, skillContent);
134
142
  }
135
- removedDeselectedSkillCount += await this.removeUnselectedSkillDirs(skillsDir, desiredWorkflows);
136
- }
137
- // Delete skill directories if delivery is commands-only
138
- if (!shouldGenerateSkills) {
139
- removedSkillCount += await this.removeSkillDirs(skillsDir);
140
143
  }
141
144
  // Generate commands if delivery includes commands
142
145
  if (shouldGenerateCommands) {
@@ -147,12 +150,23 @@ export class UpdateCommand {
147
150
  const commandFile = path.isAbsolute(cmd.path) ? cmd.path : path.join(resolvedProjectPath, cmd.path);
148
151
  await FileSystemUtils.writeFile(commandFile, cmd.fileContent);
149
152
  }
150
- removedDeselectedCommandCount += await this.removeUnselectedCommandFiles(resolvedProjectPath, toolId, desiredWorkflows);
151
153
  }
152
154
  }
153
- // Delete command files if delivery is skills-only
154
- if (!shouldGenerateCommands) {
155
- removedCommandCount += await this.removeCommandFiles(resolvedProjectPath, toolId);
155
+ // Prune by filesystem scan: remove any Pscode-managed skill dir or
156
+ // command file that is not desired for the active profile/delivery —
157
+ // including orphans of workflows deleted or renamed in the enum.
158
+ const pruned = pruneOrphansForTool(resolvedProjectPath, toolId, desiredWorkflows, delivery);
159
+ if (shouldGenerateSkills) {
160
+ removedDeselectedSkillCount += pruned.removedSkillDirs;
161
+ }
162
+ else {
163
+ removedSkillCount += pruned.removedSkillDirs;
164
+ }
165
+ if (shouldGenerateCommands) {
166
+ removedDeselectedCommandCount += pruned.removedCommandFiles;
167
+ }
168
+ else {
169
+ removedCommandCount += pruned.removedCommandFiles;
156
170
  }
157
171
  spinner.succeed(`Updated ${tool.name}`);
158
172
  updatedTools.push(tool.name);
@@ -189,9 +203,9 @@ export class UpdateCommand {
189
203
  if (newlyConfiguredTools.length > 0) {
190
204
  console.log();
191
205
  console.log(chalk.bold('Getting started:'));
192
- console.log(' /ps:new Start a new change');
193
- console.log(' /ps:continue Create the next artifact');
206
+ console.log(' /ps:propose Propose a new change');
194
207
  console.log(' /ps:apply Implement tasks');
208
+ console.log(' /ps:complete Finalize and archive a change');
195
209
  console.log();
196
210
  console.log(`Learn more: ${chalk.cyan('https://github.com/thiagodiogo/Pscode')}`);
197
211
  }
@@ -263,106 +277,6 @@ export class UpdateCommand {
263
277
  console.log(chalk.dim(`Note: ${extraWorkflows.length} extra workflows not in profile (use \`pscode config profile\` to switch profiles)`));
264
278
  }
265
279
  }
266
- /**
267
- * Removes skill directories for workflows when delivery changed to commands-only.
268
- * Returns the number of directories removed.
269
- */
270
- async removeSkillDirs(skillsDir) {
271
- let removed = 0;
272
- for (const workflow of ALL_WORKFLOWS) {
273
- const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
274
- if (!dirName)
275
- continue;
276
- const skillDir = path.join(skillsDir, dirName);
277
- try {
278
- if (fs.existsSync(skillDir)) {
279
- await fs.promises.rm(skillDir, { recursive: true, force: true });
280
- removed++;
281
- }
282
- }
283
- catch {
284
- // Ignore errors
285
- }
286
- }
287
- return removed;
288
- }
289
- /**
290
- * Removes skill directories for workflows that are no longer selected in the active profile.
291
- * Returns the number of directories removed.
292
- */
293
- async removeUnselectedSkillDirs(skillsDir, desiredWorkflows) {
294
- const desiredSet = new Set(desiredWorkflows);
295
- let removed = 0;
296
- for (const workflow of ALL_WORKFLOWS) {
297
- if (desiredSet.has(workflow))
298
- continue;
299
- const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
300
- if (!dirName)
301
- continue;
302
- const skillDir = path.join(skillsDir, dirName);
303
- try {
304
- if (fs.existsSync(skillDir)) {
305
- await fs.promises.rm(skillDir, { recursive: true, force: true });
306
- removed++;
307
- }
308
- }
309
- catch {
310
- // Ignore errors
311
- }
312
- }
313
- return removed;
314
- }
315
- /**
316
- * Removes command files for workflows when delivery changed to skills-only.
317
- * Returns the number of files removed.
318
- */
319
- async removeCommandFiles(projectPath, toolId) {
320
- let removed = 0;
321
- const adapter = CommandAdapterRegistry.get(toolId);
322
- if (!adapter)
323
- return 0;
324
- for (const workflow of ALL_WORKFLOWS) {
325
- const cmdPath = adapter.getFilePath(workflow);
326
- const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
327
- try {
328
- if (fs.existsSync(fullPath)) {
329
- await fs.promises.unlink(fullPath);
330
- removed++;
331
- }
332
- }
333
- catch {
334
- // Ignore errors
335
- }
336
- }
337
- return removed;
338
- }
339
- /**
340
- * Removes command files for workflows that are no longer selected in the active profile.
341
- * Returns the number of files removed.
342
- */
343
- async removeUnselectedCommandFiles(projectPath, toolId, desiredWorkflows) {
344
- let removed = 0;
345
- const adapter = CommandAdapterRegistry.get(toolId);
346
- if (!adapter)
347
- return 0;
348
- const desiredSet = new Set(desiredWorkflows);
349
- for (const workflow of ALL_WORKFLOWS) {
350
- if (desiredSet.has(workflow))
351
- continue;
352
- const cmdPath = adapter.getFilePath(workflow);
353
- const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
354
- try {
355
- if (fs.existsSync(fullPath)) {
356
- await fs.promises.unlink(fullPath);
357
- removed++;
358
- }
359
- }
360
- catch {
361
- // Ignore errors
362
- }
363
- }
364
- return removed;
365
- }
366
280
  /**
367
281
  * Detect and handle legacy Pscode artifacts.
368
282
  * Unlike init, update warns but continues if legacy files found in non-interactive mode.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@thiagodiogo/pscode",
3
- "version": "2.3.0",
3
+ "version": "2.4.0",
4
4
  "description": "AI-native system for spec-driven development",
5
5
  "keywords": [
6
6
  "pscode",
@@ -1,10 +0,0 @@
1
- /**
2
- * Skill Template Workflow Modules
3
- *
4
- * This file is generated by splitting the legacy monolithic
5
- * templates file into workflow-focused modules.
6
- */
7
- import type { SkillTemplate, CommandTemplate } from '../types.js';
8
- export declare function getBulkArchiveChangeSkillTemplate(): SkillTemplate;
9
- export declare function getPsBulkArchiveCommandTemplate(): CommandTemplate;
10
- //# sourceMappingURL=bulk-archive-change.d.ts.map