@jaguilar87/gaia-ops 2.2.0 → 2.2.2
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.
- package/CHANGELOG.md +137 -1
- package/README.en.md +29 -23
- package/README.md +24 -17
- package/agents/{claude-architect.md → gaia.md} +6 -6
- package/commands/{architect.md → gaia.md} +6 -6
- package/config/AGENTS.md +5 -5
- package/config/agent-catalog.md +14 -14
- package/config/context-contracts.md +4 -4
- package/config/embeddings_info.json +14 -0
- package/config/intent_embeddings.json +2002 -0
- package/config/intent_embeddings.npy +0 -0
- package/index.js +3 -1
- package/package.json +3 -2
- package/speckit/README.en.md +20 -69
- package/templates/CLAUDE.template.md +5 -13
- package/tests/README.en.md +224 -0
- package/tests/README.md +338 -0
- package/tests/fixtures/project-context.aws.json +53 -0
- package/tests/fixtures/project-context.gcp.json +53 -0
- package/tests/integration/RUN_TESTS.md +185 -0
- package/tests/integration/__init__.py +0 -0
- package/tests/integration/test_hooks_integration.py +473 -0
- package/tests/integration/test_hooks_workflow.py +397 -0
- package/tests/permissions-validation/MANUAL_VALIDATION.md +434 -0
- package/tests/permissions-validation/test_permissions_validation.py +527 -0
- package/tests/system/__init__.py +0 -0
- package/tests/system/permissions_helpers.py +318 -0
- package/tests/system/test_agent_definitions.py +166 -0
- package/tests/system/test_configuration_files.py +121 -0
- package/tests/system/test_directory_structure.py +231 -0
- package/tests/system/test_permissions_system.py +1006 -0
- package/tests/tools/__init__.py +0 -0
- package/tests/tools/test_agent_router.py +266 -0
- package/tests/tools/test_clarify_engine.py +413 -0
- package/tests/tools/test_context_provider.py +157 -0
- package/tests/validators/__init__.py +0 -0
- package/tests/validators/test_approval_gate.py +415 -0
- package/tests/validators/test_commit_validator.py +446 -0
- package/tools/context_provider.py +28 -7
- package/tools/generate_embeddings.py +3 -3
- package/tools/semantic_matcher.py +2 -2
|
@@ -0,0 +1,231 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Test suite for Claude agent system directory structure
|
|
3
|
+
Validates all required directories and files exist
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
import pytest
|
|
7
|
+
from pathlib import Path
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
class TestCoreDirectories:
|
|
11
|
+
"""Test that all core package directories exist (gaia-ops npm package structure)"""
|
|
12
|
+
|
|
13
|
+
@pytest.fixture
|
|
14
|
+
def package_root(self):
|
|
15
|
+
"""Get the package root directory (gaia-ops/)"""
|
|
16
|
+
return Path(__file__).resolve().parents[2]
|
|
17
|
+
|
|
18
|
+
def test_package_directory_exists(self, package_root):
|
|
19
|
+
"""Package root directory must exist"""
|
|
20
|
+
assert package_root.exists(), "Package root directory not found"
|
|
21
|
+
assert package_root.is_dir(), "Package root path is not a directory"
|
|
22
|
+
|
|
23
|
+
def test_required_directories_exist(self, package_root):
|
|
24
|
+
"""All required npm package directories must exist"""
|
|
25
|
+
# Directories that should be in the published npm package
|
|
26
|
+
required_dirs = [
|
|
27
|
+
"tools",
|
|
28
|
+
"agents",
|
|
29
|
+
"hooks",
|
|
30
|
+
"commands",
|
|
31
|
+
"speckit",
|
|
32
|
+
"templates",
|
|
33
|
+
"config",
|
|
34
|
+
"tests",
|
|
35
|
+
"bin"
|
|
36
|
+
]
|
|
37
|
+
|
|
38
|
+
for dir_name in required_dirs:
|
|
39
|
+
dir_path = package_root / dir_name
|
|
40
|
+
# Follow symlinks
|
|
41
|
+
if dir_path.is_symlink():
|
|
42
|
+
dir_path = dir_path.resolve()
|
|
43
|
+
assert dir_path.exists(), f"Required directory missing: {dir_name}"
|
|
44
|
+
assert dir_path.is_dir(), f"{dir_name} exists but is not a directory"
|
|
45
|
+
|
|
46
|
+
def test_config_has_required_files(self, package_root):
|
|
47
|
+
"""Config directory should have contracts and standards"""
|
|
48
|
+
config_dir = package_root / "config"
|
|
49
|
+
required_files = [
|
|
50
|
+
"context-contracts.gcp.json",
|
|
51
|
+
"context-contracts.aws.json",
|
|
52
|
+
"git_standards.json",
|
|
53
|
+
"intent_embeddings.json"
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
for file_name in required_files:
|
|
57
|
+
file_path = config_dir / file_name
|
|
58
|
+
assert file_path.exists(), f"Required config file missing: {file_name}"
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
class TestAgentsDirectory:
|
|
62
|
+
"""Test agents directory structure and contents"""
|
|
63
|
+
|
|
64
|
+
@pytest.fixture
|
|
65
|
+
def agents_dir(self):
|
|
66
|
+
"""Get the agents directory path"""
|
|
67
|
+
agents = Path(__file__).resolve().parents[2] / "agents"
|
|
68
|
+
return agents.resolve() if agents.is_symlink() else agents
|
|
69
|
+
|
|
70
|
+
def test_all_project_agents_exist(self, agents_dir):
|
|
71
|
+
"""All 5 project agents must exist"""
|
|
72
|
+
required_agents = [
|
|
73
|
+
"gitops-operator.md",
|
|
74
|
+
"gcp-troubleshooter.md",
|
|
75
|
+
"terraform-architect.md",
|
|
76
|
+
"devops-developer.md",
|
|
77
|
+
"aws-troubleshooter.md"
|
|
78
|
+
]
|
|
79
|
+
|
|
80
|
+
for agent in required_agents:
|
|
81
|
+
agent_path = agents_dir / agent
|
|
82
|
+
assert agent_path.exists(), f"Agent missing: {agent}"
|
|
83
|
+
|
|
84
|
+
def test_agent_files_not_empty(self, agents_dir):
|
|
85
|
+
"""All agent files should have substantial content"""
|
|
86
|
+
for agent_file in agents_dir.glob("*.md"):
|
|
87
|
+
content = agent_file.read_text()
|
|
88
|
+
assert len(content) > 100, f"Agent file too small: {agent_file.name}"
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
class TestToolsDirectory:
|
|
92
|
+
"""Test tools directory structure and contents"""
|
|
93
|
+
|
|
94
|
+
@pytest.fixture
|
|
95
|
+
def tools_dir(self):
|
|
96
|
+
"""Get the tools directory path"""
|
|
97
|
+
tools = Path(__file__).resolve().parents[2] / "tools"
|
|
98
|
+
return tools.resolve() if tools.is_symlink() else tools
|
|
99
|
+
|
|
100
|
+
def test_critical_tools_exist(self, tools_dir):
|
|
101
|
+
"""All critical tools must exist"""
|
|
102
|
+
critical_tools = [
|
|
103
|
+
"context_provider.py",
|
|
104
|
+
"context_section_reader.py",
|
|
105
|
+
"agent_router.py",
|
|
106
|
+
"semantic_matcher.py",
|
|
107
|
+
"generate_embeddings.py",
|
|
108
|
+
"approval_gate.py",
|
|
109
|
+
"commit_validator.py",
|
|
110
|
+
"task_manager.py",
|
|
111
|
+
"agent_invoker_helper.py"
|
|
112
|
+
]
|
|
113
|
+
|
|
114
|
+
for tool in critical_tools:
|
|
115
|
+
tool_path = tools_dir / tool
|
|
116
|
+
assert tool_path.exists(), f"Critical tool missing: {tool}"
|
|
117
|
+
|
|
118
|
+
def test_quicktriage_scripts_exist(self, tools_dir):
|
|
119
|
+
"""All QuickTriage scripts must exist"""
|
|
120
|
+
quicktriage_scripts = [
|
|
121
|
+
"quicktriage_gitops_operator.sh",
|
|
122
|
+
"quicktriage_gcp_troubleshooter.sh",
|
|
123
|
+
"quicktriage_terraform_architect.sh",
|
|
124
|
+
"quicktriage_devops_developer.sh",
|
|
125
|
+
"quicktriage_aws_troubleshooter.sh"
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
for script in quicktriage_scripts:
|
|
129
|
+
script_path = tools_dir / script
|
|
130
|
+
assert script_path.exists(), f"QuickTriage script missing: {script}"
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
class TestHooksDirectory:
|
|
134
|
+
"""Test hooks directory structure and contents"""
|
|
135
|
+
|
|
136
|
+
@pytest.fixture
|
|
137
|
+
def hooks_dir(self):
|
|
138
|
+
"""Get the hooks directory path"""
|
|
139
|
+
hooks = Path(__file__).resolve().parents[2] / "hooks"
|
|
140
|
+
return hooks.resolve() if hooks.is_symlink() else hooks
|
|
141
|
+
|
|
142
|
+
def test_security_hooks_exist(self, hooks_dir):
|
|
143
|
+
"""All security hooks must exist"""
|
|
144
|
+
required_hooks = [
|
|
145
|
+
"pre_tool_use.py",
|
|
146
|
+
"post_tool_use.py",
|
|
147
|
+
"subagent_stop.py"
|
|
148
|
+
]
|
|
149
|
+
|
|
150
|
+
for hook in required_hooks:
|
|
151
|
+
hook_path = hooks_dir / hook
|
|
152
|
+
assert hook_path.exists(), f"Security hook missing: {hook}"
|
|
153
|
+
|
|
154
|
+
def test_hooks_are_executable(self, hooks_dir):
|
|
155
|
+
"""Hook files should be executable or have proper permissions"""
|
|
156
|
+
for hook_file in hooks_dir.glob("*.py"):
|
|
157
|
+
content = hook_file.read_text()
|
|
158
|
+
assert "def " in content, f"Hook has no functions: {hook_file.name}"
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
class TestConfigDirectory:
|
|
162
|
+
"""Test config directory structure and contents"""
|
|
163
|
+
|
|
164
|
+
@pytest.fixture
|
|
165
|
+
def config_dir(self):
|
|
166
|
+
"""Get the config directory path"""
|
|
167
|
+
config = Path(__file__).resolve().parents[2] / "config"
|
|
168
|
+
return config.resolve() if config.is_symlink() else config
|
|
169
|
+
|
|
170
|
+
def test_git_standards_exist(self, config_dir):
|
|
171
|
+
"""git_standards.json must exist"""
|
|
172
|
+
git_standards = config_dir / "git_standards.json"
|
|
173
|
+
assert git_standards.exists(), "git_standards.json not found"
|
|
174
|
+
|
|
175
|
+
def test_config_files_valid_json(self, config_dir):
|
|
176
|
+
"""All JSON config files should be valid"""
|
|
177
|
+
import json
|
|
178
|
+
|
|
179
|
+
if not config_dir.exists():
|
|
180
|
+
pytest.skip("config/ directory not found")
|
|
181
|
+
|
|
182
|
+
for config_file in config_dir.glob("*.json"):
|
|
183
|
+
try:
|
|
184
|
+
with open(config_file, 'r') as f:
|
|
185
|
+
json.load(f)
|
|
186
|
+
except json.JSONDecodeError as e:
|
|
187
|
+
pytest.fail(f"Invalid JSON in {config_file.name}: {e}")
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
class TestSpecKitDirectory:
|
|
191
|
+
"""Test Spec-Kit directory structure"""
|
|
192
|
+
|
|
193
|
+
@pytest.fixture
|
|
194
|
+
def speckit_dir(self):
|
|
195
|
+
"""Get the speckit directory path"""
|
|
196
|
+
speckit = Path(__file__).resolve().parents[2] / "speckit"
|
|
197
|
+
return speckit.resolve() if speckit.is_symlink() else speckit
|
|
198
|
+
|
|
199
|
+
def test_speckit_subdirectories_exist(self, speckit_dir):
|
|
200
|
+
"""Spec-Kit subdirectories must exist"""
|
|
201
|
+
required_subdirs = ["templates", "decisions"]
|
|
202
|
+
|
|
203
|
+
for subdir in required_subdirs:
|
|
204
|
+
subdir_path = speckit_dir / subdir
|
|
205
|
+
assert subdir_path.exists(), f"Spec-Kit subdirectory missing: {subdir}"
|
|
206
|
+
|
|
207
|
+
def test_speckit_templates_exist(self, speckit_dir):
|
|
208
|
+
"""Spec-Kit templates must exist"""
|
|
209
|
+
templates_dir = speckit_dir / "templates"
|
|
210
|
+
required_templates = [
|
|
211
|
+
"spec-template.md",
|
|
212
|
+
"plan-template.md",
|
|
213
|
+
"tasks-template.md",
|
|
214
|
+
"adr-template.md"
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
for template in required_templates:
|
|
218
|
+
template_path = templates_dir / template
|
|
219
|
+
assert template_path.exists(), f"Spec-Kit template missing: {template}"
|
|
220
|
+
|
|
221
|
+
def test_governance_file_exists(self, speckit_dir):
|
|
222
|
+
"""governance.md must exist"""
|
|
223
|
+
governance = speckit_dir / "governance.md"
|
|
224
|
+
assert governance.exists(), "governance.md not found"
|
|
225
|
+
|
|
226
|
+
content = governance.read_text()
|
|
227
|
+
assert len(content) > 1000, "governance.md seems too small"
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
if __name__ == "__main__":
|
|
231
|
+
pytest.main([__file__, "-v"])
|