@thiagodiogo/pscode 1.0.0 → 1.0.1
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/README.md +2 -2
- package/dist/cli/index.js +6 -6
- package/dist/commands/config.d.ts +4 -12
- package/dist/commands/config.js +69 -242
- package/dist/core/change-metadata/schema.d.ts +1 -0
- package/dist/core/change-metadata/schema.js +1 -0
- package/dist/core/{archive.d.ts → complete.d.ts} +2 -2
- package/dist/core/{archive.js → complete.js} +28 -5
- package/dist/core/completions/command-registry.js +5 -5
- package/dist/core/config-schema.d.ts +1 -5
- package/dist/core/config-schema.js +2 -5
- package/dist/core/global-config.d.ts +1 -3
- package/dist/core/global-config.js +1 -1
- package/dist/core/init.d.ts +2 -0
- package/dist/core/init.js +81 -20
- package/dist/core/jira-transition.d.ts +16 -0
- package/dist/core/jira-transition.js +29 -0
- package/dist/core/migration.d.ts +3 -12
- package/dist/core/migration.js +10 -72
- package/dist/core/presets/dixi.d.ts +32 -0
- package/dist/core/presets/dixi.js +405 -0
- package/dist/core/profile-sync-drift.js +9 -1
- package/dist/core/profiles.d.ts +23 -21
- package/dist/core/profiles.js +28 -24
- package/dist/core/shared/skill-generation.js +3 -3
- package/dist/core/shared/tool-detection.d.ts +1 -1
- package/dist/core/shared/tool-detection.js +1 -1
- package/dist/core/templates/skill-templates.d.ts +1 -1
- package/dist/core/templates/skill-templates.js +1 -1
- package/dist/core/templates/workflows/apply-change.js +3 -3
- package/dist/core/templates/workflows/archive-change.d.ts +2 -2
- package/dist/core/templates/workflows/archive-change.js +10 -10
- package/dist/core/templates/workflows/onboard.js +9 -9
- package/dist/core/update.d.ts +1 -6
- package/dist/core/update.js +5 -29
- package/dist/core/workspace/foundation.d.ts +1 -1
- package/dist/core/workspace/foundation.js +1 -1
- package/dist/core/workspace/legacy-state.js +1 -1
- package/dist/core/workspace/skills.d.ts +4 -3
- package/dist/core/workspace/skills.js +3 -3
- package/package.json +4 -3
- package/pscode/content/dixi/architectures/feature-sliced-react/eslint-architecture.mjs.template +44 -0
- package/pscode/content/dixi/architectures/feature-sliced-react/features/README.md.template +30 -0
- package/pscode/content/dixi/architectures/feature-sliced-react/skeleton.yaml +8 -0
- package/pscode/content/dixi/architectures/hexagonal-spring/ArchitectureTest.java.template +41 -0
- package/pscode/content/dixi/architectures/hexagonal-spring/skeleton.yaml +11 -0
- package/pscode/content/dixi/claude-runtime/CLAUDE.md.java.template +62 -0
- package/pscode/content/dixi/claude-runtime/CLAUDE.md.react.template +74 -0
- package/pscode/content/dixi/claude-runtime/commands/adr.md +75 -0
- package/pscode/content/dixi/claude-runtime/commands/arch-check.md +64 -0
- package/pscode/content/dixi/claude-runtime/commands/dod.md +66 -0
- package/pscode/content/dixi/claude-runtime/commands/jira-draft.md +80 -0
- package/pscode/content/dixi/claude-runtime/commands/jira-setup.md +105 -0
- package/pscode/content/dixi/claude-runtime/commands/jira-sync.md +69 -0
- package/pscode/content/dixi/claude-runtime/commands/rfc.md +73 -0
- package/pscode/content/dixi/claude-runtime/hooks/arch-guard.mjs +101 -0
- package/pscode/content/dixi/claude-runtime/hooks/jira-context.mjs +60 -0
- package/pscode/content/dixi/claude-runtime/skills/pstld-arch-guardian.md +101 -0
- package/pscode/content/dixi/claude-runtime/skills/pstld-commit-crafter.md +98 -0
- package/pscode/content/dixi/claude-runtime/skills/pstld-jira-context.md +64 -0
- package/pscode/content/dixi/context/java/architecture.md +143 -0
- package/pscode/content/dixi/context/java/naming.md +62 -0
- package/pscode/content/dixi/context/java/testing.md +162 -0
- package/pscode/content/dixi/context/react/architecture.md +119 -0
- package/pscode/content/dixi/context/react/naming.md +129 -0
- package/pscode/content/dixi/context/react/testing.md +141 -0
- package/pscode/content/dixi/context/shared/commits.md +47 -0
- package/pscode/content/dixi/context/shared/dev-flow.md +53 -0
- package/pscode/content/dixi/context/shared/dod.md +38 -0
- package/pscode/content/dixi/context/shared/pr-flow.md +53 -0
- package/pscode/content/dixi/kit/java/.editorconfig +25 -0
- package/pscode/content/dixi/kit/java/.github/workflows/ci-java.yml +68 -0
- package/pscode/content/dixi/kit/java/.husky/commit-msg +2 -0
- package/pscode/content/dixi/kit/react/.editorconfig +20 -0
- package/pscode/content/dixi/kit/react/.github/workflows/ci-react.yml +80 -0
- package/pscode/content/dixi/kit/react/.husky/commit-msg +2 -0
- package/pscode/content/dixi/kit/react/.husky/pre-commit +2 -0
- package/pscode/content/dixi/kit/react/lint-staged.config.mjs +4 -0
- package/pscode/content/dixi/kit/shared/.commitlintrc.yml +15 -0
- package/pscode/content/dixi/kit/shared/.github/pull_request_template.md +24 -0
- package/schemas/pstld-workflow/schema.yaml +67 -0
- package/schemas/pstld-workflow/templates/design.md +15 -0
- package/schemas/pstld-workflow/templates/rfc.md +26 -0
- package/schemas/pstld-workflow/templates/tasks.md +15 -0
|
@@ -5,16 +5,12 @@ import { z } from 'zod';
|
|
|
5
5
|
*/
|
|
6
6
|
export declare const GlobalConfigSchema: z.ZodObject<{
|
|
7
7
|
featureFlags: z.ZodDefault<z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodBoolean>>>;
|
|
8
|
-
profile: z.ZodDefault<z.ZodOptional<z.
|
|
9
|
-
core: "core";
|
|
10
|
-
custom: "custom";
|
|
11
|
-
}>>>;
|
|
8
|
+
profile: z.ZodDefault<z.ZodOptional<z.ZodString>>;
|
|
12
9
|
delivery: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
13
10
|
commands: "commands";
|
|
14
11
|
skills: "skills";
|
|
15
12
|
both: "both";
|
|
16
13
|
}>>>;
|
|
17
|
-
workflows: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
18
14
|
}, z.core.$loose>;
|
|
19
15
|
export type GlobalConfigType = z.infer<typeof GlobalConfigSchema>;
|
|
20
16
|
/**
|
|
@@ -10,16 +10,13 @@ export const GlobalConfigSchema = z
|
|
|
10
10
|
.optional()
|
|
11
11
|
.default({}),
|
|
12
12
|
profile: z
|
|
13
|
-
.
|
|
13
|
+
.string()
|
|
14
14
|
.optional()
|
|
15
15
|
.default('core'),
|
|
16
16
|
delivery: z
|
|
17
17
|
.enum(['both', 'skills', 'commands'])
|
|
18
18
|
.optional()
|
|
19
19
|
.default('both'),
|
|
20
|
-
workflows: z
|
|
21
|
-
.array(z.string())
|
|
22
|
-
.optional(),
|
|
23
20
|
})
|
|
24
21
|
.passthrough();
|
|
25
22
|
/**
|
|
@@ -30,7 +27,7 @@ export const DEFAULT_CONFIG = {
|
|
|
30
27
|
profile: 'core',
|
|
31
28
|
delivery: 'both',
|
|
32
29
|
};
|
|
33
|
-
const KNOWN_TOP_LEVEL_KEYS = new Set([...Object.keys(DEFAULT_CONFIG)
|
|
30
|
+
const KNOWN_TOP_LEVEL_KEYS = new Set([...Object.keys(DEFAULT_CONFIG)]);
|
|
34
31
|
/**
|
|
35
32
|
* Validate a config key path for CLI set operations.
|
|
36
33
|
* Unknown top-level keys are rejected unless explicitly allowed by the caller.
|
|
@@ -1,13 +1,11 @@
|
|
|
1
1
|
export declare const GLOBAL_CONFIG_DIR_NAME = "pscode";
|
|
2
2
|
export declare const GLOBAL_CONFIG_FILE_NAME = "config.json";
|
|
3
3
|
export declare const GLOBAL_DATA_DIR_NAME = "pscode";
|
|
4
|
-
export type Profile = 'core' | 'custom';
|
|
5
4
|
export type Delivery = 'both' | 'skills' | 'commands';
|
|
6
5
|
export interface GlobalConfig {
|
|
7
6
|
featureFlags?: Record<string, boolean>;
|
|
8
|
-
profile?:
|
|
7
|
+
profile?: string;
|
|
9
8
|
delivery?: Delivery;
|
|
10
|
-
workflows?: string[];
|
|
11
9
|
}
|
|
12
10
|
/**
|
|
13
11
|
* Gets the global configuration directory path following XDG Base Directory Specification.
|
package/dist/core/init.d.ts
CHANGED
|
@@ -32,6 +32,8 @@ export declare class InitCommand {
|
|
|
32
32
|
private generateSkillsAndCommands;
|
|
33
33
|
private createConfig;
|
|
34
34
|
private displaySuccessMessage;
|
|
35
|
+
private generateJiraFiles;
|
|
36
|
+
private handleDixiExtras;
|
|
35
37
|
private startSpinner;
|
|
36
38
|
private removeSkillDirs;
|
|
37
39
|
private removeCommandFiles;
|
package/dist/core/init.js
CHANGED
|
@@ -21,7 +21,9 @@ import { detectLegacyToolArtifacts, runLegacyToolMigration, formatLegacyToolDete
|
|
|
21
21
|
import { runTrelloInitPrompt } from './trello-init-prompt.js';
|
|
22
22
|
import { getToolsWithSkillsDir, getToolStates, getSkillTemplates, getCommandContents, generateSkillContent, } from './shared/index.js';
|
|
23
23
|
import { getGlobalConfig } from './global-config.js';
|
|
24
|
-
import { getProfileWorkflows, ALL_WORKFLOWS } from './profiles.js';
|
|
24
|
+
import { getProfileWorkflows, isValidProfile, DEFAULT_PROFILE, PROFILES, ALL_WORKFLOWS } from './profiles.js';
|
|
25
|
+
import { detectDixiStack, getDixiStackFamily, getDixiStackLabel, installDixiExtras } from './presets/dixi.js';
|
|
26
|
+
import { stringify as stringifyYaml } from 'yaml';
|
|
25
27
|
import { getAvailableTools } from './available-tools.js';
|
|
26
28
|
import { migrateIfNeeded } from './migration.js';
|
|
27
29
|
const require = createRequire(import.meta.url);
|
|
@@ -41,7 +43,7 @@ const WORKFLOW_TO_SKILL_DIR = {
|
|
|
41
43
|
'apply': 'pscode-apply-change',
|
|
42
44
|
'ff': 'pscode-ff-change',
|
|
43
45
|
'sync': 'pscode-sync-specs',
|
|
44
|
-
'
|
|
46
|
+
'complete': 'pscode-archive-change',
|
|
45
47
|
'bulk-archive': 'pscode-bulk-archive-change',
|
|
46
48
|
'verify': 'pscode-verify-change',
|
|
47
49
|
'onboard': 'pscode-onboard',
|
|
@@ -49,6 +51,14 @@ const WORKFLOW_TO_SKILL_DIR = {
|
|
|
49
51
|
// Trello-specific workflows
|
|
50
52
|
'trello-setup': 'pscode-trello-setup',
|
|
51
53
|
'draft': 'pscode-trello-draft',
|
|
54
|
+
// Dixi-specific workflows
|
|
55
|
+
'rfc': 'pscode-dixi-rfc',
|
|
56
|
+
'design': 'pscode-dixi-design',
|
|
57
|
+
'tasks': 'pscode-dixi-tasks',
|
|
58
|
+
'arch-check': 'pscode-dixi-arch-check',
|
|
59
|
+
'adr': 'pscode-dixi-adr',
|
|
60
|
+
'jira-sync': 'pscode-dixi-jira-sync',
|
|
61
|
+
'dod': 'pscode-dixi-dod',
|
|
52
62
|
};
|
|
53
63
|
// -----------------------------------------------------------------------------
|
|
54
64
|
// Init Command Class
|
|
@@ -101,6 +111,13 @@ export class InitCommand {
|
|
|
101
111
|
const trelloConfigured = await this.handleTrelloSetup(pscodePath);
|
|
102
112
|
// Generate skills and commands for each tool
|
|
103
113
|
const results = await this.generateSkillsAndCommands(projectPath, validatedTools);
|
|
114
|
+
// Dixi profile extras: stack detection and .pscode-dixi.yaml
|
|
115
|
+
await this.handleDixiExtras(projectPath);
|
|
116
|
+
// Dixi profile: generate JIRA integration files
|
|
117
|
+
const resolvedProfile = this.resolveProfileOverride() ?? (isValidProfile(getGlobalConfig().profile ?? '') ? getGlobalConfig().profile : DEFAULT_PROFILE);
|
|
118
|
+
if (resolvedProfile === 'dixi') {
|
|
119
|
+
await this.generateJiraFiles(projectPath);
|
|
120
|
+
}
|
|
104
121
|
// Create config.yaml if needed
|
|
105
122
|
const configStatus = await this.createConfig(pscodePath, extendMode);
|
|
106
123
|
// Display success message
|
|
@@ -128,10 +145,11 @@ export class InitCommand {
|
|
|
128
145
|
if (this.profileOverride === undefined) {
|
|
129
146
|
return undefined;
|
|
130
147
|
}
|
|
131
|
-
if (this.profileOverride
|
|
148
|
+
if (isValidProfile(this.profileOverride)) {
|
|
132
149
|
return this.profileOverride;
|
|
133
150
|
}
|
|
134
|
-
|
|
151
|
+
const available = Object.keys(PROFILES).join(', ');
|
|
152
|
+
throw new Error(`Invalid profile "${this.profileOverride}". Available profiles: ${available}`);
|
|
135
153
|
}
|
|
136
154
|
// ═══════════════════════════════════════════════════════════
|
|
137
155
|
// LEGACY TOOL MIGRATION
|
|
@@ -431,14 +449,9 @@ export class InitCommand {
|
|
|
431
449
|
let removedSkillCount = 0;
|
|
432
450
|
// Read global config for profile and delivery settings (use --profile override if set)
|
|
433
451
|
const globalConfig = getGlobalConfig();
|
|
434
|
-
const profile = this.resolveProfileOverride() ?? globalConfig.profile ?? '
|
|
452
|
+
const profile = this.resolveProfileOverride() ?? (isValidProfile(globalConfig.profile ?? '') ? globalConfig.profile : DEFAULT_PROFILE);
|
|
435
453
|
const delivery = globalConfig.delivery ?? 'both';
|
|
436
|
-
const
|
|
437
|
-
// Trello workflows are always generated regardless of profile, so users can
|
|
438
|
-
// run /ps:trello-setup to configure the integration at any time.
|
|
439
|
-
const TRELLO_WORKFLOWS = ['trello-setup', 'task', 'draft'];
|
|
440
|
-
const workflowsSet = new Set([...profileWorkflows, ...TRELLO_WORKFLOWS]);
|
|
441
|
-
const workflows = [...workflowsSet];
|
|
454
|
+
const workflows = [...getProfileWorkflows(profile)];
|
|
442
455
|
// Get skill and command templates filtered by profile workflows
|
|
443
456
|
const shouldGenerateSkills = delivery !== 'commands';
|
|
444
457
|
const shouldGenerateCommands = delivery !== 'skills';
|
|
@@ -541,15 +554,13 @@ export class InitCommand {
|
|
|
541
554
|
if (results.refreshedTools.length > 0) {
|
|
542
555
|
console.log(`Refreshed: ${results.refreshedTools.map((t) => t.name).join(', ')}`);
|
|
543
556
|
}
|
|
544
|
-
// Show counts
|
|
557
|
+
// Show counts
|
|
545
558
|
const successfulTools = [...results.createdTools, ...results.refreshedTools];
|
|
546
559
|
if (successfulTools.length > 0) {
|
|
547
560
|
const globalConfig = getGlobalConfig();
|
|
548
|
-
const profile = this.
|
|
561
|
+
const profile = this.resolveProfileOverride() ?? (isValidProfile(globalConfig.profile ?? '') ? globalConfig.profile : DEFAULT_PROFILE);
|
|
549
562
|
const delivery = globalConfig.delivery ?? 'both';
|
|
550
|
-
const
|
|
551
|
-
const TRELLO_WORKFLOWS = ['trello-setup', 'task', 'draft'];
|
|
552
|
-
const workflows = [...new Set([...profileWorkflows, ...TRELLO_WORKFLOWS])];
|
|
563
|
+
const workflows = [...getProfileWorkflows(profile)];
|
|
553
564
|
const toolDirs = [...new Set(successfulTools.map((t) => t.skillsDir))].join(', ');
|
|
554
565
|
const skillCount = delivery !== 'commands' ? getSkillTemplates(workflows).length : 0;
|
|
555
566
|
const commandCount = delivery !== 'skills' ? getCommandContents(workflows).length : 0;
|
|
@@ -591,10 +602,10 @@ export class InitCommand {
|
|
|
591
602
|
else {
|
|
592
603
|
console.log(chalk.dim(`Config: skipped (non-interactive mode)`));
|
|
593
604
|
}
|
|
594
|
-
// Getting started
|
|
605
|
+
// Getting started
|
|
595
606
|
const globalCfg = getGlobalConfig();
|
|
596
|
-
const activeProfile = this.
|
|
597
|
-
const activeWorkflows = [...getProfileWorkflows(activeProfile
|
|
607
|
+
const activeProfile = this.resolveProfileOverride() ?? (isValidProfile(globalCfg.profile ?? '') ? globalCfg.profile : DEFAULT_PROFILE);
|
|
608
|
+
const activeWorkflows = [...getProfileWorkflows(activeProfile)];
|
|
598
609
|
console.log();
|
|
599
610
|
if (activeWorkflows.includes('propose')) {
|
|
600
611
|
console.log(chalk.bold('Getting started:'));
|
|
@@ -605,7 +616,7 @@ export class InitCommand {
|
|
|
605
616
|
console.log(' Start your first change: /ps:new "your idea"');
|
|
606
617
|
}
|
|
607
618
|
else {
|
|
608
|
-
console.log("Done. Run 'pscode config profile' to
|
|
619
|
+
console.log("Done. Run 'pscode config profile' to switch profiles.");
|
|
609
620
|
}
|
|
610
621
|
// Trello status
|
|
611
622
|
if (trelloConfigured) {
|
|
@@ -625,6 +636,56 @@ export class InitCommand {
|
|
|
625
636
|
}
|
|
626
637
|
console.log();
|
|
627
638
|
}
|
|
639
|
+
async generateJiraFiles(projectPath) {
|
|
640
|
+
const pastelsddPath = path.join(projectPath, 'pastelsdd');
|
|
641
|
+
await FileSystemUtils.createDirectory(pastelsddPath);
|
|
642
|
+
const jiraYamlPath = path.join(pastelsddPath, 'jira.yaml');
|
|
643
|
+
if (!fs.existsSync(jiraYamlPath)) {
|
|
644
|
+
const content = `project_key: ""\nboard_url: ""\nconfigured: false\ntransitions:\n done: ""\n`;
|
|
645
|
+
await FileSystemUtils.writeFile(jiraYamlPath, content);
|
|
646
|
+
}
|
|
647
|
+
const mcpJsonPath = path.join(projectPath, '.mcp.json');
|
|
648
|
+
let mcpConfig = {};
|
|
649
|
+
if (fs.existsSync(mcpJsonPath)) {
|
|
650
|
+
try {
|
|
651
|
+
const raw = fs.readFileSync(mcpJsonPath, 'utf-8');
|
|
652
|
+
mcpConfig = JSON.parse(raw);
|
|
653
|
+
}
|
|
654
|
+
catch {
|
|
655
|
+
console.log('Aviso: .mcp.json inválido — recriando com entrada Atlassian.');
|
|
656
|
+
mcpConfig = {};
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
const mcpServers = (mcpConfig.mcpServers ?? {});
|
|
660
|
+
if (!mcpServers['atlassian']) {
|
|
661
|
+
mcpServers['atlassian'] = {
|
|
662
|
+
command: 'npx',
|
|
663
|
+
args: ['-y', 'mcp-remote', 'https://mcp.atlassian.com/v1/sse'],
|
|
664
|
+
};
|
|
665
|
+
mcpConfig.mcpServers = mcpServers;
|
|
666
|
+
await FileSystemUtils.writeFile(mcpJsonPath, JSON.stringify(mcpConfig, null, 2) + '\n');
|
|
667
|
+
}
|
|
668
|
+
console.log('JIRA: edite pastelsdd/jira.yaml com project_key e board_url, depois use /pstld:jira-sync para testar a conexão.');
|
|
669
|
+
}
|
|
670
|
+
async handleDixiExtras(projectPath) {
|
|
671
|
+
const globalConfig = getGlobalConfig();
|
|
672
|
+
const profile = this.resolveProfileOverride() ?? (isValidProfile(globalConfig.profile ?? '') ? globalConfig.profile : DEFAULT_PROFILE);
|
|
673
|
+
if (profile !== 'dixi')
|
|
674
|
+
return;
|
|
675
|
+
const stack = detectDixiStack(projectPath);
|
|
676
|
+
const label = getDixiStackLabel(stack);
|
|
677
|
+
if (stack) {
|
|
678
|
+
console.log(`Dixi: stack detectada — ${label}`);
|
|
679
|
+
}
|
|
680
|
+
else {
|
|
681
|
+
console.log('Dixi: stack não detectada, usando configuração genérica');
|
|
682
|
+
}
|
|
683
|
+
installDixiExtras(projectPath, stack);
|
|
684
|
+
const family = getDixiStackFamily(stack);
|
|
685
|
+
const yamlContent = stringifyYaml({ stack, family, detectedAt: new Date().toISOString() });
|
|
686
|
+
const dixiYamlPath = path.join(projectPath, '.pscode-dixi.yaml');
|
|
687
|
+
await FileSystemUtils.writeFile(dixiYamlPath, yamlContent);
|
|
688
|
+
}
|
|
628
689
|
startSpinner(text) {
|
|
629
690
|
return ora({
|
|
630
691
|
text,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
interface JiraConfig {
|
|
2
|
+
project_key?: string;
|
|
3
|
+
configured?: boolean;
|
|
4
|
+
transitions?: {
|
|
5
|
+
done?: string;
|
|
6
|
+
};
|
|
7
|
+
}
|
|
8
|
+
export interface JiraTransitionResult {
|
|
9
|
+
attempted: boolean;
|
|
10
|
+
success: boolean;
|
|
11
|
+
warning?: string;
|
|
12
|
+
}
|
|
13
|
+
export declare function readJiraConfig(projectDir: string): Promise<JiraConfig | null>;
|
|
14
|
+
export declare function tryTransitionJiraIssue(issueKey: string, transitionId: string): Promise<JiraTransitionResult>;
|
|
15
|
+
export {};
|
|
16
|
+
//# sourceMappingURL=jira-transition.d.ts.map
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { promises as fs } from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { parse as parseYaml } from 'yaml';
|
|
4
|
+
export async function readJiraConfig(projectDir) {
|
|
5
|
+
const jiraYamlPath = path.join(projectDir, 'pastelsdd', 'jira.yaml');
|
|
6
|
+
try {
|
|
7
|
+
const content = await fs.readFile(jiraYamlPath, 'utf-8');
|
|
8
|
+
return parseYaml(content);
|
|
9
|
+
}
|
|
10
|
+
catch {
|
|
11
|
+
return null;
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export async function tryTransitionJiraIssue(issueKey, transitionId) {
|
|
15
|
+
// Validate issueKey format
|
|
16
|
+
if (!/^[A-Z]+-[0-9]+$/.test(issueKey)) {
|
|
17
|
+
return {
|
|
18
|
+
attempted: false,
|
|
19
|
+
success: false,
|
|
20
|
+
warning: `jiraIssueKey "${issueKey}" não corresponde ao formato esperado [A-Z]+-[0-9]+. Transição JIRA ignorada.`,
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
// The CLI cannot call the Atlassian MCP server directly.
|
|
24
|
+
// Log a message informing the user to transition manually or via /pstld:jira-sync.
|
|
25
|
+
console.log(`JIRA: issue ${issueKey} vinculada (transição "${transitionId}" pendente). ` +
|
|
26
|
+
`Use /pstld:jira-sync para confirmar o status ou transite manualmente.`);
|
|
27
|
+
return { attempted: true, success: true };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=jira-transition.js.map
|
package/dist/core/migration.d.ts
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Migration Utilities
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Called by
|
|
4
|
+
* Scans installed workflow artifacts across tools.
|
|
5
|
+
* Called by init and update commands.
|
|
6
6
|
*/
|
|
7
7
|
import type { AIToolOption } from './config.js';
|
|
8
8
|
/**
|
|
@@ -10,14 +10,5 @@ import type { AIToolOption } from './config.js';
|
|
|
10
10
|
* the union of installed workflow IDs.
|
|
11
11
|
*/
|
|
12
12
|
export declare function scanInstalledWorkflows(projectPath: string, tools: AIToolOption[]): string[];
|
|
13
|
-
|
|
14
|
-
* Performs one-time migration if the global config does not yet have a profile field.
|
|
15
|
-
* Called by both init and update before profile resolution.
|
|
16
|
-
*
|
|
17
|
-
* - If no profile field exists and workflows are installed: sets profile to 'custom'
|
|
18
|
-
* with the detected workflows, preserving the user's existing setup.
|
|
19
|
-
* - If no profile field exists and no workflows are installed: no-op (defaults apply).
|
|
20
|
-
* - If profile field already exists: no-op.
|
|
21
|
-
*/
|
|
22
|
-
export declare function migrateIfNeeded(projectPath: string, tools: AIToolOption[]): void;
|
|
13
|
+
export declare function migrateIfNeeded(_projectPath: string, _tools: AIToolOption[]): void;
|
|
23
14
|
//# sourceMappingURL=migration.d.ts.map
|
package/dist/core/migration.js
CHANGED
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Migration Utilities
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
* Called by
|
|
4
|
+
* Scans installed workflow artifacts across tools.
|
|
5
|
+
* Called by init and update commands.
|
|
6
6
|
*/
|
|
7
|
-
import { getGlobalConfig, getGlobalConfigPath, saveGlobalConfig } from './global-config.js';
|
|
8
7
|
import { CommandAdapterRegistry } from './command-generation/index.js';
|
|
9
8
|
import { WORKFLOW_TO_SKILL_DIR } from './profile-sync-drift.js';
|
|
10
9
|
import { ALL_WORKFLOWS } from './profiles.js';
|
|
11
10
|
import path from 'path';
|
|
12
11
|
import * as fs from 'fs';
|
|
13
|
-
|
|
12
|
+
/**
|
|
13
|
+
* Scans installed workflow files across all detected tools and returns
|
|
14
|
+
* the union of installed workflow IDs.
|
|
15
|
+
*/
|
|
16
|
+
export function scanInstalledWorkflows(projectPath, tools) {
|
|
14
17
|
const installed = new Set();
|
|
15
|
-
let hasSkills = false;
|
|
16
|
-
let hasCommands = false;
|
|
17
18
|
for (const tool of tools) {
|
|
18
19
|
if (!tool.skillsDir)
|
|
19
20
|
continue;
|
|
@@ -23,7 +24,6 @@ function scanInstalledWorkflowArtifacts(projectPath, tools) {
|
|
|
23
24
|
const skillFile = path.join(skillsDir, skillDirName, 'SKILL.md');
|
|
24
25
|
if (fs.existsSync(skillFile)) {
|
|
25
26
|
installed.add(workflowId);
|
|
26
|
-
hasSkills = true;
|
|
27
27
|
}
|
|
28
28
|
}
|
|
29
29
|
const adapter = CommandAdapterRegistry.get(tool.value);
|
|
@@ -36,73 +36,11 @@ function scanInstalledWorkflowArtifacts(projectPath, tools) {
|
|
|
36
36
|
: path.join(projectPath, commandPath);
|
|
37
37
|
if (fs.existsSync(fullPath)) {
|
|
38
38
|
installed.add(workflowId);
|
|
39
|
-
hasCommands = true;
|
|
40
39
|
}
|
|
41
40
|
}
|
|
42
41
|
}
|
|
43
|
-
return
|
|
44
|
-
workflows: ALL_WORKFLOWS.filter((workflowId) => installed.has(workflowId)),
|
|
45
|
-
hasSkills,
|
|
46
|
-
hasCommands,
|
|
47
|
-
};
|
|
48
|
-
}
|
|
49
|
-
/**
|
|
50
|
-
* Scans installed workflow files across all detected tools and returns
|
|
51
|
-
* the union of installed workflow IDs.
|
|
52
|
-
*/
|
|
53
|
-
export function scanInstalledWorkflows(projectPath, tools) {
|
|
54
|
-
return scanInstalledWorkflowArtifacts(projectPath, tools).workflows;
|
|
55
|
-
}
|
|
56
|
-
function inferDelivery(artifacts) {
|
|
57
|
-
if (artifacts.hasSkills && artifacts.hasCommands) {
|
|
58
|
-
return 'both';
|
|
59
|
-
}
|
|
60
|
-
if (artifacts.hasCommands) {
|
|
61
|
-
return 'commands';
|
|
62
|
-
}
|
|
63
|
-
return 'skills';
|
|
64
|
-
}
|
|
65
|
-
/**
|
|
66
|
-
* Performs one-time migration if the global config does not yet have a profile field.
|
|
67
|
-
* Called by both init and update before profile resolution.
|
|
68
|
-
*
|
|
69
|
-
* - If no profile field exists and workflows are installed: sets profile to 'custom'
|
|
70
|
-
* with the detected workflows, preserving the user's existing setup.
|
|
71
|
-
* - If no profile field exists and no workflows are installed: no-op (defaults apply).
|
|
72
|
-
* - If profile field already exists: no-op.
|
|
73
|
-
*/
|
|
74
|
-
export function migrateIfNeeded(projectPath, tools) {
|
|
75
|
-
const config = getGlobalConfig();
|
|
76
|
-
// Check raw config file for profile field presence
|
|
77
|
-
const configPath = getGlobalConfigPath();
|
|
78
|
-
let rawConfig = {};
|
|
79
|
-
try {
|
|
80
|
-
if (fs.existsSync(configPath)) {
|
|
81
|
-
rawConfig = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
82
|
-
}
|
|
83
|
-
}
|
|
84
|
-
catch {
|
|
85
|
-
return; // Can't read config, skip migration
|
|
86
|
-
}
|
|
87
|
-
// If profile is already explicitly set, no migration needed
|
|
88
|
-
if (rawConfig.profile !== undefined) {
|
|
89
|
-
return;
|
|
90
|
-
}
|
|
91
|
-
// Scan for installed workflows
|
|
92
|
-
const artifacts = scanInstalledWorkflowArtifacts(projectPath, tools);
|
|
93
|
-
const installedWorkflows = artifacts.workflows;
|
|
94
|
-
if (installedWorkflows.length === 0) {
|
|
95
|
-
// No workflows installed, new user — defaults will apply
|
|
96
|
-
return;
|
|
97
|
-
}
|
|
98
|
-
// Migrate: set profile to custom with detected workflows
|
|
99
|
-
config.profile = 'custom';
|
|
100
|
-
config.workflows = installedWorkflows;
|
|
101
|
-
if (rawConfig.delivery === undefined) {
|
|
102
|
-
config.delivery = inferDelivery(artifacts);
|
|
103
|
-
}
|
|
104
|
-
saveGlobalConfig(config);
|
|
105
|
-
console.log(`Migrated: custom profile with ${installedWorkflows.length} workflows`);
|
|
106
|
-
console.log("New in this version: /ps:propose. Try 'pscode config profile core' for the streamlined experience.");
|
|
42
|
+
return ALL_WORKFLOWS.filter((id) => installed.has(id));
|
|
107
43
|
}
|
|
44
|
+
// No-op kept for call-site compatibility during transition.
|
|
45
|
+
export function migrateIfNeeded(_projectPath, _tools) { }
|
|
108
46
|
//# sourceMappingURL=migration.js.map
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
export type DixiStack = 'java-maven' | 'java-gradle' | 'next' | 'react' | 'node' | 'python';
|
|
2
|
+
export type DixiStackFamily = 'java' | 'react' | 'node' | 'python';
|
|
3
|
+
export declare function detectDixiStack(projectDir: string): DixiStack | null;
|
|
4
|
+
export declare function getDixiStackFamily(stack: DixiStack | null): DixiStackFamily | null;
|
|
5
|
+
export declare function getDixiStackLabel(stack: DixiStack | null): string;
|
|
6
|
+
/**
|
|
7
|
+
* Copies files recursively from sourceDir to targetDir.
|
|
8
|
+
* By default skips files that already exist (brownfield-safe).
|
|
9
|
+
* Files whose basename appears in options.overwrite are always overwritten.
|
|
10
|
+
*/
|
|
11
|
+
export declare function copyKitFiles(sourceDir: string, targetDir: string, options?: {
|
|
12
|
+
overwrite?: string[];
|
|
13
|
+
}): void;
|
|
14
|
+
/**
|
|
15
|
+
* Copies all files from srcDir into <destRoot>/pastelsdd/context/, skipping files that already exist.
|
|
16
|
+
* Creates the destination directory if needed.
|
|
17
|
+
*/
|
|
18
|
+
export declare function copyContextDocs(destRoot: string, srcDir: string): void;
|
|
19
|
+
export declare function installDixiClaudeMd(projectDir: string, family: DixiStackFamily | null): void;
|
|
20
|
+
export declare function detectBasePackage(projectRoot: string): string;
|
|
21
|
+
export declare function applyHexagonalSkeleton(projectRoot: string, basePackage: string): {
|
|
22
|
+
created: number;
|
|
23
|
+
skipped: number;
|
|
24
|
+
};
|
|
25
|
+
export declare function generateArchitectureTest(projectRoot: string, basePackage: string): boolean;
|
|
26
|
+
export declare function applyFeatureSlicedSkeleton(projectRoot: string): {
|
|
27
|
+
created: number;
|
|
28
|
+
skipped: number;
|
|
29
|
+
};
|
|
30
|
+
export declare function installEslintArchitectureTemplate(projectRoot: string): void;
|
|
31
|
+
export declare function installDixiExtras(projectDir: string, stack: DixiStack | null): void;
|
|
32
|
+
//# sourceMappingURL=dixi.d.ts.map
|