@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.
- package/dist/core/init.d.ts +0 -2
- package/dist/core/init.js +7 -77
- package/dist/core/profile-sync-drift.js +1 -15
- package/dist/core/profiles.d.ts +1 -1
- package/dist/core/profiles.js +0 -13
- package/dist/core/shared/index.d.ts +1 -0
- package/dist/core/shared/index.js +1 -0
- package/dist/core/shared/prune-orphans.d.ts +39 -0
- package/dist/core/shared/prune-orphans.js +149 -0
- package/dist/core/shared/skill-generation.js +2 -14
- package/dist/core/shared/tool-detection.d.ts +2 -2
- package/dist/core/shared/tool-detection.js +1 -13
- package/dist/core/templates/skill-templates.d.ts +1 -7
- package/dist/core/templates/skill-templates.js +1 -7
- package/dist/core/templates/workflows/apply-change.js +27 -2
- package/dist/core/templates/workflows/{archive-change.d.ts → complete-change.d.ts} +1 -1
- package/dist/core/templates/workflows/{archive-change.js → complete-change.js} +2 -2
- package/dist/core/templates/workflows/propose.js +56 -1
- package/dist/core/update.d.ts +0 -20
- package/dist/core/update.js +29 -115
- package/package.json +1 -1
- package/dist/core/templates/workflows/bulk-archive-change.d.ts +0 -10
- package/dist/core/templates/workflows/bulk-archive-change.js +0 -491
- package/dist/core/templates/workflows/continue-change.d.ts +0 -10
- package/dist/core/templates/workflows/continue-change.js +0 -233
- package/dist/core/templates/workflows/ff-change.d.ts +0 -10
- package/dist/core/templates/workflows/ff-change.js +0 -199
- package/dist/core/templates/workflows/new-change.d.ts +0 -10
- package/dist/core/templates/workflows/new-change.js +0 -142
- package/dist/core/templates/workflows/onboard.d.ts +0 -10
- package/dist/core/templates/workflows/onboard.js +0 -606
- package/dist/core/templates/workflows/verify-change.d.ts +0 -10
- package/dist/core/templates/workflows/verify-change.js +0 -337
|
@@ -64,12 +64,52 @@ When ready to implement, run /ps:apply
|
|
|
64
64
|
|
|
65
65
|
Os artefatos gerados a partir do Passo 2 SHALL refletir esse entendimento refinado.
|
|
66
66
|
|
|
67
|
+
1c. **PR Integration — abrir PR draft no início (opcional)**
|
|
68
|
+
|
|
69
|
+
Use the **Read tool** (NOT a shell command) to read \`pscode/config.yaml\` from the current working directory.
|
|
70
|
+
If the Read tool returns an error (file not found), or \`pr.enabled\` is not \`true\`, **skip this step entirely** — no PR, no branch, no checkpoint commits — and continue to Step 2. Opening the PR is then left to \`/ps:apply\`. Set \`PR_OPENED = false\`.
|
|
71
|
+
|
|
72
|
+
**If \`pscode/config.yaml\` exists and \`pr.enabled: true\`:**
|
|
73
|
+
|
|
74
|
+
Ask **once**, using the **AskUserQuestion tool**, whether to open the draft PR now:
|
|
75
|
+
> "Quer abrir o Pull Request em DRAFT agora? O PR nasce em draft e cresce junto com o refinamento."
|
|
76
|
+
> - ✅ Sim, abrir o PR draft agora (Recomendada)
|
|
77
|
+
> - ❌ Não, deixar para o apply
|
|
78
|
+
|
|
79
|
+
**If the user declines (Não):** continue the normal flow from Step 2 without any PR steps. Do NOT create a branch or commit automatically. The PR will be opened later by \`/ps:apply\`. Set \`PR_OPENED = false\`.
|
|
80
|
+
|
|
81
|
+
**If the user accepts (Sim):** proceed **without asking for any further authorization**:
|
|
82
|
+
1. Resolve the branch name from \`pr.branch.pattern\`, substituting \`{change-name}\` with the change name, \`{type}\` with feat/fix/chore (infer from the change; default \`feat\`), and \`{ticket}\` with the ticket ID if available.
|
|
83
|
+
2. Create and switch to the branch: \`git checkout -b <branch>\`.
|
|
84
|
+
3. Create the change scaffold (this is Step 2): \`pscode new change "<name>"\`.
|
|
85
|
+
4. Stage and commit the scaffold: \`git add -A && git commit -m "chore(<name>): scaffold change"\`.
|
|
86
|
+
5. Push and set upstream: \`git push -u origin <branch>\`.
|
|
87
|
+
6. Open the PR in **DRAFT**, deriving the title from \`pr.title.template\` and the body from \`pr.description.template\` (substitute \`{change-name}\`/\`{type}\`/\`{ticket}\`):
|
|
88
|
+
\`gh pr create --draft --title "<resolved title>" --body "<resolved description>"\`.
|
|
89
|
+
7. Capture the PR URL from the \`gh\` output, save it as \`prUrl\`, and set \`PR_OPENED = true\`.
|
|
90
|
+
|
|
91
|
+
**Comentário do link no tracker:** after the PR is opened, if \`pr.comments.linkInTask: true\` and a Trello \`cardId\` exists, comment the PR link on the card:
|
|
92
|
+
\`\`\`tool
|
|
93
|
+
mcp__claude_ai_Trello_Custom__add_comment
|
|
94
|
+
card_id: "<cardId>"
|
|
95
|
+
text: |
|
|
96
|
+
🔀 Pull Request (DRAFT) aberto: <prUrl>
|
|
97
|
+
\`\`\`
|
|
98
|
+
The \`cardId\` is resolved in Step 3 — if it is not available yet when the PR is opened, post this comment right after Step 3 instead.
|
|
99
|
+
|
|
100
|
+
**Tratamento de falha (não-bloqueante):** if \`gh\` or \`git\` fails — \`gh\` not installed, not authenticated, or no GitHub remote — **do NOT block**:
|
|
101
|
+
- Clearly state what failed and how to fix it (e.g., "instale o \`gh\` CLI", "rode \`gh auth login\`", "configure um remote GitHub").
|
|
102
|
+
- Ask whether the user wants the agent to resolve it in parallel (e.g., run \`gh auth login\`).
|
|
103
|
+
- **Continue the propose flow regardless.** Any branch already created and local commits are preserved; set \`PR_OPENED = true\` only if the PR was actually opened.
|
|
104
|
+
|
|
67
105
|
2. **Create the change directory**
|
|
68
106
|
\`\`\`bash
|
|
69
107
|
pscode new change "<name>"
|
|
70
108
|
\`\`\`
|
|
71
109
|
This creates a scaffolded change in the planning home resolved by the CLI with \`.pscode.yaml\`.
|
|
72
110
|
|
|
111
|
+
**If you already created the change scaffold in Step 1c** (PR accepted), skip this step — the change directory already exists.
|
|
112
|
+
|
|
73
113
|
3. **Trello Integration (optional)**
|
|
74
114
|
|
|
75
115
|
Use the **Read tool** (NOT a shell command) to read \`pscode/trello.yaml\` from the current working directory.
|
|
@@ -190,6 +230,14 @@ When ready to implement, run /ps:apply
|
|
|
190
230
|
pscode status --change "<name>"
|
|
191
231
|
\`\`\`
|
|
192
232
|
|
|
233
|
+
7. **Checkpoint commit — após gerar os artefatos (only if \`PR_OPENED = true\`)**
|
|
234
|
+
|
|
235
|
+
If a draft PR was opened in Step 1c, commit and push the generated artifacts as a checkpoint so the PR reflects the refined plan:
|
|
236
|
+
\`\`\`bash
|
|
237
|
+
git add -A && git commit -m "docs(<name>): add planning artifacts" && git push
|
|
238
|
+
\`\`\`
|
|
239
|
+
If \`PR_OPENED = false\`, skip — no automatic commits. Failures here are non-blocking (same handling as Step 1c).
|
|
240
|
+
|
|
193
241
|
---
|
|
194
242
|
|
|
195
243
|
## Refinement Validation Loop
|
|
@@ -334,7 +382,14 @@ ${applyNextStep}
|
|
|
334
382
|
- Changes to technical approach → update \`design.md\`
|
|
335
383
|
- Changes to tasks → update \`tasks.md\`
|
|
336
384
|
|
|
337
|
-
3. **
|
|
385
|
+
3. **Checkpoint commit — após o ajuste (only if \`PR_OPENED = true\`)**:
|
|
386
|
+
If a draft PR was opened in Step 1c, commit and push the adjusted artifacts as a checkpoint:
|
|
387
|
+
\`\`\`bash
|
|
388
|
+
git add -A && git commit -m "docs(<name>): refine plan" && git push
|
|
389
|
+
\`\`\`
|
|
390
|
+
If \`PR_OPENED = false\`, skip. Failures here are non-blocking (same handling as Step 1c).
|
|
391
|
+
|
|
392
|
+
4. **Go back to Step R1** and show the updated refinement summary, then **re-run Step R1b**
|
|
338
393
|
so the Trello card description and comment reflect the adjusted plan before asking again.
|
|
339
394
|
Keep looping until the user approves or cancels.
|
|
340
395
|
|
package/dist/core/update.d.ts
CHANGED
|
@@ -38,26 +38,6 @@ export declare class UpdateCommand {
|
|
|
38
38
|
* Displays a note about extra workflows installed that aren't in the active profile.
|
|
39
39
|
*/
|
|
40
40
|
private displayExtraWorkflowsNote;
|
|
41
|
-
/**
|
|
42
|
-
* Removes skill directories for workflows when delivery changed to commands-only.
|
|
43
|
-
* Returns the number of directories removed.
|
|
44
|
-
*/
|
|
45
|
-
private removeSkillDirs;
|
|
46
|
-
/**
|
|
47
|
-
* Removes skill directories for workflows that are no longer selected in the active profile.
|
|
48
|
-
* Returns the number of directories removed.
|
|
49
|
-
*/
|
|
50
|
-
private removeUnselectedSkillDirs;
|
|
51
|
-
/**
|
|
52
|
-
* Removes command files for workflows when delivery changed to skills-only.
|
|
53
|
-
* Returns the number of files removed.
|
|
54
|
-
*/
|
|
55
|
-
private removeCommandFiles;
|
|
56
|
-
/**
|
|
57
|
-
* Removes command files for workflows that are no longer selected in the active profile.
|
|
58
|
-
* Returns the number of files removed.
|
|
59
|
-
*/
|
|
60
|
-
private removeUnselectedCommandFiles;
|
|
61
41
|
/**
|
|
62
42
|
* Detect and handle legacy Pscode artifacts.
|
|
63
43
|
* Unlike init, update warns but continues if legacy files found in non-interactive mode.
|
package/dist/core/update.js
CHANGED
|
@@ -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
|
|
19
|
+
import { getProfileWorkflows, isValidProfile, DEFAULT_PROFILE } from './profiles.js';
|
|
21
20
|
import { getAvailableTools } from './available-tools.js';
|
|
22
|
-
import {
|
|
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
|
-
//
|
|
154
|
-
|
|
155
|
-
|
|
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:
|
|
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,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
|