@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
|
@@ -0,0 +1,405 @@
|
|
|
1
|
+
import * as fs from 'fs';
|
|
2
|
+
import * as path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { parse as parseYaml } from 'yaml';
|
|
5
|
+
export function detectDixiStack(projectDir) {
|
|
6
|
+
if (fs.existsSync(path.join(projectDir, 'pom.xml')))
|
|
7
|
+
return 'java-maven';
|
|
8
|
+
if (fs.existsSync(path.join(projectDir, 'build.gradle')))
|
|
9
|
+
return 'java-gradle';
|
|
10
|
+
if (fs.existsSync(path.join(projectDir, 'next.config.js')) ||
|
|
11
|
+
fs.existsSync(path.join(projectDir, 'next.config.ts')) ||
|
|
12
|
+
fs.existsSync(path.join(projectDir, 'next.config.mjs')))
|
|
13
|
+
return 'next';
|
|
14
|
+
const pkgPath = path.join(projectDir, 'package.json');
|
|
15
|
+
if (fs.existsSync(pkgPath)) {
|
|
16
|
+
try {
|
|
17
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
18
|
+
const deps = { ...(pkg.dependencies ?? {}), ...(pkg.devDependencies ?? {}) };
|
|
19
|
+
if ('next' in deps)
|
|
20
|
+
return 'next';
|
|
21
|
+
if ('react' in deps)
|
|
22
|
+
return 'react';
|
|
23
|
+
}
|
|
24
|
+
catch {
|
|
25
|
+
// fallback to 'node' when package.json has invalid JSON
|
|
26
|
+
}
|
|
27
|
+
return 'node';
|
|
28
|
+
}
|
|
29
|
+
if (fs.existsSync(path.join(projectDir, 'pyproject.toml')))
|
|
30
|
+
return 'python';
|
|
31
|
+
return null;
|
|
32
|
+
}
|
|
33
|
+
export function getDixiStackFamily(stack) {
|
|
34
|
+
if (stack === null)
|
|
35
|
+
return null;
|
|
36
|
+
if (stack === 'java-maven' || stack === 'java-gradle')
|
|
37
|
+
return 'java';
|
|
38
|
+
if (stack === 'next')
|
|
39
|
+
return 'react';
|
|
40
|
+
return stack;
|
|
41
|
+
}
|
|
42
|
+
export function getDixiStackLabel(stack) {
|
|
43
|
+
if (stack === null)
|
|
44
|
+
return 'desconhecida';
|
|
45
|
+
const labels = {
|
|
46
|
+
'java-maven': 'Java/Maven',
|
|
47
|
+
'java-gradle': 'Java/Gradle',
|
|
48
|
+
'next': 'Next.js',
|
|
49
|
+
'react': 'React',
|
|
50
|
+
'node': 'Node.js',
|
|
51
|
+
'python': 'Python',
|
|
52
|
+
};
|
|
53
|
+
return labels[stack];
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* Copies files recursively from sourceDir to targetDir.
|
|
57
|
+
* By default skips files that already exist (brownfield-safe).
|
|
58
|
+
* Files whose basename appears in options.overwrite are always overwritten.
|
|
59
|
+
*/
|
|
60
|
+
export function copyKitFiles(sourceDir, targetDir, options = {}) {
|
|
61
|
+
if (!fs.existsSync(sourceDir))
|
|
62
|
+
return;
|
|
63
|
+
const overwriteSet = new Set(options.overwrite ?? []);
|
|
64
|
+
function copyDir(src, dest) {
|
|
65
|
+
if (!fs.existsSync(dest)) {
|
|
66
|
+
fs.mkdirSync(dest, { recursive: true });
|
|
67
|
+
}
|
|
68
|
+
const entries = fs.readdirSync(src, { withFileTypes: true });
|
|
69
|
+
for (const entry of entries) {
|
|
70
|
+
const srcPath = path.join(src, entry.name);
|
|
71
|
+
const destPath = path.join(dest, entry.name);
|
|
72
|
+
if (entry.isDirectory()) {
|
|
73
|
+
copyDir(srcPath, destPath);
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
if (fs.existsSync(destPath) && !overwriteSet.has(entry.name)) {
|
|
77
|
+
console.log(` ${entry.name} já existe — pulado`);
|
|
78
|
+
continue;
|
|
79
|
+
}
|
|
80
|
+
const destDirPath = path.dirname(destPath);
|
|
81
|
+
if (!fs.existsSync(destDirPath)) {
|
|
82
|
+
fs.mkdirSync(destDirPath, { recursive: true });
|
|
83
|
+
}
|
|
84
|
+
fs.copyFileSync(srcPath, destPath);
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
copyDir(sourceDir, targetDir);
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Copies all files from srcDir into <destRoot>/pastelsdd/context/, skipping files that already exist.
|
|
92
|
+
* Creates the destination directory if needed.
|
|
93
|
+
*/
|
|
94
|
+
export function copyContextDocs(destRoot, srcDir) {
|
|
95
|
+
if (!fs.existsSync(srcDir))
|
|
96
|
+
return;
|
|
97
|
+
const contextDir = path.join(destRoot, 'pastelsdd', 'context');
|
|
98
|
+
if (!fs.existsSync(contextDir)) {
|
|
99
|
+
fs.mkdirSync(contextDir, { recursive: true });
|
|
100
|
+
}
|
|
101
|
+
const files = fs.readdirSync(srcDir);
|
|
102
|
+
for (const file of files) {
|
|
103
|
+
const src = path.join(srcDir, file);
|
|
104
|
+
const dest = path.join(contextDir, file);
|
|
105
|
+
if (fs.existsSync(dest)) {
|
|
106
|
+
console.log(` ${file} já existe — pulado`);
|
|
107
|
+
continue;
|
|
108
|
+
}
|
|
109
|
+
fs.copyFileSync(src, dest);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
export function installDixiClaudeMd(projectDir, family) {
|
|
113
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
114
|
+
const packageRoot = path.join(path.dirname(currentFile), '..', '..', '..');
|
|
115
|
+
const claudeRuntimeDir = path.join(packageRoot, 'pscode', 'content', 'dixi', 'claude-runtime');
|
|
116
|
+
let templateName;
|
|
117
|
+
if (family === 'java') {
|
|
118
|
+
templateName = 'CLAUDE.md.java.template';
|
|
119
|
+
}
|
|
120
|
+
else if (family === 'react') {
|
|
121
|
+
templateName = 'CLAUDE.md.react.template';
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
templateName = 'CLAUDE.md.java.template';
|
|
125
|
+
console.log('Dixi: stack não detectada, instalando CLAUDE.md genérico (baseado em Java). ' +
|
|
126
|
+
'Edite .pscode-dixi.yaml para corrigir.');
|
|
127
|
+
}
|
|
128
|
+
const templatePath = path.join(claudeRuntimeDir, templateName);
|
|
129
|
+
const templateContent = fs.readFileSync(templatePath, 'utf-8');
|
|
130
|
+
const claudeMdPath = path.join(projectDir, 'CLAUDE.md');
|
|
131
|
+
const marker = '<!-- dixi-constitutional -->';
|
|
132
|
+
if (fs.existsSync(claudeMdPath)) {
|
|
133
|
+
const existing = fs.readFileSync(claudeMdPath, 'utf-8');
|
|
134
|
+
if (existing.includes(marker)) {
|
|
135
|
+
console.log('Dixi: CLAUDE.md já contém seção constitucional — pulando.');
|
|
136
|
+
return;
|
|
137
|
+
}
|
|
138
|
+
fs.writeFileSync(claudeMdPath, existing + '\n' + templateContent, { encoding: 'utf-8' });
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
fs.writeFileSync(claudeMdPath, templateContent, { encoding: 'utf-8' });
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
const PSTLD_COMMANDS_SRC = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'pscode', 'content', 'dixi', 'claude-runtime', 'commands');
|
|
145
|
+
const PSTLD_SKILLS_SRC = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'pscode', 'content', 'dixi', 'claude-runtime', 'skills');
|
|
146
|
+
const HOOKS_SRC = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'pscode', 'content', 'dixi', 'claude-runtime', 'hooks');
|
|
147
|
+
const DIXI_HOOK_ENTRIES = [
|
|
148
|
+
{ event: 'PreToolUse', matcher: 'Edit|Write', command: 'node .claude/hooks/arch-guard.mjs' },
|
|
149
|
+
{ event: 'UserPromptSubmit', matcher: null, command: 'node .claude/hooks/jira-context.mjs' },
|
|
150
|
+
];
|
|
151
|
+
function mergeSettingsHooks(settingsPath) {
|
|
152
|
+
let settings = {};
|
|
153
|
+
if (fs.existsSync(settingsPath)) {
|
|
154
|
+
try {
|
|
155
|
+
settings = JSON.parse(fs.readFileSync(settingsPath, 'utf-8'));
|
|
156
|
+
}
|
|
157
|
+
catch (e) {
|
|
158
|
+
console.log(`Dixi: settings.json inválido — criando novo arquivo. (${e instanceof Error ? e.message : String(e)})`);
|
|
159
|
+
settings = {};
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (!settings.hooks || typeof settings.hooks !== 'object' || Array.isArray(settings.hooks)) {
|
|
163
|
+
settings.hooks = {};
|
|
164
|
+
}
|
|
165
|
+
const hooks = settings.hooks;
|
|
166
|
+
for (const { event, matcher, command } of DIXI_HOOK_ENTRIES) {
|
|
167
|
+
if (!Array.isArray(hooks[event])) {
|
|
168
|
+
hooks[event] = [];
|
|
169
|
+
}
|
|
170
|
+
const eventHooks = hooks[event];
|
|
171
|
+
const alreadyExists = eventHooks.some(entry => Array.isArray(entry.hooks) && entry.hooks.some(h => h.command === command));
|
|
172
|
+
if (!alreadyExists) {
|
|
173
|
+
const entry = {
|
|
174
|
+
hooks: [{ type: 'command', command }],
|
|
175
|
+
};
|
|
176
|
+
if (matcher)
|
|
177
|
+
entry.matcher = matcher;
|
|
178
|
+
eventHooks.push(entry);
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
fs.writeFileSync(settingsPath, JSON.stringify(settings, null, 2), { encoding: 'utf-8' });
|
|
182
|
+
}
|
|
183
|
+
const ARCHITECTURES_BASE = path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', '..', 'pscode', 'content', 'dixi', 'architectures');
|
|
184
|
+
// Task 3.2
|
|
185
|
+
export function detectBasePackage(projectRoot) {
|
|
186
|
+
const pomPath = path.join(projectRoot, 'pom.xml');
|
|
187
|
+
if (!fs.existsSync(pomPath)) {
|
|
188
|
+
console.log('[dixi] detectBasePackage: pom.xml não encontrado — usando fallback com.example.app. Ajuste manualmente o basePackage no ArchitectureTest.java gerado.');
|
|
189
|
+
return 'com.example.app';
|
|
190
|
+
}
|
|
191
|
+
const pomContent = fs.readFileSync(pomPath, 'utf-8');
|
|
192
|
+
const groupIdMatch = pomContent.match(/<groupId>([^<]+)<\/groupId>/);
|
|
193
|
+
const artifactIdMatch = pomContent.match(/<artifactId>([^<]+)<\/artifactId>/);
|
|
194
|
+
if (!groupIdMatch || !artifactIdMatch) {
|
|
195
|
+
console.log('[dixi] detectBasePackage: groupId ou artifactId não encontrado no pom.xml — usando fallback com.example.app.');
|
|
196
|
+
return 'com.example.app';
|
|
197
|
+
}
|
|
198
|
+
const groupId = groupIdMatch[1].trim();
|
|
199
|
+
const artifactId = artifactIdMatch[1].trim().replace(/-/g, '');
|
|
200
|
+
return `${groupId}.${artifactId}`;
|
|
201
|
+
}
|
|
202
|
+
// Task 3.1
|
|
203
|
+
export function applyHexagonalSkeleton(projectRoot, basePackage) {
|
|
204
|
+
const skeletonPath = path.join(ARCHITECTURES_BASE, 'hexagonal-spring', 'skeleton.yaml');
|
|
205
|
+
if (!fs.existsSync(skeletonPath))
|
|
206
|
+
return { created: 0, skipped: 0 };
|
|
207
|
+
const skeletonData = parseYaml(fs.readFileSync(skeletonPath, 'utf-8'));
|
|
208
|
+
const basePackageDir = basePackage.replace(/\./g, '/');
|
|
209
|
+
let created = 0;
|
|
210
|
+
let skipped = 0;
|
|
211
|
+
for (const dir of skeletonData.dirs) {
|
|
212
|
+
const resolvedDir = dir.replace('{basePackageDir}', basePackageDir);
|
|
213
|
+
const dirPath = path.join(projectRoot, resolvedDir);
|
|
214
|
+
const gitkeepPath = path.join(dirPath, '.gitkeep');
|
|
215
|
+
if (!fs.existsSync(dirPath)) {
|
|
216
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
217
|
+
}
|
|
218
|
+
if (!fs.existsSync(gitkeepPath)) {
|
|
219
|
+
fs.writeFileSync(gitkeepPath, '');
|
|
220
|
+
created++;
|
|
221
|
+
}
|
|
222
|
+
else {
|
|
223
|
+
skipped++;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
return { created, skipped };
|
|
227
|
+
}
|
|
228
|
+
// Task 3.3
|
|
229
|
+
export function generateArchitectureTest(projectRoot, basePackage) {
|
|
230
|
+
const templatePath = path.join(ARCHITECTURES_BASE, 'hexagonal-spring', 'ArchitectureTest.java.template');
|
|
231
|
+
if (!fs.existsSync(templatePath))
|
|
232
|
+
return false;
|
|
233
|
+
const basePackageDir = basePackage.replace(/\./g, '/');
|
|
234
|
+
const destDir = path.join(projectRoot, 'src', 'test', 'java', basePackageDir);
|
|
235
|
+
const destPath = path.join(destDir, 'ArchitectureTest.java');
|
|
236
|
+
if (fs.existsSync(destPath)) {
|
|
237
|
+
console.log('[dixi] ArchitectureTest.java: arquivo existente — ignorado');
|
|
238
|
+
return false;
|
|
239
|
+
}
|
|
240
|
+
const template = fs.readFileSync(templatePath, 'utf-8');
|
|
241
|
+
const content = template.replace(/\{basePackage\}/g, basePackage);
|
|
242
|
+
if (!fs.existsSync(destDir)) {
|
|
243
|
+
fs.mkdirSync(destDir, { recursive: true });
|
|
244
|
+
}
|
|
245
|
+
fs.writeFileSync(destPath, content, { encoding: 'utf-8' });
|
|
246
|
+
return true;
|
|
247
|
+
}
|
|
248
|
+
// Task 3.4
|
|
249
|
+
export function applyFeatureSlicedSkeleton(projectRoot) {
|
|
250
|
+
const skeletonPath = path.join(ARCHITECTURES_BASE, 'feature-sliced-react', 'skeleton.yaml');
|
|
251
|
+
if (!fs.existsSync(skeletonPath))
|
|
252
|
+
return { created: 0, skipped: 0 };
|
|
253
|
+
const skeletonData = parseYaml(fs.readFileSync(skeletonPath, 'utf-8'));
|
|
254
|
+
const readmeTemplatePath = path.join(ARCHITECTURES_BASE, 'feature-sliced-react', 'features', 'README.md.template');
|
|
255
|
+
let created = 0;
|
|
256
|
+
let skipped = 0;
|
|
257
|
+
for (const dir of skeletonData.dirs) {
|
|
258
|
+
const dirPath = path.join(projectRoot, dir);
|
|
259
|
+
if (!fs.existsSync(dirPath)) {
|
|
260
|
+
fs.mkdirSync(dirPath, { recursive: true });
|
|
261
|
+
}
|
|
262
|
+
if (dir.endsWith('features')) {
|
|
263
|
+
const readmePath = path.join(dirPath, 'README.md');
|
|
264
|
+
if (!fs.existsSync(readmePath) && fs.existsSync(readmeTemplatePath)) {
|
|
265
|
+
fs.copyFileSync(readmeTemplatePath, readmePath);
|
|
266
|
+
created++;
|
|
267
|
+
}
|
|
268
|
+
else {
|
|
269
|
+
skipped++;
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
const gitkeepPath = path.join(dirPath, '.gitkeep');
|
|
274
|
+
if (!fs.existsSync(gitkeepPath)) {
|
|
275
|
+
fs.writeFileSync(gitkeepPath, '');
|
|
276
|
+
created++;
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
skipped++;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return { created, skipped };
|
|
284
|
+
}
|
|
285
|
+
// Task 3.5
|
|
286
|
+
export function installEslintArchitectureTemplate(projectRoot) {
|
|
287
|
+
const templatePath = path.join(ARCHITECTURES_BASE, 'feature-sliced-react', 'eslint-architecture.mjs.template');
|
|
288
|
+
if (!fs.existsSync(templatePath))
|
|
289
|
+
return;
|
|
290
|
+
const destPath = path.join(projectRoot, 'eslint-architecture.mjs');
|
|
291
|
+
if (!fs.existsSync(destPath)) {
|
|
292
|
+
fs.copyFileSync(templatePath, destPath);
|
|
293
|
+
}
|
|
294
|
+
console.log('\n[dixi] eslint-architecture.mjs instalado.\n' +
|
|
295
|
+
' Para ativar as regras arquiteturais, adicione ao seu eslint.config.js:\n\n' +
|
|
296
|
+
' import architectureRules from \'./eslint-architecture.mjs\';\n' +
|
|
297
|
+
' export default [...existingConfig, ...architectureRules];\n');
|
|
298
|
+
}
|
|
299
|
+
export function installDixiExtras(projectDir, stack) {
|
|
300
|
+
const family = getDixiStackFamily(stack);
|
|
301
|
+
// Resolve package content root: dist/core/presets/ → package root → pscode/content/dixi/
|
|
302
|
+
const currentFile = fileURLToPath(import.meta.url);
|
|
303
|
+
const packageRoot = path.join(path.dirname(currentFile), '..', '..', '..');
|
|
304
|
+
const contentBase = path.join(packageRoot, 'pscode', 'content', 'dixi', 'context');
|
|
305
|
+
const kitBase = path.join(packageRoot, 'pscode', 'content', 'dixi', 'kit');
|
|
306
|
+
// Task 4.5: Ensure pastelsdd/context/ exists in the client repo
|
|
307
|
+
const contextDir = path.join(projectDir, 'pastelsdd', 'context');
|
|
308
|
+
if (!fs.existsSync(contextDir)) {
|
|
309
|
+
fs.mkdirSync(contextDir, { recursive: true });
|
|
310
|
+
}
|
|
311
|
+
// Task 4.2: Always copy shared/ docs
|
|
312
|
+
copyContextDocs(projectDir, path.join(contentBase, 'shared'));
|
|
313
|
+
if (family === null || family === 'node') {
|
|
314
|
+
console.log('Dixi: Stack não detectada — apenas docs compartilhados instalados. ' +
|
|
315
|
+
'Configure `family` em `.pscode-dixi.yaml` para instalar docs específicos de stack.');
|
|
316
|
+
}
|
|
317
|
+
// Task 4.3: Copy java/ only for Java projects
|
|
318
|
+
if (family === 'java') {
|
|
319
|
+
copyContextDocs(projectDir, path.join(contentBase, 'java'));
|
|
320
|
+
}
|
|
321
|
+
// Task 4.4: Copy react/ only for React projects
|
|
322
|
+
if (family === 'react') {
|
|
323
|
+
copyContextDocs(projectDir, path.join(contentBase, 'react'));
|
|
324
|
+
}
|
|
325
|
+
// Task 4.2: Copy shared SDLC kit (always) — PR template always overwritten
|
|
326
|
+
copyKitFiles(path.join(kitBase, 'shared'), projectDir, {
|
|
327
|
+
overwrite: ['pull_request_template.md'],
|
|
328
|
+
});
|
|
329
|
+
// Task 4.3: Copy java SDLC kit
|
|
330
|
+
if (family === 'java') {
|
|
331
|
+
copyKitFiles(path.join(kitBase, 'java'), projectDir);
|
|
332
|
+
console.log('\nDixi [Java kit instalado]:\n' +
|
|
333
|
+
' Adicione ao pom.xml:\n' +
|
|
334
|
+
' • plugin commitlint: npm install --save-dev @commitlint/cli @commitlint/config-conventional commitlint-plugin-jira-rules\n' +
|
|
335
|
+
' • plugin Jacoco: <groupId>org.jacoco</groupId><artifactId>jacoco-maven-plugin</artifactId>\n' +
|
|
336
|
+
' • plugin Husky (se gerenciado via frontend): npx husky install\n' +
|
|
337
|
+
' Atenção: o job archunit requer ArchitectureTest.java (gerado pelo pscode init skeleton).');
|
|
338
|
+
}
|
|
339
|
+
// Task 4.4: Copy react SDLC kit
|
|
340
|
+
if (family === 'react') {
|
|
341
|
+
copyKitFiles(path.join(kitBase, 'react'), projectDir);
|
|
342
|
+
console.log('\nDixi [React kit instalado]:\n' +
|
|
343
|
+
' Execute:\n' +
|
|
344
|
+
' npm install --save-dev @commitlint/cli @commitlint/config-conventional commitlint-plugin-jira-rules husky lint-staged prettier eslint\n' +
|
|
345
|
+
' npx husky install\n' +
|
|
346
|
+
' Adicione ao package.json: "prepare": "husky install"');
|
|
347
|
+
}
|
|
348
|
+
installDixiClaudeMd(projectDir, family);
|
|
349
|
+
// Task 3.6 + 3.7: Apply architectural skeleton by stack
|
|
350
|
+
if (family === 'java') {
|
|
351
|
+
const basePackage = detectBasePackage(projectDir);
|
|
352
|
+
const skeletonResult = applyHexagonalSkeleton(projectDir, basePackage);
|
|
353
|
+
console.log(`[dixi] skeleton hexagonal: ${skeletonResult.created} diretórios criados, ${skeletonResult.skipped} ignorados`);
|
|
354
|
+
const archTestCreated = generateArchitectureTest(projectDir, basePackage);
|
|
355
|
+
console.log(`[dixi] ArchitectureTest.java: ${archTestCreated ? 'criado' : 'ignorado (já existe)'}`);
|
|
356
|
+
}
|
|
357
|
+
else if (family === 'react') {
|
|
358
|
+
const skeletonResult = applyFeatureSlicedSkeleton(projectDir);
|
|
359
|
+
console.log(`[dixi] skeleton feature-sliced: ${skeletonResult.created} arquivos criados, ${skeletonResult.skipped} ignorados`);
|
|
360
|
+
installEslintArchitectureTemplate(projectDir);
|
|
361
|
+
}
|
|
362
|
+
else {
|
|
363
|
+
console.log('[dixi] skeleton arquitetural: stack não reconhecida — skeleton não disponível para esta stack');
|
|
364
|
+
}
|
|
365
|
+
// Copy /pstld:* slash commands to .claude/commands/pstld/ (idempotent — overwrites)
|
|
366
|
+
const pstldCommandsDir = path.join(projectDir, '.claude', 'commands', 'pstld');
|
|
367
|
+
if (!fs.existsSync(pstldCommandsDir)) {
|
|
368
|
+
fs.mkdirSync(pstldCommandsDir, { recursive: true });
|
|
369
|
+
}
|
|
370
|
+
if (fs.existsSync(PSTLD_COMMANDS_SRC)) {
|
|
371
|
+
const files = fs.readdirSync(PSTLD_COMMANDS_SRC);
|
|
372
|
+
for (const file of files) {
|
|
373
|
+
fs.copyFileSync(path.join(PSTLD_COMMANDS_SRC, file), path.join(pstldCommandsDir, file));
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
// Copy pstld-* skills to .claude/skills/<name>/SKILL.md (idempotent — overwrites)
|
|
377
|
+
if (fs.existsSync(PSTLD_SKILLS_SRC)) {
|
|
378
|
+
const skillFiles = fs.readdirSync(PSTLD_SKILLS_SRC).filter(f => f.endsWith('.md'));
|
|
379
|
+
for (const file of skillFiles) {
|
|
380
|
+
const skillName = file.replace(/\.md$/, '');
|
|
381
|
+
const skillDir = path.join(projectDir, '.claude', 'skills', skillName);
|
|
382
|
+
if (!fs.existsSync(skillDir)) {
|
|
383
|
+
fs.mkdirSync(skillDir, { recursive: true });
|
|
384
|
+
}
|
|
385
|
+
fs.copyFileSync(path.join(PSTLD_SKILLS_SRC, file), path.join(skillDir, 'SKILL.md'));
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
// Copy hooks to .claude/hooks/ (brownfield-safe: skip if file already exists)
|
|
389
|
+
const hooksDestDir = path.join(projectDir, '.claude', 'hooks');
|
|
390
|
+
if (!fs.existsSync(hooksDestDir)) {
|
|
391
|
+
fs.mkdirSync(hooksDestDir, { recursive: true });
|
|
392
|
+
}
|
|
393
|
+
if (fs.existsSync(HOOKS_SRC)) {
|
|
394
|
+
const hookFiles = fs.readdirSync(HOOKS_SRC).filter(f => f.endsWith('.mjs'));
|
|
395
|
+
for (const file of hookFiles) {
|
|
396
|
+
const dest = path.join(hooksDestDir, file);
|
|
397
|
+
if (!fs.existsSync(dest)) {
|
|
398
|
+
fs.copyFileSync(path.join(HOOKS_SRC, file), dest);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
// Merge .claude/settings.json with hook registrations (never overwrite existing config)
|
|
403
|
+
mergeSettingsHooks(path.join(projectDir, '.claude', 'settings.json'));
|
|
404
|
+
}
|
|
405
|
+
//# sourceMappingURL=dixi.js.map
|
|
@@ -14,7 +14,7 @@ export const WORKFLOW_TO_SKILL_DIR = {
|
|
|
14
14
|
'apply': 'pscode-apply-change',
|
|
15
15
|
'ff': 'pscode-ff-change',
|
|
16
16
|
'sync': 'pscode-sync-specs',
|
|
17
|
-
'
|
|
17
|
+
'complete': 'pscode-archive-change',
|
|
18
18
|
'bulk-archive': 'pscode-bulk-archive-change',
|
|
19
19
|
'verify': 'pscode-verify-change',
|
|
20
20
|
'onboard': 'pscode-onboard',
|
|
@@ -22,6 +22,14 @@ export const WORKFLOW_TO_SKILL_DIR = {
|
|
|
22
22
|
// Trello-specific workflows
|
|
23
23
|
'trello-setup': 'pscode-trello-setup',
|
|
24
24
|
'draft': 'pscode-trello-draft',
|
|
25
|
+
// Dixi-specific workflows
|
|
26
|
+
'rfc': 'pscode-dixi-rfc',
|
|
27
|
+
'design': 'pscode-dixi-design',
|
|
28
|
+
'tasks': 'pscode-dixi-tasks',
|
|
29
|
+
'arch-check': 'pscode-dixi-arch-check',
|
|
30
|
+
'adr': 'pscode-dixi-adr',
|
|
31
|
+
'jira-sync': 'pscode-dixi-jira-sync',
|
|
32
|
+
'dod': 'pscode-dixi-dod',
|
|
25
33
|
};
|
|
26
34
|
function toKnownWorkflows(workflows) {
|
|
27
35
|
return workflows.filter((workflow) => ALL_WORKFLOWS.includes(workflow));
|
package/dist/core/profiles.d.ts
CHANGED
|
@@ -1,26 +1,28 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Predefined Workflow Profiles
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
4
|
+
* Add, remove or edit profiles here. Users select a profile via
|
|
5
|
+
* `pscode init --profile <name>` or `pscode config profile <name>`.
|
|
6
|
+
* The workflow lists are fixed in code — users cannot customise them.
|
|
6
7
|
*/
|
|
7
|
-
|
|
8
|
-
/**
|
|
9
|
-
* Core workflows included in the 'core' profile.
|
|
10
|
-
* These provide the streamlined experience for new users.
|
|
11
|
-
*/
|
|
12
|
-
export declare const CORE_WORKFLOWS: readonly ["propose", "explore", "apply", "sync", "archive"];
|
|
13
|
-
/**
|
|
14
|
-
* All available workflows in the system.
|
|
15
|
-
*/
|
|
16
|
-
export declare const ALL_WORKFLOWS: readonly ["propose", "explore", "new", "continue", "apply", "ff", "sync", "archive", "bulk-archive", "verify", "onboard", "trello-setup", "draft"];
|
|
8
|
+
export declare const ALL_WORKFLOWS: readonly ["propose", "explore", "new", "continue", "apply", "ff", "sync", "complete", "bulk-archive", "verify", "onboard", "trello-setup", "draft", "rfc", "design", "tasks", "arch-check", "adr", "jira-sync", "dod"];
|
|
17
9
|
export type WorkflowId = (typeof ALL_WORKFLOWS)[number];
|
|
18
|
-
export
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
10
|
+
export interface ProfileDefinition {
|
|
11
|
+
description: string;
|
|
12
|
+
workflows: readonly WorkflowId[];
|
|
13
|
+
}
|
|
14
|
+
export declare const PROFILES: {
|
|
15
|
+
readonly standard: {
|
|
16
|
+
readonly description: "Padrão — propose, explore, apply, sync, complete";
|
|
17
|
+
readonly workflows: readonly ["propose", "explore", "apply", "sync", "complete"];
|
|
18
|
+
};
|
|
19
|
+
readonly dixi: {
|
|
20
|
+
readonly description: "Dixi — RFC→Design→Tasks→Apply com guardrails para Java/Spring e React/Next.js";
|
|
21
|
+
readonly workflows: readonly ["rfc", "design", "tasks", "apply", "arch-check", "adr", "jira-sync", "dod"];
|
|
22
|
+
};
|
|
23
|
+
};
|
|
24
|
+
export type ProfileName = keyof typeof PROFILES;
|
|
25
|
+
export declare const DEFAULT_PROFILE: ProfileName;
|
|
26
|
+
export declare function getProfileWorkflows(profile: ProfileName): readonly WorkflowId[];
|
|
27
|
+
export declare function isValidProfile(name: string): name is ProfileName;
|
|
26
28
|
//# sourceMappingURL=profiles.d.ts.map
|
package/dist/core/profiles.js
CHANGED
|
@@ -1,16 +1,9 @@
|
|
|
1
1
|
/**
|
|
2
|
-
*
|
|
2
|
+
* Predefined Workflow Profiles
|
|
3
3
|
*
|
|
4
|
-
*
|
|
5
|
-
*
|
|
6
|
-
|
|
7
|
-
/**
|
|
8
|
-
* Core workflows included in the 'core' profile.
|
|
9
|
-
* These provide the streamlined experience for new users.
|
|
10
|
-
*/
|
|
11
|
-
export const CORE_WORKFLOWS = ['propose', 'explore', 'apply', 'sync', 'archive'];
|
|
12
|
-
/**
|
|
13
|
-
* All available workflows in the system.
|
|
4
|
+
* Add, remove or edit profiles here. Users select a profile via
|
|
5
|
+
* `pscode init --profile <name>` or `pscode config profile <name>`.
|
|
6
|
+
* The workflow lists are fixed in code — users cannot customise them.
|
|
14
7
|
*/
|
|
15
8
|
export const ALL_WORKFLOWS = [
|
|
16
9
|
'propose',
|
|
@@ -20,24 +13,35 @@ export const ALL_WORKFLOWS = [
|
|
|
20
13
|
'apply',
|
|
21
14
|
'ff',
|
|
22
15
|
'sync',
|
|
23
|
-
'
|
|
16
|
+
'complete',
|
|
24
17
|
'bulk-archive',
|
|
25
18
|
'verify',
|
|
26
19
|
'onboard',
|
|
27
|
-
// Trello-specific workflows
|
|
28
20
|
'trello-setup',
|
|
29
21
|
'draft',
|
|
22
|
+
'rfc',
|
|
23
|
+
'design',
|
|
24
|
+
'tasks',
|
|
25
|
+
'arch-check',
|
|
26
|
+
'adr',
|
|
27
|
+
'jira-sync',
|
|
28
|
+
'dod',
|
|
30
29
|
];
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
30
|
+
export const PROFILES = {
|
|
31
|
+
standard: {
|
|
32
|
+
description: 'Padrão — propose, explore, apply, sync, complete',
|
|
33
|
+
workflows: ['propose', 'explore', 'apply', 'sync', 'complete'],
|
|
34
|
+
},
|
|
35
|
+
dixi: {
|
|
36
|
+
description: 'Dixi — RFC→Design→Tasks→Apply com guardrails para Java/Spring e React/Next.js',
|
|
37
|
+
workflows: ['rfc', 'design', 'tasks', 'apply', 'arch-check', 'adr', 'jira-sync', 'dod'],
|
|
38
|
+
},
|
|
39
|
+
};
|
|
40
|
+
export const DEFAULT_PROFILE = 'standard';
|
|
41
|
+
export function getProfileWorkflows(profile) {
|
|
42
|
+
return PROFILES[profile].workflows;
|
|
43
|
+
}
|
|
44
|
+
export function isValidProfile(name) {
|
|
45
|
+
return name in PROFILES;
|
|
42
46
|
}
|
|
43
47
|
//# sourceMappingURL=profiles.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, getSyncSpecsSkillTemplate,
|
|
6
|
+
import { getExploreSkillTemplate, getNewChangeSkillTemplate, getContinueChangeSkillTemplate, getApplyChangeSkillTemplate, getFfChangeSkillTemplate, getSyncSpecsSkillTemplate, getCompleteChangeSkillTemplate, getBulkArchiveChangeSkillTemplate, getVerifyChangeSkillTemplate, getOnboardSkillTemplate, getProposeSkillTemplate, getTrelloSetupSkillTemplate, getTrelloDraftSkillTemplate, getPsExploreCommandTemplate, getPsNewCommandTemplate, getPsContinueCommandTemplate, getPsApplyCommandTemplate, getPsFfCommandTemplate, getPsSyncCommandTemplate, getPsCompleteCommandTemplate, getPsBulkArchiveCommandTemplate, getPsVerifyCommandTemplate, getPsOnboardCommandTemplate, getPsProposeCommandTemplate, getTrelloSetupCommandTemplate, getTrelloDraftCommandTemplate, } from '../templates/skill-templates.js';
|
|
7
7
|
/**
|
|
8
8
|
* Gets skill templates with their directory names, optionally filtered by workflow IDs.
|
|
9
9
|
*
|
|
@@ -17,7 +17,7 @@ export function getSkillTemplates(workflowFilter) {
|
|
|
17
17
|
{ template: getApplyChangeSkillTemplate(), dirName: 'pscode-apply-change', workflowId: 'apply' },
|
|
18
18
|
{ template: getFfChangeSkillTemplate(), dirName: 'pscode-ff-change', workflowId: 'ff' },
|
|
19
19
|
{ template: getSyncSpecsSkillTemplate(), dirName: 'pscode-sync-specs', workflowId: 'sync' },
|
|
20
|
-
{ template:
|
|
20
|
+
{ template: getCompleteChangeSkillTemplate(), dirName: 'pscode-archive-change', workflowId: 'complete' },
|
|
21
21
|
{ template: getBulkArchiveChangeSkillTemplate(), dirName: 'pscode-bulk-archive-change', workflowId: 'bulk-archive' },
|
|
22
22
|
{ template: getVerifyChangeSkillTemplate(), dirName: 'pscode-verify-change', workflowId: 'verify' },
|
|
23
23
|
{ template: getOnboardSkillTemplate(), dirName: 'pscode-onboard', workflowId: 'onboard' },
|
|
@@ -44,7 +44,7 @@ export function getCommandTemplates(workflowFilter) {
|
|
|
44
44
|
{ template: getPsApplyCommandTemplate(), id: 'apply' },
|
|
45
45
|
{ template: getPsFfCommandTemplate(), id: 'ff' },
|
|
46
46
|
{ template: getPsSyncCommandTemplate(), id: 'sync' },
|
|
47
|
-
{ template:
|
|
47
|
+
{ template: getPsCompleteCommandTemplate(), id: 'complete' },
|
|
48
48
|
{ template: getPsBulkArchiveCommandTemplate(), id: 'bulk-archive' },
|
|
49
49
|
{ template: getPsVerifyCommandTemplate(), id: 'verify' },
|
|
50
50
|
{ template: getPsOnboardCommandTemplate(), id: 'onboard' },
|
|
@@ -11,7 +11,7 @@ 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", "sync", "
|
|
14
|
+
export declare const COMMAND_IDS: readonly ["explore", "new", "continue", "apply", "ff", "sync", "complete", "bulk-archive", "verify", "onboard", "propose"];
|
|
15
15
|
export type CommandId = (typeof COMMAND_IDS)[number];
|
|
16
16
|
/**
|
|
17
17
|
* Status of skill configuration for a tool.
|
|
@@ -10,7 +10,7 @@ export { getContinueChangeSkillTemplate, getPsContinueCommandTemplate } from './
|
|
|
10
10
|
export { getApplyChangeSkillTemplate, getPsApplyCommandTemplate } from './workflows/apply-change.js';
|
|
11
11
|
export { getFfChangeSkillTemplate, getPsFfCommandTemplate } from './workflows/ff-change.js';
|
|
12
12
|
export { getSyncSpecsSkillTemplate, getPsSyncCommandTemplate } from './workflows/sync-specs.js';
|
|
13
|
-
export {
|
|
13
|
+
export { getCompleteChangeSkillTemplate, getPsCompleteCommandTemplate } from './workflows/archive-change.js';
|
|
14
14
|
export { getBulkArchiveChangeSkillTemplate, getPsBulkArchiveCommandTemplate } from './workflows/bulk-archive-change.js';
|
|
15
15
|
export { getVerifyChangeSkillTemplate, getPsVerifyCommandTemplate } from './workflows/verify-change.js';
|
|
16
16
|
export { getOnboardSkillTemplate, getPsOnboardCommandTemplate } from './workflows/onboard.js';
|
|
@@ -9,7 +9,7 @@ export { getContinueChangeSkillTemplate, getPsContinueCommandTemplate } from './
|
|
|
9
9
|
export { getApplyChangeSkillTemplate, getPsApplyCommandTemplate } from './workflows/apply-change.js';
|
|
10
10
|
export { getFfChangeSkillTemplate, getPsFfCommandTemplate } from './workflows/ff-change.js';
|
|
11
11
|
export { getSyncSpecsSkillTemplate, getPsSyncCommandTemplate } from './workflows/sync-specs.js';
|
|
12
|
-
export {
|
|
12
|
+
export { getCompleteChangeSkillTemplate, getPsCompleteCommandTemplate } from './workflows/archive-change.js';
|
|
13
13
|
export { getBulkArchiveChangeSkillTemplate, getPsBulkArchiveCommandTemplate } from './workflows/bulk-archive-change.js';
|
|
14
14
|
export { getVerifyChangeSkillTemplate, getPsVerifyCommandTemplate } from './workflows/verify-change.js';
|
|
15
15
|
export { getOnboardSkillTemplate, getPsOnboardCommandTemplate } from './workflows/onboard.js';
|
|
@@ -182,7 +182,7 @@ function getApplyInstructions() {
|
|
|
182
182
|
Testado por: <usuario / Claude>
|
|
183
183
|
Status: Funcionando
|
|
184
184
|
|
|
185
|
-
Proximo passo: /ps:
|
|
185
|
+
Proximo passo: /ps:complete <name> para arquivar a change.
|
|
186
186
|
\`\`\`
|
|
187
187
|
|
|
188
188
|
If any Trello call fails, continue — Trello is auxiliary, never blocking.
|
|
@@ -197,7 +197,7 @@ function getApplyInstructions() {
|
|
|
197
197
|
Display:
|
|
198
198
|
- Tasks completed this session
|
|
199
199
|
- Overall progress: "N/M tasks complete"
|
|
200
|
-
- If all done and approved: mention Trello stage (Em Teste or Ready to Deploy) and suggest \`/ps:
|
|
200
|
+
- If all done and approved: mention Trello stage (Em Teste or Ready to Deploy) and suggest \`/ps:complete\`
|
|
201
201
|
- If paused: explain why and wait for guidance
|
|
202
202
|
|
|
203
203
|
**Output During Implementation**
|
|
@@ -240,7 +240,7 @@ All tasks complete! How would you like to validate the implementation?
|
|
|
240
240
|
**Change:** <change-name>
|
|
241
241
|
**Trello:** Card moved to 🚀 Ready to Deploy ← only shown if lists.deploy is configured
|
|
242
242
|
|
|
243
|
-
Ready to archive with \`/ps:
|
|
243
|
+
Ready to archive with \`/ps:complete\`.
|
|
244
244
|
\`\`\`
|
|
245
245
|
|
|
246
246
|
**Output On Pause (Issue Encountered)**
|
|
@@ -5,6 +5,6 @@
|
|
|
5
5
|
* templates file into workflow-focused modules.
|
|
6
6
|
*/
|
|
7
7
|
import type { SkillTemplate, CommandTemplate } from '../types.js';
|
|
8
|
-
export declare function
|
|
9
|
-
export declare function
|
|
8
|
+
export declare function getCompleteChangeSkillTemplate(): SkillTemplate;
|
|
9
|
+
export declare function getPsCompleteCommandTemplate(): CommandTemplate;
|
|
10
10
|
//# sourceMappingURL=archive-change.d.ts.map
|