Skip to content

Commit 2ede6a8

Browse files
committed
Generating the new skill using the same workflow
1 parent 7dd77b8 commit 2ede6a8

6 files changed

Lines changed: 271 additions & 56 deletions

File tree

skills-generator/src/main/java/info/jab/pml/SkillsGenerator.java

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,13 +29,13 @@ public SkillsGenerator() {
2929

3030
/**
3131
* Generates SKILL.md and reference content for all skills in the inventory.
32-
* Validates that each skill has a summary in {@code skills/} and a matching system-prompt.
32+
* Skills with {@code requiresSystemPrompt=false} get SKILL.md only (no reference content).
3333
*
3434
* @return stream of generated skill outputs
3535
*/
3636
public Stream<SkillOutput> generateAllSkills() {
37-
return SkillsInventory.skillIds()
38-
.map(this::generateSkill);
37+
return SkillsInventory.skillDescriptors()
38+
.map(d -> generateSkill(d.skillId(), d.requiresSystemPrompt()));
3939
}
4040

4141
/**
@@ -46,8 +46,20 @@ public Stream<SkillOutput> generateAllSkills() {
4646
* @throws RuntimeException if resources cannot be loaded or generation fails
4747
*/
4848
public SkillOutput generateSkill(String skillId) {
49-
SkillMetadata metadata = parseMetadata(skillId);
50-
String referenceContent = generateReferenceContent(skillId, metadata);
49+
return generateSkill(skillId, true);
50+
}
51+
52+
/**
53+
* Generates SKILL.md and reference content for a given skill.
54+
*
55+
* @param skillId the skill identifier (e.g. 110-java-maven-best-practices)
56+
* @param requiresSystemPrompt when false, skips system-prompt XML and reference generation
57+
* @return the generated skill output
58+
*/
59+
public SkillOutput generateSkill(String skillId, boolean requiresSystemPrompt) {
60+
String referenceContent = requiresSystemPrompt
61+
? generateReferenceContent(skillId, parseMetadata(skillId))
62+
: "";
5163
String skillMdContent = loadSkillSummary(skillId);
5264
return new SkillOutput(skillId, skillMdContent, referenceContent);
5365
}

skills-generator/src/main/java/info/jab/pml/SkillsInventory.java

Lines changed: 54 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -20,10 +20,10 @@
2020
/**
2121
* Inventory of skills to generate, loaded from {@code skill-inventory.json}.
2222
* <p>
23-
* Each entry has an {@code id}. The corresponding skillId is derived by matching
24-
* system-prompts with prefix {@code {id}-} (e.g. id 110 matches 110-java-maven-best-practices.xml).
25-
* Each skill must have a summary in {@code skills/{id}-skill.md} and a matching
26-
* system-prompt in {@code system-prompts/}.
23+
* Each entry has an {@code id} (numeric or string like "010"). When {@code requiresSystemPrompt}
24+
* is true (default), the skillId is derived by matching system-prompts with prefix {@code {id}-}.
25+
* When false, the entry must specify {@code skillId} and no system-prompt is required.
26+
* Each skill must have a summary in {@code skills/{id}-skill.md}.
2727
*/
2828
public final class SkillsInventory {
2929

@@ -33,9 +33,9 @@ public final class SkillsInventory {
3333
private SkillsInventory() {}
3434

3535
/**
36-
* Returns the skill IDs from the inventory. For each id, resolves the skillId
37-
* by matching system-prompts with prefix {@code {id}-}. Validates that each
38-
* skill has a summary in {@code skills/} and a matching system-prompt.
36+
* Returns the skill IDs from the inventory. For each entry, validates the skill summary
37+
* exists. When {@code requiresSystemPrompt} is true, resolves skillId from system-prompts;
38+
* when false, uses the provided {@code skillId}.
3939
*
4040
* @return stream of skill IDs (e.g. 110-java-maven-best-practices)
4141
* @throws RuntimeException if the inventory cannot be loaded or validation fails
@@ -45,14 +45,39 @@ public static Stream<String> skillIds() {
4545
List<String> skillIds = new ArrayList<>();
4646

4747
for (InventoryEntry entry : entries) {
48-
validateSkillSummaryExists(entry.id());
49-
String skillId = resolveSkillIdFromPrefix(entry.id());
48+
String numericId = entry.numericId();
49+
validateSkillSummaryExists(numericId);
50+
String skillId = entry.requiresSystemPrompt()
51+
? resolveSkillIdFromPrefix(Integer.parseInt(numericId))
52+
: entry.skillId();
5053
skillIds.add(skillId);
5154
}
5255

5356
return skillIds.stream();
5457
}
5558

59+
/**
60+
* Returns skill descriptors (skillId + requiresSystemPrompt) for generator use.
61+
*/
62+
public static Stream<SkillDescriptor> skillDescriptors() {
63+
List<InventoryEntry> entries = loadInventory();
64+
List<SkillDescriptor> descriptors = new ArrayList<>();
65+
for (InventoryEntry entry : entries) {
66+
String numericId = entry.numericId();
67+
validateSkillSummaryExists(numericId);
68+
String skillId = entry.requiresSystemPrompt()
69+
? resolveSkillIdFromPrefix(Integer.parseInt(numericId))
70+
: entry.skillId();
71+
descriptors.add(new SkillDescriptor(skillId, entry.requiresSystemPrompt()));
72+
}
73+
return descriptors.stream();
74+
}
75+
76+
/**
77+
* Skill ID and whether it requires a system prompt for reference generation.
78+
*/
79+
public record SkillDescriptor(String skillId, boolean requiresSystemPrompt) {}
80+
5681
/**
5782
* Resolves skillId by finding the system-prompt XML that starts with {@code {id}-}.
5883
*
@@ -149,21 +174,32 @@ private static List<InventoryEntry> parseInventory(String json) {
149174

150175
List<InventoryEntry> entries = new ArrayList<>();
151176
for (JsonNode node : root) {
152-
int id = node.required("id").asInt();
153-
entries.add(new InventoryEntry(id));
177+
String numericId = node.get("id").isTextual()
178+
? node.get("id").asText()
179+
: String.valueOf(node.get("id").asInt());
180+
boolean requiresSystemPrompt = node.has("requiresSystemPrompt")
181+
? node.get("requiresSystemPrompt").asBoolean()
182+
: true;
183+
String skillId = node.has("skillId") ? node.get("skillId").asText() : null;
184+
185+
if (!requiresSystemPrompt && (skillId == null || skillId.isBlank())) {
186+
throw new RuntimeException("Entry with id " + numericId
187+
+ " has requiresSystemPrompt=false but no skillId specified.");
188+
}
189+
entries.add(new InventoryEntry(numericId, requiresSystemPrompt, skillId));
154190
}
155191
return entries;
156192
} catch (Exception e) {
157193
throw new RuntimeException("Failed to parse skill inventory", e);
158194
}
159195
}
160196

161-
private static void validateSkillSummaryExists(int id) {
162-
String resourceName = "skills/" + id + "-skill.md";
197+
private static void validateSkillSummaryExists(String numericId) {
198+
String resourceName = "skills/" + numericId + "-skill.md";
163199
try (InputStream stream = getResource(resourceName)) {
164200
if (stream == null) {
165201
throw new RuntimeException("Skill summary not found: " + resourceName
166-
+ ". Add skills/" + id + "-skill.md for each skill in the inventory.");
202+
+ ". Add skills/" + numericId + "-skill.md for each skill in the inventory.");
167203
}
168204
} catch (Exception e) {
169205
if (e instanceof RuntimeException re) {
@@ -186,8 +222,9 @@ private static InputStream getResource(String name) {
186222
}
187223

188224
/**
189-
* Single entry from skill-inventory.json: numeric id only. skillId is derived
190-
* by matching system-prompts with prefix {@code {id}-}.
225+
* Single entry from skill-inventory.json. When requiresSystemPrompt is true,
226+
* skillId is derived by matching system-prompts with prefix {@code {numericId}-}.
227+
* When false, skillId must be provided and no system-prompt is required.
191228
*/
192-
public record InventoryEntry(int id) {}
229+
public record InventoryEntry(String numericId, boolean requiresSystemPrompt, String skillId) {}
193230
}

skills-generator/src/main/resources/skill-inventory.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
[
2+
{"id": "010", "requiresSystemPrompt": false, "skillId": "010-java-design-plans"},
23
{"id": 110},
34
{"id": 111},
45
{"id": 112},
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
---
2+
name: 010-java-design-plans
3+
description: Use when it is creatin a plan using Plan model and enchance the creation of structured design plans in Cursor Plan mode for Java implementations. Use when the user wants to create a plan, design an implementation, structure a development plan, or use plan mode for outside-in TDD, feature implementation, or refactoring work.
4+
---
5+
6+
# Java Design Plan Creation
7+
8+
Guides the process of creating a structured plan using Cursor Plan mode. Plans follow a consistent section structure suitable for Java feature implementation, refactoring, or API design.
9+
10+
---
11+
12+
## Plan Mode Workflow
13+
14+
1. **Enter Plan mode** (or use plan-related commands) before creating the plan.
15+
2. **Gather context**: Read specs, existing code, and acceptance criteria.
16+
3. **Draft the plan** using the structure below.
17+
4. **Iterate**: Refine tasks, dependencies, and file checklist as needed.
18+
19+
---
20+
21+
## Plan File Structure
22+
23+
Plans use Markdown with YAML frontmatter. Save to `.cursor/plans/YYYY-MM-DD_<plan_name>.plan.md` (prefix with creation date).
24+
25+
### YAML Frontmatter
26+
27+
```yaml
28+
---
29+
name: <Short Plan Name>
30+
overview: "<One-line description: what, approach, key constraints.>"
31+
todos: []
32+
isProject: false
33+
---
34+
```
35+
36+
### Required Sections
37+
38+
| Section | Purpose | Content |
39+
|---------|---------|---------|
40+
| **Title** | Problem/feature identifier | `# Problem N: [Name] Implementation Plan` |
41+
| **Requirements Summary** | Business context | User story, key business rules, acceptance criteria |
42+
| **Approach** | Strategy and flow | Named approach (e.g., London Style TDD), diagram (Mermaid) |
43+
| **Task List** | Ordered implementation steps | Table with #, Phase, Task, TDD, Status |
44+
| **Execution Instructions** | How agents must execute | Update task Status after each task before advancing |
45+
| **File Checklist** | What files and when | Order, File path, When (TDD phase) |
46+
| **Notes** | Extra context | Package layout, conventions, edge cases |
47+
48+
---
49+
50+
## Section Templates
51+
52+
### Requirements Summary
53+
54+
```markdown
55+
## Requirements Summary
56+
57+
**User Story:** [One sentence describing the user goal.]
58+
59+
**Key Business Rules:**
60+
- **[Rule name]:** [Concrete rule]
61+
- **[Filtering / Conversion / Timeout]:** [Behavior]
62+
- **Expected result:** [Specific value or behavior when applicable]
63+
```
64+
65+
### Approach (with Diagram)
66+
67+
````markdown
68+
## [Approach Name] (e.g., London Style Outside-In TDD)
69+
70+
[Brief description of the strategy.]
71+
72+
```mermaid
73+
flowchart LR
74+
subgraph [Flow Name]
75+
A[Step 1] --> B[Step 2]
76+
B --> C[Step 3]
77+
end
78+
```
79+
````
80+
81+
### Task List Table
82+
83+
```markdown
84+
## Task List ([Approach] Order)
85+
86+
| # | Phase | Task | TDD | Status |
87+
| --- | ------- | ------------------------------------------------------------- | ---- | ------ |
88+
| 1 | Setup | [First task] | | |
89+
| 2 | RED | [Write failing test] | Test | |
90+
| 3 | GREEN | [Implement minimal solution] | Impl | |
91+
| 4 | Refactor| [Polish, verify] | | |
92+
```
93+
94+
**Phases:** Setup, RED (write failing test), GREEN (pass test), Refactor. Use the **Status** column to track completion (e.g., ``, `Done`, or `` when finished).
95+
96+
### Execution Instructions (Required)
97+
98+
Include this section in every plan. It reminds agents to update the task list during execution:
99+
100+
```markdown
101+
## Execution Instructions
102+
103+
When executing this plan:
104+
1. Complete the current task.
105+
2. **Update the Task List**: set the Status column for that task (e.g., ✔ or Done).
106+
3. Only then proceed to the next task.
107+
4. Repeat for all tasks. Never advance without updating the plan.
108+
```
109+
110+
### File Checklist Table
111+
112+
```markdown
113+
## File Checklist ([Approach] Order)
114+
115+
| Order | File | When (TDD) |
116+
| ----- | ------------------------------------------------- | ----------------------- |
117+
| 1 | `path/to/File1.java` | Setup |
118+
| 2 | `path/to/Test.java` | RED — write first |
119+
| 3 | `path/to/Impl.java` | GREEN — implement |
120+
```
121+
122+
---
123+
124+
## London Style (Outside-In) TDD Pattern
125+
126+
For feature implementation, prefer **outside-in** order:
127+
128+
1. **Acceptance/integration test** (RED) — defines API and expected behavior.
129+
2. **Delegate/controller** (GREEN) — minimal wiring.
130+
3. **Service unit test** (RED) — business logic in isolation.
131+
4. **Service implementation** (GREEN) — with fake/stub dependencies.
132+
5. **Client test** (RED) — external calls.
133+
6. **Client implementation** (GREEN) — wire real client.
134+
7. **Refactor** — remove fakes, add error handling, verify `mvn clean verify`.
135+
136+
---
137+
138+
## Plan Execution Workflow
139+
140+
When **executing** a plan, follow this discipline for every task:
141+
142+
1. **Run** the current task (e.g., Task 1).
143+
2. **When the task finishes**, immediately update the plan file: set the Status column for that task (e.g., ✔ or Done or ✓).
144+
3. **Then** proceed to the next task.
145+
4. Repeat steps 1–3 for all tasks in order.
146+
147+
Never advance to the next task without updating the task list. This keeps progress visible and lets the plan file reflect the current state.
148+
149+
---
150+
151+
## Plan Creation Checklist
152+
153+
Before finalizing:
154+
155+
- [ ] Frontmatter has `name`, `overview`, `todos`, `isProject`.
156+
- [ ] Requirements Summary includes user story and key business rules.
157+
- [ ] Approach section names the strategy and includes a Mermaid diagram.
158+
- [ ] Task list is ordered (Setup → RED → GREEN → Refactor) with Status column.
159+
- [ ] **Execution Instructions** section is included (update Status after each task before advancing).
160+
- [ ] File checklist maps files to TDD phases.
161+
- [ ] Notes cover package layout, conventions, and constraints.
162+
- [ ] Plan file path is `.cursor/plans/YYYY-MM-DD_<name>.plan.md`.

0 commit comments

Comments
 (0)