sengol 0.8.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.
- sengol-0.8.0/.claude/skills/pr-review/SKILL.md +60 -0
- sengol-0.8.0/.cursorrules +134 -0
- sengol-0.8.0/.dockerignore +16 -0
- sengol-0.8.0/.github/copilot-instructions.md +92 -0
- sengol-0.8.0/.github/workflows/ci.yml +84 -0
- sengol-0.8.0/.github/workflows/deploy.yml +86 -0
- sengol-0.8.0/.github/workflows/integration.yml +70 -0
- sengol-0.8.0/.github/workflows/publish.yml +41 -0
- sengol-0.8.0/.gitignore +48 -0
- sengol-0.8.0/.mcp.json +30 -0
- sengol-0.8.0/CHANGELOG.md +277 -0
- sengol-0.8.0/CLAUDE.md +214 -0
- sengol-0.8.0/Dockerfile +40 -0
- sengol-0.8.0/LICENSE +201 -0
- sengol-0.8.0/PKG-INFO +80 -0
- sengol-0.8.0/README.md +2 -0
- sengol-0.8.0/alembic/env.py +104 -0
- sengol-0.8.0/alembic/script.py.mako +26 -0
- sengol-0.8.0/alembic/versions/0001_create_audit_records.py +46 -0
- sengol-0.8.0/alembic/versions/0002_audit_records_controlbook_columns.py +50 -0
- sengol-0.8.0/alembic/versions/0003_create_gold_score_records.py +75 -0
- sengol-0.8.0/alembic/versions/0004_create_saturation_events.py +74 -0
- sengol-0.8.0/alembic/versions/0005_create_evaluation_runs.py +111 -0
- sengol-0.8.0/alembic/versions/0006_hash_chain_idempotency_schema_versioning.py +120 -0
- sengol-0.8.0/alembic/versions/0007_auth_keyring.py +134 -0
- sengol-0.8.0/alembic/versions/0008_signing_keys_active_unique.py +39 -0
- sengol-0.8.0/alembic/versions/0009_agent_inherent_risk_tier.py +38 -0
- sengol-0.8.0/alembic/versions/0010_certification_records.py +73 -0
- sengol-0.8.0/alembic/versions/0011_human_review_items.py +61 -0
- sengol-0.8.0/alembic/versions/0012_certification_tenant_id.py +56 -0
- sengol-0.8.0/alembic/versions/0013_control_books.py +58 -0
- sengol-0.8.0/alembic/versions/0014_audit_record_span_id.py +32 -0
- sengol-0.8.0/alembic/versions/0015_human_review_requested_action.py +32 -0
- sengol-0.8.0/alembic/versions/0016_evidence_countersignatures_anchor_receipts.py +84 -0
- sengol-0.8.0/alembic/versions/0017_anchor_receipts_unique_seq_high.py +39 -0
- sengol-0.8.0/alembic/versions/0018_add_signing_backend_field.py +52 -0
- sengol-0.8.0/alembic/versions/0019_widen_key_id_for_kms_arn.py +53 -0
- sengol-0.8.0/alembic/versions/0020_add_console_access_log_table.py +64 -0
- sengol-0.8.0/alembic/versions/0021_add_users_and_api_tokens_tables.py +59 -0
- sengol-0.8.0/alembic/versions/0022_add_api_token_issuance_log_table.py +55 -0
- sengol-0.8.0/alembic/versions/0023_add_github_workflow_audit_log_table.py +63 -0
- sengol-0.8.0/alembic/versions/0024_add_reports_table.py +73 -0
- sengol-0.8.0/alembic/versions/0025_add_authority_model_version_to_audit_records.py +33 -0
- sengol-0.8.0/alembic/versions/0026_add_labels_to_agent_registrations.py +29 -0
- sengol-0.8.0/alembic/versions/0027_add_tenant_id_to_human_review_items.py +44 -0
- sengol-0.8.0/alembic/versions/0028_agent_declared_capabilities.py +40 -0
- sengol-0.8.0/alembic/versions/0029_agent_call_delegation_data.py +25 -0
- sengol-0.8.0/alembic.ini +38 -0
- sengol-0.8.0/console/index.html +12 -0
- sengol-0.8.0/console/package-lock.json +4445 -0
- sengol-0.8.0/console/package.json +32 -0
- sengol-0.8.0/console/src/App.tsx +28 -0
- sengol-0.8.0/console/src/components/DriftBadge.test.tsx +33 -0
- sengol-0.8.0/console/src/components/DriftBadge.tsx +46 -0
- sengol-0.8.0/console/src/components/GoldScoreGauge.tsx +33 -0
- sengol-0.8.0/console/src/components/LiveTrajectory.tsx +38 -0
- sengol-0.8.0/console/src/components/PassRateChart.test.tsx +25 -0
- sengol-0.8.0/console/src/components/PassRateChart.tsx +50 -0
- sengol-0.8.0/console/src/components/QuarterTrend.tsx +23 -0
- sengol-0.8.0/console/src/components/badges.test.tsx +28 -0
- sengol-0.8.0/console/src/components/badges.tsx +40 -0
- sengol-0.8.0/console/src/index.css +8 -0
- sengol-0.8.0/console/src/lib/apiClient.test.ts +43 -0
- sengol-0.8.0/console/src/lib/apiClient.ts +129 -0
- sengol-0.8.0/console/src/lib/sse.test.ts +33 -0
- sengol-0.8.0/console/src/lib/sse.ts +111 -0
- sengol-0.8.0/console/src/lib/types.ts +236 -0
- sengol-0.8.0/console/src/live/LiveContext.test.tsx +36 -0
- sengol-0.8.0/console/src/live/LiveContext.tsx +103 -0
- sengol-0.8.0/console/src/main.tsx +20 -0
- sengol-0.8.0/console/src/pages/agents/AgentsPage.test.tsx +57 -0
- sengol-0.8.0/console/src/pages/agents/AgentsPage.tsx +85 -0
- sengol-0.8.0/console/src/pages/agents/AlertTimeline.tsx +57 -0
- sengol-0.8.0/console/src/pages/agents/hooks.ts +18 -0
- sengol-0.8.0/console/src/pages/governance/GovernancePage.tsx +430 -0
- sengol-0.8.0/console/src/pages/governance/hooks.ts +10 -0
- sengol-0.8.0/console/src/pages/overview/OverviewPage.test.tsx +45 -0
- sengol-0.8.0/console/src/pages/overview/OverviewPage.tsx +83 -0
- sengol-0.8.0/console/src/pages/overview/hooks.ts +10 -0
- sengol-0.8.0/console/src/pages/reports/ReportsPage.test.tsx +46 -0
- sengol-0.8.0/console/src/pages/reports/ReportsPage.tsx +113 -0
- sengol-0.8.0/console/src/pages/reports/hooks.ts +25 -0
- sengol-0.8.0/console/src/pages/review/DecisionPanel.test.tsx +32 -0
- sengol-0.8.0/console/src/pages/review/DecisionPanel.tsx +60 -0
- sengol-0.8.0/console/src/pages/review/HumanReviewPage.test.tsx +12 -0
- sengol-0.8.0/console/src/pages/review/HumanReviewPage.tsx +14 -0
- sengol-0.8.0/console/src/pages/review/ReviewCard.test.tsx +27 -0
- sengol-0.8.0/console/src/pages/review/ReviewCard.tsx +51 -0
- sengol-0.8.0/console/src/pages/review/ReviewQueue.test.tsx +35 -0
- sengol-0.8.0/console/src/pages/review/ReviewQueue.tsx +78 -0
- sengol-0.8.0/console/src/pages/review/hooks.test.tsx +24 -0
- sengol-0.8.0/console/src/pages/review/hooks.ts +40 -0
- sengol-0.8.0/console/src/pages/settings/SettingsPage.test.tsx +40 -0
- sengol-0.8.0/console/src/pages/settings/SettingsPage.tsx +126 -0
- sengol-0.8.0/console/src/pages/settings/hooks.ts +34 -0
- sengol-0.8.0/console/src/pages/traces/CallGraph.tsx +74 -0
- sengol-0.8.0/console/src/pages/traces/TraceDetail.tsx +46 -0
- sengol-0.8.0/console/src/pages/traces/TracesPage.test.tsx +39 -0
- sengol-0.8.0/console/src/pages/traces/TracesPage.tsx +167 -0
- sengol-0.8.0/console/src/pages/traces/hooks.ts +26 -0
- sengol-0.8.0/console/src/shell/AlertFeed.test.tsx +29 -0
- sengol-0.8.0/console/src/shell/AlertFeed.tsx +65 -0
- sengol-0.8.0/console/src/shell/AppShell.test.tsx +40 -0
- sengol-0.8.0/console/src/shell/AppShell.tsx +69 -0
- sengol-0.8.0/console/src/test/fakeSse.tsx +16 -0
- sengol-0.8.0/console/src/test/harness.test.tsx +9 -0
- sengol-0.8.0/console/src/test/server.ts +100 -0
- sengol-0.8.0/console/src/test/setup.ts +19 -0
- sengol-0.8.0/console/src/test/utils.tsx +13 -0
- sengol-0.8.0/console/tsconfig.json +18 -0
- sengol-0.8.0/console/tsconfig.test.json +7 -0
- sengol-0.8.0/console/vite.config.ts +22 -0
- sengol-0.8.0/docker-compose.yml +67 -0
- sengol-0.8.0/docs/decisions/DEFERRED-DECISIONS.md +22 -0
- sengol-0.8.0/docs/decisions/README.md +220 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0001-policyid-open-str.md +54 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0002-evalscore-binary-passed.md +60 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0003-deterministic-first-execution.md +90 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0004-controlbook-drives-reports.md +72 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0005-feature-gate-file.md +92 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0006-auditrecord-hmac-payload-scope.md +79 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0007-evaluator-registry-classmethod.md +74 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0008-audit-store-append-only.md +76 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0009-policy-catalog-yaml-extensibility.md +82 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0010-controlbook-validate-warn-on-unknown.md +71 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0011-synthetic-no-llm-no-pii.md +84 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0012-catalog-schema-version.md +54 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0013-evalsuite-exception-coercion.md +84 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0014-llmjudge-as-protocol.md +57 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0015-policies-field-rename.md +53 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0016-saturation-detector.md +69 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0017-pure-asgi-stub.md +64 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0018-tests-suite-package-collision.md +45 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0019-policy-agnostic-pdf-via-catalog.md +69 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0020-reportmetadata-fallback-chain.md +65 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0021-plain-language-evaluator-map.md +70 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0022-word-boundary-policy-matching.md +80 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0023-hmac-verify-records-before-report.md +63 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0024-policy-overlap-filter.md +56 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0025-compliance-report-hmac-scope.md +68 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0026-obligation-strictness.md +77 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0027-no-records-observed-failure-mode.md +72 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0028-goldscore-minimum-floor-snap.md +80 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0029-guardrailpolicy-no-evaluators-field.md +71 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0030-pre-failure-degrades-to-block-under-retry.md +69 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0031-promotiongate-toughest-obligation-wins.md +80 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0032-synthetic-guardrail-outcome-score.md +82 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0033-tpr-tnr-only-never-accuracy.md +59 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0034-memory-audit-uri-scheme.md +66 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0035-commit-body-must-match-file-list.md +74 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0036-phase2d-session1-core-types.md +94 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0037-phase2d-session2-new-stores.md +129 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0038-phase2d-session3-pii-disclosure-evaluators.md +104 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0039-phase2d-session4-structlog-integration-tests.md +88 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0040-phase2d-session5-action-outputs.md +54 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0041-plain-language-cli-flag.md +61 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0042-obligation-result-count-fields.md +85 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0043-no-agent-activity-sub-mode.md +78 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0044-guardrail-constant-move.md +63 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0046-llm-judge-client-architecture.md +63 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0047-evaluator-wiring.md +67 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0048-obligation-result-hmac-update.md +57 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0049-no-agent-activity-gha-annotation-strategy.md +61 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0050-phase3-tech-debt-resolution.md +63 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0051-model-category-mismatch.md +60 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0052-cli-to-api-boundary.md +352 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0053-workload-taxonomy.md +251 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0054-hash-chain.md +270 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0055-idempotency.md +226 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0056-workload-identity.md +262 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0057-schema-versioning.md +260 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0058-key-rotation.md +295 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0059-basic-otlp-span-export.md +113 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0060-agent-risk-taxonomy.md +101 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0061-certification-lifecycle.md +73 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0062-raw-trace-store.md +72 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0063-trace-capture-and-sampling.md +67 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0064-tracemine-dual-store-join.md +51 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0065-human-review-queue.md +61 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0066-certification-tenant-binding.md +60 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0067-controlbook-store-and-console-write-scopes.md +51 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0068-exporter-plugin-system.md +73 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0069-online-trace-sink-plugin-system.md +103 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0070-drift-evidence-policy.md +120 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0071-otel-genai-alignment.md +70 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0072-verifiable-evidence-anchoring.md +82 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0073-obligation-coverage-gate.md +71 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0074-kms-signing-backend.md +54 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0075-console-oidc-sso.md +56 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0076-local-user-self-service.md +64 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0077-federated-workload-identity.md +66 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0078-gdpr-pipeda-right-to-erasure.md +58 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0079-governance-authority-model-v1.md +61 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0080-compiled-regulation-stateless-yaml-view.md +74 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0081-cross-framework-taxonomy-ir.md +33 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0082-pluggable-red-team-backend.md +41 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0083-delegation-chain-evidence.md +39 -0
- sengol-0.8.0/docs/decisions/adr/ADR-0084-client-auto-intercept-guardrails.md +129 -0
- sengol-0.8.0/docs/decisions/adr/INDEX.md +88 -0
- sengol-0.8.0/docs/decisions/design/PHASE-1-sdk-core.md +143 -0
- sengol-0.8.0/docs/decisions/design/PHASE-2-cro-demo.md +209 -0
- sengol-0.8.0/docs/decisions/future/PHASE-1-future-needs.md +180 -0
- sengol-0.8.0/docs/decisions/future/PHASE-2-future-needs.md +256 -0
- sengol-0.8.0/docs/decisions/gaps/PHASE-1-gaps.md +211 -0
- sengol-0.8.0/docs/decisions/gaps/PHASE-2-gaps.md +114 -0
- sengol-0.8.0/docs/reference/architecture.md +309 -0
- sengol-0.8.0/docs/reference/cli.md +67 -0
- sengol-0.8.0/docs/reference/console.md +134 -0
- sengol-0.8.0/docs/reference/env.md +153 -0
- sengol-0.8.0/docs/reference/redteam-configuration.md +201 -0
- sengol-0.8.0/docs/reference/redteam-ops-checklist.md +187 -0
- sengol-0.8.0/docs/reference/regulations.md +197 -0
- sengol-0.8.0/docs/reference/reports.md +89 -0
- sengol-0.8.0/docs/reference/sinks.md +182 -0
- sengol-0.8.0/docs/superpowers/plans/2026-06-05-console-5f-reports-settings.md +1453 -0
- sengol-0.8.0/docs/superpowers/plans/2026-06-10-console-v2-live-drift.md +1571 -0
- sengol-0.8.0/docs/tech-debt/TECH-DEBT-REGISTER.md +19 -0
- sengol-0.8.0/examples/acme_controlbook.yaml +70 -0
- sengol-0.8.0/examples/demo_adapters_and_exporters.py +184 -0
- sengol-0.8.0/examples/demo_end_to_end.py +248 -0
- sengol-0.8.0/examples/demo_otlp_traces.py +80 -0
- sengol-0.8.0/examples/osfi_e23_controlbook.yaml +175 -0
- sengol-0.8.0/examples/sample_traces.jsonl +12 -0
- sengol-0.8.0/examples/sengol.yaml +40 -0
- sengol-0.8.0/examples/synthetic_osfi_config.yaml +29 -0
- sengol-0.8.0/examples/us_treasury_controlbook.yaml +198 -0
- sengol-0.8.0/helm/sengol/Chart.yaml +16 -0
- sengol-0.8.0/helm/sengol/README.md +102 -0
- sengol-0.8.0/helm/sengol/templates/_helpers.tpl +38 -0
- sengol-0.8.0/helm/sengol/templates/configmap.yaml +10 -0
- sengol-0.8.0/helm/sengol/templates/deployment.yaml +53 -0
- sengol-0.8.0/helm/sengol/templates/hpa.yaml +22 -0
- sengol-0.8.0/helm/sengol/templates/ingress.yaml +31 -0
- sengol-0.8.0/helm/sengol/templates/secret.yaml +13 -0
- sengol-0.8.0/helm/sengol/templates/service.yaml +15 -0
- sengol-0.8.0/helm/sengol/values-aws.yaml +32 -0
- sengol-0.8.0/helm/sengol/values.yaml +67 -0
- sengol-0.8.0/pyproject.toml +123 -0
- sengol-0.8.0/sengol/__init__.py +44 -0
- sengol-0.8.0/sengol/adapters/__init__.py +38 -0
- sengol-0.8.0/sengol/adapters/base.py +125 -0
- sengol-0.8.0/sengol/adapters/jsonl.py +139 -0
- sengol-0.8.0/sengol/adapters/mlflow.py +229 -0
- sengol-0.8.0/sengol/adapters/registry.py +174 -0
- sengol-0.8.0/sengol/analysis/__init__.py +27 -0
- sengol-0.8.0/sengol/analysis/sampler.py +154 -0
- sengol-0.8.0/sengol/analysis/trace_analyzer.py +373 -0
- sengol-0.8.0/sengol/analysis/transition_matrix.py +234 -0
- sengol-0.8.0/sengol/api/CLAUDE.md +17 -0
- sengol-0.8.0/sengol/api/__init__.py +25 -0
- sengol-0.8.0/sengol/api/agent_call_builder.py +160 -0
- sengol-0.8.0/sengol/api/anchor.py +315 -0
- sengol-0.8.0/sengol/api/app.py +1322 -0
- sengol-0.8.0/sengol/api/auth_oidc.py +335 -0
- sengol-0.8.0/sengol/api/countersign.py +148 -0
- sengol-0.8.0/sengol/api/drift_events.py +97 -0
- sengol-0.8.0/sengol/api/dynamodb_audit_store.py +628 -0
- sengol-0.8.0/sengol/api/eval_run_sink.py +174 -0
- sengol-0.8.0/sengol/api/gold_score_sink.py +138 -0
- sengol-0.8.0/sengol/api/middleware/__init__.py +0 -0
- sengol-0.8.0/sengol/api/middleware/auth.py +227 -0
- sengol-0.8.0/sengol/api/middleware/rate_limit.py +208 -0
- sengol-0.8.0/sengol/api/openapi.yaml +4390 -0
- sengol-0.8.0/sengol/api/otlp_ingest.py +360 -0
- sengol-0.8.0/sengol/api/postgres_audit_store.py +532 -0
- sengol-0.8.0/sengol/api/postgres_certification_store.py +260 -0
- sengol-0.8.0/sengol/api/postgres_controlbook_store.py +117 -0
- sengol-0.8.0/sengol/api/postgres_eval_run_store.py +250 -0
- sengol-0.8.0/sengol/api/postgres_evidence_store.py +279 -0
- sengol-0.8.0/sengol/api/postgres_gold_score_store.py +250 -0
- sengol-0.8.0/sengol/api/postgres_human_review_store.py +213 -0
- sengol-0.8.0/sengol/api/postgres_report_store.py +224 -0
- sengol-0.8.0/sengol/api/postgres_saturation_store.py +240 -0
- sengol-0.8.0/sengol/api/s3_audit_store.py +465 -0
- sengol-0.8.0/sengol/api/saturation_sink.py +129 -0
- sengol-0.8.0/sengol/api/signing_kms.py +203 -0
- sengol-0.8.0/sengol/api/sink.py +598 -0
- sengol-0.8.0/sengol/api/sse_broker.py +74 -0
- sengol-0.8.0/sengol/api/v1/__init__.py +0 -0
- sengol-0.8.0/sengol/api/v1/agents.py +182 -0
- sengol-0.8.0/sengol/api/v1/audit.py +124 -0
- sengol-0.8.0/sengol/api/v1/auth.py +431 -0
- sengol-0.8.0/sengol/api/v1/console.py +826 -0
- sengol-0.8.0/sengol/api/v1/console_audit.py +253 -0
- sengol-0.8.0/sengol/api/v1/controlbook.py +82 -0
- sengol-0.8.0/sengol/api/v1/github_oidc.py +186 -0
- sengol-0.8.0/sengol/api/v1/keys.py +401 -0
- sengol-0.8.0/sengol/api/v1/lifecycle.py +200 -0
- sengol-0.8.0/sengol/api/v1/regulations.py +211 -0
- sengol-0.8.0/sengol/api/v1/reports.py +242 -0
- sengol-0.8.0/sengol/api/v1/review.py +201 -0
- sengol-0.8.0/sengol/api/v1/token_issuance_log.py +129 -0
- sengol-0.8.0/sengol/api/v1/users.py +581 -0
- sengol-0.8.0/sengol/build/__init__.py +15 -0
- sengol-0.8.0/sengol/build/gate.py +256 -0
- sengol-0.8.0/sengol/build/regression.py +129 -0
- sengol-0.8.0/sengol/build/suite.py +617 -0
- sengol-0.8.0/sengol/capture/__init__.py +26 -0
- sengol-0.8.0/sengol/capture/config.py +166 -0
- sengol-0.8.0/sengol/capture/redaction.py +44 -0
- sengol-0.8.0/sengol/capture/store.py +174 -0
- sengol-0.8.0/sengol/capture/types.py +36 -0
- sengol-0.8.0/sengol/cicd/__init__.py +10 -0
- sengol-0.8.0/sengol/cicd/_render.py +273 -0
- sengol-0.8.0/sengol/cicd/azure_pipelines.py +321 -0
- sengol-0.8.0/sengol/cicd/github.py +525 -0
- sengol-0.8.0/sengol/cli/__init__.py +0 -0
- sengol-0.8.0/sengol/cli/main.py +3859 -0
- sengol-0.8.0/sengol/core/__init__.py +7 -0
- sengol-0.8.0/sengol/core/drift.py +148 -0
- sengol-0.8.0/sengol/core/evaluator.py +106 -0
- sengol-0.8.0/sengol/core/judge.py +71 -0
- sengol-0.8.0/sengol/core/judge_validation.py +196 -0
- sengol-0.8.0/sengol/core/keyring.py +60 -0
- sengol-0.8.0/sengol/core/merkle.py +43 -0
- sengol-0.8.0/sengol/core/payload_registry.py +322 -0
- sengol-0.8.0/sengol/core/registry.py +231 -0
- sengol-0.8.0/sengol/core/severity.py +33 -0
- sengol-0.8.0/sengol/core/signing.py +89 -0
- sengol-0.8.0/sengol/core/types.py +840 -0
- sengol-0.8.0/sengol/dataset/__init__.py +10 -0
- sengol-0.8.0/sengol/dataset/_hash.py +96 -0
- sengol-0.8.0/sengol/dataset/loader.py +258 -0
- sengol-0.8.0/sengol/dataset/registry.py +277 -0
- sengol-0.8.0/sengol/evaluators/CLAUDE.md +17 -0
- sengol-0.8.0/sengol/evaluators/__init__.py +151 -0
- sengol-0.8.0/sengol/evaluators/deterministic/__init__.py +33 -0
- sengol-0.8.0/sengol/evaluators/deterministic/disclosure.py +148 -0
- sengol-0.8.0/sengol/evaluators/deterministic/drift_monitor.py +60 -0
- sengol-0.8.0/sengol/evaluators/deterministic/exact_match.py +68 -0
- sengol-0.8.0/sengol/evaluators/deterministic/keyword.py +103 -0
- sengol-0.8.0/sengol/evaluators/deterministic/pii.py +180 -0
- sengol-0.8.0/sengol/evaluators/deterministic/regex.py +66 -0
- sengol-0.8.0/sengol/evaluators/deterministic/response_length.py +78 -0
- sengol-0.8.0/sengol/evaluators/deterministic/schema_validation.py +82 -0
- sengol-0.8.0/sengol/evaluators/deterministic/trajectory.py +244 -0
- sengol-0.8.0/sengol/evaluators/deterministic/unauthorized_delegation.py +68 -0
- sengol-0.8.0/sengol/evaluators/ensemble.py +243 -0
- sengol-0.8.0/sengol/evaluators/llm/__init__.py +37 -0
- sengol-0.8.0/sengol/evaluators/llm/adversarial_robustness.py +112 -0
- sengol-0.8.0/sengol/evaluators/llm/explainability.py +127 -0
- sengol-0.8.0/sengol/evaluators/llm/faithfulness.py +83 -0
- sengol-0.8.0/sengol/evaluators/llm/groundedness.py +178 -0
- sengol-0.8.0/sengol/evaluators/llm/hallucination.py +85 -0
- sengol-0.8.0/sengol/evaluators/llm/pii.py +72 -0
- sengol-0.8.0/sengol/evaluators/llm/refusal.py +125 -0
- sengol-0.8.0/sengol/evaluators/llm/relevance.py +137 -0
- sengol-0.8.0/sengol/evaluators/llm/toxicity.py +159 -0
- sengol-0.8.0/sengol/evaluators/llm/trajectory.py +295 -0
- sengol-0.8.0/sengol/evaluators/model/__init__.py +1 -0
- sengol-0.8.0/sengol/evaluators/model/ab_evaluator.py +208 -0
- sengol-0.8.0/sengol/evaluators/model/auc.py +146 -0
- sengol-0.8.0/sengol/evaluators/model/champion_challenger.py +154 -0
- sengol-0.8.0/sengol/evaluators/model/fairness.py +236 -0
- sengol-0.8.0/sengol/evaluators/model/outcome_monitor.py +166 -0
- sengol-0.8.0/sengol/evaluators/model/psi.py +175 -0
- sengol-0.8.0/sengol/evaluators/redteam/__init__.py +17 -0
- sengol-0.8.0/sengol/evaluators/redteam/base.py +155 -0
- sengol-0.8.0/sengol/evaluators/redteam/garak_backend.py +127 -0
- sengol-0.8.0/sengol/governance/CLAUDE.md +13 -0
- sengol-0.8.0/sengol/governance/__init__.py +0 -0
- sengol-0.8.0/sengol/governance/_license.py +86 -0
- sengol-0.8.0/sengol/governance/audit_store.py +329 -0
- sengol-0.8.0/sengol/governance/certification_store.py +111 -0
- sengol-0.8.0/sengol/governance/controlbook_store.py +56 -0
- sengol-0.8.0/sengol/governance/controlbook_validator.py +291 -0
- sengol-0.8.0/sengol/governance/drift_evidence.py +602 -0
- sengol-0.8.0/sengol/governance/eval_run_store.py +117 -0
- sengol-0.8.0/sengol/governance/evidence_store.py +150 -0
- sengol-0.8.0/sengol/governance/gold_score.py +207 -0
- sengol-0.8.0/sengol/governance/gold_score_store.py +171 -0
- sengol-0.8.0/sengol/governance/human_review_store.py +168 -0
- sengol-0.8.0/sengol/governance/offline_verify.py +407 -0
- sengol-0.8.0/sengol/governance/report_base.py +780 -0
- sengol-0.8.0/sengol/governance/report_enterprise.py +780 -0
- sengol-0.8.0/sengol/governance/report_store.py +173 -0
- sengol-0.8.0/sengol/governance/saturation_store.py +175 -0
- sengol-0.8.0/sengol/instrument/__init__.py +73 -0
- sengol-0.8.0/sengol/instrument/_runner.py +342 -0
- sengol-0.8.0/sengol/instrument/anthropic_patch.py +108 -0
- sengol-0.8.0/sengol/instrument/config.py +52 -0
- sengol-0.8.0/sengol/instrument/exceptions.py +16 -0
- sengol-0.8.0/sengol/instrument/extractor.py +113 -0
- sengol-0.8.0/sengol/instrument/openai_patch.py +103 -0
- sengol-0.8.0/sengol/instrument/registry.py +58 -0
- sengol-0.8.0/sengol/judges/__init__.py +22 -0
- sengol-0.8.0/sengol/judges/_base.py +147 -0
- sengol-0.8.0/sengol/judges/_exceptions.py +11 -0
- sengol-0.8.0/sengol/judges/_prompt.py +73 -0
- sengol-0.8.0/sengol/judges/anthropic.py +78 -0
- sengol-0.8.0/sengol/judges/openai_compatible.py +84 -0
- sengol-0.8.0/sengol/logging.py +76 -0
- sengol-0.8.0/sengol/observability/__init__.py +36 -0
- sengol-0.8.0/sengol/observability/config.py +156 -0
- sengol-0.8.0/sengol/observability/spans.py +128 -0
- sengol-0.8.0/sengol/observability/tracer.py +135 -0
- sengol-0.8.0/sengol/policies/__init__.py +27 -0
- sengol-0.8.0/sengol/policies/catalog.yaml +385 -0
- sengol-0.8.0/sengol/policies/compiled.py +177 -0
- sengol-0.8.0/sengol/policies/evaluator_routing.yaml +375 -0
- sengol-0.8.0/sengol/policies/evaluator_translations.yaml +14 -0
- sengol-0.8.0/sengol/policies/loader.py +358 -0
- sengol-0.8.0/sengol/policies/taxonomy.py +194 -0
- sengol-0.8.0/sengol/policies/taxonomy.yaml +105 -0
- sengol-0.8.0/sengol/policies/taxonomy_crosswalk.yaml +68 -0
- sengol-0.8.0/sengol/runtime/__init__.py +26 -0
- sengol-0.8.0/sengol/runtime/async_worker.py +216 -0
- sengol-0.8.0/sengol/runtime/drift.py +147 -0
- sengol-0.8.0/sengol/runtime/guardrails.py +695 -0
- sengol-0.8.0/sengol/runtime/inline_evaluator.py +129 -0
- sengol-0.8.0/sengol/runtime/sampling/__init__.py +6 -0
- sengol-0.8.0/sengol/runtime/sampling/clustering.py +168 -0
- sengol-0.8.0/sengol/runtime/sampling/feedback.py +22 -0
- sengol-0.8.0/sengol/runtime/sampling/random.py +41 -0
- sengol-0.8.0/sengol/runtime/sqs_eval_worker.py +292 -0
- sengol-0.8.0/sengol/runtime/webhook.py +108 -0
- sengol-0.8.0/sengol/sinks/__init__.py +48 -0
- sengol-0.8.0/sengol/sinks/base.py +121 -0
- sengol-0.8.0/sengol/sinks/dispatch.py +186 -0
- sengol-0.8.0/sengol/sinks/langfuse.py +171 -0
- sengol-0.8.0/sengol/sinks/otlp.py +277 -0
- sengol-0.8.0/sengol/sinks/registry.py +164 -0
- sengol-0.8.0/sengol/sinks/semconv.py +51 -0
- sengol-0.8.0/sengol/synthetic/__init__.py +26 -0
- sengol-0.8.0/sengol/synthetic/config.py +55 -0
- sengol-0.8.0/sengol/synthetic/generator.py +210 -0
- sengol-0.8.0/sengol/synthetic/trace_extractor.py +167 -0
- sengol-0.8.0/sengol/trajectory/__init__.py +24 -0
- sengol-0.8.0/sengol/trajectory/mapping.py +355 -0
- sengol-0.8.0/sengol/trajectory/types.py +42 -0
- sengol-0.8.0/sengol.yaml +65 -0
- sengol-0.8.0/terraform/aws/.gitignore +9 -0
- sengol-0.8.0/terraform/aws/environments/dev.tfvars +6 -0
- sengol-0.8.0/terraform/aws/environments/prod.tfvars +7 -0
- sengol-0.8.0/terraform/aws/environments/staging.tfvars +6 -0
- sengol-0.8.0/terraform/aws/main.tf +125 -0
- sengol-0.8.0/terraform/aws/modules/alb/main.tf +85 -0
- sengol-0.8.0/terraform/aws/modules/alb/outputs.tf +24 -0
- sengol-0.8.0/terraform/aws/modules/alb/variables.tf +26 -0
- sengol-0.8.0/terraform/aws/modules/ecr/main.tf +30 -0
- sengol-0.8.0/terraform/aws/modules/ecr/outputs.tf +9 -0
- sengol-0.8.0/terraform/aws/modules/ecr/variables.tf +15 -0
- sengol-0.8.0/terraform/aws/modules/ecs/main.tf +181 -0
- sengol-0.8.0/terraform/aws/modules/ecs/outputs.tf +24 -0
- sengol-0.8.0/terraform/aws/modules/ecs/variables.tf +109 -0
- sengol-0.8.0/terraform/aws/modules/kms/main.tf +57 -0
- sengol-0.8.0/terraform/aws/modules/kms/outputs.tf +14 -0
- sengol-0.8.0/terraform/aws/modules/kms/variables.tf +64 -0
- sengol-0.8.0/terraform/aws/modules/rds/main.tf +56 -0
- sengol-0.8.0/terraform/aws/modules/rds/outputs.tf +14 -0
- sengol-0.8.0/terraform/aws/modules/rds/variables.tf +52 -0
- sengol-0.8.0/terraform/aws/modules/s3_audit/main.tf +54 -0
- sengol-0.8.0/terraform/aws/modules/s3_audit/outputs.tf +9 -0
- sengol-0.8.0/terraform/aws/modules/s3_audit/variables.tf +35 -0
- sengol-0.8.0/terraform/aws/modules/sqs/main.tf +27 -0
- sengol-0.8.0/terraform/aws/modules/sqs/outputs.tf +19 -0
- sengol-0.8.0/terraform/aws/modules/sqs/variables.tf +27 -0
- sengol-0.8.0/terraform/aws/modules/vpc/main.tf +89 -0
- sengol-0.8.0/terraform/aws/modules/vpc/outputs.tf +19 -0
- sengol-0.8.0/terraform/aws/modules/vpc/variables.tf +21 -0
- sengol-0.8.0/terraform/aws/outputs.tf +46 -0
- sengol-0.8.0/terraform/aws/providers.tf +16 -0
- sengol-0.8.0/terraform/aws/variables.tf +113 -0
- sengol-0.8.0/terraform/aws/versions.tf +13 -0
- sengol-0.8.0/tests/CLAUDE.md +14 -0
- sengol-0.8.0/tests/__init__.py +0 -0
- sengol-0.8.0/tests/adapters/__init__.py +0 -0
- sengol-0.8.0/tests/adapters/test_jsonl.py +124 -0
- sengol-0.8.0/tests/adapters/test_mlflow.py +303 -0
- sengol-0.8.0/tests/adapters/test_registry.py +206 -0
- sengol-0.8.0/tests/analysis/__init__.py +0 -0
- sengol-0.8.0/tests/analysis/test_data_analysis_sampler.py +426 -0
- sengol-0.8.0/tests/analysis/test_trace_analyzer.py +222 -0
- sengol-0.8.0/tests/analysis/test_transition_matrix.py +304 -0
- sengol-0.8.0/tests/api/__init__.py +0 -0
- sengol-0.8.0/tests/api/conftest.py +42 -0
- sengol-0.8.0/tests/api/test_agents_list.py +65 -0
- sengol-0.8.0/tests/api/test_anchor_scheduler.py +228 -0
- sengol-0.8.0/tests/api/test_api_app.py +552 -0
- sengol-0.8.0/tests/api/test_api_sink.py +461 -0
- sengol-0.8.0/tests/api/test_app.py +46 -0
- sengol-0.8.0/tests/api/test_audit_severity.py +92 -0
- sengol-0.8.0/tests/api/test_auth_console_token.py +226 -0
- sengol-0.8.0/tests/api/test_auth_oidc.py +779 -0
- sengol-0.8.0/tests/api/test_certification_routes.py +164 -0
- sengol-0.8.0/tests/api/test_console_access_log.py +428 -0
- sengol-0.8.0/tests/api/test_console_auth_status.py +199 -0
- sengol-0.8.0/tests/api/test_console_reports.py +165 -0
- sengol-0.8.0/tests/api/test_console_routes.py +350 -0
- sengol-0.8.0/tests/api/test_console_static.py +67 -0
- sengol-0.8.0/tests/api/test_console_stream.py +317 -0
- sengol-0.8.0/tests/api/test_controlbook_upload.py +154 -0
- sengol-0.8.0/tests/api/test_countersign_dispatcher.py +157 -0
- sengol-0.8.0/tests/api/test_countersign_signer.py +94 -0
- sengol-0.8.0/tests/api/test_durable_spool.py +222 -0
- sengol-0.8.0/tests/api/test_dynamodb_audit_store.py +393 -0
- sengol-0.8.0/tests/api/test_eval_browse_route.py +86 -0
- sengol-0.8.0/tests/api/test_eval_run_routes.py +201 -0
- sengol-0.8.0/tests/api/test_github_oidc.py +354 -0
- sengol-0.8.0/tests/api/test_license_gate.py +133 -0
- sengol-0.8.0/tests/api/test_local_user_auth.py +679 -0
- sengol-0.8.0/tests/api/test_openapi_contract.py +198 -0
- sengol-0.8.0/tests/api/test_otlp_agent_call_ingest.py +175 -0
- sengol-0.8.0/tests/api/test_otlp_ingest.py +465 -0
- sengol-0.8.0/tests/api/test_postgres_audit_store.py +171 -0
- sengol-0.8.0/tests/api/test_postgres_gold_score_store.py +77 -0
- sengol-0.8.0/tests/api/test_postgres_report_store.py +240 -0
- sengol-0.8.0/tests/api/test_postgres_saturation_store.py +75 -0
- sengol-0.8.0/tests/api/test_rate_limit.py +212 -0
- sengol-0.8.0/tests/api/test_regulations_api.py +252 -0
- sengol-0.8.0/tests/api/test_reports_db.py +169 -0
- sengol-0.8.0/tests/api/test_reports_generate.py +88 -0
- sengol-0.8.0/tests/api/test_review_routes.py +247 -0
- sengol-0.8.0/tests/api/test_s3_audit_store.py +261 -0
- sengol-0.8.0/tests/api/test_signing_kms.py +261 -0
- sengol-0.8.0/tests/api/test_token_issuance_log.py +933 -0
- sengol-0.8.0/tests/api/test_verification_keys.py +107 -0
- sengol-0.8.0/tests/build/__init__.py +0 -0
- sengol-0.8.0/tests/build/test_gate.py +367 -0
- sengol-0.8.0/tests/build/test_regression.py +128 -0
- sengol-0.8.0/tests/build/test_suite_flake.py +198 -0
- sengol-0.8.0/tests/capture/__init__.py +0 -0
- sengol-0.8.0/tests/capture/test_config.py +240 -0
- sengol-0.8.0/tests/capture/test_redaction.py +55 -0
- sengol-0.8.0/tests/capture/test_store.py +182 -0
- sengol-0.8.0/tests/cicd/__init__.py +0 -0
- sengol-0.8.0/tests/cicd/test_azure_pipelines.py +273 -0
- sengol-0.8.0/tests/cicd/test_github.py +746 -0
- sengol-0.8.0/tests/cli/__init__.py +0 -0
- sengol-0.8.0/tests/cli/test_analyze.py +95 -0
- sengol-0.8.0/tests/cli/test_audit_verify.py +194 -0
- sengol-0.8.0/tests/cli/test_audit_verify_offline.py +273 -0
- sengol-0.8.0/tests/cli/test_controlbook_validate.py +95 -0
- sengol-0.8.0/tests/cli/test_dataset.py +393 -0
- sengol-0.8.0/tests/cli/test_eval_browse.py +51 -0
- sengol-0.8.0/tests/cli/test_eval_health.py +140 -0
- sengol-0.8.0/tests/cli/test_eval_list.py +75 -0
- sengol-0.8.0/tests/cli/test_eval_suggest.py +38 -0
- sengol-0.8.0/tests/cli/test_exporters_e2e.py +154 -0
- sengol-0.8.0/tests/cli/test_github_oidc_exchange.py +113 -0
- sengol-0.8.0/tests/cli/test_judge_validate.py +155 -0
- sengol-0.8.0/tests/cli/test_lifecycle_certify.py +154 -0
- sengol-0.8.0/tests/cli/test_policy_list.py +99 -0
- sengol-0.8.0/tests/cli/test_regulation_cli.py +181 -0
- sengol-0.8.0/tests/cli/test_report_generate.py +484 -0
- sengol-0.8.0/tests/cli/test_review_cli.py +198 -0
- sengol-0.8.0/tests/cli/test_run_suite.py +354 -0
- sengol-0.8.0/tests/cli/test_sinks_e2e.py +112 -0
- sengol-0.8.0/tests/core/__init__.py +0 -0
- sengol-0.8.0/tests/core/test_agent_call_record.py +74 -0
- sengol-0.8.0/tests/core/test_controlbook.py +214 -0
- sengol-0.8.0/tests/core/test_evidence_types.py +194 -0
- sengol-0.8.0/tests/core/test_judge_validation.py +176 -0
- sengol-0.8.0/tests/core/test_merkle.py +76 -0
- sengol-0.8.0/tests/core/test_payload_registry.py +313 -0
- sengol-0.8.0/tests/core/test_payload_version_unchanged.py +81 -0
- sengol-0.8.0/tests/core/test_registry.py +292 -0
- sengol-0.8.0/tests/core/test_risk_taxonomy.py +164 -0
- sengol-0.8.0/tests/core/test_severity.py +68 -0
- sengol-0.8.0/tests/core/test_signing.py +325 -0
- sengol-0.8.0/tests/core/test_signing_backend_field.py +231 -0
- sengol-0.8.0/tests/core/test_types.py +356 -0
- sengol-0.8.0/tests/dataset/__init__.py +0 -0
- sengol-0.8.0/tests/dataset/test_loader.py +342 -0
- sengol-0.8.0/tests/dataset/test_registry.py +216 -0
- sengol-0.8.0/tests/evaluators/__init__.py +0 -0
- sengol-0.8.0/tests/evaluators/conftest.py +32 -0
- sengol-0.8.0/tests/evaluators/deterministic/__init__.py +0 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_benchmark.py +91 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_disclosure.py +131 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_drift_monitor.py +79 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_exact_match.py +53 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_keyword.py +66 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_pii.py +232 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_regex.py +46 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_response_length.py +54 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_schema_validation.py +62 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_trajectory.py +220 -0
- sengol-0.8.0/tests/evaluators/deterministic/test_unauthorized_delegation.py +88 -0
- sengol-0.8.0/tests/evaluators/llm/__init__.py +0 -0
- sengol-0.8.0/tests/evaluators/llm/test_adversarial_robustness.py +136 -0
- sengol-0.8.0/tests/evaluators/llm/test_explainability.py +152 -0
- sengol-0.8.0/tests/evaluators/llm/test_faithfulness.py +108 -0
- sengol-0.8.0/tests/evaluators/llm/test_groundedness.py +194 -0
- sengol-0.8.0/tests/evaluators/llm/test_hallucination.py +110 -0
- sengol-0.8.0/tests/evaluators/llm/test_pii_deprecation.py +60 -0
- sengol-0.8.0/tests/evaluators/llm/test_refusal.py +133 -0
- sengol-0.8.0/tests/evaluators/llm/test_relevance.py +189 -0
- sengol-0.8.0/tests/evaluators/llm/test_stubs.py +74 -0
- sengol-0.8.0/tests/evaluators/llm/test_toxicity.py +188 -0
- sengol-0.8.0/tests/evaluators/llm/test_trajectory.py +204 -0
- sengol-0.8.0/tests/evaluators/model/__init__.py +0 -0
- sengol-0.8.0/tests/evaluators/model/test_ab_evaluator.py +492 -0
- sengol-0.8.0/tests/evaluators/model/test_auc.py +190 -0
- sengol-0.8.0/tests/evaluators/model/test_champion_challenger.py +166 -0
- sengol-0.8.0/tests/evaluators/model/test_fairness.py +295 -0
- sengol-0.8.0/tests/evaluators/model/test_outcome_monitor.py +148 -0
- sengol-0.8.0/tests/evaluators/model/test_psi.py +226 -0
- sengol-0.8.0/tests/evaluators/redteam/__init__.py +0 -0
- sengol-0.8.0/tests/evaluators/redteam/test_base.py +133 -0
- sengol-0.8.0/tests/evaluators/redteam/test_garak_backend.py +78 -0
- sengol-0.8.0/tests/evaluators/test_ensemble.py +399 -0
- sengol-0.8.0/tests/fixtures/datasets/sample.csv +4 -0
- sengol-0.8.0/tests/fixtures/datasets/sample.jsonl +3 -0
- sengol-0.8.0/tests/fixtures/datasets/sample.parquet +0 -0
- sengol-0.8.0/tests/governance/__init__.py +0 -0
- sengol-0.8.0/tests/governance/test_audit_store.py +163 -0
- sengol-0.8.0/tests/governance/test_certification_store.py +172 -0
- sengol-0.8.0/tests/governance/test_controlbook_store.py +35 -0
- sengol-0.8.0/tests/governance/test_controlbook_validator.py +561 -0
- sengol-0.8.0/tests/governance/test_evidence_store.py +164 -0
- sengol-0.8.0/tests/governance/test_gold_score.py +235 -0
- sengol-0.8.0/tests/governance/test_gold_score_store.py +180 -0
- sengol-0.8.0/tests/governance/test_human_review_store.py +230 -0
- sengol-0.8.0/tests/governance/test_inmemory_report_store.py +187 -0
- sengol-0.8.0/tests/governance/test_license.py +101 -0
- sengol-0.8.0/tests/governance/test_report_base.py +778 -0
- sengol-0.8.0/tests/governance/test_report_enterprise.py +631 -0
- sengol-0.8.0/tests/governance/test_report_enterprise_8g.py +297 -0
- sengol-0.8.0/tests/governance/test_report_tenant_filter.py +149 -0
- sengol-0.8.0/tests/governance/test_saturation_store.py +147 -0
- sengol-0.8.0/tests/governance/test_word_boundary_matching.py +148 -0
- sengol-0.8.0/tests/instrument/__init__.py +0 -0
- sengol-0.8.0/tests/instrument/test_instrument.py +444 -0
- sengol-0.8.0/tests/integration/__init__.py +0 -0
- sengol-0.8.0/tests/integration/conftest.py +89 -0
- sengol-0.8.0/tests/integration/test_alembic_migrations.py +137 -0
- sengol-0.8.0/tests/integration/test_audit_store_postgres.py +77 -0
- sengol-0.8.0/tests/integration/test_gold_score_store_postgres.py +118 -0
- sengol-0.8.0/tests/integration/test_phase4_e2e.py +304 -0
- sengol-0.8.0/tests/integration/test_report_generate_postgres.py +168 -0
- sengol-0.8.0/tests/judges/__init__.py +0 -0
- sengol-0.8.0/tests/judges/test_anthropic.py +162 -0
- sengol-0.8.0/tests/judges/test_base.py +152 -0
- sengol-0.8.0/tests/judges/test_openai_compatible.py +193 -0
- sengol-0.8.0/tests/judges/test_prompt.py +116 -0
- sengol-0.8.0/tests/observability/test_config.py +175 -0
- sengol-0.8.0/tests/observability/test_linkage.py +169 -0
- sengol-0.8.0/tests/observability/test_spans.py +83 -0
- sengol-0.8.0/tests/observability/test_tracer.py +32 -0
- sengol-0.8.0/tests/policies/__init__.py +0 -0
- sengol-0.8.0/tests/policies/test_compiled.py +167 -0
- sengol-0.8.0/tests/policies/test_compiled_taxonomy.py +25 -0
- sengol-0.8.0/tests/policies/test_loader.py +180 -0
- sengol-0.8.0/tests/policies/test_osfi_e23_pack.py +185 -0
- sengol-0.8.0/tests/policies/test_report_metadata.py +103 -0
- sengol-0.8.0/tests/policies/test_taxonomy.py +92 -0
- sengol-0.8.0/tests/policies/test_us_treasury_pack.py +166 -0
- sengol-0.8.0/tests/runtime/__init__.py +0 -0
- sengol-0.8.0/tests/runtime/sampling/test_clustering_sampler.py +94 -0
- sengol-0.8.0/tests/runtime/test_async_eval_worker.py +272 -0
- sengol-0.8.0/tests/runtime/test_guardrail_capture.py +489 -0
- sengol-0.8.0/tests/runtime/test_guardrail_from_config.py +121 -0
- sengol-0.8.0/tests/runtime/test_guardrails.py +550 -0
- sengol-0.8.0/tests/runtime/test_inline_evaluator.py +261 -0
- sengol-0.8.0/tests/runtime/test_sampling.py +67 -0
- sengol-0.8.0/tests/runtime/test_sqs_eval_worker.py +289 -0
- sengol-0.8.0/tests/runtime/test_sqs_eval_worker_integration.py +111 -0
- sengol-0.8.0/tests/sinks/__init__.py +0 -0
- sengol-0.8.0/tests/sinks/test_dispatch.py +191 -0
- sengol-0.8.0/tests/sinks/test_import_boundary.py +95 -0
- sengol-0.8.0/tests/sinks/test_langfuse_sink.py +164 -0
- sengol-0.8.0/tests/sinks/test_otlp_sink.py +239 -0
- sengol-0.8.0/tests/sinks/test_registry.py +178 -0
- sengol-0.8.0/tests/suite/__init__.py +0 -0
- sengol-0.8.0/tests/suite/test_saturation_detector.py +69 -0
- sengol-0.8.0/tests/suite/test_suite.py +594 -0
- sengol-0.8.0/tests/synthetic/__init__.py +0 -0
- sengol-0.8.0/tests/synthetic/test_augment.py +100 -0
- sengol-0.8.0/tests/synthetic/test_generator.py +120 -0
- sengol-0.8.0/tests/test_adapters_and_exporters_demo.py +80 -0
- sengol-0.8.0/tests/test_api_eval_run_sink.py +209 -0
- sengol-0.8.0/tests/test_drift.py +1333 -0
- sengol-0.8.0/tests/test_end_to_end_demo.py +113 -0
- sengol-0.8.0/tests/test_eval_run_record.py +111 -0
- sengol-0.8.0/tests/test_eval_run_store.py +136 -0
- sengol-0.8.0/tests/test_governance_routes.py +247 -0
- sengol-0.8.0/tests/test_hash_chain.py +253 -0
- sengol-0.8.0/tests/test_idempotency.py +214 -0
- sengol-0.8.0/tests/test_logging.py +74 -0
- sengol-0.8.0/tests/test_run_suite_workload.py +769 -0
- sengol-0.8.0/tests/test_schema_versioning.py +234 -0
- sengol-0.8.0/tests/test_structured_logging.py +341 -0
- sengol-0.8.0/tests/trajectory/__init__.py +0 -0
- sengol-0.8.0/tests/trajectory/fixtures/openinference_trace.json +63 -0
- sengol-0.8.0/tests/trajectory/fixtures/otelgenai_trace.json +65 -0
- sengol-0.8.0/tests/trajectory/test_mapping_snapshot.py +122 -0
- sengol-0.8.0/uv.lock +6159 -0
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: pr-review
|
|
3
|
+
description: Triage and resolve review comments on sengol/product PRs — gather (haiku) → decide FIX/REJECT/SKIP (opus) → implement (sonnet) → verify+ship (haiku). Use when a PR has review comments to work through. Args: one or more "<owner>/<repo>#<number>".
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# PR Review Triage — four stages, model pinned per stage
|
|
7
|
+
|
|
8
|
+
Cost rule: each stage runs on its named model. The expensive model (opus/fable) sees ONLY the
|
|
9
|
+
gathered comment list — never raw diffs or whole files. Announce the model switch before each
|
|
10
|
+
stage; if the harness can't switch models, say so and continue, keeping stage boundaries.
|
|
11
|
+
|
|
12
|
+
## Stage 1 — GATHER (haiku). No judgments, no fixes, no file edits.
|
|
13
|
+
|
|
14
|
+
For each PR argument, fetch via GitHub MCP tools (fall back to `gh` with `--jq` only if MCP
|
|
15
|
+
is unavailable): review comment threads, review summaries, and issue comments.
|
|
16
|
+
|
|
17
|
+
Output ONE numbered list, grouped by repo:
|
|
18
|
+
```
|
|
19
|
+
[N] repo · file:line · author · priority badge if present
|
|
20
|
+
verbatim body (strip bot boilerplate/badges)
|
|
21
|
+
type: question / requested-change / suggestion / nit / informational
|
|
22
|
+
```
|
|
23
|
+
End with counts by type. STOP — next stage decides.
|
|
24
|
+
|
|
25
|
+
## Stage 2 — DECIDE (opus or fable). One verdict per item: FIX / REJECT / SKIP.
|
|
26
|
+
|
|
27
|
+
Decide against the session brief (product `phases/phase-<N>/session-<Nx>.md`) and the repo
|
|
28
|
+
invariants. Standing REJECT grounds:
|
|
29
|
+
- **Out of scope** — expands into another session's territory (cite the brief).
|
|
30
|
+
- **Invariant violation** — would weaken: binary `EvalScore.passed` (Rule 2); ControlBook
|
|
31
|
+
drives reports (Rule 4); ADR-0052 store boundary; append-only AuditStore + HMAC payload
|
|
32
|
+
scope; sinks/exporters never fail the gate or add latency; credentials from env only,
|
|
33
|
+
never `sengol.yaml`; `...` is valid in Protocol bodies (PEP 544).
|
|
34
|
+
- **Vendor brokering** — Sengol never maps/holds vendor credentials.
|
|
35
|
+
|
|
36
|
+
Standing SKIP: bot overview wrappers, duplicates, pure informational.
|
|
37
|
+
|
|
38
|
+
Output a decision table (#, item, verdict, one-sentence action or reply), flag the 2–3
|
|
39
|
+
riskiest FIXes, then STOP for the user's approval. **If zero FIXes: recommend merging and
|
|
40
|
+
stop — do not run stages 3–4.**
|
|
41
|
+
|
|
42
|
+
## Stage 3 — IMPLEMENT (sonnet). Only after explicit approval.
|
|
43
|
+
|
|
44
|
+
- Trivial fixes first, then functional. Touch only files the comments implicate.
|
|
45
|
+
- Post each approved REJECT reply verbatim on its thread (one comment per thread, never a
|
|
46
|
+
new thread). SKIPs stay silent.
|
|
47
|
+
- Test rules: no full-suite runs while iterating; SSE/streaming tested via the async
|
|
48
|
+
generator with bounded reads + `aclose()` — never GET through TestClient; never "fix" a
|
|
49
|
+
hang by raising a timeout.
|
|
50
|
+
- When all fixes are written: STOP. Stage 4 verifies.
|
|
51
|
+
|
|
52
|
+
## Stage 4 — VERIFY + SHIP (haiku).
|
|
53
|
+
|
|
54
|
+
1. Changed test files only, each bounded:
|
|
55
|
+
`uv run pytest <files> -q --timeout=30 -p no:cacheprovider` (never pipe through tail/head).
|
|
56
|
+
2. Green → full fast suite ONCE (`-m "not llm and not integration"`) + `npx vitest run` ONCE
|
|
57
|
+
if frontend files changed.
|
|
58
|
+
3. Push (the PR updates automatically), confirm CI green via MCP check-runs, report a
|
|
59
|
+
one-line status per PR. A code fix needed mid-verify goes back to Stage 3 — never fixed
|
|
60
|
+
on haiku. If still red after one full pass: STOP and report the failure output verbatim.
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
# Sengol v3.6 — Cursor Rules (Phases 1–2)
|
|
2
|
+
|
|
3
|
+
## Identity
|
|
4
|
+
Sengol — Apache 2.0 Python 3.12 SDK. AI governance for regulated financial institutions.
|
|
5
|
+
Building Phases 1–2: SDK core + OSFI E-23 PDF compliance report.
|
|
6
|
+
|
|
7
|
+
## Critical Rules — Never Violate
|
|
8
|
+
|
|
9
|
+
### 1. PolicyId is open str — NEVER Literal
|
|
10
|
+
```python
|
|
11
|
+
# ✓ CORRECT — any org can define their own
|
|
12
|
+
PolicyId = str # "OSFI_E23", "MY_BANK_POLICY_V3", "MAS_TRM" all valid
|
|
13
|
+
|
|
14
|
+
# ✗ WRONG — breaks for Singapore, Saudi, Indian banks
|
|
15
|
+
PolicyId = Literal["OSFI_E23", "FINTRAC_6F"]
|
|
16
|
+
```
|
|
17
|
+
|
|
18
|
+
### 2. EvalScore.passed is binary bool — NEVER float
|
|
19
|
+
```python
|
|
20
|
+
# ✓ CORRECT
|
|
21
|
+
EvalScore(passed=True, failure_mode=None)
|
|
22
|
+
EvalScore(passed=False, failure_mode="REQUIRED_DISCLOSURE_MISSING")
|
|
23
|
+
|
|
24
|
+
# ✗ WRONG
|
|
25
|
+
EvalScore(score=0.87) # NEVER — pre-commit blocks this
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
### 3. Deterministic before LLM — asyncio.gather() for LLM
|
|
29
|
+
```python
|
|
30
|
+
# EvalSuite runs in this order:
|
|
31
|
+
# 1. All DeterministicEvaluator — sync, <1ms, no API
|
|
32
|
+
# 2. Short-circuit if CRITICAL failure (skip LLM)
|
|
33
|
+
# 3. All LLMEvaluator — asyncio.gather() — O(1) not O(n)
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
### 4. ControlBook drives reports — never bypass it
|
|
37
|
+
```python
|
|
38
|
+
# ✓ CORRECT — works for any regulation
|
|
39
|
+
ComplianceReportGenerator(controlbook=controlbook).generate(agent_id, period)
|
|
40
|
+
|
|
41
|
+
# ✗ WRONG — hardcoded, breaks for non-OSFI customers
|
|
42
|
+
OSFIReportGenerator().generate(agent_id, period)
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### 5. Audit records: sign before write, append-only
|
|
46
|
+
```python
|
|
47
|
+
# ✓ CORRECT
|
|
48
|
+
signed = record.sign(signing_key)
|
|
49
|
+
await audit_store.write(signed)
|
|
50
|
+
|
|
51
|
+
# ✗ WRONG — audit_store has no update() method
|
|
52
|
+
await audit_store.update(record_id, new_data)
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
## Code Patterns to Suggest
|
|
56
|
+
|
|
57
|
+
### Deterministic evaluator skeleton
|
|
58
|
+
```python
|
|
59
|
+
from sengol.core.evaluator import DeterministicEvaluator
|
|
60
|
+
from sengol.core.types import LLMEvalInput, EvalScore
|
|
61
|
+
|
|
62
|
+
class RequiredDisclosureEvaluator(DeterministicEvaluator):
|
|
63
|
+
"""Checks OSFI E-23 required disclosure phrases. Observed at: Canadian retail bank."""
|
|
64
|
+
name = "RequiredDisclosureEvaluator"
|
|
65
|
+
failure_mode = "REQUIRED_DISCLOSURE_MISSING"
|
|
66
|
+
policies: list[str] = ["OSFI_E23"]
|
|
67
|
+
version: str = "1.0.0"
|
|
68
|
+
|
|
69
|
+
def evaluate(self, input: LLMEvalInput) -> EvalScore:
|
|
70
|
+
passed = "not a guarantee" in input.response.lower()
|
|
71
|
+
return EvalScore(
|
|
72
|
+
evaluator=self.name,
|
|
73
|
+
passed=passed,
|
|
74
|
+
failure_mode=None if passed else self.failure_mode,
|
|
75
|
+
reason="Disclosure present" if passed else "Missing required disclosure",
|
|
76
|
+
)
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
### LLM evaluator stub (Phase 1)
|
|
80
|
+
```python
|
|
81
|
+
class FaithfulnessEvaluator(LLMEvaluator):
|
|
82
|
+
name = "FaithfulnessEvaluator"
|
|
83
|
+
failure_mode = "FAITHFULNESS_FAILURE"
|
|
84
|
+
policies: list[str] = ["OSFI_E23"]
|
|
85
|
+
|
|
86
|
+
async def evaluate_async(self, input: LLMEvalInput) -> EvalScore:
|
|
87
|
+
# Phase 1 stub — Phase 3 wires real LLM judge
|
|
88
|
+
return EvalScore(evaluator=self.name, passed=True, failure_mode=None)
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### AuditRecord (sign before write)
|
|
92
|
+
```python
|
|
93
|
+
signed = record.sign(os.getenv("SENGOL_SIGNING_KEY"))
|
|
94
|
+
await audit_store.write(signed)
|
|
95
|
+
assert await audit_store.verify(signed.record_id)
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### ControlBook-driven report
|
|
99
|
+
```python
|
|
100
|
+
report = ComplianceReportGenerator(
|
|
101
|
+
audit_store=audit_store,
|
|
102
|
+
controlbook=controlbook,
|
|
103
|
+
).generate(
|
|
104
|
+
agent_id="rag-advisor-001",
|
|
105
|
+
period_from=datetime(2026, 1, 1),
|
|
106
|
+
period_to=datetime(2026, 5, 1),
|
|
107
|
+
)
|
|
108
|
+
# report.pdf_path — hand to CRO
|
|
109
|
+
# report.json_path — machine-readable evidence
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Never Suggest
|
|
113
|
+
- `PolicyId = Literal[...]` — must be `str`
|
|
114
|
+
- `EvalScore(score=0.87)` — float primary output
|
|
115
|
+
- `print()` — use `structlog`
|
|
116
|
+
- `logging.basicConfig()` — use `structlog`
|
|
117
|
+
- Sequential LLM evaluator calls — use `asyncio.gather()`
|
|
118
|
+
- `UPDATE` or `DELETE` on `audit_records`
|
|
119
|
+
- Hardcoded OSFI-only report generator
|
|
120
|
+
- `import openai` — respect `ControlBook.judge_by_tier`
|
|
121
|
+
|
|
122
|
+
## File Locations
|
|
123
|
+
- New evaluator → `sengol/evaluators/{deterministic|llm}/{name}.py`
|
|
124
|
+
- New type → `sengol/core/types.py` (check spec §5 first)
|
|
125
|
+
- New API route → `sengol/api/routes/{name}.py`
|
|
126
|
+
- New CLI command → `sengol/cli/main.py` (Typer)
|
|
127
|
+
- Policy catalog → `sengol/policies/catalog.yaml`
|
|
128
|
+
|
|
129
|
+
## Logging
|
|
130
|
+
```python
|
|
131
|
+
import structlog
|
|
132
|
+
log = structlog.get_logger()
|
|
133
|
+
log.info("eval.complete", evaluator="MyEval", passed=True, latency_ms=12)
|
|
134
|
+
```
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# Files excluded from the Docker build context.
|
|
2
|
+
#
|
|
3
|
+
# IMPORTANT: do NOT add `*.md` or `README.md` here — the Dockerfile COPYs
|
|
4
|
+
# `README.md` and uv requires it to resolve the package metadata.
|
|
5
|
+
|
|
6
|
+
.git
|
|
7
|
+
.github
|
|
8
|
+
.claude
|
|
9
|
+
.pytest_cache
|
|
10
|
+
.ruff_cache
|
|
11
|
+
.venv
|
|
12
|
+
.coverage
|
|
13
|
+
**/__pycache__
|
|
14
|
+
*.pyc
|
|
15
|
+
tests
|
|
16
|
+
docs
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# GitHub Copilot — sengol (Phases 1–2)
|
|
2
|
+
# .github/copilot-instructions.md
|
|
3
|
+
|
|
4
|
+
## Project
|
|
5
|
+
Sengol — Apache 2.0 Python 3.12 SDK for AI governance in regulated financial institutions.
|
|
6
|
+
Building Phases 1–2: SDK core → OSFI E-23 compliance PDF report.
|
|
7
|
+
|
|
8
|
+
## Always Suggest
|
|
9
|
+
|
|
10
|
+
### Evaluator pattern (deterministic — no LLM)
|
|
11
|
+
```python
|
|
12
|
+
from sengol.core.evaluator import DeterministicEvaluator
|
|
13
|
+
from sengol.core.types import LLMEvalInput, EvalScore
|
|
14
|
+
|
|
15
|
+
class RequiredDisclosureEvaluator(DeterministicEvaluator):
|
|
16
|
+
"""Checks OSFI E-23 required disclosure phrases are present. Observed at: Canadian retail bank."""
|
|
17
|
+
name = "RequiredDisclosureEvaluator"
|
|
18
|
+
failure_mode = "REQUIRED_DISCLOSURE_MISSING"
|
|
19
|
+
policies: list[str] = ["OSFI_E23"] # list of str — not Literal
|
|
20
|
+
|
|
21
|
+
def evaluate(self, input: LLMEvalInput) -> EvalScore:
|
|
22
|
+
passed = "not a guarantee" in input.response.lower()
|
|
23
|
+
return EvalScore(
|
|
24
|
+
evaluator=self.name,
|
|
25
|
+
passed=passed, # bool — always
|
|
26
|
+
failure_mode=None if passed else self.failure_mode,
|
|
27
|
+
reason="Disclosure present" if passed else "Missing required disclosure",
|
|
28
|
+
)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### LLM evaluator stub pattern (Phase 1)
|
|
32
|
+
```python
|
|
33
|
+
class FaithfulnessEvaluator(LLMEvaluator):
|
|
34
|
+
name = "FaithfulnessEvaluator"
|
|
35
|
+
failure_mode = "FAITHFULNESS_FAILURE"
|
|
36
|
+
policies: list[str] = ["OSFI_E23"]
|
|
37
|
+
|
|
38
|
+
async def evaluate_async(self, input: LLMEvalInput) -> EvalScore:
|
|
39
|
+
# Phase 1: stub — returns True
|
|
40
|
+
# Phase 3: wire real LLM judge here
|
|
41
|
+
return EvalScore(evaluator=self.name, passed=True, failure_mode=None)
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
### AuditRecord write (always sign before write)
|
|
45
|
+
```python
|
|
46
|
+
signed = record.sign(os.getenv("SENGOL_SIGNING_KEY"))
|
|
47
|
+
await audit_store.write(signed) # only write signed records
|
|
48
|
+
# verify immediately after
|
|
49
|
+
assert await audit_store.verify(signed.record_id)
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
### ControlBook-driven report
|
|
53
|
+
```python
|
|
54
|
+
# Always ControlBook-driven — works for any regulation
|
|
55
|
+
report = ComplianceReportGenerator(
|
|
56
|
+
audit_store=audit_store,
|
|
57
|
+
controlbook=controlbook, # loads from acme_controlbook.yaml
|
|
58
|
+
).generate(agent_id="rag-advisor-001", period_from=..., period_to=...)
|
|
59
|
+
# report.pdf_path — hand to CRO
|
|
60
|
+
# report.json_path — machine-readable evidence
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Logging
|
|
64
|
+
```python
|
|
65
|
+
import structlog
|
|
66
|
+
log = structlog.get_logger()
|
|
67
|
+
log.info("eval.complete", evaluator="MyEval", passed=True, latency_ms=12)
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
## Never Suggest
|
|
71
|
+
|
|
72
|
+
- `PolicyId = Literal["OSFI_E23", ...]` — it must be `str`
|
|
73
|
+
- Float as `EvalScore.passed` — always `bool`
|
|
74
|
+
- `print()` for logging — always `structlog`
|
|
75
|
+
- Sequential LLM evaluator calls — always `asyncio.gather()`
|
|
76
|
+
- `UPDATE` or `DELETE` on `audit_records` table
|
|
77
|
+
- Hardcoded OSFI-only reports — use `ComplianceReportGenerator(controlbook=...)`
|
|
78
|
+
- `import openai` — for judge calls, respect `ControlBook.judge_by_tier`
|
|
79
|
+
|
|
80
|
+
## Test Pattern
|
|
81
|
+
```python
|
|
82
|
+
@pytest.mark.asyncio
|
|
83
|
+
async def test_evaluator_fails_missing_disclosure():
|
|
84
|
+
ev = RequiredDisclosureEvaluator()
|
|
85
|
+
result = ev.evaluate(LLMEvalInput(
|
|
86
|
+
agent_id="test", agent_version="1.0",
|
|
87
|
+
prompt="What should I know?",
|
|
88
|
+
response="Buy this fund now.", # missing disclosure
|
|
89
|
+
))
|
|
90
|
+
assert result.passed is False
|
|
91
|
+
assert result.failure_mode == "REQUIRED_DISCLOSURE_MISSING"
|
|
92
|
+
```
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
name: ci
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
ci:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
steps:
|
|
13
|
+
- uses: actions/checkout@v4
|
|
14
|
+
- name: Install uv
|
|
15
|
+
uses: astral-sh/setup-uv@v3
|
|
16
|
+
with:
|
|
17
|
+
enable-cache: true
|
|
18
|
+
- name: Set up Python
|
|
19
|
+
run: uv python install 3.11
|
|
20
|
+
- name: Install dependencies
|
|
21
|
+
run: uv sync --all-extras
|
|
22
|
+
- name: Lint
|
|
23
|
+
run: uv run ruff check .
|
|
24
|
+
- name: Format check
|
|
25
|
+
run: uv run ruff format --check .
|
|
26
|
+
- name: Fast tests
|
|
27
|
+
run: uv run pytest -v -m "not llm and not integration"
|
|
28
|
+
- name: Generate OpenAPI spec
|
|
29
|
+
env:
|
|
30
|
+
SENGOL_SIGNING_KEY: ci-placeholder
|
|
31
|
+
SENGOL_AUDIT_URI: memory://
|
|
32
|
+
run: |
|
|
33
|
+
uv run python -c "
|
|
34
|
+
import yaml
|
|
35
|
+
from sengol.api.app import app
|
|
36
|
+
with open('sengol/api/openapi_ci.yaml', 'w') as f:
|
|
37
|
+
yaml.safe_dump(app.openapi(), f, sort_keys=False, allow_unicode=True, width=120)
|
|
38
|
+
"
|
|
39
|
+
- name: Check for breaking API changes (ADR-0057)
|
|
40
|
+
uses: tufin/oasdiff-action@v1
|
|
41
|
+
with:
|
|
42
|
+
base: sengol/api/openapi.yaml
|
|
43
|
+
revision: sengol/api/openapi_ci.yaml
|
|
44
|
+
fail-on-diff: breaking
|
|
45
|
+
|
|
46
|
+
terraform-plan:
|
|
47
|
+
runs-on: ubuntu-latest
|
|
48
|
+
defaults:
|
|
49
|
+
run:
|
|
50
|
+
working-directory: terraform/aws
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- name: Set up Terraform
|
|
54
|
+
uses: hashicorp/setup-terraform@v3
|
|
55
|
+
with:
|
|
56
|
+
terraform_version: "1.9.8"
|
|
57
|
+
- name: Terraform init
|
|
58
|
+
run: terraform init -backend=false -input=false
|
|
59
|
+
- name: Terraform validate
|
|
60
|
+
run: terraform validate
|
|
61
|
+
- name: Terraform fmt check
|
|
62
|
+
run: terraform fmt -check -recursive
|
|
63
|
+
- name: Terraform plan (no apply — mock credentials baked into providers.tf)
|
|
64
|
+
run: terraform plan -var-file=environments/dev.tfvars -input=false
|
|
65
|
+
|
|
66
|
+
frontend:
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
defaults:
|
|
69
|
+
run:
|
|
70
|
+
working-directory: console
|
|
71
|
+
steps:
|
|
72
|
+
- uses: actions/checkout@v4
|
|
73
|
+
- name: Set up Node
|
|
74
|
+
uses: actions/setup-node@v4
|
|
75
|
+
with:
|
|
76
|
+
node-version: 20
|
|
77
|
+
cache: npm
|
|
78
|
+
cache-dependency-path: console/package-lock.json
|
|
79
|
+
- name: Install dependencies
|
|
80
|
+
run: npm ci
|
|
81
|
+
- name: Test
|
|
82
|
+
run: npm test
|
|
83
|
+
- name: Build
|
|
84
|
+
run: npm run build
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
name: Deploy
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches:
|
|
6
|
+
- main
|
|
7
|
+
workflow_dispatch:
|
|
8
|
+
inputs:
|
|
9
|
+
environment:
|
|
10
|
+
description: "Target environment"
|
|
11
|
+
required: true
|
|
12
|
+
default: staging
|
|
13
|
+
type: choice
|
|
14
|
+
options:
|
|
15
|
+
- dev
|
|
16
|
+
- staging
|
|
17
|
+
- production
|
|
18
|
+
|
|
19
|
+
permissions:
|
|
20
|
+
id-token: write
|
|
21
|
+
contents: read
|
|
22
|
+
|
|
23
|
+
jobs:
|
|
24
|
+
deploy:
|
|
25
|
+
name: Deploy to ${{ github.event_name == 'workflow_dispatch' && inputs.environment || 'staging' }}
|
|
26
|
+
runs-on: ubuntu-latest
|
|
27
|
+
environment: ${{ inputs.environment || 'staging' }}
|
|
28
|
+
|
|
29
|
+
env:
|
|
30
|
+
DEPLOY_ENV: ${{ github.event_name == 'workflow_dispatch' && inputs.environment || 'staging' }}
|
|
31
|
+
|
|
32
|
+
steps:
|
|
33
|
+
- name: Checkout
|
|
34
|
+
uses: actions/checkout@v4
|
|
35
|
+
|
|
36
|
+
- name: Configure AWS credentials (OIDC)
|
|
37
|
+
uses: aws-actions/configure-aws-credentials@v4
|
|
38
|
+
with:
|
|
39
|
+
role-to-assume: ${{ secrets.AWS_ROLE_ARN }}
|
|
40
|
+
aws-region: ${{ secrets.KUBE_CLUSTER_REGION }}
|
|
41
|
+
|
|
42
|
+
- name: Login to Amazon ECR
|
|
43
|
+
id: ecr-login
|
|
44
|
+
uses: aws-actions/amazon-ecr-login@v2
|
|
45
|
+
|
|
46
|
+
- name: Build and push Docker image to ECR
|
|
47
|
+
env:
|
|
48
|
+
IMAGE_URI: ${{ secrets.ECR_REGISTRY }}/${{ secrets.ECR_REPOSITORY }}:${{ github.sha }}
|
|
49
|
+
run: |
|
|
50
|
+
docker build -t "${IMAGE_URI}" .
|
|
51
|
+
docker push "${IMAGE_URI}"
|
|
52
|
+
echo "image_uri=${IMAGE_URI}" >> "${GITHUB_OUTPUT}"
|
|
53
|
+
id: build
|
|
54
|
+
|
|
55
|
+
- name: Set up kubectl
|
|
56
|
+
uses: azure/setup-kubectl@v3
|
|
57
|
+
|
|
58
|
+
- name: Set up Helm
|
|
59
|
+
uses: azure/setup-helm@v3
|
|
60
|
+
with:
|
|
61
|
+
version: v3.14.0
|
|
62
|
+
|
|
63
|
+
- name: Update kubeconfig for EKS
|
|
64
|
+
run: |
|
|
65
|
+
aws eks update-kubeconfig \
|
|
66
|
+
--name ${{ secrets.KUBE_CLUSTER_NAME }} \
|
|
67
|
+
--region ${{ secrets.KUBE_CLUSTER_REGION }}
|
|
68
|
+
|
|
69
|
+
- name: Helm upgrade/install
|
|
70
|
+
run: |
|
|
71
|
+
helm upgrade --install sengol ./helm/sengol \
|
|
72
|
+
--namespace sengol \
|
|
73
|
+
--create-namespace \
|
|
74
|
+
-f helm/sengol/values-aws.yaml \
|
|
75
|
+
--set image.repository=${{ secrets.ECR_REGISTRY }}/${{ secrets.ECR_REPOSITORY }} \
|
|
76
|
+
--set image.tag=${{ github.sha }} \
|
|
77
|
+
--set secrets.SENGOL_SIGNING_KEY="${{ secrets.SENGOL_SIGNING_KEY }}" \
|
|
78
|
+
--set secrets.SENGOL_KMS_KEY_ID="${{ secrets.SENGOL_KMS_KEY_ID }}" \
|
|
79
|
+
--set config.SENGOL_AWS_REGION=${{ secrets.KUBE_CLUSTER_REGION }} \
|
|
80
|
+
--wait --timeout 5m
|
|
81
|
+
|
|
82
|
+
- name: Smoke test
|
|
83
|
+
run: |
|
|
84
|
+
SENGOL_URL="${{ secrets.SENGOL_URL }}"
|
|
85
|
+
curl --fail --retry 3 --retry-delay 5 "${SENGOL_URL}/health"
|
|
86
|
+
echo "Smoke test passed"
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
name: Integration tests (Postgres)
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
paths:
|
|
7
|
+
- 'sengol/core/types.py'
|
|
8
|
+
- 'sengol/governance/audit_store.py'
|
|
9
|
+
- 'sengol/governance/gold_score_store.py'
|
|
10
|
+
- 'sengol/governance/saturation_store.py'
|
|
11
|
+
- 'sengol/governance/report_base.py'
|
|
12
|
+
- 'sengol/cli/main.py'
|
|
13
|
+
- 'sengol/logging.py'
|
|
14
|
+
- 'alembic/**'
|
|
15
|
+
- 'tests/integration/**'
|
|
16
|
+
pull_request:
|
|
17
|
+
paths:
|
|
18
|
+
- 'sengol/core/types.py'
|
|
19
|
+
- 'sengol/governance/audit_store.py'
|
|
20
|
+
- 'sengol/governance/gold_score_store.py'
|
|
21
|
+
- 'sengol/governance/saturation_store.py'
|
|
22
|
+
- 'sengol/governance/report_base.py'
|
|
23
|
+
- 'sengol/cli/main.py'
|
|
24
|
+
- 'sengol/logging.py'
|
|
25
|
+
- 'alembic/**'
|
|
26
|
+
- 'tests/integration/**'
|
|
27
|
+
|
|
28
|
+
jobs:
|
|
29
|
+
integration:
|
|
30
|
+
runs-on: ubuntu-latest
|
|
31
|
+
|
|
32
|
+
services:
|
|
33
|
+
postgres:
|
|
34
|
+
image: postgres:16
|
|
35
|
+
env:
|
|
36
|
+
POSTGRES_USER: sengol
|
|
37
|
+
POSTGRES_PASSWORD: sengol
|
|
38
|
+
POSTGRES_DB: sengol_test
|
|
39
|
+
ports:
|
|
40
|
+
- 5432:5432
|
|
41
|
+
options: >-
|
|
42
|
+
--health-cmd pg_isready
|
|
43
|
+
--health-interval 10s
|
|
44
|
+
--health-timeout 5s
|
|
45
|
+
--health-retries 5
|
|
46
|
+
|
|
47
|
+
env:
|
|
48
|
+
SENGOL_AUDIT_URI: postgresql+asyncpg://sengol:sengol@localhost:5432/sengol_test
|
|
49
|
+
SENGOL_SIGNING_KEY: test-signing-key-32-bytes-minimum
|
|
50
|
+
SENGOL_ENVIRONMENT: development
|
|
51
|
+
|
|
52
|
+
steps:
|
|
53
|
+
- uses: actions/checkout@v4
|
|
54
|
+
|
|
55
|
+
- name: Install uv
|
|
56
|
+
uses: astral-sh/setup-uv@v3
|
|
57
|
+
with:
|
|
58
|
+
enable-cache: true
|
|
59
|
+
|
|
60
|
+
- name: Set up Python
|
|
61
|
+
run: uv python install 3.11
|
|
62
|
+
|
|
63
|
+
- name: Install dependencies
|
|
64
|
+
run: uv sync --all-extras
|
|
65
|
+
|
|
66
|
+
- name: Run Alembic migrations
|
|
67
|
+
run: uv run alembic upgrade head
|
|
68
|
+
|
|
69
|
+
- name: Run integration tests
|
|
70
|
+
run: uv run pytest tests/integration/ -v --tb=short -m integration
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Publish to PyPI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
release:
|
|
5
|
+
types: [published]
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
id-token: write # required for PyPI OIDC trusted publisher
|
|
10
|
+
contents: read
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
publish:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
steps:
|
|
16
|
+
- uses: actions/checkout@v4
|
|
17
|
+
|
|
18
|
+
- name: Install uv
|
|
19
|
+
uses: astral-sh/setup-uv@v3
|
|
20
|
+
with:
|
|
21
|
+
enable-cache: true
|
|
22
|
+
|
|
23
|
+
- name: Set up Python
|
|
24
|
+
run: uv python install 3.11
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: uv sync --all-extras
|
|
28
|
+
|
|
29
|
+
- name: Build
|
|
30
|
+
run: uv build
|
|
31
|
+
|
|
32
|
+
- name: Publish to PyPI
|
|
33
|
+
run: uv publish
|
|
34
|
+
# uv publish defaults to PyPI and auto-uses the OIDC token from Actions.
|
|
35
|
+
# No UV_PUBLISH_URL or UV_PUBLISH_TOKEN needed.
|
|
36
|
+
#
|
|
37
|
+
# One-time setup required on pypi.org (per account):
|
|
38
|
+
# Account -> Publishing -> Add pending publisher
|
|
39
|
+
# GitHub owner: sengol-io
|
|
40
|
+
# repo: sengol
|
|
41
|
+
# workflow: publish.yml
|
sengol-0.8.0/.gitignore
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
# Python
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
*.so
|
|
6
|
+
.Python
|
|
7
|
+
/build/
|
|
8
|
+
/dist/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
.eggs/
|
|
11
|
+
|
|
12
|
+
# Virtual environments
|
|
13
|
+
.venv/
|
|
14
|
+
venv/
|
|
15
|
+
env/
|
|
16
|
+
|
|
17
|
+
# Testing & coverage
|
|
18
|
+
.pytest_cache/
|
|
19
|
+
.coverage
|
|
20
|
+
.coverage.*
|
|
21
|
+
htmlcov/
|
|
22
|
+
coverage.xml
|
|
23
|
+
.hypothesis/
|
|
24
|
+
|
|
25
|
+
# Editors / OS
|
|
26
|
+
.DS_Store
|
|
27
|
+
.idea/
|
|
28
|
+
.vscode/
|
|
29
|
+
*.swp
|
|
30
|
+
|
|
31
|
+
# Secrets / env
|
|
32
|
+
.env
|
|
33
|
+
.env.local
|
|
34
|
+
*.pem
|
|
35
|
+
|
|
36
|
+
# Demo + run artifacts (regenerated by examples/demo_end_to_end.py)
|
|
37
|
+
/reports/
|
|
38
|
+
/datasets/
|
|
39
|
+
/eval-results.xml
|
|
40
|
+
|
|
41
|
+
# Claude (local settings stay ignored; versioned skills are tracked)
|
|
42
|
+
.claude/*
|
|
43
|
+
!.claude/skills/
|
|
44
|
+
|
|
45
|
+
# Console frontend (built assets ship in wheel, not committed)
|
|
46
|
+
console/node_modules/
|
|
47
|
+
sengol/console_static/
|
|
48
|
+
console/*.tsbuildinfo
|
sengol-0.8.0/.mcp.json
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
{
|
|
2
|
+
"mcpServers": {
|
|
3
|
+
"filesystem": {
|
|
4
|
+
"command": "npx",
|
|
5
|
+
"args": ["-y", "@modelcontextprotocol/server-filesystem", "."],
|
|
6
|
+
"description": "Read sengol.yaml, catalog.yaml, source files"
|
|
7
|
+
},
|
|
8
|
+
"github": {
|
|
9
|
+
"command": "npx",
|
|
10
|
+
"args": ["-y", "@modelcontextprotocol/server-github"],
|
|
11
|
+
"env": { "GITHUB_PERSONAL_ACCESS_TOKEN": "${GITHUB_TOKEN}" },
|
|
12
|
+
"description": "Create PRs, manage issues, read commits"
|
|
13
|
+
},
|
|
14
|
+
"postgres": {
|
|
15
|
+
"command": "npx",
|
|
16
|
+
"args": ["-y", "@modelcontextprotocol/server-postgres", "${SENGOL_AUDIT_URI}"],
|
|
17
|
+
"description": "Query AuditStore, verify HMAC records"
|
|
18
|
+
},
|
|
19
|
+
"memory": {
|
|
20
|
+
"command": "npx",
|
|
21
|
+
"args": ["-y", "@modelcontextprotocol/server-memory"],
|
|
22
|
+
"description": "Persist phase state across Claude Code sessions"
|
|
23
|
+
},
|
|
24
|
+
"sequential-thinking": {
|
|
25
|
+
"command": "npx",
|
|
26
|
+
"args": ["-y", "@modelcontextprotocol/server-sequential-thinking"],
|
|
27
|
+
"description": "Multi-step phase builds — plan before implementing"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
}
|