cfa-kernel 0.1.5__tar.gz → 0.1.7__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.
- cfa_kernel-0.1.7/CFA_LLM_Demo.ipynb +706 -0
- cfa_kernel-0.1.7/CFA_LLM_Demo.ipynb.py +620 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/PKG-INFO +2 -2
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/README.md +1 -1
- cfa_kernel-0.1.7/cfa_demo_complete.ipynb +971 -0
- cfa_kernel-0.1.7/examples/cfa_demo.py +187 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/pyproject.toml +79 -79
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/__init__.py +39 -39
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/behavior/llm.py +5 -4
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/reporting/serve.py +1 -1
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/core/conditions.py +4 -3
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/core/kernel.py +224 -224
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/normalizer/llm.py +5 -4
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/observability/promotion.py +380 -380
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/reporting/engine.py +456 -456
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/api.md +184 -184
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/faq.md +75 -75
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/intro.md +107 -107
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/whitepaper.md +204 -204
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docusaurus.config.ts +118 -118
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/api.md +170 -170
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/intro.md +106 -106
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/whitepaper.md +58 -58
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/src/pages/index.tsx +104 -104
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.gitattributes +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.github/workflows/ci.yml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.github/workflows/deploy-docs.yml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.github/workflows/deploy-pypi.yml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.github/workflows/governance.yml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.gitignore +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.uv-cache/.gitignore +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.uv-cache/.lock +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.uv-cache/CACHEDIR.TAG +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/.uv-cache/sdists-v9/.gitignore +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/CODE_OF_CONDUCT.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/CONTRIBUTING.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/LICENSE +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/MANUAL_TESTING_GUIDE.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/SECURITY.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/examples/fiscal_governance.yaml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/examples/full_pipeline.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/examples/llm_systematizer.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/examples/runtime_gate.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/examples/standalone_governance.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/examples/standalone_lifecycle.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/examples/standalone_resolution.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/integrations/airflow-governance-gate/README.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/integrations/airflow-governance-gate/dags/cfa_governance_gate_demo.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/integrations/airflow-governance-gate/requirements.txt +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/integrations/airflow-governance-gate/src/governance_gate.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/mcp.json +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/policies/compliance-strict-v1.yaml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/policies/finops-strict-v1.yaml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/policies/prod-v1.yaml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/_lazy.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/adapters/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/adapters/autogen.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/adapters/crewai.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/adapters/dspy.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/adapters/langgraph.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/adapters/openai_agents.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/audit/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/audit/context.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/audit/hashing.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/audit/trail.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/backends/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/backends/dbt.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/backends/pyspark.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/backends/sql.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/behavior/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/behavior/spec.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/behavior/systematizer.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/__main__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/_helpers.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/core/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/core/evaluate.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/core/validate.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/formatters.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/governance/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/governance/audit.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/governance/catalog.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/governance/policy.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/governance/rules.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/governance/signature.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/infrastructure/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/infrastructure/backend_list.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/infrastructure/storage.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/project/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/project/init.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/project/lifecycle.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/project/status.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/project/taxonomy.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/reporting/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/cli/reporting/report.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/config.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/core/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/core/codegen.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/core/phases/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/core/phases/runner.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/core/planner.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/execution/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/execution/partial.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/execution/state_projection.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/governance/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/lifecycle/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/mcp/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/mcp/__main__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/normalizer/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/normalizer/base.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/observability/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/observability/indices.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/observability/metrics.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/observability/notify.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/observability/otel.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/policy/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/policy/bundle.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/policy/catalog.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/policy/engine.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/reporting/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/reporting/charts.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/resolution/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/runtime/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/runtime/gate.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/sandbox/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/sandbox/executor.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/sandbox/mock.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/sandbox/panic.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/storage/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/testing/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/testing/asserts.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/testing/evaluate.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/testing/fixtures.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/testing/markers.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/types.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/validation/__init__.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/validation/runtime.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/validation/signature.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/src/cfa/validation/static.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/conftest.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_adapters.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_airflow_governance_gate.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_audit_persistent.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_behavior.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_behavior_llm.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_catalog.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_cli_validation.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_codegen.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_config.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_context.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_context_persistent.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_dbt_backend.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_hashing.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_indices.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_integration.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_intensive.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_kernel.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_mcp.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_metrics.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_normalizer.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_normalizer_llm.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_notify.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_otel.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_partial_execution.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_planner.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_policy.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_policy_bundle.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_promotion.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_reporting.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_runtime.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_runtime_validation.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_sandbox.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_serialization.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_signature.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_sql_backend.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_state_projection.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_static_validation.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_storage.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_testing.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_types.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/tests/test_user_journeys.py +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/.gitignore +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/README.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/blog/2019-05-28-first-blog-post.mdx +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/blog/2019-05-29-long-blog-post.mdx +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/blog/2021-08-01-mdx-blog-post.mdx +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/blog/2021-08-26-welcome/docusaurus-plushie-banner.jpeg +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/blog/2021-08-26-welcome/index.mdx +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/blog/authors.yml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/blog/tags.yml +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/architecture-notes.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/backends.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/behavior-spec.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/cli.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/getting-started.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/guide.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/integrations/airflow.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/integrations/langgraph.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/integrations/openai-agents.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/mcp-server.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/policy-bundles.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/docs/reporting.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/code.json +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/architecture-notes.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/backends.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/behavior-spec.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/cli.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/faq.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/getting-started.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/guide.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/integrations/airflow.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/integrations/langgraph.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/integrations/openai-agents.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/mcp-server.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/policy-bundles.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/i18n/pt-BR/docusaurus-plugin-content-docs/current/reporting.md +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/package-lock.json +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/package.json +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/sidebars.ts +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/src/components/HomepageFeatures/index.tsx +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/src/components/HomepageFeatures/styles.module.css +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/src/css/custom.css +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/src/pages/index.module.css +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/src/pages/markdown-page.mdx +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/static/.nojekyll +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/static/img/favicon.ico +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/static/img/logo.svg +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/static/img/undraw_docusaurus_mountain.svg +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/static/img/undraw_docusaurus_react.svg +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/static/img/undraw_docusaurus_tree.svg +0 -0
- {cfa_kernel-0.1.5 → cfa_kernel-0.1.7}/website/tsconfig.json +0 -0
|
@@ -0,0 +1,706 @@
|
|
|
1
|
+
{
|
|
2
|
+
"cells": [
|
|
3
|
+
{
|
|
4
|
+
"cell_type": "markdown",
|
|
5
|
+
"id": "",
|
|
6
|
+
"metadata": {},
|
|
7
|
+
"source": [
|
|
8
|
+
"# CFA — Contextual Flux Architecture\n",
|
|
9
|
+
"## LLM-Powered Governance Demo\n",
|
|
10
|
+
"\n",
|
|
11
|
+
"| Section | Feature | LLM Role |\n",
|
|
12
|
+
"|---|---|---|\n",
|
|
13
|
+
"| S1 | Setup & Secrets | Read API key from Databricks Secret Scope |\n",
|
|
14
|
+
"| S2 | Catalog | Operational metadata |\n",
|
|
15
|
+
"| S3 | LLM Normalizer | Semantic intent resolution (replaces keywords) |\n",
|
|
16
|
+
"| S4 | Strict Mode | LLM output validated against catalog |\n",
|
|
17
|
+
"| S5 | LLM Audit Trail | Every call SHA-256 traceable |\n",
|
|
18
|
+
"| S6 | LLM Systematizer | NL governance → BehaviorSpec → PolicyRules |\n",
|
|
19
|
+
"| S7 | Full Kernel + LLM | End-to-end governed execution |\n",
|
|
20
|
+
"| S8 | Runtime Gate + LLM | Guard with LLM-backed validation |\n",
|
|
21
|
+
"| S9 | Compare Normalizers | Rule-based vs LLM side-by-side |\n",
|
|
22
|
+
"| S10 | PolicyEngine + LLM Rules | Close the NL→Rules→Engine loop |\n",
|
|
23
|
+
"\n",
|
|
24
|
+
"**API key:** stored in Databricks Secret Scope `cfa-secrets`, never in code.\n",
|
|
25
|
+
"\n",
|
|
26
|
+
"---\n"
|
|
27
|
+
]
|
|
28
|
+
},
|
|
29
|
+
{
|
|
30
|
+
"cell_type": "markdown",
|
|
31
|
+
"id": "",
|
|
32
|
+
"metadata": {},
|
|
33
|
+
"source": [
|
|
34
|
+
"## Section 1 — Setup & Secrets\n",
|
|
35
|
+
"\n",
|
|
36
|
+
"API key read from Databricks Secret Scope `cfa-secrets/deepseek-key`.\n",
|
|
37
|
+
"Falls back to `DEEPSEEK_API_KEY` env var for local testing.\n"
|
|
38
|
+
]
|
|
39
|
+
},
|
|
40
|
+
{
|
|
41
|
+
"cell_type": "markdown",
|
|
42
|
+
"id": "",
|
|
43
|
+
"metadata": {},
|
|
44
|
+
"source": [
|
|
45
|
+
"## Section 0 — Install\n",
|
|
46
|
+
"\n",
|
|
47
|
+
"Run this cell first to install dependencies.\n"
|
|
48
|
+
]
|
|
49
|
+
},
|
|
50
|
+
{
|
|
51
|
+
"cell_type": "code",
|
|
52
|
+
"id": "",
|
|
53
|
+
"metadata": {},
|
|
54
|
+
"outputs": [],
|
|
55
|
+
"source": [
|
|
56
|
+
"%pip install -q cfa-kernel[all] openai\n"
|
|
57
|
+
]
|
|
58
|
+
},
|
|
59
|
+
{
|
|
60
|
+
"cell_type": "code",
|
|
61
|
+
"id": "",
|
|
62
|
+
"metadata": {},
|
|
63
|
+
"outputs": [],
|
|
64
|
+
"source": [
|
|
65
|
+
"# --- Test if openai is importable ---\n",
|
|
66
|
+
"HAS_OPENAI = False\n",
|
|
67
|
+
"try:\n",
|
|
68
|
+
" import openai\n",
|
|
69
|
+
" print(f\"openai {openai.__version__} - OK\")\n",
|
|
70
|
+
" HAS_OPENAI = True\n",
|
|
71
|
+
"except ImportError as e:\n",
|
|
72
|
+
" print(f\"ERROR: openai not importable: {e}\")\n",
|
|
73
|
+
" print(\"Run: %%pip install openai\")\n",
|
|
74
|
+
"\n",
|
|
75
|
+
"import cfa, os\n",
|
|
76
|
+
"from cfa.normalizer.llm import OpenAILMProvider, LLMNormalizerBackend\n",
|
|
77
|
+
"from cfa.normalizer.base import IntentNormalizer, RuleBasedNormalizerBackend\n",
|
|
78
|
+
"from cfa.runtime import RuntimeGate\n",
|
|
79
|
+
"from cfa.policy.engine import PolicyEngine\n",
|
|
80
|
+
"from cfa.types import StateSignature\n",
|
|
81
|
+
"from cfa.core.kernel import KernelConfig\n",
|
|
82
|
+
"\n",
|
|
83
|
+
"print(f\"CFA version: {cfa.__version__}\")\n",
|
|
84
|
+
"\n",
|
|
85
|
+
"# --- Read API keys from secret scope ---\n",
|
|
86
|
+
"def _try_secret(key):\n",
|
|
87
|
+
" try:\n",
|
|
88
|
+
" return dbutils.secrets.get(\"cfa-secrets\", key)\n",
|
|
89
|
+
" except Exception:\n",
|
|
90
|
+
" return None\n",
|
|
91
|
+
"\n",
|
|
92
|
+
"# Try Databricks secrets, fall back to env vars\n",
|
|
93
|
+
"OPENAI_KEY = _try_secret(\"openai-key\") or os.environ.get(\"OPENAI_API_KEY\")\n",
|
|
94
|
+
"DEEPSEEK_KEY = _try_secret(\"deepseek-key\") or os.environ.get(\"DEEPSEEK_API_KEY\")\n",
|
|
95
|
+
"\n",
|
|
96
|
+
"# Auto-select: prefer OpenAI (better reachability from Azure), fallback to DeepSeek\n",
|
|
97
|
+
"if OPENAI_KEY:\n",
|
|
98
|
+
" LLM_MODEL = \"gpt-4o-mini\"\n",
|
|
99
|
+
" LLM_BASE_URL = None # default api.openai.com\n",
|
|
100
|
+
" LLM_API_KEY = OPENAI_KEY\n",
|
|
101
|
+
" print(f\"Using OpenAI ({LLM_MODEL})\")\n",
|
|
102
|
+
"elif DEEPSEEK_KEY:\n",
|
|
103
|
+
" LLM_MODEL = \"deepseek-chat\"\n",
|
|
104
|
+
" LLM_BASE_URL = \"https://api.deepseek.com\"\n",
|
|
105
|
+
" LLM_API_KEY = DEEPSEEK_KEY\n",
|
|
106
|
+
" print(f\"Using DeepSeek ({LLM_MODEL})\")\n",
|
|
107
|
+
"else:\n",
|
|
108
|
+
" LLM_MODEL = None\n",
|
|
109
|
+
" LLM_BASE_URL = None\n",
|
|
110
|
+
" LLM_API_KEY = None\n",
|
|
111
|
+
" print(\"WARNING: No API key found.\")\n",
|
|
112
|
+
" print(\" Databricks: secrets create-scope cfa-secrets\")\n",
|
|
113
|
+
" print(\" Local: set OPENAI_API_KEY or DEEPSEEK_API_KEY env var\")\n",
|
|
114
|
+
"\n",
|
|
115
|
+
"# Combined gate: need both openai + API key\n",
|
|
116
|
+
"HAS_LLM = HAS_OPENAI and LLM_API_KEY is not None\n",
|
|
117
|
+
"\n",
|
|
118
|
+
"# Helper: create an LLM provider with the auto-detected config\n",
|
|
119
|
+
"def make_provider():\n",
|
|
120
|
+
" \"\"\"Return OpenAILMProvider with auto-detected config.\"\"\"\n",
|
|
121
|
+
" return OpenAILMProvider(\n",
|
|
122
|
+
" model=LLM_MODEL,\n",
|
|
123
|
+
" api_key=LLM_API_KEY,\n",
|
|
124
|
+
" base_url=LLM_BASE_URL,\n",
|
|
125
|
+
" temperature=0.0,\n",
|
|
126
|
+
" )\n"
|
|
127
|
+
]
|
|
128
|
+
},
|
|
129
|
+
{
|
|
130
|
+
"cell_type": "markdown",
|
|
131
|
+
"id": "",
|
|
132
|
+
"metadata": {},
|
|
133
|
+
"source": [
|
|
134
|
+
"---\n",
|
|
135
|
+
"## Section 2 — Data Catalog\n",
|
|
136
|
+
"\n",
|
|
137
|
+
"Catalog grounds the LLM. The LLM receives it in the prompt and MUST reference real datasets.\n"
|
|
138
|
+
]
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
"cell_type": "code",
|
|
142
|
+
"id": "",
|
|
143
|
+
"metadata": {},
|
|
144
|
+
"outputs": [],
|
|
145
|
+
"source": [
|
|
146
|
+
"CATALOG = {\n",
|
|
147
|
+
" 'nfe_bronze': {\n",
|
|
148
|
+
" 'type': 'delta', 'layer': 'bronze', 'size_gb': 50,\n",
|
|
149
|
+
" 'partition_by': ['processing_date'], 'pii': False,\n",
|
|
150
|
+
" 'description': 'Notas Fiscais Eletronicas brutas',\n",
|
|
151
|
+
" },\n",
|
|
152
|
+
" 'clientes_bronze': {\n",
|
|
153
|
+
" 'type': 'delta', 'layer': 'bronze', 'size_gb': 10,\n",
|
|
154
|
+
" 'partition_by': ['processing_date'], 'pii': True,\n",
|
|
155
|
+
" 'pii_columns': ['cpf', 'nome', 'endereco'],\n",
|
|
156
|
+
" 'description': 'Dados cadastrais com CPF e endereco',\n",
|
|
157
|
+
" },\n",
|
|
158
|
+
" 'vendas_bronze': {\n",
|
|
159
|
+
" 'type': 'delta', 'layer': 'bronze', 'size_gb': 2000,\n",
|
|
160
|
+
" 'pii': False,\n",
|
|
161
|
+
" 'description': 'Registros de transacoes de venda',\n",
|
|
162
|
+
" },\n",
|
|
163
|
+
" 'fornecedores_bronze': {\n",
|
|
164
|
+
" 'type': 'delta', 'layer': 'bronze', 'size_gb': 10,\n",
|
|
165
|
+
" 'pii': False,\n",
|
|
166
|
+
" 'description': 'Cadastro de fornecedores',\n",
|
|
167
|
+
" },\n",
|
|
168
|
+
" 'vendas_gold_agregado': {\n",
|
|
169
|
+
" 'type': 'delta', 'layer': 'gold', 'size_gb': 500,\n",
|
|
170
|
+
" 'pii': False,\n",
|
|
171
|
+
" 'description': 'Agregados de vendas para BI',\n",
|
|
172
|
+
" },\n",
|
|
173
|
+
"}\n",
|
|
174
|
+
"\n",
|
|
175
|
+
"from cfa.policy.catalog import validate_catalog\n",
|
|
176
|
+
"result = validate_catalog(CATALOG)\n",
|
|
177
|
+
"print(f\"Catalog valid: {result.valid}\")\n",
|
|
178
|
+
"print(f\" {len(CATALOG)} datasets registered\")\n",
|
|
179
|
+
"for msg in result.messages:\n",
|
|
180
|
+
" print(f\" {msg}\")\n"
|
|
181
|
+
]
|
|
182
|
+
},
|
|
183
|
+
{
|
|
184
|
+
"cell_type": "markdown",
|
|
185
|
+
"id": "",
|
|
186
|
+
"metadata": {},
|
|
187
|
+
"source": [
|
|
188
|
+
"---\n",
|
|
189
|
+
"## Section 3 — LLM Normalizer: Semantic Intent Resolution\n",
|
|
190
|
+
"\n",
|
|
191
|
+
"Rule-based = keyword matching (`join`, `aggregate`, `anonymize`).\n",
|
|
192
|
+
"LLM = sends `intent + catalog` to DeepSeek, parses structured JSON.\n",
|
|
193
|
+
"\n",
|
|
194
|
+
"The `SemanticResolution` returned contains the resolved `StateSignature`.\n"
|
|
195
|
+
]
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
"cell_type": "code",
|
|
199
|
+
"id": "",
|
|
200
|
+
"metadata": {},
|
|
201
|
+
"outputs": [],
|
|
202
|
+
"source": [
|
|
203
|
+
"if not HAS_LLM:\n",
|
|
204
|
+
" print(\"SKIP: no API key configured.\")\n",
|
|
205
|
+
"else:\n",
|
|
206
|
+
" provider = make_provider()\n",
|
|
207
|
+
" llm_backend = LLMNormalizerBackend(provider=provider, strict=False)\n",
|
|
208
|
+
" normalizer = IntentNormalizer(backend=llm_backend)\n",
|
|
209
|
+
"\n",
|
|
210
|
+
" print(\"=\" * 55)\n",
|
|
211
|
+
" print(\"LLM NORMALIZER -- Semantic Resolution\")\n",
|
|
212
|
+
" print(\"=\" * 55)\n",
|
|
213
|
+
"\n",
|
|
214
|
+
" intents = [\n",
|
|
215
|
+
" \"Join NFe with Clientes anonymize CPF and persist to Silver\",\n",
|
|
216
|
+
" \"Aggregate vendas by region persist to Gold\",\n",
|
|
217
|
+
" \"Export raw clientes PII to Gold\",\n",
|
|
218
|
+
" ]\n",
|
|
219
|
+
"\n",
|
|
220
|
+
" for raw in intents:\n",
|
|
221
|
+
" print(f'\\nIntent: \"{raw}\"')\n",
|
|
222
|
+
" res = normalizer.normalize(raw, {}, CATALOG)\n",
|
|
223
|
+
" sig = res.signature\n",
|
|
224
|
+
" print(f\" Domain : {sig.domain}\")\n",
|
|
225
|
+
" print(f\" Intent : {sig.intent}\")\n",
|
|
226
|
+
" print(f\" Target layer : {sig.target_layer}\")\n",
|
|
227
|
+
" ds_names = [d.name for d in sig.datasets]\n",
|
|
228
|
+
" print(f\" Datasets : {ds_names}\")\n",
|
|
229
|
+
" print(f\" Confidence : {res.confidence_score:.2f}\")\n",
|
|
230
|
+
" print(f\" Ambiguity : {res.ambiguity_level}\")\n",
|
|
231
|
+
" if res.reasoning:\n",
|
|
232
|
+
" print(f\" Reasoning : {res.reasoning[:150]}...\")\n",
|
|
233
|
+
"\n",
|
|
234
|
+
" print(\"\\nLLM normalizer baseline complete\")\n"
|
|
235
|
+
]
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
"cell_type": "markdown",
|
|
239
|
+
"id": "",
|
|
240
|
+
"metadata": {},
|
|
241
|
+
"source": [
|
|
242
|
+
"---\n",
|
|
243
|
+
"## Section 4 — Strict Mode: Catalog-Grounded LLM\n",
|
|
244
|
+
"\n",
|
|
245
|
+
"`strict=True` validates the LLM output against the catalog.\n",
|
|
246
|
+
"Hallucinated datasets/references raise `ValueError`.\n"
|
|
247
|
+
]
|
|
248
|
+
},
|
|
249
|
+
{
|
|
250
|
+
"cell_type": "code",
|
|
251
|
+
"id": "",
|
|
252
|
+
"metadata": {},
|
|
253
|
+
"outputs": [],
|
|
254
|
+
"source": [
|
|
255
|
+
"if not HAS_LLM:\n",
|
|
256
|
+
" print(\"SKIP: no API key available\")\n",
|
|
257
|
+
"else:\n",
|
|
258
|
+
" sp = make_provider()\n",
|
|
259
|
+
" sb = LLMNormalizerBackend(provider=sp, strict=True)\n",
|
|
260
|
+
" sn = IntentNormalizer(backend=sb)\n",
|
|
261
|
+
"\n",
|
|
262
|
+
" print(\"=\" * 55)\n",
|
|
263
|
+
" print(\"STRICT MODE — Catalog-grounded LLM\")\n",
|
|
264
|
+
" print(\"=\" * 55)\n",
|
|
265
|
+
"\n",
|
|
266
|
+
" for raw in [\n",
|
|
267
|
+
" \"Join NFe with Clientes anonymize CPF persist to Silver\",\n",
|
|
268
|
+
" \"Full scan vendas without partition to Gold\",\n",
|
|
269
|
+
" ]:\n",
|
|
270
|
+
" print(f\"\\nIntent: \\\"{raw}\\\"\")\n",
|
|
271
|
+
" try:\n",
|
|
272
|
+
" res = sn.normalize(raw, {}, CATALOG)\n",
|
|
273
|
+
" print(f\" PASSED | confidence={res.confidence_score:.2f} layer={res.signature.target_layer}\")\n",
|
|
274
|
+
" except ValueError as e:\n",
|
|
275
|
+
" print(f\" REJECTED | {str(e)[:120]}\")\n",
|
|
276
|
+
"\n",
|
|
277
|
+
" print(\"\\nStrict mode demo complete\")\n"
|
|
278
|
+
]
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
"cell_type": "markdown",
|
|
282
|
+
"id": "",
|
|
283
|
+
"metadata": {},
|
|
284
|
+
"source": [
|
|
285
|
+
"---\n",
|
|
286
|
+
"## Section 5 — LLM Audit Trail\n",
|
|
287
|
+
"\n",
|
|
288
|
+
"Every LLM call is SHA-256 hashed (prompt, response, catalog).\n",
|
|
289
|
+
"Full traceability for compliance audits.\n"
|
|
290
|
+
]
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
"cell_type": "code",
|
|
294
|
+
"id": "",
|
|
295
|
+
"metadata": {},
|
|
296
|
+
"outputs": [],
|
|
297
|
+
"source": [
|
|
298
|
+
"if not HAS_LLM:\n",
|
|
299
|
+
" print(\"SKIP: no API key available\")\n",
|
|
300
|
+
"else:\n",
|
|
301
|
+
" # The 'sb' backend from section 4 already recorded calls\n",
|
|
302
|
+
" records = sb.audit_records\n",
|
|
303
|
+
" print(\"=\" * 55)\n",
|
|
304
|
+
" print(\"LLM AUDIT TRAIL — Tamper-evident LLM calls\")\n",
|
|
305
|
+
" print(\"=\" * 55)\n",
|
|
306
|
+
" print(f\" Total LLM calls recorded: {len(records)}\")\n",
|
|
307
|
+
"\n",
|
|
308
|
+
" for i, rec in enumerate(records):\n",
|
|
309
|
+
" print(f\"\\n Call {i+1}:\")\n",
|
|
310
|
+
" print(f\" Model : {rec.model}\")\n",
|
|
311
|
+
" print(f\" Prompt hash : {rec.prompt_hash[:16]}...\")\n",
|
|
312
|
+
" print(f\" Response hash : {rec.response_hash[:16]}...\")\n",
|
|
313
|
+
" print(f\" Catalog hash : {rec.catalog_hash[:16]}...\")\n",
|
|
314
|
+
" if rec.catalog_validation_errors:\n",
|
|
315
|
+
" for err in rec.catalog_validation_errors:\n",
|
|
316
|
+
" print(f\" Val. error : {err}\")\n",
|
|
317
|
+
" if rec.parsed_json:\n",
|
|
318
|
+
" keys = list(rec.parsed_json.keys())\n",
|
|
319
|
+
" print(f\" Parsed keys : {keys[:8]}\")\n",
|
|
320
|
+
"\n",
|
|
321
|
+
" print(\"\\nLLM audit trail complete\")\n"
|
|
322
|
+
]
|
|
323
|
+
},
|
|
324
|
+
{
|
|
325
|
+
"cell_type": "markdown",
|
|
326
|
+
"id": "",
|
|
327
|
+
"metadata": {},
|
|
328
|
+
"source": [
|
|
329
|
+
"---\n",
|
|
330
|
+
"## Section 6 — LLM Systematizer: NL → PolicyRules\n",
|
|
331
|
+
"\n",
|
|
332
|
+
"Describe governance in natural language. LLM produces `BehaviorSpec`.\n",
|
|
333
|
+
"`Systematizer` converts it to executable `PolicyRule` objects.\n"
|
|
334
|
+
]
|
|
335
|
+
},
|
|
336
|
+
{
|
|
337
|
+
"cell_type": "code",
|
|
338
|
+
"id": "",
|
|
339
|
+
"metadata": {},
|
|
340
|
+
"outputs": [],
|
|
341
|
+
"source": [
|
|
342
|
+
"from cfa.behavior.llm import OpenAISystematizerBackend\n",
|
|
343
|
+
"from cfa.behavior import Systematizer\n",
|
|
344
|
+
"\n",
|
|
345
|
+
"taxonomy, rules = None, None\n",
|
|
346
|
+
"\n",
|
|
347
|
+
"if not HAS_LLM:\n",
|
|
348
|
+
" print(\"SKIP: no LLM available (missing openai or API key)\")\n",
|
|
349
|
+
"else:\n",
|
|
350
|
+
" try:\n",
|
|
351
|
+
" print(\"=\" * 55)\n",
|
|
352
|
+
" print(\"LLM SYSTEMATIZER -- NL to Policy Rules\")\n",
|
|
353
|
+
" print(\"=\" * 55)\n",
|
|
354
|
+
"\n",
|
|
355
|
+
" governance_desc = \"\"\"\\\n",
|
|
356
|
+
"Fiscal ETL pipeline governance:\n",
|
|
357
|
+
"1. All datasets moving from Bronze to Silver/Gold MUST anonymize PII (CPF, nome, endereco)\n",
|
|
358
|
+
"2. Every Silver and Gold write requires a merge_key (upsert, not append)\n",
|
|
359
|
+
"3. Datasets larger than 100GB MUST have partition_by defined\n",
|
|
360
|
+
"4. No raw PII columns may appear in Gold layer\n",
|
|
361
|
+
"5. Maximum cost per pipeline run: 50 DBU\n",
|
|
362
|
+
"\"\"\"\n",
|
|
363
|
+
"\n",
|
|
364
|
+
" sys_backend = OpenAISystematizerBackend(\n",
|
|
365
|
+
" model=LLM_MODEL,\n",
|
|
366
|
+
" api_key=LLM_API_KEY,\n",
|
|
367
|
+
" base_url=LLM_BASE_URL,\n",
|
|
368
|
+
" temperature=0.0,\n",
|
|
369
|
+
" max_tokens=2048,\n",
|
|
370
|
+
" )\n",
|
|
371
|
+
"\n",
|
|
372
|
+
" taxonomy, rules = Systematizer().systematize_from_nl(\n",
|
|
373
|
+
" governance_desc,\n",
|
|
374
|
+
" backend=sys_backend,\n",
|
|
375
|
+
" context=\"Fiscal ETL: NFe, Clientes, Vendas, Fornecedores on Databricks Delta Lake\",\n",
|
|
376
|
+
" target_layer=\"silver\",\n",
|
|
377
|
+
" )\n",
|
|
378
|
+
"\n",
|
|
379
|
+
" print(f\" Categories : {taxonomy.category_count}\")\n",
|
|
380
|
+
" print(f\" Rules generated : {len(rules)}\")\n",
|
|
381
|
+
" print()\n",
|
|
382
|
+
"\n",
|
|
383
|
+
" for rule in rules:\n",
|
|
384
|
+
" print(f\" Rule : {rule.name}\")\n",
|
|
385
|
+
" print(f\" code : {rule.fault_code}\")\n",
|
|
386
|
+
" print(f\" action : {rule.action.value}\")\n",
|
|
387
|
+
" print(f\" severity : {rule.severity.value}\")\n",
|
|
388
|
+
" print()\n",
|
|
389
|
+
"\n",
|
|
390
|
+
" test_intents = taxonomy.generate_test_intents(3)\n",
|
|
391
|
+
" print(f\" CI test intents generated: {len(test_intents)}\")\n",
|
|
392
|
+
" for intent in test_intents:\n",
|
|
393
|
+
" print(f\" - {intent}\")\n",
|
|
394
|
+
"\n",
|
|
395
|
+
" print(\"\\nLLM Systematizer complete\")\n",
|
|
396
|
+
" except Exception as e:\n",
|
|
397
|
+
" print(f\" LLM call failed: {type(e).__name__}: {str(e)[:100]}\")\n"
|
|
398
|
+
]
|
|
399
|
+
},
|
|
400
|
+
{
|
|
401
|
+
"cell_type": "markdown",
|
|
402
|
+
"id": "",
|
|
403
|
+
"metadata": {},
|
|
404
|
+
"source": [
|
|
405
|
+
"---\n",
|
|
406
|
+
"## Section 7 — Full Kernel with LLM Normalizer\n",
|
|
407
|
+
"\n",
|
|
408
|
+
"Same 5-phase pipeline (Formalize → Govern → Generate → Execute → Validate/Audit).\n",
|
|
409
|
+
"Only the **Formalize** phase switches from keyword-matching to DeepSeek.\n"
|
|
410
|
+
]
|
|
411
|
+
},
|
|
412
|
+
{
|
|
413
|
+
"cell_type": "code",
|
|
414
|
+
"id": "",
|
|
415
|
+
"metadata": {},
|
|
416
|
+
"outputs": [],
|
|
417
|
+
"source": [
|
|
418
|
+
"from cfa import KernelOrchestrator\n",
|
|
419
|
+
"\n",
|
|
420
|
+
"if not HAS_LLM:\n",
|
|
421
|
+
" print(\"SKIP: no API key available\")\n",
|
|
422
|
+
"else:\n",
|
|
423
|
+
" provider = make_provider()\n",
|
|
424
|
+
" backend = LLMNormalizerBackend(provider=provider, strict=True)\n",
|
|
425
|
+
"\n",
|
|
426
|
+
" kernel = KernelOrchestrator(\n",
|
|
427
|
+
" catalog=CATALOG,\n",
|
|
428
|
+
" config=KernelConfig(\n",
|
|
429
|
+
" policy_bundle_version=\"fiscal-prod-v1.0\",\n",
|
|
430
|
+
" backend=\"pyspark\",\n",
|
|
431
|
+
" ),\n",
|
|
432
|
+
" normalizer_backend=backend,\n",
|
|
433
|
+
" )\n",
|
|
434
|
+
"\n",
|
|
435
|
+
" print(\"=\" * 55)\n",
|
|
436
|
+
" print(\"FULL KERNEL + LLM NORMALIZER\")\n",
|
|
437
|
+
" print(\"=\" * 55)\n",
|
|
438
|
+
"\n",
|
|
439
|
+
" for intent in [\n",
|
|
440
|
+
" \"Join NFe with Clientes anonymize CPF and persist to Silver\",\n",
|
|
441
|
+
" \"Aggregate vendas by region persist to Gold\",\n",
|
|
442
|
+
" \"Export raw clientes PII to Gold\",\n",
|
|
443
|
+
" ]:\n",
|
|
444
|
+
" print(f\"\\nIntent: \\\"{intent}\\\"\")\n",
|
|
445
|
+
" try:\n",
|
|
446
|
+
" result = kernel.process(intent)\n",
|
|
447
|
+
" print(f\" -> Decision : {result.state.value.upper()}\")\n",
|
|
448
|
+
" if result.signature is not None:\n",
|
|
449
|
+
" print(f\" -> Sig hash : {result.signature.signature_hash[:24]}...\")\n",
|
|
450
|
+
" if result.replan_history:\n",
|
|
451
|
+
" print(f\" -> Replans : {len(result.replan_history)}\")\n",
|
|
452
|
+
" if result.generated_code and result.generated_code.code:\n",
|
|
453
|
+
" lines = result.generated_code.code.splitlines()\n",
|
|
454
|
+
" print(f\" -> Code gen : {len(lines)} lines {result.generated_code.language}\")\n",
|
|
455
|
+
" except Exception as e:\n",
|
|
456
|
+
" print(f\" -> BLOCKED : {type(e).__name__} | {str(e)[:100]}\")\n",
|
|
457
|
+
"\n",
|
|
458
|
+
" calls = backend.audit_records\n",
|
|
459
|
+
" print(f\"\\n LLM calls by kernel: {len(calls)}\")\n",
|
|
460
|
+
" for rec in calls:\n",
|
|
461
|
+
" print(f\" prompt={rec.prompt_hash[:16]}... response={rec.response_hash[:16]}...\")\n",
|
|
462
|
+
"\n",
|
|
463
|
+
" print(\"\\nFull kernel + LLM complete\")\n"
|
|
464
|
+
]
|
|
465
|
+
},
|
|
466
|
+
{
|
|
467
|
+
"cell_type": "markdown",
|
|
468
|
+
"id": "",
|
|
469
|
+
"metadata": {},
|
|
470
|
+
"source": [
|
|
471
|
+
"---\n",
|
|
472
|
+
"## Section 8 — Runtime Gate\n",
|
|
473
|
+
"\n",
|
|
474
|
+
"`RuntimeGate` validates intents before execution.\n",
|
|
475
|
+
"With `policy_rules` from LLM Systematizer, the gate inherits NL-defined governance.\n"
|
|
476
|
+
]
|
|
477
|
+
},
|
|
478
|
+
{
|
|
479
|
+
"cell_type": "code",
|
|
480
|
+
"id": "",
|
|
481
|
+
"metadata": {},
|
|
482
|
+
"outputs": [],
|
|
483
|
+
"source": [
|
|
484
|
+
"import traceback\n",
|
|
485
|
+
"print(\"=\" * 55)\n",
|
|
486
|
+
"print(\"RUNTIME GATE\")\n",
|
|
487
|
+
"print(\"=\" * 55)\n",
|
|
488
|
+
"\n",
|
|
489
|
+
"try:\n",
|
|
490
|
+
" gate = RuntimeGate(\n",
|
|
491
|
+
" catalog=CATALOG,\n",
|
|
492
|
+
" policy_rules=rules if rules is not None else None,\n",
|
|
493
|
+
" )\n",
|
|
494
|
+
"\n",
|
|
495
|
+
" result = gate.validate(\"Join NFe with Clientes and persist to Silver\")\n",
|
|
496
|
+
" print(f\" validate() -> state={result.state.value} passed={result.passed}\")\n",
|
|
497
|
+
" print(f\" gate_id={result.gate_id} execution_id={result.execution_id[:8]}...\")\n",
|
|
498
|
+
"\n",
|
|
499
|
+
" @gate.guard(\"aggregate sales data with PII protected\")\n",
|
|
500
|
+
" def my_pipeline():\n",
|
|
501
|
+
" return \"pipeline executed\"\n",
|
|
502
|
+
"\n",
|
|
503
|
+
" print(f\" @gate.guard -> {my_pipeline()}\")\n",
|
|
504
|
+
" print(\"\\nRuntime Gate demo complete\")\n",
|
|
505
|
+
"except Exception as e:\n",
|
|
506
|
+
" print(f\" RUNTIME GATE FAILED: {type(e).__name__}\")\n",
|
|
507
|
+
" traceback.print_exc()\n"
|
|
508
|
+
]
|
|
509
|
+
},
|
|
510
|
+
{
|
|
511
|
+
"cell_type": "markdown",
|
|
512
|
+
"id": "",
|
|
513
|
+
"metadata": {},
|
|
514
|
+
"source": [
|
|
515
|
+
"---\n",
|
|
516
|
+
"## Section 9 — Comparing Normalizers: Rule-Based vs LLM\n",
|
|
517
|
+
"\n",
|
|
518
|
+
"Same intent, two backends — side-by-side comparison.\n"
|
|
519
|
+
]
|
|
520
|
+
},
|
|
521
|
+
{
|
|
522
|
+
"cell_type": "code",
|
|
523
|
+
"id": "",
|
|
524
|
+
"metadata": {},
|
|
525
|
+
"outputs": [],
|
|
526
|
+
"source": [
|
|
527
|
+
"print(\"=\" * 55)\n",
|
|
528
|
+
"print(\"NORMALIZER COMPARISON: Rule-Based vs LLM\")\n",
|
|
529
|
+
"print(\"=\" * 55)\n",
|
|
530
|
+
"\n",
|
|
531
|
+
"rule_norm = IntentNormalizer(backend=RuleBasedNormalizerBackend())\n",
|
|
532
|
+
"llm_norm = None\n",
|
|
533
|
+
"if HAS_LLM:\n",
|
|
534
|
+
" provider = make_provider()\n",
|
|
535
|
+
" llm_norm = IntentNormalizer(backend=LLMNormalizerBackend(provider=provider, strict=True))\n",
|
|
536
|
+
"\n",
|
|
537
|
+
"header = f\"{'Intent':<50s} | {'Method':<12s} | {'Domain':<10s} | {'Layer':<8s} | {'Confidence':>10s}\"\n",
|
|
538
|
+
"print(header)\n",
|
|
539
|
+
"print(\"-\" * len(header))\n",
|
|
540
|
+
"\n",
|
|
541
|
+
"for raw in [\n",
|
|
542
|
+
" \"Join NFe with Clientes anonymize CPF and persist to Silver\",\n",
|
|
543
|
+
" \"Aggregate vendas by region persist to Gold\",\n",
|
|
544
|
+
" \"Export raw clientes PII to Gold\",\n",
|
|
545
|
+
"]:\n",
|
|
546
|
+
" # Rule-based\n",
|
|
547
|
+
" rb = rule_norm.normalize(raw, {}, CATALOG)\n",
|
|
548
|
+
" sig_rb = rb.signature\n",
|
|
549
|
+
" print(f\"{raw[:47]:<50s} | {'rule-based':<12s} | {sig_rb.domain:<10s} | {sig_rb.target_layer:<8s} | {rb.confidence_score:>9.2f}\")\n",
|
|
550
|
+
" # LLM\n",
|
|
551
|
+
" if llm_norm is not None:\n",
|
|
552
|
+
" try:\n",
|
|
553
|
+
" llm = llm_norm.normalize(raw, {}, CATALOG)\n",
|
|
554
|
+
" sig_llm = llm.signature\n",
|
|
555
|
+
" print(f\"{'':50s} | {'LLM':<12s} | {sig_llm.domain:<10s} | {sig_llm.target_layer:<8s} | {llm.confidence_score:>9.2f}\")\n",
|
|
556
|
+
" except Exception as e:\n",
|
|
557
|
+
" print(f\"{'':50s} | {'LLM':<12s} | ERROR: {type(e).__name__}\")\n",
|
|
558
|
+
" else:\n",
|
|
559
|
+
" print(f\"{'':50s} | {'LLM':<12s} | (no API key)\")\n",
|
|
560
|
+
" print()\n",
|
|
561
|
+
"\n",
|
|
562
|
+
"print(\"Normalizer comparison complete\")\n"
|
|
563
|
+
]
|
|
564
|
+
},
|
|
565
|
+
{
|
|
566
|
+
"cell_type": "markdown",
|
|
567
|
+
"id": "",
|
|
568
|
+
"metadata": {},
|
|
569
|
+
"source": [
|
|
570
|
+
"---\n",
|
|
571
|
+
"## Section 10 — PolicyEngine with LLM-Generated Rules\n",
|
|
572
|
+
"\n",
|
|
573
|
+
"Rules from `LLMSystematizer` (Section 6) feed `PolicyEngine`.\n",
|
|
574
|
+
"Closes the loop: NL governance → LLM → BehaviorSpec → PolicyRules → Engine.\n"
|
|
575
|
+
]
|
|
576
|
+
},
|
|
577
|
+
{
|
|
578
|
+
"cell_type": "code",
|
|
579
|
+
"id": "",
|
|
580
|
+
"metadata": {},
|
|
581
|
+
"outputs": [],
|
|
582
|
+
"source": [
|
|
583
|
+
"from cfa.types import DatasetRef, SignatureConstraints, TargetLayer, ExecutionContext\n",
|
|
584
|
+
"\n",
|
|
585
|
+
"print(\"=\" * 55)\n",
|
|
586
|
+
"print(\"POLICY ENGINE WITH LLM-GENERATED RULES\")\n",
|
|
587
|
+
"print(\"=\" * 55)\n",
|
|
588
|
+
"\n",
|
|
589
|
+
"if rules is None:\n",
|
|
590
|
+
" print(\"SKIP: rules not available (LLM Systematizer requires API key)\")\n",
|
|
591
|
+
" print(\" Using default policy rules instead.\")\n",
|
|
592
|
+
" engine = PolicyEngine() # default rules\n",
|
|
593
|
+
"else:\n",
|
|
594
|
+
" print(f\" Using {len(rules)} LLM-generated rules from Section 6\")\n",
|
|
595
|
+
" engine = PolicyEngine(rules=rules)\n",
|
|
596
|
+
"\n",
|
|
597
|
+
"# --- Safe signature ---\n",
|
|
598
|
+
"sig_safe = StateSignature(\n",
|
|
599
|
+
" domain=\"fiscal\",\n",
|
|
600
|
+
" intent=\"Join NFe with Clientes anonymize CPF persist to Silver\",\n",
|
|
601
|
+
" source_intent_raw=\"Join NFe with Clientes anonymize CPF persist to Silver\",\n",
|
|
602
|
+
" target_layer=TargetLayer.SILVER,\n",
|
|
603
|
+
" datasets=(\n",
|
|
604
|
+
" DatasetRef(name=\"nfe_bronze\"),\n",
|
|
605
|
+
" DatasetRef(name=\"clientes_bronze\", pii_columns=(\"cpf\", \"nome\")),\n",
|
|
606
|
+
" ),\n",
|
|
607
|
+
" constraints=SignatureConstraints(\n",
|
|
608
|
+
" no_pii_raw=True,\n",
|
|
609
|
+
" merge_key_required=True,\n",
|
|
610
|
+
" partition_by=(\"processing_date\",),\n",
|
|
611
|
+
" ),\n",
|
|
612
|
+
" execution_context=ExecutionContext(\n",
|
|
613
|
+
" policy_bundle_version=\"v1.0\",\n",
|
|
614
|
+
" catalog_snapshot_version=\"catalog_default\",\n",
|
|
615
|
+
" context_registry_version_id=\"ctx-default\",\n",
|
|
616
|
+
" ),\n",
|
|
617
|
+
")\n",
|
|
618
|
+
"\n",
|
|
619
|
+
"r = engine.evaluate(sig_safe)\n",
|
|
620
|
+
"print(f\"\\n Safe signature -> {r.action.value.upper()} faults={len(r.faults)}\")\n",
|
|
621
|
+
"\n",
|
|
622
|
+
"# --- Unsafe signature ---\n",
|
|
623
|
+
"sig_unsafe = StateSignature(\n",
|
|
624
|
+
" domain=\"fiscal\",\n",
|
|
625
|
+
" intent=\"Export raw clientes PII to Gold\",\n",
|
|
626
|
+
" source_intent_raw=\"Export raw clientes PII to Gold\",\n",
|
|
627
|
+
" target_layer=TargetLayer.GOLD,\n",
|
|
628
|
+
" datasets=(\n",
|
|
629
|
+
" DatasetRef(name=\"clientes_bronze\", pii_columns=(\"cpf\", \"nome\", \"endereco\")),\n",
|
|
630
|
+
" ),\n",
|
|
631
|
+
" constraints=SignatureConstraints(\n",
|
|
632
|
+
" no_pii_raw=False,\n",
|
|
633
|
+
" merge_key_required=False,\n",
|
|
634
|
+
" partition_by=(),\n",
|
|
635
|
+
" ),\n",
|
|
636
|
+
" execution_context=ExecutionContext(\n",
|
|
637
|
+
" policy_bundle_version=\"v1.0\",\n",
|
|
638
|
+
" catalog_snapshot_version=\"catalog_default\",\n",
|
|
639
|
+
" context_registry_version_id=\"ctx-default\",\n",
|
|
640
|
+
" ),\n",
|
|
641
|
+
")\n",
|
|
642
|
+
"\n",
|
|
643
|
+
"r2 = engine.evaluate(sig_unsafe)\n",
|
|
644
|
+
"print(f\" Unsafe signature -> {r2.action.value.upper()} faults={len(r2.faults)}\")\n",
|
|
645
|
+
"for fault in r2.faults[:4]:\n",
|
|
646
|
+
" print(f\" [{fault.severity.value.upper():<10s}] {fault.code}\")\n",
|
|
647
|
+
"\n",
|
|
648
|
+
"print(\"\\nLLM-rules PolicyEngine complete\")\n"
|
|
649
|
+
]
|
|
650
|
+
},
|
|
651
|
+
{
|
|
652
|
+
"cell_type": "markdown",
|
|
653
|
+
"id": "",
|
|
654
|
+
"metadata": {},
|
|
655
|
+
"source": [
|
|
656
|
+
"---\n",
|
|
657
|
+
"## Summary\n",
|
|
658
|
+
"\n",
|
|
659
|
+
"| LLM Feature | Status | Notes |\n",
|
|
660
|
+
"|---|---|---|\n",
|
|
661
|
+
"| LLM Normalizer | \\\\u2713 | Semantic intent resolution via DeepSeek |\n",
|
|
662
|
+
"| Strict Mode | \\\\u2713 | LLM output validated against catalog |\n",
|
|
663
|
+
"| LLM Audit Trail | \\\\u2713 | Every call SHA-256 traceable |\n",
|
|
664
|
+
"| LLM Systematizer | \\\\u2713 | NL → BehaviorSpec → PolicyRules |\n",
|
|
665
|
+
"| Full Kernel + LLM | \\\\u2713 | End-to-end with LLM normalizer |\n",
|
|
666
|
+
"| Runtime Gate | \\\\u2713 | Guard with LLM-generated policy rules |\n",
|
|
667
|
+
"| Normalizer Comparison | \\\\u2713 | Rule-based vs LLM side-by-side |\n",
|
|
668
|
+
"| Secret Management | \\\\u2713 | Databricks Secret Scope `cfa-secrets` |\n",
|
|
669
|
+
"\n",
|
|
670
|
+
"**Key differences from rule-based:**\n",
|
|
671
|
+
"\n",
|
|
672
|
+
"- LLM understands intent **semantics**, not just keywords\n",
|
|
673
|
+
"- Natural language governance descriptions → executable rules\n",
|
|
674
|
+
"- Every LLM call is audited (prompt/response/catalog SHA-256)\n",
|
|
675
|
+
"- Strict mode prevents hallucinations by validating against catalog\n",
|
|
676
|
+
"- API key stored in **Databricks Secret Scope** — never in code\n",
|
|
677
|
+
"\n",
|
|
678
|
+
"**Secret scope setup (one-time):**\n",
|
|
679
|
+
"```bash\n",
|
|
680
|
+
"databricks secrets create-scope cfa-secrets\n",
|
|
681
|
+
"databricks secrets put-secret cfa-secrets deepseek-key\n",
|
|
682
|
+
"```\n",
|
|
683
|
+
"\n",
|
|
684
|
+
"---\n",
|
|
685
|
+
"\n",
|
|
686
|
+
"**Links**\n",
|
|
687
|
+
"- [Documentation](https://marquesantero.github.io/cfa/docs/intro)\n",
|
|
688
|
+
"- [PyPI](https://pypi.org/project/cfa-kernel/)\n",
|
|
689
|
+
"- [GitHub](https://github.com/marquesantero/cfa)\n"
|
|
690
|
+
]
|
|
691
|
+
}
|
|
692
|
+
],
|
|
693
|
+
"metadata": {
|
|
694
|
+
"kernelspec": {
|
|
695
|
+
"display_name": "Python 3",
|
|
696
|
+
"language": "python",
|
|
697
|
+
"name": "python3"
|
|
698
|
+
},
|
|
699
|
+
"language_info": {
|
|
700
|
+
"name": "python",
|
|
701
|
+
"version": "3.11.0"
|
|
702
|
+
}
|
|
703
|
+
},
|
|
704
|
+
"nbformat": 4,
|
|
705
|
+
"nbformat_minor": 5
|
|
706
|
+
}
|