cursor-kit-cli 1.2.0-beta → 1.2.0-beta.3

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 (92) hide show
  1. package/bin/cursor-reinstall-instance.sh +102 -0
  2. package/dist/cli.cjs +366 -69
  3. package/dist/cli.cjs.map +1 -1
  4. package/dist/cli.js +367 -70
  5. package/dist/cli.js.map +1 -1
  6. package/dist/index.cjs +39 -1
  7. package/dist/index.cjs.map +1 -1
  8. package/dist/index.d.cts +9 -1
  9. package/dist/index.d.ts +9 -1
  10. package/dist/index.js +33 -2
  11. package/dist/index.js.map +1 -1
  12. package/package.json +1 -1
  13. package/templates/commands/docs.md +5 -3
  14. package/templates/commands/explain.md +5 -3
  15. package/templates/commands/fix.md +5 -3
  16. package/templates/commands/implement.md +5 -3
  17. package/templates/commands/refactor.md +5 -3
  18. package/templates/commands/review.md +5 -3
  19. package/templates/commands/test.md +5 -3
  20. package/templates/manifest.json +11 -8
  21. package/templates/rules/git.mdc +0 -2
  22. package/templates/rules/toc.mdc +17 -9
  23. package/templates/skills/aesthetic/SKILL.md +121 -0
  24. package/templates/skills/aesthetic/assets/design-guideline-template.md +163 -0
  25. package/templates/skills/aesthetic/assets/design-story-template.md +135 -0
  26. package/templates/skills/aesthetic/references/design-principles.md +62 -0
  27. package/templates/skills/aesthetic/references/design-resources.md +75 -0
  28. package/templates/skills/aesthetic/references/micro-interactions.md +53 -0
  29. package/templates/skills/aesthetic/references/storytelling-design.md +50 -0
  30. package/templates/skills/backend-development/SKILL.mdc +95 -0
  31. package/templates/skills/backend-development/references/backend-api-design.md +495 -0
  32. package/templates/skills/backend-development/references/backend-architecture.md +454 -0
  33. package/templates/skills/backend-development/references/backend-authentication.md +338 -0
  34. package/templates/skills/backend-development/references/backend-code-quality.md +659 -0
  35. package/templates/skills/backend-development/references/backend-debugging.md +904 -0
  36. package/templates/skills/backend-development/references/backend-devops.md +494 -0
  37. package/templates/skills/backend-development/references/backend-mindset.md +387 -0
  38. package/templates/skills/backend-development/references/backend-performance.md +397 -0
  39. package/templates/skills/backend-development/references/backend-security.md +290 -0
  40. package/templates/skills/backend-development/references/backend-technologies.md +256 -0
  41. package/templates/skills/backend-development/references/backend-testing.md +429 -0
  42. package/templates/skills/frontend-design/SKILL.mdc +41 -0
  43. package/templates/skills/frontend-design/references/animejs.md +396 -0
  44. package/templates/skills/frontend-development/SKILL.mdc +399 -0
  45. package/templates/skills/frontend-development/resources/common-patterns.md +331 -0
  46. package/templates/skills/frontend-development/resources/complete-examples.md +872 -0
  47. package/templates/skills/frontend-development/resources/component-patterns.md +502 -0
  48. package/templates/skills/frontend-development/resources/data-fetching.md +767 -0
  49. package/templates/skills/frontend-development/resources/file-organization.md +502 -0
  50. package/templates/skills/frontend-development/resources/loading-and-error-states.md +501 -0
  51. package/templates/skills/frontend-development/resources/performance.md +406 -0
  52. package/templates/skills/frontend-development/resources/routing-guide.md +364 -0
  53. package/templates/skills/frontend-development/resources/styling-guide.md +428 -0
  54. package/templates/skills/frontend-development/resources/typescript-standards.md +418 -0
  55. package/templates/skills/problem-solving/SKILL.mdc +96 -0
  56. package/templates/skills/problem-solving/references/attribution.md +69 -0
  57. package/templates/skills/problem-solving/references/collision-zone-thinking.md +79 -0
  58. package/templates/skills/problem-solving/references/inversion-exercise.md +91 -0
  59. package/templates/skills/problem-solving/references/meta-pattern-recognition.md +87 -0
  60. package/templates/skills/problem-solving/references/scale-game.md +95 -0
  61. package/templates/skills/problem-solving/references/simplification-cascades.md +80 -0
  62. package/templates/skills/problem-solving/references/when-stuck.md +72 -0
  63. package/templates/skills/research/SKILL.mdc +168 -0
  64. package/templates/skills/sequential-thinking/.env.example +8 -0
  65. package/templates/skills/sequential-thinking/README.md +183 -0
  66. package/templates/skills/sequential-thinking/SKILL.mdc +94 -0
  67. package/templates/skills/sequential-thinking/package.json +31 -0
  68. package/templates/skills/sequential-thinking/references/advanced-strategies.md +79 -0
  69. package/templates/skills/sequential-thinking/references/advanced-techniques.md +76 -0
  70. package/templates/skills/sequential-thinking/references/core-patterns.md +95 -0
  71. package/templates/skills/sequential-thinking/references/examples-api.md +88 -0
  72. package/templates/skills/sequential-thinking/references/examples-architecture.md +94 -0
  73. package/templates/skills/sequential-thinking/references/examples-debug.md +90 -0
  74. package/templates/skills/sequential-thinking/scripts/format-thought.js +159 -0
  75. package/templates/skills/sequential-thinking/scripts/process-thought.js +236 -0
  76. package/templates/skills/sequential-thinking/tests/format-thought.test.js +133 -0
  77. package/templates/skills/sequential-thinking/tests/process-thought.test.js +215 -0
  78. package/templates/skills/ui-styling/LICENSE.txt +202 -0
  79. package/templates/skills/ui-styling/SKILL.mdc +321 -0
  80. package/templates/skills/ui-styling/references/canvas-design-system.md +320 -0
  81. package/templates/skills/ui-styling/references/shadcn-accessibility.md +471 -0
  82. package/templates/skills/ui-styling/references/shadcn-components.md +424 -0
  83. package/templates/skills/ui-styling/references/shadcn-theming.md +373 -0
  84. package/templates/skills/ui-styling/references/tailwind-customization.md +483 -0
  85. package/templates/skills/ui-styling/references/tailwind-responsive.md +382 -0
  86. package/templates/skills/ui-styling/references/tailwind-utilities.md +455 -0
  87. package/templates/rules/frontend-design.mdc +0 -48
  88. package/templates/rules/performance.mdc +0 -54
  89. package/templates/rules/react.mdc +0 -58
  90. package/templates/rules/security.mdc +0 -50
  91. package/templates/rules/testing.mdc +0 -54
  92. package/templates/rules/typescript.mdc +0 -36
@@ -0,0 +1,94 @@
1
+ # Example: Architecture Decision with Sequential Thinking
2
+
3
+ **Problem**: Choose state management for growing React app.
4
+
5
+ ## Sequential Thinking Approach
6
+
7
+ ```
8
+ Thought 1/4: Initial assessment
9
+
10
+ React app growing complex. useState scattered across components.
11
+ Need centralized state management.
12
+ Options: Redux, MobX, Zustand, Context API, Jotai.
13
+
14
+ Next: Define requirements
15
+
16
+ Thought 2/5: Requirements (adjusted up)
17
+
18
+ App needs:
19
+ - Real-time updates (WebSocket)
20
+ - Offline support
21
+ - Complex nested state
22
+ - Multiple devs (maintainability)
23
+ - TypeScript (type safety)
24
+
25
+ These eliminate simpler solutions.
26
+ Next: Evaluate remaining options
27
+
28
+ Thought 3/5 [REVISION of Thought 1]: Scope refinement
29
+
30
+ Original assumption: Need global state management.
31
+ Realization: Not all state needs centralization.
32
+
33
+ Better breakdown:
34
+ - Server state (API data): React Query
35
+ - UI state (modals, forms): Local useState
36
+ - Auth state: Context API
37
+ - App-wide settings: Simple global store
38
+
39
+ This reduces problem scope significantly.
40
+ Changes evaluation criteria.
41
+ Next: Re-evaluate with refined scope
42
+
43
+ Thought 4/6: Re-evaluation (adjusted)
44
+
45
+ Only need lightweight store for app-wide settings.
46
+ Zustand fits:
47
+ - Minimal boilerplate
48
+ - Excellent TypeScript support
49
+ - No provider wrapper
50
+ - ~1KB size
51
+
52
+ React Query handles server state (caching, refetch, offline).
53
+ Most state stays local.
54
+
55
+ Next: Verify this handles all requirements
56
+
57
+ Thought 5/6 [HYPOTHESIS]: Hybrid approach
58
+
59
+ Hypothesis: Zustand + React Query + local state solves needs.
60
+
61
+ - Zustand: Theme, user prefs, global UI flags
62
+ - React Query: All server data, caching, sync
63
+ - useState: Component-local UI
64
+
65
+ Benefits: Simple, performant, maintainable.
66
+ Uncertainty: Real-time updates?
67
+
68
+ Thought 6/6 [FINAL]: Verified solution
69
+
70
+ React Query supports WebSocket via custom hooks.
71
+ Zustand handles global UI simply.
72
+ Local state for component-specific needs.
73
+
74
+ Architecture decision:
75
+ - Zustand for global UI state
76
+ - React Query for all server interactions
77
+ - Local useState for component state
78
+
79
+ Confidence: High
80
+ Assumptions: Team comfortable with React Query patterns
81
+ Benefits: Simpler than Redux, more powerful than Context
82
+ Trade-offs: Learning curve for React Query (but worthwhile)
83
+ ```
84
+
85
+ ## Key Insights
86
+
87
+ 1. **Scope revision crucial**: Original "need global state" reframed to specific state categories
88
+ 2. **Separation of concerns**: Different state types need different solutions
89
+ 3. **Hypothesis verification**: Confirmed WebSocket support before finalizing
90
+ 4. **Simpler is better**: Avoided over-engineering with heavy Redux solution
91
+
92
+ ## Impact of Revision
93
+
94
+ Without Thought 3 revision, might have chosen Redux for all state—significant over-engineering. Revision led to more appropriate, simpler solution.
@@ -0,0 +1,90 @@
1
+ # Example: Performance Debugging with Sequential Thinking
2
+
3
+ **Problem**: API endpoint slow (2-3s instead of <200ms).
4
+
5
+ ## Sequential Thinking Approach
6
+
7
+ ```
8
+ Thought 1/5: Initial investigation
9
+
10
+ Endpoint: GET /api/users/{id}/dashboard
11
+ Expected: <200ms
12
+ Actual: 2-3s
13
+
14
+ Need to identify bottleneck.
15
+ Next: Analyze endpoint logic
16
+
17
+ Thought 2/5: Endpoint analysis
18
+
19
+ Dashboard fetches:
20
+ - User profile
21
+ - Recent activities (last 50)
22
+ - Notifications (unread)
23
+ - Analytics summary
24
+
25
+ Each is separate DB query. Could be N+1 problem.
26
+ Next: Profile actual execution
27
+
28
+ Thought 3/6: Profiling results (adjusted up—more complex)
29
+
30
+ Profiling:
31
+ - User profile: 20ms
32
+ - Activities: 1800ms (!!)
33
+ - Notifications: 100ms
34
+ - Analytics: 80ms
35
+
36
+ Activities query is bottleneck (90% of time).
37
+ Need to examine that query.
38
+ Next: Investigate activities query
39
+
40
+ Thought 4/6 [BRANCH A]: Hypothesis - N+1 query
41
+
42
+ Activities table has user_id FK to users.
43
+ Query might fetch activities, then user for each (N+1).
44
+ Verification: Check if uses joins or loops.
45
+
46
+ Thought 4/6 [BRANCH B]: Hypothesis - Missing index
47
+
48
+ Activities table might lack index on user_id + created_at.
49
+ Without index, full table scan for user's activities.
50
+ Verification: Check table indexes.
51
+
52
+ Thought 5/6 [VERIFICATION]: Testing hypotheses
53
+
54
+ Query examination: Uses proper joins (not N+1).
55
+ Index check: user_id indexed, NOT created_at.
56
+ Query filters by user_id AND sorts by created_at.
57
+
58
+ Branch B confirmed: Missing composite index causes slow sort.
59
+ Branch A eliminated: No N+1 issue.
60
+
61
+ Root cause identified.
62
+ Next: Implement solution
63
+
64
+ Thought 6/6 [FINAL]: Solution and verification
65
+
66
+ Create composite index:
67
+ ```sql
68
+ CREATE INDEX idx_activities_user_created
69
+ ON activities(user_id, created_at DESC);
70
+ ```
71
+
72
+ Tested: Response time now 120ms (target met).
73
+
74
+ Confidence: High (verified with profiling)
75
+ Result: 95% performance improvement
76
+ ```
77
+
78
+ ## Key Techniques Demonstrated
79
+
80
+ 1. **Branching for hypothesis testing**: Explored N+1 vs index hypotheses in parallel
81
+ 2. **Verification before solution**: Tested both hypotheses systematically
82
+ 3. **Data-driven decisions**: Used profiling data to guide investigation
83
+ 4. **Dynamic adjustment**: Expanded thought count when complexity emerged
84
+ 5. **Elimination method**: Ruled out N+1, confirmed index issue
85
+
86
+ ## Comparison
87
+
88
+ **Without sequential thinking**: Might jump to N+1 conclusion (common issue), waste time optimizing wrong thing.
89
+
90
+ **With sequential thinking**: Systematically tested hypotheses, identified actual root cause, implemented correct fix.
@@ -0,0 +1,159 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Sequential Thinking Thought Formatter
5
+ *
6
+ * Formats thoughts for display with visual indicators for type (regular/revision/branch).
7
+ * Provides consistent, readable output for thought sequences.
8
+ *
9
+ * Usage:
10
+ * node format-thought.js --thought "Analysis" --number 1 --total 5
11
+ * node format-thought.js --thought "Revision" --number 2 --total 5 --revision 1
12
+ * node format-thought.js --thought "Branch A" --number 3 --total 5 --branch 2 --branchId "a"
13
+ */
14
+
15
+ class ThoughtFormatter {
16
+ static format(thoughtData) {
17
+ const { thoughtNumber, totalThoughts, thought, isRevision, revisesThought, branchFromThought, branchId } = thoughtData;
18
+
19
+ let prefix = '';
20
+ let context = '';
21
+ let emoji = '';
22
+
23
+ if (isRevision && revisesThought) {
24
+ emoji = '🔄';
25
+ prefix = 'REVISION';
26
+ context = ` (revising thought ${revisesThought})`;
27
+ } else if (branchFromThought) {
28
+ emoji = '🌿';
29
+ prefix = 'BRANCH';
30
+ context = branchId ? ` (from thought ${branchFromThought}, ID: ${branchId})` : ` (from thought ${branchFromThought})`;
31
+ } else {
32
+ emoji = '💭';
33
+ prefix = 'Thought';
34
+ context = '';
35
+ }
36
+
37
+ const header = `${emoji} ${prefix} ${thoughtNumber}/${totalThoughts}${context}`;
38
+ const maxLength = Math.max(header.length, thought.length);
39
+ const border = '─'.repeat(maxLength + 4);
40
+
41
+ // Wrap long thoughts
42
+ const wrappedThought = this.wrapText(thought, maxLength);
43
+ const thoughtLines = wrappedThought.map(line => `│ ${line.padEnd(maxLength + 2)} │`).join('\n');
44
+
45
+ return `
46
+ ┌${border}┐
47
+ │ ${header.padEnd(maxLength + 2)} │
48
+ ├${border}┤
49
+ ${thoughtLines}
50
+ └${border}┘`;
51
+ }
52
+
53
+ static wrapText(text, maxWidth) {
54
+ if (text.length <= maxWidth) {
55
+ return [text];
56
+ }
57
+
58
+ const words = text.split(' ');
59
+ const lines = [];
60
+ let currentLine = '';
61
+
62
+ for (const word of words) {
63
+ if ((currentLine + ' ' + word).trim().length <= maxWidth) {
64
+ currentLine = currentLine ? currentLine + ' ' + word : word;
65
+ } else {
66
+ if (currentLine) lines.push(currentLine);
67
+ currentLine = word;
68
+ }
69
+ }
70
+
71
+ if (currentLine) lines.push(currentLine);
72
+ return lines;
73
+ }
74
+
75
+ static formatSimple(thoughtData) {
76
+ const { thoughtNumber, totalThoughts, thought, isRevision, revisesThought, branchFromThought, branchId } = thoughtData;
77
+
78
+ let marker = '';
79
+ if (isRevision && revisesThought) {
80
+ marker = ` [REVISION of Thought ${revisesThought}]`;
81
+ } else if (branchFromThought) {
82
+ marker = branchId ? ` [BRANCH ${branchId.toUpperCase()} from Thought ${branchFromThought}]` : ` [BRANCH from Thought ${branchFromThought}]`;
83
+ }
84
+
85
+ return `Thought ${thoughtNumber}/${totalThoughts}${marker}: ${thought}`;
86
+ }
87
+
88
+ static formatMarkdown(thoughtData) {
89
+ const { thoughtNumber, totalThoughts, thought, isRevision, revisesThought, branchFromThought, branchId } = thoughtData;
90
+
91
+ let marker = '';
92
+ if (isRevision && revisesThought) {
93
+ marker = ` **[REVISION of Thought ${revisesThought}]**`;
94
+ } else if (branchFromThought) {
95
+ marker = branchId ? ` **[BRANCH ${branchId.toUpperCase()} from Thought ${branchFromThought}]**` : ` **[BRANCH from Thought ${branchFromThought}]**`;
96
+ }
97
+
98
+ return `**Thought ${thoughtNumber}/${totalThoughts}**${marker}\n\n${thought}\n`;
99
+ }
100
+ }
101
+
102
+ // CLI Interface
103
+ if (require.main === module) {
104
+ const args = process.argv.slice(2);
105
+
106
+ const parseArgs = (args) => {
107
+ const parsed = {};
108
+ for (let i = 0; i < args.length; i++) {
109
+ const arg = args[i];
110
+ if (arg.startsWith('--')) {
111
+ const key = arg.slice(2);
112
+ const value = args[i + 1];
113
+
114
+ if (value && !value.startsWith('--')) {
115
+ // Parse boolean
116
+ if (value === 'true') parsed[key] = true;
117
+ else if (value === 'false') parsed[key] = false;
118
+ // Parse number
119
+ else if (!isNaN(value)) parsed[key] = parseFloat(value);
120
+ // String
121
+ else parsed[key] = value;
122
+ i++;
123
+ }
124
+ }
125
+ }
126
+ return parsed;
127
+ };
128
+
129
+ const input = parseArgs(args);
130
+
131
+ const thoughtData = {
132
+ thought: input.thought || 'No thought provided',
133
+ thoughtNumber: input.number || 1,
134
+ totalThoughts: input.total || 1,
135
+ isRevision: input.revision !== undefined,
136
+ revisesThought: input.revision,
137
+ branchFromThought: input.branch,
138
+ branchId: input.branchId
139
+ };
140
+
141
+ const format = input.format || 'box';
142
+
143
+ let output;
144
+ switch (format) {
145
+ case 'simple':
146
+ output = ThoughtFormatter.formatSimple(thoughtData);
147
+ break;
148
+ case 'markdown':
149
+ output = ThoughtFormatter.formatMarkdown(thoughtData);
150
+ break;
151
+ case 'box':
152
+ default:
153
+ output = ThoughtFormatter.format(thoughtData);
154
+ }
155
+
156
+ console.log(output);
157
+ }
158
+
159
+ module.exports = { ThoughtFormatter };
@@ -0,0 +1,236 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Sequential Thinking Thought Processor
5
+ *
6
+ * Validates and tracks sequential thoughts with revision and branching support.
7
+ * Provides deterministic validation and context management.
8
+ *
9
+ * Usage:
10
+ * node process-thought.js --thought "Analysis text" --number 1 --total 5 --next true
11
+ * node process-thought.js --thought "Revision" --number 2 --total 5 --next true --revision 1
12
+ * node process-thought.js --reset # Reset thought history
13
+ */
14
+
15
+ const fs = require('fs');
16
+ const path = require('path');
17
+
18
+ // Configuration
19
+ const HISTORY_FILE = path.join(__dirname, '.thought-history.json');
20
+ const DISABLE_LOGGING = process.env.DISABLE_THOUGHT_LOGGING?.toLowerCase() === 'true';
21
+
22
+ class ThoughtProcessor {
23
+ constructor() {
24
+ this.loadHistory();
25
+ }
26
+
27
+ loadHistory() {
28
+ try {
29
+ if (fs.existsSync(HISTORY_FILE)) {
30
+ const data = JSON.parse(fs.readFileSync(HISTORY_FILE, 'utf8'));
31
+ this.thoughtHistory = data.thoughtHistory || [];
32
+ this.branches = data.branches || {};
33
+ } else {
34
+ this.thoughtHistory = [];
35
+ this.branches = {};
36
+ }
37
+ } catch (error) {
38
+ this.thoughtHistory = [];
39
+ this.branches = {};
40
+ }
41
+ }
42
+
43
+ saveHistory() {
44
+ fs.writeFileSync(
45
+ HISTORY_FILE,
46
+ JSON.stringify({
47
+ thoughtHistory: this.thoughtHistory,
48
+ branches: this.branches
49
+ }, null, 2)
50
+ );
51
+ }
52
+
53
+ resetHistory() {
54
+ this.thoughtHistory = [];
55
+ this.branches = {};
56
+ if (fs.existsSync(HISTORY_FILE)) {
57
+ fs.unlinkSync(HISTORY_FILE);
58
+ }
59
+ }
60
+
61
+ validateThought(input) {
62
+ const errors = [];
63
+
64
+ if (!input.thought || typeof input.thought !== 'string' || input.thought.trim() === '') {
65
+ errors.push('Invalid thought: must be a non-empty string');
66
+ }
67
+
68
+ if (!input.thoughtNumber || typeof input.thoughtNumber !== 'number' || input.thoughtNumber < 1) {
69
+ errors.push('Invalid thoughtNumber: must be a positive number');
70
+ }
71
+
72
+ if (!input.totalThoughts || typeof input.totalThoughts !== 'number' || input.totalThoughts < 1) {
73
+ errors.push('Invalid totalThoughts: must be a positive number');
74
+ }
75
+
76
+ if (typeof input.nextThoughtNeeded !== 'boolean') {
77
+ errors.push('Invalid nextThoughtNeeded: must be a boolean');
78
+ }
79
+
80
+ // Optional field validations
81
+ if (input.isRevision !== undefined && typeof input.isRevision !== 'boolean') {
82
+ errors.push('Invalid isRevision: must be a boolean');
83
+ }
84
+
85
+ if (input.revisesThought !== undefined && (typeof input.revisesThought !== 'number' || input.revisesThought < 1)) {
86
+ errors.push('Invalid revisesThought: must be a positive number');
87
+ }
88
+
89
+ if (input.branchFromThought !== undefined && (typeof input.branchFromThought !== 'number' || input.branchFromThought < 1)) {
90
+ errors.push('Invalid branchFromThought: must be a positive number');
91
+ }
92
+
93
+ if (input.branchId !== undefined && typeof input.branchId !== 'string') {
94
+ errors.push('Invalid branchId: must be a string');
95
+ }
96
+
97
+ if (input.needsMoreThoughts !== undefined && typeof input.needsMoreThoughts !== 'boolean') {
98
+ errors.push('Invalid needsMoreThoughts: must be a boolean');
99
+ }
100
+
101
+ return errors;
102
+ }
103
+
104
+ processThought(input) {
105
+ const errors = this.validateThought(input);
106
+
107
+ if (errors.length > 0) {
108
+ return {
109
+ success: false,
110
+ errors,
111
+ status: 'failed'
112
+ };
113
+ }
114
+
115
+ // Auto-adjust totalThoughts if thoughtNumber exceeds it
116
+ if (input.thoughtNumber > input.totalThoughts) {
117
+ input.totalThoughts = input.thoughtNumber;
118
+ }
119
+
120
+ // Create thought data
121
+ const thoughtData = {
122
+ thought: input.thought,
123
+ thoughtNumber: input.thoughtNumber,
124
+ totalThoughts: input.totalThoughts,
125
+ nextThoughtNeeded: input.nextThoughtNeeded,
126
+ isRevision: input.isRevision,
127
+ revisesThought: input.revisesThought,
128
+ branchFromThought: input.branchFromThought,
129
+ branchId: input.branchId,
130
+ needsMoreThoughts: input.needsMoreThoughts,
131
+ timestamp: new Date().toISOString()
132
+ };
133
+
134
+ // Add to history
135
+ this.thoughtHistory.push(thoughtData);
136
+
137
+ // Track branches
138
+ if (thoughtData.branchFromThought && thoughtData.branchId) {
139
+ if (!this.branches[thoughtData.branchId]) {
140
+ this.branches[thoughtData.branchId] = [];
141
+ }
142
+ this.branches[thoughtData.branchId].push(thoughtData);
143
+ }
144
+
145
+ // Save history
146
+ this.saveHistory();
147
+
148
+ return {
149
+ success: true,
150
+ thoughtNumber: thoughtData.thoughtNumber,
151
+ totalThoughts: thoughtData.totalThoughts,
152
+ nextThoughtNeeded: thoughtData.nextThoughtNeeded,
153
+ branches: Object.keys(this.branches),
154
+ thoughtHistoryLength: this.thoughtHistory.length,
155
+ timestamp: thoughtData.timestamp
156
+ };
157
+ }
158
+
159
+ getHistory() {
160
+ return {
161
+ thoughts: this.thoughtHistory,
162
+ branches: this.branches,
163
+ totalThoughts: this.thoughtHistory.length
164
+ };
165
+ }
166
+ }
167
+
168
+ // CLI Interface
169
+ if (require.main === module) {
170
+ const args = process.argv.slice(2);
171
+ const processor = new ThoughtProcessor();
172
+
173
+ // Parse arguments
174
+ const parseArgs = (args) => {
175
+ const parsed = {};
176
+ for (let i = 0; i < args.length; i++) {
177
+ const arg = args[i];
178
+ if (arg.startsWith('--')) {
179
+ const key = arg.slice(2);
180
+ const value = args[i + 1];
181
+
182
+ if (key === 'reset') {
183
+ return { reset: true };
184
+ }
185
+
186
+ if (key === 'history') {
187
+ return { history: true };
188
+ }
189
+
190
+ if (value && !value.startsWith('--')) {
191
+ // Parse boolean
192
+ if (value === 'true') parsed[key] = true;
193
+ else if (value === 'false') parsed[key] = false;
194
+ // Parse number
195
+ else if (!isNaN(value)) parsed[key] = parseFloat(value);
196
+ // String
197
+ else parsed[key] = value;
198
+ i++;
199
+ }
200
+ }
201
+ }
202
+ return parsed;
203
+ };
204
+
205
+ const input = parseArgs(args);
206
+
207
+ if (input.reset) {
208
+ processor.resetHistory();
209
+ console.log(JSON.stringify({ success: true, message: 'History reset' }, null, 2));
210
+ process.exit(0);
211
+ }
212
+
213
+ if (input.history) {
214
+ console.log(JSON.stringify(processor.getHistory(), null, 2));
215
+ process.exit(0);
216
+ }
217
+
218
+ // Map CLI args to expected field names
219
+ const thoughtInput = {
220
+ thought: input.thought,
221
+ thoughtNumber: input.number,
222
+ totalThoughts: input.total,
223
+ nextThoughtNeeded: input.next,
224
+ isRevision: input.revision !== undefined ? true : input.isRevision,
225
+ revisesThought: input.revision,
226
+ branchFromThought: input.branch,
227
+ branchId: input.branchId,
228
+ needsMoreThoughts: input.needsMore
229
+ };
230
+
231
+ const result = processor.processThought(thoughtInput);
232
+ console.log(JSON.stringify(result, null, 2));
233
+ process.exit(result.success ? 0 : 1);
234
+ }
235
+
236
+ module.exports = { ThoughtProcessor };
@@ -0,0 +1,133 @@
1
+ /**
2
+ * Tests for Sequential Thinking Thought Formatter
3
+ *
4
+ * Run with: npm test
5
+ */
6
+
7
+ const { ThoughtFormatter } = require('../scripts/format-thought');
8
+
9
+ describe('ThoughtFormatter', () => {
10
+ describe('Simple Format', () => {
11
+ test('formats regular thought', () => {
12
+ const result = ThoughtFormatter.formatSimple({
13
+ thought: 'Test thought',
14
+ thoughtNumber: 1,
15
+ totalThoughts: 5
16
+ });
17
+
18
+ expect(result).toBe('Thought 1/5: Test thought');
19
+ });
20
+
21
+ test('formats revision thought', () => {
22
+ const result = ThoughtFormatter.formatSimple({
23
+ thought: 'Revised thought',
24
+ thoughtNumber: 2,
25
+ totalThoughts: 5,
26
+ isRevision: true,
27
+ revisesThought: 1
28
+ });
29
+
30
+ expect(result).toContain('[REVISION of Thought 1]');
31
+ expect(result).toContain('Revised thought');
32
+ });
33
+
34
+ test('formats branch thought', () => {
35
+ const result = ThoughtFormatter.formatSimple({
36
+ thought: 'Branch thought',
37
+ thoughtNumber: 3,
38
+ totalThoughts: 5,
39
+ branchFromThought: 2,
40
+ branchId: 'a'
41
+ });
42
+
43
+ expect(result).toContain('[BRANCH A from Thought 2]');
44
+ expect(result).toContain('Branch thought');
45
+ });
46
+ });
47
+
48
+ describe('Markdown Format', () => {
49
+ test('formats regular thought', () => {
50
+ const result = ThoughtFormatter.formatMarkdown({
51
+ thought: 'Test thought',
52
+ thoughtNumber: 1,
53
+ totalThoughts: 5
54
+ });
55
+
56
+ expect(result).toContain('**Thought 1/5**');
57
+ expect(result).toContain('Test thought');
58
+ });
59
+
60
+ test('formats revision thought', () => {
61
+ const result = ThoughtFormatter.formatMarkdown({
62
+ thought: 'Revised thought',
63
+ thoughtNumber: 2,
64
+ totalThoughts: 5,
65
+ isRevision: true,
66
+ revisesThought: 1
67
+ });
68
+
69
+ expect(result).toContain('**[REVISION of Thought 1]**');
70
+ });
71
+ });
72
+
73
+ describe('Box Format', () => {
74
+ test('formats with border', () => {
75
+ const result = ThoughtFormatter.format({
76
+ thought: 'Test thought',
77
+ thoughtNumber: 1,
78
+ totalThoughts: 5
79
+ });
80
+
81
+ expect(result).toContain('┌');
82
+ expect(result).toContain('└');
83
+ expect(result).toContain('💭');
84
+ expect(result).toContain('Test thought');
85
+ });
86
+
87
+ test('formats revision with emoji', () => {
88
+ const result = ThoughtFormatter.format({
89
+ thought: 'Revised',
90
+ thoughtNumber: 2,
91
+ totalThoughts: 5,
92
+ isRevision: true,
93
+ revisesThought: 1
94
+ });
95
+
96
+ expect(result).toContain('🔄');
97
+ expect(result).toContain('REVISION');
98
+ });
99
+
100
+ test('formats branch with emoji', () => {
101
+ const result = ThoughtFormatter.format({
102
+ thought: 'Branch',
103
+ thoughtNumber: 3,
104
+ totalThoughts: 5,
105
+ branchFromThought: 2,
106
+ branchId: 'a'
107
+ });
108
+
109
+ expect(result).toContain('🌿');
110
+ expect(result).toContain('BRANCH');
111
+ });
112
+ });
113
+
114
+ describe('Text Wrapping', () => {
115
+ test('wraps long text', () => {
116
+ const longText = 'This is a very long thought that should be wrapped across multiple lines when it exceeds the maximum width specified for the formatter';
117
+ const wrapped = ThoughtFormatter.wrapText(longText, 50);
118
+
119
+ expect(wrapped.length).toBeGreaterThan(1);
120
+ wrapped.forEach(line => {
121
+ expect(line.length).toBeLessThanOrEqual(50);
122
+ });
123
+ });
124
+
125
+ test('does not wrap short text', () => {
126
+ const shortText = 'Short thought';
127
+ const wrapped = ThoughtFormatter.wrapText(shortText, 50);
128
+
129
+ expect(wrapped.length).toBe(1);
130
+ expect(wrapped[0]).toBe(shortText);
131
+ });
132
+ });
133
+ });