Implemented the deployment-bound SQL vertical slice for PostgreSQL and MySQL.
Logical DataFlow release remains a semantic, binding-free reference. Physical
dataset bindings are consumed only by BoundSqlPlanService, which selects a
registered concrete compiler and persists the resulting plan as compiled.
The Runner still requires the exact bound plan and RuleVersion to be
published; full test-evidence publication lifecycle hardening remains Task 7.
Initial RED command:
PYTHONPATH=. .venv/bin/pytest -q \
tests/core/data_rules/test_sql_compiler.py \
tests/runner/test_rule_sql.py
Initial RED result:
18 failed in 1.38s
Representative expected failures:
ModuleNotFoundError: No module named 'app.core.data_rules.compilers'
ModuleNotFoundError: No module named 'app.runner.rule_sql'
Additional RED checks were added before each hardening fix:
PYTHONPATH=. .venv/bin/pytest -q \
tests/core/data_rules/test_sql_compiler.py::test_repository_persists_bound_plan_only_for_one_deployment_linkage
1 failed in 1.05s
AttributeError: 'DataRuleRepository' object has no attribute 'persist_bound_component_plan'
PYTHONPATH=. .venv/bin/pytest -q \
tests/runner/test_rule_sql.py::test_sqlglot_rule_adapter_rejects_unimplemented_idempotency_strategy \
tests/runner/test_rule_sql.py::test_rule_executor_matches_node_idempotency_to_persisted_component
2 failed in 1.09s
PYTHONPATH=. .venv/bin/pytest -q \
tests/core/data_rules/test_sql_compiler.py::test_repository_persists_bound_plan_only_for_one_deployment_linkage
1 failed in 0.88s
Failed: DID NOT RAISE ValueError
This proved a compiled plan was not yet checked against the physical source and target relations stored for the deployment.
PYTHONPATH=. .venv/bin/pytest -q \
tests/core/data_rules/test_sql_compiler.py::test_sql_compiler_fails_closed_for_unsupported_operations_and_binding_mismatch
1 failed in 0.86s
Failed: DID NOT RAISE ValueError
This proved assert.on_failure=quarantine was being accepted without a
quarantine destination, so the compiler was tightened to support only
reject.
PYTHONPATH=. .venv/bin/pytest -q \
tests/runner/test_rule_sql.py::test_sqlglot_rule_adapter_verifies_and_executes_one_transaction
1 failed in 0.98s
This proved affected-row counts were not a stable rows_out metric for
idempotent upserts. The adapter now counts the compiled accepted-row query
inside the same transaction before executing the write.
PYTHONPATH=. .venv/bin/pytest -q \
tests/core/data_rules/test_sql_compiler.py::test_sql_compiler_rejects_unproven_operator_type_semantics
5 failed in 0.90s
This proved text, fill, derive, map, and final output types required additional fail-closed compiler checks.
Focused GREEN after the implementation and hardening:
PYTHONPATH=. .venv/bin/pytest -q \
tests/core/data_rules/test_sql_compiler.py \
tests/runner/test_rule_sql.py \
tests/runner/test_rules.py
33 passed in 0.84s
Related release/repository/bootstrap regression GREEN:
PYTHONPATH=. .venv/bin/pytest -q \
tests/core/data_rules/test_release.py \
tests/core/data_rules/test_data_rule_repository.py \
tests/runner/test_bootstrap.py \
tests/runner/test_rules.py \
tests/core/data_rules/test_execution_contracts.py
49 passed in 0.89s
The source containers were already healthy on PostgreSQL port 25432 and
MySQL port 23306. The integration test:
task4_rule_source and task4_rule_target;compiled;published;RulePlanExecutor;rows_in, rows_out, and
rows_rejected;finally.Direct dialect integration result:
TEST_DATABASE_URL=postgresql://dataops:dataops-test-password@127.0.0.1:15432/dataops \
PYTHONPATH=. .venv/bin/pytest -q \
tests/integration/test_data_rule_sql_execution.py
2 passed in 0.93s
Required vertical-slice command:
TEST_DATABASE_URL=postgresql://dataops:dataops-test-password@127.0.0.1:15432/dataops \
PYTHONPATH=. .venv/bin/pytest -q \
tests/core/data_rules/test_sql_compiler.py \
tests/runner/test_rule_sql.py \
tests/integration/test_data_rule_sql_execution.py
28 passed in 0.97s
PYTHONPATH=. .venv/bin/pytest -q
477 passed, 26 skipped, 59 subtests passed in 4.16s
.venv/bin/ruff check \
app/core/data_rules/compilers \
app/core/data_rules/release.py \
app/core/data_rules/repository.py \
app/runner/rule_sql.py \
app/runner/rules.py \
app/runner/bootstrap.py \
tests/core/data_rules/test_sql_compiler.py \
tests/runner/test_rule_sql.py \
tests/runner/test_rules.py \
tests/integration/test_data_rule_sql_execution.py
All checks passed!
git diff --check produced no output.
sqlglot==30.13.0.License-Expression: MIT.Requires-Python: >=3.9.dataops-sqlglot-30.13.0.requirements.txtapp/core/data_rules/compilers/__init__.pyapp/core/data_rules/compilers/base.pyapp/core/data_rules/compilers/sql.pyapp/core/data_rules/release.pyapp/core/data_rules/repository.pyapp/runner/rule_sql.pyapp/runner/rules.pyapp/runner/bootstrap.pytests/core/data_rules/test_sql_compiler.pytests/runner/test_rule_sql.pytests/runner/test_rules.pytests/integration/test_data_rule_sql_execution.py.superpowers/sdd/task-4-report.mdIdentifier nodes only
after the closed identifier check. RuleSpec values become compiler-owned
named placeholders and never enter SQL text.cast, trim-only
normalize_text, portable regex_replace, type-compatible fill_null,
typed filter, typed derive, reject-only assert, deterministic
deduplicate, and string map_values. Unsupported or semantically
unprovable variants fail closed.upsert is implemented;
the other declared orchestration strategies fail closed at this adapter.not_committed; commit ambiguity returns unknown.quality_check -> SQL write adapter alias was removed.
SqlGlotQualityPlanAdapter explicitly fails closed until a read-only
quality plan contract is implemented.compiled and does not claim tested/published
production state.partition_replace and deduplication_key remain valid orchestration
contract values but are not executable by this SQL adapter; only an exact
persisted upsert binding is accepted.sql_rule_capabilities. Existing deployments without those concrete
capabilities will fail closed until Task 9 binds and validates them.Date: 2026-07-23
All critical, important, and identifier-limit review findings were corrected. The bound SQL compiler now accepts only canonical identifiers at its public service boundary. RuleVersion, schema snapshots, deployment bindings, and the server SQL capability profile are loaded through one repository join before compilation. Caller-provided RuleSpec, schema, binding, or capability objects are no longer accepted.
The plan attests the exact compiler version, RuleSpec hash, input/output schema snapshot IDs and hashes, and deployment binding IDs. Persistence compares those attestations against the canonical database rows. The runner loads and rechecks the same canonical RuleVersion and snapshots before dispatch.
Logical release plans now persist as compiled, and released package plan
references explicitly identify themselves as plan_kind=semantic and
status=compiled. Physical plans use the explicit lifecycle
compiled -> tested -> published; only successful integration_preflight
evidence can produce tested, and only an attested tested plan whose
RuleVersion remains published can be published. The runner rejects both
compiled and tested plans.
ON DUPLICATE KEY UPDATE from merging a different
logical row through another unique collision path.on_error=fail; reject, quarantine, and warn fail
closed.dataops-sqlglot-30.13.0
attestation and validates a closed INSERT-SELECT SQLGlot AST subset.
Anonymous and non-allowlisted functions, joins, CTEs, set operations, and
other out-of-compiler nodes are rejected even if a malicious publisher
recomputes the plan hash.tested to the durable execution-plan status
constraint.The initial RED run produced the expected failures for the old caller-object API, canonical component-to-rule mismatch, and function-bearing plan. Additional regression tests cover non-fail cast actions, exact numeric types, total deduplication order, UTF-8 identifier byte limits, logical compiled status, registry availability before release allocation, canonical runner attestation tampering, and lifecycle evidence.
Final verification:
Focused compiler/repository/release/runner plus real database integration:
63 passed
Real PostgreSQL/MySQL execution and MySQL uniqueness failure cases:
3 passed
Full repository suite:
496 passed, 26 skipped, 59 subtests passed
Ruff on all changed Python and migration files:
All checks passed!
git diff --check:
no output
C/POSIX for PostgreSQL and
utf8mb4_0900_bin/ICU for MySQL). A deployment with different concrete
datasource capabilities fails closed at runner dispatch.Date: 2026-07-23
This section supersedes the earlier statement in this report that Task 4
provided a production compiled -> tested -> published transition.
record_bound_plan_test and publish_tested_bound_plan from
DataRuleRepository. Task 4 exposes no production API that accepts
caller-authored execution evidence or promotes a plan.compiled./) is removed from PostgreSQL and MySQL V1 capability
support. Both dialect compilers reject a rule containing division; Polars
reference capability remains available for its defined decimal semantics.20260723_120 migration remains unchanged.
20260723_130 pins the database status constraint to
compiled, published, and revoked; it does not add tested.
Its downgrade raises a clear RuntimeError because persisted compiled plans
make this status-contract migration intentionally forward-only.The RED run produced six expected failures:
After the migration-chain correction, final verification was:
Focused expressions/compiler/repository/release/runner/schema:
89 passed
Real PostgreSQL/MySQL integration:
3 passed
Full repository suite:
501 passed, 26 skipped, 59 subtests passed
Ruff on all changed Python and migration files:
All checks passed!
git diff --check:
no output