xp-libs-analytics 0.4.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.
- xp_libs_analytics-0.4.0/.coveragerc +6 -0
- xp_libs_analytics-0.4.0/.dockerignore +11 -0
- xp_libs_analytics-0.4.0/.github/CODEOWNERS.template +7 -0
- xp_libs_analytics-0.4.0/.github/dependabot.yml +31 -0
- xp_libs_analytics-0.4.0/.github/pull_request_template.md +26 -0
- xp_libs_analytics-0.4.0/.github/workflows/ci.yml +91 -0
- xp_libs_analytics-0.4.0/.github/workflows/release.yml +91 -0
- xp_libs_analytics-0.4.0/.github/workflows/security.yml +49 -0
- xp_libs_analytics-0.4.0/.gitignore +24 -0
- xp_libs_analytics-0.4.0/CHANGELOG.md +39 -0
- xp_libs_analytics-0.4.0/CONTRIBUTING.md +9 -0
- xp_libs_analytics-0.4.0/Dockerfile +7 -0
- xp_libs_analytics-0.4.0/LICENSE +22 -0
- xp_libs_analytics-0.4.0/PKG-INFO +199 -0
- xp_libs_analytics-0.4.0/README.md +154 -0
- xp_libs_analytics-0.4.0/SECURITY.md +15 -0
- xp_libs_analytics-0.4.0/THIRD_PARTY_NOTICES.md +175 -0
- xp_libs_analytics-0.4.0/docs/GITHUB_SETUP.md +12 -0
- xp_libs_analytics-0.4.0/docs/adr/ADR-001-schema.md +3 -0
- xp_libs_analytics-0.4.0/docs/adr/ADR-002-errors.md +3 -0
- xp_libs_analytics-0.4.0/docs/adr/ADR-003-snapshots.md +3 -0
- xp_libs_analytics-0.4.0/docs/adr/ADR-004-execution.md +3 -0
- xp_libs_analytics-0.4.0/docs/adr/ADR-005-YAML-DSL.md +49 -0
- xp_libs_analytics-0.4.0/docs/adr/entity-inference-deferred.md +7 -0
- xp_libs_analytics-0.4.0/docs/architecture.md +21 -0
- xp_libs_analytics-0.4.0/docs/errors.md +97 -0
- xp_libs_analytics-0.4.0/docs/query-language.md +306 -0
- xp_libs_analytics-0.4.0/docs/releasing.md +13 -0
- xp_libs_analytics-0.4.0/docs/security-review.md +15 -0
- xp_libs_analytics-0.4.0/docs/string-matching.md +122 -0
- xp_libs_analytics-0.4.0/docs/yaml-security.md +119 -0
- xp_libs_analytics-0.4.0/evals/__init__.py +1 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/README.md +97 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/__init__.py +1 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/cli.py +156 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/empty.jsonl +0 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/epoch.jsonl +2 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/events.jsonl +5 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/extreme.jsonl +2 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/injection.jsonl +2 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/invalid_time.jsonl +1 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/matching.jsonl +28 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/mixed.jsonl +5 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/nested_records.jsonl +4 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/sales.jsonl +6 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/sparse_records.jsonl +4 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/telemetry.jsonl +14 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/datasets/timezone.jsonl +2 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/endpoint_security.py +85 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/fixtures.py +52 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/generate.py +762 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/prompts/agent_system.md +7 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/recovery.py +75 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/reporting.py +159 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/reports/.gitignore +2 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/scenarios/adversarial.yaml +389 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/scenarios/negative.yaml +573 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/scenarios/positive.yaml +1584 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/scenarios/recovery.yaml +503 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/scenarios/skill_comparison.yaml +99 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/scenarios/temporal.yaml +314 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/scenarios.py +153 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/scoring.py +388 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/server.py +34 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/skill_loader.py +28 -0
- xp_libs_analytics-0.4.0/evals/agent_skill/task.py +409 -0
- xp_libs_analytics-0.4.0/examples/README.md +69 -0
- xp_libs_analytics-0.4.0/examples/data/events.json +97 -0
- xp_libs_analytics-0.4.0/examples/data/events.ndjson +12 -0
- xp_libs_analytics-0.4.0/examples/data/matching_events.json +335 -0
- xp_libs_analytics-0.4.0/examples/data/mixed_types.json +17 -0
- xp_libs_analytics-0.4.0/examples/queries/01_count_all.yaml +8 -0
- xp_libs_analytics-0.4.0/examples/queries/02_filter_and_count.yaml +15 -0
- xp_libs_analytics-0.4.0/examples/queries/03_group_stats_and_topk.yaml +21 -0
- xp_libs_analytics-0.4.0/examples/queries/04_nested_or_predicates.yaml +17 -0
- xp_libs_analytics-0.4.0/examples/queries/05_is_missing.yaml +11 -0
- xp_libs_analytics-0.4.0/examples/queries/06_missing_vs_null.yaml +17 -0
- xp_libs_analytics-0.4.0/examples/queries/07_conditional_aggregation.yaml +19 -0
- xp_libs_analytics-0.4.0/examples/queries/08_ratio_if.yaml +16 -0
- xp_libs_analytics-0.4.0/examples/queries/09_tumbling_window.yaml +23 -0
- xp_libs_analytics-0.4.0/examples/queries/10_sliding_window.yaml +32 -0
- xp_libs_analytics-0.4.0/examples/queries/11_explicit_cast.yaml +16 -0
- xp_libs_analytics-0.4.0/examples/queries/12_text_range_distinct.yaml +23 -0
- xp_libs_analytics-0.4.0/examples/queries/13_summary_statistics.yaml +15 -0
- xp_libs_analytics-0.4.0/examples/queries/14_nested_and_not.yaml +20 -0
- xp_libs_analytics-0.4.0/examples/queries/15_conditional_sum.yaml +13 -0
- xp_libs_analytics-0.4.0/examples/queries/16_mixed_types_cast.yaml +17 -0
- xp_libs_analytics-0.4.0/examples/queries/17_relative_last_hour.yaml +15 -0
- xp_libs_analytics-0.4.0/examples/queries/18_string_exact.yaml +11 -0
- xp_libs_analytics-0.4.0/examples/queries/19_string_normalization.yaml +15 -0
- xp_libs_analytics-0.4.0/examples/queries/20_prefix_suffix.yaml +16 -0
- xp_libs_analytics-0.4.0/examples/queries/21_whole_word.yaml +13 -0
- xp_libs_analytics-0.4.0/examples/queries/22_ilike.yaml +11 -0
- xp_libs_analytics-0.4.0/examples/queries/23_rust_regex.yaml +11 -0
- xp_libs_analytics-0.4.0/examples/queries/24_fuzzy.yaml +17 -0
- xp_libs_analytics-0.4.0/examples/queries/25_multi_field_matching.yaml +24 -0
- xp_libs_analytics-0.4.0/examples/queries/26_conditional_fuzzy.yaml +20 -0
- xp_libs_analytics-0.4.0/examples/queries/27_temporal_fuzzy.yaml +38 -0
- xp_libs_analytics-0.4.0/examples/queries/28_safe_matching_diagnostics.yaml +22 -0
- xp_libs_analytics-0.4.0/examples/run_examples.py +70 -0
- xp_libs_analytics-0.4.0/pyproject.toml +101 -0
- xp_libs_analytics-0.4.0/requirements-lock.txt +168 -0
- xp_libs_analytics-0.4.0/scripts/benchmark.py +99 -0
- xp_libs_analytics-0.4.0/scripts/benchmark_matching.py +144 -0
- xp_libs_analytics-0.4.0/scripts/check_critical_coverage.py +59 -0
- xp_libs_analytics-0.4.0/scripts/check_name.py +31 -0
- xp_libs_analytics-0.4.0/scripts/inventory.py +84 -0
- xp_libs_analytics-0.4.0/scripts/resource_probe.py +113 -0
- xp_libs_analytics-0.4.0/scripts/smoke.py +46 -0
- xp_libs_analytics-0.4.0/scripts/verify_dist.py +57 -0
- xp_libs_analytics-0.4.0/skills/generic-analytics/SKILL.md +236 -0
- xp_libs_analytics-0.4.0/skills/generic-analytics/references/errors.md +55 -0
- xp_libs_analytics-0.4.0/skills/generic-analytics/references/query-language.md +39 -0
- xp_libs_analytics-0.4.0/skills/generic-analytics/references/string-matching.md +11 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/__init__.py +18 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/engine/__init__.py +1 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/engine/backend.py +379 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/engine/planner.py +450 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/engine/worker.py +121 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/errors/__init__.py +43 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/errors/catalog.json +75 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/errors/codes.py +81 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/ingest/__init__.py +309 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/interfaces.py +70 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/matching/__init__.py +1 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/matching/compiler.py +344 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/matching/diagnostics.py +115 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/matching/models.py +98 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/matching/normalize.py +16 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/matching/patterns.py +71 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/mcp/__init__.py +1 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/mcp/server.py +248 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/models/__init__.py +654 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/parser/__init__.py +142 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/policy/__init__.py +69 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/py.typed +0 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/registry.py +204 -0
- xp_libs_analytics-0.4.0/src/xp_libs_analytics/sdk/__init__.py +259 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_live/__init__.py +1 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_live/conftest.py +16 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_live/test_live.py +35 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/__init__.py +1 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_contract_failures.py +62 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_controls.py +185 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_endpoint_privacy.py +59 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_equivalence.py +50 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_fixture_oracles.py +21 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_native_agent.py +52 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_preflight_failures.py +86 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_privacy_runtime.py +27 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_recovery_seeding.py +29 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_runtime_failures.py +97 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_scenario_contracts.py +33 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_scoring.py +74 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_skill_loading.py +9 -0
- xp_libs_analytics-0.4.0/tests/agent_eval_offline/test_variations.py +16 -0
- xp_libs_analytics-0.4.0/tests/conftest.py +33 -0
- xp_libs_analytics-0.4.0/tests/fixtures/matching_events.jsonl +28 -0
- xp_libs_analytics-0.4.0/tests/fixtures/query-schema.json +3407 -0
- xp_libs_analytics-0.4.0/tests/matching/__init__.py +0 -0
- xp_libs_analytics-0.4.0/tests/matching/support.py +47 -0
- xp_libs_analytics-0.4.0/tests/matching/test_agent_contract.py +63 -0
- xp_libs_analytics-0.4.0/tests/matching/test_budgets_diagnostics.py +202 -0
- xp_libs_analytics-0.4.0/tests/matching/test_components_security.py +180 -0
- xp_libs_analytics-0.4.0/tests/matching/test_composition.py +279 -0
- xp_libs_analytics-0.4.0/tests/matching/test_operators.py +267 -0
- xp_libs_analytics-0.4.0/tests/matching/test_properties.py +162 -0
- xp_libs_analytics-0.4.0/tests/oracle.py +116 -0
- xp_libs_analytics-0.4.0/tests/test_agent_workflows.py +66 -0
- xp_libs_analytics-0.4.0/tests/test_contracts.py +133 -0
- xp_libs_analytics-0.4.0/tests/test_edge_cases.py +119 -0
- xp_libs_analytics-0.4.0/tests/test_import_separation.py +31 -0
- xp_libs_analytics-0.4.0/tests/test_ingest_policy.py +132 -0
- xp_libs_analytics-0.4.0/tests/test_mcp.py +176 -0
- xp_libs_analytics-0.4.0/tests/test_operations.py +173 -0
- xp_libs_analytics-0.4.0/tests/test_packaging_contract.py +25 -0
- xp_libs_analytics-0.4.0/tests/test_registry.py +341 -0
- xp_libs_analytics-0.4.0/tests/test_security.py +166 -0
- xp_libs_analytics-0.4.0/tests/test_telemetry.py +24 -0
- xp_libs_analytics-0.4.0/tests/test_time.py +119 -0
- xp_libs_analytics-0.4.0/tests/test_validation.py +214 -0
- xp_libs_analytics-0.4.0/tests/test_worker_limits.py +64 -0
- xp_libs_analytics-0.4.0/tests/test_workflows.py +22 -0
- xp_libs_analytics-0.4.0/tests/test_yaml_security.py +148 -0
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
# Rename to .github/CODEOWNERS and replace @ORG/TEAM with real authorized users/teams.
|
|
2
|
+
# Do not leave a fake owner file in the active CODEOWNERS path.
|
|
3
|
+
/src/xp_libs_analytics/engine/ @ORG/TEAM
|
|
4
|
+
/src/xp_libs_analytics/policy/ @ORG/TEAM
|
|
5
|
+
/src/xp_libs_analytics/errors/catalog.json @ORG/TEAM
|
|
6
|
+
/.github/workflows/ @ORG/TEAM
|
|
7
|
+
/pyproject.toml @ORG/TEAM
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
version: 2
|
|
2
|
+
updates:
|
|
3
|
+
- package-ecosystem: pip
|
|
4
|
+
directory: /
|
|
5
|
+
schedule:
|
|
6
|
+
interval: weekly
|
|
7
|
+
open-pull-requests-limit: 5
|
|
8
|
+
# Refresh the Inspect AI storage stack together. Keep security updates eligible.
|
|
9
|
+
ignore:
|
|
10
|
+
- dependency-name: aiobotocore
|
|
11
|
+
update-types: ['version-update:semver-major', 'version-update:semver-minor', 'version-update:semver-patch']
|
|
12
|
+
- dependency-name: boto3
|
|
13
|
+
update-types: ['version-update:semver-major', 'version-update:semver-minor', 'version-update:semver-patch']
|
|
14
|
+
- dependency-name: botocore
|
|
15
|
+
update-types: ['version-update:semver-major', 'version-update:semver-minor', 'version-update:semver-patch']
|
|
16
|
+
- dependency-name: fsspec
|
|
17
|
+
update-types: ['version-update:semver-major', 'version-update:semver-minor', 'version-update:semver-patch']
|
|
18
|
+
- dependency-name: python-dateutil
|
|
19
|
+
update-types: ['version-update:semver-major', 'version-update:semver-minor', 'version-update:semver-patch']
|
|
20
|
+
- dependency-name: s3fs
|
|
21
|
+
update-types: ['version-update:semver-major', 'version-update:semver-minor', 'version-update:semver-patch']
|
|
22
|
+
- package-ecosystem: github-actions
|
|
23
|
+
directory: /
|
|
24
|
+
schedule:
|
|
25
|
+
interval: weekly
|
|
26
|
+
open-pull-requests-limit: 5
|
|
27
|
+
groups:
|
|
28
|
+
codeql:
|
|
29
|
+
patterns: ['github/codeql-action*']
|
|
30
|
+
artifacts:
|
|
31
|
+
patterns: ['actions/upload-artifact', 'actions/download-artifact']
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
## Description and motivation
|
|
2
|
+
|
|
3
|
+
## Affected contracts / V1 operators / public API
|
|
4
|
+
- [ ] Updated `QUERY_LANGUAGE_V1.md` / semantic version decision if applicable
|
|
5
|
+
- [ ] New/changed error codes and catalog parity (single `catalog.json`)
|
|
6
|
+
- [ ] Updated agent skill and machine-valid examples if behavior changed
|
|
7
|
+
|
|
8
|
+
## Safety and threat model
|
|
9
|
+
- [ ] No unsafe SQL/Python/UDF/network/file access introduced
|
|
10
|
+
- [ ] Authorization and handle ownership unchanged or explicitly reviewed
|
|
11
|
+
- [ ] Resource budgets and input/output leakage considered
|
|
12
|
+
- [ ] No real records/secrets in fixtures, logs or artifacts
|
|
13
|
+
|
|
14
|
+
## Testing evidence (actual)
|
|
15
|
+
- [ ] Positive and negative cases
|
|
16
|
+
- [ ] Penetration/security regression for affected boundary
|
|
17
|
+
- [ ] Property/fuzz invariants
|
|
18
|
+
- [ ] FastMCP client tests if MCP changed
|
|
19
|
+
- [ ] Line and branch coverage thresholds
|
|
20
|
+
- [ ] Fresh wheel install/import/skill/catalog smoke
|
|
21
|
+
|
|
22
|
+
## Performance and operational impact
|
|
23
|
+
|
|
24
|
+
## Backward compatibility / migration
|
|
25
|
+
|
|
26
|
+
## Reviewer notes / release risk
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
merge_group:
|
|
7
|
+
permissions:
|
|
8
|
+
contents: read
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ci-${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
jobs:
|
|
13
|
+
quality:
|
|
14
|
+
name: lint-and-type
|
|
15
|
+
runs-on: ubuntu-latest
|
|
16
|
+
steps:
|
|
17
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
18
|
+
with:
|
|
19
|
+
persist-credentials: false
|
|
20
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
|
|
21
|
+
with:
|
|
22
|
+
python-version: '3.12'
|
|
23
|
+
- run: python -m pip install -c requirements-lock.txt -e '.[dev,mcp,agent-eval]'
|
|
24
|
+
- run: ruff check .
|
|
25
|
+
- run: ruff format --check .
|
|
26
|
+
- run: mypy src/xp_libs_analytics
|
|
27
|
+
tests:
|
|
28
|
+
name: tests (${{ matrix.os }}, ${{ matrix.python }})
|
|
29
|
+
runs-on: ${{ matrix.os }}
|
|
30
|
+
strategy:
|
|
31
|
+
fail-fast: false
|
|
32
|
+
matrix:
|
|
33
|
+
os: [ubuntu-latest, windows-latest]
|
|
34
|
+
python: ['3.12', '3.13', '3.14']
|
|
35
|
+
steps:
|
|
36
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
37
|
+
with:
|
|
38
|
+
persist-credentials: false
|
|
39
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
|
|
40
|
+
with:
|
|
41
|
+
python-version: ${{ matrix.python }}
|
|
42
|
+
- run: python -m pip install -c requirements-lock.txt -e '.[dev,mcp,agent-eval]'
|
|
43
|
+
- run: python -m pytest --cov=xp_libs_analytics --cov=evals.agent_skill --cov-branch --cov-report=json --cov-report=xml --cov-fail-under=90 --junitxml=junit.xml
|
|
44
|
+
- run: python scripts/check_critical_coverage.py coverage.json
|
|
45
|
+
- run: python examples/run_examples.py --lint-only
|
|
46
|
+
- run: python examples/run_examples.py --all
|
|
47
|
+
- run: python scripts/resource_probe.py
|
|
48
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
49
|
+
if: always()
|
|
50
|
+
with:
|
|
51
|
+
name: evidence-${{ matrix.os }}-${{ matrix.python }}
|
|
52
|
+
path: |
|
|
53
|
+
junit.xml
|
|
54
|
+
coverage.json
|
|
55
|
+
coverage.xml
|
|
56
|
+
docs/evidence/resource-probes.json
|
|
57
|
+
retention-days: 7
|
|
58
|
+
package:
|
|
59
|
+
name: build-smoke
|
|
60
|
+
runs-on: ubuntu-latest
|
|
61
|
+
steps:
|
|
62
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
63
|
+
with:
|
|
64
|
+
persist-credentials: false
|
|
65
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
|
|
66
|
+
with:
|
|
67
|
+
python-version: '3.12'
|
|
68
|
+
- run: python -m pip install -c requirements-lock.txt build twine
|
|
69
|
+
- run: python -m build
|
|
70
|
+
- run: python -m twine check dist/*
|
|
71
|
+
- run: python scripts/verify_dist.py
|
|
72
|
+
benchmark:
|
|
73
|
+
if: github.event_name == 'push'
|
|
74
|
+
runs-on: ubuntu-latest
|
|
75
|
+
steps:
|
|
76
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
77
|
+
with:
|
|
78
|
+
persist-credentials: false
|
|
79
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
|
|
80
|
+
with:
|
|
81
|
+
python-version: '3.12'
|
|
82
|
+
- run: python -m pip install -c requirements-lock.txt -e '.[dev]'
|
|
83
|
+
- run: python scripts/benchmark.py
|
|
84
|
+
- run: python scripts/benchmark_matching.py --trusted-in-process
|
|
85
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
86
|
+
with:
|
|
87
|
+
name: benchmarks
|
|
88
|
+
path: |
|
|
89
|
+
docs/evidence/benchmarks.json
|
|
90
|
+
docs/evidence/matching-benchmarks-v0.4.json
|
|
91
|
+
retention-days: 7
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
tags: ['v*']
|
|
5
|
+
permissions:
|
|
6
|
+
contents: read
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
12
|
+
with:
|
|
13
|
+
persist-credentials: false
|
|
14
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
|
|
15
|
+
with:
|
|
16
|
+
python-version: '3.12'
|
|
17
|
+
- name: Verify version tag
|
|
18
|
+
run: |
|
|
19
|
+
python - <<'PY'
|
|
20
|
+
import os, tomllib
|
|
21
|
+
from pathlib import Path
|
|
22
|
+
version = tomllib.loads(Path('pyproject.toml').read_text())['project']['version']
|
|
23
|
+
assert version != '0.0.0' and os.environ['GITHUB_REF_NAME'] == f'v{version}'
|
|
24
|
+
PY
|
|
25
|
+
- run: python -m pip install --upgrade pip
|
|
26
|
+
- run: python -m pip install -c requirements-lock.txt -e '.[dev,mcp,agent-eval]'
|
|
27
|
+
- run: ruff check . && ruff format --check . && mypy src/xp_libs_analytics
|
|
28
|
+
- run: python -m pytest --cov=xp_libs_analytics --cov=evals.agent_skill --cov-branch --cov-report=json --cov-fail-under=90
|
|
29
|
+
- run: python scripts/check_critical_coverage.py coverage.json
|
|
30
|
+
- run: python -m pip_audit
|
|
31
|
+
- run: python scripts/inventory.py
|
|
32
|
+
- run: python -m build
|
|
33
|
+
- run: python -m twine check dist/*
|
|
34
|
+
- run: python scripts/verify_dist.py
|
|
35
|
+
- run: sha256sum dist/* > SHA256SUMS
|
|
36
|
+
- uses: actions/upload-artifact@cf430e030ddbb5b0abf93d22962f4752f3646cd9 # v7.0.2
|
|
37
|
+
with:
|
|
38
|
+
name: release-artifacts
|
|
39
|
+
path: |
|
|
40
|
+
dist/*
|
|
41
|
+
SHA256SUMS
|
|
42
|
+
scripts/smoke.py
|
|
43
|
+
docs/evidence/sbom.json
|
|
44
|
+
retention-days: 30
|
|
45
|
+
testpypi:
|
|
46
|
+
needs: build
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
environment: testpypi
|
|
49
|
+
permissions:
|
|
50
|
+
contents: read
|
|
51
|
+
id-token: write
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
54
|
+
with:
|
|
55
|
+
name: release-artifacts
|
|
56
|
+
- run: sha256sum -c SHA256SUMS
|
|
57
|
+
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # release/v1
|
|
58
|
+
with:
|
|
59
|
+
repository-url: https://test.pypi.org/legacy/
|
|
60
|
+
verify-testpypi:
|
|
61
|
+
needs: testpypi
|
|
62
|
+
runs-on: ubuntu-latest
|
|
63
|
+
steps:
|
|
64
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
65
|
+
with:
|
|
66
|
+
name: release-artifacts
|
|
67
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
|
|
68
|
+
with:
|
|
69
|
+
python-version: '3.12'
|
|
70
|
+
- run: |
|
|
71
|
+
VERSION="${GITHUB_REF_NAME#v}"
|
|
72
|
+
python -m pip download --no-deps --index-url https://test.pypi.org/simple "xp-libs-analytics==$VERSION" --dest fetched
|
|
73
|
+
cmp dist/*.whl fetched/*.whl
|
|
74
|
+
sha256sum -c SHA256SUMS
|
|
75
|
+
python -m venv smoke
|
|
76
|
+
smoke/bin/python -m pip install fetched/*.whl
|
|
77
|
+
smoke/bin/python scripts/smoke.py
|
|
78
|
+
smoke/bin/xp-libs-analytics --help
|
|
79
|
+
pypi:
|
|
80
|
+
needs: verify-testpypi
|
|
81
|
+
runs-on: ubuntu-latest
|
|
82
|
+
environment: pypi
|
|
83
|
+
permissions:
|
|
84
|
+
contents: read
|
|
85
|
+
id-token: write
|
|
86
|
+
steps:
|
|
87
|
+
- uses: actions/download-artifact@9000827ccba6bdab643e8b6fd33ac0654aef8333 # v8.0.2
|
|
88
|
+
with:
|
|
89
|
+
name: release-artifacts
|
|
90
|
+
- run: sha256sum -c SHA256SUMS
|
|
91
|
+
- uses: pypa/gh-action-pypi-publish@7245906fb61fa33a13554f9d5fb856fe61758086 # release/v1
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
name: Security
|
|
2
|
+
on:
|
|
3
|
+
pull_request:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
schedule:
|
|
7
|
+
- cron: '17 8 * * 1'
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
jobs:
|
|
11
|
+
audit:
|
|
12
|
+
runs-on: ubuntu-latest
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
15
|
+
with:
|
|
16
|
+
persist-credentials: false
|
|
17
|
+
- uses: actions/setup-python@6d4fd22b20465ccc0f7354476588e8df7c9ca0e0 # v7
|
|
18
|
+
with:
|
|
19
|
+
python-version: '3.12'
|
|
20
|
+
- run: python -m pip install --upgrade pip
|
|
21
|
+
- run: python -m pip install -c requirements-lock.txt -e '.[dev,mcp,agent-eval]'
|
|
22
|
+
- run: python -m pip_audit
|
|
23
|
+
codeql:
|
|
24
|
+
runs-on: ubuntu-latest
|
|
25
|
+
permissions:
|
|
26
|
+
actions: read
|
|
27
|
+
contents: read
|
|
28
|
+
security-events: write
|
|
29
|
+
steps:
|
|
30
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
31
|
+
with:
|
|
32
|
+
persist-credentials: false
|
|
33
|
+
- uses: github/codeql-action/init@33d7b85da1a04171e211befe2c739303b9a4c066 # v4
|
|
34
|
+
with:
|
|
35
|
+
languages: python
|
|
36
|
+
- uses: github/codeql-action/analyze@33d7b85da1a04171e211befe2c739303b9a4c066 # v4
|
|
37
|
+
dependency-review:
|
|
38
|
+
if: github.event_name == 'pull_request'
|
|
39
|
+
runs-on: ubuntu-latest
|
|
40
|
+
permissions:
|
|
41
|
+
contents: read
|
|
42
|
+
pull-requests: read
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7
|
|
45
|
+
with:
|
|
46
|
+
persist-credentials: false
|
|
47
|
+
- uses: actions/dependency-review-action@a1d282b36b6f3519aa1f3fc636f609c47dddb294 # v5.0.0
|
|
48
|
+
with:
|
|
49
|
+
fail-on-severity: high
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
.pytest_cache/
|
|
4
|
+
.ruff_cache/
|
|
5
|
+
.mypy_cache/
|
|
6
|
+
.hypothesis/
|
|
7
|
+
.coverage*
|
|
8
|
+
!.coveragerc
|
|
9
|
+
coverage.xml
|
|
10
|
+
coverage.json
|
|
11
|
+
htmlcov/
|
|
12
|
+
dist/
|
|
13
|
+
build/
|
|
14
|
+
*.egg-info/
|
|
15
|
+
.venv/
|
|
16
|
+
.venv-smoke/
|
|
17
|
+
evals/agent_skill/reports/*
|
|
18
|
+
!evals/agent_skill/reports/.gitignore
|
|
19
|
+
*.log
|
|
20
|
+
.env
|
|
21
|
+
.env.*
|
|
22
|
+
!.env.example
|
|
23
|
+
docs/evidence/*.xml
|
|
24
|
+
docs/evidence/*.txt
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
## 0.4.0 — Bounded string and fuzzy query matching
|
|
5
|
+
|
|
6
|
+
- Extend analytics.query/v1 with explicit Unicode/trim/casefold normalization, not_contains, Unicode word boundaries, LIKE/ILIKE, Rust regex and exhaustive RapidFuzz ratio/wratio/token_sort predicates.
|
|
7
|
+
- Add strict disjoint multi-field match nodes shared by filters and every conditional aggregate; preserve typed datetime/numeric comparisons, all 20 aggregates, grouping/HAVING/ordering and temporal semantics.
|
|
8
|
+
- Prevalidate Rust syntax with Polars, enforce authorized fields and candidate/comparison/normalization/expanded-AST budgets, and use native Polars membership without Python row UDFs or persistent value caches.
|
|
9
|
+
- Default regex/fuzzy/diagnostics to OS-limited workers. Rank optional privacy-cleared matching evidence independently of aggregates; raw values require explicit host and field disclosure policy.
|
|
10
|
+
- Add 11 MATCH_* canonical error distinctions (73 total), preserve catalog-only messages, and explicitly reject entity/alias/identity inference.
|
|
11
|
+
- Add 11 runnable YAML examples (28 total), a full matching resource/skill, deterministic security/property/integration tests and 11 optional agent evaluation recipes (116 total). Live model ID and endpoint are runtime-only.
|
|
12
|
+
- Require MIT-licensed RapidFuzz >=3.14.6,<3.15; preserve optional FastMCP/Inspect separation. Keep the 0.3.0 named registry API, without reintroducing legacy dataset handles or a search prerequisite.
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## 0.3.0 — Named context-local dataset sources (breaking)
|
|
16
|
+
|
|
17
|
+
- Replace dataset.handle with dataset.name and query_yaml(handle, text) with query_yaml(text). No handle-based compatibility API remains.
|
|
18
|
+
- Add DatasetRegistry, explicit register_records(name, records), atomic replace_records, list_datasets, unregister_dataset, independent create_context namespaces and safe closure.
|
|
19
|
+
- Keep opaque IDs internal; snapshot leases retain running queries through replacement/removal and keep retired storage charged until safe reclamation. Revisions do not repeat within a context; expected_revision rejects stale writes.
|
|
20
|
+
- MCP adds analytics_list_datasets, requires names for describe/uploads/unregister, removes analytics_release_dataset, and supports trusted context_resolver. Authenticated policy changes retain namespace identity while rechecking permissions.
|
|
21
|
+
- Replace DATA_HANDLE_UNKNOWN / DATA_HANDLE_EXPIRED / RESOURCE_HANDLES_LIMIT with DATASET_NAME_UNKNOWN / DATASET_SNAPSHOT_STALE / RESOURCE_DATASETS_LIMIT. Add DATASET_NAME_DUPLICATE and DATASET_NAME_INVALID: 62 canonical codes total.
|
|
22
|
+
- Update every YAML example, schema, product skill, evaluator and developer reference. Reserve register_stream with explicit unsupported-feature rejection; no streaming implementation.
|
|
23
|
+
|
|
24
|
+
## 0.2.0 — local build
|
|
25
|
+
|
|
26
|
+
- Rename the distribution/CLI to `xp-libs-analytics` and imports to `xp_libs_analytics`.
|
|
27
|
+
- Preserve the independently usable YAML/analytics core and optional FastMCP adapter; add a bring-your-own-MCP example and import-isolation regression test.
|
|
28
|
+
- Add optional Inspect AI agent evaluations, deterministic scenario/oracle contracts, real MCP recovery seeding, semantic/result scorers, memory-only Inspect logs, sanitized reporting and skill/baseline comparison.
|
|
29
|
+
- Add 105 synthetic scenarios and offline/live test separation. Live results are recorded separately from deterministic test evidence.
|
|
30
|
+
|
|
31
|
+
## 0.1.0 — local build
|
|
32
|
+
|
|
33
|
+
- Implement JSON/NDJSON/mapping admission, full-snapshot discovery, immutable owner-scoped handles, field visibility and shared quotas.
|
|
34
|
+
- Implement restricted YAML, strict discriminated Pydantic models, semantic authorization, immutable cost plans, and fixed Polars compilation.
|
|
35
|
+
- Support all 19 predicate/logical operators and 20 aggregates, UTC ranges, tumbling/sliding windows, HAVING, stable sorting, and quality evidence.
|
|
36
|
+
- Preserve the 60-code canonical catalog; include structured errors and YAML locations.
|
|
37
|
+
- Add optional standalone FastMCP tools, upload policy, launcher/authenticated-host identity, and packaged skill/examples.
|
|
38
|
+
- Add independent oracle, property/security/agent-workflow tests, real MCP/stdio integration, OS-limited workers, benchmarks, distribution smoke and release workflows.
|
|
39
|
+
- Public GitHub/TestPyPI/PyPI release is not configured or performed.
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Use Python 3.12+ and install `-c requirements-lock.txt -e '.[dev,mcp]'`. Run the verification commands in README before submitting a PR. Tests use synthetic fixtures and an independent Python oracle. Every YAML example must execute through the restricted parser, strict AST, semantic planner and backend.
|
|
4
|
+
|
|
5
|
+
Preserve the [language](docs/query-language.md), [parser boundary](docs/yaml-security.md), and [error contract](docs/errors.md). Messages live exclusively in `src/xp_libs_analytics/errors/catalog.json`; code additions require enum, tests, and changelog changes. Semantic changes require schema/fixture review and a version decision.
|
|
6
|
+
|
|
7
|
+
PR CI enforces lint, format, strict mypy, >=90% aggregate coverage and >=95% branch coverage for each critical module. Branchless critical modules require >=95% statement coverage. Run security and actual FastMCP-client integration tests.
|
|
8
|
+
|
|
9
|
+
Original contributions are MIT licensed. Preserve third-party notices. Never put credentials, real private records, or sensitive schemas in code, issues, fixtures, logs or CI artifacts. See SECURITY.md for disclosure and docs/releasing.md for protected OIDC publishing.
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
FROM python:3.12-slim
|
|
2
|
+
ENV PYTHONUNBUFFERED=1 POLARS_MAX_THREADS=2
|
|
3
|
+
WORKDIR /app
|
|
4
|
+
COPY . /app
|
|
5
|
+
RUN python -m pip install --no-cache-dir --upgrade 'pip>=26.3' && python -m pip install --no-cache-dir -c requirements-lock.txt '.[mcp]' && useradd --uid 10001 --create-home analytics
|
|
6
|
+
USER 10001
|
|
7
|
+
ENTRYPOINT ["xp-libs-analytics"]
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Rodrigo Alves
|
|
4
|
+
Copyright (c) 2026 Generic In-Memory Analytics contributors
|
|
5
|
+
|
|
6
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
7
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
8
|
+
in the Software without restriction, including without limitation the rights
|
|
9
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
10
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
11
|
+
furnished to do so, subject to the following conditions:
|
|
12
|
+
|
|
13
|
+
The above copyright notice and this permission notice shall be included in all
|
|
14
|
+
copies or substantial portions of the Software.
|
|
15
|
+
|
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
17
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
18
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
19
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
20
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
21
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
22
|
+
SOFTWARE.
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: xp-libs-analytics
|
|
3
|
+
Version: 0.4.0
|
|
4
|
+
Summary: Schema-on-read, in-memory analytics for agent-generated YAML queries
|
|
5
|
+
Project-URL: Source, https://github.com/rrodrigoa/xp-libs-analytics
|
|
6
|
+
Project-URL: Issues, https://github.com/rrodrigoa/xp-libs-analytics/issues
|
|
7
|
+
Project-URL: Documentation, https://github.com/rrodrigoa/xp-libs-analytics/blob/main/README.md
|
|
8
|
+
Author: Generic In-Memory Analytics contributors
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
12
|
+
Keywords: agents,analytics,in-memory,json,mcp,polars,yaml
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Operating System :: OS Independent
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering :: Information Analysis
|
|
20
|
+
Requires-Python: >=3.12
|
|
21
|
+
Requires-Dist: polars<2.2,>=2.1
|
|
22
|
+
Requires-Dist: pydantic<3,>=2.14
|
|
23
|
+
Requires-Dist: pyyaml<7,>=6.0.2
|
|
24
|
+
Requires-Dist: rapidfuzz<3.15,>=3.14.6
|
|
25
|
+
Requires-Dist: tzdata>=2025.2; sys_platform == 'win32'
|
|
26
|
+
Provides-Extra: agent-eval
|
|
27
|
+
Requires-Dist: fastmcp<4.2,>=4.1.6; extra == 'agent-eval'
|
|
28
|
+
Requires-Dist: inspect-ai==0.3.287; extra == 'agent-eval'
|
|
29
|
+
Requires-Dist: openai==3.46.0; extra == 'agent-eval'
|
|
30
|
+
Provides-Extra: dev
|
|
31
|
+
Requires-Dist: build>=1.2; extra == 'dev'
|
|
32
|
+
Requires-Dist: hypothesis>=6; extra == 'dev'
|
|
33
|
+
Requires-Dist: mypy>=1.15; extra == 'dev'
|
|
34
|
+
Requires-Dist: pip-audit>=2.8; extra == 'dev'
|
|
35
|
+
Requires-Dist: psutil>=7; extra == 'dev'
|
|
36
|
+
Requires-Dist: pytest-asyncio<3,>=1; extra == 'dev'
|
|
37
|
+
Requires-Dist: pytest-cov<8,>=6; extra == 'dev'
|
|
38
|
+
Requires-Dist: pytest<10,>=8; extra == 'dev'
|
|
39
|
+
Requires-Dist: ruff>=0.9; extra == 'dev'
|
|
40
|
+
Requires-Dist: twine>=6; extra == 'dev'
|
|
41
|
+
Requires-Dist: types-pyyaml>=6; extra == 'dev'
|
|
42
|
+
Provides-Extra: mcp
|
|
43
|
+
Requires-Dist: fastmcp<4.2,>=4.1.6; extra == 'mcp'
|
|
44
|
+
Description-Content-Type: text/markdown
|
|
45
|
+
|
|
46
|
+
# XP Libs Analytics
|
|
47
|
+
|
|
48
|
+
A Python library for bounded, in-memory snapshot analytics over JSON records with unknown, heterogeneous schemas. Queries are restricted YAML, validated with strict Pydantic models and compiled to fixed Polars expressions. The optional standalone FastMCP adapter supplies tools, an agent skill, and 28 read-only query examples.
|
|
49
|
+
|
|
50
|
+
Python 3.12+ · MIT · Import: `xp_libs_analytics` · Distribution: `xp-libs-analytics`
|
|
51
|
+
|
|
52
|
+
The distribution uses hyphens for package indexes and `pip`; Python imports use underscores because hyphens are not valid identifiers. The previous `agent_analytics` import and `agent-analytics-mcp` distribution/command have been replaced.
|
|
53
|
+
|
|
54
|
+
## Install and run
|
|
55
|
+
|
|
56
|
+
From this checkout:
|
|
57
|
+
|
|
58
|
+
```sh
|
|
59
|
+
python -m pip install .
|
|
60
|
+
python -m pip install '.[mcp]' # optional MCP adapter
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
```python
|
|
64
|
+
from xp_libs_analytics import AnalyticsEngine
|
|
65
|
+
|
|
66
|
+
engine = AnalyticsEngine()
|
|
67
|
+
my_data = [{"value": 10}, {"value": 20}, {"value": None}, {}]
|
|
68
|
+
engine.register_records(name="observations", records=my_data)
|
|
69
|
+
engine.register_records("events", [{"kind": "created"}])
|
|
70
|
+
print(engine.list_datasets())
|
|
71
|
+
|
|
72
|
+
query_yaml = """version: analytics.query/v1
|
|
73
|
+
dataset:
|
|
74
|
+
name: observations
|
|
75
|
+
aggregations:
|
|
76
|
+
- {op: count, as: records}
|
|
77
|
+
- {op: avg, field: /value, as: mean}
|
|
78
|
+
- {op: missing_count, field: /value, as: missing}
|
|
79
|
+
"""
|
|
80
|
+
result = engine.query_yaml(query_yaml)
|
|
81
|
+
print(result["rows"]) # [{"records": 4, "mean": 15.0, "missing": 1}]
|
|
82
|
+
|
|
83
|
+
# Atomic publication: future queries resolve the new snapshot.
|
|
84
|
+
engine.replace_records("observations", [{"value": 30}])
|
|
85
|
+
engine.unregister_dataset("events")
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
Logical dataset names are symbolic references, independent of Python variable names, paths and opaque internal snapshot IDs. Registering a duplicate name fails; use `replace_records` to update it. Each query resolves exactly one immutable snapshot. Running queries retain their resolved snapshot through replacement, unregister or context closure; storage remains charged until their leases are released. Result metadata reports the logical name and resolved revision. Revisions increase within a context and can have gaps; re-registering a removed name never reuses an old revision. Optional `expected_revision` on replacement/unregister rejects stale updates.
|
|
89
|
+
|
|
90
|
+
For independent namespaces in one application:
|
|
91
|
+
|
|
92
|
+
```python
|
|
93
|
+
with engine.create_context() as ctx:
|
|
94
|
+
ctx.register_records("observations", [{"value": 7}])
|
|
95
|
+
print(ctx.query_yaml(query_yaml)["rows"])
|
|
96
|
+
# ctx closes and removes its bindings; engine's observations remain independent.
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
Names use 1–64 ASCII letters, digits, underscores or hyphens, starting with a letter. Unknown names return `DATASET_NAME_UNKNOWN` without revealing other contexts. Expired snapshots and stale expected revisions return `DATASET_SNAPSHOT_STALE`. Expired bindings are omitted from discovery; replace or unregister them to reuse resources. `register_stream(name, source)` is reserved and always rejects with `QUERY_UNSUPPORTED_FEATURE`; streaming is not implemented.
|
|
100
|
+
|
|
101
|
+
Input accepts JSON objects, arrays of objects, NDJSON, or Python iterables of JSON mappings. Admission copies records into immutable owner-scoped snapshots. Schema discovery examines every admitted record and returns no raw samples. Fields use RFC 6901 pointers; `/a~1b` addresses key `a/b`. Arrays remain opaque.
|
|
102
|
+
|
|
103
|
+
## Query features
|
|
104
|
+
|
|
105
|
+
| Feature | Supported V1 behavior |
|
|
106
|
+
|---|---|
|
|
107
|
+
| Predicates | 22 typed leaf operators; nested `and`, `or`, `not`; multi-field `match`; three-valued null logic |
|
|
108
|
+
| Aggregates | 20 count, distinct, numeric, linear quantile, sample variance, and conditional operations |
|
|
109
|
+
| Grouping | Up to four scalar dimensions; missing and explicit null groups remain separate |
|
|
110
|
+
| Time | Explicit RFC3339/epoch casts, absolute or relative UTC ranges, epoch-aligned tumbling/sliding windows |
|
|
111
|
+
| Results | HAVING, stable sorting, limit/truncation, strict JSON and quality/provenance evidence |
|
|
112
|
+
| Errors | 73 catalog codes, one canonical packaged message catalog, safe diagnostic locations |
|
|
113
|
+
|
|
114
|
+
See the [query language](docs/query-language.md), [examples](examples/README.md), and [agent skill](skills/generic-analytics/SKILL.md). `NO_DATA` reports absent matching observations. `INSUFFICIENT_DATA` applies the host's minimum sample policy. Unknown sampling cadence yields `coverage: UNKNOWN`; counts do not imply duration.
|
|
115
|
+
|
|
116
|
+
Mixed scalar types require explicit casts. Boolean values are never numeric. Null/missing values are excluded from numeric samples; cast failures configured as null are counted and warned. Integer sums detect overflow. Float statistics reject integer samples beyond exact float64 integer precision. V1 does not offer exact decimal analytics. String matching defaults to case-sensitive literal semantics, with explicit Unicode/case normalization, word, LIKE/ILIKE, bounded Rust regex and RapidFuzz similarity options. See the [matching contract](docs/string-matching.md).
|
|
117
|
+
|
|
118
|
+
## Matching observed values
|
|
119
|
+
|
|
120
|
+
```yaml
|
|
121
|
+
version: analytics.query/v1
|
|
122
|
+
dataset: {name: observations}
|
|
123
|
+
filters:
|
|
124
|
+
- match:
|
|
125
|
+
fields: [/actor/name, /actor/email]
|
|
126
|
+
patterns:
|
|
127
|
+
- {op: word, value: Peter}
|
|
128
|
+
- {op: fuzzy, value: Pter, algorithm: ratio, min_score: 85}
|
|
129
|
+
normalization: {case_sensitive: false, unicode: nfkc, trim: true}
|
|
130
|
+
mode: any
|
|
131
|
+
aggregations:
|
|
132
|
+
- {op: count, as: matching_records}
|
|
133
|
+
options:
|
|
134
|
+
matching_details: {include: true, top_values: 5, include_raw_values: false}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
Discover paths before authoring this query. Every eligible distinct fuzzy candidate is evaluated within host budgets; limit/top_values never approximate an aggregate. A record contributes once even when multiple fields/rules match. Diagnostics are redacted by default; raw display requires host and field permissions. Similarity does not infer identities, merge people or expand nicknames. All new predicates also work in conditional aggregates and with existing grouping, HAVING and windows. Examples 18–28 are runnable against synthetic matching data. RapidFuzz is a required MIT-licensed core dependency; FastMCP and Inspect AI remain optional.
|
|
138
|
+
|
|
139
|
+
Regex/fuzzy and requested matching diagnostics automatically use the bounded worker by default. Keep the documented Windows __main__ guard. Trusted benchmarking can explicitly disable force_matching_isolation; untrusted hosts should retain it. No search API or separate matching tools are needed.
|
|
140
|
+
|
|
141
|
+
## Bounds and deployment
|
|
142
|
+
|
|
143
|
+
Defaults are declared in `Limits` and returned by `engine.capabilities()`: 8 MiB input, 100,000 rows, 256 paths, depth 12, 128 KiB per record, eight named bindings per context and eight active snapshots per principal in a shared store, 64 MiB admitted storage per store, 900-second leases, 64 KiB YAML, 10,000 groups/windows/distinct values, overlap at most 12, 500 result rows and 1 MiB results. Queries share owner quotas within a store (120/minute, two concurrent executions). Hosts may tighten limits; requests cannot change them.
|
|
144
|
+
|
|
145
|
+
The default SDK runs inside a **trusted host process**. Use `AnalyticsEngine(isolated=True)` for untrusted execution: a fresh worker has a 15-second wall deadline, CPU ceiling and 1 GiB absolute memory ceiling (POSIX address-space rlimits / Windows Job Object commit limits). Linux Polars needs native virtual mappings beyond 512 MiB even for small numeric queries; measured additional RSS is much lower. Use a `__main__` guard around executable application entry points on Windows. Parsing and bounded snapshot admission remain in the host process. Containers additionally control network/filesystem privileges; see [security](SECURITY.md) and [architecture](docs/architecture.md).
|
|
146
|
+
|
|
147
|
+
V1 evaluates one snapshot per query. It rejects joins, unions, continuous queries, external sources/sinks, SQL, UDFs, unbounded regex and executable expressions. Dense windows are supported only without grouping, with a bounded grid. In-flight executions keep their admitted snapshot; unregister blocks subsequent name resolution. Foreign-context names and unknown names receive the same unknown-name error. Scope failures receive ACCESS_DENIED.
|
|
148
|
+
|
|
149
|
+
## MCP
|
|
150
|
+
|
|
151
|
+
The YAML parser, typed query models, semantic planner and execution engine belong to the core library. They do not import FastMCP or Inspect AI. A developer can expose the SDK using any MCP implementation or another transport:
|
|
152
|
+
|
|
153
|
+
```python
|
|
154
|
+
from xp_libs_analytics import AnalyticsEngine
|
|
155
|
+
|
|
156
|
+
# Construct per trusted application principal; do not accept identity from agent arguments.
|
|
157
|
+
analytics = AnalyticsEngine()
|
|
158
|
+
analytics.register_records("observations", [{"value": 2}, {"value": 4}])
|
|
159
|
+
|
|
160
|
+
|
|
161
|
+
def query_tool(query_yaml: str) -> dict:
|
|
162
|
+
return analytics.query_yaml(query_yaml)
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
def validation_tool(query_yaml: str) -> dict:
|
|
166
|
+
return analytics.validate_query(query_yaml)
|
|
167
|
+
```
|
|
168
|
+
|
|
169
|
+
Register those callables with your chosen server. Select the authorized execution context and identity in the host, enforce transport authentication, and use `isolated=True` for untrusted execution. The bundled FastMCP adapter is an optional convenience layer.
|
|
170
|
+
|
|
171
|
+
```sh
|
|
172
|
+
xp-libs-analytics --help
|
|
173
|
+
xp-libs-analytics # stdio; uploads disabled
|
|
174
|
+
xp-libs-analytics --allow-uploads # bounded local uploads
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Tools: `analytics_capabilities`, `analytics_list_datasets`, `analytics_load_json`, `analytics_describe`, `analytics_validate_query`, `analytics_explain_query`, `analytics_query`, `analytics_unregister_dataset`, `analytics_error_info`. Query tools accept `query_yaml: str`. Core imports do not load FastMCP.
|
|
178
|
+
|
|
179
|
+
The local stdio server inherits its launcher's authority; one process is one local context. The default backend uses isolated workers. HTTP access fails closed unless a host supplies an authenticated `principal_resolver` and configures FastMCP transport authentication. A host-supplied `engine` deliberately selects that engine's context for local use. Hosted sessions can supply `context_resolver`, a trusted callable returning their authorized engine/context. No tool accepts a context ID or principal. The identity resolver creates distinct namespaces per authenticated principal and reapplies current field/scopes policy per request. The adapter caps cached principal contexts at 128; restarting clears local state. It is not a turnkey public multi-tenant service.
|
|
180
|
+
|
|
181
|
+
## Development and evidence
|
|
182
|
+
|
|
183
|
+
Optional real-model evaluations use Inspect AI and the actual MCP adapter. From this checkout, install `python -m pip install -e '.[dev,mcp,agent-eval]'`, then run `python -m evals.agent_skill.cli validate`. Live evaluation accepts the model connection only at execution time; see [evaluation usage](evals/agent_skill/README.md). Normal CI runs offline evaluator tests and excludes live model tests.
|
|
184
|
+
|
|
185
|
+
```sh
|
|
186
|
+
python -m pip install -c requirements-lock.txt -e '.[dev,mcp,agent-eval]'
|
|
187
|
+
ruff check .
|
|
188
|
+
ruff format --check .
|
|
189
|
+
mypy src/xp_libs_analytics
|
|
190
|
+
pytest --cov=xp_libs_analytics --cov=evals.agent_skill --cov-branch --cov-report=json --cov-report=xml --cov-fail-under=90
|
|
191
|
+
python scripts/check_critical_coverage.py coverage.json
|
|
192
|
+
python examples/run_examples.py --all
|
|
193
|
+
python scripts/resource_probe.py
|
|
194
|
+
python scripts/benchmark.py
|
|
195
|
+
python -m build
|
|
196
|
+
python -m twine check dist/*
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
[Verification evidence](docs/evidence/verification.md) records actual local tests, coverage, benchmarks, audit and build hashes. GitHub checks, protected environments and TestPyPI/PyPI publication require maintainer configuration; this checkout makes no publication claim. See [releasing](docs/releasing.md).
|