agile-context-engineering 0.3.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 (139) hide show
  1. package/.claude-plugin/marketplace.json +18 -0
  2. package/.claude-plugin/plugin.json +10 -0
  3. package/CHANGELOG.md +7 -1
  4. package/LICENSE +51 -51
  5. package/README.md +330 -318
  6. package/agents/ace-code-discovery-analyst.md +245 -245
  7. package/agents/ace-code-integration-analyst.md +248 -248
  8. package/agents/ace-code-reviewer.md +375 -375
  9. package/agents/ace-product-owner.md +365 -361
  10. package/agents/ace-project-researcher.md +606 -606
  11. package/agents/ace-research-synthesizer.md +228 -228
  12. package/agents/ace-technical-application-architect.md +315 -315
  13. package/agents/ace-wiki-mapper.md +449 -445
  14. package/bin/install.js +605 -195
  15. package/hooks/ace-check-update.js +71 -62
  16. package/hooks/ace-statusline.js +107 -89
  17. package/hooks/hooks.json +14 -0
  18. package/package.json +7 -5
  19. package/shared/lib/ace-core.js +361 -0
  20. package/shared/lib/ace-core.test.js +308 -0
  21. package/shared/lib/ace-github.js +753 -0
  22. package/shared/lib/ace-story.js +400 -0
  23. package/shared/lib/ace-story.test.js +250 -0
  24. package/{agile-context-engineering → shared}/utils/questioning.xml +110 -110
  25. package/{agile-context-engineering → shared}/utils/ui-formatting.md +299 -299
  26. package/{commands/ace/execute-story.md → skills/execute-story/SKILL.md} +116 -138
  27. package/skills/execute-story/script.js +291 -0
  28. package/skills/execute-story/script.test.js +261 -0
  29. package/{agile-context-engineering/templates/product/story.xml → skills/execute-story/story-template.xml} +451 -451
  30. package/skills/execute-story/walkthrough-template.xml +255 -0
  31. package/{agile-context-engineering/workflows/execute-story.xml → skills/execute-story/workflow.xml} +1221 -1219
  32. package/skills/help/SKILL.md +71 -0
  33. package/skills/help/script.js +315 -0
  34. package/skills/help/script.test.js +183 -0
  35. package/{agile-context-engineering/workflows/help.xml → skills/help/workflow.xml} +544 -533
  36. package/{commands/ace/init-coding-standards.md → skills/init-coding-standards/SKILL.md} +91 -83
  37. package/{agile-context-engineering/templates/wiki/coding-standards.xml → skills/init-coding-standards/coding-standards-template.xml} +531 -531
  38. package/skills/init-coding-standards/script.js +50 -0
  39. package/skills/init-coding-standards/script.test.js +70 -0
  40. package/{agile-context-engineering/workflows/init-coding-standards.xml → skills/init-coding-standards/workflow.xml} +381 -386
  41. package/skills/map-cross-cutting/SKILL.md +126 -0
  42. package/{agile-context-engineering/templates/wiki → skills/map-cross-cutting}/system-cross-cutting.xml +197 -197
  43. package/skills/map-cross-cutting/workflow.xml +330 -0
  44. package/skills/map-guide/SKILL.md +126 -0
  45. package/{agile-context-engineering/templates/wiki → skills/map-guide}/guide.xml +137 -137
  46. package/skills/map-guide/workflow.xml +320 -0
  47. package/skills/map-pattern/SKILL.md +125 -0
  48. package/{agile-context-engineering/templates/wiki → skills/map-pattern}/pattern.xml +159 -159
  49. package/skills/map-pattern/workflow.xml +331 -0
  50. package/{commands/ace/map-story.md → skills/map-story/SKILL.md} +180 -165
  51. package/{agile-context-engineering/templates/wiki → skills/map-story/templates}/decizions.xml +115 -115
  52. package/skills/map-story/templates/guide.xml +137 -0
  53. package/skills/map-story/templates/pattern.xml +159 -0
  54. package/skills/map-story/templates/system-cross-cutting.xml +197 -0
  55. package/{agile-context-engineering/templates/wiki → skills/map-story/templates}/system.xml +381 -381
  56. package/{agile-context-engineering/templates/wiki → skills/map-story/templates}/tech-debt-index.xml +125 -125
  57. package/{agile-context-engineering/templates/wiki → skills/map-story/templates}/walkthrough.xml +255 -255
  58. package/{agile-context-engineering/workflows/map-story.xml → skills/map-story/workflow.xml} +1046 -1046
  59. package/{commands/ace/map-subsystem.md → skills/map-subsystem/SKILL.md} +155 -140
  60. package/skills/map-subsystem/script.js +51 -0
  61. package/skills/map-subsystem/script.test.js +68 -0
  62. package/skills/map-subsystem/templates/decizions.xml +115 -0
  63. package/skills/map-subsystem/templates/guide.xml +137 -0
  64. package/{agile-context-engineering/templates/wiki → skills/map-subsystem/templates}/module-discovery.xml +174 -174
  65. package/skills/map-subsystem/templates/pattern.xml +159 -0
  66. package/{agile-context-engineering/templates/wiki → skills/map-subsystem/templates}/subsystem-architecture.xml +343 -343
  67. package/{agile-context-engineering/templates/wiki → skills/map-subsystem/templates}/subsystem-structure.xml +234 -234
  68. package/skills/map-subsystem/templates/system-cross-cutting.xml +197 -0
  69. package/skills/map-subsystem/templates/system.xml +381 -0
  70. package/skills/map-subsystem/templates/walkthrough.xml +255 -0
  71. package/{agile-context-engineering/workflows/map-subsystem.xml → skills/map-subsystem/workflow.xml} +1173 -1178
  72. package/skills/map-sys-doc/SKILL.md +125 -0
  73. package/skills/map-sys-doc/system.xml +381 -0
  74. package/skills/map-sys-doc/workflow.xml +336 -0
  75. package/{commands/ace/map-system.md → skills/map-system/SKILL.md} +103 -92
  76. package/skills/map-system/script.js +75 -0
  77. package/skills/map-system/script.test.js +73 -0
  78. package/{agile-context-engineering/templates/wiki → skills/map-system/templates}/system-architecture.xml +254 -254
  79. package/{agile-context-engineering/templates/wiki → skills/map-system/templates}/system-structure.xml +177 -177
  80. package/{agile-context-engineering/templates/wiki → skills/map-system/templates}/testing-framework.xml +283 -283
  81. package/{agile-context-engineering/templates/wiki → skills/map-system/templates}/wiki-readme.xml +296 -296
  82. package/{agile-context-engineering/workflows/map-system.xml → skills/map-system/workflow.xml} +667 -672
  83. package/{commands/ace/map-walkthrough.md → skills/map-walkthrough/SKILL.md} +140 -127
  84. package/skills/map-walkthrough/walkthrough.xml +255 -0
  85. package/{agile-context-engineering/workflows/map-walkthrough.xml → skills/map-walkthrough/workflow.xml} +457 -457
  86. package/{commands/ace/plan-backlog.md → skills/plan-backlog/SKILL.md} +93 -83
  87. package/{agile-context-engineering/templates/product/product-backlog.xml → skills/plan-backlog/product-backlog-template.xml} +231 -231
  88. package/skills/plan-backlog/script.js +121 -0
  89. package/skills/plan-backlog/script.test.js +83 -0
  90. package/{agile-context-engineering/workflows/plan-backlog.xml → skills/plan-backlog/workflow.xml} +1348 -1356
  91. package/{commands/ace/plan-feature.md → skills/plan-feature/SKILL.md} +99 -89
  92. package/{agile-context-engineering/templates/product/feature.xml → skills/plan-feature/feature-template.xml} +361 -361
  93. package/skills/plan-feature/script.js +131 -0
  94. package/skills/plan-feature/script.test.js +80 -0
  95. package/{agile-context-engineering/workflows/plan-feature.xml → skills/plan-feature/workflow.xml} +1487 -1495
  96. package/{commands/ace/plan-product-vision.md → skills/plan-product-vision/SKILL.md} +91 -81
  97. package/{agile-context-engineering/templates/product/product-vision.xml → skills/plan-product-vision/product-vision-template.xml} +227 -227
  98. package/skills/plan-product-vision/script.js +51 -0
  99. package/skills/plan-product-vision/script.test.js +69 -0
  100. package/{agile-context-engineering/workflows/plan-product-vision.xml → skills/plan-product-vision/workflow.xml} +337 -342
  101. package/{commands/ace/plan-story.md → skills/plan-story/SKILL.md} +139 -159
  102. package/skills/plan-story/script.js +295 -0
  103. package/skills/plan-story/script.test.js +240 -0
  104. package/skills/plan-story/story-template.xml +458 -0
  105. package/{agile-context-engineering/workflows/plan-story.xml → skills/plan-story/workflow.xml} +1301 -944
  106. package/{commands/ace/research-external-solution.md → skills/research-external-solution/SKILL.md} +120 -138
  107. package/{agile-context-engineering/templates/product/external-solution.xml → skills/research-external-solution/external-solution-template.xml} +832 -832
  108. package/skills/research-external-solution/script.js +229 -0
  109. package/skills/research-external-solution/script.test.js +134 -0
  110. package/{agile-context-engineering/workflows/research-external-solution.xml → skills/research-external-solution/workflow.xml} +657 -659
  111. package/{commands/ace/research-integration-solution.md → skills/research-integration-solution/SKILL.md} +121 -135
  112. package/{agile-context-engineering/templates/product/story-integration-solution.xml → skills/research-integration-solution/integration-solution-template.xml} +1015 -1015
  113. package/skills/research-integration-solution/script.js +223 -0
  114. package/skills/research-integration-solution/script.test.js +134 -0
  115. package/{agile-context-engineering/workflows/research-integration-solution.xml → skills/research-integration-solution/workflow.xml} +711 -713
  116. package/{commands/ace/research-story-wiki.md → skills/research-story-wiki/SKILL.md} +101 -116
  117. package/skills/research-story-wiki/script.js +223 -0
  118. package/skills/research-story-wiki/script.test.js +138 -0
  119. package/{agile-context-engineering/templates/product/story-wiki.xml → skills/research-story-wiki/story-wiki-template.xml} +194 -194
  120. package/{agile-context-engineering/workflows/research-story-wiki.xml → skills/research-story-wiki/workflow.xml} +473 -475
  121. package/{commands/ace/research-technical-solution.md → skills/research-technical-solution/SKILL.md} +131 -147
  122. package/skills/research-technical-solution/script.js +223 -0
  123. package/skills/research-technical-solution/script.test.js +134 -0
  124. package/{agile-context-engineering/templates/product/story-technical-solution.xml → skills/research-technical-solution/technical-solution-template.xml} +1025 -1025
  125. package/{agile-context-engineering/workflows/research-technical-solution.xml → skills/research-technical-solution/workflow.xml} +761 -763
  126. package/{commands/ace/review-story.md → skills/review-story/SKILL.md} +99 -109
  127. package/skills/review-story/script.js +249 -0
  128. package/skills/review-story/script.test.js +169 -0
  129. package/skills/review-story/story-template.xml +451 -0
  130. package/{agile-context-engineering/workflows/review-story.xml → skills/review-story/workflow.xml} +279 -281
  131. package/{commands/ace/update.md → skills/update/SKILL.md} +65 -56
  132. package/{agile-context-engineering/workflows/update.xml → skills/update/workflow.xml} +33 -18
  133. package/agile-context-engineering/src/ace-tools.js +0 -2881
  134. package/agile-context-engineering/src/ace-tools.test.js +0 -1089
  135. package/agile-context-engineering/templates/_command.md +0 -54
  136. package/agile-context-engineering/templates/_workflow.xml +0 -17
  137. package/agile-context-engineering/templates/config.json +0 -0
  138. package/agile-context-engineering/templates/product/integration-solution.xml +0 -0
  139. package/commands/ace/help.md +0 -93
@@ -1,147 +1,131 @@
1
- ---
2
- name: ace:research-technical-solution
3
- description: COMPREHENSIVE Technical Solution Design for a Story Architecture, Patterns, Algorithms, Sequence Diagrams, and Implementation Plan
4
- argument-hint: "story=<file-path|github-url>"
5
- allowed-tools:
6
- - Read
7
- - Bash
8
- - Write
9
- - Edit
10
- - AskUserQuestion
11
- - Glob
12
- - Grep
13
- - Agent
14
- ---
15
-
16
- ```xml
17
- <command>
18
-
19
- <execution-time>
20
- <runs-after>
21
- <trigger>After /ace:plan-story — once story requirements (pass 1-2) are complete</trigger>
22
- <trigger>After /ace:research-integration-solution — integration analysis (pass 4) MUST exist</trigger>
23
- <trigger>Optionally after /ace:research-external-solution — external analysis (pass 3) if applicable</trigger>
24
- </runs-after>
25
- <use-when>
26
- <condition>Story requirements, wiki references, and integration analysis are available (passes 1-4 complete)</condition>
27
- <condition>Need to design a concrete technical solution for the story</condition>
28
- <condition>Want a detailed implementation blueprint with class diagrams, sequence diagrams, algorithms, and file structure</condition>
29
- <condition>Need a comprehensive technical design to guide AI agents implementing the story</condition>
30
- </use-when>
31
- </execution-time>
32
-
33
- <input>
34
- <flags>
35
- </flags>
36
-
37
- <parameters>
38
- <required>
39
- <param name="story" type="file | github-url">
40
- Story source — can be either:
41
- - **File path**: Path to a markdown file containing the story (from plan-story command)
42
- - **GitHub URL or issue number**: GitHub story reference
43
- Must be a valid, accessible file or GitHub issue.
44
- Contains the user story, acceptance criteria, and Relevant Wiki references
45
- that define what to design a technical solution for.
46
-
47
- **All context is extracted from the story document:**
48
- - Feature file (from story description/metadata)
49
- - Story requirements (User Story, Description, AC)
50
- - Wiki references (from Relevant Wiki section pass 2)
51
- - External analysis (auto-detected in story directory OPTIONAL)
52
- - Integration analysis (auto-detected in story directory MANDATORY)
53
-
54
- If not valid, stop and prompt the user.
55
- </param>
56
- </required>
57
-
58
- <optional>
59
- <!-- No optional parameters.
60
- All context is extracted from the story document and story directory:
61
- - Feature file (from story description/metadata)
62
- - Story requirements (User Story, Description, AC)
63
- - Wiki references (from Relevant Wiki section — pass 2)
64
- - External analysis (auto-detected in story directory)
65
- - Integration analysis (auto-detected in story directory)
66
- -->
67
- </optional>
68
- </parameters>
69
- </input>
70
-
71
- <execution-context>
72
- <research-technical-workflow>@~/.claude/agile-context-engineering/workflows/research-technical-solution.xml</research-technical-workflow>
73
- <technical-solution-template>@~/.claude/agile-context-engineering/templates/product/story-technical-solution.xml</technical-solution-template>
74
- <ui-formatting>@~/.claude/agile-context-engineering/utils/ui-formatting.md</ui-formatting>
75
- </execution-context>
76
-
77
- <output>
78
- <objective>
79
- Use business requirements, integration analysis, and optionally external/industry-standard
80
- analysis to create a CONCRETE TECHNICAL SOLUTION DESIGN for the story, following Clean
81
- Architecture principles, SOLID patterns, OOP best practices, considering external analysis
82
- for approach, algorithms and formulas (when most efficient and performant), while following
83
- the integration analysis so that we don't break our already complex codebase.
84
-
85
- **CRITICAL**: The technical solution MUST include detailed sequence diagrams for EVERY
86
- scenario in the Acceptance Criteria, showing the complete flow of data and control
87
- through all architectural layers.
88
-
89
- The analysis covers:
90
- - Complete component and boundary architecture
91
- - Design patterns and technical decisions
92
- - Full class diagrams and interfaces (one per file!)
93
- - Data models and structures
94
- - Algorithms and business logic
95
- - Event flow and entry points
96
- - MANDATORY sequence diagrams for ALL AC scenarios
97
- - Complete file structure tree
98
- - DI container configuration
99
- - Testing strategy (unit, integration, e2e)
100
- - Implementation order and dependencies
101
-
102
- **Output**: The entire technical solution is written INTO the story document
103
- (appended as the Technical Solution section) AND updated in the GitHub issue.
104
- No separate output file is created.
105
- </objective>
106
-
107
- <artifacts>
108
- Written directly into the story file and GitHub issue — pass 5 of the story specification pipeline.
109
- See story.xml: &lt;section name="technical-solution" pass="5" template="story-technical-solution.xml"&gt;
110
- </artifacts>
111
- </output>
112
-
113
- <process>
114
- For this command use the `ace-technical-application-architect` agent
115
- that's specialized in application architecture and is intimate with the codebase.
116
-
117
- Execute the research-technical-solution workflow from
118
- `@~/.claude/agile-context-engineering/workflows/research-technical-solution.xml` end-to-end.
119
- Preserve all workflow gates (validation, approvals, commits).
120
- </process>
121
-
122
- <example-usage>
123
- ```
124
- # Example with file path story
125
- /ace:research-technical-solution \
126
- story=.ace/artifacts/product/e1-auth/f3-oauth/s1-buttons/s1-buttons.md
127
-
128
- # Example with GitHub story
129
- /ace:research-technical-solution \
130
- story=https://github.com/owner/repo/issues/83
131
-
132
- # Example with just issue number (uses current repo)
133
- /ace:research-technical-solution \
134
- story=83
135
- ```
136
- </example-usage>
137
-
138
- <next-steps>
139
- **After this command:**
140
- - The story is now fully refined (pass 5 complete) — ready for implementation
141
- - `/ace:execute-story story=...` — Execute the story implementation
142
- - `/ace:refine-story story=...` — Re-refine if scope changes
143
- - `/ace:help` — Check project initialization status
144
- </next-steps>
145
-
146
- </command>
147
- ```
1
+ ---
2
+ name: research-technical-solution
3
+ description: COMPREHENSIVE Technical Solution Design for a Story -- Architecture, Patterns, Algorithms, Sequence Diagrams, and Implementation Plan
4
+ argument-hint: "story=<file-path|github-url>"
5
+ disable-model-invocation: true
6
+ allowed-tools: Read, Bash, Write, Edit, AskUserQuestion, Glob, Grep, Agent
7
+ model: opus
8
+ effort: max
9
+ context: fork
10
+ agent: ace-technical-application-architect
11
+ ---
12
+
13
+ ## Environment Context (preprocessed)
14
+
15
+ !`node "${CLAUDE_SKILL_DIR}/script.js" init "$ARGUMENTS" 2>/dev/null`
16
+
17
+ ## Supporting Resources (auto-loaded)
18
+
19
+ !`cat "${CLAUDE_SKILL_DIR}/workflow.xml"`
20
+
21
+ !`cat "${CLAUDE_SKILL_DIR}/technical-solution-template.xml"`
22
+
23
+ !`cat "${CLAUDE_SKILL_DIR}/../../shared/utils/ui-formatting.md"`
24
+
25
+ ```xml
26
+ <command>
27
+
28
+ <execution-time>
29
+ <runs-after>
30
+ <trigger>After /ace:plan-story — once story requirements (pass 1-2) are complete</trigger>
31
+ <trigger>After /ace:research-integration-solution — integration analysis (pass 4) MUST exist</trigger>
32
+ <trigger>Optionally after /ace:research-external-solution — external analysis (pass 3) if applicable</trigger>
33
+ </runs-after>
34
+ <use-when>
35
+ <condition>Story requirements, wiki references, and integration analysis are available (passes 1-4 complete)</condition>
36
+ <condition>Need to design a concrete technical solution for the story</condition>
37
+ <condition>Want a detailed implementation blueprint with class diagrams, sequence diagrams, algorithms, and file structure</condition>
38
+ <condition>Need a comprehensive technical design to guide AI agents implementing the story</condition>
39
+ </use-when>
40
+ </execution-time>
41
+
42
+ <input>
43
+ <flags>
44
+ </flags>
45
+
46
+ <parameters>
47
+ <required>
48
+ <param name="story" type="file | github-url">
49
+ Story source can be either:
50
+ - **File path**: Path to a markdown file containing the story (from plan-story command)
51
+ - **GitHub URL or issue number**: GitHub story reference
52
+ Must be a valid, accessible file or GitHub issue.
53
+ Contains the user story, acceptance criteria, and Relevant Wiki references
54
+ that define what to design a technical solution for.
55
+
56
+ **All context is extracted from the story document:**
57
+ - Feature file (from story description/metadata)
58
+ - Story requirements (User Story, Description, AC)
59
+ - Wiki references (from Relevant Wiki section — pass 2)
60
+ - External analysis (auto-detected in story directory OPTIONAL)
61
+ - Integration analysis (auto-detected in story directory — MANDATORY)
62
+
63
+ If not valid, stop and prompt the user.
64
+ </param>
65
+ </required>
66
+
67
+ <optional>
68
+ <!-- No optional parameters.
69
+ All context is extracted from the story document and story directory:
70
+ - Feature file (from story description/metadata)
71
+ - Story requirements (User Story, Description, AC)
72
+ - Wiki references (from Relevant Wiki section — pass 2)
73
+ - External analysis (auto-detected in story directory)
74
+ - Integration analysis (auto-detected in story directory)
75
+ -->
76
+ </optional>
77
+ </parameters>
78
+ </input>
79
+
80
+ <execution-context>
81
+ <!-- All supporting files are auto-loaded in the Supporting Resources section above.
82
+ The model does NOT need to Read these files they are already in context. -->
83
+ </execution-context>
84
+
85
+ <output>
86
+ <objective>
87
+ Use business requirements, integration analysis, and optionally external/industry-standard
88
+ analysis to create a CONCRETE TECHNICAL SOLUTION DESIGN for the story, following Clean
89
+ Architecture principles, SOLID patterns, OOP best practices, considering external analysis
90
+ for approach, algorithms and formulas (when most efficient and performant), while following
91
+ the integration analysis so that we don't break our already complex codebase.
92
+
93
+ **CRITICAL**: The technical solution MUST include detailed sequence diagrams for EVERY
94
+ scenario in the Acceptance Criteria, showing the complete flow of data and control
95
+ through all architectural layers.
96
+
97
+ The analysis covers:
98
+ - Complete component and boundary architecture
99
+ - Design patterns and technical decisions
100
+ - Full class diagrams and interfaces (one per file!)
101
+ - Data models and structures
102
+ - Algorithms and business logic
103
+ - Event flow and entry points
104
+ - MANDATORY sequence diagrams for ALL AC scenarios
105
+ - Complete file structure tree
106
+ - DI container configuration
107
+ - Testing strategy (unit, integration, e2e)
108
+ - Implementation order and dependencies
109
+
110
+ **Output**: The entire technical solution is written INTO the story document
111
+ (appended as the Technical Solution section) AND updated in the GitHub issue.
112
+ No separate output file is created.
113
+ </objective>
114
+
115
+ <artifacts>
116
+ Written directly into the story file and GitHub issue — pass 5 of the story specification pipeline.
117
+ See story.xml: &lt;section name="technical-solution" pass="5" template="story-technical-solution.xml"&gt;
118
+ </artifacts>
119
+ </output>
120
+
121
+ <process>
122
+ For this command use the `ace-technical-application-architect` agent
123
+ that's specialized in application architecture and is intimate with the codebase.
124
+
125
+ Execute the research-technical-solution workflow from
126
+ `workflow.xml` end-to-end.
127
+ Preserve all workflow gates (validation, approvals, commits).
128
+ </process>
129
+
130
+ <example-usage>
131
+ ```
@@ -0,0 +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, 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
+ }
@@ -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
+ });