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,231 @@
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * research-technical-solution skill script — Entry point for ace-tools operations
5
+ * needed by the research-technical-solution skill.
6
+ *
7
+ * Subcommands:
8
+ * init [story-param] Environment detection for research-technical-solution workflow
9
+ *
10
+ * Usage: node script.js <subcommand> [args] [--raw]
11
+ */
12
+
13
+ const path = require('path');
14
+
15
+ const {
16
+ loadConfig, pathExists, safeReadFile, loadSettings, resolveModel,
17
+ execCommand, output, error,
18
+ } = require('../../shared/lib/ace-core');
19
+
20
+ const {
21
+ classifyStoryParam, extractStoryMetadata, extractStoryRequirements,
22
+ extractWikiReferences,
23
+ computeStoryPaths,
24
+ } = require('../../shared/lib/ace-story');
25
+
26
+ // ─── CLI Dispatch ────────────────────────────────────────────────────────────
27
+
28
+ const cwd = process.cwd();
29
+ const args = process.argv.slice(2);
30
+ const raw = args.includes('--raw');
31
+ const cmd = args[0];
32
+
33
+ switch (cmd) {
34
+ case 'init':
35
+ cmdInit(cwd, raw, args.slice(1).filter(a => a !== '--raw').join(' ') || undefined);
36
+ break;
37
+ default:
38
+ error(`Unknown command: ${cmd}\nAvailable: init`);
39
+ }
40
+
41
+ // ─── Init: Research Story ───────────────────────────────────────────────────
42
+
43
+ /**
44
+ * Environment detection for the research-technical-solution workflow.
45
+ *
46
+ * Replicates cmdInitResearchStory from ace-tools.js:
47
+ * 1. loadConfig, detect git/gh CLI/github_project
48
+ * 2. classifyStoryParam — validate story source
49
+ * 3. Load story content (from file or GitHub)
50
+ * 4. extractStoryMetadata, extractStoryRequirements, extractWikiReferences
51
+ * 5. computeStoryPaths or derive from file location
52
+ * 6. Check artifact existence (external/integration analysis, feature file)
53
+ * 7. Verify wiki doc existence
54
+ * 8. Output JSON with all data
55
+ */
56
+ function cmdInit(cwd, raw, storyParam) {
57
+ const config = loadConfig(cwd);
58
+
59
+ // ── Environment detection ──
60
+ const has_git = pathExists(cwd, '.git');
61
+ const has_gh_cli = (() => {
62
+ try {
63
+ const { execSync } = require('child_process');
64
+ execSync('gh --version', { stdio: 'pipe' });
65
+ return true;
66
+ } catch { return false; }
67
+ })();
68
+ const github_project = (() => {
69
+ const settings = loadSettings(cwd);
70
+ return settings.github_project;
71
+ })();
72
+
73
+ // ── Classify the story parameter ──
74
+ const classified = classifyStoryParam(storyParam);
75
+
76
+ // Early exit if invalid
77
+ if (classified.type === null || classified.type === 'invalid') {
78
+ output({
79
+ analyst_model: resolveModel(cwd, 'ace-code-integration-analyst'),
80
+ mapper_model: resolveModel(cwd, 'ace-wiki-mapper'),
81
+ commit_docs: config.commit_docs,
82
+ has_git, has_gh_cli, github_project,
83
+ story_source: null,
84
+ story_valid: false,
85
+ story_error: classified.reason || 'No story parameter provided',
86
+ story: { id: null, title: null, status: null, size: null },
87
+ feature: { id: null, title: null },
88
+ epic: { id: null, title: null },
89
+ user_story: null, description: null, acceptance_criteria_count: 0,
90
+ paths: null,
91
+ has_external_analysis: false, has_integration_analysis: false, has_feature_file: false,
92
+ wiki_references: { system_wide: [], subsystem_docs: [], total_count: 0 },
93
+ wiki_docs_exist: { existing: [], missing: [] },
94
+ }, raw);
95
+ return;
96
+ }
97
+
98
+ // ── Load story content ──
99
+ let storyContent = null;
100
+ let storySource = classified.type === 'file' ? 'file' : 'github';
101
+ let storyError = null;
102
+ let storyFilePath = null;
103
+
104
+ if (classified.type === 'file') {
105
+ const resolvedPath = path.isAbsolute(classified.filePath)
106
+ ? classified.filePath
107
+ : path.join(cwd, classified.filePath);
108
+ if (!pathExists(cwd, classified.filePath)) {
109
+ storyError = `Story file not found: ${classified.filePath}`;
110
+ } else {
111
+ storyContent = safeReadFile(resolvedPath);
112
+ storyFilePath = classified.filePath;
113
+ if (!storyContent) storyError = `Could not read story file: ${classified.filePath}`;
114
+ }
115
+ } else {
116
+ // github-url or issue-number
117
+ if (!has_gh_cli) {
118
+ storyError = 'GitHub CLI (gh) not installed. Cannot fetch GitHub issues.';
119
+ } else {
120
+ const repo = classified.repo || (github_project.repo || null);
121
+ if (!repo) {
122
+ storyError = 'No repository configured. Provide a full GitHub URL or configure github_project.repo in settings.';
123
+ } else {
124
+ const ghResult = execCommand(
125
+ `gh issue view ${classified.issueNumber} --repo ${repo} --json title,body,labels,state`,
126
+ cwd
127
+ );
128
+ if (!ghResult) {
129
+ storyError = `Could not fetch GitHub issue #${classified.issueNumber} from ${repo}.`;
130
+ } else {
131
+ try {
132
+ const issue = JSON.parse(ghResult);
133
+ storyContent = issue.body || '';
134
+ if (storyContent && !storyContent.match(/^#\s+/m)) {
135
+ storyContent = `# ${issue.title}\n\n${storyContent}`;
136
+ }
137
+ } catch {
138
+ storyError = `Failed to parse GitHub issue response for #${classified.issueNumber}.`;
139
+ }
140
+ }
141
+ }
142
+ }
143
+ }
144
+
145
+ // ── Extract metadata & requirements ──
146
+ const metadata = extractStoryMetadata(storyContent);
147
+ const requirements = extractStoryRequirements(storyContent);
148
+ const wikiRefs = extractWikiReferences(storyContent);
149
+
150
+ // ── Compute paths ──
151
+ let paths = null;
152
+ if (storyFilePath) {
153
+ const resolvedPath = path.isAbsolute(storyFilePath)
154
+ ? storyFilePath
155
+ : path.join(cwd, storyFilePath);
156
+ const storyDir = path.dirname(resolvedPath);
157
+ const relStoryDir = path.relative(cwd, storyDir).replace(/\\/g, '/');
158
+ const storySlug = path.basename(storyDir);
159
+ const featureDir = path.dirname(storyDir);
160
+ const relFeatureDir = path.relative(cwd, featureDir).replace(/\\/g, '/');
161
+ const featureSlug = path.basename(featureDir);
162
+
163
+ paths = {
164
+ epic_slug: null,
165
+ feature_slug: featureSlug,
166
+ story_slug: storySlug,
167
+ story_dir: relStoryDir,
168
+ story_file: storyFilePath.replace(/\\/g, '/'),
169
+ external_analysis_file: `${relStoryDir}/external-analysis.md`,
170
+ integration_analysis_file: `${relStoryDir}/integration-analysis.md`,
171
+ feature_dir: relFeatureDir,
172
+ feature_file: `${relFeatureDir}/${featureSlug}.md`,
173
+ };
174
+ } else if (metadata.epic.id && metadata.feature.id && metadata.id) {
175
+ paths = computeStoryPaths(
176
+ metadata.epic.id, metadata.epic.title || '',
177
+ metadata.feature.id, metadata.feature.title || '',
178
+ metadata.id, metadata.title || ''
179
+ );
180
+ }
181
+
182
+ // ── Check artifact existence ──
183
+ const has_external_analysis = paths ? pathExists(cwd, paths.external_analysis_file) : false;
184
+ const has_integration_analysis = paths ? pathExists(cwd, paths.integration_analysis_file) : false;
185
+ const has_feature_file = paths ? pathExists(cwd, paths.feature_file) : false;
186
+
187
+ // ── Verify wiki doc existence ──
188
+ const allWikiPaths = [...wikiRefs.system_wide, ...wikiRefs.subsystem_docs.map(d => d.path)];
189
+ const wikiExisting = [];
190
+ const wikiMissing = [];
191
+ for (const wikiPath of allWikiPaths) {
192
+ if (pathExists(cwd, wikiPath)) {
193
+ wikiExisting.push(wikiPath);
194
+ } else {
195
+ wikiMissing.push(wikiPath);
196
+ }
197
+ }
198
+
199
+ // ── Build result ──
200
+ const result = {
201
+ analyst_model: resolveModel(cwd, 'ace-code-integration-analyst'),
202
+ mapper_model: resolveModel(cwd, 'ace-wiki-mapper'),
203
+ commit_docs: config.commit_docs,
204
+ has_git, has_gh_cli, github_project,
205
+ story_source: storySource,
206
+ story_valid: storyContent !== null && storyError === null,
207
+ story_error: storyError,
208
+ story: {
209
+ id: metadata.id,
210
+ title: metadata.title,
211
+ status: metadata.status,
212
+ size: metadata.size,
213
+ },
214
+ feature: metadata.feature,
215
+ epic: metadata.epic,
216
+ user_story: requirements.user_story,
217
+ description: requirements.description,
218
+ acceptance_criteria_count: requirements.acceptance_criteria_count,
219
+ paths,
220
+ has_external_analysis,
221
+ has_integration_analysis,
222
+ has_feature_file,
223
+ wiki_references: wikiRefs,
224
+ wiki_docs_exist: {
225
+ existing: wikiExisting,
226
+ missing: wikiMissing,
227
+ },
228
+ };
229
+
230
+ output(result, raw);
231
+ }
@@ -0,0 +1,134 @@
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('research-technical-solution 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.analyst_model, 'should have analyst_model');
104
+ assert.ok(result.mapper_model, 'should have mapper_model');
105
+ assert.strictEqual(result.story_valid, true, 'story should be valid');
106
+ assert.strictEqual(result.story_source, 'file');
107
+ assert.strictEqual(result.story.id, 'S1');
108
+ assert.strictEqual(result.story.title, 'Add Login Button');
109
+ assert.strictEqual(result.acceptance_criteria_count, 1);
110
+ assert.ok(result.paths, 'should have computed paths');
111
+ assert.ok(result.wiki_references, 'should have wiki_references');
112
+ assert.ok(result.wiki_docs_exist, 'should have wiki_docs_exist');
113
+ });
114
+
115
+ it('errors on init without story param', () => {
116
+ const result = JSON.parse(runScript('init', '', tmpDir));
117
+ assert.strictEqual(result.story_valid, false);
118
+ });
119
+
120
+ it('handles non-existent story file gracefully', () => {
121
+ const result = JSON.parse(runScript('init', 'nonexistent/story.md', tmpDir));
122
+ assert.strictEqual(result.story_valid, false);
123
+ assert.ok(result.story_error.includes('not found'));
124
+ });
125
+ });
126
+
127
+ describe('error handling', () => {
128
+ it('errors on unknown command', () => {
129
+ assert.throws(() => {
130
+ execSync(`node "${SCRIPT}" bogus`, { encoding: 'utf-8', stdio: 'pipe' });
131
+ });
132
+ });
133
+ });
134
+ });
@@ -33,12 +33,10 @@
33
33
  <step name="setup" order="1">
34
34
  **MANDATORY FIRST STEP — Execute environment detection and story initialization:**
35
35
 
36
- ```bash
37
- INIT=$(node ~/.claude/agile-context-engineering/src/ace-tools.js init research-story {story_param})
38
- ```
36
+ INIT is available from the preprocessed Environment Context above — do NOT re-run init.
39
37
 
40
- This single call validates the story parameter, extracts metadata/requirements/wiki
41
- references, computes all paths and slugs, and checks artifact existence.
38
+ This preprocessing validated the story parameter, extracted metadata/requirements/wiki
39
+ references, computed all paths and slugs, and checked artifact existence.
42
40
 
43
41
  Parse INIT JSON for:
44
42
  - **Environment**: `has_git`, `has_gh_cli`, `github_project`, `analyst_model`
@@ -0,0 +1,100 @@
1
+ ---
2
+ name: review-story
3
+ description: Standalone code review -- performs 3-level artifact verification, anti-pattern detection, coding standards enforcement, and tech debt discovery against a story's implementation
4
+ argument-hint: "story=<file-path|github-url>"
5
+ disable-model-invocation: true
6
+ allowed-tools: Read, Bash, Glob, Grep
7
+ model: sonnet
8
+ effort: high
9
+ context: fork
10
+ agent: ace-code-reviewer
11
+ ---
12
+
13
+ # Review Story
14
+
15
+ Review a story's implementation directly -- performing 3-level artifact verification, anti-pattern detection, coding standards enforcement, and tech debt discovery.
16
+
17
+ ## When to Use
18
+
19
+ - After `/ace:execute-story` -- to re-run code review after manual changes
20
+ - Anytime to review a story implementation standalone
21
+ - When a story has been implemented and needs code review
22
+ - Re-checking after manual changes post-execution
23
+ - Verifying stories implemented outside ACE
24
+ - Pre-merge quality gate
25
+
26
+ ## Input
27
+
28
+ ### Required
29
+
30
+ - **`story`** -- Story source:
31
+ - **File path**: Path to a fully-planned story markdown file (must have AC + Technical Solution sections)
32
+ - **GitHub URL or issue number**: GitHub story reference
33
+ - Must be a valid, accessible file or GitHub issue.
34
+ - The story MUST have Acceptance Criteria and Technical Solution.
35
+ - If not valid, stop and prompt the user.
36
+
37
+ ## Environment Context (preprocessed)
38
+
39
+ !`node "${CLAUDE_SKILL_DIR}/script.js" init "$ARGUMENTS" 2>/dev/null`
40
+
41
+ ## Supporting Resources
42
+
43
+ Read ALL of these before starting the workflow:
44
+
45
+ - **Workflow**: Read [workflow.xml](workflow.xml) -- complete orchestration process with all steps
46
+ - **Story template**: Read [story-template.xml](story-template.xml) -- story document structure reference
47
+ - **UI formatting**: Read `${CLAUDE_SKILL_DIR}/../../shared/utils/ui-formatting.md` -- ACE output formatting rules
48
+
49
+ ## Process
50
+
51
+ Use the `ace-code-reviewer` agent for code review.
52
+
53
+ The Environment Context above contains the preprocessed INIT JSON -- use it directly instead of running the init script manually. The workflow's step 1 setup can skip the init bash call since that data is already available.
54
+
55
+ Read all supporting resources listed above, then execute the workflow defined in [workflow.xml](workflow.xml) end-to-end.
56
+
57
+ **CRITICAL REQUIREMENTS:**
58
+ - Story MUST have Acceptance Criteria -- STOP if missing
59
+ - Story MUST have Technical Solution -- STOP if missing
60
+ - This is a READ-ONLY command -- do NOT modify any code
61
+ - Coding standards violations are BLOCKERS, not warnings
62
+ - Dead code and backwards-compatible shims must be flagged for DELETION
63
+
64
+ The review process:
65
+ 1. Load story context (AC, Technical Solution, Out of Scope)
66
+ 2. Identify changed/created files related to the story
67
+ 3. Run 3-level artifact verification (EXISTS -> SUBSTANTIVE -> WIRED)
68
+ 4. Detect anti-patterns (dead code, stubs, TODOs, hardcoded values)
69
+ 5. Enforce coding standards (mandatory, blocker-level)
70
+ 6. Check AC coverage (all Gherkin scenarios implemented)
71
+ 7. Discover pre-existing tech debt in touched files
72
+ 8. Report results with structured format
73
+
74
+ ## Artifacts
75
+
76
+ ```
77
+ No files modified -- this command is read-only.
78
+ Outputs a structured review report to the conversation.
79
+ ```
80
+
81
+ ## Example Usage
82
+
83
+ ```
84
+ # Review a story from a file path
85
+ /ace:review-story \
86
+ story=.ace/artifacts/product/e1-auth/f3-oauth/s1-buttons/s1-buttons.md
87
+
88
+ # Review from a GitHub issue
89
+ /ace:review-story \
90
+ story=https://github.com/owner/repo/issues/95
91
+
92
+ # With just an issue number
93
+ /ace:review-story story=#95
94
+ ```
95
+
96
+ ## Next Steps
97
+
98
+ - `/ace:execute-story story=...` -- Re-execute to fix reported issues
99
+ - `/ace:review-story story=...` -- Re-run review after fixes
100
+ - `/ace:help` -- Check project status