@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.
Files changed (84) hide show
  1. package/README.md +2 -2
  2. package/dist/cli/index.js +6 -6
  3. package/dist/commands/config.d.ts +4 -12
  4. package/dist/commands/config.js +69 -242
  5. package/dist/core/change-metadata/schema.d.ts +1 -0
  6. package/dist/core/change-metadata/schema.js +1 -0
  7. package/dist/core/{archive.d.ts → complete.d.ts} +2 -2
  8. package/dist/core/{archive.js → complete.js} +28 -5
  9. package/dist/core/completions/command-registry.js +5 -5
  10. package/dist/core/config-schema.d.ts +1 -5
  11. package/dist/core/config-schema.js +2 -5
  12. package/dist/core/global-config.d.ts +1 -3
  13. package/dist/core/global-config.js +1 -1
  14. package/dist/core/init.d.ts +2 -0
  15. package/dist/core/init.js +81 -20
  16. package/dist/core/jira-transition.d.ts +16 -0
  17. package/dist/core/jira-transition.js +29 -0
  18. package/dist/core/migration.d.ts +3 -12
  19. package/dist/core/migration.js +10 -72
  20. package/dist/core/presets/dixi.d.ts +32 -0
  21. package/dist/core/presets/dixi.js +405 -0
  22. package/dist/core/profile-sync-drift.js +9 -1
  23. package/dist/core/profiles.d.ts +23 -21
  24. package/dist/core/profiles.js +28 -24
  25. package/dist/core/shared/skill-generation.js +3 -3
  26. package/dist/core/shared/tool-detection.d.ts +1 -1
  27. package/dist/core/shared/tool-detection.js +1 -1
  28. package/dist/core/templates/skill-templates.d.ts +1 -1
  29. package/dist/core/templates/skill-templates.js +1 -1
  30. package/dist/core/templates/workflows/apply-change.js +3 -3
  31. package/dist/core/templates/workflows/archive-change.d.ts +2 -2
  32. package/dist/core/templates/workflows/archive-change.js +10 -10
  33. package/dist/core/templates/workflows/onboard.js +9 -9
  34. package/dist/core/update.d.ts +1 -6
  35. package/dist/core/update.js +5 -29
  36. package/dist/core/workspace/foundation.d.ts +1 -1
  37. package/dist/core/workspace/foundation.js +1 -1
  38. package/dist/core/workspace/legacy-state.js +1 -1
  39. package/dist/core/workspace/skills.d.ts +4 -3
  40. package/dist/core/workspace/skills.js +3 -3
  41. package/package.json +4 -3
  42. package/pscode/content/dixi/architectures/feature-sliced-react/eslint-architecture.mjs.template +44 -0
  43. package/pscode/content/dixi/architectures/feature-sliced-react/features/README.md.template +30 -0
  44. package/pscode/content/dixi/architectures/feature-sliced-react/skeleton.yaml +8 -0
  45. package/pscode/content/dixi/architectures/hexagonal-spring/ArchitectureTest.java.template +41 -0
  46. package/pscode/content/dixi/architectures/hexagonal-spring/skeleton.yaml +11 -0
  47. package/pscode/content/dixi/claude-runtime/CLAUDE.md.java.template +62 -0
  48. package/pscode/content/dixi/claude-runtime/CLAUDE.md.react.template +74 -0
  49. package/pscode/content/dixi/claude-runtime/commands/adr.md +75 -0
  50. package/pscode/content/dixi/claude-runtime/commands/arch-check.md +64 -0
  51. package/pscode/content/dixi/claude-runtime/commands/dod.md +66 -0
  52. package/pscode/content/dixi/claude-runtime/commands/jira-draft.md +80 -0
  53. package/pscode/content/dixi/claude-runtime/commands/jira-setup.md +105 -0
  54. package/pscode/content/dixi/claude-runtime/commands/jira-sync.md +69 -0
  55. package/pscode/content/dixi/claude-runtime/commands/rfc.md +73 -0
  56. package/pscode/content/dixi/claude-runtime/hooks/arch-guard.mjs +101 -0
  57. package/pscode/content/dixi/claude-runtime/hooks/jira-context.mjs +60 -0
  58. package/pscode/content/dixi/claude-runtime/skills/pstld-arch-guardian.md +101 -0
  59. package/pscode/content/dixi/claude-runtime/skills/pstld-commit-crafter.md +98 -0
  60. package/pscode/content/dixi/claude-runtime/skills/pstld-jira-context.md +64 -0
  61. package/pscode/content/dixi/context/java/architecture.md +143 -0
  62. package/pscode/content/dixi/context/java/naming.md +62 -0
  63. package/pscode/content/dixi/context/java/testing.md +162 -0
  64. package/pscode/content/dixi/context/react/architecture.md +119 -0
  65. package/pscode/content/dixi/context/react/naming.md +129 -0
  66. package/pscode/content/dixi/context/react/testing.md +141 -0
  67. package/pscode/content/dixi/context/shared/commits.md +47 -0
  68. package/pscode/content/dixi/context/shared/dev-flow.md +53 -0
  69. package/pscode/content/dixi/context/shared/dod.md +38 -0
  70. package/pscode/content/dixi/context/shared/pr-flow.md +53 -0
  71. package/pscode/content/dixi/kit/java/.editorconfig +25 -0
  72. package/pscode/content/dixi/kit/java/.github/workflows/ci-java.yml +68 -0
  73. package/pscode/content/dixi/kit/java/.husky/commit-msg +2 -0
  74. package/pscode/content/dixi/kit/react/.editorconfig +20 -0
  75. package/pscode/content/dixi/kit/react/.github/workflows/ci-react.yml +80 -0
  76. package/pscode/content/dixi/kit/react/.husky/commit-msg +2 -0
  77. package/pscode/content/dixi/kit/react/.husky/pre-commit +2 -0
  78. package/pscode/content/dixi/kit/react/lint-staged.config.mjs +4 -0
  79. package/pscode/content/dixi/kit/shared/.commitlintrc.yml +15 -0
  80. package/pscode/content/dixi/kit/shared/.github/pull_request_template.md +24 -0
  81. package/schemas/pstld-workflow/schema.yaml +67 -0
  82. package/schemas/pstld-workflow/templates/design.md +15 -0
  83. package/schemas/pstld-workflow/templates/rfc.md +26 -0
  84. package/schemas/pstld-workflow/templates/tasks.md +15 -0
@@ -1,26 +1,26 @@
1
- export function getArchiveChangeSkillTemplate() {
1
+ export function getCompleteChangeSkillTemplate() {
2
2
  return {
3
3
  name: 'pscode-archive-change',
4
- description: 'Archive a completed change. Use when the user wants to finalize and archive a change after implementation is complete.',
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 getPsArchiveCommandTemplate() {
11
+ export function getPsCompleteCommandTemplate() {
12
12
  return {
13
- name: 'PS: Archive',
14
- description: 'Archive a completed change',
13
+ name: 'PS: Complete',
14
+ description: 'Complete a change',
15
15
  category: 'Workflow',
16
- tags: ['workflow', 'archive'],
16
+ tags: ['workflow', 'complete'],
17
17
  content: getArchiveInstructions(),
18
18
  };
19
19
  }
20
20
  function getArchiveInstructions() {
21
- return `Archive a completed change.
21
+ return `Complete a change.
22
22
 
23
- **Input**: Optionally specify a change name (e.g., \`/ps:archive add-auth\`). If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
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: "Arquivada via /ps:archive"
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 arquivada via /ps:archive
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 archive it.
415
+ The change is implemented! One more step—let's complete it.
416
416
  \`\`\`
417
417
 
418
418
  ---
419
419
 
420
- ## Phase 10: Archive
420
+ ## Phase 10: Complete
421
421
 
422
422
  **EXPLAIN:**
423
423
  \`\`\`
424
- ## Archiving
424
+ ## Completing
425
425
 
426
- When a change is complete, we archive it. The archive path is derived from \`planningHome.changesDir\` and the date.
426
+ When a change is complete, we complete it. The archive path is derived from \`planningHome.changesDir\` and the date.
427
427
 
428
- Archived changes become your project's decision history—you can always find them later to understand why something was built a certain way.
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 archive "<name>"
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:archive → move card para "Concluído"
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:archive\` | Archive a completed change |
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:archive <name>\` | Archive when done |
570
+ | \`/ps:complete <name>\` | Complete when done |
571
571
 
572
572
  **Additional commands:**
573
573
 
@@ -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 current profile.
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.
@@ -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 ?? 'core';
56
+ const profile = isValidProfile(globalConfig.profile ?? '') ? globalConfig.profile : DEFAULT_PROFILE;
58
57
  const delivery = globalConfig.delivery ?? 'both';
59
- const profileWorkflows = getProfileWorkflows(profile, globalConfig.workflows);
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 current profile.
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 manage)`));
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?: 'core' | 'custom';
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.enum(['core', 'custom']).optional(),
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(['core', 'custom']).optional(),
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, type Profile } from '../global-config.js';
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: 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: 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 ?? 'core';
14
+ const profile = isValidProfile(globalConfig.profile ?? '') ? globalConfig.profile : DEFAULT_PROFILE;
15
15
  const delivery = globalConfig.delivery ?? 'both';
16
- const workflowIds = [...getProfileWorkflows(profile, globalConfig.workflows)];
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.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": "./bin/pscode.js"
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__",
@@ -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,8 @@
1
+ dirs:
2
+ - src/shared/components/ui
3
+ - src/shared/hooks
4
+ - src/shared/services
5
+ - src/shared/types
6
+ - src/shared/utils
7
+ - src/entities
8
+ - src/features
@@ -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.