@thiagodiogo/pscode 2.3.0 → 2.5.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 (33) 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/apply-change.js +27 -2
  16. package/dist/core/templates/workflows/{archive-change.d.ts → complete-change.d.ts} +1 -1
  17. package/dist/core/templates/workflows/{archive-change.js → complete-change.js} +2 -2
  18. package/dist/core/templates/workflows/propose.js +56 -1
  19. package/dist/core/update.d.ts +0 -20
  20. package/dist/core/update.js +29 -115
  21. package/package.json +1 -1
  22. package/dist/core/templates/workflows/bulk-archive-change.d.ts +0 -10
  23. package/dist/core/templates/workflows/bulk-archive-change.js +0 -491
  24. package/dist/core/templates/workflows/continue-change.d.ts +0 -10
  25. package/dist/core/templates/workflows/continue-change.js +0 -233
  26. package/dist/core/templates/workflows/ff-change.d.ts +0 -10
  27. package/dist/core/templates/workflows/ff-change.js +0 -199
  28. package/dist/core/templates/workflows/new-change.d.ts +0 -10
  29. package/dist/core/templates/workflows/new-change.js +0 -142
  30. package/dist/core/templates/workflows/onboard.d.ts +0 -10
  31. package/dist/core/templates/workflows/onboard.js +0 -606
  32. package/dist/core/templates/workflows/verify-change.d.ts +0 -10
  33. package/dist/core/templates/workflows/verify-change.js +0 -337
@@ -38,8 +38,6 @@ export declare class InitCommand {
38
38
  private generateJiraFiles;
39
39
  private handleDixiExtras;
40
40
  private startSpinner;
41
- private removeSkillDirs;
42
- private removeCommandFiles;
43
41
  }
44
42
  export {};
45
43
  //# sourceMappingURL=init.d.ts.map
package/dist/core/init.js CHANGED
@@ -19,9 +19,9 @@ import { generateCommands, CommandAdapterRegistry, } from './command-generation/
19
19
  import { detectLegacyArtifacts, cleanupLegacyArtifacts, formatCleanupSummary, formatDetectionSummary, } from './legacy-cleanup.js';
20
20
  import { detectLegacyToolArtifacts, runLegacyToolMigration, formatLegacyToolDetectionSummary, formatLegacyToolMigrationSummary, pscodeDirExists, } from './openspec-migration.js';
21
21
  import { runTrelloInitPrompt } from './trello-init-prompt.js';
22
- import { getToolsWithSkillsDir, getToolStates, getSkillTemplates, getCommandContents, generateSkillContent, } from './shared/index.js';
22
+ import { getToolsWithSkillsDir, getToolStates, getSkillTemplates, getCommandContents, generateSkillContent, pruneOrphansForTool, } from './shared/index.js';
23
23
  import { getGlobalConfig } from './global-config.js';
24
- import { getProfileWorkflows, isValidProfile, DEFAULT_PROFILE, PROFILES, ALL_WORKFLOWS } from './profiles.js';
24
+ import { getProfileWorkflows, isValidProfile, DEFAULT_PROFILE, PROFILES } from './profiles.js';
25
25
  import { detectDixiStack, getDixiStackFamily, getDixiStackLabel, installDixiExtras, migrateLegacyPastelsddDir } from './presets/dixi.js';
26
26
  import { stringify as stringifyYaml } from 'yaml';
27
27
  import { parse as parseYaml } from 'yaml';
@@ -38,31 +38,6 @@ const PROGRESS_SPINNER = {
38
38
  interval: 80,
39
39
  frames: ['░░░', '▒░░', '▒▒░', '▒▒▒', '▓▒▒', '▓▓▒', '▓▓▓', '▒▓▓', '░▒▓'],
40
40
  };
41
- const WORKFLOW_TO_SKILL_DIR = {
42
- 'explore': 'pscode-explore',
43
- 'new': 'pscode-new-change',
44
- 'continue': 'pscode-continue-change',
45
- 'apply': 'pscode-apply-change',
46
- 'ff': 'pscode-ff-change',
47
- 'complete': 'pscode-archive-change',
48
- 'bulk-archive': 'pscode-bulk-archive-change',
49
- 'verify': 'pscode-verify-change',
50
- 'onboard': 'pscode-onboard',
51
- 'propose': 'pscode-propose',
52
- // Trello-specific workflows
53
- 'trello-setup': 'pscode-trello-setup',
54
- 'draft': 'pscode-trello-draft',
55
- // Productivity workflows
56
- 'handoff': 'pscode-handoff',
57
- // Dixi-specific workflows
58
- 'rfc': 'pscode-dixi-rfc',
59
- 'design': 'pscode-dixi-design',
60
- 'tasks': 'pscode-dixi-tasks',
61
- 'arch-check': 'pscode-dixi-arch-check',
62
- 'adr': 'pscode-dixi-adr',
63
- 'jira-sync': 'pscode-dixi-jira-sync',
64
- 'dod': 'pscode-dixi-dod',
65
- };
66
41
  // -----------------------------------------------------------------------------
67
42
  // Init Command Class
68
43
  // -----------------------------------------------------------------------------
@@ -529,10 +504,6 @@ export class InitCommand {
529
504
  await FileSystemUtils.writeFile(skillFile, skillContent);
530
505
  }
531
506
  }
532
- if (!shouldGenerateSkills) {
533
- const skillsDir = path.join(projectPath, tool.skillsDir, 'skills');
534
- removedSkillCount += await this.removeSkillDirs(skillsDir);
535
- }
536
507
  // Generate commands if delivery includes commands
537
508
  if (shouldGenerateCommands) {
538
509
  const adapter = CommandAdapterRegistry.get(tool.value);
@@ -547,9 +518,11 @@ export class InitCommand {
547
518
  commandsSkipped.push(tool.value);
548
519
  }
549
520
  }
550
- if (!shouldGenerateCommands) {
551
- removedCommandCount += await this.removeCommandFiles(projectPath, tool.value);
552
- }
521
+ // Prune by filesystem scan: drop any Pscode-managed artifact not desired
522
+ // for the active profile/delivery, including orphans of removed workflows.
523
+ const pruned = pruneOrphansForTool(projectPath, tool.value, workflows, delivery);
524
+ removedSkillCount += pruned.removedSkillDirs;
525
+ removedCommandCount += pruned.removedCommandFiles;
553
526
  spinner.succeed(`Setup complete for ${tool.name}`);
554
527
  if (tool.wasConfigured) {
555
528
  refreshedTools.push(tool);
@@ -689,10 +662,6 @@ export class InitCommand {
689
662
  console.log(chalk.bold('Getting started:'));
690
663
  console.log(' Start your first change: /ps:propose "your idea"');
691
664
  }
692
- else if (activeWorkflows.includes('new')) {
693
- console.log(chalk.bold('Getting started:'));
694
- console.log(' Start your first change: /ps:new "your idea"');
695
- }
696
665
  else {
697
666
  console.log("Done. Run 'pscode config profile' to switch profiles.");
698
667
  }
@@ -773,44 +742,5 @@ export class InitCommand {
773
742
  spinner: PROGRESS_SPINNER,
774
743
  }).start();
775
744
  }
776
- async removeSkillDirs(skillsDir) {
777
- let removed = 0;
778
- for (const workflow of ALL_WORKFLOWS) {
779
- const dirName = WORKFLOW_TO_SKILL_DIR[workflow];
780
- if (!dirName)
781
- continue;
782
- const skillDir = path.join(skillsDir, dirName);
783
- try {
784
- if (fs.existsSync(skillDir)) {
785
- await fs.promises.rm(skillDir, { recursive: true, force: true });
786
- removed++;
787
- }
788
- }
789
- catch {
790
- // Ignore errors
791
- }
792
- }
793
- return removed;
794
- }
795
- async removeCommandFiles(projectPath, toolId) {
796
- let removed = 0;
797
- const adapter = CommandAdapterRegistry.get(toolId);
798
- if (!adapter)
799
- return 0;
800
- for (const workflow of ALL_WORKFLOWS) {
801
- const cmdPath = adapter.getFilePath(workflow);
802
- const fullPath = path.isAbsolute(cmdPath) ? cmdPath : path.join(projectPath, cmdPath);
803
- try {
804
- if (fs.existsSync(fullPath)) {
805
- await fs.promises.unlink(fullPath);
806
- removed++;
807
- }
808
- }
809
- catch {
810
- // Ignore errors
811
- }
812
- }
813
- return removed;
814
- }
815
745
  }
816
746
  //# sourceMappingURL=init.js.map
@@ -9,14 +9,8 @@ import { COMMAND_IDS, getConfiguredTools } from './shared/index.js';
9
9
  */
10
10
  export const WORKFLOW_TO_SKILL_DIR = {
11
11
  'explore': 'pscode-explore',
12
- 'new': 'pscode-new-change',
13
- 'continue': 'pscode-continue-change',
14
12
  'apply': 'pscode-apply-change',
15
- 'ff': 'pscode-ff-change',
16
- 'complete': 'pscode-archive-change',
17
- 'bulk-archive': 'pscode-bulk-archive-change',
18
- 'verify': 'pscode-verify-change',
19
- 'onboard': 'pscode-onboard',
13
+ 'complete': 'pscode-complete-change',
20
14
  'propose': 'pscode-propose',
21
15
  // Trello-specific workflows
22
16
  'trello-setup': 'pscode-trello-setup',
@@ -24,14 +18,6 @@ export const WORKFLOW_TO_SKILL_DIR = {
24
18
  // Productivity workflows
25
19
  'handoff': 'pscode-handoff',
26
20
  'grill-me': 'pscode-grill-me',
27
- // Dixi-specific workflows
28
- 'rfc': 'pscode-dixi-rfc',
29
- 'design': 'pscode-dixi-design',
30
- 'tasks': 'pscode-dixi-tasks',
31
- 'arch-check': 'pscode-dixi-arch-check',
32
- 'adr': 'pscode-dixi-adr',
33
- 'jira-sync': 'pscode-dixi-jira-sync',
34
- 'dod': 'pscode-dixi-dod',
35
21
  };
36
22
  function toKnownWorkflows(workflows) {
37
23
  return workflows.filter((workflow) => ALL_WORKFLOWS.includes(workflow));
@@ -5,7 +5,7 @@
5
5
  * `pscode init --profile <name>` or `pscode config profile <name>`.
6
6
  * The workflow lists are fixed in code — users cannot customise them.
7
7
  */
8
- export declare const ALL_WORKFLOWS: readonly ["propose", "explore", "new", "continue", "apply", "ff", "complete", "bulk-archive", "verify", "onboard", "trello-setup", "draft", "rfc", "design", "tasks", "arch-check", "adr", "jira-sync", "dod", "handoff", "grill-me"];
8
+ export declare const ALL_WORKFLOWS: readonly ["propose", "explore", "apply", "complete", "trello-setup", "draft", "handoff", "grill-me"];
9
9
  export type WorkflowId = (typeof ALL_WORKFLOWS)[number];
10
10
  export interface ProfileDefinition {
11
11
  description: string;
@@ -8,23 +8,10 @@
8
8
  export const ALL_WORKFLOWS = [
9
9
  'propose',
10
10
  'explore',
11
- 'new',
12
- 'continue',
13
11
  'apply',
14
- 'ff',
15
12
  'complete',
16
- 'bulk-archive',
17
- 'verify',
18
- 'onboard',
19
13
  'trello-setup',
20
14
  'draft',
21
- 'rfc',
22
- 'design',
23
- 'tasks',
24
- 'arch-check',
25
- 'adr',
26
- 'jira-sync',
27
- 'dod',
28
15
  'handoff',
29
16
  'grill-me',
30
17
  ];
@@ -5,4 +5,5 @@
5
5
  */
6
6
  export { SKILL_NAMES, type SkillName, COMMAND_IDS, type CommandId, type ToolSkillStatus, type ToolVersionStatus, getToolsWithSkillsDir, getToolSkillStatus, getToolStates, extractGeneratedByVersion, getToolVersionStatus, getConfiguredTools, getAllToolVersionStatus, } from './tool-detection.js';
7
7
  export { type SkillTemplateEntry, type CommandTemplateEntry, getSkillTemplates, getCommandTemplates, getCommandContents, generateSkillContent, } from './skill-generation.js';
8
+ export { type PruneResult, pruneOrphans, pruneOrphansForTool, } from './prune-orphans.js';
8
9
  //# sourceMappingURL=index.d.ts.map
@@ -5,4 +5,5 @@
5
5
  */
6
6
  export { SKILL_NAMES, COMMAND_IDS, getToolsWithSkillsDir, getToolSkillStatus, getToolStates, extractGeneratedByVersion, getToolVersionStatus, getConfiguredTools, getAllToolVersionStatus, } from './tool-detection.js';
7
7
  export { getSkillTemplates, getCommandTemplates, getCommandContents, generateSkillContent, } from './skill-generation.js';
8
+ export { pruneOrphans, pruneOrphansForTool, } from './prune-orphans.js';
8
9
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,39 @@
1
+ /**
2
+ * Orphan Artifact Pruning
3
+ *
4
+ * Removes Pscode-managed skill directories and slash command files that no
5
+ * longer correspond to a desired workflow, by **scanning the filesystem**
6
+ * rather than iterating `ALL_WORKFLOWS`. This is what lets `init`/`update`
7
+ * clean up artifacts of workflows that were deleted (or renamed) from the
8
+ * enum entirely — a loop over `ALL_WORKFLOWS` would never visit them.
9
+ *
10
+ * The "desired" set is computed from the same generators used when writing
11
+ * (`getSkillTemplates` / `adapter.getFilePath`), so there is a single source
12
+ * of truth and a valid artifact is never removed.
13
+ *
14
+ * Removal is strictly limited to Pscode-managed naming patterns (skill dirs
15
+ * prefixed `pscode-`; command files matching the adapter's own filename
16
+ * pattern), so user files are preserved.
17
+ */
18
+ import type { Delivery } from '../global-config.js';
19
+ export interface PruneResult {
20
+ removedSkillDirs: number;
21
+ removedCommandFiles: number;
22
+ }
23
+ /**
24
+ * Scans installed Pscode artifacts for a single tool and removes orphans —
25
+ * artifacts that do not belong to a desired workflow for the active delivery.
26
+ *
27
+ * - Skills: every `pscode-*` directory whose name is not in the desired set is
28
+ * removed. When skills are not generated (commands-only delivery) the desired
29
+ * set is empty, so all Pscode skill dirs are removed.
30
+ * - Commands: every Pscode-managed command file whose decoded id is not in the
31
+ * desired set is removed. When commands are not generated (skills-only) the
32
+ * desired set is empty, so all managed command files are removed.
33
+ */
34
+ export declare function pruneOrphansForTool(projectPath: string, toolId: string, desiredWorkflows: readonly string[], delivery: Delivery): PruneResult;
35
+ /**
36
+ * Prunes orphan artifacts across multiple tools, aggregating the counts.
37
+ */
38
+ export declare function pruneOrphans(projectPath: string, toolIds: readonly string[], desiredWorkflows: readonly string[], delivery: Delivery): PruneResult;
39
+ //# sourceMappingURL=prune-orphans.d.ts.map
@@ -0,0 +1,149 @@
1
+ /**
2
+ * Orphan Artifact Pruning
3
+ *
4
+ * Removes Pscode-managed skill directories and slash command files that no
5
+ * longer correspond to a desired workflow, by **scanning the filesystem**
6
+ * rather than iterating `ALL_WORKFLOWS`. This is what lets `init`/`update`
7
+ * clean up artifacts of workflows that were deleted (or renamed) from the
8
+ * enum entirely — a loop over `ALL_WORKFLOWS` would never visit them.
9
+ *
10
+ * The "desired" set is computed from the same generators used when writing
11
+ * (`getSkillTemplates` / `adapter.getFilePath`), so there is a single source
12
+ * of truth and a valid artifact is never removed.
13
+ *
14
+ * Removal is strictly limited to Pscode-managed naming patterns (skill dirs
15
+ * prefixed `pscode-`; command files matching the adapter's own filename
16
+ * pattern), so user files are preserved.
17
+ */
18
+ import path from 'path';
19
+ import * as fs from 'fs';
20
+ import { CommandAdapterRegistry } from '../command-generation/index.js';
21
+ import { AI_TOOLS } from '../config.js';
22
+ import { getSkillTemplates } from './skill-generation.js';
23
+ const SKILL_DIR_PREFIX = 'pscode-';
24
+ /** Sentinel unlikely to collide with a real command id. */
25
+ const PROBE_ID = '__pscode_probe__';
26
+ /**
27
+ * Lists the immediate child directory names of `dir`, or `[]` if it doesn't exist.
28
+ */
29
+ function listDirs(dir) {
30
+ try {
31
+ return fs
32
+ .readdirSync(dir, { withFileTypes: true })
33
+ .filter((e) => e.isDirectory())
34
+ .map((e) => e.name);
35
+ }
36
+ catch {
37
+ return [];
38
+ }
39
+ }
40
+ /**
41
+ * Lists the immediate child file names of `dir`, or `[]` if it doesn't exist.
42
+ */
43
+ function listFiles(dir) {
44
+ try {
45
+ return fs
46
+ .readdirSync(dir, { withFileTypes: true })
47
+ .filter((e) => e.isFile())
48
+ .map((e) => e.name);
49
+ }
50
+ catch {
51
+ return [];
52
+ }
53
+ }
54
+ /**
55
+ * Derives the command directory and the Pscode-managed filename pattern for an
56
+ * adapter by probing `getFilePath` with a sentinel id. Returns the directory,
57
+ * the filename prefix/suffix that wrap the id, and a decoder from filename → id.
58
+ */
59
+ function resolveCommandPattern(toolId, projectPath) {
60
+ const adapter = CommandAdapterRegistry.get(toolId);
61
+ if (!adapter)
62
+ return null;
63
+ const probePath = adapter.getFilePath(PROBE_ID);
64
+ const absProbe = path.isAbsolute(probePath) ? probePath : path.join(projectPath, probePath);
65
+ const dir = path.dirname(absProbe);
66
+ const base = path.basename(absProbe);
67
+ const idx = base.indexOf(PROBE_ID);
68
+ if (idx === -1)
69
+ return null;
70
+ const prefix = base.slice(0, idx);
71
+ const suffix = base.slice(idx + PROBE_ID.length);
72
+ const idFromFile = (file) => {
73
+ if (!file.startsWith(prefix) || !file.endsWith(suffix))
74
+ return null;
75
+ const id = file.slice(prefix.length, file.length - suffix.length);
76
+ return id.length > 0 ? id : null;
77
+ };
78
+ return { dir, prefix, suffix, idFromFile };
79
+ }
80
+ /**
81
+ * Scans installed Pscode artifacts for a single tool and removes orphans —
82
+ * artifacts that do not belong to a desired workflow for the active delivery.
83
+ *
84
+ * - Skills: every `pscode-*` directory whose name is not in the desired set is
85
+ * removed. When skills are not generated (commands-only delivery) the desired
86
+ * set is empty, so all Pscode skill dirs are removed.
87
+ * - Commands: every Pscode-managed command file whose decoded id is not in the
88
+ * desired set is removed. When commands are not generated (skills-only) the
89
+ * desired set is empty, so all managed command files are removed.
90
+ */
91
+ export function pruneOrphansForTool(projectPath, toolId, desiredWorkflows, delivery) {
92
+ const tool = AI_TOOLS.find((t) => t.value === toolId);
93
+ if (!tool?.skillsDir)
94
+ return { removedSkillDirs: 0, removedCommandFiles: 0 };
95
+ const shouldGenerateSkills = delivery !== 'commands';
96
+ const shouldGenerateCommands = delivery !== 'skills';
97
+ let removedSkillDirs = 0;
98
+ let removedCommandFiles = 0;
99
+ // ── Skills ──────────────────────────────────────────────────────────────
100
+ const skillsDir = path.join(projectPath, tool.skillsDir, 'skills');
101
+ const desiredSkillDirs = new Set(shouldGenerateSkills ? getSkillTemplates(desiredWorkflows).map((t) => t.dirName) : []);
102
+ for (const name of listDirs(skillsDir)) {
103
+ if (!name.startsWith(SKILL_DIR_PREFIX))
104
+ continue; // never touch user dirs
105
+ if (desiredSkillDirs.has(name))
106
+ continue;
107
+ try {
108
+ fs.rmSync(path.join(skillsDir, name), { recursive: true, force: true });
109
+ removedSkillDirs++;
110
+ }
111
+ catch {
112
+ // Ignore errors
113
+ }
114
+ }
115
+ // ── Commands ────────────────────────────────────────────────────────────
116
+ const pattern = resolveCommandPattern(toolId, projectPath);
117
+ if (pattern) {
118
+ const desiredCommandIds = new Set(shouldGenerateCommands ? desiredWorkflows : []);
119
+ for (const file of listFiles(pattern.dir)) {
120
+ const id = pattern.idFromFile(file);
121
+ if (id == null)
122
+ continue; // not a Pscode-managed command file
123
+ if (desiredCommandIds.has(id))
124
+ continue;
125
+ try {
126
+ fs.unlinkSync(path.join(pattern.dir, file));
127
+ removedCommandFiles++;
128
+ }
129
+ catch {
130
+ // Ignore errors
131
+ }
132
+ }
133
+ }
134
+ return { removedSkillDirs, removedCommandFiles };
135
+ }
136
+ /**
137
+ * Prunes orphan artifacts across multiple tools, aggregating the counts.
138
+ */
139
+ export function pruneOrphans(projectPath, toolIds, desiredWorkflows, delivery) {
140
+ let removedSkillDirs = 0;
141
+ let removedCommandFiles = 0;
142
+ for (const toolId of toolIds) {
143
+ const result = pruneOrphansForTool(projectPath, toolId, desiredWorkflows, delivery);
144
+ removedSkillDirs += result.removedSkillDirs;
145
+ removedCommandFiles += result.removedCommandFiles;
146
+ }
147
+ return { removedSkillDirs, removedCommandFiles };
148
+ }
149
+ //# sourceMappingURL=prune-orphans.js.map
@@ -3,7 +3,7 @@
3
3
  *
4
4
  * Shared utilities for generating skill and command files.
5
5
  */
6
- import { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getCompleteChangeSkillTemplate, getBulkArchiveChangeSkillTemplate, getVerifyChangeSkillTemplate, getOnboardSkillTemplate, getProposeSkillTemplate, getTrelloSetupSkillTemplate, getTrelloDraftSkillTemplate, getHandoffSkillTemplate, getGrillMeSkillTemplate, getPsExploreCommandTemplate, getPsNewCommandTemplate, getPsContinueCommandTemplate, getPsApplyCommandTemplate, getPsFfCommandTemplate, getPsCompleteCommandTemplate, getPsBulkArchiveCommandTemplate, getPsVerifyCommandTemplate, getPsOnboardCommandTemplate, getPsProposeCommandTemplate, getTrelloSetupCommandTemplate, getTrelloDraftCommandTemplate, getHandoffCommandTemplate, getGrillMeCommandTemplate, } from '../templates/skill-templates.js';
6
+ import { getExploreSkillTemplate, getApplyChangeSkillTemplate, getCompleteChangeSkillTemplate, getProposeSkillTemplate, getTrelloSetupSkillTemplate, getTrelloDraftSkillTemplate, getHandoffSkillTemplate, getGrillMeSkillTemplate, getPsExploreCommandTemplate, getPsApplyCommandTemplate, getPsCompleteCommandTemplate, getPsProposeCommandTemplate, getTrelloSetupCommandTemplate, getTrelloDraftCommandTemplate, getHandoffCommandTemplate, getGrillMeCommandTemplate, } from '../templates/skill-templates.js';
7
7
  /**
8
8
  * Gets skill templates with their directory names, optionally filtered by workflow IDs.
9
9
  *
@@ -12,14 +12,8 @@ import { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSk
12
12
  export function getSkillTemplates(workflowFilter) {
13
13
  const all = [
14
14
  { template: getExploreSkillTemplate(), dirName: 'pscode-explore', workflowId: 'explore' },
15
- { template: getNewChangeSkillTemplate(), dirName: 'pscode-new-change', workflowId: 'new' },
16
- { template: getContinueChangeSkillTemplate(), dirName: 'pscode-continue-change', workflowId: 'continue' },
17
15
  { template: getApplyChangeSkillTemplate(), dirName: 'pscode-apply-change', workflowId: 'apply' },
18
- { template: getFfChangeSkillTemplate(), dirName: 'pscode-ff-change', workflowId: 'ff' },
19
- { template: getCompleteChangeSkillTemplate(), dirName: 'pscode-archive-change', workflowId: 'complete' },
20
- { template: getBulkArchiveChangeSkillTemplate(), dirName: 'pscode-bulk-archive-change', workflowId: 'bulk-archive' },
21
- { template: getVerifyChangeSkillTemplate(), dirName: 'pscode-verify-change', workflowId: 'verify' },
22
- { template: getOnboardSkillTemplate(), dirName: 'pscode-onboard', workflowId: 'onboard' },
16
+ { template: getCompleteChangeSkillTemplate(), dirName: 'pscode-complete-change', workflowId: 'complete' },
23
17
  { template: getProposeSkillTemplate(), dirName: 'pscode-propose', workflowId: 'propose' },
24
18
  // Trello-specific workflows
25
19
  { template: getTrelloSetupSkillTemplate(), dirName: 'pscode-trello-setup', workflowId: 'trello-setup' },
@@ -41,14 +35,8 @@ export function getSkillTemplates(workflowFilter) {
41
35
  export function getCommandTemplates(workflowFilter) {
42
36
  const all = [
43
37
  { template: getPsExploreCommandTemplate(), id: 'explore' },
44
- { template: getPsNewCommandTemplate(), id: 'new' },
45
- { template: getPsContinueCommandTemplate(), id: 'continue' },
46
38
  { template: getPsApplyCommandTemplate(), id: 'apply' },
47
- { template: getPsFfCommandTemplate(), id: 'ff' },
48
39
  { template: getPsCompleteCommandTemplate(), id: 'complete' },
49
- { template: getPsBulkArchiveCommandTemplate(), id: 'bulk-archive' },
50
- { template: getPsVerifyCommandTemplate(), id: 'verify' },
51
- { template: getPsOnboardCommandTemplate(), id: 'onboard' },
52
40
  { template: getPsProposeCommandTemplate(), id: 'propose' },
53
41
  // Trello-specific workflows
54
42
  { template: getTrelloSetupCommandTemplate(), id: 'trello-setup' },
@@ -6,12 +6,12 @@
6
6
  /**
7
7
  * Names of skill directories created by pscode init.
8
8
  */
9
- export declare const SKILL_NAMES: readonly ["pscode-explore", "pscode-new-change", "pscode-continue-change", "pscode-apply-change", "pscode-ff-change", "pscode-archive-change", "pscode-bulk-archive-change", "pscode-verify-change", "pscode-onboard", "pscode-propose"];
9
+ export declare const SKILL_NAMES: readonly ["pscode-explore", "pscode-apply-change", "pscode-complete-change", "pscode-propose"];
10
10
  export type SkillName = (typeof SKILL_NAMES)[number];
11
11
  /**
12
12
  * IDs of command templates created by pscode init.
13
13
  */
14
- export declare const COMMAND_IDS: readonly ["explore", "new", "continue", "apply", "ff", "complete", "bulk-archive", "verify", "onboard", "propose"];
14
+ export declare const COMMAND_IDS: readonly ["explore", "apply", "complete", "propose"];
15
15
  export type CommandId = (typeof COMMAND_IDS)[number];
16
16
  /**
17
17
  * Status of skill configuration for a tool.
@@ -11,14 +11,8 @@ import { AI_TOOLS } from '../config.js';
11
11
  */
12
12
  export const SKILL_NAMES = [
13
13
  'pscode-explore',
14
- 'pscode-new-change',
15
- 'pscode-continue-change',
16
14
  'pscode-apply-change',
17
- 'pscode-ff-change',
18
- 'pscode-archive-change',
19
- 'pscode-bulk-archive-change',
20
- 'pscode-verify-change',
21
- 'pscode-onboard',
15
+ 'pscode-complete-change',
22
16
  'pscode-propose',
23
17
  ];
24
18
  /**
@@ -26,14 +20,8 @@ export const SKILL_NAMES = [
26
20
  */
27
21
  export const COMMAND_IDS = [
28
22
  'explore',
29
- 'new',
30
- 'continue',
31
23
  'apply',
32
- 'ff',
33
24
  'complete',
34
- 'bulk-archive',
35
- 'verify',
36
- 'onboard',
37
25
  'propose',
38
26
  ];
39
27
  /**
@@ -5,14 +5,8 @@
5
5
  */
6
6
  export type { SkillTemplate, CommandTemplate } from './types.js';
7
7
  export { getExploreSkillTemplate, getPsExploreCommandTemplate } from './workflows/explore.js';
8
- export { getNewChangeSkillTemplate, getPsNewCommandTemplate } from './workflows/new-change.js';
9
- export { getContinueChangeSkillTemplate, getPsContinueCommandTemplate } from './workflows/continue-change.js';
10
8
  export { getApplyChangeSkillTemplate, getPsApplyCommandTemplate } from './workflows/apply-change.js';
11
- export { getFfChangeSkillTemplate, getPsFfCommandTemplate } from './workflows/ff-change.js';
12
- export { getCompleteChangeSkillTemplate, getPsCompleteCommandTemplate } from './workflows/archive-change.js';
13
- export { getBulkArchiveChangeSkillTemplate, getPsBulkArchiveCommandTemplate } from './workflows/bulk-archive-change.js';
14
- export { getVerifyChangeSkillTemplate, getPsVerifyCommandTemplate } from './workflows/verify-change.js';
15
- export { getOnboardSkillTemplate, getPsOnboardCommandTemplate } from './workflows/onboard.js';
9
+ export { getCompleteChangeSkillTemplate, getPsCompleteCommandTemplate } from './workflows/complete-change.js';
16
10
  export { getProposeSkillTemplate, getPsProposeCommandTemplate } from './workflows/propose.js';
17
11
  export { getFeedbackSkillTemplate } from './workflows/feedback.js';
18
12
  export { getTrelloSetupSkillTemplate, getTrelloSetupCommandTemplate } from './workflows/trello-setup.js';
@@ -4,14 +4,8 @@
4
4
  * Compatibility facade that re-exports split workflow template modules.
5
5
  */
6
6
  export { getExploreSkillTemplate, getPsExploreCommandTemplate } from './workflows/explore.js';
7
- export { getNewChangeSkillTemplate, getPsNewCommandTemplate } from './workflows/new-change.js';
8
- export { getContinueChangeSkillTemplate, getPsContinueCommandTemplate } from './workflows/continue-change.js';
9
7
  export { getApplyChangeSkillTemplate, getPsApplyCommandTemplate } from './workflows/apply-change.js';
10
- export { getFfChangeSkillTemplate, getPsFfCommandTemplate } from './workflows/ff-change.js';
11
- export { getCompleteChangeSkillTemplate, getPsCompleteCommandTemplate } from './workflows/archive-change.js';
12
- export { getBulkArchiveChangeSkillTemplate, getPsBulkArchiveCommandTemplate } from './workflows/bulk-archive-change.js';
13
- export { getVerifyChangeSkillTemplate, getPsVerifyCommandTemplate } from './workflows/verify-change.js';
14
- export { getOnboardSkillTemplate, getPsOnboardCommandTemplate } from './workflows/onboard.js';
8
+ export { getCompleteChangeSkillTemplate, getPsCompleteCommandTemplate } from './workflows/complete-change.js';
15
9
  export { getProposeSkillTemplate, getPsProposeCommandTemplate } from './workflows/propose.js';
16
10
  export { getFeedbackSkillTemplate } from './workflows/feedback.js';
17
11
  // Trello-specific workflows
@@ -118,10 +118,35 @@ function getApplyInstructions() {
118
118
  > - Descrição do PR: use o template definido em \`pr.description.template\`
119
119
  > - Ao abrir o PR: \`<"comente o link do PR nesta task" se pr.comments.linkInTask: true, senão omita>\`
120
120
 
121
- The agent MUST create the branch with the configured pattern before making any code changes.
122
121
  Template variables available: \`{change-name}\` = current change name, \`{type}\` = feat/fix/chore, \`{ticket}\` = ticket ID if available.
123
122
 
124
- **If \`pscode/config.yaml\` does not exist, or \`pr.enabled: false\`, or file not found:** continue normally without any PR instructions.
123
+ **Detect whether a PR already exists for this change** (it may have been opened in \`/ps:propose\`). Resolve the branch name from \`pr.branch.pattern\`, then check the current branch and its PR:
124
+ \`\`\`bash
125
+ git checkout <branch> # if it already exists; otherwise it will be created below
126
+ gh pr view --json state,url
127
+ \`\`\`
128
+
129
+ - **If a PR already exists** (the \`gh pr view\` returns an open PR): do NOT open another — just continue working on the existing PR. Save its URL as \`prUrl\`.
130
+
131
+ - **If NO PR exists:** open one in **DRAFT automatically, without asking the user**:
132
+ 1. Create the branch with the configured \`pr.branch.pattern\` if it does not exist yet (\`git checkout -b <branch>\`) — the agent MUST be on this branch before making any code changes.
133
+ 2. Commit any pending planning artifacts: \`git add -A && git commit -m "chore(<change-name>): planning artifacts"\` (skip if nothing to commit).
134
+ 3. Push and set upstream: \`git push -u origin <branch>\`.
135
+ 4. Open the PR in DRAFT, deriving the title from \`pr.title.template\` and the body from \`pr.description.template\`:
136
+ \`gh pr create --draft --title "<resolved title>" --body "<resolved description>"\`.
137
+ 5. Capture the PR URL as \`prUrl\`.
138
+
139
+ **Comentário do link no tracker:** after opening a PR (or detecting an existing one just opened), if \`pr.comments.linkInTask: true\` and a Trello \`cardId\` was saved in Step 2, comment the PR link on the card:
140
+ \`\`\`tool
141
+ mcp__claude_ai_Trello_Custom__add_comment
142
+ card_id: "<cardId>"
143
+ text: |
144
+ 🔀 Pull Request (DRAFT): <prUrl>
145
+ \`\`\`
146
+
147
+ **Tratamento de falha (não-bloqueante):** if \`gh\` or \`git\` fails — \`gh\` not installed, not authenticated, or no GitHub remote — **do NOT block**: state what failed and how to fix it (e.g., \`gh auth login\`), ask whether the user wants the agent to resolve it in parallel, and **continue the implementation regardless**. The branch and local commits are preserved.
148
+
149
+ **If \`pscode/config.yaml\` does not exist, or \`pr.enabled: false\`, or file not found:** continue normally without any PR instructions — no branch, no PR.
125
150
 
126
151
  6. **Show current progress**
127
152
 
@@ -7,4 +7,4 @@
7
7
  import type { SkillTemplate, CommandTemplate } from '../types.js';
8
8
  export declare function getCompleteChangeSkillTemplate(): SkillTemplate;
9
9
  export declare function getPsCompleteCommandTemplate(): CommandTemplate;
10
- //# sourceMappingURL=archive-change.d.ts.map
10
+ //# sourceMappingURL=complete-change.d.ts.map
@@ -1,6 +1,6 @@
1
1
  export function getCompleteChangeSkillTemplate() {
2
2
  return {
3
- name: 'pscode-archive-change',
3
+ name: 'pscode-complete-change',
4
4
  description: 'Complete a completed change. Use when the user wants to finalize and complete a change after implementation is complete.',
5
5
  instructions: getArchiveInstructions(),
6
6
  compatibility: 'Requires pscode CLI.',
@@ -223,4 +223,4 @@ Target archive directory already exists.
223
223
  - All content written to Trello must be in Portuguese
224
224
  `;
225
225
  }
226
- //# sourceMappingURL=archive-change.js.map
226
+ //# sourceMappingURL=complete-change.js.map