@we-scrum/cli 1.0.4 → 1.0.5

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.
@@ -1,150 +1,26 @@
1
- import { WeScrumHelper } from '@helpers';
2
- import { _compact } from '@my-devkit/core';
3
- import { Operation, ProgressStatus } from '@we-scrum/enums';
4
- import {
5
- ProjectStorySectionModelEnumerationChange,
6
- ProjectStorySectionModelObjectChange,
7
- ProjectStorySectionModelRelationChange,
8
- ProjectStorySectionModelRouteChange,
9
- ProjectStorySectionModelTask,
10
- } from '@we-scrum/models';
1
+ import { renderTemplate, WeScrumHelper } from '@helpers';
2
+ import { ProgressStatus } from '@we-scrum/enums';
3
+ import { StorySectionHelper, stringifyAnalysisDslChange } from '@we-scrum/utils';
11
4
 
12
- export async function getNextTask(identificationNumber: string): Promise<Record<string, string>> {
13
- const nextTask = await WeScrumHelper.getNextChange(identificationNumber);
5
+ export async function getNextTask(identificationNumber: string): Promise<string> {
6
+ const nextChange = await WeScrumHelper.getNextChange(identificationNumber);
14
7
 
15
- if (!nextTask) {
16
- return { message: `All tasks for story "${identificationNumber}" are complete.` };
8
+ if (!nextChange) {
9
+ return `## Story ${identificationNumber}\n\nAll tasks are complete.`;
17
10
  }
18
11
 
19
- const isTodo = nextTask.progress.status === ProgressStatus.ToDo;
20
- const generalInstructions = _compact([
21
- 'Implement the task described in the fields below.',
22
- 'Refer to `implementationGuidelines` for coding conventions and project-specific instructions.',
23
- isTodo ? 'Before making any changes, run `start_task` to mark the task as in progress.' : null,
24
- 'If anything is unclear, stop and ask before making any changes.',
25
- 'Once all changes are done, commit your code and run `complete_task`.',
26
- 'After completing a task, immediately run `get_next_task` again and continue until all tasks are complete.',
27
- ]).join('\n');
12
+ const analysisChange = StorySectionHelper.mapSingleChange(nextChange);
13
+ const isTodo = nextChange.progress.status === ProgressStatus.ToDo;
14
+ const developmentPolicy = await WeScrumHelper.getChangeDevelopmentPolicy(nextChange);
28
15
 
29
- const developmentPolicy = await WeScrumHelper.getChangeDevelopmentPolicy(nextTask);
30
- const implementationGuidelines = developmentPolicy?.codeGuidelines ?? 'No guidelines found for this task... :-(';
16
+ const { guidelinesPath, unitTestsPath } = WeScrumHelper.getDevelopmentPolicyPaths(developmentPolicy);
31
17
 
32
- const unitTestInstructions = 'Run get_unit_test_guidelines to get instructions to generate unit tests for this task';
33
- const unitTests = developmentPolicy?.areUnitTestsMandatory ? unitTestInstructions : 'No unit test needed.';
34
-
35
- if (nextTask instanceof ProjectStorySectionModelEnumerationChange) {
36
- const propertyChanges = nextTask.propertyChanges
37
- .filter((pc) => !!pc.operation)
38
- .map((pc) => `${pc.operation} property ${pc.propertyName} (= '${pc.propertyValue}')`)
39
- .sort()
40
- .join('\n');
41
-
42
- return {
43
- generalInstructions,
44
- taskType: `${nextTask.operation} enumeration`,
45
- enumerationName: nextTask.enumerationName,
46
- propertyChanges: propertyChanges || 'No change on properties',
47
- taskDescription: nextTask.description ?? undefined,
48
- implementationGuidelines,
49
- unitTests,
50
- };
51
- }
52
- if (nextTask instanceof ProjectStorySectionModelObjectChange) {
53
- const propertyMap = new Map(nextTask.propertyChanges.map((pc) => [pc.objectPropertyId, pc]));
54
-
55
- const buildPath = (pc: (typeof nextTask.propertyChanges)[0]): string => {
56
- const name = pc.isArray ? `${pc.propertyName}[]` : pc.propertyName;
57
- if (!pc.objectPropertyParentId) return name;
58
- const parent = propertyMap.get(pc.objectPropertyParentId);
59
- return parent ? `${buildPath(parent)}.${name}` : name;
60
- };
61
-
62
- const changedProperties = nextTask.propertyChanges.filter((pc) => !!pc.operation);
63
- const parentIdsWithChangedChildren = new Set(changedProperties.map((pc) => pc.objectPropertyParentId).filter(Boolean));
64
-
65
- const propertyChanges = changedProperties
66
- .filter((pc) => !(pc.operation === Operation.Create && parentIdsWithChangedChildren.has(pc.objectPropertyId)))
67
- .map((pc) => {
68
- const enumInfo = pc.enumerationName ? ` (enum: ${pc.enumerationName})` : '';
69
- return `${pc.operation} property ${buildPath(pc)}: ${pc.propertyType}${enumInfo}`;
70
- })
71
- .sort()
72
- .join('\n');
73
-
74
- return {
75
- generalInstructions,
76
- taskType: `${nextTask.operation} object`,
77
- objectName: nextTask.objectName,
78
- renamedFrom: nextTask.initialObjectName
79
- ? `Object renamed from "${nextTask.initialObjectName}" to "${nextTask.objectName}"`
80
- : undefined,
81
- propertyChanges: propertyChanges || 'No change on properties',
82
- taskDescription: nextTask.description ?? undefined,
83
- implementationGuidelines,
84
- unitTests,
85
- };
86
- }
87
- if (nextTask instanceof ProjectStorySectionModelRouteChange) {
88
- const queryParamChanges = nextTask.queryParamChanges
89
- .filter((qp) => !!qp.operation)
90
- .map((qp) => {
91
- const enumInfo = qp.enumerationName ? ` (enum: ${qp.enumerationName})` : '';
92
- return `${qp.operation} query param ${qp.routeQueryParamName}: ${qp.routeQueryParamType}${enumInfo}`;
93
- })
94
- .sort()
95
- .join('\n');
96
-
97
- return {
98
- generalInstructions,
99
- taskType: `${nextTask.operation} route`,
100
- route: `${nextTask.routeMethod} ${nextTask.routePath}`,
101
- routeObject: nextTask.routeObjectName ?? undefined,
102
- pathChangedFrom:
103
- nextTask.initialRoutePath && nextTask.initialRoutePath !== nextTask.routePath ? nextTask.initialRoutePath : undefined,
104
- methodChangedFrom:
105
- nextTask.initialRouteMethod && nextTask.initialRouteMethod !== nextTask.routeMethod
106
- ? nextTask.initialRouteMethod
107
- : undefined,
108
- objectChangedFrom:
109
- nextTask.initialRouteObjectName && nextTask.initialRouteObjectName !== nextTask.routeObjectName
110
- ? nextTask.initialRouteObjectName
111
- : undefined,
112
- permissionChangedFrom:
113
- nextTask.initialRoutePermission && nextTask.initialRoutePermission !== nextTask.routePermission
114
- ? nextTask.initialRoutePermission
115
- : undefined,
116
- queryParamChanges: queryParamChanges || 'No change on query params',
117
- taskDescription: nextTask.description ?? undefined,
118
- implementationGuidelines,
119
- unitTests,
120
- };
121
- }
122
- if (nextTask instanceof ProjectStorySectionModelRelationChange) {
123
- const relations = nextTask.relations
124
- .filter((r) => !!r.operation)
125
- .map((r) => `${r.operation} [${r.objects.map((o) => o.objectName).join(' ⇒ ')}]`)
126
- .sort()
127
- .join('\n');
128
-
129
- return {
130
- generalInstructions,
131
- taskType: 'relation change',
132
- handlerName: nextTask.handlerName,
133
- boundedContext: nextTask.boundedContext,
134
- subscriptionName: nextTask.subscriptionName ?? undefined,
135
- relations: relations || 'No relation changes',
136
- taskDescription: nextTask.description ?? undefined,
137
- implementationGuidelines,
138
- unitTests,
139
- };
140
- }
141
- if (nextTask instanceof ProjectStorySectionModelTask) {
142
- return {
143
- generalInstructions,
144
- taskType: nextTask.taskTypeName,
145
- taskDescription: nextTask.description ?? undefined,
146
- implementationGuidelines,
147
- unitTests,
148
- };
149
- }
18
+ return renderTemplate('get-next-task', {
19
+ taskDetails: stringifyAnalysisDslChange(analysisChange),
20
+ guidelinesPath,
21
+ unitTestsPath: developmentPolicy?.areUnitTestsMandatory ? unitTestsPath : null,
22
+ isTodo,
23
+ identificationNumber,
24
+ taskId: analysisChange.id,
25
+ });
150
26
  }
@@ -1,4 +1 @@
1
- export * from './complete-task';
2
1
  export * from './get-next-task';
3
- export * from './get-unit-test-guidelines';
4
- export * from './start-task';
@@ -0,0 +1,40 @@
1
+ ---
2
+ name: develop-story
3
+ description: >
4
+ Develop a we-scrum user story by iterating through its tasks one by one.
5
+ Use this skill whenever the user says "develop story XXXXX", "/develop-story XXXXX",
6
+ or asks to implement or work on a specific story number. The skill synchronizes
7
+ development policies, then fetches and implements each task in sequence using
8
+ the we-scrum MCP server and CLI.
9
+ compatibility: "Requires: we-scrum MCP server, we-scrum CLI (we-scrum)"
10
+ ---
11
+
12
+ # Develop Story Skill
13
+
14
+ Iterates through a we-scrum story's tasks, implementing each one in sequence until
15
+ all tasks are complete.
16
+
17
+ ---
18
+
19
+ ## Step 0 — Resolve the story identification number
20
+
21
+ If the user provided a story identification number (e.g. `/develop-story 00240`), use it.
22
+ Otherwise, ask: _"Which story would you like to develop? Please provide the identification number."_
23
+ Do not proceed until a number is provided.
24
+
25
+ ---
26
+
27
+ ## Step 1 — Synchronize development policies
28
+
29
+ Pull the latest development guidelines into the project before starting any work:
30
+
31
+ ```bash
32
+ we-scrum synchronize-development-policies
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Step 2 — Fetch and implement tasks
38
+
39
+ Call the `get_next_task` MCP tool with the story identification number and follow
40
+ the instructions it returns. Repeat until all tasks are complete.
@@ -0,0 +1,3 @@
1
+ Get the next pending task for a story as a Markdown document.
2
+ Returns the task description, location of development guidelines, unit test instructions,
3
+ and the exact CLI commands to run (we-scrum start-task / complete-task, with taskId pre-filled).
@@ -0,0 +1,21 @@
1
+ {{{taskDetails}}}
2
+
3
+ ## Development guidelines
4
+ {{#if guidelinesPath}}Refer to `{{{guidelinesPath}}}` for coding conventions and project-specific instructions.{{else}}_No development guidelines file configured for this task._{{/if}}
5
+
6
+ ## Unit tests
7
+ {{#if unitTestsPath}}Unit tests are required. Refer to `{{{unitTestsPath}}}` for test writing guidelines.{{else}}No unit tests required.{{/if}}
8
+
9
+ ## Next steps
10
+ {{#if isTodo}}
11
+ 1. Run `we-scrum start-task --identificationNumber "{{identificationNumber}}" --taskId "{{taskId}}"` before making any changes.
12
+ 2. Implement the task described above.
13
+ 3. Commit your changes.
14
+ 4. Run `we-scrum complete-task --identificationNumber "{{identificationNumber}}" --taskId "{{taskId}}"` when done.
15
+ 5. Call `get_next_task` to continue with the next task.
16
+ {{else}}
17
+ 1. Implement the task described above.
18
+ 2. Commit your changes.
19
+ 3. Run `we-scrum complete-task --identificationNumber "{{identificationNumber}}" --taskId "{{taskId}}"` when done.
20
+ 4. Call `get_next_task` to continue with the next task.
21
+ {{/if}}
package/tsconfig.json CHANGED
@@ -14,6 +14,7 @@
14
14
  "resolveJsonModule": true,
15
15
  "paths": {
16
16
  "@helpers": ["helpers"]
17
- }
17
+ },
18
+ "forceConsistentCasingInFileNames": true
18
19
  }
19
20
  }
@@ -1,6 +0,0 @@
1
- import { WeScrumHelper } from '@helpers';
2
-
3
- export async function completeTask(identificationNumber: string): Promise<Record<string, string>> {
4
- await WeScrumHelper.completeTask(identificationNumber);
5
- return { message: 'Task completed successfully.' };
6
- }
@@ -1,15 +0,0 @@
1
- import { WeScrumHelper } from '@helpers';
2
-
3
- export async function getUnitTestGuidelines(identificationNumber: string): Promise<Record<string, string>> {
4
- const nextTask = await WeScrumHelper.getNextChange(identificationNumber);
5
-
6
- if (!nextTask) {
7
- return { message: `All tasks for story "${identificationNumber}" are complete.` };
8
- }
9
-
10
- const developmentPolicy = await WeScrumHelper.getChangeDevelopmentPolicy(nextTask);
11
-
12
- return {
13
- unitTestGuidelines: developmentPolicy?.unitTestsGuidelines ?? 'No unit test guidelines found for this task.',
14
- };
15
- }
@@ -1,6 +0,0 @@
1
- import { WeScrumHelper } from '@helpers';
2
-
3
- export async function startTask(identificationNumber: string): Promise<Record<string, string>> {
4
- await WeScrumHelper.startTask(identificationNumber);
5
- return { message: 'Task started successfully. You can now make changes to the codebase.' };
6
- }