Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,12 @@ The project follows Semantic Versioning and the Keep a Changelog format.

### Added

### Changed

## [1.1.0] - 2026-08-18

### Added

- Python 3.10 and 3.11 CI matrix.
- API contract tests and expanded data-ingestion edge-case coverage.
- Coverage XML and JUnit test artifacts.
Expand Down Expand Up @@ -37,5 +43,6 @@ The project follows Semantic Versioning and the Keep a Changelog format.
- FastAPI service.
- Initial Docker and test infrastructure.

[Unreleased]: https://github.com/CoreyLeath-code/HelixAgent/compare/v1.0.0...HEAD
[Unreleased]: https://github.com/CoreyLeath-code/HelixAgent/compare/v1.1.0...HEAD
[1.1.0]: https://github.com/CoreyLeath-code/HelixAgent/compare/v1.0.0...v1.1.0
[1.0.0]: https://github.com/CoreyLeath-code/HelixAgent/releases/tag/v1.0.0
42 changes: 42 additions & 0 deletions RELEASE_NOTES_v1.1.0.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# HelixAgent v1.1.0

This release packages the existing runtime and aligns its release evidence with the implementation already on `main`. It covers validation, delivery, documentation correction, and the existing vector-backend design without adding a performance claim or a new product capability.

## Tag-triggered release contract

Pushing a newly created annotated `v1.1.0` tag triggers **HelixAgent Release**. The workflow checks out the exact tag commit; verifies the tag, `pyproject.toml` version, and changelog section; runs Ruff, pytest, the release-image C++-interop probe, CodeQL, secret scanning, and CycloneDX SBOM generation; then attaches a source archive, SHA-256 checksum, `helixagent-release-sbom`, and reproduction instructions to the GitHub Release before publishing the validated GHCR image.

## Added

- Python 3.10 and 3.11 CI matrix.
- API contract tests and expanded data-ingestion edge-case coverage.
- Coverage XML and JUnit test artifacts.
- Ruff correctness gates and Python syntax validation.
- Container build and live health smoke tests.
- CodeQL, Gitleaks, Trivy, pip-audit, Dependabot, and CycloneDX SBOM automation.
- GitHub Release artifacts and GHCR image publishing.
- Security, contribution, release-readiness, and nine-tier deployment-hygiene documentation.
- Evidence-driven semantic-tag release validation with source checksums, CycloneDX SBOM attachment, and reproducibility instructions.
- Three-way vector-backend benchmark infrastructure that writes measurements only when executed.

## Changed

- Hardened `DataIngestor` with file validation, split-parameter validation, deterministic partitioning, duplicate-column detection, and explicit types.
- Reworked the production image into isolated Java, C++, Python build stages and a non-root runtime stage.
- Made NumPy/BLAS the default cosine-similarity backend; the C++ ctypes backend is explicit opt-in interoperability and pure Python remains the degradation path.
- Hardened the ctypes boundary by coercing vectors to contiguous float64 buffers before pointer passing.
- Corrected vector-backend documentation to remove unsupported C++ performance claims.

## Verification

- SBOM artifact: `helixagent-release-sbom` (CycloneDX JSON).
- Source checksum: `sha256sum` of the deterministic `git archive` source tarball (`gzip -n`).
- Reproduce the release gates:

~~~bash
pip install -r requirements-dev.txt
ruff check api agent src tests streamlit_app.py --select E9,F63,F7,F82
pytest
docker build -t helixagent-release .
python -m benchmarks.vector_ops --output vector-ops-results.json
~~~
2 changes: 1 addition & 1 deletion agent/autonomy/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def close(self) -> None:
"""Release the database handle deterministically."""
self._connection.close()

def __enter__(self) -> SQLiteRunStore:
def __enter__(self) -> SQLiteRunStore: # noqa: PYI034 - Python 3.10 compatibility
return self

def __exit__(self, *_exc: object) -> None:
Expand Down
7 changes: 4 additions & 3 deletions agent/autonomy/tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@
from __future__ import annotations

import time
from concurrent.futures import ThreadPoolExecutor, TimeoutError as FutureTimeout
from collections.abc import Callable
from concurrent.futures import ThreadPoolExecutor
from concurrent.futures import TimeoutError as FutureTimeout
from dataclasses import dataclass
from typing import Any, Callable
from typing import Any

from agent.autonomy.models import Observation, RiskLevel, Task


ToolHandler = Callable[[dict[str, Any]], Any]


Expand Down
10 changes: 6 additions & 4 deletions agent/reporter.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
# agent/reporter.py
import os
import datetime
import os
import subprocess

from openai import OpenAI # Or your framework's custom wrapper


def get_git_metadata():
"""Extracts recent activity directly from the repository environment."""
try:
Expand All @@ -14,13 +16,13 @@ def get_git_metadata():
["git", "diff", "HEAD~1", "HEAD"]
).decode("utf-8")[:2000] # Cap to prevent context blowing up
return commits, diff
except Exception:
except (OSError, subprocess.CalledProcessError):
return "No recent commits found or shallow clone.", ""

def generate_daily_log():
client = OpenAI(api_key=os.getenv("OPENAI_API_KEY"))
commits, diff = get_git_metadata()
date_str = datetime.date.today().strftime("%Y-%m-%d")
date_str = datetime.datetime.now(datetime.timezone.utc).date().strftime("%Y-%m-%d")

prompt = f"""
You are an autonomous MLOps & System Hygiene Agent responsible for maintaining HelixAgent.
Expand Down Expand Up @@ -56,7 +58,7 @@ def generate_daily_log():
with open(log_file, "r") as f:
existing_content = f.read()

header = f"# HelixAgent Autonomous Logs\n\n" if not existing_content else ""
header = "# HelixAgent Autonomous Logs\n\n" if not existing_content else ""

new_entry = f"## Log Entry: {date_str}\n\n{log_content}\n\n---\n\n"

Expand Down
5 changes: 2 additions & 3 deletions agent/tools/sagemaker_job.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,8 @@
AWS_DEFAULT_REGION
"""


import boto3
import json
from typing import Dict

sm_client = boto3.client("sagemaker")
runtime = boto3.client("sagemaker-runtime")
Expand Down Expand Up @@ -50,7 +49,7 @@ def start_batch_transform(job_name: str,
)
return response["TransformJobArn"]

def get_batch_status(job_name: str) -> Dict:
def get_batch_status(job_name: str) -> dict:
"""Return status dict for batch job."""
return sm_client.describe_transform_job(TransformJobName=job_name)

Expand Down
30 changes: 6 additions & 24 deletions agent/tools/snowflake_query.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
"""
snowflake_query.py
"""snowflake_query.py
==================
Tool for the Agentic AI Assistant: execute parameterized SQL against
Snowflake and return results in a Pythonic format (list[dict]).
Expand All @@ -19,9 +18,10 @@
"""

import os
import snowflake.connector
from contextlib import contextmanager
from typing import List, Dict

import snowflake.connector


@contextmanager
def snowflake_connection():
Expand All @@ -38,30 +38,12 @@ def snowflake_connection():
finally:
conn.close()

def run_query(sql: str, params: tuple | None = None) -> List[Dict]:
"""
Execute SQL and return results as list of dicts.

Parameters
----------
sql : str
Parameterized SQL (use %s placeholders).
params : tuple | None
Values for placeholders.

Returns
-------
list[dict]
Query results with keys=column names, values=rows.
"""
def run_query(sql: str, params: tuple | None = None) -> list[dict]:
"""Execute SQL and return results as list of dictionaries."""
with snowflake_connection() as conn:
cur = conn.cursor(snowflake.connector.DictCursor)
cur.execute(sql, params) if params else cur.execute(sql)
results = cur.fetchall()
cur.close()
return results

# Quick CLI test (commented; ensure env vars first)
# if __name__ == "__main__":
# rows = run_query("SELECT CURRENT_TIMESTAMP() AS ts")
# print(rows)
21 changes: 21 additions & 0 deletions agent/version.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
"""Resolve HelixAgent's version from installed package metadata or pyproject.toml."""

from __future__ import annotations

import re
from importlib.metadata import PackageNotFoundError, version
from pathlib import Path

_PROJECT_VERSION = re.compile(r'^version\s*=\s*"(?P<version>[^"]+)"\s*$', re.MULTILINE)


def get_version() -> str:
"""Return the installed distribution version or the source-tree project version."""
try:
return version("helixagent")
except PackageNotFoundError:
pyproject = Path(__file__).resolve().parents[1] / "pyproject.toml"
match = _PROJECT_VERSION.search(pyproject.read_text(encoding="utf-8"))
if match is None:
raise RuntimeError("Could not determine the HelixAgent project version.")
return match.group("version")
7 changes: 5 additions & 2 deletions api/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,15 @@
from agent.autonomy.models import AgentRun
from agent.autonomy.runtime import AutonomousRuntime
from agent.autonomy.store import RunNotFoundError
from agent.version import get_version
from api.monitoring import setup_monitoring

APP_VERSION = get_version()

app = FastAPI(
title="HelixAgent API",
description="Modular AI agent framework for automation, reasoning, and decision-making.",
version="1.0.0",
version=APP_VERSION,
)

# Attach Prometheus metrics + OpenTelemetry tracing
Expand Down Expand Up @@ -54,7 +57,7 @@ async def root():
@app.get("/health", tags=["Operations"])
async def health():
"""Liveness / readiness probe for container orchestration."""
return {"status": "healthy", "version": "1.0.0"}
return {"status": "healthy", "version": APP_VERSION}


@app.post("/predict", tags=["Agent"])
Expand Down
2 changes: 1 addition & 1 deletion api/monitoring.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@
import os
import time

from fastapi import FastAPI, Request
from opentelemetry import trace
from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
from opentelemetry.sdk.trace import TracerProvider
from opentelemetry.sdk.trace.export import BatchSpanProcessor, ConsoleSpanExporter
from fastapi import FastAPI, Request
from prometheus_client import CONTENT_TYPE_LATEST, Counter, Histogram, generate_latest
from starlette.responses import Response

Expand Down
2 changes: 1 addition & 1 deletion config/config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# General project settings
project:
name: "HelixAgent"
version: "1.0.0"
version: "1.1.0"
author: "Corey Leath"
description: "Modular AI agent framework for automation, reasoning, and decision-making."

Expand Down
2 changes: 1 addition & 1 deletion github/ISSUE_TEMPLATE/bug_report.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ body:
placeholder: |
- OS: Ubuntu 22.04
- Python: 3.10.12
- Docker tag: agentic-ai:1.0.0
- Docker tag: helixagent:1.1.0
- Commit: abc123
validations:
required: true
Expand Down
2 changes: 1 addition & 1 deletion helm/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ name: helixagent
description: A modular AI agent framework deployed with Kubernetes + Helm
type: application
version: 0.1.0
appVersion: "1.0.0"
appVersion: "1.1.0"
maintainers:
- name: Corey Leath
email: corey.leath@example.com
2 changes: 1 addition & 1 deletion helm/configmap.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ data:
config.yaml: |
project:
name: "HelixAgent"
version: "1.0.0"
version: "1.1.0"
author: "Corey Leath"
description: "Modular AI agent framework for automation, reasoning, and decision-making."

Expand Down
2 changes: 1 addition & 1 deletion infra/helm/agentic-ai-assistant/Chart.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,4 +3,4 @@ name: agentic-ai-assistant
description: Helm chart for deploying the Agentic AI Assistant (Python + Java + C++)
type: application
version: 0.1.0
appVersion: "1.0.0"
appVersion: "1.1.0"
19 changes: 18 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,12 +1,29 @@
[project]
name = "helixagent"
version = "1.0.0"
version = "1.1.0"
description = "Deterministic budgeted agent runtime with governed tools and SQLite checkpoints."
readme = "README.md"
requires-python = ">=3.10"
license = { text = "MIT" }
authors = [{ name = "Corey Leath" }]

[project.urls]
Homepage = "https://github.com/CoreyLeath-code/HelixAgent"
Repository = "https://github.com/CoreyLeath-code/HelixAgent"
Changelog = "https://github.com/CoreyLeath-code/HelixAgent/blob/main/CHANGELOG.md"

[build-system]
requires = ["setuptools>=68", "wheel"]
build-backend = "setuptools.build_meta"

[tool.setuptools.packages.find]
where = ["."]
include = ["agent*", "api*", "src*"]
namespaces = true

[tool.ruff.lint.per-file-ignores]
"src/main.py" = ["RUF100"]

[tool.pytest.ini_options]
testpaths = ["tests"]
pythonpath = ["."]
Expand Down
1 change: 1 addition & 0 deletions requirements-dev.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
-r requirements.txt
setuptools>=68,<81
pytest-asyncio>=0.23.7
ruff>=0.9.0
mypy>=1.14.0
Expand Down
3 changes: 2 additions & 1 deletion src/utils/logger.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,10 @@
Ensures consistent, professional logs across all modules.
"""

from loguru import logger
import sys

from loguru import logger


def setup_logger(log_file: str = "logs/helixagent.log", level: str = "INFO"):
"""
Expand Down
5 changes: 3 additions & 2 deletions src/utils/tracker.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"""

import mlflow

from src.utils.logger import setup_logger

log = setup_logger()
Expand All @@ -26,7 +27,7 @@ def __init__(self, experiment_name: str = "HelixAgent-Experiments", tracking_uri
mlflow.set_experiment(experiment_name)
log.info(f"Initialized MLflow tracker: {experiment_name}")

def start_run(self, run_name: str = None):
def start_run(self, run_name: str | None = None):
"""Start a new MLflow run"""
return mlflow.start_run(run_name=run_name)

Expand All @@ -35,7 +36,7 @@ def log_params(self, params: dict):
mlflow.log_params(params)
log.debug(f"Logged parameters: {params}")

def log_metrics(self, metrics: dict, step: int = None):
def log_metrics(self, metrics: dict, step: int | None = None):
"""Log metrics to MLflow"""
mlflow.log_metrics(metrics, step=step)
log.debug(f"Logged metrics: {metrics}")
Expand Down
2 changes: 1 addition & 1 deletion streamlit_app.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,7 @@ def main() -> None:
with st.spinner("Planning and executing the workflow..."):
try:
response, elapsed = run_agent(prompt.strip())
except Exception as exc: # pragma: no cover - defensive UI boundary
except Exception as exc: # noqa: BLE001 - defensive UI boundary
st.error("HelixAgent could not complete this request.")
st.exception(exc)
else:
Expand Down
3 changes: 2 additions & 1 deletion tests/test_runtime_invariants.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@
from pathlib import Path

import pytest
from hypothesis import given, strategies as st
from hypothesis import given
from hypothesis import strategies as st

from agent import agent_core
from agent.autonomy.models import GoalSpec, RunStatus, Task
Expand Down
Loading