WP-0004: ecosystem integration complete
Add Helix Forge correlation (HELIX_SESSION_UID env, metrics correlate), artifact-store publish (metrics publish), activity-core ActivityDefinition references, integration patterns docs, and canon/knowledge design artifacts.
This commit is contained in:
161
tests/test_helix_correlation.py
Normal file
161
tests/test_helix_correlation.py
Normal file
@@ -0,0 +1,161 @@
|
||||
"""Tests for Helix Forge correlation (WP-0004 Part 1)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
import os
|
||||
import sqlite3
|
||||
from pathlib import Path
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from kaizen_agentic.cli import cli
|
||||
from kaizen_agentic.integrations.helix import (
|
||||
HelixCorrelationAdapter,
|
||||
enrich_helix_correlation,
|
||||
)
|
||||
|
||||
|
||||
def test_enrich_helix_correlation_from_env(monkeypatch: pytest.MonkeyPatch):
|
||||
monkeypatch.setenv("HELIX_SESSION_UID", "claude:test-uid")
|
||||
monkeypatch.setenv("HELIX_REPO", "kaizen-agentic")
|
||||
monkeypatch.setenv("HELIX_FLAVOR", "claude")
|
||||
monkeypatch.setenv("HELIX_TOKENS", "9900")
|
||||
monkeypatch.setenv("HELIX_INFRA_OVERHEAD_SHARE", "0.15")
|
||||
|
||||
result = enrich_helix_correlation({"success": True})
|
||||
|
||||
assert result["helix_session_uid"] == "claude:test-uid"
|
||||
assert result["repo"] == "kaizen-agentic"
|
||||
assert result["flavor"] == "claude"
|
||||
assert result["tokens"] == 9900
|
||||
assert result["infra_overhead_share"] == 0.15
|
||||
|
||||
|
||||
def test_enrich_does_not_override_existing_fields():
|
||||
record = {
|
||||
"success": True,
|
||||
"helix_session_uid": "grok:existing",
|
||||
"repo": "other-repo",
|
||||
}
|
||||
result = enrich_helix_correlation(record)
|
||||
assert result["helix_session_uid"] == "grok:existing"
|
||||
assert result["repo"] == "other-repo"
|
||||
|
||||
|
||||
def test_adapter_stub_when_store_unconfigured():
|
||||
adapter = HelixCorrelationAdapter(store_db=None)
|
||||
summary = adapter.lookup("claude:missing")
|
||||
assert summary["adapter"] == "stub"
|
||||
assert summary["status"] == "not_configured"
|
||||
|
||||
|
||||
def test_adapter_sqlite_lookup(tmp_path: Path):
|
||||
db_path = tmp_path / "store.db"
|
||||
conn = sqlite3.connect(db_path)
|
||||
conn.execute(
|
||||
"CREATE TABLE digests (session_uid TEXT PRIMARY KEY, json TEXT NOT NULL)"
|
||||
)
|
||||
conn.execute(
|
||||
"CREATE TABLE sessions (session_uid TEXT PRIMARY KEY, json TEXT NOT NULL)"
|
||||
)
|
||||
digest = {
|
||||
"outcome": "success",
|
||||
"cost": {"input_tokens": 800, "output_tokens": 200, "wall_clock_s": 3600},
|
||||
"tool_histogram": {"mcp__state-hub__x": 3, "Bash": 7},
|
||||
"markers": {"errors": 0, "retries": 1},
|
||||
}
|
||||
session = {"repo": "demo-app", "flavor": "claude"}
|
||||
conn.execute(
|
||||
"INSERT INTO digests VALUES (?, ?)",
|
||||
("claude:abc", json.dumps(digest)),
|
||||
)
|
||||
conn.execute(
|
||||
"INSERT INTO sessions VALUES (?, ?)",
|
||||
("claude:abc", json.dumps(session)),
|
||||
)
|
||||
conn.commit()
|
||||
conn.close()
|
||||
|
||||
adapter = HelixCorrelationAdapter(store_db=db_path)
|
||||
summary = adapter.lookup("claude:abc")
|
||||
|
||||
assert summary["adapter"] == "helix-sqlite"
|
||||
assert summary["repo"] == "demo-app"
|
||||
assert summary["flavor"] == "claude"
|
||||
assert summary["fleet_outcome"] == "success"
|
||||
assert summary["tokens"] == 1000
|
||||
assert summary["wall_clock_s"] == 3600
|
||||
assert summary["infra_overhead_share"] == 0.3
|
||||
|
||||
|
||||
class TestHelixCorrelationCli:
|
||||
def test_record_populates_helix_uid_from_env(
|
||||
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
monkeypatch.setenv("HELIX_SESSION_UID", "claude:session-42")
|
||||
monkeypatch.setenv("HELIX_REPO", "kaizen-agentic")
|
||||
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[
|
||||
"metrics",
|
||||
"record",
|
||||
"tdd-workflow",
|
||||
"--target",
|
||||
str(tmp_path),
|
||||
"--success",
|
||||
"--time",
|
||||
"10",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
|
||||
show = runner.invoke(
|
||||
cli,
|
||||
["metrics", "show", "tdd-workflow", "--target", str(tmp_path)],
|
||||
)
|
||||
assert "claude:session-42" in show.output
|
||||
assert "kaizen-agentic" in show.output
|
||||
|
||||
def test_correlate_stub_output(self):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(cli, ["metrics", "correlate", "claude:stub-uid"])
|
||||
assert result.exit_code == 0
|
||||
payload = json.loads(result.output)
|
||||
assert payload["helix_session_uid"] == "claude:stub-uid"
|
||||
assert payload["adapter"] == "stub"
|
||||
|
||||
def test_brief_works_with_correlated_metrics(
|
||||
self, tmp_path: Path, monkeypatch: pytest.MonkeyPatch
|
||||
):
|
||||
memory_dir = tmp_path / ".kaizen" / "agents" / "tdd-workflow"
|
||||
memory_dir.mkdir(parents=True)
|
||||
(memory_dir / "memory.md").write_text(
|
||||
"---\nagent: tdd-workflow\nproject: demo\nsession_count: 1\n---\n\n## Session Log\n",
|
||||
encoding="utf-8",
|
||||
)
|
||||
monkeypatch.setenv("HELIX_SESSION_UID", "claude:brief-test")
|
||||
|
||||
runner = CliRunner()
|
||||
runner.invoke(
|
||||
cli,
|
||||
[
|
||||
"metrics",
|
||||
"record",
|
||||
"tdd-workflow",
|
||||
"--target",
|
||||
str(tmp_path),
|
||||
"--success",
|
||||
"--quality",
|
||||
"0.9",
|
||||
],
|
||||
)
|
||||
brief = runner.invoke(
|
||||
cli,
|
||||
["memory", "brief", "tdd-workflow", "--target", str(tmp_path)],
|
||||
)
|
||||
assert brief.exit_code == 0
|
||||
assert "## Performance Summary" in brief.output
|
||||
33
tests/test_integration_patterns.py
Normal file
33
tests/test_integration_patterns.py
Normal file
@@ -0,0 +1,33 @@
|
||||
"""Smoke tests for WP-0004 integration artifacts."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from pathlib import Path
|
||||
|
||||
import yaml
|
||||
|
||||
|
||||
DEFINITIONS_DIR = (
|
||||
Path(__file__).parent.parent / "docs" / "integrations" / "activity-definitions"
|
||||
)
|
||||
|
||||
|
||||
def test_activity_definitions_have_required_frontmatter():
|
||||
files = list(DEFINITIONS_DIR.glob("*.md"))
|
||||
assert len(files) == 3
|
||||
|
||||
for path in files:
|
||||
text = path.read_text(encoding="utf-8")
|
||||
assert text.startswith("---\n")
|
||||
end = text.index("\n---\n", 4)
|
||||
frontmatter = yaml.safe_load(text[4:end])
|
||||
assert frontmatter["id"]
|
||||
assert frontmatter["trigger"]["type"] in ("cron", "event")
|
||||
assert frontmatter["owner"] == "kaizen-agentic"
|
||||
|
||||
|
||||
def test_integration_docs_exist():
|
||||
root = Path(__file__).parent.parent / "docs"
|
||||
assert (root / "INTEGRATION_PATTERNS.md").exists()
|
||||
assert (root / "integrations" / "helix-forge-correlation.md").exists()
|
||||
assert (root / "integrations" / "optimizer-artifact-manifest.md").exists()
|
||||
143
tests/test_metrics_publish.py
Normal file
143
tests/test_metrics_publish.py
Normal file
@@ -0,0 +1,143 @@
|
||||
"""Tests for artifact-store publish integration (WP-0004 Part 3)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from pathlib import Path
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from click.testing import CliRunner
|
||||
|
||||
from kaizen_agentic.cli import cli
|
||||
from kaizen_agentic.integrations.artifact_store import (
|
||||
PublishResult,
|
||||
build_optimizer_manifest,
|
||||
publish_optimizer_evidence,
|
||||
)
|
||||
from kaizen_agentic.metrics import OptimizerStore
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def project_with_optimizer(tmp_path: Path) -> Path:
|
||||
store = OptimizerStore(tmp_path)
|
||||
store.write_analysis(
|
||||
{
|
||||
"project": "demo",
|
||||
"optimized_at": "2026-06-18",
|
||||
"agents": [{"agent": "tdd-workflow"}],
|
||||
}
|
||||
)
|
||||
store.append_recommendations(
|
||||
"tdd-workflow",
|
||||
[{"type": "reliability", "message": "Improve test stability"}],
|
||||
metrics_count=10,
|
||||
)
|
||||
return tmp_path
|
||||
|
||||
|
||||
def test_build_optimizer_manifest(project_with_optimizer: Path):
|
||||
manifest = build_optimizer_manifest(project_with_optimizer)
|
||||
assert manifest["schema"] == "kaizen-agentic/optimizer-evidence/v1"
|
||||
assert manifest["retention_class"] == "raw-evidence"
|
||||
assert manifest["retention_days"] == 180
|
||||
assert "tdd-workflow" in manifest["agents"]
|
||||
|
||||
|
||||
def test_publish_optimizer_evidence_calls_api(project_with_optimizer: Path):
|
||||
calls: list[tuple[str, str]] = []
|
||||
|
||||
def fake_json(method, base_url, path, token, payload):
|
||||
calls.append((method, path))
|
||||
if path == "/packages":
|
||||
return {"id": "pkg-123"}
|
||||
if path.endswith("/finalize"):
|
||||
return {"id": "pkg-123", "manifest_digest": "blake3:deadbeef"}
|
||||
raise AssertionError(path)
|
||||
|
||||
def fake_multipart(base_url, path, token, **kwargs):
|
||||
calls.append(("POST", path))
|
||||
return {"id": "file-1"}
|
||||
|
||||
with patch(
|
||||
"kaizen_agentic.integrations.artifact_store._http_json",
|
||||
side_effect=fake_json,
|
||||
), patch(
|
||||
"kaizen_agentic.integrations.artifact_store._http_multipart",
|
||||
side_effect=fake_multipart,
|
||||
):
|
||||
result = publish_optimizer_evidence(
|
||||
project_with_optimizer,
|
||||
api_url="http://api.test",
|
||||
token="secret",
|
||||
)
|
||||
|
||||
assert result.package_id == "pkg-123"
|
||||
assert result.files_uploaded == 2
|
||||
assert result.retention_class == "raw-evidence"
|
||||
assert calls[0] == ("POST", "/packages")
|
||||
assert any("/files" in path for _, path in calls)
|
||||
assert calls[-1] == ("POST", "/packages/pkg-123/finalize")
|
||||
|
||||
|
||||
class TestMetricsPublishCli:
|
||||
def test_publish_requires_token(self, project_with_optimizer: Path):
|
||||
runner = CliRunner()
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
["metrics", "publish", "--target", str(project_with_optimizer)],
|
||||
)
|
||||
assert result.exit_code != 0
|
||||
assert "token" in result.output.lower()
|
||||
|
||||
def test_publish_success(self, project_with_optimizer: Path):
|
||||
runner = CliRunner()
|
||||
with patch(
|
||||
"kaizen_agentic.cli.publish_optimizer_evidence",
|
||||
return_value=PublishResult(
|
||||
package_id="pkg-99",
|
||||
manifest_digest="blake3:abc",
|
||||
files_uploaded=2,
|
||||
retention_class="raw-evidence",
|
||||
),
|
||||
):
|
||||
result = runner.invoke(
|
||||
cli,
|
||||
[
|
||||
"metrics",
|
||||
"publish",
|
||||
"--target",
|
||||
str(project_with_optimizer),
|
||||
"--token",
|
||||
"test-token",
|
||||
"--api-url",
|
||||
"http://127.0.0.1:8000",
|
||||
],
|
||||
)
|
||||
assert result.exit_code == 0
|
||||
assert "pkg-99" in result.output
|
||||
|
||||
|
||||
@pytest.mark.integration
|
||||
def test_publish_against_live_artifact_store(project_with_optimizer: Path):
|
||||
"""Optional live test — skipped when artifact-store is unreachable."""
|
||||
import urllib.error
|
||||
import urllib.request
|
||||
|
||||
api_url = "http://127.0.0.1:8000"
|
||||
try:
|
||||
urllib.request.urlopen(f"{api_url}/health", timeout=2)
|
||||
except (urllib.error.URLError, TimeoutError):
|
||||
pytest.skip("artifact-store not reachable")
|
||||
|
||||
token = __import__("os").environ.get("ARTIFACTSTORE_API_TOKEN")
|
||||
if not token:
|
||||
pytest.skip("ARTIFACTSTORE_API_TOKEN not set")
|
||||
|
||||
result = publish_optimizer_evidence(
|
||||
project_with_optimizer,
|
||||
api_url=api_url,
|
||||
token=token,
|
||||
)
|
||||
assert result.package_id
|
||||
assert result.files_uploaded >= 1
|
||||
Reference in New Issue
Block a user