@plaited/development-skills 0.5.0 → 0.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/{.claude → .plaited}/rules/accuracy.md +3 -10
- package/{.claude → .plaited}/rules/code-review.md +2 -9
- package/.plaited/rules/git-workflow.md +36 -0
- package/{.claude → .plaited}/rules/module-organization.md +1 -1
- package/{.claude → .plaited}/rules/testing.md +1 -1
- package/package.json +2 -2
- package/src/lsp-analyze.ts +1 -1
- package/src/lsp-find.ts +1 -1
- package/src/lsp-hover.ts +1 -1
- package/src/lsp-references.ts +1 -1
- package/src/lsp-symbols.ts +1 -1
- package/src/scaffold-rules.ts +148 -204
- package/src/tests/scaffold-rules.spec.ts +148 -118
- package/.claude/commands/lsp-analyze.md +0 -66
- package/.claude/commands/lsp-find.md +0 -74
- package/.claude/commands/lsp-hover.md +0 -57
- package/.claude/commands/lsp-refs.md +0 -64
- package/.claude/commands/scaffold-rules.md +0 -221
- package/.claude/commands/validate-skill.md +0 -29
- package/.claude/rules/git-workflow.md +0 -66
- package/.claude/skills/code-documentation/SKILL.md +0 -47
- package/.claude/skills/code-documentation/references/internal-templates.md +0 -113
- package/.claude/skills/code-documentation/references/maintenance.md +0 -164
- package/.claude/skills/code-documentation/references/public-api-templates.md +0 -100
- package/.claude/skills/code-documentation/references/type-documentation.md +0 -116
- package/.claude/skills/code-documentation/references/workflow.md +0 -60
- package/.claude/skills/scaffold-rules/SKILL.md +0 -104
- package/.claude/skills/typescript-lsp/SKILL.md +0 -249
- package/.claude/skills/validate-skill/SKILL.md +0 -105
- /package/{.claude → .plaited}/rules/bun-apis.md +0 -0
- /package/{.claude → .plaited}/rules/github.md +0 -0
|
@@ -9,12 +9,9 @@ type Template = {
|
|
|
9
9
|
}
|
|
10
10
|
|
|
11
11
|
type ScaffoldOutput = {
|
|
12
|
-
agent: string
|
|
13
12
|
rulesPath: string
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
supportsAgentsMd: boolean
|
|
17
|
-
agentsMdContent?: string
|
|
13
|
+
claudeMdSection: string
|
|
14
|
+
agentsMdSection: string
|
|
18
15
|
templates: Record<string, Template>
|
|
19
16
|
}
|
|
20
17
|
|
|
@@ -22,7 +19,7 @@ const binDir = join(import.meta.dir, '../../bin')
|
|
|
22
19
|
|
|
23
20
|
describe('scaffold-rules', () => {
|
|
24
21
|
test('outputs JSON with all templates', async () => {
|
|
25
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
22
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
26
23
|
|
|
27
24
|
expect(result).toHaveProperty('templates')
|
|
28
25
|
expect(result.templates).toBeObject()
|
|
@@ -35,10 +32,11 @@ describe('scaffold-rules', () => {
|
|
|
35
32
|
expect(templateKeys).toContain('git-workflow')
|
|
36
33
|
expect(templateKeys).toContain('github')
|
|
37
34
|
expect(templateKeys).toContain('testing')
|
|
35
|
+
expect(templateKeys).toContain('module-organization')
|
|
38
36
|
})
|
|
39
37
|
|
|
40
38
|
test('each template has required properties', async () => {
|
|
41
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
39
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
42
40
|
|
|
43
41
|
for (const [ruleId, template] of Object.entries(result.templates)) {
|
|
44
42
|
expect(template).toHaveProperty('filename')
|
|
@@ -52,7 +50,7 @@ describe('scaffold-rules', () => {
|
|
|
52
50
|
})
|
|
53
51
|
|
|
54
52
|
test('removes template headers from content', async () => {
|
|
55
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
53
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
56
54
|
|
|
57
55
|
// Check that template headers are removed
|
|
58
56
|
for (const template of Object.values(result.templates)) {
|
|
@@ -62,7 +60,7 @@ describe('scaffold-rules', () => {
|
|
|
62
60
|
})
|
|
63
61
|
|
|
64
62
|
test('processes development-skills conditionals', async () => {
|
|
65
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
63
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
66
64
|
|
|
67
65
|
const accuracy = result.templates.accuracy
|
|
68
66
|
expect(accuracy).toBeDefined()
|
|
@@ -78,8 +76,7 @@ describe('scaffold-rules', () => {
|
|
|
78
76
|
})
|
|
79
77
|
|
|
80
78
|
test('filters to specific rules when requested', async () => {
|
|
81
|
-
const result: ScaffoldOutput =
|
|
82
|
-
await $`bun ${binDir}/cli.ts scaffold-rules --rules testing --rules bun-apis --format=json`.json()
|
|
79
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --rules testing --rules bun-apis`.json()
|
|
83
80
|
|
|
84
81
|
const templateKeys = Object.keys(result.templates)
|
|
85
82
|
|
|
@@ -94,7 +91,7 @@ describe('scaffold-rules', () => {
|
|
|
94
91
|
})
|
|
95
92
|
|
|
96
93
|
test('extracts meaningful descriptions', async () => {
|
|
97
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
94
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
98
95
|
|
|
99
96
|
// Check a few descriptions
|
|
100
97
|
const accuracy = result.templates.accuracy
|
|
@@ -108,179 +105,212 @@ describe('scaffold-rules', () => {
|
|
|
108
105
|
expect(testing!.description.length).toBeGreaterThan(10)
|
|
109
106
|
})
|
|
110
107
|
|
|
111
|
-
test('exits with error for invalid agent', async () => {
|
|
112
|
-
const proc = Bun.spawn(['bun', `${binDir}/cli.ts`, 'scaffold-rules', '--agent=invalid'], {
|
|
113
|
-
stderr: 'pipe',
|
|
114
|
-
})
|
|
115
|
-
|
|
116
|
-
const exitCode = await proc.exited
|
|
117
|
-
expect(exitCode).not.toBe(0)
|
|
118
|
-
})
|
|
119
|
-
|
|
120
108
|
test('handles missing bundled rules directory gracefully', async () => {
|
|
121
109
|
// This test ensures the script fails gracefully if templates are missing
|
|
122
|
-
// In production, .
|
|
123
|
-
const result = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
110
|
+
// In production, .plaited/rules/ should always be bundled with the package
|
|
111
|
+
const result = await $`bun ${binDir}/cli.ts scaffold-rules`.nothrow().quiet()
|
|
124
112
|
|
|
125
|
-
// Should succeed because .
|
|
113
|
+
// Should succeed because .plaited/rules/ exists in development
|
|
126
114
|
expect(result.exitCode).toBe(0)
|
|
127
115
|
})
|
|
128
116
|
|
|
129
|
-
describe('
|
|
130
|
-
test('defaults to
|
|
131
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
132
|
-
|
|
133
|
-
expect(result.agent).toBe('claude')
|
|
134
|
-
expect(result.rulesPath).toBe('.claude/rules')
|
|
135
|
-
expect(result.format).toBe('multi-file')
|
|
136
|
-
expect(result.supportsAgentsMd).toBe(false)
|
|
137
|
-
})
|
|
138
|
-
|
|
139
|
-
test('processes has-sandbox for Claude (sandbox environment)', async () => {
|
|
140
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --agent=claude --format=json`.json()
|
|
141
|
-
|
|
142
|
-
const gitWorkflow = result.templates['git-workflow']
|
|
143
|
-
expect(gitWorkflow).toBeDefined()
|
|
144
|
-
|
|
145
|
-
// Claude has sandbox - should include sandbox-specific content
|
|
146
|
-
expect(gitWorkflow!.content).toContain('sandbox environment')
|
|
147
|
-
expect(gitWorkflow!.content).toContain('single-quoted strings')
|
|
148
|
-
|
|
149
|
-
// Should not have conditional syntax
|
|
150
|
-
expect(gitWorkflow!.content).not.toContain('{{#if has-sandbox}}')
|
|
151
|
-
expect(gitWorkflow!.content).not.toContain('{{/if}}')
|
|
152
|
-
})
|
|
153
|
-
|
|
154
|
-
test('processes supports-slash-commands for Claude', async () => {
|
|
155
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --agent=claude --format=json`.json()
|
|
156
|
-
|
|
157
|
-
const accuracy = result.templates.accuracy
|
|
158
|
-
expect(accuracy).toBeDefined()
|
|
117
|
+
describe('output structure', () => {
|
|
118
|
+
test('defaults to .plaited/rules path', async () => {
|
|
119
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
159
120
|
|
|
160
|
-
|
|
161
|
-
expect(accuracy!.content).toContain('/lsp-hover')
|
|
162
|
-
expect(accuracy!.content).toContain('/lsp-find')
|
|
121
|
+
expect(result.rulesPath).toBe('.plaited/rules')
|
|
163
122
|
})
|
|
164
123
|
|
|
165
|
-
test('
|
|
166
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
124
|
+
test('includes claudeMdSection with markers and @ syntax', async () => {
|
|
125
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
167
126
|
|
|
168
|
-
|
|
169
|
-
expect(
|
|
170
|
-
expect(
|
|
171
|
-
expect(
|
|
127
|
+
expect(result.claudeMdSection).toContain('<!-- PLAITED-RULES-START -->')
|
|
128
|
+
expect(result.claudeMdSection).toContain('<!-- PLAITED-RULES-END -->')
|
|
129
|
+
expect(result.claudeMdSection).toContain('@.plaited/rules/')
|
|
130
|
+
expect(result.claudeMdSection).toContain('## Project Rules')
|
|
172
131
|
})
|
|
173
|
-
})
|
|
174
132
|
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --agent=agents-md --format=json`.json()
|
|
133
|
+
test('includes agentsMdSection with markers and markdown links', async () => {
|
|
134
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
178
135
|
|
|
179
|
-
expect(result.
|
|
180
|
-
expect(result.
|
|
181
|
-
expect(result.
|
|
182
|
-
expect(result.
|
|
136
|
+
expect(result.agentsMdSection).toContain('<!-- PLAITED-RULES-START -->')
|
|
137
|
+
expect(result.agentsMdSection).toContain('<!-- PLAITED-RULES-END -->')
|
|
138
|
+
expect(result.agentsMdSection).toContain('[')
|
|
139
|
+
expect(result.agentsMdSection).toContain('](.plaited/rules/')
|
|
140
|
+
expect(result.agentsMdSection).toContain('## Rules')
|
|
183
141
|
})
|
|
184
142
|
|
|
185
|
-
test('
|
|
186
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
143
|
+
test('claudeMdSection lists all selected rules', async () => {
|
|
144
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
187
145
|
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
expect(result.agentsMdContent).toContain('## Rules')
|
|
146
|
+
for (const template of Object.values(result.templates)) {
|
|
147
|
+
expect(result.claudeMdSection).toContain(`@.plaited/rules/${template.filename}`)
|
|
148
|
+
}
|
|
192
149
|
})
|
|
193
150
|
|
|
194
|
-
test('
|
|
195
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
151
|
+
test('agentsMdSection lists all selected rules', async () => {
|
|
152
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
196
153
|
|
|
197
|
-
const agentsMd = result.agentsMdContent ?? ''
|
|
198
|
-
|
|
199
|
-
// Should link to each rule file
|
|
200
154
|
for (const [ruleId, template] of Object.entries(result.templates)) {
|
|
201
|
-
expect(
|
|
155
|
+
expect(result.agentsMdSection).toContain(`[${ruleId}](.plaited/rules/${template.filename})`)
|
|
202
156
|
}
|
|
203
157
|
})
|
|
158
|
+
})
|
|
204
159
|
|
|
205
|
-
|
|
206
|
-
|
|
160
|
+
describe('template content', () => {
|
|
161
|
+
test('git-workflow uses standard commit format', async () => {
|
|
162
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
207
163
|
|
|
208
164
|
const gitWorkflow = result.templates['git-workflow']
|
|
209
165
|
expect(gitWorkflow).toBeDefined()
|
|
210
|
-
expect(gitWorkflow!.content).not.toContain('sandbox environment')
|
|
211
166
|
expect(gitWorkflow!.content).toContain('multi-line commit')
|
|
167
|
+
expect(gitWorkflow!.content).toContain('git commit -m')
|
|
212
168
|
})
|
|
213
169
|
|
|
214
|
-
test('
|
|
215
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
170
|
+
test('accuracy uses CLI syntax for LSP tools', async () => {
|
|
171
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
216
172
|
|
|
217
173
|
const accuracy = result.templates.accuracy
|
|
218
174
|
expect(accuracy).toBeDefined()
|
|
219
175
|
|
|
220
|
-
// Should use CLI
|
|
176
|
+
// Should use CLI syntax
|
|
221
177
|
expect(accuracy!.content).toContain('bunx @plaited/development-skills lsp-')
|
|
222
|
-
expect(accuracy!.content).not.toContain('/lsp-hover')
|
|
223
178
|
})
|
|
224
179
|
|
|
225
|
-
test('
|
|
226
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules
|
|
180
|
+
test('cross-references use path syntax', async () => {
|
|
181
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
227
182
|
|
|
228
183
|
const accuracy = result.templates.accuracy
|
|
229
184
|
expect(accuracy).toBeDefined()
|
|
230
185
|
expect(accuracy!.content).toContain('.plaited/rules/testing.md')
|
|
186
|
+
expect(accuracy!.content).not.toContain('{{LINK:testing}}')
|
|
231
187
|
})
|
|
232
188
|
})
|
|
233
189
|
|
|
234
190
|
describe('path customization', () => {
|
|
235
|
-
test('
|
|
236
|
-
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --
|
|
191
|
+
test('--rules-dir overrides default rules path', async () => {
|
|
192
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --rules-dir=.cursor/rules`.json()
|
|
237
193
|
|
|
238
|
-
expect(result.
|
|
194
|
+
expect(result.rulesPath).toBe('.cursor/rules')
|
|
239
195
|
})
|
|
240
196
|
|
|
241
|
-
test('
|
|
242
|
-
const result: ScaffoldOutput =
|
|
243
|
-
await $`bun ${binDir}/cli.ts scaffold-rules --agent=agents-md --rules-dir=.cursor/rules --format=json`.json()
|
|
197
|
+
test('claudeMdSection uses custom path', async () => {
|
|
198
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --rules-dir=.cursor/rules`.json()
|
|
244
199
|
|
|
245
|
-
expect(result.
|
|
246
|
-
|
|
247
|
-
expect(result.agentsMdContent).toContain('.cursor/rules/')
|
|
248
|
-
expect(result.agentsMdContent).not.toContain('.plaited/rules/')
|
|
200
|
+
expect(result.claudeMdSection).toContain('@.cursor/rules/')
|
|
201
|
+
expect(result.claudeMdSection).not.toContain('.plaited/rules/')
|
|
249
202
|
})
|
|
250
203
|
|
|
251
|
-
test('
|
|
252
|
-
const result: ScaffoldOutput =
|
|
253
|
-
await $`bun ${binDir}/cli.ts scaffold-rules --agent=agents-md --agents-md-path=docs/AGENTS.md --format=json`.json()
|
|
204
|
+
test('agentsMdSection uses custom path', async () => {
|
|
205
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --rules-dir=.cursor/rules`.json()
|
|
254
206
|
|
|
255
|
-
expect(result.
|
|
207
|
+
expect(result.agentsMdSection).toContain('.cursor/rules/')
|
|
208
|
+
expect(result.agentsMdSection).not.toContain('.plaited/rules/')
|
|
256
209
|
})
|
|
257
210
|
|
|
258
211
|
test('cross-references use custom rules-dir', async () => {
|
|
259
|
-
const result: ScaffoldOutput =
|
|
260
|
-
await $`bun ${binDir}/cli.ts scaffold-rules --agent=agents-md --rules-dir=.factory/rules --format=json`.json()
|
|
212
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --rules-dir=.factory/rules`.json()
|
|
261
213
|
|
|
262
214
|
const accuracy = result.templates.accuracy
|
|
263
215
|
expect(accuracy).toBeDefined()
|
|
264
216
|
expect(accuracy!.content).toContain('.factory/rules/testing.md')
|
|
265
217
|
})
|
|
266
218
|
|
|
267
|
-
test('short
|
|
268
|
-
const result: ScaffoldOutput =
|
|
269
|
-
await $`bun ${binDir}/cli.ts scaffold-rules --agent=agents-md -d custom/rules -m custom/AGENTS.md --format=json`.json()
|
|
219
|
+
test('short flag -d works', async () => {
|
|
220
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules -d custom/rules`.json()
|
|
270
221
|
|
|
271
222
|
expect(result.rulesPath).toBe('custom/rules')
|
|
272
|
-
expect(result.agentsMdPath).toBe('custom/AGENTS.md')
|
|
273
223
|
})
|
|
224
|
+
})
|
|
274
225
|
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
226
|
+
describe('--list flag', () => {
|
|
227
|
+
test('outputs array of available rules', async () => {
|
|
228
|
+
const result = await $`bun ${binDir}/cli.ts scaffold-rules --list`.json()
|
|
229
|
+
|
|
230
|
+
expect(result).toBeArray()
|
|
231
|
+
expect(result.length).toBeGreaterThan(0)
|
|
232
|
+
|
|
233
|
+
// Each entry should have id and filename
|
|
234
|
+
for (const rule of result) {
|
|
235
|
+
expect(rule).toHaveProperty('id')
|
|
236
|
+
expect(rule).toHaveProperty('filename')
|
|
237
|
+
expect(rule.filename).toBe(`${rule.id}.md`)
|
|
238
|
+
}
|
|
239
|
+
})
|
|
240
|
+
|
|
241
|
+
test('includes expected rules', async () => {
|
|
242
|
+
const result = await $`bun ${binDir}/cli.ts scaffold-rules --list`.json()
|
|
243
|
+
const ids = result.map((r: { id: string }) => r.id)
|
|
244
|
+
|
|
245
|
+
expect(ids).toContain('accuracy')
|
|
246
|
+
expect(ids).toContain('testing')
|
|
247
|
+
expect(ids).toContain('bun-apis')
|
|
248
|
+
})
|
|
249
|
+
|
|
250
|
+
test('short flag -l works', async () => {
|
|
251
|
+
const result = await $`bun ${binDir}/cli.ts scaffold-rules -l`.json()
|
|
252
|
+
|
|
253
|
+
expect(result).toBeArray()
|
|
254
|
+
expect(result.length).toBeGreaterThan(0)
|
|
255
|
+
})
|
|
256
|
+
})
|
|
257
|
+
|
|
258
|
+
describe('--rules validation', () => {
|
|
259
|
+
test('warns about unknown rules', async () => {
|
|
260
|
+
const result = await $`bun ${binDir}/cli.ts scaffold-rules --rules nonexistent --rules testing`.nothrow()
|
|
261
|
+
|
|
262
|
+
// Should still succeed but with warning
|
|
263
|
+
expect(result.exitCode).toBe(0)
|
|
264
|
+
expect(result.stderr.toString()).toContain('Warning: Unknown rules: nonexistent')
|
|
265
|
+
})
|
|
266
|
+
|
|
267
|
+
test('shows available rules in warning', async () => {
|
|
268
|
+
const result = await $`bun ${binDir}/cli.ts scaffold-rules --rules fake-rule`.nothrow()
|
|
269
|
+
|
|
270
|
+
expect(result.stderr.toString()).toContain('Available rules:')
|
|
271
|
+
expect(result.stderr.toString()).toContain('testing')
|
|
272
|
+
})
|
|
273
|
+
})
|
|
274
|
+
|
|
275
|
+
describe('edge cases', () => {
|
|
276
|
+
test('handles all rules filtered out gracefully', async () => {
|
|
277
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --rules nonexistent`.nothrow().json()
|
|
278
|
+
|
|
279
|
+
// Should return valid output with empty templates
|
|
280
|
+
expect(result.templates).toEqual({})
|
|
281
|
+
expect(result.claudeMdSection).toContain('<!-- PLAITED-RULES-START -->')
|
|
282
|
+
expect(result.claudeMdSection).toContain('<!-- PLAITED-RULES-END -->')
|
|
283
|
+
})
|
|
284
|
+
|
|
285
|
+
test('description extraction falls back for heading-only content', async () => {
|
|
286
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
287
|
+
|
|
288
|
+
// All templates should have non-empty descriptions
|
|
289
|
+
for (const template of Object.values(result.templates)) {
|
|
290
|
+
expect(template.description).toBeTruthy()
|
|
291
|
+
expect(template.description.length).toBeGreaterThan(0)
|
|
292
|
+
}
|
|
293
|
+
})
|
|
294
|
+
|
|
295
|
+
test('processes nested conditionals correctly', async () => {
|
|
296
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules --rules accuracy`.json()
|
|
278
297
|
|
|
279
|
-
expect(result.rulesPath).toBe('.my-rules')
|
|
280
|
-
// Cross-references should use custom path
|
|
281
298
|
const accuracy = result.templates.accuracy
|
|
282
299
|
expect(accuracy).toBeDefined()
|
|
283
|
-
|
|
300
|
+
|
|
301
|
+
// Should not contain any unprocessed conditional syntax
|
|
302
|
+
expect(accuracy!.content).not.toContain('{{#if')
|
|
303
|
+
expect(accuracy!.content).not.toContain('{{^if')
|
|
304
|
+
expect(accuracy!.content).not.toContain('{{/if}}')
|
|
305
|
+
})
|
|
306
|
+
|
|
307
|
+
test('template content has no excessive blank lines', async () => {
|
|
308
|
+
const result: ScaffoldOutput = await $`bun ${binDir}/cli.ts scaffold-rules`.json()
|
|
309
|
+
|
|
310
|
+
for (const template of Object.values(result.templates)) {
|
|
311
|
+
// Should not have 3+ consecutive newlines
|
|
312
|
+
expect(template.content).not.toMatch(/\n{3,}/)
|
|
313
|
+
}
|
|
284
314
|
})
|
|
285
315
|
})
|
|
286
316
|
})
|
|
@@ -1,66 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Analyze a TypeScript file structure, exports, and symbols
|
|
3
|
-
allowed-tools: Bash
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# LSP Analyze
|
|
7
|
-
|
|
8
|
-
Batch analysis of a TypeScript/JavaScript file. Get an overview of exports, symbols, and optionally type info at specific positions.
|
|
9
|
-
|
|
10
|
-
**Arguments:** $ARGUMENTS
|
|
11
|
-
|
|
12
|
-
## Usage
|
|
13
|
-
|
|
14
|
-
```
|
|
15
|
-
/lsp-analyze <file> [options]
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
Options:
|
|
19
|
-
- `--symbols` or `-s`: List all symbols
|
|
20
|
-
- `--exports` or `-e`: List only exported symbols (default if no options)
|
|
21
|
-
- `--hover <line:char>`: Get type info at position (repeatable)
|
|
22
|
-
- `--refs <line:char>`: Find references at position (repeatable)
|
|
23
|
-
- `--all`: Run symbols + exports analysis
|
|
24
|
-
|
|
25
|
-
## Instructions
|
|
26
|
-
|
|
27
|
-
### Step 1: Parse Arguments
|
|
28
|
-
|
|
29
|
-
Extract file path and options from `$ARGUMENTS`.
|
|
30
|
-
|
|
31
|
-
If file is missing, show usage:
|
|
32
|
-
```
|
|
33
|
-
Usage: /lsp-analyze <file> [options]
|
|
34
|
-
|
|
35
|
-
Examples:
|
|
36
|
-
/lsp-analyze src/utils/parser.ts --exports
|
|
37
|
-
/lsp-analyze src/lib/config.ts --all
|
|
38
|
-
/lsp-analyze src/index.ts --hover 50:10 --refs 60:5
|
|
39
|
-
```
|
|
40
|
-
|
|
41
|
-
Default to `--exports` if no options provided.
|
|
42
|
-
|
|
43
|
-
### Step 2: Run LSP Analyze
|
|
44
|
-
|
|
45
|
-
Execute the development-skills CLI command:
|
|
46
|
-
```bash
|
|
47
|
-
bunx @plaited/development-skills lsp-analyze <file> [options]
|
|
48
|
-
```
|
|
49
|
-
|
|
50
|
-
### Step 3: Format Output
|
|
51
|
-
|
|
52
|
-
Parse the JSON output and present in a structured format:
|
|
53
|
-
|
|
54
|
-
**File:** `<file>`
|
|
55
|
-
|
|
56
|
-
**Exports:**
|
|
57
|
-
| Name | Kind | Line |
|
|
58
|
-
|------|------|------|
|
|
59
|
-
| ... | ... | ... |
|
|
60
|
-
|
|
61
|
-
**Symbols:** (if requested)
|
|
62
|
-
| Name | Kind | Line |
|
|
63
|
-
|------|------|------|
|
|
64
|
-
| ... | ... | ... |
|
|
65
|
-
|
|
66
|
-
For hover/refs results, format as described in the individual commands.
|
|
@@ -1,74 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Search for TypeScript SYMBOLS (functions, types, classes) - NOT text
|
|
3
|
-
allowed-tools: Bash
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# LSP Find
|
|
7
|
-
|
|
8
|
-
Search for TypeScript **symbols** (functions, types, classes, variables) across the codebase.
|
|
9
|
-
|
|
10
|
-
**Arguments:** $ARGUMENTS
|
|
11
|
-
|
|
12
|
-
## When to Use Each Tool
|
|
13
|
-
|
|
14
|
-
| Tool | Purpose |
|
|
15
|
-
|------|---------|
|
|
16
|
-
| **Glob** | Find files by pattern |
|
|
17
|
-
| **Grep** | Search text content |
|
|
18
|
-
| **lsp-find** | Search TypeScript symbols |
|
|
19
|
-
| **lsp-hover** | Get type info + TSDoc documentation |
|
|
20
|
-
|
|
21
|
-
## Usage
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
/lsp-find <query> <context-file>
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
- `query`: TypeScript symbol name (function, type, class, variable)
|
|
28
|
-
- `context-file`: Any `.ts` file in the project for LSP context
|
|
29
|
-
|
|
30
|
-
## When NOT to Use
|
|
31
|
-
|
|
32
|
-
```
|
|
33
|
-
# ❌ WRONG: Searching for text (use Grep instead)
|
|
34
|
-
/lsp-find scaffold
|
|
35
|
-
/lsp-find TODO
|
|
36
|
-
|
|
37
|
-
# ❌ WRONG: Missing context file
|
|
38
|
-
/lsp-find createClient
|
|
39
|
-
|
|
40
|
-
# ✅ CORRECT: Symbol search with context file
|
|
41
|
-
/lsp-find createClient src/lsp-client.ts
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
## Instructions
|
|
45
|
-
|
|
46
|
-
### Step 1: Parse Arguments
|
|
47
|
-
|
|
48
|
-
Extract query and context file from `$ARGUMENTS`.
|
|
49
|
-
|
|
50
|
-
If either is missing, show usage:
|
|
51
|
-
```
|
|
52
|
-
Usage: /lsp-find <query> <context-file>
|
|
53
|
-
|
|
54
|
-
Examples:
|
|
55
|
-
/lsp-find LspClient src/lsp-client.ts
|
|
56
|
-
/lsp-find createClient src/app.ts
|
|
57
|
-
```
|
|
58
|
-
|
|
59
|
-
### Step 2: Run LSP Find
|
|
60
|
-
|
|
61
|
-
Execute the development-skills CLI command:
|
|
62
|
-
```bash
|
|
63
|
-
bunx @plaited/development-skills lsp-find <query> <context-file>
|
|
64
|
-
```
|
|
65
|
-
|
|
66
|
-
### Step 3: Format Output
|
|
67
|
-
|
|
68
|
-
Parse the JSON output and present results as a table:
|
|
69
|
-
|
|
70
|
-
| Symbol | Kind | File | Line |
|
|
71
|
-
|--------|------|------|------|
|
|
72
|
-
| ... | ... | ... | ... |
|
|
73
|
-
|
|
74
|
-
Group results by file if there are many matches. Highlight the most relevant matches (exact name matches first).
|
|
@@ -1,57 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Get TypeScript type signature + TSDoc documentation at a position
|
|
3
|
-
allowed-tools: Bash
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# LSP Hover
|
|
7
|
-
|
|
8
|
-
Get type signature and TSDoc documentation at a specific position in a TypeScript/JavaScript file.
|
|
9
|
-
|
|
10
|
-
**Arguments:** $ARGUMENTS
|
|
11
|
-
|
|
12
|
-
## When to Use Each Tool
|
|
13
|
-
|
|
14
|
-
| Tool | Purpose |
|
|
15
|
-
|------|---------|
|
|
16
|
-
| **Glob** | Find files by pattern |
|
|
17
|
-
| **Grep** | Search text content |
|
|
18
|
-
| **lsp-find** | Search TypeScript symbols |
|
|
19
|
-
| **lsp-hover** | Get type info + TSDoc documentation |
|
|
20
|
-
|
|
21
|
-
## Usage
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
/lsp-hover <file> <line> <char>
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
- `file`: Path to TypeScript/JavaScript file (absolute, relative, or package export path)
|
|
28
|
-
- `line`: Line number (0-indexed)
|
|
29
|
-
- `char`: Character position (0-indexed)
|
|
30
|
-
|
|
31
|
-
## Instructions
|
|
32
|
-
|
|
33
|
-
### Step 1: Parse Arguments
|
|
34
|
-
|
|
35
|
-
Extract file path, line, and character from `$ARGUMENTS`.
|
|
36
|
-
|
|
37
|
-
If arguments are missing, show usage:
|
|
38
|
-
```
|
|
39
|
-
Usage: /lsp-hover <file> <line> <char>
|
|
40
|
-
|
|
41
|
-
Example: /lsp-hover src/utils/parser.ts 42 15
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Step 2: Run LSP Hover
|
|
45
|
-
|
|
46
|
-
Execute the development-skills CLI command:
|
|
47
|
-
```bash
|
|
48
|
-
bunx @plaited/development-skills lsp-hover <file> <line> <char>
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Step 3: Format Output
|
|
52
|
-
|
|
53
|
-
Parse the JSON output and present the type information in a readable format:
|
|
54
|
-
|
|
55
|
-
- Show the type signature in a code block
|
|
56
|
-
- If documentation is present, show it below
|
|
57
|
-
- If no hover info found, explain that no type information is available at that position
|
|
@@ -1,64 +0,0 @@
|
|
|
1
|
-
---
|
|
2
|
-
description: Find all references to a TypeScript symbol across the codebase
|
|
3
|
-
allowed-tools: Bash
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# LSP References
|
|
7
|
-
|
|
8
|
-
Find all references to a symbol at a specific position. Use this before modifying or deleting exports to understand impact.
|
|
9
|
-
|
|
10
|
-
**Arguments:** $ARGUMENTS
|
|
11
|
-
|
|
12
|
-
## When to Use Each Tool
|
|
13
|
-
|
|
14
|
-
| Tool | Purpose |
|
|
15
|
-
|------|---------|
|
|
16
|
-
| **Glob** | Find files by pattern |
|
|
17
|
-
| **Grep** | Search text content |
|
|
18
|
-
| **lsp-find** | Search TypeScript symbols |
|
|
19
|
-
| **lsp-refs** | Find all references to a symbol |
|
|
20
|
-
|
|
21
|
-
## Usage
|
|
22
|
-
|
|
23
|
-
```
|
|
24
|
-
/lsp-refs <file> <line> <char>
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
- `file`: Path to TypeScript/JavaScript file
|
|
28
|
-
- `line`: Line number (0-indexed)
|
|
29
|
-
- `char`: Character position (0-indexed)
|
|
30
|
-
|
|
31
|
-
## Instructions
|
|
32
|
-
|
|
33
|
-
### Step 1: Parse Arguments
|
|
34
|
-
|
|
35
|
-
Extract file path, line, and character from `$ARGUMENTS`.
|
|
36
|
-
|
|
37
|
-
If arguments are missing, show usage:
|
|
38
|
-
```
|
|
39
|
-
Usage: /lsp-refs <file> <line> <char>
|
|
40
|
-
|
|
41
|
-
Example: /lsp-refs src/utils/parser.ts 42 10
|
|
42
|
-
```
|
|
43
|
-
|
|
44
|
-
### Step 2: Run LSP References
|
|
45
|
-
|
|
46
|
-
Execute the development-skills CLI command:
|
|
47
|
-
```bash
|
|
48
|
-
bunx @plaited/development-skills lsp-refs <file> <line> <char>
|
|
49
|
-
```
|
|
50
|
-
|
|
51
|
-
### Step 3: Format Output
|
|
52
|
-
|
|
53
|
-
Parse the JSON output and present references grouped by file:
|
|
54
|
-
|
|
55
|
-
**Found X references:**
|
|
56
|
-
|
|
57
|
-
`src/file1.ts`
|
|
58
|
-
- Line 42: `const x = targetSymbol()`
|
|
59
|
-
- Line 58: `import { targetSymbol } from...`
|
|
60
|
-
|
|
61
|
-
`src/file2.ts`
|
|
62
|
-
- Line 15: `targetSymbol.method()`
|
|
63
|
-
|
|
64
|
-
If no references found, indicate that the symbol may be unused or only defined.
|