agile-context-engineering 0.3.0 → 0.5.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.
Files changed (147) hide show
  1. package/.claude-plugin/plugin.json +10 -0
  2. package/LICENSE +51 -51
  3. package/README.md +332 -324
  4. package/agents/ace-product-owner.md +1 -1
  5. package/agents/ace-research-synthesizer.md +228 -228
  6. package/agents/ace-wiki-mapper.md +449 -445
  7. package/bin/install.js +60 -64
  8. package/hooks/ace-check-update.js +70 -62
  9. package/hooks/ace-statusline.js +89 -89
  10. package/package.json +5 -4
  11. package/shared/lib/ace-core.js +308 -0
  12. package/shared/lib/ace-core.test.js +308 -0
  13. package/shared/lib/ace-github.js +753 -0
  14. package/shared/lib/ace-story.js +400 -0
  15. package/shared/lib/ace-story.test.js +250 -0
  16. package/{agile-context-engineering → shared}/utils/questioning.xml +110 -110
  17. package/{agile-context-engineering → shared}/utils/ui-formatting.md +299 -299
  18. package/skills/execute-story/SKILL.md +110 -0
  19. package/skills/execute-story/script.js +305 -0
  20. package/skills/execute-story/script.test.js +261 -0
  21. package/skills/execute-story/walkthrough-template.xml +255 -0
  22. package/{agile-context-engineering/workflows/execute-story.xml → skills/execute-story/workflow.xml} +1219 -1219
  23. package/skills/help/SKILL.md +69 -0
  24. package/skills/help/script.js +318 -0
  25. package/skills/help/script.test.js +183 -0
  26. package/{agile-context-engineering/workflows/help.xml → skills/help/workflow.xml} +540 -540
  27. package/skills/init-coding-standards/SKILL.md +72 -0
  28. package/skills/init-coding-standards/script.js +59 -0
  29. package/skills/init-coding-standards/script.test.js +70 -0
  30. package/{agile-context-engineering/workflows/init-coding-standards.xml → skills/init-coding-standards/workflow.xml} +381 -386
  31. package/skills/map-cross-cutting/SKILL.md +89 -0
  32. package/{agile-context-engineering/templates/wiki → skills/map-cross-cutting}/system-cross-cutting.xml +197 -197
  33. package/skills/map-cross-cutting/workflow.xml +330 -0
  34. package/skills/map-guide/SKILL.md +89 -0
  35. package/{agile-context-engineering/templates/wiki → skills/map-guide}/guide.xml +137 -137
  36. package/skills/map-guide/workflow.xml +320 -0
  37. package/skills/map-pattern/SKILL.md +89 -0
  38. package/{agile-context-engineering/templates/wiki → skills/map-pattern}/pattern.xml +159 -159
  39. package/skills/map-pattern/workflow.xml +331 -0
  40. package/skills/map-story/SKILL.md +127 -0
  41. package/{agile-context-engineering/templates/wiki → skills/map-story/templates}/decizions.xml +115 -115
  42. package/skills/map-story/templates/guide.xml +137 -0
  43. package/skills/map-story/templates/pattern.xml +159 -0
  44. package/skills/map-story/templates/system-cross-cutting.xml +197 -0
  45. package/{agile-context-engineering/templates/wiki → skills/map-story/templates}/system.xml +381 -381
  46. package/{agile-context-engineering/templates/wiki → skills/map-story/templates}/walkthrough.xml +255 -255
  47. package/{agile-context-engineering/workflows/map-story.xml → skills/map-story/workflow.xml} +1046 -1046
  48. package/skills/map-subsystem/SKILL.md +111 -0
  49. package/skills/map-subsystem/script.js +60 -0
  50. package/skills/map-subsystem/script.test.js +68 -0
  51. package/skills/map-subsystem/templates/decizions.xml +115 -0
  52. package/skills/map-subsystem/templates/guide.xml +137 -0
  53. package/{agile-context-engineering/templates/wiki → skills/map-subsystem/templates}/module-discovery.xml +174 -174
  54. package/skills/map-subsystem/templates/pattern.xml +159 -0
  55. package/skills/map-subsystem/templates/system-cross-cutting.xml +197 -0
  56. package/skills/map-subsystem/templates/system.xml +381 -0
  57. package/skills/map-subsystem/templates/walkthrough.xml +255 -0
  58. package/{agile-context-engineering/workflows/map-subsystem.xml → skills/map-subsystem/workflow.xml} +15 -20
  59. package/skills/map-sys-doc/SKILL.md +90 -0
  60. package/skills/map-sys-doc/system.xml +381 -0
  61. package/skills/map-sys-doc/workflow.xml +336 -0
  62. package/skills/map-system/SKILL.md +85 -0
  63. package/skills/map-system/script.js +84 -0
  64. package/skills/map-system/script.test.js +73 -0
  65. package/{agile-context-engineering/templates/wiki → skills/map-system/templates}/system-architecture.xml +254 -254
  66. package/{agile-context-engineering/templates/wiki → skills/map-system/templates}/wiki-readme.xml +296 -296
  67. package/{agile-context-engineering/workflows/map-system.xml → skills/map-system/workflow.xml} +11 -16
  68. package/skills/map-walkthrough/SKILL.md +92 -0
  69. package/skills/map-walkthrough/walkthrough.xml +255 -0
  70. package/skills/plan-backlog/SKILL.md +75 -0
  71. package/{agile-context-engineering/templates/product/product-backlog.xml → skills/plan-backlog/product-backlog-template.xml} +231 -231
  72. package/skills/plan-backlog/script.js +136 -0
  73. package/skills/plan-backlog/script.test.js +83 -0
  74. package/{agile-context-engineering/workflows/plan-backlog.xml → skills/plan-backlog/workflow.xml} +13 -21
  75. package/skills/plan-feature/SKILL.md +76 -0
  76. package/skills/plan-feature/script.js +148 -0
  77. package/skills/plan-feature/script.test.js +80 -0
  78. package/{agile-context-engineering/workflows/plan-feature.xml → skills/plan-feature/workflow.xml} +1487 -1495
  79. package/skills/plan-product-vision/SKILL.md +75 -0
  80. package/skills/plan-product-vision/script.js +60 -0
  81. package/skills/plan-product-vision/script.test.js +69 -0
  82. package/{agile-context-engineering/workflows/plan-product-vision.xml → skills/plan-product-vision/workflow.xml} +4 -9
  83. package/skills/plan-story/SKILL.md +116 -0
  84. package/skills/plan-story/script.js +326 -0
  85. package/skills/plan-story/script.test.js +240 -0
  86. package/skills/plan-story/story-template.xml +451 -0
  87. package/{agile-context-engineering/workflows/plan-story.xml → skills/plan-story/workflow.xml} +1285 -944
  88. package/skills/research-external-solution/SKILL.md +107 -0
  89. package/skills/research-external-solution/script.js +238 -0
  90. package/skills/research-external-solution/script.test.js +134 -0
  91. package/{agile-context-engineering/workflows/research-external-solution.xml → skills/research-external-solution/workflow.xml} +4 -6
  92. package/skills/research-integration-solution/SKILL.md +98 -0
  93. package/skills/research-integration-solution/script.js +231 -0
  94. package/skills/research-integration-solution/script.test.js +134 -0
  95. package/{agile-context-engineering/workflows/research-integration-solution.xml → skills/research-integration-solution/workflow.xml} +3 -5
  96. package/skills/research-story-wiki/SKILL.md +92 -0
  97. package/skills/research-story-wiki/script.js +231 -0
  98. package/skills/research-story-wiki/script.test.js +138 -0
  99. package/{agile-context-engineering/workflows/research-story-wiki.xml → skills/research-story-wiki/workflow.xml} +3 -5
  100. package/skills/research-technical-solution/SKILL.md +103 -0
  101. package/skills/research-technical-solution/script.js +231 -0
  102. package/skills/research-technical-solution/script.test.js +134 -0
  103. package/{agile-context-engineering/workflows/research-technical-solution.xml → skills/research-technical-solution/workflow.xml} +3 -5
  104. package/skills/review-story/SKILL.md +100 -0
  105. package/skills/review-story/script.js +257 -0
  106. package/skills/review-story/script.test.js +169 -0
  107. package/skills/review-story/story-template.xml +451 -0
  108. package/{agile-context-engineering/workflows/review-story.xml → skills/review-story/workflow.xml} +279 -281
  109. package/skills/update/SKILL.md +53 -0
  110. package/{agile-context-engineering/workflows/update.xml → skills/update/workflow.xml} +12 -13
  111. package/agile-context-engineering/src/ace-tools.js +0 -2881
  112. package/agile-context-engineering/src/ace-tools.test.js +0 -1089
  113. package/agile-context-engineering/templates/_command.md +0 -54
  114. package/agile-context-engineering/templates/_workflow.xml +0 -17
  115. package/agile-context-engineering/templates/config.json +0 -0
  116. package/agile-context-engineering/templates/product/integration-solution.xml +0 -0
  117. package/commands/ace/execute-story.md +0 -138
  118. package/commands/ace/help.md +0 -93
  119. package/commands/ace/init-coding-standards.md +0 -83
  120. package/commands/ace/map-story.md +0 -165
  121. package/commands/ace/map-subsystem.md +0 -140
  122. package/commands/ace/map-system.md +0 -92
  123. package/commands/ace/map-walkthrough.md +0 -127
  124. package/commands/ace/plan-backlog.md +0 -83
  125. package/commands/ace/plan-feature.md +0 -89
  126. package/commands/ace/plan-product-vision.md +0 -81
  127. package/commands/ace/plan-story.md +0 -159
  128. package/commands/ace/research-external-solution.md +0 -138
  129. package/commands/ace/research-integration-solution.md +0 -135
  130. package/commands/ace/research-story-wiki.md +0 -116
  131. package/commands/ace/research-technical-solution.md +0 -147
  132. package/commands/ace/review-story.md +0 -109
  133. package/commands/ace/update.md +0 -56
  134. /package/{agile-context-engineering/templates/product/story.xml → skills/execute-story/story-template.xml} +0 -0
  135. /package/{agile-context-engineering/templates/wiki/coding-standards.xml → skills/init-coding-standards/coding-standards-template.xml} +0 -0
  136. /package/{agile-context-engineering/templates/wiki → skills/map-story/templates}/tech-debt-index.xml +0 -0
  137. /package/{agile-context-engineering/templates/wiki → skills/map-subsystem/templates}/subsystem-architecture.xml +0 -0
  138. /package/{agile-context-engineering/templates/wiki → skills/map-subsystem/templates}/subsystem-structure.xml +0 -0
  139. /package/{agile-context-engineering/templates/wiki → skills/map-system/templates}/system-structure.xml +0 -0
  140. /package/{agile-context-engineering/templates/wiki → skills/map-system/templates}/testing-framework.xml +0 -0
  141. /package/{agile-context-engineering/workflows/map-walkthrough.xml → skills/map-walkthrough/workflow.xml} +0 -0
  142. /package/{agile-context-engineering/templates/product/feature.xml → skills/plan-feature/feature-template.xml} +0 -0
  143. /package/{agile-context-engineering/templates/product/product-vision.xml → skills/plan-product-vision/product-vision-template.xml} +0 -0
  144. /package/{agile-context-engineering/templates/product/external-solution.xml → skills/research-external-solution/external-solution-template.xml} +0 -0
  145. /package/{agile-context-engineering/templates/product/story-integration-solution.xml → skills/research-integration-solution/integration-solution-template.xml} +0 -0
  146. /package/{agile-context-engineering/templates/product/story-wiki.xml → skills/research-story-wiki/story-wiki-template.xml} +0 -0
  147. /package/{agile-context-engineering/templates/product/story-technical-solution.xml → skills/research-technical-solution/technical-solution-template.xml} +0 -0
@@ -0,0 +1,240 @@
1
+ const { describe, it, before, after } = require('node:test');
2
+ const assert = require('node:assert');
3
+ const { execSync } = require('child_process');
4
+ const fs = require('fs');
5
+ const path = require('path');
6
+ const os = require('os');
7
+
8
+ const SCRIPT = path.join(__dirname, 'script.js');
9
+
10
+ /**
11
+ * Create a minimal ACE project structure in a temp directory.
12
+ */
13
+ function createTestProject() {
14
+ const tmpDir = fs.mkdtempSync(path.join(os.tmpdir(), 'ace-test-'));
15
+
16
+ // .ace/config.json
17
+ const aceDir = path.join(tmpDir, '.ace');
18
+ fs.mkdirSync(aceDir, { recursive: true });
19
+ fs.writeFileSync(path.join(aceDir, 'config.json'), JSON.stringify({
20
+ version: '0.1.0',
21
+ projectName: 'test-project',
22
+ model_profile: 'quality',
23
+ commit_docs: true,
24
+ github: { enabled: false },
25
+ }, null, 2));
26
+
27
+ // .ace/settings.json
28
+ fs.writeFileSync(path.join(aceDir, 'settings.json'), JSON.stringify({
29
+ model_profile: 'quality',
30
+ commit_docs: true,
31
+ agent_teams: false,
32
+ github_project: { enabled: false, gh_installed: false, repo: '', project_number: null, owner: '' },
33
+ }, null, 2));
34
+
35
+ return tmpDir;
36
+ }
37
+
38
+ /**
39
+ * Create a story file in the test project.
40
+ */
41
+ function createStoryFile(tmpDir, relPath, content) {
42
+ const fullPath = path.join(tmpDir, relPath);
43
+ fs.mkdirSync(path.dirname(fullPath), { recursive: true });
44
+ fs.writeFileSync(fullPath, content, 'utf-8');
45
+ return relPath;
46
+ }
47
+
48
+ function runScript(subcommand, args, cwd) {
49
+ return execSync(`node "${SCRIPT}" ${subcommand} ${args}`, {
50
+ cwd,
51
+ encoding: 'utf-8',
52
+ timeout: 10000,
53
+ });
54
+ }
55
+
56
+ function cleanup(tmpDir) {
57
+ fs.rmSync(tmpDir, { recursive: true, force: true });
58
+ }
59
+
60
+ // ─── Tests ───────────────────────────────────────────────────────────────────
61
+
62
+ describe('plan-story script', () => {
63
+
64
+ describe('init', () => {
65
+ let tmpDir;
66
+
67
+ before(() => { tmpDir = createTestProject(); });
68
+ after(() => { cleanup(tmpDir); });
69
+
70
+ it('returns valid JSON with environment detection for a story file', () => {
71
+ const storyContent = [
72
+ '# S1: Add Login Button',
73
+ '**Feature**: F1 User Auth | **Epic**: E1 Platform',
74
+ '**Status**: Todo | **Size**: 3 | **Sprint**: — | **Link**: —',
75
+ '',
76
+ '## User Story',
77
+ '',
78
+ '> As a user,',
79
+ '> I want to click a login button,',
80
+ '> so that I can access my account.',
81
+ '',
82
+ '## Description',
83
+ '',
84
+ 'Adds a login button to the header.',
85
+ '',
86
+ '## Acceptance Criteria',
87
+ '',
88
+ '### Scenario: Click login button',
89
+ '',
90
+ '**Given** the user is on the homepage',
91
+ '**When** they click "Login"',
92
+ '**Then** they see the login form',
93
+ ].join('\n');
94
+
95
+ const storyPath = createStoryFile(
96
+ tmpDir,
97
+ '.ace/artifacts/product/e1-platform/f1-user-auth/s1-add-login-button/s1-add-login-button.md',
98
+ storyContent
99
+ );
100
+
101
+ const result = JSON.parse(runScript('init', storyPath, tmpDir));
102
+
103
+ assert.ok(result.product_owner_model, 'should have product_owner_model');
104
+ assert.strictEqual(result.story_valid, true, 'story should be valid');
105
+ assert.strictEqual(result.story_source, 'file');
106
+ assert.strictEqual(result.story.id, 'S1');
107
+ assert.strictEqual(result.story.title, 'Add Login Button');
108
+ assert.strictEqual(result.story.status, 'Todo');
109
+ assert.strictEqual(result.acceptance_criteria_count, 1);
110
+ assert.ok(result.paths, 'should have computed paths');
111
+ assert.ok(result.paths.story_file.includes('s1-add-login-button'));
112
+ assert.strictEqual(result.has_story_file, true);
113
+ assert.strictEqual(typeof result.commit_docs, 'boolean');
114
+ assert.strictEqual(typeof result.has_git, 'boolean');
115
+ });
116
+
117
+ it('returns valid result for new story mode (no params)', () => {
118
+ const result = JSON.parse(runScript('init', '', tmpDir));
119
+
120
+ assert.strictEqual(result.story_source, 'new');
121
+ assert.strictEqual(result.story_valid, true);
122
+ assert.strictEqual(result.story_content, null);
123
+ assert.strictEqual(result.story.id, null);
124
+ assert.strictEqual(result.paths, null);
125
+ });
126
+
127
+ it('returns valid result for text mode', () => {
128
+ const result = JSON.parse(runScript('init', 'text="User can reset password"', tmpDir));
129
+
130
+ assert.strictEqual(result.story_source, 'text');
131
+ assert.strictEqual(result.story_valid, true);
132
+ assert.strictEqual(result.story_content, 'User can reset password');
133
+ assert.strictEqual(result.description, 'User can reset password');
134
+ assert.strictEqual(result.story.id, null);
135
+ });
136
+
137
+ it('handles non-existent story file gracefully', () => {
138
+ const result = JSON.parse(runScript('init', 'nonexistent/story.md', tmpDir));
139
+
140
+ assert.strictEqual(result.story_valid, false);
141
+ assert.ok(result.story_error.includes('not found'));
142
+ });
143
+
144
+ it('returns brownfield detection fields', () => {
145
+ const result = JSON.parse(runScript('init', '', tmpDir));
146
+
147
+ assert.strictEqual(typeof result.is_brownfield, 'boolean');
148
+ assert.strictEqual(typeof result.is_greenfield, 'boolean');
149
+ assert.strictEqual(result.is_brownfield, !result.is_greenfield);
150
+ });
151
+ });
152
+
153
+ describe('resolve-model', () => {
154
+ let tmpDir;
155
+
156
+ before(() => { tmpDir = createTestProject(); });
157
+ after(() => { cleanup(tmpDir); });
158
+
159
+ it('returns a model string with --raw', () => {
160
+ const result = runScript('resolve-model', 'ace-product-owner --raw', tmpDir).trim();
161
+ assert.match(result, /^(opus|sonnet|haiku)$/);
162
+ });
163
+
164
+ it('returns JSON without --raw', () => {
165
+ const result = JSON.parse(runScript('resolve-model', 'ace-product-owner', tmpDir));
166
+ assert.ok(result.model);
167
+ assert.strictEqual(result.agent, 'ace-product-owner');
168
+ });
169
+
170
+ it('returns sonnet for unknown agent type', () => {
171
+ const result = runScript('resolve-model', 'unknown-agent --raw', tmpDir).trim();
172
+ assert.strictEqual(result, 'sonnet');
173
+ });
174
+ });
175
+
176
+ describe('update-state', () => {
177
+ let tmpDir;
178
+
179
+ before(() => { tmpDir = createTestProject(); });
180
+ after(() => { cleanup(tmpDir); });
181
+
182
+ it('updates story status in the story file', () => {
183
+ const storyContent = [
184
+ '# S1: Test Story',
185
+ '**Feature**: F1 Test Feature | **Epic**: E1 Test Epic',
186
+ '**Status**: Todo | **Size**: 3 | **Sprint**: — | **Link**: —',
187
+ ].join('\n');
188
+
189
+ const storyPath = createStoryFile(
190
+ tmpDir,
191
+ '.ace/artifacts/product/e1-test-epic/f1-test-feature/s1-test-story/s1-test-story.md',
192
+ storyContent
193
+ );
194
+
195
+ const result = JSON.parse(runScript('update-state', `story=${storyPath} status=Refined`, tmpDir));
196
+
197
+ assert.strictEqual(result.story_updated, true);
198
+ assert.strictEqual(result.new_status, 'Refined');
199
+
200
+ // Verify file was actually updated
201
+ const updated = fs.readFileSync(path.join(tmpDir, storyPath), 'utf-8');
202
+ assert.ok(updated.includes('**Status**: Refined'));
203
+ });
204
+
205
+ it('normalizes InProgress to "In Progress"', () => {
206
+ const storyContent = [
207
+ '# S2: Another Story',
208
+ '**Feature**: F1 Test Feature | **Epic**: E1 Test Epic',
209
+ '**Status**: Refined | **Size**: 2 | **Sprint**: — | **Link**: —',
210
+ ].join('\n');
211
+
212
+ const storyPath = createStoryFile(
213
+ tmpDir,
214
+ '.ace/artifacts/product/e1-test-epic/f1-test-feature/s2-another-story/s2-another-story.md',
215
+ storyContent
216
+ );
217
+
218
+ const result = JSON.parse(runScript('update-state', `story=${storyPath} status=InProgress`, tmpDir));
219
+
220
+ assert.strictEqual(result.new_status, 'In Progress');
221
+
222
+ const updated = fs.readFileSync(path.join(tmpDir, storyPath), 'utf-8');
223
+ assert.ok(updated.includes('**Status**: In Progress'));
224
+ });
225
+ });
226
+
227
+ describe('error handling', () => {
228
+ it('errors on unknown command', () => {
229
+ assert.throws(() => {
230
+ execSync(`node "${SCRIPT}" bogus`, { encoding: 'utf-8', stdio: 'pipe' });
231
+ });
232
+ });
233
+
234
+ it('errors on resolve-model without agent type', () => {
235
+ assert.throws(() => {
236
+ execSync(`node "${SCRIPT}" resolve-model`, { encoding: 'utf-8', stdio: 'pipe' });
237
+ });
238
+ });
239
+ });
240
+ });