From ec7a33d31f17c20874ed70c4a2f5591b9a99c639 Mon Sep 17 00:00:00 2001 From: agent-db0ec53c058f1326 Date: Wed, 15 Apr 2026 22:39:37 +0200 Subject: [PATCH] build(agent): molt-z#db0ec5 iteration --- README.md | 4 + .../adapters/dsl_bridge.py | 24 ++++++ .../dsl.py | 79 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 opengrowth_privacy_preserving_federated_/adapters/dsl_bridge.py create mode 100644 opengrowth_privacy_preserving_federated_/dsl.py diff --git a/README.md b/README.md index 79f3eb4..9e5e26b 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,10 @@ This repository contains a minimal, self-contained Python MVP for a privacy-preserving federated growth experimentation platform. +- New: DSL sketch and bridge for CatOpt-inspired federation primitives + - opengrowth_privacy_preserving_federated_/dsl.py provides LocalExperiment, SharedSignal, and PlanDelta data models as a minimal DSL surface. + - opengrowth_privacy_preserving_federated_/adapters/dsl_bridge.py offers a small bridge to convert local metrics via existing adapters (GA4Adapter, SegmentAdapter) into a canonical representation for federation. + - Exposes a lightweight API surface used by tests: - SchemaRegistry, ExperimentTemplate - SecureAggregator, CloudLedger, AccessControl, Governance diff --git a/opengrowth_privacy_preserving_federated_/adapters/dsl_bridge.py b/opengrowth_privacy_preserving_federated_/adapters/dsl_bridge.py new file mode 100644 index 0000000..f7fc639 --- /dev/null +++ b/opengrowth_privacy_preserving_federated_/adapters/dsl_bridge.py @@ -0,0 +1,24 @@ +from typing import Dict, Any + +from .ga4 import GA4Adapter +from .segment import SegmentAdapter + + +class DSLBridgeAdapter: + """A tiny bridge that translates local metrics into a canonical DSL-ready + representation using a chosen adapter. + + The bridge does not attempt to perform any privacy-preserving operations; + it merely maps source metrics to the standard keys used by downstream + federation components. + """ + + def __init__(self, adapter: object = None): + self.adapter = adapter or GA4Adapter() + + def fill(self, source_metrics: Dict[str, Any]) -> Dict[str, Any]: + # Delegate to the provided adapter to normalize keys + return self.adapter.fill(source_metrics) + + +__all__ = ["DSLBridgeAdapter"] diff --git a/opengrowth_privacy_preserving_federated_/dsl.py b/opengrowth_privacy_preserving_federated_/dsl.py new file mode 100644 index 0000000..6d7c853 --- /dev/null +++ b/opengrowth_privacy_preserving_federated_/dsl.py @@ -0,0 +1,79 @@ +"""OpenGrowth DSL sketch for CatOpt-inspired federation primitives. + +This module provides a lightweight, self-contained Domain-Specific Language +sketch that models local experiments, exchanged signals, and incremental plan +updates in a privacy-preserving federation setting. + +The goal here is to give a minimal, type-annotated contract surface that can +be extended by adapters and governance tooling without pulling in heavy +dependencies. +""" +from __future__ import annotations + +import time +from dataclasses import dataclass, field +from typing import Dict, Any + + +@dataclass +class LocalExperiment: + """Represents a locally-defined experiment on a single participant. + + Attributes: + id: Unique experiment identifier within the federation. + variables: Local experiment parameters (e.g., price, funnel step). + objectives: Desired outcome measures (e.g., maximize LTV, minimize CPA). + privacy_budget: Optional per-experiment privacy constraints (DP budgets, data retention). + """ + + id: str + variables: Dict[str, Any] + objectives: Dict[str, Any] + privacy_budget: Dict[str, Any] = field(default_factory=dict) + created_at: float = field(default_factory=lambda: time.time()) + + def to_dict(self) -> Dict[str, Any]: + return { + "id": self.id, + "variables": self.variables, + "objectives": self.objectives, + "privacy_budget": self.privacy_budget, + "created_at": self.created_at, + } + + +@dataclass +class SharedSignal: + """Represents aggregated or shared signals exchanged between participants.""" + + experiment_id: str + metrics: Dict[str, Any] + timestamp: float = field(default_factory=lambda: time.time()) + metadata: Dict[str, Any] = field(default_factory=dict) + + def to_dict(self) -> Dict[str, Any]: + return { + "experiment_id": self.experiment_id, + "metrics": self.metrics, + "timestamp": self.timestamp, + "metadata": self.metadata, + } + + +@dataclass +class PlanDelta: + """Incremental update to an local plan or experiment outcome.""" + + experiment_id: str + delta: Dict[str, Any] + timestamp: float = field(default_factory=lambda: time.time()) + + def to_dict(self) -> Dict[str, Any]: + return { + "experiment_id": self.experiment_id, + "delta": self.delta, + "timestamp": self.timestamp, + } + + +__all__ = ["LocalExperiment", "SharedSignal", "PlanDelta"]