agile-context-engineering 0.5.0 → 0.5.1

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 (102) hide show
  1. package/.claude-plugin/marketplace.json +18 -0
  2. package/.claude-plugin/plugin.json +1 -1
  3. package/CHANGELOG.md +7 -1
  4. package/README.md +16 -12
  5. package/agents/ace-code-discovery-analyst.md +245 -245
  6. package/agents/ace-code-integration-analyst.md +248 -248
  7. package/agents/ace-code-reviewer.md +375 -375
  8. package/agents/ace-product-owner.md +365 -361
  9. package/agents/ace-project-researcher.md +606 -606
  10. package/agents/ace-technical-application-architect.md +315 -315
  11. package/bin/install.js +587 -173
  12. package/hooks/ace-check-update.js +15 -14
  13. package/hooks/ace-statusline.js +30 -12
  14. package/hooks/hooks.json +14 -0
  15. package/package.json +3 -2
  16. package/shared/lib/ace-core.js +53 -0
  17. package/shared/lib/ace-core.test.js +308 -308
  18. package/shared/lib/ace-story.test.js +250 -250
  19. package/skills/execute-story/SKILL.md +116 -110
  20. package/skills/execute-story/script.js +13 -27
  21. package/skills/execute-story/script.test.js +261 -261
  22. package/skills/execute-story/story-template.xml +451 -451
  23. package/skills/execute-story/workflow.xml +3 -1
  24. package/skills/help/SKILL.md +71 -69
  25. package/skills/help/script.js +32 -35
  26. package/skills/help/script.test.js +183 -183
  27. package/skills/help/workflow.xml +14 -3
  28. package/skills/init-coding-standards/SKILL.md +91 -72
  29. package/skills/init-coding-standards/coding-standards-template.xml +531 -531
  30. package/skills/init-coding-standards/script.js +50 -59
  31. package/skills/init-coding-standards/script.test.js +70 -70
  32. package/skills/init-coding-standards/workflow.xml +1 -1
  33. package/skills/map-cross-cutting/SKILL.md +126 -89
  34. package/skills/map-cross-cutting/workflow.xml +1 -1
  35. package/skills/map-guide/SKILL.md +126 -89
  36. package/skills/map-guide/workflow.xml +1 -1
  37. package/skills/map-pattern/SKILL.md +125 -89
  38. package/skills/map-pattern/workflow.xml +1 -1
  39. package/skills/map-story/SKILL.md +180 -127
  40. package/skills/map-story/templates/tech-debt-index.xml +125 -125
  41. package/skills/map-story/workflow.xml +2 -2
  42. package/skills/map-subsystem/SKILL.md +155 -111
  43. package/skills/map-subsystem/script.js +51 -60
  44. package/skills/map-subsystem/script.test.js +68 -68
  45. package/skills/map-subsystem/templates/subsystem-architecture.xml +343 -343
  46. package/skills/map-subsystem/templates/subsystem-structure.xml +234 -234
  47. package/skills/map-subsystem/workflow.xml +1173 -1173
  48. package/skills/map-sys-doc/SKILL.md +125 -90
  49. package/skills/map-sys-doc/workflow.xml +1 -1
  50. package/skills/map-system/SKILL.md +103 -85
  51. package/skills/map-system/script.js +75 -84
  52. package/skills/map-system/script.test.js +73 -73
  53. package/skills/map-system/templates/system-structure.xml +177 -177
  54. package/skills/map-system/templates/testing-framework.xml +283 -283
  55. package/skills/map-system/workflow.xml +667 -667
  56. package/skills/map-walkthrough/SKILL.md +140 -92
  57. package/skills/map-walkthrough/workflow.xml +457 -457
  58. package/skills/plan-backlog/SKILL.md +93 -75
  59. package/skills/plan-backlog/script.js +121 -136
  60. package/skills/plan-backlog/script.test.js +83 -83
  61. package/skills/plan-backlog/workflow.xml +1348 -1348
  62. package/skills/plan-feature/SKILL.md +99 -76
  63. package/skills/plan-feature/feature-template.xml +361 -361
  64. package/skills/plan-feature/script.js +131 -148
  65. package/skills/plan-feature/script.test.js +80 -80
  66. package/skills/plan-feature/workflow.xml +1 -1
  67. package/skills/plan-product-vision/SKILL.md +91 -75
  68. package/skills/plan-product-vision/product-vision-template.xml +227 -227
  69. package/skills/plan-product-vision/script.js +51 -60
  70. package/skills/plan-product-vision/script.test.js +69 -69
  71. package/skills/plan-product-vision/workflow.xml +337 -337
  72. package/skills/plan-story/SKILL.md +125 -102
  73. package/skills/plan-story/script.js +18 -49
  74. package/skills/plan-story/story-template.xml +8 -1
  75. package/skills/plan-story/workflow.xml +17 -1
  76. package/skills/research-external-solution/SKILL.md +120 -107
  77. package/skills/research-external-solution/external-solution-template.xml +832 -832
  78. package/skills/research-external-solution/script.js +229 -238
  79. package/skills/research-external-solution/script.test.js +134 -134
  80. package/skills/research-external-solution/workflow.xml +657 -657
  81. package/skills/research-integration-solution/SKILL.md +121 -98
  82. package/skills/research-integration-solution/integration-solution-template.xml +1015 -1015
  83. package/skills/research-integration-solution/script.js +223 -231
  84. package/skills/research-integration-solution/script.test.js +134 -134
  85. package/skills/research-integration-solution/workflow.xml +711 -711
  86. package/skills/research-story-wiki/SKILL.md +101 -92
  87. package/skills/research-story-wiki/script.js +223 -231
  88. package/skills/research-story-wiki/script.test.js +138 -138
  89. package/skills/research-story-wiki/story-wiki-template.xml +194 -194
  90. package/skills/research-story-wiki/workflow.xml +473 -473
  91. package/skills/research-technical-solution/SKILL.md +131 -103
  92. package/skills/research-technical-solution/script.js +223 -231
  93. package/skills/research-technical-solution/script.test.js +134 -134
  94. package/skills/research-technical-solution/technical-solution-template.xml +1025 -1025
  95. package/skills/research-technical-solution/workflow.xml +761 -761
  96. package/skills/review-story/SKILL.md +99 -100
  97. package/skills/review-story/script.js +8 -16
  98. package/skills/review-story/script.test.js +169 -169
  99. package/skills/review-story/story-template.xml +451 -451
  100. package/skills/review-story/workflow.xml +1 -1
  101. package/skills/update/SKILL.md +65 -53
  102. package/skills/update/workflow.xml +21 -5
@@ -1,238 +1,229 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * research-external-solution skill script — Entry point for ace-tools operations
5
- * needed by the research-external-solution skill.
6
- *
7
- * Subcommands:
8
- * init [story-param] Environment detection for research-external-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
- case 'verify-path-exists': {
38
- const targetPath = args.slice(1).filter(a => a !== '--raw').join(' ');
39
- if (!targetPath) error('verify-path-exists requires path argument');
40
- const exists = pathExists(cwd, targetPath);
41
- output({ exists, path: targetPath }, raw, String(exists));
42
- break;
43
- }
44
- default:
45
- error(`Unknown command: ${cmd}\nAvailable: init, verify-path-exists`);
46
- }
47
-
48
- // ─── Init: Research Story ───────────────────────────────────────────────────
49
-
50
- /**
51
- * Environment detection for the research-external-solution workflow.
52
- *
53
- * Replicates cmdInitResearchStory from ace-tools.js:
54
- * 1. loadConfig, detect git/gh CLI/github_project
55
- * 2. classifyStoryParam — validate story source
56
- * 3. Load story content (from file or GitHub)
57
- * 4. extractStoryMetadata, extractStoryRequirements, extractWikiReferences
58
- * 5. computeStoryPaths or derive from file location
59
- * 6. Check artifact existence (external/integration analysis, feature file)
60
- * 7. Verify wiki doc existence
61
- * 8. Output JSON with all data
62
- */
63
- function cmdInit(cwd, raw, storyParam) {
64
- const config = loadConfig(cwd);
65
-
66
- // ── Environment detection ──
67
- const has_git = pathExists(cwd, '.git');
68
- const has_gh_cli = (() => {
69
- try {
70
- const { execSync } = require('child_process');
71
- execSync('gh --version', { stdio: 'pipe' });
72
- return true;
73
- } catch { return false; }
74
- })();
75
- const github_project = (() => {
76
- const settings = loadSettings(cwd);
77
- return settings.github_project;
78
- })();
79
-
80
- // ── Classify the story parameter ──
81
- const classified = classifyStoryParam(storyParam);
82
-
83
- // Early exit if invalid
84
- if (classified.type === null || classified.type === 'invalid') {
85
- output({
86
- analyst_model: resolveModel(cwd, 'ace-code-integration-analyst'),
87
- mapper_model: resolveModel(cwd, 'ace-wiki-mapper'),
88
- commit_docs: config.commit_docs,
89
- has_git, has_gh_cli, github_project,
90
- story_source: null,
91
- story_valid: false,
92
- story_error: classified.reason || 'No story parameter provided',
93
- story: { id: null, title: null, status: null, size: null },
94
- feature: { id: null, title: null },
95
- epic: { id: null, title: null },
96
- user_story: null, description: null, acceptance_criteria_count: 0,
97
- paths: null,
98
- has_external_analysis: false, has_integration_analysis: false, has_feature_file: false,
99
- wiki_references: { system_wide: [], subsystem_docs: [], total_count: 0 },
100
- wiki_docs_exist: { existing: [], missing: [] },
101
- }, raw);
102
- return;
103
- }
104
-
105
- // ── Load story content ──
106
- let storyContent = null;
107
- let storySource = classified.type === 'file' ? 'file' : 'github';
108
- let storyError = null;
109
- let storyFilePath = null;
110
-
111
- if (classified.type === 'file') {
112
- const resolvedPath = path.isAbsolute(classified.filePath)
113
- ? classified.filePath
114
- : path.join(cwd, classified.filePath);
115
- if (!pathExists(cwd, classified.filePath)) {
116
- storyError = `Story file not found: ${classified.filePath}`;
117
- } else {
118
- storyContent = safeReadFile(resolvedPath);
119
- storyFilePath = classified.filePath;
120
- if (!storyContent) storyError = `Could not read story file: ${classified.filePath}`;
121
- }
122
- } else {
123
- // github-url or issue-number
124
- if (!has_gh_cli) {
125
- storyError = 'GitHub CLI (gh) not installed. Cannot fetch GitHub issues.';
126
- } else {
127
- const repo = classified.repo || (github_project.repo || null);
128
- if (!repo) {
129
- storyError = 'No repository configured. Provide a full GitHub URL or configure github_project.repo in settings.';
130
- } else {
131
- const ghResult = execCommand(
132
- `gh issue view ${classified.issueNumber} --repo ${repo} --json title,body,labels,state`,
133
- cwd
134
- );
135
- if (!ghResult) {
136
- storyError = `Could not fetch GitHub issue #${classified.issueNumber} from ${repo}.`;
137
- } else {
138
- try {
139
- const issue = JSON.parse(ghResult);
140
- storyContent = issue.body || '';
141
- if (storyContent && !storyContent.match(/^#\s+/m)) {
142
- storyContent = `# ${issue.title}\n\n${storyContent}`;
143
- }
144
- } catch {
145
- storyError = `Failed to parse GitHub issue response for #${classified.issueNumber}.`;
146
- }
147
- }
148
- }
149
- }
150
- }
151
-
152
- // ── Extract metadata & requirements ──
153
- const metadata = extractStoryMetadata(storyContent);
154
- const requirements = extractStoryRequirements(storyContent);
155
- const wikiRefs = extractWikiReferences(storyContent);
156
-
157
- // ── Compute paths ──
158
- let paths = null;
159
- if (storyFilePath) {
160
- const resolvedPath = path.isAbsolute(storyFilePath)
161
- ? storyFilePath
162
- : path.join(cwd, storyFilePath);
163
- const storyDir = path.dirname(resolvedPath);
164
- const relStoryDir = path.relative(cwd, storyDir).replace(/\\/g, '/');
165
- const storySlug = path.basename(storyDir);
166
- const featureDir = path.dirname(storyDir);
167
- const relFeatureDir = path.relative(cwd, featureDir).replace(/\\/g, '/');
168
- const featureSlug = path.basename(featureDir);
169
-
170
- paths = {
171
- epic_slug: null,
172
- feature_slug: featureSlug,
173
- story_slug: storySlug,
174
- story_dir: relStoryDir,
175
- story_file: storyFilePath.replace(/\\/g, '/'),
176
- external_analysis_file: `${relStoryDir}/external-analysis.md`,
177
- integration_analysis_file: `${relStoryDir}/integration-analysis.md`,
178
- feature_dir: relFeatureDir,
179
- feature_file: `${relFeatureDir}/${featureSlug}.md`,
180
- };
181
- } else if (metadata.epic.id && metadata.feature.id && metadata.id) {
182
- paths = computeStoryPaths(
183
- metadata.epic.id, metadata.epic.title || '',
184
- metadata.feature.id, metadata.feature.title || '',
185
- metadata.id, metadata.title || ''
186
- );
187
- }
188
-
189
- // ── Check artifact existence ──
190
- const has_external_analysis = paths ? pathExists(cwd, paths.external_analysis_file) : false;
191
- const has_integration_analysis = paths ? pathExists(cwd, paths.integration_analysis_file) : false;
192
- const has_feature_file = paths ? pathExists(cwd, paths.feature_file) : false;
193
-
194
- // ── Verify wiki doc existence ──
195
- const allWikiPaths = [...wikiRefs.system_wide, ...wikiRefs.subsystem_docs.map(d => d.path)];
196
- const wikiExisting = [];
197
- const wikiMissing = [];
198
- for (const wikiPath of allWikiPaths) {
199
- if (pathExists(cwd, wikiPath)) {
200
- wikiExisting.push(wikiPath);
201
- } else {
202
- wikiMissing.push(wikiPath);
203
- }
204
- }
205
-
206
- // ── Build result ──
207
- const result = {
208
- analyst_model: resolveModel(cwd, 'ace-code-integration-analyst'),
209
- mapper_model: resolveModel(cwd, 'ace-wiki-mapper'),
210
- commit_docs: config.commit_docs,
211
- has_git, has_gh_cli, github_project,
212
- story_source: storySource,
213
- story_valid: storyContent !== null && storyError === null,
214
- story_error: storyError,
215
- story: {
216
- id: metadata.id,
217
- title: metadata.title,
218
- status: metadata.status,
219
- size: metadata.size,
220
- },
221
- feature: metadata.feature,
222
- epic: metadata.epic,
223
- user_story: requirements.user_story,
224
- description: requirements.description,
225
- acceptance_criteria_count: requirements.acceptance_criteria_count,
226
- paths,
227
- has_external_analysis,
228
- has_integration_analysis,
229
- has_feature_file,
230
- wiki_references: wikiRefs,
231
- wiki_docs_exist: {
232
- existing: wikiExisting,
233
- missing: wikiMissing,
234
- },
235
- };
236
-
237
- output(result, raw);
238
- }
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * research-external-solution skill script — Entry point for ace-tools operations
5
+ * needed by the research-external-solution skill.
6
+ *
7
+ * Subcommands:
8
+ * init [story-param] Environment detection for research-external-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, runSkillScript,
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
+ runSkillScript({
29
+ init: cmdInit,
30
+ 'verify-path-exists': (cwd, raw, args, parsed) => {
31
+ const targetPath = parsed._positional || args.join(' ');
32
+ if (!targetPath) error('verify-path-exists requires path argument');
33
+ const exists = pathExists(cwd, targetPath);
34
+ output({ exists, path: targetPath }, raw, String(exists));
35
+ },
36
+ });
37
+
38
+ // ─── Init: Research Story ───────────────────────────────────────────────────
39
+
40
+ /**
41
+ * Environment detection for the research-external-solution workflow.
42
+ *
43
+ * Replicates cmdInitResearchStory from ace-tools.js:
44
+ * 1. loadConfig, detect git/gh CLI/github_project
45
+ * 2. classifyStoryParam — validate story source
46
+ * 3. Load story content (from file or GitHub)
47
+ * 4. extractStoryMetadata, extractStoryRequirements, extractWikiReferences
48
+ * 5. computeStoryPaths or derive from file location
49
+ * 6. Check artifact existence (external/integration analysis, feature file)
50
+ * 7. Verify wiki doc existence
51
+ * 8. Output JSON with all data
52
+ */
53
+ function cmdInit(cwd, raw, args, parsed) {
54
+ const storyParam = parsed.story || parsed._positional || null;
55
+ const config = loadConfig(cwd);
56
+
57
+ // ── Environment detection ──
58
+ const has_git = pathExists(cwd, '.git');
59
+ const has_gh_cli = (() => {
60
+ try {
61
+ const { execSync } = require('child_process');
62
+ execSync('gh --version', { stdio: 'pipe' });
63
+ return true;
64
+ } catch { return false; }
65
+ })();
66
+ const github_project = (() => {
67
+ const settings = loadSettings(cwd);
68
+ return settings.github_project;
69
+ })();
70
+
71
+ // ── Classify the story parameter ──
72
+ const classified = classifyStoryParam(storyParam);
73
+
74
+ // Early exit if invalid
75
+ if (classified.type === null || classified.type === 'invalid') {
76
+ output({
77
+ analyst_model: resolveModel(cwd, 'ace-code-integration-analyst'),
78
+ mapper_model: resolveModel(cwd, 'ace-wiki-mapper'),
79
+ commit_docs: config.commit_docs,
80
+ has_git, has_gh_cli, github_project,
81
+ story_source: null,
82
+ story_valid: false,
83
+ story_error: classified.reason || 'No story parameter provided',
84
+ story: { id: null, title: null, status: null, size: null },
85
+ feature: { id: null, title: null },
86
+ epic: { id: null, title: null },
87
+ user_story: null, description: null, acceptance_criteria_count: 0,
88
+ paths: null,
89
+ has_external_analysis: false, has_integration_analysis: false, has_feature_file: false,
90
+ wiki_references: { system_wide: [], subsystem_docs: [], total_count: 0 },
91
+ wiki_docs_exist: { existing: [], missing: [] },
92
+ }, raw);
93
+ return;
94
+ }
95
+
96
+ // ── Load story content ──
97
+ let storyContent = null;
98
+ let storySource = classified.type === 'file' ? 'file' : 'github';
99
+ let storyError = null;
100
+ let storyFilePath = null;
101
+
102
+ if (classified.type === 'file') {
103
+ const resolvedPath = path.isAbsolute(classified.filePath)
104
+ ? classified.filePath
105
+ : path.join(cwd, classified.filePath);
106
+ if (!pathExists(cwd, classified.filePath)) {
107
+ storyError = `Story file not found: ${classified.filePath}`;
108
+ } else {
109
+ storyContent = safeReadFile(resolvedPath);
110
+ storyFilePath = classified.filePath;
111
+ if (!storyContent) storyError = `Could not read story file: ${classified.filePath}`;
112
+ }
113
+ } else {
114
+ // github-url or issue-number
115
+ if (!has_gh_cli) {
116
+ storyError = 'GitHub CLI (gh) not installed. Cannot fetch GitHub issues.';
117
+ } else {
118
+ const repo = classified.repo || (github_project.repo || null);
119
+ if (!repo) {
120
+ storyError = 'No repository configured. Provide a full GitHub URL or configure github_project.repo in settings.';
121
+ } else {
122
+ const ghResult = execCommand(
123
+ `gh issue view ${classified.issueNumber} --repo ${repo} --json title,body,labels,state`,
124
+ cwd
125
+ );
126
+ if (!ghResult) {
127
+ storyError = `Could not fetch GitHub issue #${classified.issueNumber} from ${repo}.`;
128
+ } else {
129
+ try {
130
+ const issue = JSON.parse(ghResult);
131
+ storyContent = issue.body || '';
132
+ if (storyContent && !storyContent.match(/^#\s+/m)) {
133
+ storyContent = `# ${issue.title}\n\n${storyContent}`;
134
+ }
135
+ } catch {
136
+ storyError = `Failed to parse GitHub issue response for #${classified.issueNumber}.`;
137
+ }
138
+ }
139
+ }
140
+ }
141
+ }
142
+
143
+ // ── Extract metadata & requirements ──
144
+ const metadata = extractStoryMetadata(storyContent);
145
+ const requirements = extractStoryRequirements(storyContent);
146
+ const wikiRefs = extractWikiReferences(storyContent);
147
+
148
+ // ── Compute paths ──
149
+ let paths = null;
150
+ if (storyFilePath) {
151
+ const resolvedPath = path.isAbsolute(storyFilePath)
152
+ ? storyFilePath
153
+ : path.join(cwd, storyFilePath);
154
+ const storyDir = path.dirname(resolvedPath);
155
+ const relStoryDir = path.relative(cwd, storyDir).replace(/\\/g, '/');
156
+ const storySlug = path.basename(storyDir);
157
+ const featureDir = path.dirname(storyDir);
158
+ const relFeatureDir = path.relative(cwd, featureDir).replace(/\\/g, '/');
159
+ const featureSlug = path.basename(featureDir);
160
+
161
+ paths = {
162
+ epic_slug: null,
163
+ feature_slug: featureSlug,
164
+ story_slug: storySlug,
165
+ story_dir: relStoryDir,
166
+ story_file: storyFilePath.replace(/\\/g, '/'),
167
+ external_analysis_file: `${relStoryDir}/external-analysis.md`,
168
+ integration_analysis_file: `${relStoryDir}/integration-analysis.md`,
169
+ feature_dir: relFeatureDir,
170
+ feature_file: `${relFeatureDir}/${featureSlug}.md`,
171
+ };
172
+ } else if (metadata.epic.id && metadata.feature.id && metadata.id) {
173
+ paths = computeStoryPaths(
174
+ metadata.epic.id, metadata.epic.title || '',
175
+ metadata.feature.id, metadata.feature.title || '',
176
+ metadata.id, metadata.title || ''
177
+ );
178
+ }
179
+
180
+ // ── Check artifact existence ──
181
+ const has_external_analysis = paths ? pathExists(cwd, paths.external_analysis_file) : false;
182
+ const has_integration_analysis = paths ? pathExists(cwd, paths.integration_analysis_file) : false;
183
+ const has_feature_file = paths ? pathExists(cwd, paths.feature_file) : false;
184
+
185
+ // ── Verify wiki doc existence ──
186
+ const allWikiPaths = [...wikiRefs.system_wide, ...wikiRefs.subsystem_docs.map(d => d.path)];
187
+ const wikiExisting = [];
188
+ const wikiMissing = [];
189
+ for (const wikiPath of allWikiPaths) {
190
+ if (pathExists(cwd, wikiPath)) {
191
+ wikiExisting.push(wikiPath);
192
+ } else {
193
+ wikiMissing.push(wikiPath);
194
+ }
195
+ }
196
+
197
+ // ── Build result ──
198
+ const result = {
199
+ analyst_model: resolveModel(cwd, 'ace-code-integration-analyst'),
200
+ mapper_model: resolveModel(cwd, 'ace-wiki-mapper'),
201
+ commit_docs: config.commit_docs,
202
+ has_git, has_gh_cli, github_project,
203
+ story_source: storySource,
204
+ story_valid: storyContent !== null && storyError === null,
205
+ story_error: storyError,
206
+ story: {
207
+ id: metadata.id,
208
+ title: metadata.title,
209
+ status: metadata.status,
210
+ size: metadata.size,
211
+ },
212
+ feature: metadata.feature,
213
+ epic: metadata.epic,
214
+ user_story: requirements.user_story,
215
+ description: requirements.description,
216
+ acceptance_criteria_count: requirements.acceptance_criteria_count,
217
+ paths,
218
+ has_external_analysis,
219
+ has_integration_analysis,
220
+ has_feature_file,
221
+ wiki_references: wikiRefs,
222
+ wiki_docs_exist: {
223
+ existing: wikiExisting,
224
+ missing: wikiMissing,
225
+ },
226
+ };
227
+
228
+ output(result, raw);
229
+ }