ref-agents 1.0.0__py3-none-any.whl

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 (175) hide show
  1. ref_agents/__init__.py +9 -0
  2. ref_agents/api_keys.json.example +8 -0
  3. ref_agents/auth.py +129 -0
  4. ref_agents/codemap/..md +62 -0
  5. ref_agents/codemap/CODE_MAP.md +37 -0
  6. ref_agents/codemap/core.md +43 -0
  7. ref_agents/codemap/models.md +43 -0
  8. ref_agents/codemap/prompts.md +40 -0
  9. ref_agents/codemap/security.md +45 -0
  10. ref_agents/codemap/tools.md +94 -0
  11. ref_agents/codemap/tools_browser.md +44 -0
  12. ref_agents/codemap/utils.md +42 -0
  13. ref_agents/codemap/workflow.md +42 -0
  14. ref_agents/config/ai_patterns.yaml +101 -0
  15. ref_agents/config/frameworks/angular.yaml +104 -0
  16. ref_agents/config/frameworks/aspnet.yaml +84 -0
  17. ref_agents/config/frameworks/ef_core.yaml +81 -0
  18. ref_agents/config/frameworks/react.yaml +111 -0
  19. ref_agents/config/frameworks/spring_boot.yaml +117 -0
  20. ref_agents/config/languages/csharp.yaml +153 -0
  21. ref_agents/config/languages/java.yaml +188 -0
  22. ref_agents/config/languages/javascript.yaml +172 -0
  23. ref_agents/config/languages/python.yaml +153 -0
  24. ref_agents/config/languages/typescript.yaml +193 -0
  25. ref_agents/constants.py +553 -0
  26. ref_agents/core/__init__.py +15 -0
  27. ref_agents/core/config_loader.py +160 -0
  28. ref_agents/core/config_models.py +167 -0
  29. ref_agents/core/config_parsing.py +84 -0
  30. ref_agents/core/language_detector.py +388 -0
  31. ref_agents/core/validation_models.py +66 -0
  32. ref_agents/core/validation_primitives.py +176 -0
  33. ref_agents/errors.py +34 -0
  34. ref_agents/license_client.py +247 -0
  35. ref_agents/models/__init__.py +22 -0
  36. ref_agents/models/gherkin.py +45 -0
  37. ref_agents/models/hierarchy.py +80 -0
  38. ref_agents/models/invest.py +59 -0
  39. ref_agents/models/version.py +49 -0
  40. ref_agents/prompts/__init__.py +9 -0
  41. ref_agents/prompts/start_agent.py +772 -0
  42. ref_agents/rules/architecture/backend_patterns.md +43 -0
  43. ref_agents/rules/architecture/diagramming.md +100 -0
  44. ref_agents/rules/architecture/frontend_patterns.md +40 -0
  45. ref_agents/rules/architecture/impact_analysis.md +129 -0
  46. ref_agents/rules/architecture/migration_strategy.md +208 -0
  47. ref_agents/rules/architecture/regression_protocol.md +77 -0
  48. ref_agents/rules/architecture/system_design.md +97 -0
  49. ref_agents/rules/common/codemap_standard.md +97 -0
  50. ref_agents/rules/common/core_protocol.md +59 -0
  51. ref_agents/rules/common/prompt_engineering.md +294 -0
  52. ref_agents/rules/development/debugging.md +32 -0
  53. ref_agents/rules/development/implementation.md +205 -0
  54. ref_agents/rules/operations/completion.md +119 -0
  55. ref_agents/rules/operations/cutover_protocol.md +218 -0
  56. ref_agents/rules/operations/discovery.md +179 -0
  57. ref_agents/rules/operations/fix_workflow.md +87 -0
  58. ref_agents/rules/operations/forensics.md +278 -0
  59. ref_agents/rules/operations/platform.md +263 -0
  60. ref_agents/rules/operations/synchronous_flow.md +25 -0
  61. ref_agents/rules/product/ac_validation.md +25 -0
  62. ref_agents/rules/product/brainstorming.md +27 -0
  63. ref_agents/rules/product/ref_flow.md +101 -0
  64. ref_agents/rules/product/requirements_std.md +114 -0
  65. ref_agents/rules/product/spec_writing.md +235 -0
  66. ref_agents/rules/product/strategy.md +96 -0
  67. ref_agents/rules/quality/documentation_standards.md +46 -0
  68. ref_agents/rules/quality/parity_testing.md +234 -0
  69. ref_agents/rules/quality/project_documentation.md +56 -0
  70. ref_agents/rules/quality/qa_lead.md +111 -0
  71. ref_agents/rules/quality/test_design.md +146 -0
  72. ref_agents/rules/quality/testing_standards.md +293 -0
  73. ref_agents/rules/review/pr_review.md +116 -0
  74. ref_agents/rules/security/security_audit.md +83 -0
  75. ref_agents/security/__init__.py +22 -0
  76. ref_agents/security/dependency_audit.py +188 -0
  77. ref_agents/security/file_audit.py +208 -0
  78. ref_agents/security/network_scan.py +179 -0
  79. ref_agents/security/report_generator.py +313 -0
  80. ref_agents/security/secret_scan.py +252 -0
  81. ref_agents/security/url_scan.py +240 -0
  82. ref_agents/security_scan.py +236 -0
  83. ref_agents/server.py +1586 -0
  84. ref_agents/session.py +100 -0
  85. ref_agents/tool_names.py +55 -0
  86. ref_agents/tools/__init__.py +8 -0
  87. ref_agents/tools/agents_generator.py +315 -0
  88. ref_agents/tools/ai_pattern_detector.py +815 -0
  89. ref_agents/tools/brownfield_populator.py +529 -0
  90. ref_agents/tools/browser/__init__.py +50 -0
  91. ref_agents/tools/browser/evidence_verifier.py +302 -0
  92. ref_agents/tools/browser/execution_logger.py +249 -0
  93. ref_agents/tools/browser/playwright_mcp_client.py +259 -0
  94. ref_agents/tools/browser/screenshot_utils.py +184 -0
  95. ref_agents/tools/browser/test_executor.py +537 -0
  96. ref_agents/tools/code_quality_scanner.py +629 -0
  97. ref_agents/tools/codemap/..md +93 -0
  98. ref_agents/tools/codemap/CODE_MAP.md +30 -0
  99. ref_agents/tools/codemap/browser.md +44 -0
  100. ref_agents/tools/codemap.py +403 -0
  101. ref_agents/tools/codemap_freshness.py +234 -0
  102. ref_agents/tools/comment_smell_scanner.py +346 -0
  103. ref_agents/tools/complexity.py +436 -0
  104. ref_agents/tools/complexity_ast.py +333 -0
  105. ref_agents/tools/compliance.py +246 -0
  106. ref_agents/tools/compliance_remediation.py +846 -0
  107. ref_agents/tools/context_graph.py +839 -0
  108. ref_agents/tools/context_manager.py +550 -0
  109. ref_agents/tools/context_tools.py +121 -0
  110. ref_agents/tools/cross_repo_linker.py +393 -0
  111. ref_agents/tools/dead_code_scanner.py +637 -0
  112. ref_agents/tools/debt_scanner.py +1092 -0
  113. ref_agents/tools/dependency_graph.py +272 -0
  114. ref_agents/tools/discovery_audit.py +372 -0
  115. ref_agents/tools/docs_scanner.py +600 -0
  116. ref_agents/tools/evaluate_gate.py +119 -0
  117. ref_agents/tools/external_detector.py +524 -0
  118. ref_agents/tools/features_generator.py +282 -0
  119. ref_agents/tools/flow_gap_detector.py +373 -0
  120. ref_agents/tools/flow_mapper.py +327 -0
  121. ref_agents/tools/full_suite_runner.py +740 -0
  122. ref_agents/tools/gherkin_parser.py +227 -0
  123. ref_agents/tools/guard_tools.py +139 -0
  124. ref_agents/tools/handoff_tools.py +282 -0
  125. ref_agents/tools/health_scanner.py +1211 -0
  126. ref_agents/tools/hierarchy_manager.py +289 -0
  127. ref_agents/tools/invest_scorer.py +249 -0
  128. ref_agents/tools/jira_confluence_export.py +306 -0
  129. ref_agents/tools/json_output.py +76 -0
  130. ref_agents/tools/migration_mapper.py +946 -0
  131. ref_agents/tools/migration_readiness_scanner.py +209 -0
  132. ref_agents/tools/pattern_learner.py +522 -0
  133. ref_agents/tools/report_utils.py +155 -0
  134. ref_agents/tools/requirements_serializer.py +225 -0
  135. ref_agents/tools/security_audit_tool.py +106 -0
  136. ref_agents/tools/sequencing_engine.py +288 -0
  137. ref_agents/tools/summary_generator.py +275 -0
  138. ref_agents/tools/symbol_resolver.py +306 -0
  139. ref_agents/tools/symbol_smoke_runner.py +336 -0
  140. ref_agents/tools/test_plan_validator.py +189 -0
  141. ref_agents/tools/test_smell_walker.py +902 -0
  142. ref_agents/tools/tier1_fixer.py +502 -0
  143. ref_agents/tools/validators/__init__.py +419 -0
  144. ref_agents/tools/validators/architect.py +268 -0
  145. ref_agents/tools/validators/cutover_engineer.py +167 -0
  146. ref_agents/tools/validators/developer.py +180 -0
  147. ref_agents/tools/validators/discovery.py +150 -0
  148. ref_agents/tools/validators/forensic_engineer.py +191 -0
  149. ref_agents/tools/validators/impact_architect.py +181 -0
  150. ref_agents/tools/validators/migration_planner.py +166 -0
  151. ref_agents/tools/validators/parity_tester.py +155 -0
  152. ref_agents/tools/validators/platform_engineer.py +134 -0
  153. ref_agents/tools/validators/pr_reviewer.py +129 -0
  154. ref_agents/tools/validators/product_manager.py +291 -0
  155. ref_agents/tools/validators/qa_lead.py +172 -0
  156. ref_agents/tools/validators/scrum_master.py +212 -0
  157. ref_agents/tools/validators/security_owner.py +162 -0
  158. ref_agents/tools/validators/specifier.py +134 -0
  159. ref_agents/tools/validators/strategist.py +149 -0
  160. ref_agents/tools/validators/tester.py +121 -0
  161. ref_agents/tools/version_manager.py +202 -0
  162. ref_agents/tools/workflow_tools.py +1549 -0
  163. ref_agents/utils/__init__.py +21 -0
  164. ref_agents/utils/git_utils.py +351 -0
  165. ref_agents/utils/handoff_logger.py +368 -0
  166. ref_agents/utils/ignore_matcher.py +270 -0
  167. ref_agents/workflow/__init__.py +19 -0
  168. ref_agents/workflow/capabilities.py +328 -0
  169. ref_agents/workflow/state_machine.py +708 -0
  170. ref_agents/workflow/transitions.py +658 -0
  171. ref_agents-1.0.0.dist-info/METADATA +365 -0
  172. ref_agents-1.0.0.dist-info/RECORD +175 -0
  173. ref_agents-1.0.0.dist-info/WHEEL +4 -0
  174. ref_agents-1.0.0.dist-info/entry_points.txt +2 -0
  175. ref_agents-1.0.0.dist-info/licenses/LICENSE +115 -0
@@ -0,0 +1,306 @@
1
+ """JIRA and Confluence export functions for requirements.
2
+
3
+ Provides functions to convert REF-Agents requirements to JIRA/Confluence formats.
4
+ """
5
+
6
+ from typing import Any
7
+
8
+ import structlog
9
+
10
+ from ref_agents.models.hierarchy import Epic, Feature, Story
11
+ from ref_agents.models.invest import INVESTScores
12
+
13
+ logger = structlog.get_logger(__name__)
14
+
15
+
16
+ def export_to_jira_format(
17
+ story: Story,
18
+ invest_scores: INVESTScores | None = None,
19
+ acceptance_criteria: list[dict[str, Any]] | None = None,
20
+ ) -> dict[str, Any]:
21
+ """Export story to JIRA issue format.
22
+
23
+ Compatible with JIRA REST API for issue creation.
24
+
25
+ Args:
26
+ story: Story model
27
+ invest_scores: Optional INVEST scores
28
+ acceptance_criteria: Optional structured acceptance criteria
29
+
30
+ Returns:
31
+ Dictionary compatible with JIRA REST API createIssue endpoint
32
+ """
33
+ fields: dict[str, Any] = {
34
+ "summary": story.title,
35
+ "description": {
36
+ "type": "doc",
37
+ "version": 1,
38
+ "content": [
39
+ {
40
+ "type": "paragraph",
41
+ "content": [{"type": "text", "text": story.description or ""}],
42
+ }
43
+ ],
44
+ },
45
+ "issuetype": {"name": "Story"},
46
+ }
47
+
48
+ # Add user story
49
+ if story.user_story:
50
+ fields["description"]["content"].append(
51
+ {
52
+ "type": "paragraph",
53
+ "content": [
54
+ {"type": "text", "text": f"User Story: {story.user_story}"}
55
+ ],
56
+ }
57
+ )
58
+
59
+ # Add epic link if present
60
+ if story.epic_id:
61
+ fields["customfield_10014"] = (
62
+ story.epic_id
63
+ ) # Epic Link field (varies by JIRA instance)
64
+
65
+ # Add feature link if present (custom field)
66
+ if story.feature_id:
67
+ fields["customfield_10015"] = story.feature_id # Feature Link (custom field)
68
+
69
+ # Add INVEST scores as custom fields or labels
70
+ if invest_scores:
71
+ fields["labels"] = [
72
+ f"INVEST-{k}:{v}" for k, v in invest_scores.to_dict().items()
73
+ ]
74
+
75
+ # Add acceptance criteria
76
+ if acceptance_criteria:
77
+ ac_content = [
78
+ {
79
+ "type": "heading",
80
+ "attrs": {"level": 3},
81
+ "content": [{"type": "text", "text": "Acceptance Criteria"}],
82
+ }
83
+ ]
84
+ for idx, ac in enumerate(acceptance_criteria, 1):
85
+ scenario = ac.get("scenario", f"AC-{idx}")
86
+ steps = ac.get("steps", [])
87
+ ac_content.append(
88
+ {
89
+ "type": "paragraph",
90
+ "content": [
91
+ {"type": "text", "text": f"{scenario}:"},
92
+ ],
93
+ }
94
+ )
95
+ for step in steps:
96
+ keyword = step.get("keyword", "")
97
+ text = step.get("text", "")
98
+ ac_content.append(
99
+ {
100
+ "type": "paragraph",
101
+ "content": [
102
+ {"type": "text", "text": f"{keyword} {text}"},
103
+ ],
104
+ }
105
+ )
106
+
107
+ fields["description"]["content"].extend(ac_content)
108
+
109
+ return {
110
+ "fields": fields,
111
+ }
112
+
113
+
114
+ def export_to_confluence_format(
115
+ story: Story,
116
+ invest_scores: INVESTScores | None = None,
117
+ acceptance_criteria: list[dict[str, Any]] | None = None,
118
+ ) -> dict[str, Any]:
119
+ """Export story to Confluence page format.
120
+
121
+ Compatible with Confluence REST API for page creation.
122
+
123
+ Args:
124
+ story: Story model
125
+ invest_scores: Optional INVEST scores
126
+ acceptance_criteria: Optional structured acceptance criteria
127
+
128
+ Returns:
129
+ Dictionary compatible with Confluence REST API createPage endpoint
130
+ """
131
+ # Build Confluence storage format (Confluence Wiki or Storage format)
132
+ body_content: list[dict[str, Any]] = []
133
+
134
+ # Title and description
135
+ body_content.append(
136
+ {
137
+ "type": "paragraph",
138
+ "content": [
139
+ {"type": "text", "text": story.description or ""},
140
+ ],
141
+ }
142
+ )
143
+
144
+ # User story
145
+ if story.user_story:
146
+ body_content.append(
147
+ {
148
+ "type": "paragraph",
149
+ "content": [
150
+ {"type": "text", "text": f"User Story: {story.user_story}"},
151
+ ],
152
+ }
153
+ )
154
+
155
+ # Epic and Feature links
156
+ if story.epic_id or story.feature_id:
157
+ links = []
158
+ if story.epic_id:
159
+ links.append(f"Epic: {story.epic_id}")
160
+ if story.feature_id:
161
+ links.append(f"Feature: {story.feature_id}")
162
+ body_content.append(
163
+ {
164
+ "type": "paragraph",
165
+ "content": [
166
+ {"type": "text", "text": " | ".join(links)},
167
+ ],
168
+ }
169
+ )
170
+
171
+ # INVEST scores
172
+ if invest_scores:
173
+ scores_text = ", ".join(f"{k}: {v}" for k, v in invest_scores.to_dict().items())
174
+ body_content.append(
175
+ {
176
+ "type": "paragraph",
177
+ "content": [
178
+ {"type": "text", "text": f"INVEST Scores: {scores_text}"},
179
+ ],
180
+ }
181
+ )
182
+
183
+ # Acceptance criteria
184
+ if acceptance_criteria:
185
+ body_content.append(
186
+ {
187
+ "type": "heading",
188
+ "attrs": {"level": 3},
189
+ "content": [{"type": "text", "text": "Acceptance Criteria"}],
190
+ }
191
+ )
192
+ for idx, ac in enumerate(acceptance_criteria, 1):
193
+ scenario = ac.get("scenario", f"AC-{idx}")
194
+ steps = ac.get("steps", [])
195
+ body_content.append(
196
+ {
197
+ "type": "heading",
198
+ "attrs": {"level": 4},
199
+ "content": [{"type": "text", "text": scenario}],
200
+ }
201
+ )
202
+ for step in steps:
203
+ keyword = step.get("keyword", "")
204
+ text = step.get("text", "")
205
+ body_content.append(
206
+ {
207
+ "type": "paragraph",
208
+ "content": [
209
+ {"type": "text", "text": f"{keyword} {text}"},
210
+ ],
211
+ }
212
+ )
213
+
214
+ return {
215
+ "title": story.title,
216
+ "type": "page",
217
+ "space": {"key": "REF"}, # Default space, should be configurable
218
+ "body": {
219
+ "storage": {
220
+ "value": _convert_to_storage_format(body_content),
221
+ "representation": "storage",
222
+ }
223
+ },
224
+ }
225
+
226
+
227
+ def export_epic_to_jira(epic: Epic) -> dict[str, Any]:
228
+ """Export epic to JIRA format.
229
+
230
+ Args:
231
+ epic: Epic model
232
+
233
+ Returns:
234
+ Dictionary compatible with JIRA REST API
235
+ """
236
+ return {
237
+ "fields": {
238
+ "summary": epic.title,
239
+ "description": {
240
+ "type": "doc",
241
+ "version": 1,
242
+ "content": [
243
+ {
244
+ "type": "paragraph",
245
+ "content": [{"type": "text", "text": epic.description or ""}],
246
+ }
247
+ ],
248
+ },
249
+ "issuetype": {"name": "Epic"},
250
+ "customfield_10011": epic.title, # Epic Name field
251
+ },
252
+ }
253
+
254
+
255
+ def export_feature_to_jira(feature: Feature) -> dict[str, Any]:
256
+ """Export feature to JIRA format.
257
+
258
+ Args:
259
+ feature: Feature model
260
+
261
+ Returns:
262
+ Dictionary compatible with JIRA REST API
263
+ """
264
+ return {
265
+ "fields": {
266
+ "summary": feature.title,
267
+ "description": {
268
+ "type": "doc",
269
+ "version": 1,
270
+ "content": [
271
+ {
272
+ "type": "paragraph",
273
+ "content": [
274
+ {"type": "text", "text": feature.description or ""}
275
+ ],
276
+ }
277
+ ],
278
+ },
279
+ "issuetype": {"name": "Feature"},
280
+ "customfield_10014": feature.epic_id, # Epic Link
281
+ },
282
+ }
283
+
284
+
285
+ def _convert_to_storage_format(content: list[dict[str, Any]]) -> str:
286
+ """Convert Confluence content to storage format string.
287
+
288
+ Simplified implementation - in production, use Confluence API client.
289
+ """
290
+ # This is a placeholder - actual implementation would use Confluence's
291
+ # storage format or use a Confluence API client library
292
+ lines = []
293
+ for item in content:
294
+ if item["type"] == "paragraph":
295
+ text = " ".join(
296
+ c.get("text", "") for c in item.get("content", []) if "text" in c
297
+ )
298
+ lines.append(text)
299
+ elif item["type"] == "heading":
300
+ level = item.get("attrs", {}).get("level", 1)
301
+ text = " ".join(
302
+ c.get("text", "") for c in item.get("content", []) if "text" in c
303
+ )
304
+ lines.append(f"{'#' * level} {text}")
305
+
306
+ return "\n\n".join(lines)
@@ -0,0 +1,76 @@
1
+ """JSON output utility for generating JSON artifacts alongside markdown."""
2
+
3
+ import json
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ import structlog
8
+
9
+ logger = structlog.get_logger(__name__)
10
+
11
+
12
+ def generate_json_output(artifact_type: str, data: Any, output_path: Path) -> Path:
13
+ """Generate JSON output file for an artifact.
14
+
15
+ Args:
16
+ artifact_type: Type of artifact (story, epic, feature, report)
17
+ data: Data to serialize (dict or Pydantic model)
18
+ output_path: Path for JSON file (will replace .md with .json if needed)
19
+
20
+ Returns:
21
+ Path to generated JSON file
22
+ """
23
+ # Ensure .json extension
24
+ if output_path.suffix == ".md":
25
+ json_path = output_path.with_suffix(".json")
26
+ elif output_path.suffix != ".json":
27
+ json_path = output_path.with_suffix(".json")
28
+ else:
29
+ json_path = output_path
30
+
31
+ # Convert Pydantic models to dict if needed
32
+ if hasattr(data, "model_dump"):
33
+ json_data = data.model_dump()
34
+ elif hasattr(data, "dict"):
35
+ json_data = data.dict()
36
+ elif isinstance(data, dict):
37
+ json_data = data
38
+ else:
39
+ json_data = {"data": str(data)}
40
+
41
+ # Ensure directory exists
42
+ json_path.parent.mkdir(parents=True, exist_ok=True)
43
+
44
+ # Write JSON file
45
+ json_path.write_text(
46
+ json.dumps(json_data, indent=2, ensure_ascii=False), encoding="utf-8"
47
+ )
48
+
49
+ logger.info(
50
+ "JSON output generated",
51
+ artifact_type=artifact_type,
52
+ path=str(json_path),
53
+ )
54
+
55
+ return json_path
56
+
57
+
58
+ def serialize_to_json(data: Any) -> str:
59
+ """Serialize data to JSON string.
60
+
61
+ Args:
62
+ data: Data to serialize (dict, Pydantic model, or other)
63
+
64
+ Returns:
65
+ JSON string
66
+ """
67
+ if hasattr(data, "model_dump"):
68
+ json_data = data.model_dump()
69
+ elif hasattr(data, "dict"):
70
+ json_data = data.dict()
71
+ elif isinstance(data, dict):
72
+ json_data = data
73
+ else:
74
+ json_data = {"data": str(data)}
75
+
76
+ return json.dumps(json_data, indent=2, ensure_ascii=False)