@jaguilar87/gaia-ops 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (91) hide show
  1. package/CHANGELOG.md +315 -0
  2. package/CLAUDE.md +154 -0
  3. package/LICENSE +21 -0
  4. package/README.md +221 -0
  5. package/agents/aws-troubleshooter.md +50 -0
  6. package/agents/claude-architect.md +821 -0
  7. package/agents/devops-developer.md +92 -0
  8. package/agents/gcp-troubleshooter.md +50 -0
  9. package/agents/gitops-operator.md +360 -0
  10. package/agents/terraform-architect.md +289 -0
  11. package/bin/gaia-init.js +620 -0
  12. package/commands/architect.md +97 -0
  13. package/commands/restore-session.md +87 -0
  14. package/commands/save-session.md +88 -0
  15. package/commands/session-status.md +61 -0
  16. package/commands/speckit.add-task.md +144 -0
  17. package/commands/speckit.analyze-task.md +65 -0
  18. package/commands/speckit.implement.md +96 -0
  19. package/commands/speckit.init.md +237 -0
  20. package/commands/speckit.plan.md +88 -0
  21. package/commands/speckit.specify.md +161 -0
  22. package/commands/speckit.tasks.md +188 -0
  23. package/config/AGENTS.md +162 -0
  24. package/config/agent-catalog.md +604 -0
  25. package/config/context-contracts.md +682 -0
  26. package/config/git-standards.md +674 -0
  27. package/config/git_standards.json +69 -0
  28. package/config/orchestration-workflow.md +735 -0
  29. package/hooks/__pycache__/post_tool_use.cpython-312.pyc +0 -0
  30. package/hooks/__pycache__/pre_kubectl_security.cpython-312.pyc +0 -0
  31. package/hooks/__pycache__/pre_tool_use.cpython-312.pyc +0 -0
  32. package/hooks/__pycache__/session_start.cpython-312.pyc +0 -0
  33. package/hooks/__pycache__/subagent_stop.cpython-312.pyc +0 -0
  34. package/hooks/post_tool_use.py +463 -0
  35. package/hooks/pre_kubectl_security.py +205 -0
  36. package/hooks/pre_tool_use.py +530 -0
  37. package/hooks/session_start.py +315 -0
  38. package/hooks/subagent_stop.py +549 -0
  39. package/index.js +92 -0
  40. package/package.json +59 -0
  41. package/speckit/README.en.md +648 -0
  42. package/speckit/README.md +353 -0
  43. package/speckit/governance.md +169 -0
  44. package/speckit/scripts/check-prerequisites.sh +194 -0
  45. package/speckit/scripts/common.sh +126 -0
  46. package/speckit/scripts/create-new-feature.sh +131 -0
  47. package/speckit/scripts/init.sh +42 -0
  48. package/speckit/scripts/setup-plan.sh +95 -0
  49. package/speckit/scripts/update-agent-context.sh +718 -0
  50. package/speckit/templates/adr-template.md +118 -0
  51. package/speckit/templates/agent-file-template.md +23 -0
  52. package/speckit/templates/plan-template.md +233 -0
  53. package/speckit/templates/spec-template.md +116 -0
  54. package/speckit/templates/tasks-template-bkp.md +136 -0
  55. package/speckit/templates/tasks-template.md +345 -0
  56. package/templates/CLAUDE.template.md +170 -0
  57. package/templates/code-examples/approval_gate_workflow.py +141 -0
  58. package/templates/code-examples/clarification_workflow.py +94 -0
  59. package/templates/code-examples/commit_validation.py +86 -0
  60. package/templates/project-context.template.json +126 -0
  61. package/templates/settings.template.json +307 -0
  62. package/tools/__pycache__/agent_router.cpython-312.pyc +0 -0
  63. package/tools/__pycache__/approval_gate.cpython-312.pyc +0 -0
  64. package/tools/__pycache__/clarify_engine.cpython-312.pyc +0 -0
  65. package/tools/__pycache__/clarify_patterns.cpython-312.pyc +0 -0
  66. package/tools/__pycache__/commit_validator.cpython-312.pyc +0 -0
  67. package/tools/__pycache__/context_section_reader.cpython-312.pyc +0 -0
  68. package/tools/__pycache__/routing_dashboard.cpython-312.pyc +0 -0
  69. package/tools/__pycache__/routing_feedback.cpython-312.pyc +0 -0
  70. package/tools/__pycache__/semantic_matcher.cpython-312.pyc +0 -0
  71. package/tools/__pycache__/task_manager.cpython-312.pyc +0 -0
  72. package/tools/agent_capabilities.json +231 -0
  73. package/tools/agent_invoker_helper.py +239 -0
  74. package/tools/agent_router.py +730 -0
  75. package/tools/approval_gate.py +318 -0
  76. package/tools/clarify_engine.py +511 -0
  77. package/tools/clarify_patterns.py +356 -0
  78. package/tools/commit_validator.py +338 -0
  79. package/tools/context_provider.py +181 -0
  80. package/tools/context_section_reader.py +301 -0
  81. package/tools/demo_clarify.py +104 -0
  82. package/tools/generate_embeddings.py +168 -0
  83. package/tools/quicktriage_aws_troubleshooter.sh +45 -0
  84. package/tools/quicktriage_devops_developer.sh +38 -0
  85. package/tools/quicktriage_gcp_troubleshooter.sh +51 -0
  86. package/tools/quicktriage_gitops_operator.sh +47 -0
  87. package/tools/quicktriage_terraform_architect.sh +40 -0
  88. package/tools/semantic_matcher.py +222 -0
  89. package/tools/task_manager.py +547 -0
  90. package/tools/task_manager_README.md +395 -0
  91. package/tools/task_manager_example.py +215 -0
@@ -0,0 +1,318 @@
1
+ """
2
+ Approval Gate Enforcement
3
+
4
+ Ensures that no realization occurs without explicit user approval.
5
+ This is a CRITICAL component of the Two-Phase Workflow.
6
+ """
7
+
8
+ import json
9
+ import os
10
+ from typing import Dict, Any, Optional
11
+ from datetime import datetime
12
+
13
+
14
+ class ApprovalGate:
15
+ """
16
+ Enforces approval gate before any realization actions.
17
+
18
+ CRITICAL: This gate is MANDATORY in the workflow. No realization
19
+ can proceed without explicit user approval via AskUserQuestion.
20
+ """
21
+
22
+ def __init__(self):
23
+ self.approval_log_path = ".claude/logs/approvals.jsonl"
24
+ self._ensure_log_directory()
25
+
26
+ def _ensure_log_directory(self):
27
+ """Ensure the logs directory exists."""
28
+ log_dir = os.path.dirname(self.approval_log_path)
29
+ os.makedirs(log_dir, exist_ok=True)
30
+
31
+ def generate_approval_question(
32
+ self,
33
+ realization_package: Dict[str, Any],
34
+ agent_name: str,
35
+ phase: str
36
+ ) -> Dict[str, Any]:
37
+ """
38
+ Generate the approval question configuration for AskUserQuestion tool.
39
+
40
+ Args:
41
+ realization_package: The plan to be realized
42
+ agent_name: Name of the agent that generated the plan
43
+ phase: Current phase (e.g., "Phase 3.3")
44
+
45
+ Returns:
46
+ Dict with AskUserQuestion configuration
47
+ """
48
+
49
+ critical_ops = self._get_critical_operations(realization_package)
50
+ operation_count = self._get_operation_count(realization_package)
51
+
52
+ return {
53
+ "questions": [{
54
+ "question": f"¿Apruebas la realización de este plan? Se ejecutará: {critical_ops}",
55
+ "header": "Approval",
56
+ "multiSelect": False,
57
+ "options": [
58
+ {
59
+ "label": "✅ Aprobar y ejecutar",
60
+ "description": f"Proceder con {operation_count} operaciones: {critical_ops}"
61
+ },
62
+ {
63
+ "label": "❌ Rechazar",
64
+ "description": "Cancelar la realización. No se harán cambios."
65
+ }
66
+ ]
67
+ }]
68
+ }
69
+
70
+ def generate_summary(self, realization_package: Dict[str, Any]) -> str:
71
+ """
72
+ Generate human-readable summary of the realization package.
73
+
74
+ This summary should be presented to the user BEFORE calling
75
+ AskUserQuestion so they have full context for their decision.
76
+ """
77
+
78
+ summary_parts = []
79
+ summary_parts.append("="*60)
80
+ summary_parts.append("📦 REALIZATION PACKAGE - APPROVAL REQUIRED")
81
+ summary_parts.append("="*60)
82
+
83
+ # Files
84
+ if "files" in realization_package:
85
+ files = realization_package["files"]
86
+ summary_parts.append(f"\n**Archivos a crear/modificar:** {len(files)}")
87
+ for file_info in files[:10]: # Show first 10
88
+ action = file_info.get('action', 'create')
89
+ summary_parts.append(f" [{action}] {file_info['path']}")
90
+ if len(files) > 10:
91
+ summary_parts.append(f" ... y {len(files) - 10} archivos más")
92
+
93
+ # Git operations
94
+ if "git_operations" in realization_package:
95
+ git_ops = realization_package["git_operations"]
96
+ summary_parts.append(f"\n**Git Operations:**")
97
+ summary_parts.append(f" Commit: {git_ops.get('commit_message', 'N/A')}")
98
+ summary_parts.append(f" Branch: {git_ops.get('branch', 'main')}")
99
+ summary_parts.append(f" Remote: {git_ops.get('remote', 'origin')}")
100
+ summary_parts.append(f" Operation: git push")
101
+
102
+ # Resources affected
103
+ if "resources_affected" in realization_package:
104
+ resources = realization_package["resources_affected"]
105
+ summary_parts.append(f"\n**Recursos Afectados en el Cluster:**")
106
+ for resource_type, items in resources.items():
107
+ if isinstance(items, list):
108
+ summary_parts.append(f" {resource_type}: {len(items)}")
109
+ for item in items[:5]:
110
+ summary_parts.append(f" - {item}")
111
+ if len(items) > 5:
112
+ summary_parts.append(f" ... y {len(items) - 5} más")
113
+ else:
114
+ summary_parts.append(f" {resource_type}: {items}")
115
+
116
+ # Terraform operations
117
+ if "terraform_operations" in realization_package:
118
+ tf_ops = realization_package["terraform_operations"]
119
+ summary_parts.append(f"\n**Terraform Operations:**")
120
+ summary_parts.append(f" Command: {tf_ops.get('command', 'N/A')}")
121
+ summary_parts.append(f" Path: {tf_ops.get('path', 'N/A')}")
122
+ if "resources" in tf_ops:
123
+ summary_parts.append(f" Resources to change: {len(tf_ops['resources'])}")
124
+
125
+ # Validation results (if present)
126
+ if "validation_results" in realization_package:
127
+ validation = realization_package["validation_results"]
128
+ summary_parts.append(f"\n**Pre-Deployment Validation:**")
129
+ summary_parts.append(f" Status: {validation.get('status', 'N/A')}")
130
+ if validation.get('warnings'):
131
+ summary_parts.append(f" ⚠️ Warnings: {len(validation['warnings'])}")
132
+ for warning in validation['warnings'][:3]:
133
+ summary_parts.append(f" - {warning}")
134
+
135
+ # Estimated impact
136
+ if "estimated_impact" in realization_package:
137
+ impact = realization_package["estimated_impact"]
138
+ summary_parts.append(f"\n**Estimated Impact:**")
139
+ summary_parts.append(f" Downtime: {impact.get('downtime', 'None expected')}")
140
+ summary_parts.append(f" Risk Level: {impact.get('risk_level', 'Medium')}")
141
+
142
+ summary_parts.append("\n" + "="*60)
143
+
144
+ return "\n".join(summary_parts)
145
+
146
+ def _get_critical_operations(self, realization_package: Dict[str, Any]) -> str:
147
+ """Extract critical operations for the approval question."""
148
+ operations = []
149
+
150
+ if "git_operations" in realization_package:
151
+ git_ops = realization_package["git_operations"]
152
+ branch = git_ops.get('branch', 'main')
153
+ operations.append(f"git push origin {branch}")
154
+
155
+ if "kubectl_operations" in realization_package:
156
+ operations.append("kubectl apply")
157
+
158
+ if "terraform_operations" in realization_package:
159
+ tf_ops = realization_package["terraform_operations"]
160
+ command = tf_ops.get('command', 'apply')
161
+ operations.append(f"terraform {command}")
162
+
163
+ if "flux_operations" in realization_package:
164
+ operations.append("flux reconcile")
165
+
166
+ return ", ".join(operations) if operations else "cambios al repositorio"
167
+
168
+ def _get_operation_count(self, realization_package: Dict[str, Any]) -> int:
169
+ """Count total operations in the package."""
170
+ count = 0
171
+
172
+ if "files" in realization_package:
173
+ count += len(realization_package["files"])
174
+
175
+ if "git_operations" in realization_package:
176
+ count += 2 # commit + push
177
+
178
+ if "kubectl_operations" in realization_package:
179
+ kubectl_ops = realization_package["kubectl_operations"]
180
+ count += len(kubectl_ops) if isinstance(kubectl_ops, list) else 1
181
+
182
+ if "terraform_operations" in realization_package:
183
+ count += 1
184
+
185
+ return count
186
+
187
+ def validate_approval_response(self, user_response: str) -> Dict[str, Any]:
188
+ """
189
+ Validate the user's approval response.
190
+
191
+ Args:
192
+ user_response: The response from AskUserQuestion
193
+
194
+ Returns:
195
+ Dict with validation result and action to take
196
+ """
197
+
198
+ if user_response == "✅ Aprobar y ejecutar":
199
+ return {
200
+ "approved": True,
201
+ "action": "proceed_to_realization",
202
+ "message": "✅ Aprobación recibida. Procediendo a Fase 5 (Realization)..."
203
+ }
204
+
205
+ elif user_response == "❌ Rechazar":
206
+ return {
207
+ "approved": False,
208
+ "action": "halt_workflow",
209
+ "message": "❌ Realización rechazada por el usuario. Workflow detenido."
210
+ }
211
+
212
+ else:
213
+ # User selected "Other" or provided custom response
214
+ return {
215
+ "approved": False,
216
+ "action": "clarify_with_user",
217
+ "message": f"⚠️ Respuesta no estándar recibida: '{user_response}'. Se requiere clarificación.",
218
+ "user_input": user_response
219
+ }
220
+
221
+ def log_approval(
222
+ self,
223
+ realization_package: Dict[str, Any],
224
+ user_response: str,
225
+ approved: bool,
226
+ agent_name: str,
227
+ phase: str
228
+ ):
229
+ """
230
+ Log the approval decision for audit trail.
231
+
232
+ This creates a permanent record of all approval decisions
233
+ for compliance and troubleshooting purposes.
234
+ """
235
+
236
+ log_entry = {
237
+ "timestamp": datetime.now().isoformat(),
238
+ "agent": agent_name,
239
+ "phase": phase,
240
+ "approved": approved,
241
+ "user_response": user_response,
242
+ "files_count": len(realization_package.get("files", [])),
243
+ "operations": self._get_critical_operations(realization_package),
244
+ "git_commit": realization_package.get("git_operations", {}).get("commit_message", "N/A")
245
+ }
246
+
247
+ # Append to JSONL log file
248
+ with open(self.approval_log_path, "a") as f:
249
+ f.write(json.dumps(log_entry) + "\n")
250
+
251
+ return log_entry
252
+
253
+
254
+ # Convenience function for orchestrator to use
255
+ def request_approval(
256
+ realization_package: Dict[str, Any],
257
+ agent_name: str,
258
+ phase: str
259
+ ) -> Dict[str, Any]:
260
+ """
261
+ Main function to request approval from user.
262
+
263
+ This should be called by the orchestrator in Phase 4 (Approval Gate).
264
+
265
+ Args:
266
+ realization_package: The complete realization package from the agent
267
+ agent_name: Name of the agent that generated the plan
268
+ phase: Current phase identifier
269
+
270
+ Returns:
271
+ Dict with:
272
+ - summary: String to present to user
273
+ - question_config: Dict to pass to AskUserQuestion tool
274
+ """
275
+
276
+ gate = ApprovalGate()
277
+
278
+ return {
279
+ "summary": gate.generate_summary(realization_package),
280
+ "question_config": gate.generate_approval_question(realization_package, agent_name, phase),
281
+ "gate_instance": gate
282
+ }
283
+
284
+
285
+ def process_approval_response(
286
+ gate_instance: ApprovalGate,
287
+ user_response: str,
288
+ realization_package: Dict[str, Any],
289
+ agent_name: str,
290
+ phase: str
291
+ ) -> Dict[str, Any]:
292
+ """
293
+ Process the user's approval response.
294
+
295
+ Args:
296
+ gate_instance: The ApprovalGate instance from request_approval
297
+ user_response: The user's response from AskUserQuestion
298
+ realization_package: The realization package
299
+ agent_name: Name of the agent
300
+ phase: Current phase
301
+
302
+ Returns:
303
+ Dict with validation result and action to take
304
+ """
305
+
306
+ # Validate response
307
+ validation = gate_instance.validate_approval_response(user_response)
308
+
309
+ # Log the decision
310
+ gate_instance.log_approval(
311
+ realization_package,
312
+ user_response,
313
+ validation["approved"],
314
+ agent_name,
315
+ phase
316
+ )
317
+
318
+ return validation