clusteraudiencekit 5.9.2__tar.gz → 7.3.0__tar.gz
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.
- clusteraudiencekit-7.3.0/.env.example +27 -0
- clusteraudiencekit-7.3.0/.gitattributes +19 -0
- clusteraudiencekit-7.3.0/.github/CI_ERRORS.md +42 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/.github/workflows/ci.yml +13 -7
- clusteraudiencekit-7.3.0/.github/workflows/tests.yml +27 -0
- clusteraudiencekit-7.3.0/.gitignore +52 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/CHANGELOG.md +206 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/CONTRIBUTING.md +1 -1
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/Cargo.lock +1 -1
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/Cargo.toml +1 -2
- clusteraudiencekit-7.3.0/LICENSE +22 -0
- clusteraudiencekit-7.3.0/OTEL_SETUP_GUIDE.md +319 -0
- clusteraudiencekit-7.3.0/PKG-INFO +225 -0
- clusteraudiencekit-7.3.0/PRODUCTION_DEPLOYMENT.md +512 -0
- clusteraudiencekit-7.3.0/README.md +177 -0
- clusteraudiencekit-7.3.0/SECURITY.md +44 -0
- clusteraudiencekit-7.3.0/benches/benchmarks.rs +88 -0
- clusteraudiencekit-7.3.0/clusteraudiencekit/__init__.py +49 -0
- clusteraudiencekit-7.3.0/docs/ROADMAP_HONEST.md +329 -0
- clusteraudiencekit-7.3.0/docs/SECURITY_AUDIT.md +156 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/api-reference.md +9 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/comparison.md +9 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/getting-started-simple.md +9 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/performance-comparison.md +9 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/press-release.md +11 -2
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/troubleshooting.md +1 -1
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/examples/basic_segmentation.py +23 -27
- clusteraudiencekit-7.3.0/otel_exporter.py +189 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/pyproject.toml +7 -9
- clusteraudiencekit-7.3.0/scripts/test_dashboards_crossplatform.sh +208 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/activation.rs +16 -15
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/activation_orchestrator.rs +59 -15
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/algorithms.rs +27 -41
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/b2b_governance.rs +93 -21
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/b2b_segmentation.rs +25 -13
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/behavioral.rs +37 -38
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/churn_prediction.rs +123 -28
- clusteraudiencekit-7.3.0/src/engine/clustering.rs +813 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/clv.rs +33 -35
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/cohorts.rs +28 -28
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/dashboard.rs +9 -44
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/drift_detection.rs +133 -35
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/governance.rs +36 -50
- clusteraudiencekit-5.9.2/src/engine/xgboost_models.rs → clusteraudiencekit-7.3.0/src/engine/heuristic_score_estimator.rs +112 -88
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/k_estimation.rs +29 -18
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/lifecycle.rs +35 -42
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/lookalike.rs +30 -22
- clusteraudiencekit-7.3.0/src/engine/metrics.rs +279 -0
- clusteraudiencekit-7.3.0/src/engine/mod.rs +277 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/neural_networks.rs +24 -28
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/pattern_discovery.rs +131 -110
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/platform_adapters.rs +99 -37
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/plugins.rs +20 -21
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/price_intelligence.rs +61 -30
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/privacy.rs +18 -19
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/profiling.rs +30 -14
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/quality_metrics.rs +43 -18
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/revenue_intelligence.rs +25 -19
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/rfm.rs +71 -15
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/segment_intelligence.rs +117 -91
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/segments.rs +35 -20
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/sql_export.rs +422 -103
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/streaming.rs +403 -27
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/engine/temporal_analytics.rs +60 -42
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/lib.rs +0 -1
- clusteraudiencekit-7.3.0/src/python.rs +2477 -0
- clusteraudiencekit-7.3.0/tests/test_basic.py +92 -0
- clusteraudiencekit-7.3.0/tests/test_clustering.py +186 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/tests/test_performance.py +60 -40
- clusteraudiencekit-7.3.0/tests/test_wired_modules.py +326 -0
- clusteraudiencekit-5.9.2/.gitignore +0 -54
- clusteraudiencekit-5.9.2/LICENSE +0 -21
- clusteraudiencekit-5.9.2/PKG-INFO +0 -440
- clusteraudiencekit-5.9.2/README.md +0 -390
- clusteraudiencekit-5.9.2/ROADMAP_HONEST.md +0 -105
- clusteraudiencekit-5.9.2/SECURITY_AUDIT.md +0 -105
- clusteraudiencekit-5.9.2/benches/benchmarks.rs +0 -8
- clusteraudiencekit-5.9.2/clusteraudiencekit/__init__.py +0 -71
- clusteraudiencekit-5.9.2/clusteraudiencekit/_multi_algorithm.py +0 -304
- clusteraudiencekit-5.9.2/clusteraudiencekit/clusteraudiencekit.pyi +0 -76
- clusteraudiencekit-5.9.2/clusteraudiencekit/error_messages.py +0 -139
- clusteraudiencekit-5.9.2/clusteraudiencekit/limits.py +0 -107
- clusteraudiencekit-5.9.2/clusteraudiencekit/logging_config.py +0 -81
- clusteraudiencekit-5.9.2/clusteraudiencekit/okf_segment_profiles.py +0 -95
- clusteraudiencekit-5.9.2/clusteraudiencekit/py.typed +0 -0
- clusteraudiencekit-5.9.2/clusteraudiencekit/validation.py +0 -53
- clusteraudiencekit-5.9.2/python/clusteraudiencekit/__init__.py +0 -70
- clusteraudiencekit-5.9.2/python/clusteraudiencekit/cli.py +0 -359
- clusteraudiencekit-5.9.2/python/clusteraudiencekit/clusteraudiencekit.pyi +0 -76
- clusteraudiencekit-5.9.2/python/clusteraudiencekit/server.py +0 -212
- clusteraudiencekit-5.9.2/src/engine/clustering.rs +0 -67
- clusteraudiencekit-5.9.2/src/engine/metrics.rs +0 -31
- clusteraudiencekit-5.9.2/src/engine/mod.rs +0 -111
- clusteraudiencekit-5.9.2/src/python.rs +0 -96
- clusteraudiencekit-5.9.2/src/streaming/mod.rs +0 -27
- clusteraudiencekit-5.9.2/tests/test_basic.py +0 -53
- clusteraudiencekit-5.9.2/tests/test_clustering.py +0 -251
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/.github/dependabot.yml +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/.pre-commit-config.yaml +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/ARCHITECTURE.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/Makefile +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/CODE_OF_CONDUCT.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/CONTRIBUTING.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0/docs}/CONTRIBUTORS.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0/docs}/PYPI_UPLOAD.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0/docs}/ROADMAP.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0/docs}/SECURITY.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0/docs}/SQL_EXPORT.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/WORKFLOW_INTEGRATION.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/architecture.md +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/docs/error-catalog.json +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/examples/sql_export_example.py +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/examples/streaming_updates.py +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/install.sh +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/rust-toolchain.toml +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/scripts/install-curl.sh +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/scripts/install-from-source.sh +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/scripts/install-pip.ps1 +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/scripts/install-pip.sh +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/utils/conversions.rs +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/utils/mod.rs +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/src/utils/validation.rs +0 -0
- {clusteraudiencekit-5.9.2 → clusteraudiencekit-7.3.0}/tests/test_sql_export.py +0 -0
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
# ClusterAudienceKit environment variables
|
|
2
|
+
#
|
|
3
|
+
# HONESTY NOTE: as of this release, NO environment variable is actually read
|
|
4
|
+
# by any code path in this repository. The two variables below
|
|
5
|
+
# (CLUSTERAUDIENCEKIT_LOG_LEVEL / CLUSTERAUDIENCEKIT_LOG_FILE) were
|
|
6
|
+
# previously read by a Python module (`src/clusteraudiencekit/`) that turned
|
|
7
|
+
# out to be a stale, unused duplicate of the real package (see repo hygiene
|
|
8
|
+
# notes in docs/ROADMAP_HONEST.md) and has since been removed; the `log`
|
|
9
|
+
# crate is a declared-but-not-yet-used Rust dependency with no
|
|
10
|
+
# `env_logger`/equivalent initialization wired up yet. Both are listed here
|
|
11
|
+
# as RESERVED — the intended shape once logging is actually wired — rather
|
|
12
|
+
# than removed outright, since re-adding real logging support is a small,
|
|
13
|
+
# reasonable near-term addition and this documents the intended variable
|
|
14
|
+
# names for that work. Every other variable previously in this file (API
|
|
15
|
+
# keys, database credentials, encryption keys, Redis/Elasticsearch URLs,
|
|
16
|
+
# etc.) described a server/database/secrets-management product surface that
|
|
17
|
+
# doesn't exist in this package at all (it's a library, not a service) and
|
|
18
|
+
# has been removed rather than left as a misleading checklist.
|
|
19
|
+
|
|
20
|
+
# RESERVED (not yet wired to any code): intended logging verbosity once a
|
|
21
|
+
# logging backend (e.g. env_logger) is added. One of: error, warn, info,
|
|
22
|
+
# debug, trace.
|
|
23
|
+
CLUSTERAUDIENCEKIT_LOG_LEVEL=info
|
|
24
|
+
|
|
25
|
+
# RESERVED (not yet wired to any code): intended log output file path once
|
|
26
|
+
# a logging backend is added. If unset, would default to stderr.
|
|
27
|
+
CLUSTERAUDIENCEKIT_LOG_FILE=
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# Mark Rust/C code as vendored (don't count toward language stats)
|
|
2
|
+
crates/** linguist-vendored=true
|
|
3
|
+
*.rs linguist-vendored=true
|
|
4
|
+
src/c/** linguist-vendored=true
|
|
5
|
+
src/cpp/** linguist-vendored=true
|
|
6
|
+
|
|
7
|
+
# Mark build artifacts as generated
|
|
8
|
+
*.so linguist-generated=true
|
|
9
|
+
*.pyd linguist-generated=true
|
|
10
|
+
*.dylib linguist-generated=true
|
|
11
|
+
*.dll linguist-generated=true
|
|
12
|
+
build/** linguist-generated=true
|
|
13
|
+
dist/** linguist-generated=true
|
|
14
|
+
*.egg-info/** linguist-generated=true
|
|
15
|
+
|
|
16
|
+
# Force Python as primary language
|
|
17
|
+
*.py linguist-language=Python
|
|
18
|
+
pyproject.toml linguist-language=Python
|
|
19
|
+
setup.py linguist-language=Python
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# CI/CD Workflow Errors
|
|
2
|
+
|
|
3
|
+
This file documents known CI/CD workflow errors and issues discovered during automated scanning.
|
|
4
|
+
|
|
5
|
+
**Last Updated**: 2026-07-27
|
|
6
|
+
|
|
7
|
+
## Quick Links
|
|
8
|
+
- Full Error Report: See main [CI/CD Error Report](../../CI_ERRORS_REPORT.md)
|
|
9
|
+
- GitHub Actions Documentation: https://docs.github.com/en/actions
|
|
10
|
+
- Troubleshooting Guide: [TROUBLESHOOTING.md](.github/TROUBLESHOOTING.md)
|
|
11
|
+
|
|
12
|
+
## How to Check Workflow Status
|
|
13
|
+
|
|
14
|
+
```bash
|
|
15
|
+
# List recent workflow runs
|
|
16
|
+
gh run list -R Mullassery/$REPO_NAME --limit 10
|
|
17
|
+
|
|
18
|
+
# View details of a specific run
|
|
19
|
+
gh run view <RUN_ID> -R Mullassery/$REPO_NAME
|
|
20
|
+
|
|
21
|
+
# View logs from a failed run
|
|
22
|
+
gh run view <RUN_ID> -R Mullassery/$REPO_NAME --log-failed
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
## Known Issues in This Repository
|
|
26
|
+
|
|
27
|
+
Please see the main CI/CD Error Report for details specific to this repository:
|
|
28
|
+
[CI_ERRORS_REPORT.md](../../CI_ERRORS_REPORT.md#$repo)
|
|
29
|
+
|
|
30
|
+
## Action Items
|
|
31
|
+
|
|
32
|
+
- Review the full error report
|
|
33
|
+
- Check your GitHub Actions workflows in `.github/workflows/`
|
|
34
|
+
- Update deprecated action versions
|
|
35
|
+
- Test fixes in a development branch before merging
|
|
36
|
+
|
|
37
|
+
## Need Help?
|
|
38
|
+
|
|
39
|
+
- Check the [GitHub Actions Documentation](https://docs.github.com/en/actions)
|
|
40
|
+
- Review the main error report for details on your specific issues
|
|
41
|
+
- Run `gh run view <run-id> --log` to see full logs
|
|
42
|
+
|
|
@@ -13,14 +13,15 @@ jobs:
|
|
|
13
13
|
steps:
|
|
14
14
|
- uses: actions/checkout@v4
|
|
15
15
|
|
|
16
|
-
- uses: dtolnay/rust-toolchain
|
|
16
|
+
- uses: dtolnay/rust-toolchain@stable
|
|
17
17
|
|
|
18
18
|
- uses: Swatinem/rust-cache@v2
|
|
19
19
|
with:
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
20
|
+
# Single-crate repo (one root Cargo.toml, no [workspace] members),
|
|
21
|
+
# so the workspace root is ".". A prior config referenced
|
|
22
|
+
# "crates"/"core"/"python" dirs that don't exist here, which
|
|
23
|
+
# Swatinem/rust-cache silently no-ops on instead of failing.
|
|
24
|
+
workspaces: .
|
|
24
25
|
|
|
25
26
|
- name: Build Rust
|
|
26
27
|
run: cargo build --release --all-features
|
|
@@ -37,12 +38,17 @@ jobs:
|
|
|
37
38
|
steps:
|
|
38
39
|
- uses: actions/checkout@v4
|
|
39
40
|
|
|
40
|
-
- uses: actions/setup-python@
|
|
41
|
+
- uses: actions/setup-python@v5
|
|
41
42
|
with:
|
|
42
43
|
python-version: ${{ matrix.python-version }}
|
|
43
44
|
|
|
45
|
+
- name: Install build dependencies
|
|
46
|
+
run: |
|
|
47
|
+
sudo apt-get update
|
|
48
|
+
sudo apt-get install -y build-essential python3-dev
|
|
49
|
+
|
|
44
50
|
- name: Install dependencies
|
|
45
51
|
run: pip install -e ".[dev]"
|
|
46
52
|
|
|
47
53
|
- name: Run pytest
|
|
48
|
-
run: pytest tests/ -v --tb=short
|
|
54
|
+
run: if [ -d "tests" ]; then pytest tests/ -v --tb=short; else echo "No Python tests found"; fi
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
on: [push, pull_request]
|
|
3
|
+
jobs:
|
|
4
|
+
test:
|
|
5
|
+
runs-on: ubuntu-latest
|
|
6
|
+
strategy:
|
|
7
|
+
matrix:
|
|
8
|
+
python-version: ["3.10", "3.11", "3.12"]
|
|
9
|
+
steps:
|
|
10
|
+
- uses: actions/checkout@v4
|
|
11
|
+
- uses: actions/setup-python@v4
|
|
12
|
+
with:
|
|
13
|
+
python-version: ${{ matrix.python-version }}
|
|
14
|
+
- name: Install
|
|
15
|
+
# [project.optional-dependencies].dev is always defined in
|
|
16
|
+
# pyproject.toml, so the old `2>/dev/null || pip install -e .`
|
|
17
|
+
# fallback was dead code that just hid real install failures behind
|
|
18
|
+
# a swallowed stderr.
|
|
19
|
+
run: pip install -e ".[dev]"
|
|
20
|
+
- name: Test
|
|
21
|
+
# `pytest 2>/dev/null || echo "No tests"` previously meant this step
|
|
22
|
+
# reported success unconditionally, regardless of whether pytest
|
|
23
|
+
# actually ran, crashed, or genuinely failed - a real failure would
|
|
24
|
+
# have been silently swallowed rather than turning CI red.
|
|
25
|
+
run: pytest
|
|
26
|
+
- name: Lint
|
|
27
|
+
run: ruff check . 2>/dev/null || true
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Sensitive files and credentials
|
|
2
|
+
.env
|
|
3
|
+
.env.local
|
|
4
|
+
.env.*.local
|
|
5
|
+
*.key
|
|
6
|
+
*.pem
|
|
7
|
+
*.crt
|
|
8
|
+
credentials.json
|
|
9
|
+
secrets.json
|
|
10
|
+
.credentials
|
|
11
|
+
config.local.*
|
|
12
|
+
.config.local
|
|
13
|
+
oauth_tokens.json
|
|
14
|
+
|
|
15
|
+
# IDE files
|
|
16
|
+
.vscode/
|
|
17
|
+
.idea/
|
|
18
|
+
*.swp
|
|
19
|
+
*~
|
|
20
|
+
.DS_Store
|
|
21
|
+
|
|
22
|
+
# Python
|
|
23
|
+
__pycache__/
|
|
24
|
+
*.py[cod]
|
|
25
|
+
*.egg-info/
|
|
26
|
+
dist/
|
|
27
|
+
build/
|
|
28
|
+
.pytest_cache/
|
|
29
|
+
|
|
30
|
+
# Compiled extension module (built in-place by `maturin develop` into
|
|
31
|
+
# clusteraudiencekit/) and maturin/wheel build output
|
|
32
|
+
*.so
|
|
33
|
+
*.pyd
|
|
34
|
+
*.dylib
|
|
35
|
+
wheels/
|
|
36
|
+
target/wheels/
|
|
37
|
+
|
|
38
|
+
# Virtual environments
|
|
39
|
+
venv/
|
|
40
|
+
env/
|
|
41
|
+
.venv
|
|
42
|
+
|
|
43
|
+
# Rust
|
|
44
|
+
target/
|
|
45
|
+
# NOTE: Cargo.lock is intentionally tracked (not ignored) for reproducible
|
|
46
|
+
# `cargo build`/`maturin build` output across contributors and CI.
|
|
47
|
+
|
|
48
|
+
# Temp files
|
|
49
|
+
*.tmp
|
|
50
|
+
*.log
|
|
51
|
+
temp/
|
|
52
|
+
tmp/
|
|
@@ -2,6 +2,212 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to ClusterAudienceKit are documented here.
|
|
4
4
|
|
|
5
|
+
## [7.3.0] - 2026-08-30
|
|
6
|
+
|
|
7
|
+
### Fixed
|
|
8
|
+
- **`n_jobs` was completely fake.** It was hardcoded to `-1` in
|
|
9
|
+
`SegmenterConfig` and never actually read anywhere, and the real PyO3
|
|
10
|
+
constructor (`PyAudienceSegmenter::new()`) didn't even accept it as a
|
|
11
|
+
parameter — despite `docs/api-reference.md` documenting it as a working,
|
|
12
|
+
user-settable thread-throttle control. `n_jobs` is now a real accepted
|
|
13
|
+
constructor parameter, wired through to a scoped
|
|
14
|
+
`rayon::ThreadPoolBuilder` around the clustering/RFM computation, so it
|
|
15
|
+
actually controls parallelism instead of silently doing nothing.
|
|
16
|
+
|
|
17
|
+
## [7.2.0] - 2026-08-25
|
|
18
|
+
|
|
19
|
+
### Added
|
|
20
|
+
- **Drift-triggered re-clustering** (`DriftDetector` wired into
|
|
21
|
+
`StreamingSegmentationEngine`, closing a previously-standalone gap noted
|
|
22
|
+
in `docs/ROADMAP_HONEST.md`): `process_batch` now arms a drift baseline
|
|
23
|
+
over the tracked population's RFM distribution once enough customers
|
|
24
|
+
accumulate, and checks every subsequent batch against it. If
|
|
25
|
+
recency/frequency/monetary drift crosses a configurable severity
|
|
26
|
+
threshold, a real k-means re-fit (`clustering::kmeans`) runs over every
|
|
27
|
+
tracked customer and segment assignments are overwritten with the fresh
|
|
28
|
+
cluster labels. New `check_drift()`, `maybe_recluster()`,
|
|
29
|
+
`set_recluster_baseline()`, `recluster_history()` methods and
|
|
30
|
+
`ReclusterConfig`/`ReclusterEvent` types, exposed to Python as
|
|
31
|
+
`StreamingSegmentationEngine(config, recluster_config)`,
|
|
32
|
+
`ReclusterConfig`, `ReclusterEvent`.
|
|
33
|
+
- **Chunked/streaming ingestion for batch clustering**
|
|
34
|
+
(`clustering::MiniBatchKMeans`, Sculley 2010): an online variant of
|
|
35
|
+
Lloyd's algorithm that ingests one chunk at a time via `partial_fit` and
|
|
36
|
+
updates centers incrementally, bounding memory to
|
|
37
|
+
O(chunk_size + n_clusters) regardless of total dataset size — unlike
|
|
38
|
+
`kmeans()`/`AudienceSegmenter.fit()`, which require the full dataset in
|
|
39
|
+
one in-memory `Array2` for repeated passes. Exposed to Python as
|
|
40
|
+
`MiniBatchKMeans(n_clusters, random_state)`.
|
|
41
|
+
- Friendly (non-`Py`-prefixed) Python aliases for the streaming-segmentation
|
|
42
|
+
and drift-detection classes (`StreamingEvent`, `StreamingConfig`,
|
|
43
|
+
`StreamingSegmentUpdate`, `StreamingSegmentationEngine`, `FeatureDrift`,
|
|
44
|
+
`SegmentCompositionChange`) and drift functions
|
|
45
|
+
(`kolmogorov_smirnov`, `hellinger_distance`, `chi_square_drift`,
|
|
46
|
+
`detect_feature_drift`) — these existed in the compiled extension but
|
|
47
|
+
were never added to `clusteraudiencekit/__init__.py`'s alias list or
|
|
48
|
+
`__all__`, unlike every other public class.
|
|
49
|
+
|
|
50
|
+
### Fixed
|
|
51
|
+
- `DriftDetector::kolmogorov_smirnov` computed the baseline empirical CDF
|
|
52
|
+
via `(rank + 1) / n`, which silently assumed no ties: a run of repeated
|
|
53
|
+
identical values (e.g. an integer feature like event count) produced
|
|
54
|
+
large phantom drift between two byte-identical samples. Now evaluates
|
|
55
|
+
both samples' empirical CDFs via the same counting rule, at every point
|
|
56
|
+
present in either sample (the standard two-sample KS statistic).
|
|
57
|
+
- `DriftDetector::hellinger_distance` short-circuited to 0 drift whenever
|
|
58
|
+
either sample had exactly zero variance (a degenerate/constant
|
|
59
|
+
distribution) — even when the other sample was wildly different in mean
|
|
60
|
+
and/or spread, which is a textbook case of *total* drift, not "nothing to
|
|
61
|
+
compare." Its variance term (`0.5*ln(a/b) + 0.5*ln(b/a)`) also
|
|
62
|
+
algebraically canceled to exactly 0 for any `a, b > 0`, so the function
|
|
63
|
+
only ever reacted to mean differences. Replaced with the standard
|
|
64
|
+
Bhattacharyya-distance formula for two Gaussians, with variance floored
|
|
65
|
+
at a small epsilon instead of short-circuited.
|
|
66
|
+
|
|
67
|
+
Both were discovered while building drift-triggered re-clustering on top of
|
|
68
|
+
`DriftDetector` — the KS-test bug made the new trigger fire on tied
|
|
69
|
+
RFM feature values (e.g. every customer having made exactly one purchase),
|
|
70
|
+
and the Hellinger bug made it silently miss real drift whenever the
|
|
71
|
+
baseline window happened to be uniform.
|
|
72
|
+
|
|
73
|
+
## [7.1.1] - 2026-08-12
|
|
74
|
+
|
|
75
|
+
Remediation pass following a technical audit. 7.1.0 was never published to
|
|
76
|
+
PyPI, so this release supersedes it rather than shipping alongside it.
|
|
77
|
+
|
|
78
|
+
### Fixed (honesty / correctness)
|
|
79
|
+
- `xgboost_models.rs` fabricated a "trained model": `train()` computed
|
|
80
|
+
scores from a fixed formula involving only `learning_rate`, not from `y`,
|
|
81
|
+
and `predict()` did a linear combination of feature-magnitude weights, not
|
|
82
|
+
a decision-tree traversal — despite being typed/named as a real XGBoost
|
|
83
|
+
wrapper. No viable Rust XGBoost binding avoids requiring a system
|
|
84
|
+
`libxgboost` C++ build, which isn't available here, so rather than ship
|
|
85
|
+
the fake version, the module was renamed to
|
|
86
|
+
`heuristic_score_estimator.rs` with all XGBoost/gradient-boosting
|
|
87
|
+
terminology removed (`HeuristicScoreEstimator`, `heuristic_fit_score`,
|
|
88
|
+
etc.), a doc comment explaining what it actually is, and
|
|
89
|
+
"xgboost"/"gradient-boosting" dropped from `pyproject.toml` keywords. It
|
|
90
|
+
remains Rust-only (not Python-exposed).
|
|
91
|
+
- `churn_prediction.rs`: `evaluate_model_performance` returned a hardcoded
|
|
92
|
+
`auc_roc: 0.82 // Simulated`. Replaced with a real trapezoidal-rule
|
|
93
|
+
AUC-ROC computed from the same prediction/label pairs used for the
|
|
94
|
+
confusion-matrix metrics, with tests for perfect separation (1.0),
|
|
95
|
+
perfectly inverted ranking (0.0), no discrimination (0.5), and a
|
|
96
|
+
hand-computed 0.75 case.
|
|
97
|
+
- `src/python.rs`'s module `info.algorithms` listed `"dbscan"`,
|
|
98
|
+
`"hierarchical"`, `"gmm"` — none of which exist anywhere in this
|
|
99
|
+
codebase. Now lists only `"kmeans"`/`"kprototypes"`.
|
|
100
|
+
|
|
101
|
+
### Added (Python API surface)
|
|
102
|
+
Wired 10 previously Rust-only-tested engine modules into the Python
|
|
103
|
+
extension, each with new Python-level tests in `tests/test_wired_modules.py`:
|
|
104
|
+
`engine::privacy` (differential privacy + k-anonymity), `engine::streaming`
|
|
105
|
+
(real-time incremental segmentation), `engine::drift_detection`,
|
|
106
|
+
`engine::lookalike`, `engine::cohorts`, `engine::lifecycle`,
|
|
107
|
+
`engine::quality_metrics`, `engine::k_estimation`, `engine::behavioral`,
|
|
108
|
+
`engine::profiling`. See `docs/ROADMAP_HONEST.md` for the full list of new
|
|
109
|
+
entry points and what's still deferred (`segment_intelligence`,
|
|
110
|
+
`pattern_discovery`, `temporal_analytics`, `price_intelligence`,
|
|
111
|
+
`revenue_intelligence`, `neural_networks`).
|
|
112
|
+
|
|
113
|
+
### Security
|
|
114
|
+
- SQL injection: `sql_export.rs`'s `table_name` and `ColumnMapping` fields
|
|
115
|
+
were interpolated into generated SQL via `format!()` with no validation.
|
|
116
|
+
Added `validate_identifier()` (alphanumeric/underscore, optionally
|
|
117
|
+
dot-qualified, allow-list) applied before any query string is built.
|
|
118
|
+
|
|
119
|
+
### Changed
|
|
120
|
+
- Deleted the duplicate, genuinely-empty `src/streaming/mod.rs` stub
|
|
121
|
+
(`StreamingState` with `// TODO` bodies) that shadowed the real,
|
|
122
|
+
673-line, fully-implemented `engine::streaming`. Removed `pub mod
|
|
123
|
+
streaming;` from `lib.rs`.
|
|
124
|
+
- `rayon` was a declared dependency with zero call sites. Now used to
|
|
125
|
+
parallelize the nearest-center assignment step in `kmeans`/`kprototypes`
|
|
126
|
+
and the per-customer computation in `calculate_rfm`.
|
|
127
|
+
- `benches/benchmarks.rs` replaced its `dummy_benchmark` (measured `1 + 1`)
|
|
128
|
+
with real Criterion benchmarks for `kmeans` and `calculate_rfm` at 10k and
|
|
129
|
+
100k rows.
|
|
130
|
+
- Repo hygiene: deleted `clusteraudiencekit.bak/`, `README.md.bak`,
|
|
131
|
+
`python/clusteraudiencekit/__init__.py.bak`, and the two stale duplicate
|
|
132
|
+
Python package directories `python/clusteraudiencekit/` and
|
|
133
|
+
`src/clusteraudiencekit/` (only `./clusteraudiencekit/` is the real,
|
|
134
|
+
maturin-packaged source — confirmed against `pyproject.toml`'s
|
|
135
|
+
`[tool.maturin]` config). Deleted `MCP_QUICKSTART.md`,
|
|
136
|
+
`DASHBOARD_SHORTCUTS.md`, `FINAL_REPORT.txt`, and `clusteraudiencekit.toml`,
|
|
137
|
+
which described an MCP connector and auto-starting dashboard daemon that
|
|
138
|
+
don't exist anywhere in the real, exported API.
|
|
139
|
+
- `.gitignore`: added `*.so`/`*.pyd`/`*.dylib`/`wheels/`/`target/wheels/`;
|
|
140
|
+
removed the stale (and already-ineffective, since the file was already
|
|
141
|
+
tracked) `Cargo.lock` ignore entry.
|
|
142
|
+
- `tests/test_clustering.py` imported `ClusterEngine` (never implemented)
|
|
143
|
+
and tested a "hierarchical" algorithm explicitly marked "Not Planned".
|
|
144
|
+
Rewritten against the real API (`AudienceSegmenter`, `kmeans`,
|
|
145
|
+
`silhouette_score`, `assess_cluster_quality`); hierarchical case removed.
|
|
146
|
+
`tests/test_basic.py` had the same `AudienceSegmenter(method=...)`
|
|
147
|
+
mismatch and a skipped fit/predict test; both fixed with real,
|
|
148
|
+
passing, end-to-end tests. `tests/test_performance.py`'s five
|
|
149
|
+
placeholder `pytest.skip(...)` performance tests are now real.
|
|
150
|
+
- `cargo fmt` applied repo-wide (previously not clean in any file).
|
|
151
|
+
`cargo clippy --workspace -- -D warnings` reduced from 214 to 43 findings,
|
|
152
|
+
all now confined to modules not reachable from the Python API.
|
|
153
|
+
- `README.md` rewritten: removed fabricated API examples
|
|
154
|
+
(`Segmentation`/`CLV`/`Churn`/`Lookalikes` classes that don't exist,
|
|
155
|
+
4-algorithm claims including DBSCAN/GMM that were already partly
|
|
156
|
+
corrected, an "MIT License" claim contradicting the actual proprietary
|
|
157
|
+
`LICENSE`), replaced with a working 30-second example and an accurate
|
|
158
|
+
capability table. `docs/ROADMAP_HONEST.md` and `docs/SECURITY_AUDIT.md`
|
|
159
|
+
rewritten to reflect current state (both predated the 2026-08-07 clustering
|
|
160
|
+
implementation and described a materially different, stale codebase).
|
|
161
|
+
`docs/api-reference.md`, `docs/getting-started-simple.md`,
|
|
162
|
+
`docs/comparison.md`, `docs/performance-comparison.md`, and
|
|
163
|
+
`docs/press-release.md` — large pre-existing docs with fabricated API
|
|
164
|
+
details (e.g. a fictional `AudienceSegmenter(method=..., ...)`
|
|
165
|
+
constructor) — got an honesty banner pointing to the verified-accurate
|
|
166
|
+
README/ROADMAP rather than a full rewrite (out of scope for this pass).
|
|
167
|
+
- `.env.example` trimmed to the two variables anything in this repo could
|
|
168
|
+
plausibly read, both marked RESERVED (not yet wired to any code) rather
|
|
169
|
+
than claimed as functional; removed the API-key/database/secrets
|
|
170
|
+
variables that described a server this package doesn't run.
|
|
171
|
+
|
|
172
|
+
## [7.1.0] - 2026-08-07
|
|
173
|
+
|
|
174
|
+
### Fixed
|
|
175
|
+
- **Critical: the published package crashed on `import` for every user.** A leftover
|
|
176
|
+
`.cargo/config.toml` from an earlier debugging attempt force-linked the extension
|
|
177
|
+
module against a specific `libpython3.13.dylib` — which is the wrong approach for a
|
|
178
|
+
`cdylib` Python extension (it should resolve Python symbols dynamically from
|
|
179
|
+
whatever interpreter loads it, not embed its own copy). This caused
|
|
180
|
+
`PyInterpreterState_Get: ... GIL released ... thread state NULL` immediately on
|
|
181
|
+
import, on every Python version tested (3.9, 3.11). Removed the file; `maturin`'s
|
|
182
|
+
default linking (already correct) now applies.
|
|
183
|
+
- **Core clustering engine was entirely unimplemented.** `engine::clustering`
|
|
184
|
+
(KMeans, K-Prototypes, cluster assignment) and `engine::metrics` (Silhouette,
|
|
185
|
+
Davies-Bouldin, inertia) were `// TODO` stubs returning empty/zero results, despite
|
|
186
|
+
being the backing implementation for the public `AudienceSegmenter` / `kmeans_py`
|
|
187
|
+
API and the README's "6 clustering algorithms, process 1M+ customers in <1s"
|
|
188
|
+
claims. Implemented:
|
|
189
|
+
- KMeans via Lloyd's algorithm with k-means++ initialization, deterministic for a
|
|
190
|
+
given `random_state`.
|
|
191
|
+
- K-Prototypes (Huang 1998) for mixed numeric/categorical data.
|
|
192
|
+
- Silhouette / Davies-Bouldin / inertia — cross-verified against
|
|
193
|
+
`sklearn.metrics` on a fixed reference dataset (bit-exact to 1e-9).
|
|
194
|
+
- `AudienceSegmenterCore::fit()`/`predict()` now actually call the above instead
|
|
195
|
+
of being no-ops.
|
|
196
|
+
- Fixed a K-Prototypes bug found by testing: categorical cluster centers were
|
|
197
|
+
seeded from static row indices instead of the same rows k-means++ chose for the
|
|
198
|
+
numeric centers, and mode tie-breaking went through a `HashMap` (whose iteration
|
|
199
|
+
order — and therefore tie-breaking — is randomized per-process in Rust),
|
|
200
|
+
making output nondeterministic across runs of the same `random_state`.
|
|
201
|
+
- README corrected: "6 clustering algorithms (K-means, DBSCAN, Spectral,
|
|
202
|
+
Hierarchical, GMM, Isolation Forest)" → 4 real ones (K-means, DBSCAN, Hierarchical,
|
|
203
|
+
GMM). Spectral clustering and Isolation Forest don't exist anywhere in this
|
|
204
|
+
codebase, not even as stubs.
|
|
205
|
+
|
|
206
|
+
### Known remaining gaps (not fixed in this release)
|
|
207
|
+
- `utils::conversions::pandas_to_arrow` / `arrow_to_pandas` still return
|
|
208
|
+
"Not implemented".
|
|
209
|
+
- `streaming::StreamingState` is still a stub.
|
|
210
|
+
|
|
5
211
|
## [5.9.0] - 2026-07-16
|
|
6
212
|
|
|
7
213
|
### 🎉 Phase 5.8: Price Intelligence (15 features, 50 hours)
|
|
@@ -132,6 +132,6 @@ Use the [GitHub issue tracker](https://github.com/Mullassery/clusteraudiencekit/
|
|
|
132
132
|
|
|
133
133
|
## License
|
|
134
134
|
|
|
135
|
-
By contributing, you agree your contributions will be licensed
|
|
135
|
+
By contributing, you agree your contributions will be licensed proprietary license.
|
|
136
136
|
|
|
137
137
|
Thank you for contributing to ClusterAudienceKit!
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
[package]
|
|
2
2
|
name = "clusteraudiencekit"
|
|
3
|
-
version = "
|
|
3
|
+
version = "7.3.0"
|
|
4
4
|
edition = "2021"
|
|
5
5
|
authors = ["Georgi Mammen Mullassery <mullassery@gmail.com>"]
|
|
6
|
-
license = "MIT"
|
|
7
6
|
description = "High-performance audience segmentation engine with Python bindings"
|
|
8
7
|
repository = "https://github.com/Mullassery/clusteraudiencekit"
|
|
9
8
|
readme = "README.md"
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
Proprietary License — Free to use with explicit attribution
|
|
2
|
+
|
|
3
|
+
Copyright © 2026 Georgi Mammen Mullassery
|
|
4
|
+
|
|
5
|
+
Permission is granted to any person obtaining a copy of this software to use,
|
|
6
|
+
copy, modify, and distribute this software and its documentation, provided that:
|
|
7
|
+
|
|
8
|
+
1. The above copyright notice and this permission notice appear in all copies
|
|
9
|
+
or substantial portions of the software.
|
|
10
|
+
|
|
11
|
+
2. Explicit attribution to the original author (Georgi Mammen Mullassery) is
|
|
12
|
+
provided in any project documentation and significant code comments where
|
|
13
|
+
this software is used.
|
|
14
|
+
|
|
15
|
+
3. The software is provided "AS IS" without warranty of any kind, express or
|
|
16
|
+
implied, including but not limited to the warranties of merchantability,
|
|
17
|
+
fitness for a particular purpose, or non-infringement.
|
|
18
|
+
|
|
19
|
+
4. In no event shall the author be liable for any claim, damages, or other
|
|
20
|
+
liability arising from the use of this software.
|
|
21
|
+
|
|
22
|
+
For more information, visit: https://github.com/Mullassery
|