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,231 +1,223 @@
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
- }
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, 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
+ });
31
+
32
+ // ─── Init: Research Story ───────────────────────────────────────────────────
33
+
34
+ /**
35
+ * Environment detection for the research-technical-solution workflow.
36
+ *
37
+ * Replicates cmdInitResearchStory from ace-tools.js:
38
+ * 1. loadConfig, detect git/gh CLI/github_project
39
+ * 2. classifyStoryParam — validate story source
40
+ * 3. Load story content (from file or GitHub)
41
+ * 4. extractStoryMetadata, extractStoryRequirements, extractWikiReferences
42
+ * 5. computeStoryPaths or derive from file location
43
+ * 6. Check artifact existence (external/integration analysis, feature file)
44
+ * 7. Verify wiki doc existence
45
+ * 8. Output JSON with all data
46
+ */
47
+ function cmdInit(cwd, raw, args, parsed) {
48
+ const storyParam = parsed.story || parsed._positional || null;
49
+ const config = loadConfig(cwd);
50
+
51
+ // ── Environment detection ──
52
+ const has_git = pathExists(cwd, '.git');
53
+ const has_gh_cli = (() => {
54
+ try {
55
+ const { execSync } = require('child_process');
56
+ execSync('gh --version', { stdio: 'pipe' });
57
+ return true;
58
+ } catch { return false; }
59
+ })();
60
+ const github_project = (() => {
61
+ const settings = loadSettings(cwd);
62
+ return settings.github_project;
63
+ })();
64
+
65
+ // ── Classify the story parameter ──
66
+ const classified = classifyStoryParam(storyParam);
67
+
68
+ // Early exit if invalid
69
+ if (classified.type === null || classified.type === 'invalid') {
70
+ output({
71
+ analyst_model: resolveModel(cwd, 'ace-code-integration-analyst'),
72
+ mapper_model: resolveModel(cwd, 'ace-wiki-mapper'),
73
+ commit_docs: config.commit_docs,
74
+ has_git, has_gh_cli, github_project,
75
+ story_source: null,
76
+ story_valid: false,
77
+ story_error: classified.reason || 'No story parameter provided',
78
+ story: { id: null, title: null, status: null, size: null },
79
+ feature: { id: null, title: null },
80
+ epic: { id: null, title: null },
81
+ user_story: null, description: null, acceptance_criteria_count: 0,
82
+ paths: null,
83
+ has_external_analysis: false, has_integration_analysis: false, has_feature_file: false,
84
+ wiki_references: { system_wide: [], subsystem_docs: [], total_count: 0 },
85
+ wiki_docs_exist: { existing: [], missing: [] },
86
+ }, raw);
87
+ return;
88
+ }
89
+
90
+ // ── Load story content ──
91
+ let storyContent = null;
92
+ let storySource = classified.type === 'file' ? 'file' : 'github';
93
+ let storyError = null;
94
+ let storyFilePath = null;
95
+
96
+ if (classified.type === 'file') {
97
+ const resolvedPath = path.isAbsolute(classified.filePath)
98
+ ? classified.filePath
99
+ : path.join(cwd, classified.filePath);
100
+ if (!pathExists(cwd, classified.filePath)) {
101
+ storyError = `Story file not found: ${classified.filePath}`;
102
+ } else {
103
+ storyContent = safeReadFile(resolvedPath);
104
+ storyFilePath = classified.filePath;
105
+ if (!storyContent) storyError = `Could not read story file: ${classified.filePath}`;
106
+ }
107
+ } else {
108
+ // github-url or issue-number
109
+ if (!has_gh_cli) {
110
+ storyError = 'GitHub CLI (gh) not installed. Cannot fetch GitHub issues.';
111
+ } else {
112
+ const repo = classified.repo || (github_project.repo || null);
113
+ if (!repo) {
114
+ storyError = 'No repository configured. Provide a full GitHub URL or configure github_project.repo in settings.';
115
+ } else {
116
+ const ghResult = execCommand(
117
+ `gh issue view ${classified.issueNumber} --repo ${repo} --json title,body,labels,state`,
118
+ cwd
119
+ );
120
+ if (!ghResult) {
121
+ storyError = `Could not fetch GitHub issue #${classified.issueNumber} from ${repo}.`;
122
+ } else {
123
+ try {
124
+ const issue = JSON.parse(ghResult);
125
+ storyContent = issue.body || '';
126
+ if (storyContent && !storyContent.match(/^#\s+/m)) {
127
+ storyContent = `# ${issue.title}\n\n${storyContent}`;
128
+ }
129
+ } catch {
130
+ storyError = `Failed to parse GitHub issue response for #${classified.issueNumber}.`;
131
+ }
132
+ }
133
+ }
134
+ }
135
+ }
136
+
137
+ // ── Extract metadata & requirements ──
138
+ const metadata = extractStoryMetadata(storyContent);
139
+ const requirements = extractStoryRequirements(storyContent);
140
+ const wikiRefs = extractWikiReferences(storyContent);
141
+
142
+ // ── Compute paths ──
143
+ let paths = null;
144
+ if (storyFilePath) {
145
+ const resolvedPath = path.isAbsolute(storyFilePath)
146
+ ? storyFilePath
147
+ : path.join(cwd, storyFilePath);
148
+ const storyDir = path.dirname(resolvedPath);
149
+ const relStoryDir = path.relative(cwd, storyDir).replace(/\\/g, '/');
150
+ const storySlug = path.basename(storyDir);
151
+ const featureDir = path.dirname(storyDir);
152
+ const relFeatureDir = path.relative(cwd, featureDir).replace(/\\/g, '/');
153
+ const featureSlug = path.basename(featureDir);
154
+
155
+ paths = {
156
+ epic_slug: null,
157
+ feature_slug: featureSlug,
158
+ story_slug: storySlug,
159
+ story_dir: relStoryDir,
160
+ story_file: storyFilePath.replace(/\\/g, '/'),
161
+ external_analysis_file: `${relStoryDir}/external-analysis.md`,
162
+ integration_analysis_file: `${relStoryDir}/integration-analysis.md`,
163
+ feature_dir: relFeatureDir,
164
+ feature_file: `${relFeatureDir}/${featureSlug}.md`,
165
+ };
166
+ } else if (metadata.epic.id && metadata.feature.id && metadata.id) {
167
+ paths = computeStoryPaths(
168
+ metadata.epic.id, metadata.epic.title || '',
169
+ metadata.feature.id, metadata.feature.title || '',
170
+ metadata.id, metadata.title || ''
171
+ );
172
+ }
173
+
174
+ // ── Check artifact existence ──
175
+ const has_external_analysis = paths ? pathExists(cwd, paths.external_analysis_file) : false;
176
+ const has_integration_analysis = paths ? pathExists(cwd, paths.integration_analysis_file) : false;
177
+ const has_feature_file = paths ? pathExists(cwd, paths.feature_file) : false;
178
+
179
+ // ── Verify wiki doc existence ──
180
+ const allWikiPaths = [...wikiRefs.system_wide, ...wikiRefs.subsystem_docs.map(d => d.path)];
181
+ const wikiExisting = [];
182
+ const wikiMissing = [];
183
+ for (const wikiPath of allWikiPaths) {
184
+ if (pathExists(cwd, wikiPath)) {
185
+ wikiExisting.push(wikiPath);
186
+ } else {
187
+ wikiMissing.push(wikiPath);
188
+ }
189
+ }
190
+
191
+ // ── Build result ──
192
+ const result = {
193
+ analyst_model: resolveModel(cwd, 'ace-code-integration-analyst'),
194
+ mapper_model: resolveModel(cwd, 'ace-wiki-mapper'),
195
+ commit_docs: config.commit_docs,
196
+ has_git, has_gh_cli, github_project,
197
+ story_source: storySource,
198
+ story_valid: storyContent !== null && storyError === null,
199
+ story_error: storyError,
200
+ story: {
201
+ id: metadata.id,
202
+ title: metadata.title,
203
+ status: metadata.status,
204
+ size: metadata.size,
205
+ },
206
+ feature: metadata.feature,
207
+ epic: metadata.epic,
208
+ user_story: requirements.user_story,
209
+ description: requirements.description,
210
+ acceptance_criteria_count: requirements.acceptance_criteria_count,
211
+ paths,
212
+ has_external_analysis,
213
+ has_integration_analysis,
214
+ has_feature_file,
215
+ wiki_references: wikiRefs,
216
+ wiki_docs_exist: {
217
+ existing: wikiExisting,
218
+ missing: wikiMissing,
219
+ },
220
+ };
221
+
222
+ output(result, raw);
223
+ }