Observed since 20 Oct, 20:18 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
aegis-qa
Aegis — The AI Quality Control Plane
The AI Quality Control Plane
Aegis is a lightweight orchestration layer that unifies AI-powered QA tools into a single control plane. It coordinates route discovery, test generation, bug triage, and fix proposals across your development workflow.
graph TB
subgraph Aegis["Aegis — Control Plane"]
API[FastAPI API<br/>Typed OpenAPI Spec]
WF[Workflow Engine]
REG[Service Registry]
EV[Event System<br/>Emitter · Log · Webhooks]
HIST[History<br/>SQLite / In-Memory]
HP[Health Endpoint<br/>Version · Uptime · Config]
LP[Landing Page]
end
SDK[Python SDK<br/>AegisClient · AsyncAegisClient] --> API
subgraph Tools["QA Tool Suite"]
QA[QA Agent<br/>Route Discovery · Risk Analysis<br/>Test Generation · Orchestration]
BUG[Bugalizer<br/>Bug Triage · Code Localization<br/>Duplicate Detection]
end
subgraph LLM["LLM Backend"]
OLL[Ollama<br/>qwen2.5-coder:7b]
end
API --> WF
WF --> REG
WF --> HIST
WF --> EV
REG --> QA
REG --> BUG
QA --> OLL
BUG --> OLL
LP --> API
EV -->|webhooks| EXT[External Systems]
# Install from PyPI
pip install aegis-qa
# Or install from source (for development)
pip install -e ".[dev]"
# Configure
cp .aegis.yaml.example .aegis.yaml
# Edit .aegis.yaml with your service URLs
# Check service status
aegis status
# Run the full QA pipeline
aegis run full_pipeline
# Start the API server + landing page
aegis serve
The SDK is included when you pip install aegis-qa — no extra dependency needed.
from aegis_qa.client import AegisClient
# Sync client
with AegisClient(base_url="http://localhost:8000") as client:
health = client.health()
print(f"Status: {health.status}, uptime: {health.uptime_seconds}s")
services = client.list_services()
for svc in services:
print(f" {svc.name}: {svc.status}")
result = client.run_workflow("full_pipeline")
print(f"Pipeline {'passed' if result.success else 'failed'}")
from aegis_qa.client import AsyncAegisClient
# Async client
async with AsyncAegisClient(api_key="your-key") as client:
workflows = await client.list_workflows()
history = await client.recent_history(limit=5)
# Pull the latest image
docker pull ghcr.io/jblacketter/aegis:latest
# Or build locally
docker build -t aegis .
# Run the server
docker run -p 8000:8000 aegis
# Verify it's running
curl http://localhost:8000/health
# Start with SQLite persistence and config mounting
docker compose up
# Run in background
docker compose up -d
The compose file mounts .aegis.yaml (read-only) and persists the SQLite database on a named volume.
| Variable | Description | Default |
|---|---|---|
AEGIS_DB_PATH | Override SQLite database path | Value from .aegis.yaml |
| Tool | Description | Features |
|---|---|---|
| QA Agent | Route discovery, risk analysis, test generation & orchestration | Route Discovery, Risk Assessment, Test Generation, Test Orchestration, Branch Board |
| Bugalizer | AI-powered bug triage, code localization & fix proposals | Bug Triage, Code Localization, Duplicate Detection |
| Command | Description |
|---|---|
aegis status | Show all services and their health status |
aegis serve | Start API server and serve landing page |
aegis run <workflow> | Execute a named workflow pipeline |
aegis openapi | Export OpenAPI spec as JSON |
aegis config show | Print resolved configuration |
| Endpoint | Method | Description |
|---|---|---|
/health | GET | Health check with version, uptime, and config summary |
/api/services | GET | List services with health status |
/api/services/{name}/health | GET | Live health check for one service |
/api/workflows | GET | List all configured workflows |
/api/workflows/{name} | GET | Get a specific workflow definition |
/api/workflows/{name}/run | POST | Trigger a named workflow |
/api/workflows/{name}/history | GET | Execution history for a workflow |
/api/history | GET | Recent execution history across all workflows |
/api/events | GET | Recent events (filterable by type) |
/api/portfolio | GET | Tool metadata for landing page |
Aegis uses .aegis.yaml for configuration. See .aegis.yaml.example for the full schema.
Environment variables can be interpolated using ${VAR_NAME} syntax:
services:
qaagent:
url: ${QAAGENT_URL:-http://localhost:8080}
MIT
Download counts and popularity will appear here as the collector receives them.
| Package / target | Requirement | Relationship |
|---|---|---|
typerEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | typer>=0.12 | runtime |
pydanticEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | pydantic>=2.0 | runtime |
pydantic-settingsEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | pydantic-settings>=2.0 | runtime |
richEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | rich>=13.7 | runtime |
PyYAMLEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | PyYAML>=6.0 | runtime |
fastapiEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | fastapi>=0.110 | runtime |
uvicornEnvironment{
"extras": "standard",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | uvicorn[standard]>=0.27 | runtime |
httpxEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | httpx>=0.27 | runtime |
aiosqliteEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | aiosqlite>=0.20 | runtime |
prometheus_clientEnvironment{
"extras": "",
"marker": null,
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | prometheus_client>=0.20 | runtime |
pytestEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | pytest>=8.0; extra == "dev" | runtime |
pytest-asyncioEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | pytest-asyncio>=0.23; extra == "dev" | runtime |
pytest-covEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | pytest-cov>=6.0; extra == "dev" | runtime |
ruffEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | ruff>=0.8; extra == "dev" | runtime |
mypyEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | mypy>=1.13; extra == "dev" | runtime |
types-PyYAMLEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | types-PyYAML>=6.0; extra == "dev" | runtime |
pre-commitEnvironment{
"extras": "",
"marker": "extra == \"dev\"",
"requires_python": ">=3.11",
"evaluation": "NOT_EVALUATED"
} | pre-commit>=4.0; extra == "dev" | runtime |
bdist_wheel · 49.08 KB · Python py3
sdist · 65.32 KB · Python source
Observed since 20 Oct, 20:18 UTC
No superseded metadata states collected. Unchanged observations do not create new revisions.
package_version:f2748d3e56bca14aece362ca52b068b2fb6b2335599cc2e29df14e5307708d89