@thiagodiogo/pastelsdd 1.0.0-beta.1 → 1.0.0-beta.2

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 (95) hide show
  1. package/README.md +141 -2
  2. package/bin/pastelsdd.js +1 -1
  3. package/dist/core/command-generation/adapters/index.d.ts +0 -21
  4. package/dist/core/command-generation/adapters/index.js +0 -21
  5. package/dist/core/command-generation/index.d.ts +1 -1
  6. package/dist/core/command-generation/index.js +1 -1
  7. package/dist/core/command-generation/registry.d.ts +0 -1
  8. package/dist/core/command-generation/registry.js +0 -43
  9. package/dist/core/config.js +0 -25
  10. package/dist/core/init.d.ts +3 -0
  11. package/dist/core/init.js +95 -12
  12. package/dist/core/legacy-cleanup.d.ts +1 -1
  13. package/dist/core/legacy-cleanup.js +0 -25
  14. package/dist/core/openspec-migration.d.ts +71 -0
  15. package/dist/core/openspec-migration.js +317 -0
  16. package/dist/core/profile-sync-drift.js +3 -0
  17. package/dist/core/profiles.d.ts +1 -1
  18. package/dist/core/profiles.js +3 -0
  19. package/dist/core/shared/skill-generation.d.ts +2 -2
  20. package/dist/core/shared/skill-generation.js +31 -25
  21. package/dist/core/templates/skill-templates.d.ts +13 -11
  22. package/dist/core/templates/skill-templates.js +14 -11
  23. package/dist/core/templates/workflows/apply-change.d.ts +1 -1
  24. package/dist/core/templates/workflows/apply-change.js +212 -300
  25. package/dist/core/templates/workflows/archive-change.d.ts +1 -1
  26. package/dist/core/templates/workflows/archive-change.js +214 -264
  27. package/dist/core/templates/workflows/bulk-archive-change.d.ts +1 -1
  28. package/dist/core/templates/workflows/bulk-archive-change.js +2 -2
  29. package/dist/core/templates/workflows/continue-change.d.ts +1 -1
  30. package/dist/core/templates/workflows/continue-change.js +2 -2
  31. package/dist/core/templates/workflows/explore.d.ts +1 -1
  32. package/dist/core/templates/workflows/explore.js +2 -2
  33. package/dist/core/templates/workflows/ff-change.d.ts +1 -1
  34. package/dist/core/templates/workflows/ff-change.js +2 -2
  35. package/dist/core/templates/workflows/new-change.d.ts +1 -1
  36. package/dist/core/templates/workflows/new-change.js +2 -2
  37. package/dist/core/templates/workflows/onboard.d.ts +1 -1
  38. package/dist/core/templates/workflows/onboard.js +59 -15
  39. package/dist/core/templates/workflows/propose.d.ts +2 -2
  40. package/dist/core/templates/workflows/propose.js +83 -115
  41. package/dist/core/templates/workflows/sync-specs.d.ts +1 -1
  42. package/dist/core/templates/workflows/sync-specs.js +2 -2
  43. package/dist/core/templates/workflows/trello-draft.d.ts +12 -0
  44. package/dist/core/templates/workflows/trello-draft.js +139 -0
  45. package/dist/core/templates/workflows/trello-setup.d.ts +11 -0
  46. package/dist/core/templates/workflows/trello-setup.js +243 -0
  47. package/dist/core/templates/workflows/verify-change.d.ts +1 -1
  48. package/dist/core/templates/workflows/verify-change.js +2 -2
  49. package/dist/core/trello-config.d.ts +58 -0
  50. package/dist/core/trello-config.js +52 -0
  51. package/dist/core/trello-init-prompt.d.ts +44 -0
  52. package/dist/core/trello-init-prompt.js +152 -0
  53. package/package.json +3 -2
  54. package/dist/core/command-generation/adapters/amazon-q.d.ts +0 -13
  55. package/dist/core/command-generation/adapters/amazon-q.js +0 -26
  56. package/dist/core/command-generation/adapters/antigravity.d.ts +0 -13
  57. package/dist/core/command-generation/adapters/antigravity.js +0 -26
  58. package/dist/core/command-generation/adapters/auggie.d.ts +0 -13
  59. package/dist/core/command-generation/adapters/auggie.js +0 -27
  60. package/dist/core/command-generation/adapters/bob.d.ts +0 -14
  61. package/dist/core/command-generation/adapters/bob.js +0 -45
  62. package/dist/core/command-generation/adapters/cline.d.ts +0 -14
  63. package/dist/core/command-generation/adapters/cline.js +0 -27
  64. package/dist/core/command-generation/adapters/codebuddy.d.ts +0 -13
  65. package/dist/core/command-generation/adapters/codebuddy.js +0 -28
  66. package/dist/core/command-generation/adapters/continue.d.ts +0 -13
  67. package/dist/core/command-generation/adapters/continue.js +0 -28
  68. package/dist/core/command-generation/adapters/costrict.d.ts +0 -13
  69. package/dist/core/command-generation/adapters/costrict.js +0 -27
  70. package/dist/core/command-generation/adapters/crush.d.ts +0 -13
  71. package/dist/core/command-generation/adapters/crush.js +0 -30
  72. package/dist/core/command-generation/adapters/factory.d.ts +0 -13
  73. package/dist/core/command-generation/adapters/factory.js +0 -27
  74. package/dist/core/command-generation/adapters/iflow.d.ts +0 -13
  75. package/dist/core/command-generation/adapters/iflow.js +0 -29
  76. package/dist/core/command-generation/adapters/junie.d.ts +0 -13
  77. package/dist/core/command-generation/adapters/junie.js +0 -26
  78. package/dist/core/command-generation/adapters/kilocode.d.ts +0 -14
  79. package/dist/core/command-generation/adapters/kilocode.js +0 -23
  80. package/dist/core/command-generation/adapters/kiro.d.ts +0 -13
  81. package/dist/core/command-generation/adapters/kiro.js +0 -26
  82. package/dist/core/command-generation/adapters/lingma.d.ts +0 -13
  83. package/dist/core/command-generation/adapters/lingma.js +0 -30
  84. package/dist/core/command-generation/adapters/opencode.d.ts +0 -13
  85. package/dist/core/command-generation/adapters/opencode.js +0 -29
  86. package/dist/core/command-generation/adapters/pi.d.ts +0 -18
  87. package/dist/core/command-generation/adapters/pi.js +0 -55
  88. package/dist/core/command-generation/adapters/qoder.d.ts +0 -13
  89. package/dist/core/command-generation/adapters/qoder.js +0 -30
  90. package/dist/core/command-generation/adapters/qwen.d.ts +0 -13
  91. package/dist/core/command-generation/adapters/qwen.js +0 -26
  92. package/dist/core/command-generation/adapters/roocode.d.ts +0 -14
  93. package/dist/core/command-generation/adapters/roocode.js +0 -27
  94. package/dist/core/command-generation/adapters/windsurf.d.ts +0 -14
  95. package/dist/core/command-generation/adapters/windsurf.js +0 -51
package/README.md CHANGED
@@ -1,3 +1,142 @@
1
- # pastelsdd
1
+ # pastelsdd
2
2
 
3
- > Work in progress.
3
+ > Spec-driven, AI-native development workflow CLI
4
+
5
+ [![npm](https://img.shields.io/npm/v/@thiagodiogo/pastelsdd)](https://www.npmjs.com/package/@thiagodiogo/pastelsdd)
6
+ [![license](https://img.shields.io/npm/l/@thiagodiogo/pastelsdd)](LICENSE)
7
+ [![node](https://img.shields.io/node/v/@thiagodiogo/pastelsdd)](https://nodejs.org)
8
+
9
+ Pastelsdd installs a planning pipeline inside your repo. Every feature goes through **proposal → specs → design → tasks → apply**, tracked as versioned files and exposed as slash commands to your AI agent.
10
+
11
+ ---
12
+
13
+ ## Requirements
14
+
15
+ - Node.js `>= 20.19.0`
16
+ - At least one supported AI tool: **Claude Code**, **Cursor**, **Gemini CLI**, **GitHub Copilot**, or **Codex CLI**
17
+
18
+ ---
19
+
20
+ ## Install
21
+
22
+ ```bash
23
+ npm install -g @thiagodiogo/pastelsdd
24
+ # or
25
+ pnpm add -g @thiagodiogo/pastelsdd
26
+ ```
27
+
28
+ ---
29
+
30
+ ## Quick Start
31
+
32
+ ```bash
33
+ cd your-project
34
+ pastelsdd init
35
+ ```
36
+
37
+ The init wizard auto-detects which AI tools you have (`.claude/`, `.cursor/`, etc.), installs skill files and slash commands, and creates the planning folder:
38
+
39
+ ```
40
+ pastelsdd/
41
+ ├── changes/ ← one subfolder per active change
42
+ │ └── archive/ ← completed changes
43
+ ├── specs/ ← project capability specs
44
+ └── config.yaml ← local schema config
45
+ ```
46
+
47
+ Once initialized, use slash commands in your AI agent:
48
+
49
+ ```
50
+ /pastel:propose "add dark mode" ← creates a new change
51
+ /pastel:continue ← advances to the next artifact
52
+ /pastel:apply ← applies pending tasks
53
+ /pastel:archive ← archives a completed change
54
+ ```
55
+
56
+ ---
57
+
58
+ ## How It Works
59
+
60
+ Each change lives in `pastelsdd/changes/<name>/` and follows a DAG of artifacts defined by a workflow schema:
61
+
62
+ ```
63
+ pastelsdd/changes/dark-mode/
64
+ ├── proposal.md ← why this change
65
+ ├── specs/ ← what the system must do
66
+ ├── design.md ← how to implement it
67
+ └── tasks.md ← implementation checklist
68
+ ```
69
+
70
+ The AI agent reads these files at each step and generates the next artifact using enriched instructions from the schema.
71
+
72
+ ---
73
+
74
+ ## CLI Reference
75
+
76
+ | Command | Description |
77
+ |---------|-------------|
78
+ | `pastelsdd init [path]` | Initialize Pastelsdd in a project |
79
+ | `pastelsdd update [path]` | Regenerate skill/command files after an upgrade |
80
+ | `pastelsdd list` | List active changes |
81
+ | `pastelsdd list --specs` | List project specs |
82
+ | `pastelsdd status` | Show artifact completion for the current change |
83
+ | `pastelsdd instructions [artifact]` | Print enriched instructions for an artifact |
84
+ | `pastelsdd validate [name]` | Validate a change or spec |
85
+ | `pastelsdd validate --all` | Validate everything |
86
+ | `pastelsdd show [name]` | Display a change or spec |
87
+ | `pastelsdd archive [name]` | Archive a completed change |
88
+ | `pastelsdd new change <name>` | Create a new change directory |
89
+ | `pastelsdd schemas` | List available workflow schemas |
90
+ | `pastelsdd view` | Interactive dashboard |
91
+ | `pastelsdd feedback <message>` | Submit feedback |
92
+ | `pastelsdd completion install` | Install shell completions |
93
+
94
+ ### `init` options
95
+
96
+ | Flag | Description |
97
+ |------|-------------|
98
+ | `--tools <list>` | Skip interactive selection. Use `all`, `none`, or e.g. `claude,cursor` |
99
+ | `--force` | Skip all confirmations (CI-friendly) |
100
+ | `--profile <name>` | Workflow profile: `core` (default) or `custom` |
101
+
102
+ **Non-interactive example:**
103
+
104
+ ```bash
105
+ pastelsdd init --tools claude --force
106
+ ```
107
+
108
+ ---
109
+
110
+ ## Supported AI Tools
111
+
112
+ | Tool | Skills dir |
113
+ |------|-----------|
114
+ | Claude Code | `.claude/` |
115
+ | Codex CLI | `.codex/` |
116
+ | Cursor | `.cursor/` |
117
+ | Gemini CLI | `.gemini/` |
118
+ | GitHub Copilot | `.github/` |
119
+
120
+ ---
121
+
122
+ ## Migrating from OpenSpec
123
+
124
+ If your project used the old `openspec` tool, `pastelsdd init` detects `.openspec/` automatically and offers to migrate your changes and specs — no manual steps needed.
125
+
126
+ ---
127
+
128
+ ## After Upgrading
129
+
130
+ Re-run `pastelsdd init` (or `pastelsdd update`) to regenerate skill files with the latest instructions:
131
+
132
+ ```bash
133
+ pastelsdd update
134
+ ```
135
+
136
+ ---
137
+
138
+ ## Links
139
+
140
+ - [npm](https://www.npmjs.com/package/@thiagodiogo/pastelsdd)
141
+ - [Repository](https://github.com/thiagodiogo/pastelsdd)
142
+ - [Issues / Feedback](https://github.com/thiagodiogo/pastelsdd/issues)
package/bin/pastelsdd.js CHANGED
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
 
3
3
  import { runCli } from '../dist/cli/index.js';
4
4
 
@@ -3,30 +3,9 @@
3
3
  *
4
4
  * Re-exports all tool command adapters.
5
5
  */
6
- export { amazonQAdapter } from './amazon-q.js';
7
- export { antigravityAdapter } from './antigravity.js';
8
- export { auggieAdapter } from './auggie.js';
9
- export { bobAdapter } from './bob.js';
10
6
  export { claudeAdapter } from './claude.js';
11
- export { clineAdapter } from './cline.js';
12
7
  export { codexAdapter } from './codex.js';
13
- export { codebuddyAdapter } from './codebuddy.js';
14
- export { continueAdapter } from './continue.js';
15
- export { costrictAdapter } from './costrict.js';
16
- export { crushAdapter } from './crush.js';
17
8
  export { cursorAdapter } from './cursor.js';
18
- export { factoryAdapter } from './factory.js';
19
9
  export { geminiAdapter } from './gemini.js';
20
10
  export { githubCopilotAdapter } from './github-copilot.js';
21
- export { iflowAdapter } from './iflow.js';
22
- export { junieAdapter } from './junie.js';
23
- export { kilocodeAdapter } from './kilocode.js';
24
- export { kiroAdapter } from './kiro.js';
25
- export { opencodeAdapter } from './opencode.js';
26
- export { piAdapter } from './pi.js';
27
- export { qoderAdapter } from './qoder.js';
28
- export { lingmaAdapter } from './lingma.js';
29
- export { qwenAdapter } from './qwen.js';
30
- export { roocodeAdapter } from './roocode.js';
31
- export { windsurfAdapter } from './windsurf.js';
32
11
  //# sourceMappingURL=index.d.ts.map
@@ -3,30 +3,9 @@
3
3
  *
4
4
  * Re-exports all tool command adapters.
5
5
  */
6
- export { amazonQAdapter } from './amazon-q.js';
7
- export { antigravityAdapter } from './antigravity.js';
8
- export { auggieAdapter } from './auggie.js';
9
- export { bobAdapter } from './bob.js';
10
6
  export { claudeAdapter } from './claude.js';
11
- export { clineAdapter } from './cline.js';
12
7
  export { codexAdapter } from './codex.js';
13
- export { codebuddyAdapter } from './codebuddy.js';
14
- export { continueAdapter } from './continue.js';
15
- export { costrictAdapter } from './costrict.js';
16
- export { crushAdapter } from './crush.js';
17
8
  export { cursorAdapter } from './cursor.js';
18
- export { factoryAdapter } from './factory.js';
19
9
  export { geminiAdapter } from './gemini.js';
20
10
  export { githubCopilotAdapter } from './github-copilot.js';
21
- export { iflowAdapter } from './iflow.js';
22
- export { junieAdapter } from './junie.js';
23
- export { kilocodeAdapter } from './kilocode.js';
24
- export { kiroAdapter } from './kiro.js';
25
- export { opencodeAdapter } from './opencode.js';
26
- export { piAdapter } from './pi.js';
27
- export { qoderAdapter } from './qoder.js';
28
- export { lingmaAdapter } from './lingma.js';
29
- export { qwenAdapter } from './qwen.js';
30
- export { roocodeAdapter } from './roocode.js';
31
- export { windsurfAdapter } from './windsurf.js';
32
11
  //# sourceMappingURL=index.js.map
@@ -18,5 +18,5 @@
18
18
  export type { CommandContent, ToolCommandAdapter, GeneratedCommand, } from './types.js';
19
19
  export { CommandAdapterRegistry } from './registry.js';
20
20
  export { generateCommand, generateCommands } from './generator.js';
21
- export { claudeAdapter, cursorAdapter, windsurfAdapter } from './adapters/index.js';
21
+ export { claudeAdapter, codexAdapter, cursorAdapter, geminiAdapter, githubCopilotAdapter } from './adapters/index.js';
22
22
  //# sourceMappingURL=index.d.ts.map
@@ -20,5 +20,5 @@ export { CommandAdapterRegistry } from './registry.js';
20
20
  // Generator functions
21
21
  export { generateCommand, generateCommands } from './generator.js';
22
22
  // Adapters (for direct access if needed)
23
- export { claudeAdapter, cursorAdapter, windsurfAdapter } from './adapters/index.js';
23
+ export { claudeAdapter, codexAdapter, cursorAdapter, geminiAdapter, githubCopilotAdapter } from './adapters/index.js';
24
24
  //# sourceMappingURL=index.js.map
@@ -2,7 +2,6 @@
2
2
  * Command Adapter Registry
3
3
  *
4
4
  * Centralized registry for tool command adapters.
5
- * Similar pattern to existing SlashCommandRegistry in the codebase.
6
5
  */
7
6
  import type { ToolCommandAdapter } from './types.js';
8
7
  /**
@@ -2,34 +2,12 @@
2
2
  * Command Adapter Registry
3
3
  *
4
4
  * Centralized registry for tool command adapters.
5
- * Similar pattern to existing SlashCommandRegistry in the codebase.
6
5
  */
7
- import { amazonQAdapter } from './adapters/amazon-q.js';
8
- import { antigravityAdapter } from './adapters/antigravity.js';
9
- import { auggieAdapter } from './adapters/auggie.js';
10
- import { bobAdapter } from './adapters/bob.js';
11
6
  import { claudeAdapter } from './adapters/claude.js';
12
- import { clineAdapter } from './adapters/cline.js';
13
7
  import { codexAdapter } from './adapters/codex.js';
14
- import { codebuddyAdapter } from './adapters/codebuddy.js';
15
- import { continueAdapter } from './adapters/continue.js';
16
- import { costrictAdapter } from './adapters/costrict.js';
17
- import { crushAdapter } from './adapters/crush.js';
18
8
  import { cursorAdapter } from './adapters/cursor.js';
19
- import { factoryAdapter } from './adapters/factory.js';
20
9
  import { geminiAdapter } from './adapters/gemini.js';
21
10
  import { githubCopilotAdapter } from './adapters/github-copilot.js';
22
- import { iflowAdapter } from './adapters/iflow.js';
23
- import { junieAdapter } from './adapters/junie.js';
24
- import { kilocodeAdapter } from './adapters/kilocode.js';
25
- import { kiroAdapter } from './adapters/kiro.js';
26
- import { opencodeAdapter } from './adapters/opencode.js';
27
- import { piAdapter } from './adapters/pi.js';
28
- import { qoderAdapter } from './adapters/qoder.js';
29
- import { lingmaAdapter } from './adapters/lingma.js';
30
- import { qwenAdapter } from './adapters/qwen.js';
31
- import { roocodeAdapter } from './adapters/roocode.js';
32
- import { windsurfAdapter } from './adapters/windsurf.js';
33
11
  /**
34
12
  * Registry for looking up tool command adapters.
35
13
  */
@@ -37,32 +15,11 @@ export class CommandAdapterRegistry {
37
15
  static adapters = new Map();
38
16
  // Static initializer - register built-in adapters
39
17
  static {
40
- CommandAdapterRegistry.register(amazonQAdapter);
41
- CommandAdapterRegistry.register(antigravityAdapter);
42
- CommandAdapterRegistry.register(auggieAdapter);
43
- CommandAdapterRegistry.register(bobAdapter);
44
18
  CommandAdapterRegistry.register(claudeAdapter);
45
- CommandAdapterRegistry.register(clineAdapter);
46
19
  CommandAdapterRegistry.register(codexAdapter);
47
- CommandAdapterRegistry.register(codebuddyAdapter);
48
- CommandAdapterRegistry.register(continueAdapter);
49
- CommandAdapterRegistry.register(costrictAdapter);
50
- CommandAdapterRegistry.register(crushAdapter);
51
20
  CommandAdapterRegistry.register(cursorAdapter);
52
- CommandAdapterRegistry.register(factoryAdapter);
53
21
  CommandAdapterRegistry.register(geminiAdapter);
54
22
  CommandAdapterRegistry.register(githubCopilotAdapter);
55
- CommandAdapterRegistry.register(iflowAdapter);
56
- CommandAdapterRegistry.register(junieAdapter);
57
- CommandAdapterRegistry.register(kilocodeAdapter);
58
- CommandAdapterRegistry.register(kiroAdapter);
59
- CommandAdapterRegistry.register(opencodeAdapter);
60
- CommandAdapterRegistry.register(piAdapter);
61
- CommandAdapterRegistry.register(qoderAdapter);
62
- CommandAdapterRegistry.register(lingmaAdapter);
63
- CommandAdapterRegistry.register(qwenAdapter);
64
- CommandAdapterRegistry.register(roocodeAdapter);
65
- CommandAdapterRegistry.register(windsurfAdapter);
66
23
  }
67
24
  /**
68
25
  * Register a tool command adapter.
@@ -4,35 +4,10 @@ export const PASTELSDD_MARKERS = {
4
4
  end: '<!-- PASTELSDD:END -->'
5
5
  };
6
6
  export const AI_TOOLS = [
7
- { name: 'Amazon Q Developer', value: 'amazon-q', available: true, successLabel: 'Amazon Q Developer', skillsDir: '.amazonq' },
8
- { name: 'Antigravity', value: 'antigravity', available: true, successLabel: 'Antigravity', skillsDir: '.agent' },
9
- { name: 'Auggie (Augment CLI)', value: 'auggie', available: true, successLabel: 'Auggie', skillsDir: '.augment' },
10
- { name: 'Bob Shell', value: 'bob', available: true, successLabel: 'Bob Shell', skillsDir: '.bob' },
11
7
  { name: 'Claude Code', value: 'claude', available: true, successLabel: 'Claude Code', skillsDir: '.claude' },
12
- { name: 'Cline', value: 'cline', available: true, successLabel: 'Cline', skillsDir: '.cline' },
13
8
  { name: 'Codex', value: 'codex', available: true, successLabel: 'Codex', skillsDir: '.codex' },
14
- { name: 'ForgeCode', value: 'forgecode', available: true, successLabel: 'ForgeCode', skillsDir: '.forge' },
15
- { name: 'CodeBuddy Code (CLI)', value: 'codebuddy', available: true, successLabel: 'CodeBuddy Code', skillsDir: '.codebuddy' },
16
- { name: 'Continue', value: 'continue', available: true, successLabel: 'Continue (VS Code / JetBrains / Cli)', skillsDir: '.continue' },
17
- { name: 'CoStrict', value: 'costrict', available: true, successLabel: 'CoStrict', skillsDir: '.cospec' },
18
- { name: 'Crush', value: 'crush', available: true, successLabel: 'Crush', skillsDir: '.crush' },
19
9
  { name: 'Cursor', value: 'cursor', available: true, successLabel: 'Cursor', skillsDir: '.cursor' },
20
- { name: 'Factory Droid', value: 'factory', available: true, successLabel: 'Factory Droid', skillsDir: '.factory' },
21
10
  { name: 'Gemini CLI', value: 'gemini', available: true, successLabel: 'Gemini CLI', skillsDir: '.gemini' },
22
11
  { name: 'GitHub Copilot', value: 'github-copilot', available: true, successLabel: 'GitHub Copilot', skillsDir: '.github', detectionPaths: ['.github/copilot-instructions.md', '.github/instructions', '.github/workflows/copilot-setup-steps.yml', '.github/prompts', '.github/agents', '.github/skills', '.github/.mcp.json'] },
23
- { name: 'iFlow', value: 'iflow', available: true, successLabel: 'iFlow', skillsDir: '.iflow' },
24
- { name: 'Junie', value: 'junie', available: true, successLabel: 'Junie', skillsDir: '.junie' },
25
- { name: 'Kilo Code', value: 'kilocode', available: true, successLabel: 'Kilo Code', skillsDir: '.kilocode' },
26
- { name: 'Kimi CLI', value: 'kimi', available: true, successLabel: 'Kimi CLI', skillsDir: '.kimi' },
27
- { name: 'Kiro', value: 'kiro', available: true, successLabel: 'Kiro', skillsDir: '.kiro' },
28
- { name: 'OpenCode', value: 'opencode', available: true, successLabel: 'OpenCode', skillsDir: '.opencode' },
29
- { name: 'Pi', value: 'pi', available: true, successLabel: 'Pi', skillsDir: '.pi' },
30
- { name: 'Qoder', value: 'qoder', available: true, successLabel: 'Qoder', skillsDir: '.qoder' },
31
- { name: 'Lingma', value: 'lingma', available: true, successLabel: 'Lingma', skillsDir: '.lingma' },
32
- { name: 'Qwen Code', value: 'qwen', available: true, successLabel: 'Qwen Code', skillsDir: '.qwen' },
33
- { name: 'RooCode', value: 'roocode', available: true, successLabel: 'RooCode', skillsDir: '.roo' },
34
- { name: 'Trae', value: 'trae', available: true, successLabel: 'Trae', skillsDir: '.trae' },
35
- { name: 'Windsurf', value: 'windsurf', available: true, successLabel: 'Windsurf', skillsDir: '.windsurf' },
36
- { name: 'AGENTS.md (works with Amp, VS Code, …)', value: 'agents', available: false, successLabel: 'your AGENTS.md-compatible assistant' }
37
12
  ];
38
13
  //# sourceMappingURL=config.js.map
@@ -20,11 +20,14 @@ export declare class InitCommand {
20
20
  private validate;
21
21
  private canPromptInteractively;
22
22
  private resolveProfileOverride;
23
+ private handleOpenspecMigration;
24
+ private performOpenspecMigration;
23
25
  private handleLegacyCleanup;
24
26
  private performLegacyCleanup;
25
27
  private getSelectedTools;
26
28
  private resolveToolsArg;
27
29
  private validateTools;
30
+ private handleTrelloSetup;
28
31
  private createDirectoryStructure;
29
32
  private generateSkillsAndCommands;
30
33
  private createConfig;
package/dist/core/init.js CHANGED
@@ -17,6 +17,8 @@ import { isInteractive } from '../utils/interactive.js';
17
17
  import { serializeConfig } from './config-prompts.js';
18
18
  import { generateCommands, CommandAdapterRegistry, } from './command-generation/index.js';
19
19
  import { detectLegacyArtifacts, cleanupLegacyArtifacts, formatCleanupSummary, formatDetectionSummary, } from './legacy-cleanup.js';
20
+ import { detectOpenspecArtifacts, migrateFromOpenspec, formatOpenspecDetectionSummary, formatOpenspecMigrationSummary, pastelsddDirExists, } from './openspec-migration.js';
21
+ import { runTrelloInitPrompt } from './trello-init-prompt.js';
20
22
  import { getToolsWithSkillsDir, getToolStates, getSkillTemplates, getCommandContents, generateSkillContent, } from './shared/index.js';
21
23
  import { getGlobalConfig } from './global-config.js';
22
24
  import { getProfileWorkflows, ALL_WORKFLOWS } from './profiles.js';
@@ -44,6 +46,9 @@ const WORKFLOW_TO_SKILL_DIR = {
44
46
  'verify': 'pastelsdd-verify-change',
45
47
  'onboard': 'pastelsdd-onboard',
46
48
  'propose': 'pastelsdd-propose',
49
+ // Trello-specific workflows
50
+ 'trello-setup': 'pastelsdd-trello-setup',
51
+ 'draft': 'pastelsdd-trello-draft',
47
52
  };
48
53
  // -----------------------------------------------------------------------------
49
54
  // Init Command Class
@@ -65,6 +70,8 @@ export class InitCommand {
65
70
  const pastelsddPath = path.join(projectPath, pastelsddDir);
66
71
  // Validation happens silently in the background
67
72
  const extendMode = await this.validate(projectPath, pastelsddPath);
73
+ // Check for openspec migration first (before legacy cleanup)
74
+ await this.handleOpenspecMigration(projectPath);
68
75
  // Check for legacy artifacts and handle cleanup
69
76
  await this.handleLegacyCleanup(projectPath, extendMode);
70
77
  // Detect available tools in the project (task 7.1)
@@ -90,12 +97,14 @@ export class InitCommand {
90
97
  const validatedTools = this.validateTools(selectedToolIds, toolStates);
91
98
  // Create directory structure and config
92
99
  await this.createDirectoryStructure(pastelsddPath, extendMode);
100
+ // Trello integration setup (interactive mode only)
101
+ const trelloConfigured = await this.handleTrelloSetup(pastelsddPath);
93
102
  // Generate skills and commands for each tool
94
103
  const results = await this.generateSkillsAndCommands(projectPath, validatedTools);
95
104
  // Create config.yaml if needed
96
105
  const configStatus = await this.createConfig(pastelsddPath, extendMode);
97
106
  // Display success message
98
- this.displaySuccessMessage(projectPath, validatedTools, results, configStatus);
107
+ this.displaySuccessMessage(projectPath, validatedTools, results, configStatus, trelloConfigured);
99
108
  }
100
109
  // ═══════════════════════════════════════════════════════════
101
110
  // VALIDATION & SETUP
@@ -125,6 +134,51 @@ export class InitCommand {
125
134
  throw new Error(`Invalid profile "${this.profileOverride}". Available profiles: core, custom`);
126
135
  }
127
136
  // ═══════════════════════════════════════════════════════════
137
+ // OPENSPEC MIGRATION
138
+ // ═══════════════════════════════════════════════════════════
139
+ async handleOpenspecMigration(projectPath) {
140
+ const detection = await detectOpenspecArtifacts(projectPath);
141
+ if (!detection.hasOpenspecArtifacts) {
142
+ return;
143
+ }
144
+ // Determine whether pastelsdd/ already exists so we can show the right summary
145
+ const alreadyExists = await pastelsddDirExists(projectPath);
146
+ console.log();
147
+ console.log(formatOpenspecDetectionSummary(detection, alreadyExists));
148
+ console.log();
149
+ const canPrompt = this.canPromptInteractively();
150
+ if (this.force || !canPrompt) {
151
+ // Non-interactive or --force: migrate automatically
152
+ await this.performOpenspecMigration(projectPath, detection);
153
+ return;
154
+ }
155
+ const { confirm } = await import('@inquirer/prompts');
156
+ const dirName = detection.openspecDirName;
157
+ const migrateLabel = alreadyExists
158
+ ? `Merge ${dirName}/ into pastelsdd/ and complete the migration?`
159
+ : `Migrate this project from OpenSpec to Pastelsdd?`;
160
+ const shouldMigrate = await confirm({
161
+ message: migrateLabel,
162
+ default: true,
163
+ });
164
+ if (!shouldMigrate) {
165
+ console.log(chalk.dim('Migration cancelled. Re-run with --force to skip this prompt.'));
166
+ process.exit(0);
167
+ }
168
+ await this.performOpenspecMigration(projectPath, detection);
169
+ }
170
+ async performOpenspecMigration(projectPath, detection) {
171
+ const spinner = ora('Migrating from OpenSpec...').start();
172
+ const result = await migrateFromOpenspec(projectPath, detection);
173
+ spinner.succeed('OpenSpec migration complete');
174
+ const summary = formatOpenspecMigrationSummary(result);
175
+ if (summary) {
176
+ console.log();
177
+ console.log(summary);
178
+ }
179
+ console.log();
180
+ }
181
+ // ═══════════════════════════════════════════════════════════
128
182
  // LEGACY CLEANUP
129
183
  // ═══════════════════════════════════════════════════════════
130
184
  async handleLegacyCleanup(projectPath, extendMode) {
@@ -185,18 +239,21 @@ export class InitCommand {
185
239
  .map(([toolId]) => toolId));
186
240
  const shouldPreselectDetected = !extendMode && configuredToolIds.size === 0;
187
241
  const canPrompt = this.canPromptInteractively();
188
- // Non-interactive mode: use detected tools as fallback (task 7.8)
242
+ // Non-interactive mode: use detected tools, fallback to Claude if nothing detected
189
243
  if (!canPrompt) {
190
244
  if (detectedToolIds.size > 0) {
191
245
  return [...detectedToolIds];
192
246
  }
193
- throw new Error(`No tools detected and no --tools flag provided. Valid tools:\n ${validTools.join('\n ')}\n\nUse --tools all, --tools none, or --tools claude,cursor,...`);
247
+ // Default to Claude Code when no tools detected and no --tools flag
248
+ return ['claude'];
194
249
  }
195
250
  if (validTools.length === 0) {
196
251
  throw new Error(`No tools available for skill generation.`);
197
252
  }
198
253
  // Interactive mode: show searchable multi-select
199
254
  const { searchableMultiSelect } = await import('../prompts/searchable-multi-select.js');
255
+ // Claude is pre-selected by default when nothing is configured or detected yet
256
+ const shouldPreselectClaude = !extendMode && configuredToolIds.size === 0 && detectedToolIds.size === 0;
200
257
  // Build choices: pre-select configured tools; keep detected tools visible but unselected.
201
258
  const sortedChoices = validTools
202
259
  .map((toolId) => {
@@ -204,12 +261,13 @@ export class InitCommand {
204
261
  const status = toolStates.get(toolId);
205
262
  const configured = status?.configured ?? false;
206
263
  const detected = detectedToolIds.has(toolId);
264
+ const isClaudeDefault = toolId === 'claude' && shouldPreselectClaude;
207
265
  return {
208
266
  name: tool?.name || toolId,
209
267
  value: toolId,
210
268
  configured,
211
269
  detected: detected && !configured,
212
- preSelected: configured || (shouldPreselectDetected && detected && !configured),
270
+ preSelected: configured || (shouldPreselectDetected && detected && !configured) || isClaudeDefault,
213
271
  };
214
272
  })
215
273
  .sort((a, b) => {
@@ -315,6 +373,21 @@ export class InitCommand {
315
373
  return validatedTools;
316
374
  }
317
375
  // ═══════════════════════════════════════════════════════════
376
+ // TRELLO SETUP
377
+ // ═══════════════════════════════════════════════════════════
378
+ async handleTrelloSetup(pastelsddPath) {
379
+ if (!this.canPromptInteractively()) {
380
+ return false;
381
+ }
382
+ try {
383
+ return await runTrelloInitPrompt(pastelsddPath);
384
+ }
385
+ catch {
386
+ // Non-fatal — Trello setup is optional
387
+ return false;
388
+ }
389
+ }
390
+ // ═══════════════════════════════════════════════════════════
318
391
  // DIRECTORY STRUCTURE
319
392
  // ═══════════════════════════════════════════════════════════
320
393
  async createDirectoryStructure(pastelsddPath, extendMode) {
@@ -360,7 +433,12 @@ export class InitCommand {
360
433
  const globalConfig = getGlobalConfig();
361
434
  const profile = this.resolveProfileOverride() ?? globalConfig.profile ?? 'core';
362
435
  const delivery = globalConfig.delivery ?? 'both';
363
- const workflows = getProfileWorkflows(profile, globalConfig.workflows);
436
+ const profileWorkflows = getProfileWorkflows(profile, globalConfig.workflows);
437
+ // Trello workflows are always generated regardless of profile, so users can
438
+ // run /pastel:trello-setup to configure the integration at any time.
439
+ const TRELLO_WORKFLOWS = ['trello-setup', 'task', 'draft'];
440
+ const workflowsSet = new Set([...profileWorkflows, ...TRELLO_WORKFLOWS]);
441
+ const workflows = [...workflowsSet];
364
442
  // Get skill and command templates filtered by profile workflows
365
443
  const shouldGenerateSkills = delivery !== 'commands';
366
444
  const shouldGenerateCommands = delivery !== 'skills';
@@ -440,10 +518,6 @@ export class InitCommand {
440
518
  if (configYamlExists || configYmlExists) {
441
519
  return 'exists';
442
520
  }
443
- // In non-interactive mode without --force, skip config creation
444
- if (!this.canPromptInteractively() && !this.force) {
445
- return 'skipped';
446
- }
447
521
  try {
448
522
  const yamlContent = serializeConfig({ schema: DEFAULT_SCHEMA });
449
523
  await FileSystemUtils.writeFile(configPath, yamlContent);
@@ -456,7 +530,7 @@ export class InitCommand {
456
530
  // ═══════════════════════════════════════════════════════════
457
531
  // UI & OUTPUT
458
532
  // ═══════════════════════════════════════════════════════════
459
- displaySuccessMessage(projectPath, tools, results, configStatus) {
533
+ displaySuccessMessage(projectPath, tools, results, configStatus, trelloConfigured = false) {
460
534
  console.log();
461
535
  console.log(chalk.bold('Pastelsdd Setup Complete'));
462
536
  console.log();
@@ -467,13 +541,15 @@ export class InitCommand {
467
541
  if (results.refreshedTools.length > 0) {
468
542
  console.log(`Refreshed: ${results.refreshedTools.map((t) => t.name).join(', ')}`);
469
543
  }
470
- // Show counts (respecting profile filter)
544
+ // Show counts (respecting profile filter + trello workflows always included)
471
545
  const successfulTools = [...results.createdTools, ...results.refreshedTools];
472
546
  if (successfulTools.length > 0) {
473
547
  const globalConfig = getGlobalConfig();
474
548
  const profile = this.profileOverride ?? globalConfig.profile ?? 'core';
475
549
  const delivery = globalConfig.delivery ?? 'both';
476
- const workflows = getProfileWorkflows(profile, globalConfig.workflows);
550
+ const profileWorkflows = getProfileWorkflows(profile, globalConfig.workflows);
551
+ const TRELLO_WORKFLOWS = ['trello-setup', 'task', 'draft'];
552
+ const workflows = [...new Set([...profileWorkflows, ...TRELLO_WORKFLOWS])];
477
553
  const toolDirs = [...new Set(successfulTools.map((t) => t.skillsDir))].join(', ');
478
554
  const skillCount = delivery !== 'commands' ? getSkillTemplates(workflows).length : 0;
479
555
  const commandCount = delivery !== 'skills' ? getCommandContents(workflows).length : 0;
@@ -531,6 +607,13 @@ export class InitCommand {
531
607
  else {
532
608
  console.log("Done. Run 'pastelsdd config profile' to configure your workflows.");
533
609
  }
610
+ // Trello status
611
+ if (trelloConfigured) {
612
+ console.log();
613
+ console.log(chalk.bold('Trello Integration'));
614
+ console.log(` Preferences saved to ${chalk.cyan('pastelsdd/trello.yaml')}`);
615
+ console.log(` Run ${chalk.cyan('/pastel:trello-setup')} in Claude Code to connect your Trello lists.`);
616
+ }
534
617
  // Links
535
618
  console.log();
536
619
  console.log(`Learn more: ${chalk.cyan('https://github.com/thiagodiogo/Pastelsdd')}`);
@@ -6,7 +6,7 @@
6
6
  * Legacy config file names from the old ToolRegistry.
7
7
  * These were config files created at project root with Pastelsdd markers.
8
8
  */
9
- export declare const LEGACY_CONFIG_FILES: readonly ["CLAUDE.md", "CLINE.md", "CODEBUDDY.md", "COSTRICT.md", "QODER.md", "IFLOW.md", "AGENTS.md", "QWEN.md"];
9
+ export declare const LEGACY_CONFIG_FILES: readonly ["CLAUDE.md", "AGENTS.md"];
10
10
  /**
11
11
  * Legacy slash command patterns from the old SlashCommandRegistry.
12
12
  * These map toolId to the path pattern where legacy commands were created.
@@ -12,13 +12,7 @@ import { PASTELSDD_MARKERS } from './config.js';
12
12
  */
13
13
  export const LEGACY_CONFIG_FILES = [
14
14
  'CLAUDE.md',
15
- 'CLINE.md',
16
- 'CODEBUDDY.md',
17
- 'COSTRICT.md',
18
- 'QODER.md',
19
- 'IFLOW.md',
20
15
  'AGENTS.md', // root AGENTS.md (not pastelsdd/AGENTS.md)
21
- 'QWEN.md',
22
16
  ];
23
17
  /**
24
18
  * Legacy slash command patterns from the old SlashCommandRegistry.
@@ -28,29 +22,10 @@ export const LEGACY_CONFIG_FILES = [
28
22
  export const LEGACY_SLASH_COMMAND_PATHS = {
29
23
  // Directory-based: .tooldir/commands/pastelsdd/ or .tooldir/commands/pastelsdd/*.md
30
24
  'claude': { type: 'directory', path: '.claude/commands/pastelsdd' },
31
- 'codebuddy': { type: 'directory', path: '.codebuddy/commands/pastelsdd' },
32
- 'qoder': { type: 'directory', path: '.qoder/commands/pastelsdd' },
33
- 'lingma': { type: 'directory', path: '.lingma/commands/pastelsdd' },
34
- 'crush': { type: 'directory', path: '.crush/commands/pastelsdd' },
35
25
  'gemini': { type: 'directory', path: '.gemini/commands/pastelsdd' },
36
- 'costrict': { type: 'directory', path: '.cospec/pastelsdd/commands' },
37
26
  // File-based: individual pastelsdd-*.md files in a commands/workflows/prompts folder
38
27
  'cursor': { type: 'files', pattern: '.cursor/commands/pastelsdd-*.md' },
39
- 'windsurf': { type: 'files', pattern: '.windsurf/workflows/pastelsdd-*.md' },
40
- 'kilocode': { type: 'files', pattern: '.kilocode/workflows/pastelsdd-*.md' },
41
- 'kiro': { type: 'files', pattern: '.kiro/prompts/pastelsdd-*.prompt.md' },
42
28
  'github-copilot': { type: 'files', pattern: '.github/prompts/pastelsdd-*.prompt.md' },
43
- 'amazon-q': { type: 'files', pattern: '.amazonq/prompts/pastelsdd-*.md' },
44
- 'cline': { type: 'files', pattern: '.clinerules/workflows/pastelsdd-*.md' },
45
- 'roocode': { type: 'files', pattern: '.roo/commands/pastelsdd-*.md' },
46
- 'auggie': { type: 'files', pattern: '.augment/commands/pastelsdd-*.md' },
47
- 'factory': { type: 'files', pattern: '.factory/commands/pastelsdd-*.md' },
48
- 'opencode': { type: 'files', pattern: ['.opencode/command/pastel-*.md', '.opencode/command/pastelsdd-*.md'] },
49
- 'continue': { type: 'files', pattern: '.continue/prompts/pastelsdd-*.prompt' },
50
- 'antigravity': { type: 'files', pattern: '.agent/workflows/pastelsdd-*.md' },
51
- 'iflow': { type: 'files', pattern: '.iflow/commands/pastelsdd-*.md' },
52
- 'junie': { type: 'files', pattern: ['.junie/commands/pastel-*.md', '.junie/commands/pastelsdd-*.md'] },
53
- 'qwen': { type: 'files', pattern: '.qwen/commands/pastelsdd-*.toml' },
54
29
  'codex': { type: 'files', pattern: '.codex/prompts/pastelsdd-*.md' },
55
30
  };
56
31
  /**