@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
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
export function
|
|
1
|
+
export function getCompleteChangeSkillTemplate() {
|
|
2
2
|
return {
|
|
3
3
|
name: 'pscode-archive-change',
|
|
4
|
-
description: '
|
|
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
|
license: 'MIT',
|
|
7
7
|
compatibility: 'Requires pscode CLI.',
|
|
8
8
|
metadata: { author: 'pscode', version: '1.0' },
|
|
9
9
|
};
|
|
10
10
|
}
|
|
11
|
-
export function
|
|
11
|
+
export function getPsCompleteCommandTemplate() {
|
|
12
12
|
return {
|
|
13
|
-
name: 'PS:
|
|
14
|
-
description: '
|
|
13
|
+
name: 'PS: Complete',
|
|
14
|
+
description: 'Complete a change',
|
|
15
15
|
category: 'Workflow',
|
|
16
|
-
tags: ['workflow', '
|
|
16
|
+
tags: ['workflow', 'complete'],
|
|
17
17
|
content: getArchiveInstructions(),
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
20
|
function getArchiveInstructions() {
|
|
21
|
-
return `
|
|
21
|
+
return `Complete a change.
|
|
22
22
|
|
|
23
|
-
**Input**: Optionally specify a change name (e.g., \`/ps:
|
|
23
|
+
**Input**: Optionally specify a change name (e.g., \`/ps:complete add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
24
24
|
|
|
25
25
|
**Steps**
|
|
26
26
|
|
|
@@ -116,7 +116,7 @@ function getArchiveInstructions() {
|
|
|
116
116
|
mcp__claude_ai_Trello_Custom__create_card
|
|
117
117
|
list_id: "<lists.done.id>"
|
|
118
118
|
name: "<human-readable change name in Portuguese>"
|
|
119
|
-
desc: "
|
|
119
|
+
desc: "Concluida via /ps:complete"
|
|
120
120
|
\`\`\`
|
|
121
121
|
Then mark it complete.
|
|
122
122
|
|
|
@@ -140,7 +140,7 @@ function getArchiveInstructions() {
|
|
|
140
140
|
mcp__claude_ai_Trello_Custom__add_comment
|
|
141
141
|
card_id: "<cardId>"
|
|
142
142
|
text: |
|
|
143
|
-
Change
|
|
143
|
+
Change concluida via /ps:complete
|
|
144
144
|
|
|
145
145
|
Change: <change-name>
|
|
146
146
|
Schema: <schema-name>
|
|
@@ -412,25 +412,25 @@ All tasks done:
|
|
|
412
412
|
- [x] Task 2
|
|
413
413
|
- [x] ...
|
|
414
414
|
|
|
415
|
-
The change is implemented! One more step—let's
|
|
415
|
+
The change is implemented! One more step—let's complete it.
|
|
416
416
|
\`\`\`
|
|
417
417
|
|
|
418
418
|
---
|
|
419
419
|
|
|
420
|
-
## Phase 10:
|
|
420
|
+
## Phase 10: Complete
|
|
421
421
|
|
|
422
422
|
**EXPLAIN:**
|
|
423
423
|
\`\`\`
|
|
424
|
-
##
|
|
424
|
+
## Completing
|
|
425
425
|
|
|
426
|
-
When a change is complete, we
|
|
426
|
+
When a change is complete, we complete it. The archive path is derived from \`planningHome.changesDir\` and the date.
|
|
427
427
|
|
|
428
|
-
|
|
428
|
+
Completed changes become your project's decision history—you can always find them later to understand why something was built a certain way.
|
|
429
429
|
\`\`\`
|
|
430
430
|
|
|
431
431
|
**DO:**
|
|
432
432
|
\`\`\`bash
|
|
433
|
-
pscode
|
|
433
|
+
pscode complete "<name>"
|
|
434
434
|
\`\`\`
|
|
435
435
|
|
|
436
436
|
**SHOW:**
|
|
@@ -463,7 +463,7 @@ automaticamente cards no Trello conforme você avança nas suas changes.
|
|
|
463
463
|
- /ps:draft → registra ideias em "Para Explorar"
|
|
464
464
|
- /ps:propose → move card para "Em Refinamento"
|
|
465
465
|
- /ps:apply → move card para "Em Desenvolvimento" e depois "Em Teste"
|
|
466
|
-
- /ps:
|
|
466
|
+
- /ps:complete → move card para "Concluído"
|
|
467
467
|
|
|
468
468
|
Deseja configurar agora?
|
|
469
469
|
\`\`\`
|
|
@@ -507,7 +507,7 @@ This same rhythm works for any size change—a small fix or a major feature.
|
|
|
507
507
|
| \`/ps:propose\` | Create a change and generate all artifacts |
|
|
508
508
|
| \`/ps:explore\` | Think through problems before/during work |
|
|
509
509
|
| \`/ps:apply\` | Implement tasks from a change |
|
|
510
|
-
| \`/ps:
|
|
510
|
+
| \`/ps:complete\` | Complete a change |
|
|
511
511
|
|
|
512
512
|
**Additional commands:**
|
|
513
513
|
|
|
@@ -567,7 +567,7 @@ If the user says they just want to see the commands or skip the tutorial:
|
|
|
567
567
|
| \`/ps:propose <name>\` | Create a change and generate all artifacts |
|
|
568
568
|
| \`/ps:explore\` | Think through problems (no code changes) |
|
|
569
569
|
| \`/ps:apply <name>\` | Implement tasks |
|
|
570
|
-
| \`/ps:
|
|
570
|
+
| \`/ps:complete <name>\` | Complete when done |
|
|
571
571
|
|
|
572
572
|
**Additional commands:**
|
|
573
573
|
|
package/dist/core/update.d.ts
CHANGED
|
@@ -35,14 +35,9 @@ export declare class UpdateCommand {
|
|
|
35
35
|
*/
|
|
36
36
|
private detectNewTools;
|
|
37
37
|
/**
|
|
38
|
-
* Displays a note about extra workflows installed that aren't in the
|
|
38
|
+
* Displays a note about extra workflows installed that aren't in the active profile.
|
|
39
39
|
*/
|
|
40
40
|
private displayExtraWorkflowsNote;
|
|
41
|
-
/**
|
|
42
|
-
* Suggest opting back into core when a custom profile still matches the old
|
|
43
|
-
* pre-sync core set. Keep custom profiles user-owned; do not mutate them.
|
|
44
|
-
*/
|
|
45
|
-
private displayOldCoreCustomProfileNote;
|
|
46
41
|
/**
|
|
47
42
|
* Removes skill directories for workflows when delivery changed to commands-only.
|
|
48
43
|
* Returns the number of directories removed.
|
package/dist/core/update.js
CHANGED
|
@@ -17,13 +17,12 @@ import { getToolVersionStatus, getSkillTemplates, getCommandContents, generateSk
|
|
|
17
17
|
import { detectLegacyArtifacts, cleanupLegacyArtifacts, formatCleanupSummary, formatDetectionSummary, getToolsFromLegacyArtifacts, } from './legacy-cleanup.js';
|
|
18
18
|
import { isInteractive } from '../utils/interactive.js';
|
|
19
19
|
import { getGlobalConfig } from './global-config.js';
|
|
20
|
-
import { getProfileWorkflows, ALL_WORKFLOWS } from './profiles.js';
|
|
20
|
+
import { getProfileWorkflows, isValidProfile, DEFAULT_PROFILE, ALL_WORKFLOWS } from './profiles.js';
|
|
21
21
|
import { getAvailableTools } from './available-tools.js';
|
|
22
22
|
import { WORKFLOW_TO_SKILL_DIR, getCommandConfiguredTools, getConfiguredToolsForProfileSync, getToolsNeedingProfileSync, } from './profile-sync-drift.js';
|
|
23
23
|
import { scanInstalledWorkflows as scanInstalledWorkflowsShared, migrateIfNeeded as migrateIfNeededShared, } from './migration.js';
|
|
24
24
|
const require = createRequire(import.meta.url);
|
|
25
25
|
const { version: PSCODE_VERSION } = require('../../package.json');
|
|
26
|
-
const OLD_CORE_WORKFLOWS = ['propose', 'explore', 'apply', 'archive'];
|
|
27
26
|
/**
|
|
28
27
|
* Scans installed workflow artifacts (skills and managed commands) across all configured tools.
|
|
29
28
|
* Returns the union of detected workflow IDs that match ALL_WORKFLOWS.
|
|
@@ -54,13 +53,9 @@ export class UpdateCommand {
|
|
|
54
53
|
migrateIfNeededShared(resolvedProjectPath, detectedTools);
|
|
55
54
|
// 3. Read global config for profile/delivery
|
|
56
55
|
const globalConfig = getGlobalConfig();
|
|
57
|
-
const profile = globalConfig.profile ?? '
|
|
56
|
+
const profile = isValidProfile(globalConfig.profile ?? '') ? globalConfig.profile : DEFAULT_PROFILE;
|
|
58
57
|
const delivery = globalConfig.delivery ?? 'both';
|
|
59
|
-
const
|
|
60
|
-
// Trello workflows are always included regardless of profile, mirroring InitCommand behavior.
|
|
61
|
-
const TRELLO_WORKFLOWS = ['trello-setup', 'task', 'draft'];
|
|
62
|
-
const workflowsSet = new Set([...profileWorkflows, ...TRELLO_WORKFLOWS]);
|
|
63
|
-
const desiredWorkflows = [...workflowsSet].filter((workflow) => ALL_WORKFLOWS.includes(workflow));
|
|
58
|
+
const desiredWorkflows = [...getProfileWorkflows(profile)];
|
|
64
59
|
const shouldGenerateSkills = delivery !== 'commands';
|
|
65
60
|
const shouldGenerateCommands = delivery !== 'skills';
|
|
66
61
|
// 4. Detect and handle legacy artifacts + upgrade legacy tools using effective config
|
|
@@ -99,7 +94,6 @@ export class UpdateCommand {
|
|
|
99
94
|
// Still check for new tool directories and extra workflows
|
|
100
95
|
this.detectNewTools(resolvedProjectPath, configuredTools);
|
|
101
96
|
this.displayExtraWorkflowsNote(resolvedProjectPath, configuredTools, desiredWorkflows);
|
|
102
|
-
this.displayOldCoreCustomProfileNote(profile, globalConfig.workflows);
|
|
103
97
|
return;
|
|
104
98
|
}
|
|
105
99
|
// 8. Display update plan
|
|
@@ -206,7 +200,6 @@ export class UpdateCommand {
|
|
|
206
200
|
this.detectNewTools(resolvedProjectPath, configuredAndNewTools);
|
|
207
201
|
// 14. Display note about extra workflows not in profile
|
|
208
202
|
this.displayExtraWorkflowsNote(resolvedProjectPath, configuredAndNewTools, desiredWorkflows);
|
|
209
|
-
this.displayOldCoreCustomProfileNote(profile, globalConfig.workflows);
|
|
210
203
|
// 15. List affected tools
|
|
211
204
|
if (updatedTools.length > 0) {
|
|
212
205
|
const toolDisplayNames = updatedTools;
|
|
@@ -260,33 +253,16 @@ export class UpdateCommand {
|
|
|
260
253
|
}
|
|
261
254
|
}
|
|
262
255
|
/**
|
|
263
|
-
* Displays a note about extra workflows installed that aren't in the
|
|
256
|
+
* Displays a note about extra workflows installed that aren't in the active profile.
|
|
264
257
|
*/
|
|
265
258
|
displayExtraWorkflowsNote(projectPath, configuredTools, profileWorkflows) {
|
|
266
259
|
const installedWorkflows = scanInstalledWorkflows(projectPath, configuredTools);
|
|
267
260
|
const profileSet = new Set(profileWorkflows);
|
|
268
261
|
const extraWorkflows = installedWorkflows.filter((w) => !profileSet.has(w));
|
|
269
262
|
if (extraWorkflows.length > 0) {
|
|
270
|
-
console.log(chalk.dim(`Note: ${extraWorkflows.length} extra workflows not in profile (use \`pscode config profile\` to
|
|
263
|
+
console.log(chalk.dim(`Note: ${extraWorkflows.length} extra workflows not in profile (use \`pscode config profile\` to switch profiles)`));
|
|
271
264
|
}
|
|
272
265
|
}
|
|
273
|
-
/**
|
|
274
|
-
* Suggest opting back into core when a custom profile still matches the old
|
|
275
|
-
* pre-sync core set. Keep custom profiles user-owned; do not mutate them.
|
|
276
|
-
*/
|
|
277
|
-
displayOldCoreCustomProfileNote(profile, workflows) {
|
|
278
|
-
if (profile !== 'custom' || !workflows) {
|
|
279
|
-
return;
|
|
280
|
-
}
|
|
281
|
-
const workflowSet = new Set(workflows);
|
|
282
|
-
const matchesOldCore = workflowSet.size === OLD_CORE_WORKFLOWS.length &&
|
|
283
|
-
OLD_CORE_WORKFLOWS.every((workflow) => workflowSet.has(workflow));
|
|
284
|
-
if (!matchesOldCore) {
|
|
285
|
-
return;
|
|
286
|
-
}
|
|
287
|
-
console.log(chalk.dim('Note: The core profile now includes sync. Your custom profile is preserving the old core workflow set.'));
|
|
288
|
-
console.log(chalk.dim('Run `pscode config profile core` and then `pscode update` to add sync.'));
|
|
289
|
-
}
|
|
290
266
|
/**
|
|
291
267
|
* Removes skill directories for workflows when delivery changed to commands-only.
|
|
292
268
|
* Returns the number of directories removed.
|
|
@@ -34,7 +34,7 @@ export interface WorkspaceViewState {
|
|
|
34
34
|
}
|
|
35
35
|
export interface WorkspaceSkillState {
|
|
36
36
|
selected_agents: string[];
|
|
37
|
-
last_applied_profile?:
|
|
37
|
+
last_applied_profile?: string;
|
|
38
38
|
last_applied_delivery?: 'both' | 'skills' | 'commands';
|
|
39
39
|
last_applied_workflow_ids?: string[];
|
|
40
40
|
last_applied_at?: string;
|
|
@@ -116,7 +116,7 @@ const WorkspaceContextSchema = WorkspaceInitiativeContextSchema;
|
|
|
116
116
|
const WorkspaceSkillStateSchema = z
|
|
117
117
|
.object({
|
|
118
118
|
selected_agents: z.array(z.string()),
|
|
119
|
-
last_applied_profile: z.
|
|
119
|
+
last_applied_profile: z.string().optional(),
|
|
120
120
|
last_applied_delivery: z.enum(['both', 'skills', 'commands']).optional(),
|
|
121
121
|
last_applied_workflow_ids: z.array(z.string()).optional(),
|
|
122
122
|
last_applied_at: z.string().optional(),
|
|
@@ -29,7 +29,7 @@ const PreferredOpenerSchema = z
|
|
|
29
29
|
const WorkspaceSkillStateSchema = z
|
|
30
30
|
.object({
|
|
31
31
|
selected_agents: z.array(z.string()),
|
|
32
|
-
last_applied_profile: z.enum(['
|
|
32
|
+
last_applied_profile: z.enum(['standard', 'dixi']).optional(),
|
|
33
33
|
last_applied_delivery: z.enum(['both', 'skills', 'commands']).optional(),
|
|
34
34
|
last_applied_workflow_ids: z.array(z.string()).optional(),
|
|
35
35
|
last_applied_at: z.string().optional(),
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type AIToolOption } from '../config.js';
|
|
2
|
-
import { type Delivery
|
|
2
|
+
import { type Delivery } from '../global-config.js';
|
|
3
|
+
import { type ProfileName } from '../profiles.js';
|
|
3
4
|
import type { WorkspaceSkillState } from './foundation.js';
|
|
4
5
|
export interface WorkspaceSkillAgentResult {
|
|
5
6
|
tool_id: string;
|
|
@@ -22,7 +23,7 @@ export interface WorkspaceSkillFailedResult {
|
|
|
22
23
|
error: string;
|
|
23
24
|
}
|
|
24
25
|
export interface WorkspaceSkillInstallationReport {
|
|
25
|
-
profile:
|
|
26
|
+
profile: ProfileName;
|
|
26
27
|
delivery: Delivery;
|
|
27
28
|
workflow_ids: string[];
|
|
28
29
|
selected_agents: string[];
|
|
@@ -39,7 +40,7 @@ type WorkspaceSkillCapableTool = AIToolOption & {
|
|
|
39
40
|
skillsDir: string;
|
|
40
41
|
};
|
|
41
42
|
export declare function getCurrentWorkspaceSkillProfileSelection(): {
|
|
42
|
-
profile:
|
|
43
|
+
profile: ProfileName;
|
|
43
44
|
delivery: Delivery;
|
|
44
45
|
workflow_ids: string[];
|
|
45
46
|
};
|
|
@@ -4,16 +4,16 @@ import { FileSystemUtils } from '../../utils/file-system.js';
|
|
|
4
4
|
import { transformToHyphenCommands } from '../../utils/command-references.js';
|
|
5
5
|
import { AI_TOOLS } from '../config.js';
|
|
6
6
|
import { getGlobalConfig } from '../global-config.js';
|
|
7
|
-
import { getProfileWorkflows } from '../profiles.js';
|
|
7
|
+
import { getProfileWorkflows, isValidProfile, DEFAULT_PROFILE } from '../profiles.js';
|
|
8
8
|
import { generateSkillContent, getSkillTemplates, getToolSkillStatus, getToolsWithSkillsDir, extractGeneratedByVersion, } from '../shared/index.js';
|
|
9
9
|
const require = createRequire(import.meta.url);
|
|
10
10
|
const { version: PSCODE_VERSION } = require('../../../package.json');
|
|
11
11
|
const fs = nodeFs.promises;
|
|
12
12
|
function resolveWorkspaceSkillProfileContext() {
|
|
13
13
|
const globalConfig = getGlobalConfig();
|
|
14
|
-
const profile = globalConfig.profile ?? '
|
|
14
|
+
const profile = isValidProfile(globalConfig.profile ?? '') ? globalConfig.profile : DEFAULT_PROFILE;
|
|
15
15
|
const delivery = globalConfig.delivery ?? 'both';
|
|
16
|
-
const workflowIds = [...getProfileWorkflows(profile
|
|
16
|
+
const workflowIds = [...getProfileWorkflows(profile)];
|
|
17
17
|
const deliveryNotice = delivery === 'skills'
|
|
18
18
|
? null
|
|
19
19
|
: 'Workspace setup installs skills only; workspace command generation is not part of this slice.';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@thiagodiogo/pscode",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.1",
|
|
4
4
|
"description": "AI-native system for spec-driven development",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"pscode",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"homepage": "https://github.com/eipastel/pscode",
|
|
13
13
|
"repository": {
|
|
14
14
|
"type": "git",
|
|
15
|
-
"url": "https://github.com/eipastel/pscode"
|
|
15
|
+
"url": "git+https://github.com/eipastel/pscode.git"
|
|
16
16
|
},
|
|
17
17
|
"license": "MIT",
|
|
18
18
|
"author": "thiagodiogo",
|
|
@@ -27,12 +27,13 @@
|
|
|
27
27
|
}
|
|
28
28
|
},
|
|
29
29
|
"bin": {
|
|
30
|
-
"pscode": "
|
|
30
|
+
"pscode": "bin/pscode.js"
|
|
31
31
|
},
|
|
32
32
|
"files": [
|
|
33
33
|
"dist",
|
|
34
34
|
"bin",
|
|
35
35
|
"schemas",
|
|
36
|
+
"pscode/content",
|
|
36
37
|
"scripts/postinstall.js",
|
|
37
38
|
"!dist/**/*.test.js",
|
|
38
39
|
"!dist/**/__tests__",
|
package/pscode/content/dixi/architectures/feature-sliced-react/eslint-architecture.mjs.template
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
// eslint-architecture.mjs
|
|
2
|
+
// Regras de isolamento arquitetural para feature-sliced design.
|
|
3
|
+
//
|
|
4
|
+
// Integração: adicione ao seu eslint.config.js:
|
|
5
|
+
//
|
|
6
|
+
// import architectureRules from './eslint-architecture.mjs';
|
|
7
|
+
// export default [...existingConfig, ...architectureRules];
|
|
8
|
+
|
|
9
|
+
export default [
|
|
10
|
+
{
|
|
11
|
+
files: ['src/features/**/*.{ts,tsx,js,jsx}'],
|
|
12
|
+
rules: {
|
|
13
|
+
'no-restricted-imports': [
|
|
14
|
+
'error',
|
|
15
|
+
{
|
|
16
|
+
patterns: [
|
|
17
|
+
{
|
|
18
|
+
group: ['../features/*', '../../features/*', '@/features/*/'],
|
|
19
|
+
message:
|
|
20
|
+
'Features não devem importar umas das outras. Use shared/ para código compartilhado.',
|
|
21
|
+
},
|
|
22
|
+
],
|
|
23
|
+
},
|
|
24
|
+
],
|
|
25
|
+
},
|
|
26
|
+
},
|
|
27
|
+
{
|
|
28
|
+
files: ['src/pages/**/*.{ts,tsx}', 'src/app/**/*.{ts,tsx}'],
|
|
29
|
+
rules: {
|
|
30
|
+
'no-restricted-imports': [
|
|
31
|
+
'error',
|
|
32
|
+
{
|
|
33
|
+
patterns: [
|
|
34
|
+
{
|
|
35
|
+
group: ['*/application/*', '*/domain/*', '*/usecases/*'],
|
|
36
|
+
message:
|
|
37
|
+
'Páginas não devem importar lógica de negócio diretamente. Use features/ ou shared/ como intermediários.',
|
|
38
|
+
},
|
|
39
|
+
],
|
|
40
|
+
},
|
|
41
|
+
],
|
|
42
|
+
},
|
|
43
|
+
},
|
|
44
|
+
];
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
# Features
|
|
2
|
+
|
|
3
|
+
Cada feature é uma unidade autônoma de funcionalidade de negócio.
|
|
4
|
+
|
|
5
|
+
## Estrutura de uma feature
|
|
6
|
+
|
|
7
|
+
```
|
|
8
|
+
features/
|
|
9
|
+
└── nome-da-feature/
|
|
10
|
+
├── components/ # Componentes React específicos da feature
|
|
11
|
+
├── hooks/ # React hooks específicos da feature
|
|
12
|
+
├── services/ # Chamadas de API específicas da feature
|
|
13
|
+
├── types/ # Tipos TypeScript específicos da feature
|
|
14
|
+
└── index.ts # Ponto de entrada — exporta apenas a API pública
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Regras de importação
|
|
18
|
+
|
|
19
|
+
- Features **não importam umas das outras**
|
|
20
|
+
- ❌ `import { foo } from '@/features/outra-feature'`
|
|
21
|
+
- ✅ Mova o código compartilhado para `shared/`
|
|
22
|
+
- Código compartilhado vive em `shared/` (componentes, hooks, serviços, tipos, utils)
|
|
23
|
+
- Páginas (`pages/` ou `app/`) podem importar de `features/` via `index.ts`
|
|
24
|
+
|
|
25
|
+
## Como criar uma nova feature
|
|
26
|
+
|
|
27
|
+
1. Crie o diretório `features/nome-da-feature/`
|
|
28
|
+
2. Adicione subdiretórios conforme necessário (`components/`, `hooks/`, etc.)
|
|
29
|
+
3. Exporte a API pública via `index.ts`
|
|
30
|
+
4. Importe nas páginas via `@/features/nome-da-feature`
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
package {basePackage};
|
|
2
|
+
|
|
3
|
+
import com.tngtech.archunit.core.domain.JavaClasses;
|
|
4
|
+
import com.tngtech.archunit.core.importer.ClassFileImporter;
|
|
5
|
+
import com.tngtech.archunit.lang.ArchRule;
|
|
6
|
+
import org.junit.jupiter.api.Test;
|
|
7
|
+
|
|
8
|
+
import static com.tngtech.archunit.lang.syntax.ArchRuleDefinition.noClasses;
|
|
9
|
+
|
|
10
|
+
public class ArchitectureTest {
|
|
11
|
+
|
|
12
|
+
private static final JavaClasses classes =
|
|
13
|
+
new ClassFileImporter().importPackages("{basePackage}");
|
|
14
|
+
|
|
15
|
+
@Test
|
|
16
|
+
void dominio_nao_deve_depender_de_infra() {
|
|
17
|
+
ArchRule rule = noClasses()
|
|
18
|
+
.that().resideInAPackage("{basePackage}.domain..")
|
|
19
|
+
.should().dependOnClassesThat()
|
|
20
|
+
.resideInAPackage("{basePackage}.infrastructure..");
|
|
21
|
+
rule.check(classes);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
@Test
|
|
25
|
+
void aplicacao_nao_deve_depender_de_infra() {
|
|
26
|
+
ArchRule rule = noClasses()
|
|
27
|
+
.that().resideInAPackage("{basePackage}.application..")
|
|
28
|
+
.should().dependOnClassesThat()
|
|
29
|
+
.resideInAPackage("{basePackage}.infrastructure..");
|
|
30
|
+
rule.check(classes);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
@Test
|
|
34
|
+
void adapter_in_nao_deve_depender_de_adapter_out() {
|
|
35
|
+
ArchRule rule = noClasses()
|
|
36
|
+
.that().resideInAPackage("{basePackage}.infrastructure.adapter.in..")
|
|
37
|
+
.should().dependOnClassesThat()
|
|
38
|
+
.resideInAPackage("{basePackage}.infrastructure.adapter.out..");
|
|
39
|
+
rule.check(classes);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
dirs:
|
|
2
|
+
- src/main/java/{basePackageDir}/domain/model
|
|
3
|
+
- src/main/java/{basePackageDir}/domain/port/in
|
|
4
|
+
- src/main/java/{basePackageDir}/domain/port/out
|
|
5
|
+
- src/main/java/{basePackageDir}/application/usecase
|
|
6
|
+
- src/main/java/{basePackageDir}/infrastructure/adapter/in/rest
|
|
7
|
+
- src/main/java/{basePackageDir}/infrastructure/adapter/out/persistence
|
|
8
|
+
- src/main/java/{basePackageDir}/infrastructure/config
|
|
9
|
+
- src/test/java/{basePackageDir}/domain
|
|
10
|
+
- src/test/java/{basePackageDir}/application
|
|
11
|
+
- src/test/java/{basePackageDir}/infrastructure
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
<!-- dixi-constitutional -->
|
|
2
|
+
# Regras Constitucionais — Java/Spring (Arquitetura Hexagonal)
|
|
3
|
+
|
|
4
|
+
> Regras invioláveis. Não negocie sem motivo documentado.
|
|
5
|
+
> Detalhes completos em `pastelsdd/context/`.
|
|
6
|
+
|
|
7
|
+
## Arquitetura Hexagonal
|
|
8
|
+
|
|
9
|
+
### Camadas (da mais interna para a mais externa)
|
|
10
|
+
- `domain/` — entidades, value objects, interfaces de repositório, regras de negócio puras
|
|
11
|
+
- `application/` — use cases, ports (interfaces de entrada e saída)
|
|
12
|
+
- `infrastructure/` — adapters (JPA, REST controllers, messaging, config)
|
|
13
|
+
|
|
14
|
+
### Regra de Dependência (OBRIGATÓRIO)
|
|
15
|
+
```
|
|
16
|
+
infrastructure → application → domain
|
|
17
|
+
```
|
|
18
|
+
- `domain` não importa NADA de `application` ou `infrastructure`
|
|
19
|
+
- `application` não importa NADA de `infrastructure`
|
|
20
|
+
- Adapters (`infrastructure`) só acessam `application` via interfaces (ports)
|
|
21
|
+
|
|
22
|
+
### Imports Proibidos
|
|
23
|
+
- `domain.*` nunca importa `application.*` ou `infrastructure.*`
|
|
24
|
+
- `application.*` nunca importa `infrastructure.*`
|
|
25
|
+
- Exceção: testes de integração em `infrastructure/` podem referenciar qualquer camada
|
|
26
|
+
|
|
27
|
+
## Nomenclatura por Camada
|
|
28
|
+
|
|
29
|
+
| Camada | Sufixo/Convenção |
|
|
30
|
+
|--------|------------------|
|
|
31
|
+
| `domain/entity/` | `Order`, `Customer` (sem sufixo) |
|
|
32
|
+
| `domain/repository/` | `OrderRepository` (interface) |
|
|
33
|
+
| `domain/service/` | `PricingService` (interface/pura) |
|
|
34
|
+
| `application/usecase/` | `CreateOrderUseCase` |
|
|
35
|
+
| `application/port/in/` | `CreateOrderPort` |
|
|
36
|
+
| `application/port/out/` | `SaveOrderPort` |
|
|
37
|
+
| `infrastructure/adapter/in/` | `OrderController`, `OrderListener` |
|
|
38
|
+
| `infrastructure/adapter/out/` | `OrderJpaAdapter`, `OrderEmailAdapter` |
|
|
39
|
+
|
|
40
|
+
## Commits
|
|
41
|
+
|
|
42
|
+
Formato obrigatório: `<type>(<scope>): <msg> [TICKET-123]`
|
|
43
|
+
|
|
44
|
+
- `type`: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`
|
|
45
|
+
- `scope`: módulo ou camada afetada (e.g., `order`, `domain`, `infra`)
|
|
46
|
+
- Ticket JIRA obrigatório. Se não houver ticket, usar `[NO-TICKET]`
|
|
47
|
+
|
|
48
|
+
Exemplos:
|
|
49
|
+
```
|
|
50
|
+
feat(order): add CreateOrderUseCase [PROJ-42]
|
|
51
|
+
fix(infra): correct JPA mapping for OrderStatus [PROJ-55]
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
## Referências
|
|
55
|
+
|
|
56
|
+
Docs completos em `pastelsdd/context/`:
|
|
57
|
+
- `pastelsdd/context/java/architecture.md` — guia completo de arquitetura hexagonal
|
|
58
|
+
- `pastelsdd/context/java/naming.md` — convenções de nomenclatura por camada
|
|
59
|
+
- `pastelsdd/context/shared/commits.md` — convenção completa de commits
|
|
60
|
+
- `pastelsdd/context/shared/dev-flow.md` — fluxo de desenvolvimento e PR
|
|
61
|
+
|
|
62
|
+
> Se `pastelsdd/context/` não existe, rode `pscode init --profile dixi` para instalar.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
<!-- dixi-constitutional -->
|
|
2
|
+
# Regras Constitucionais — React/Next.js + TypeScript (Feature-Sliced Design)
|
|
3
|
+
|
|
4
|
+
> Regras invioláveis. Não negocie sem motivo documentado.
|
|
5
|
+
> Detalhes completos em `pastelsdd/context/`.
|
|
6
|
+
|
|
7
|
+
## Feature-Sliced Design
|
|
8
|
+
|
|
9
|
+
### Camadas (da mais compartilhada para a mais específica)
|
|
10
|
+
```
|
|
11
|
+
shared → entities → features → pages/app
|
|
12
|
+
```
|
|
13
|
+
- `shared/` — UI primitivos, utilitários, tipos globais, configuração de API
|
|
14
|
+
- `entities/` — modelos de domínio (User, Order) sem lógica de feature
|
|
15
|
+
- `features/` — funcionalidades de produto isoladas (auth, cart, checkout)
|
|
16
|
+
- `pages/` ou `app/` — composição de features e rotas (Next.js)
|
|
17
|
+
|
|
18
|
+
### Regra de Isolamento de Features (OBRIGATÓRIO)
|
|
19
|
+
- **Features NÃO importam umas das outras**
|
|
20
|
+
- Se dois features precisam de algo em comum → mover para `entities/` ou `shared/`
|
|
21
|
+
- `pages/app` orquestra features; não contém lógica de negócio
|
|
22
|
+
|
|
23
|
+
### Imports Proibidos
|
|
24
|
+
- `features/auth` nunca importa `features/cart` (ou qualquer outro feature)
|
|
25
|
+
- `shared/` nunca importa `entities/` ou `features/`
|
|
26
|
+
- `entities/` nunca importa `features/`
|
|
27
|
+
|
|
28
|
+
## Nomenclatura
|
|
29
|
+
|
|
30
|
+
| Tipo | Convenção |
|
|
31
|
+
|------|-----------|
|
|
32
|
+
| Componentes React | `PascalCase` — `UserCard`, `OrderList` |
|
|
33
|
+
| Hooks | `use` + `PascalCase` — `useUserSession`, `useCartItems` |
|
|
34
|
+
| Services / API | `camelCase` — `userService`, `orderApi` |
|
|
35
|
+
| Arquivos de componente | `PascalCase.tsx` — `UserCard.tsx` |
|
|
36
|
+
| Arquivos de hook | `camelCase.ts` — `useUserSession.ts` |
|
|
37
|
+
| Arquivos de tipo | `camelCase.types.ts` ou `types.ts` no módulo |
|
|
38
|
+
| Testes | `<nome>.test.tsx` no mesmo diretório |
|
|
39
|
+
|
|
40
|
+
## Estrutura Interna de um Feature
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
features/auth/
|
|
44
|
+
ui/ ← componentes do feature
|
|
45
|
+
model/ ← store, hooks, lógica de estado
|
|
46
|
+
api/ ← chamadas de API específicas do feature
|
|
47
|
+
lib/ ← helpers internos
|
|
48
|
+
index.ts ← API pública do feature (barrel export)
|
|
49
|
+
```
|
|
50
|
+
Só o que está em `index.ts` pode ser importado de fora do feature.
|
|
51
|
+
|
|
52
|
+
## Commits
|
|
53
|
+
|
|
54
|
+
Formato obrigatório: `<type>(<scope>): <msg> [TICKET-123]`
|
|
55
|
+
|
|
56
|
+
- `type`: `feat`, `fix`, `refactor`, `test`, `docs`, `chore`
|
|
57
|
+
- `scope`: feature ou camada afetada (e.g., `auth`, `cart`, `shared`)
|
|
58
|
+
- Ticket JIRA obrigatório. Se não houver ticket, usar `[NO-TICKET]`
|
|
59
|
+
|
|
60
|
+
Exemplos:
|
|
61
|
+
```
|
|
62
|
+
feat(auth): add OAuth2 login flow [PROJ-10]
|
|
63
|
+
fix(cart): correct item count on empty cart [PROJ-23]
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Referências
|
|
67
|
+
|
|
68
|
+
Docs completos em `pastelsdd/context/`:
|
|
69
|
+
- `pastelsdd/context/react/architecture.md` — guia completo de feature-sliced design
|
|
70
|
+
- `pastelsdd/context/react/naming.md` — convenções de nomenclatura
|
|
71
|
+
- `pastelsdd/context/shared/commits.md` — convenção completa de commits
|
|
72
|
+
- `pastelsdd/context/shared/dev-flow.md` — fluxo de desenvolvimento e PR
|
|
73
|
+
|
|
74
|
+
> Se `pastelsdd/context/` não existe, rode `pscode init --profile dixi` para instalar.
|