Skip to content

feat(preflight): P041 — flag a typed leaf whose audience contradicts its gate-broken category (CONNECT-812 PF-29) - #3592

Open
zaman-atlan wants to merge 2 commits into
mainfrom
zaman-atlan/connect-812-p041-gate-broken-audience
Open

zaman-atlan wants to merge 2 commits into
mainfrom
zaman-atlan/connect-812-p041-gate-broken-audience

Conversation

@zaman-atlan

Copy link
Copy Markdown
Contributor

What

The preflight gate keeps DEPENDENCY_UNAVAILABLE, RATE_LIMITED, RESOURCE_EXHAUSTED and CANCELLED in _GATE_BROKEN_CATEGORIES (preflight_gate.py:423) so a failure in one of them fails open — the gate could not form a verdict, so the run proceeds rather than blaming the source.

A leaf in one of those categories that also declares audience = USER says the opposite: that the customer caused it and must fix it. Both cannot be true, and the taxonomy already answers which.

Resolved against the real MRO of all 21 AppError subclasses — RateLimitedError is the sole outlier of the nine gate-broken leaves:

CancelledError               CANCELLED               APP_OWNER  ok
ColdStartRaceError           DEPENDENCY_UNAVAILABLE  PLATFORM   ok
DaprSidecarUnreachableError  DEPENDENCY_UNAVAILABLE  PLATFORM   ok
DependencyUnavailableError   DEPENDENCY_UNAVAILABLE  PLATFORM   ok
DiskFullError                RESOURCE_EXHAUSTED      PLATFORM   ok
ObjectStoreDownloadError     DEPENDENCY_UNAVAILABLE  PLATFORM   ok
ObjectStoreReadError         DEPENDENCY_UNAVAILABLE  PLATFORM   ok
RateLimitedError             RATE_LIMITED            USER       <-- CONTRADICTS
ResourceExhaustedError       RESOURCE_EXHAUSTED      PLATFORM   ok

Concretely: the remediation a USER audience implies — reduce crawl concurrency — is something Atlan controls and the customer cannot change. Meanwhile every throttle aggregated against the customer's SLA.

Changes

The fixRateLimitedError.audience USERAPP_OWNER. A 429 is our call rate against a customer-owned endpoint, so the locus is the team that chose the concurrency; wire.py:36-39 already resolves an unclear locus to APP_OWNER. PLATFORM would route throttles to platform-oncall, who control neither the rate nor the source.

The rule that keeps it fixedP041 GateBrokenCategoryUserAudience, STATIC / WARN, scope BOTH so it grades the SDK's own leaves as well as app subclasses. It lands green because the leaf is fixed in the same change.

Follows PR #3492 (P047) for file layout: rule definition + one private detector module + registration + generated docs + tests.

Why this rule is cheap and safe

It compares two constants the SDK already publishes. No semantics, no judgement about whether a message matches a category — the part that makes category-correctness undecidable in general (cf. PF-21, where P034 was satisfied by the wrong typed error).

Scope is deliberately narrow, matching the P series' false-negative-over-false-positive stance:

  • Only an audience bound in the class body is flagged. An inherited USER is not resolved across the SDK boundary — once the leaf itself is correct, inheriting from it is the right answer, and modelling SDK internals from an app repo is exactly the false-positive surface to avoid.
  • A subclass that redeclares its own category leaves the gate-broken set and is not flagged here; P002 governs that redeclaration.

Verification

Not just synthetic fixtures — run against the real application_sdk/errors/leaves.py:

P041 findings on leaves.py
before the fix 1leaves.py:98, class RateLimitedError
after the fix 0

No false positives across the other 20 leaves.

packages/conformance/tests/test_preflight.py     55 passed  (10 new for P041)
packages/conformance/tests/test_catalog.py
  + test_prescriptions.py                       229 passed, 1 xfailed
tests/unit/errors/                              266 passed
tests/unit/{execution,handler,interceptors}/   1489 passed
gen-rule-docs --check                           up-to-date
ruff check <new file>                           clean

The 10 new tests cover both directions: fires on each of the four gate-broken categories, on a subclass inheriting the category from an SDK leaf, and through an in-file intermediate; stays silent on APP_OWNER/PLATFORM, on a non-gate-broken category (AUTH, where USER is correct), on inherit-only, and on a subclass that redeclares a safe category. Plus the inline-suppression path.

Note on the rule ID

CONNECT-812 specced this as P040 on 2026-08-12, when that was the next free ID. P040 (TransformTemplateReservedKeyword) and P042P050 have shipped since, and P-ids are permanent and never reused — so this takes P041, the one remaining gap in the series.

Registry rows PF-01/PF-31 (P051) and EP-03/EP-03b (P052) need the same renumbering when they land.

Follow-ups (not in this PR)

  • Apps carrying a local RedshiftRateLimitError.audience = APP_OWNER override (redshift#387) can drop it now that the leaf is correct.
  • AppTimeoutError built by the gate leaves operation / timeout_seconds / elapsed_seconds null though all three exist on the class (preflight_gate.py:1086-1093) — SDK-side instance of PF-28.

CONNECT-812 PF-29.

🤖 Generated with Claude Code

…its gate-broken category

The gate keeps DEPENDENCY_UNAVAILABLE, RATE_LIMITED, RESOURCE_EXHAUSTED and
CANCELLED in _GATE_BROKEN_CATEGORIES so a failure in one of them fails *open* —
the gate could not form a verdict, so the run proceeds rather than blaming the
source. A leaf in one of those categories that also declares audience=USER says
the opposite: that the customer caused it and must fix it. Both cannot be true,
and the taxonomy already answers which — 8 of the SDK's 9 gate-broken leaves
resolve to PLATFORM or APP_OWNER.

RateLimitedError was the sole outlier, verified against the resolved MRO of all
21 AppError subclasses. Its USER audience implied a remediation ("reduce crawl
concurrency") that Atlan owns and the customer cannot perform, and it aggregated
every throttle against the customer's SLA.

Fixes the leaf and adds the rule that keeps it fixed:

- RateLimitedError.audience USER -> APP_OWNER. A 429 is our call rate against a
  customer-owned endpoint, so the locus is the team that chose the concurrency;
  wire.py already resolves an unclear locus to APP_OWNER. PLATFORM would route
  throttles to platform-oncall, who control neither the rate nor the source.
- P041 GateBrokenCategoryUserAudience, STATIC/WARN, scope BOTH — it grades the
  SDK's own leaves as well as app subclasses, and lands green because the leaf
  is fixed in the same change.

The rule compares two constants the SDK already publishes, so it makes no
judgement about whether a message matches a category — the part that makes
category-correctness undecidable in general. Only an audience bound in the class
body is flagged; an inherited USER is deliberately not resolved across the SDK
boundary, since once the leaf is correct, inheriting from it is right.

Verified end to end: against the real leaves.py the rule reports exactly one
finding at leaves.py:98 (RateLimitedError) before the fix and zero after, with
no false positives across the other 20 leaves.

CONNECT-812 PF-29.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@linear

linear Bot commented Sep 1, 2026

Copy link
Copy Markdown

CONNECT-812

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

📜 Docstring Coverage Report

RESULT: PASSED (minimum: 30.0%, actual: 81.0%)

Detailed Coverage Report
======= Coverage for /home/runner/work/application-sdk/application-sdk/ ========
----------------------------------- Summary ------------------------------------
| Name                                                                                           | Total |  Miss | Cover | Cover% |
|------------------------------------------------------------------------------------------------|-------|-------|-------|--------|
| .claude/skills/capability-manifest/references/extractor.py                                     |    31 |     2 |    29 |    94% |
| application_sdk/__init__.py                                                                    |     1 |     0 |     1 |   100% |
| application_sdk/_discovery_errors.py                                                           |     7 |     0 |     7 |   100% |
| application_sdk/constants.py                                                                   |     5 |     2 |     3 |    60% |
| application_sdk/discovery.py                                                                   |    12 |     3 |     9 |    75% |
| application_sdk/main.py                                                                        |    42 |    10 |    32 |    76% |
| application_sdk/main_errors.py                                                                 |     5 |     0 |     5 |   100% |
| application_sdk/version.py                                                                     |     1 |     0 |     1 |   100% |
| application_sdk/_runtime/__init__.py                                                           |     1 |     0 |     1 |   100% |
| application_sdk/_runtime/offload.py                                                            |    11 |     1 |    10 |    91% |
| application_sdk/_runtime/progress.py                                                           |    32 |     2 |    30 |    94% |
| application_sdk/app/__init__.py                                                                |     1 |     0 |     1 |   100% |
| application_sdk/app/_artifact_schema_guard.py                                                  |     8 |     0 |     8 |   100% |
| application_sdk/app/_ep_registration.py                                                        |     6 |     0 |     6 |   100% |
| application_sdk/app/base.py                                                                    |    81 |    19 |    62 |    77% |
| application_sdk/app/base_errors.py                                                             |     6 |     0 |     6 |   100% |
| application_sdk/app/client.py                                                                  |     1 |     0 |     1 |   100% |
| application_sdk/app/context.py                                                                 |    40 |     2 |    38 |    95% |
| application_sdk/app/entrypoint.py                                                              |    21 |     5 |    16 |    76% |
| application_sdk/app/registry.py                                                                |    40 |    11 |    29 |    72% |
| application_sdk/app/task.py                                                                    |    17 |     6 |    11 |    65% |
| application_sdk/clients/__init__.py                                                            |     2 |     1 |     1 |    50% |
| application_sdk/clients/_interface.py                                                          |     4 |     1 |     3 |    75% |
| application_sdk/clients/base.py                                                                |     6 |     1 |     5 |    83% |
| application_sdk/clients/models.py                                                              |     2 |     0 |     2 |   100% |
| application_sdk/clients/redis.py                                                               |    27 |     0 |    27 |   100% |
| application_sdk/clients/redis_errors.py                                                        |     5 |     0 |     5 |   100% |
| application_sdk/clients/sql.py                                                                 |    23 |     1 |    22 |    96% |
| application_sdk/clients/sql_errors.py                                                          |    11 |     0 |    11 |   100% |
| application_sdk/clients/sql_typecasters.py                                                     |    14 |     4 |    10 |    71% |
| application_sdk/clients/ssl_utils.py                                                           |     8 |     0 |     8 |   100% |
| application_sdk/clients/azure/__init__.py                                                      |     1 |     0 |     1 |   100% |
| application_sdk/clients/azure/auth.py                                                          |     7 |     0 |     7 |   100% |
| application_sdk/clients/azure/azure_errors.py                                                  |     8 |     0 |     8 |   100% |
| application_sdk/clients/azure/client.py                                                        |    13 |     0 |    13 |   100% |
| application_sdk/common/__init__.py                                                             |     1 |     0 |     1 |   100% |
| application_sdk/common/_env.py                                                                 |     2 |     0 |     2 |   100% |
| application_sdk/common/_listing.py                                                             |     6 |     0 |     6 |   100% |
| application_sdk/common/atomic.py                                                               |    13 |     0 |    13 |   100% |
| application_sdk/common/aws_utils.py                                                            |    10 |     1 |     9 |    90% |
| application_sdk/common/aws_utils_errors.py                                                     |     7 |     0 |     7 |   100% |
| application_sdk/common/concurrency.py                                                          |     3 |     0 |     3 |   100% |
| application_sdk/common/env_warnings.py                                                         |     2 |     0 |     2 |   100% |
| application_sdk/common/error_codes.py                                                          |    15 |     3 |    12 |    80% |
| application_sdk/common/errors.py                                                               |     7 |     0 |     7 |   100% |
| application_sdk/common/file_converter.py                                                       |     9 |     5 |     4 |    44% |
| application_sdk/common/file_ops.py                                                             |    16 |     1 |    15 |    94% |
| application_sdk/common/filter_matching.py                                                      |     9 |     3 |     6 |    67% |
| application_sdk/common/models.py                                                               |     4 |     2 |     2 |    50% |
| application_sdk/common/path.py                                                                 |     2 |     1 |     1 |    50% |
| application_sdk/common/spillable_dict.py                                                       |    17 |    11 |     6 |    35% |
| application_sdk/common/sql_filters.py                                                          |    14 |     2 |    12 |    86% |
| application_sdk/common/sql_filters_errors.py                                                   |     2 |     0 |     2 |   100% |
| application_sdk/common/task_queue.py                                                           |    10 |     0 |    10 |   100% |
| application_sdk/common/transforms.py                                                           |     5 |     0 |     5 |   100% |
| application_sdk/common/types.py                                                                |     2 |     0 |     2 |   100% |
| application_sdk/common/utils.py                                                                |     2 |     0 |     2 |   100% |
| application_sdk/common/incremental/__init__.py                                                 |     3 |     0 |     3 |   100% |
| application_sdk/common/incremental/helpers.py                                                  |    11 |     0 |    11 |   100% |
| application_sdk/common/incremental/incremental_errors.py                                       |    11 |     0 |    11 |   100% |
| application_sdk/common/incremental/marker.py                                                   |     5 |     0 |     5 |   100% |
| application_sdk/common/incremental/models.py                                                   |    10 |     0 |    10 |   100% |
| application_sdk/common/incremental/column_extraction/__init__.py                               |     1 |     0 |     1 |   100% |
| application_sdk/common/incremental/column_extraction/analysis.py                               |     3 |     0 |     3 |   100% |
| application_sdk/common/incremental/column_extraction/backfill.py                               |     3 |     0 |     3 |   100% |
| application_sdk/common/incremental/state/__init__.py                                           |     1 |     1 |     0 |     0% |
| application_sdk/common/incremental/state/incremental_diff.py                                   |     8 |     0 |     8 |   100% |
| application_sdk/common/incremental/state/state_reader.py                                       |     2 |     0 |     2 |   100% |
| application_sdk/common/incremental/state/state_writer.py                                       |    10 |     0 |    10 |   100% |
| application_sdk/common/incremental/state/table_scope.py                                        |     8 |     0 |     8 |   100% |
| application_sdk/common/incremental/storage/__init__.py                                         |     1 |     1 |     0 |     0% |
| application_sdk/common/incremental/storage/duckdb_utils.py                                     |    12 |     2 |    10 |    83% |
| application_sdk/common/incremental/storage/rocksdb_utils.py                                    |     3 |     0 |     3 |   100% |
| application_sdk/contracts/__init__.py                                                          |     1 |     0 |     1 |   100% |
| application_sdk/contracts/base.py                                                              |    37 |     7 |    30 |    81% |
| application_sdk/contracts/cleanup.py                                                           |     5 |     0 |     5 |   100% |
| application_sdk/contracts/compat.py                                                            |     9 |     1 |     8 |    89% |
| application_sdk/contracts/events.py                                                            |    12 |     0 |    12 |   100% |
| application_sdk/contracts/storage.py                                                           |     6 |     1 |     5 |    83% |
| application_sdk/contracts/types.py                                                             |    15 |     0 |    15 |   100% |
| application_sdk/contracts/types_errors.py                                                      |     2 |     0 |     2 |   100% |
| application_sdk/credentials/__init__.py                                                        |     1 |     0 |     1 |   100% |
| application_sdk/credentials/agent.py                                                           |    13 |     3 |    10 |    77% |
| application_sdk/credentials/atlan.py                                                           |    12 |     6 |     6 |    50% |
| application_sdk/credentials/atlan_client.py                                                    |     6 |     0 |     6 |   100% |
| application_sdk/credentials/errors.py                                                          |    20 |    12 |     8 |    40% |
| application_sdk/credentials/git.py                                                             |     9 |     6 |     3 |    33% |
| application_sdk/credentials/ingress.py                                                         |     8 |     0 |     8 |   100% |
| application_sdk/credentials/oauth.py                                                           |    13 |     2 |    11 |    85% |
| application_sdk/credentials/ref.py                                                             |    17 |     1 |    16 |    94% |
| application_sdk/credentials/registry.py                                                        |    11 |     3 |     8 |    73% |
| application_sdk/credentials/resolver.py                                                        |    11 |     4 |     7 |    64% |
| application_sdk/credentials/spec.py                                                            |     6 |     1 |     5 |    83% |
| application_sdk/credentials/types.py                                                           |    35 |    17 |    18 |    51% |
| application_sdk/credentials/utils.py                                                           |     4 |     1 |     3 |    75% |
| application_sdk/dev/__init__.py                                                                |     1 |     0 |     1 |   100% |
| application_sdk/dev/_dapr.py                                                                   |    11 |     2 |     9 |    82% |
| application_sdk/dev/_dapr_errors.py                                                            |     7 |     6 |     1 |    14% |
| application_sdk/dev/_embedded.py                                                               |     3 |     0 |     3 |   100% |
| application_sdk/errors/__init__.py                                                             |     4 |     1 |     3 |    75% |
| application_sdk/errors/base.py                                                                 |    10 |     2 |     8 |    80% |
| application_sdk/errors/categories.py                                                           |     3 |     0 |     3 |   100% |
| application_sdk/errors/leaves.py                                                               |    22 |     8 |    14 |    64% |
| application_sdk/errors/wire.py                                                                 |     4 |     1 |     3 |    75% |
| application_sdk/execution/__init__.py                                                          |     1 |     0 |     1 |   100% |
| application_sdk/execution/decorators.py                                                        |     3 |     2 |     1 |    33% |
| application_sdk/execution/errors.py                                                            |     2 |     0 |     2 |   100% |
| application_sdk/execution/heartbeat.py                                                         |    17 |     2 |    15 |    88% |
| application_sdk/execution/progress.py                                                          |     6 |     0 |     6 |   100% |
| application_sdk/execution/progress_telemetry.py                                                |     7 |     1 |     6 |    86% |
| application_sdk/execution/retry.py                                                             |     9 |     0 |     9 |   100% |
| application_sdk/execution/run_length.py                                                        |     7 |     1 |     6 |    86% |
| application_sdk/execution/sandbox.py                                                           |     4 |     0 |     4 |   100% |
| application_sdk/execution/settings.py                                                          |     9 |     2 |     7 |    78% |
| application_sdk/execution/shutdown.py                                                          |     4 |     0 |     4 |   100% |
| application_sdk/execution/_temporal/__init__.py                                                |     1 |     1 |     0 |     0% |
| application_sdk/execution/_temporal/_activity_errors.py                                        |     8 |     0 |     8 |   100% |
| application_sdk/execution/_temporal/_backend_errors.py                                         |     6 |     4 |     2 |    33% |
| application_sdk/execution/_temporal/_lock_errors.py                                            |     5 |     0 |     5 |   100% |
| application_sdk/execution/_temporal/activities.py                                              |    11 |     0 |    11 |   100% |
| application_sdk/execution/_temporal/activity_utils.py                                          |     6 |     0 |     6 |   100% |
| application_sdk/execution/_temporal/auth.py                                                    |    16 |     0 |    16 |   100% |
| application_sdk/execution/_temporal/backend.py                                                 |    16 |     1 |    15 |    94% |
| application_sdk/execution/_temporal/converter.py                                               |     3 |     0 |     3 |   100% |
| application_sdk/execution/_temporal/eviction_retry.py                                          |     3 |     0 |     3 |   100% |
| application_sdk/execution/_temporal/lock_activities.py                                         |     3 |     0 |     3 |   100% |
| application_sdk/execution/_temporal/poll_state.py                                              |     7 |     1 |     6 |    86% |
| application_sdk/execution/_temporal/preflight_gate.py                                          |    39 |     4 |    35 |    90% |
| application_sdk/execution/_temporal/sdr.py                                                     |    17 |     7 |    10 |    59% |
| application_sdk/execution/_temporal/worker.py                                                  |    17 |     6 |    11 |    65% |
| application_sdk/execution/_temporal/workflows.py                                               |     3 |     0 |     3 |   100% |
| application_sdk/execution/_temporal/interceptors/__init__.py                                   |     1 |     0 |     1 |   100% |
| application_sdk/execution/_temporal/interceptors/events.py                                     |    13 |     0 |    13 |   100% |
| application_sdk/execution/_temporal/interceptors/liveness.py                                   |    11 |     9 |     2 |    18% |
| application_sdk/execution/_temporal/interceptors/lock.py                                       |    10 |     2 |     8 |    80% |
| application_sdk/execution/_temporal/interceptors/log.py                                        |    22 |    12 |    10 |    45% |
| application_sdk/execution/_temporal/interceptors/metrics.py                                    |    18 |    15 |     3 |    17% |
| application_sdk/execution/_temporal/interceptors/outputs.py                                    |     9 |     0 |     9 |   100% |
| application_sdk/execution/_temporal/interceptors/sizing.py                                     |    10 |     6 |     4 |    40% |
| application_sdk/execution/_temporal/interceptors/trace.py                                      |     6 |     4 |     2 |    33% |
| application_sdk/handler/__init__.py                                                            |     1 |     0 |     1 |   100% |
| application_sdk/handler/base.py                                                                |    14 |     3 |    11 |    79% |
| application_sdk/handler/context.py                                                             |    18 |     5 |    13 |    72% |
| application_sdk/handler/contracts.py                                                           |    40 |     6 |    34 |    85% |
| application_sdk/handler/manifest.py                                                            |     5 |     0 |     5 |   100% |
| application_sdk/handler/service.py                                                             |    65 |    23 |    42 |    65% |
| application_sdk/handler/service_errors.py                                                      |     4 |     0 |     4 |   100% |
| application_sdk/infrastructure/__init__.py                                                     |     1 |     0 |     1 |   100% |
| application_sdk/infrastructure/_secret_utils.py                                                |     2 |     0 |     2 |   100% |
| application_sdk/infrastructure/bindings.py                                                     |    16 |     3 |    13 |    81% |
| application_sdk/infrastructure/capacity.py                                                     |    11 |     0 |    11 |   100% |
| application_sdk/infrastructure/context.py                                                      |     6 |     0 |     6 |   100% |
| application_sdk/infrastructure/credential_vault.py                                             |     7 |     3 |     4 |    57% |
| application_sdk/infrastructure/pubsub.py                                                       |    13 |     3 |    10 |    77% |
| application_sdk/infrastructure/secrets.py                                                      |    25 |     8 |    17 |    68% |
| application_sdk/infrastructure/state.py                                                        |    10 |     7 |     3 |    30% |
| application_sdk/infrastructure/_dapr/__init__.py                                               |     1 |     0 |     1 |   100% |
| application_sdk/infrastructure/_dapr/_dapr_errors.py                                           |     3 |     0 |     3 |   100% |
| application_sdk/infrastructure/_dapr/client.py                                                 |    31 |     4 |    27 |    87% |
| application_sdk/infrastructure/_dapr/credential_vault.py                                       |    18 |     7 |    11 |    61% |
| application_sdk/infrastructure/_dapr/http.py                                                   |    22 |    14 |     8 |    36% |
| application_sdk/infrastructure/_redis/__init__.py                                              |     1 |     0 |     1 |   100% |
| application_sdk/infrastructure/_redis/capacity.py                                              |     9 |     4 |     5 |    56% |
| application_sdk/observability/__init__.py                                                      |     1 |     1 |     0 |     0% |
| application_sdk/observability/_objectstore_metric_exporter.py                                  |    14 |     8 |     6 |    43% |
| application_sdk/observability/_objectstore_metric_reader.py                                    |     2 |     0 |     2 |   100% |
| application_sdk/observability/_prometheus_enrichment.py                                        |     6 |     3 |     3 |    50% |
| application_sdk/observability/cgroup.py                                                        |    20 |     1 |    19 |    95% |
| application_sdk/observability/context.py                                                       |     6 |     0 |     6 |   100% |
| application_sdk/observability/correlation.py                                                   |     6 |     0 |     6 |   100% |
| application_sdk/observability/dapr_log_forwarder.py                                            |    14 |     4 |    10 |    71% |
| application_sdk/observability/events.py                                                        |     1 |     0 |     1 |   100% |
| application_sdk/observability/logger_adaptor.py                                                |    56 |    10 |    46 |    82% |
| application_sdk/observability/logger_adaptor_errors.py                                         |     2 |     0 |     2 |   100% |
| application_sdk/observability/metrics.py                                                       |     8 |     6 |     2 |    25% |
| application_sdk/observability/metrics_adaptor.py                                               |    13 |     2 |    11 |    85% |
| application_sdk/observability/models.py                                                        |     6 |     0 |     6 |   100% |
| application_sdk/observability/observability.py                                                 |    22 |     4 |    18 |    82% |
| application_sdk/observability/pushgateway.py                                                   |    16 |    11 |     5 |    31% |
| application_sdk/observability/pushgateway_errors.py                                            |     3 |     0 |     3 |   100% |
| application_sdk/observability/resource_sampler.py                                              |     6 |     0 |     6 |   100% |
| application_sdk/observability/segment_client.py                                                |    15 |     1 |    14 |    93% |
| application_sdk/observability/sizing.py                                                        |    16 |     7 |     9 |    56% |
| application_sdk/observability/sizing_census.py                                                 |     8 |     3 |     5 |    62% |
| application_sdk/observability/sizing_inputs.py                                                 |    13 |     3 |    10 |    77% |
| application_sdk/observability/sizing_sink.py                                                   |    13 |     2 |    11 |    85% |
| application_sdk/observability/trace_context.py                                                 |     2 |     0 |     2 |   100% |
| application_sdk/observability/traces_adaptor.py                                                |    15 |     1 |    14 |    93% |
| application_sdk/observability/utils.py                                                         |     8 |     1 |     7 |    88% |
| application_sdk/observability/decorators/observability_decorator.py                            |     7 |     4 |     3 |    43% |
| application_sdk/outputs/__init__.py                                                            |     2 |     0 |     2 |   100% |
| application_sdk/outputs/collector.py                                                           |     9 |     0 |     9 |   100% |
| application_sdk/outputs/models.py                                                              |     3 |     0 |     3 |   100% |
| application_sdk/server/__init__.py                                                             |     1 |     0 |     1 |   100% |
| application_sdk/server/health.py                                                               |    24 |     0 |    24 |   100% |
| application_sdk/server/fastapi/models.py                                                       |    21 |    17 |     4 |    19% |
| application_sdk/server/fastapi/utils.py                                                        |     5 |     0 |     5 |   100% |
| application_sdk/server/mcp/__init__.py                                                         |     2 |     2 |     0 |     0% |
| application_sdk/server/mcp/decorators.py                                                       |     3 |     1 |     2 |    67% |
| application_sdk/server/mcp/models.py                                                           |     2 |     2 |     0 |     0% |
| application_sdk/server/mcp/server.py                                                           |     7 |     1 |     6 |    86% |
| application_sdk/server/middleware/__init__.py                                                  |     1 |     0 |     1 |   100% |
| application_sdk/server/middleware/_constants.py                                                |     1 |     0 |     1 |   100% |
| application_sdk/server/middleware/log.py                                                       |     4 |     3 |     1 |    25% |
| application_sdk/storage/__init__.py                                                            |     1 |     0 |     1 |   100% |
| application_sdk/storage/_concurrency.py                                                        |     3 |     1 |     2 |    67% |
| application_sdk/storage/_credential_providers.py                                               |     6 |     0 |     6 |   100% |
| application_sdk/storage/_locks.py                                                              |     5 |     1 |     4 |    80% |
| application_sdk/storage/_obstore_config.py                                                     |    13 |     0 |    13 |   100% |
| application_sdk/storage/_telemetry.py                                                          |     5 |     0 |     5 |   100% |
| application_sdk/storage/batch.py                                                               |    17 |     4 |    13 |    76% |
| application_sdk/storage/binding.py                                                             |    27 |     1 |    26 |    96% |
| application_sdk/storage/chunked.py                                                             |    12 |     0 |    12 |   100% |
| application_sdk/storage/cloud.py                                                               |    24 |     6 |    18 |    75% |
| application_sdk/storage/errors.py                                                              |    38 |    25 |    13 |    34% |
| application_sdk/storage/factory.py                                                             |     3 |     0 |     3 |   100% |
| application_sdk/storage/file_ref_sync.py                                                       |    15 |     3 |    12 |    80% |
| application_sdk/storage/integrity.py                                                           |    14 |     0 |    14 |   100% |
| application_sdk/storage/ops.py                                                                 |    29 |     1 |    28 |    97% |
| application_sdk/storage/preflight.py                                                           |    13 |     0 |    13 |   100% |
| application_sdk/storage/reference.py                                                           |    11 |     1 |    10 |    91% |
| application_sdk/storage/rolling.py                                                             |    33 |    12 |    21 |    64% |
| application_sdk/storage/rolling_errors.py                                                      |     4 |     0 |     4 |   100% |
| application_sdk/storage/transfer.py                                                            |    15 |     3 |    12 |    80% |
| application_sdk/storage/formats/__init__.py                                                    |    32 |     0 |    32 |   100% |
| application_sdk/storage/formats/format_errors.py                                               |    16 |     0 |    16 |   100% |
| application_sdk/storage/formats/json.py                                                        |    16 |     6 |    10 |    62% |
| application_sdk/storage/formats/parquet.py                                                     |    33 |     5 |    28 |    85% |
| application_sdk/storage/formats/utils.py                                                       |    10 |     2 |     8 |    80% |
| application_sdk/templates/__init__.py                                                          |     2 |     1 |     1 |    50% |
| application_sdk/templates/_template_errors.py                                                  |    10 |     0 |    10 |   100% |
| application_sdk/templates/base_metadata_extractor.py                                           |     4 |     1 |     3 |    75% |
| application_sdk/templates/incremental_sql_metadata_extractor.py                                |    19 |     2 |    17 |    89% |
| application_sdk/templates/sql_app.py                                                           |    47 |     6 |    41 |    87% |
| application_sdk/templates/sql_app_errors.py                                                    |     8 |     0 |     8 |   100% |
| application_sdk/templates/sql_metadata_extractor.py                                            |    14 |     1 |    13 |    93% |
| application_sdk/templates/sql_query_extractor.py                                               |     6 |     1 |     5 |    83% |
| application_sdk/templates/contracts/__init__.py                                                |     1 |     0 |     1 |   100% |
| application_sdk/templates/contracts/base_metadata_extraction.py                                |     3 |     0 |     3 |   100% |
| application_sdk/templates/contracts/incremental_sql.py                                         |    26 |     5 |    21 |    81% |
| application_sdk/templates/contracts/sql_metadata.py                                            |    33 |     8 |    25 |    76% |
| application_sdk/templates/contracts/sql_query.py                                               |     7 |     0 |     7 |   100% |
| application_sdk/test_utils/integration/__init__.py                                             |     1 |     1 |     0 |     0% |
| application_sdk/testing/__init__.py                                                            |     2 |     0 |     2 |   100% |
| application_sdk/testing/_errors.py                                                             |     4 |     0 |     4 |   100% |
| application_sdk/testing/_mustache.py                                                           |     2 |     0 |     2 |   100% |
| application_sdk/testing/fake_source.py                                                         |    58 |    16 |    42 |    72% |
| application_sdk/testing/fixtures.py                                                            |    11 |     0 |    11 |   100% |
| application_sdk/testing/golden.py                                                              |    26 |    10 |    16 |    62% |
| application_sdk/testing/mocks.py                                                               |    68 |    17 |    51 |    75% |
| application_sdk/testing/volatile_fields.py                                                     |     1 |     0 |     1 |   100% |
| application_sdk/testing/e2e/__init__.py                                                        |     1 |     0 |     1 |   100% |
| application_sdk/testing/e2e/_errors.py                                                         |    13 |     0 |    13 |   100% |
| application_sdk/testing/e2e/_manifest_identity.py                                              |    11 |     0 |    11 |   100% |
| application_sdk/testing/e2e/base.py                                                            |   102 |     6 |    96 |    94% |
| application_sdk/testing/e2e/client.py                                                          |    29 |     7 |    22 |    76% |
| application_sdk/testing/e2e/config.py                                                          |     5 |     0 |     5 |   100% |
| application_sdk/testing/e2e/credential.py                                                      |     2 |     0 |     2 |   100% |
| application_sdk/testing/e2e/logs.py                                                            |     9 |     1 |     8 |    89% |
| application_sdk/testing/e2e/payload.py                                                         |    11 |     0 |    11 |   100% |
| application_sdk/testing/e2e/portforward.py                                                     |     1 |     0 |     1 |   100% |
| application_sdk/testing/e2e/sql_app.py                                                         |    10 |     0 |    10 |   100% |
| application_sdk/testing/e2e/substitutions.py                                                   |     3 |     0 |     3 |   100% |
| application_sdk/testing/e2e/workflows.py                                                       |     6 |     1 |     5 |    83% |
| application_sdk/testing/full_dag/__init__.py                                                   |     1 |     0 |     1 |   100% |
| application_sdk/testing/full_dag/_errors.py                                                    |     1 |     0 |     1 |   100% |
| application_sdk/testing/full_dag/base.py                                                       |    18 |     2 |    16 |    89% |
| application_sdk/testing/full_dag/client.py                                                     |     1 |     0 |     1 |   100% |
| application_sdk/testing/full_dag/payload.py                                                    |     8 |     0 |     8 |   100% |
| application_sdk/testing/full_dag/sql_app.py                                                    |     6 |     1 |     5 |    83% |
| application_sdk/testing/harness/__init__.py                                                    |     1 |     0 |     1 |   100% |
| application_sdk/testing/harness/_errors.py                                                     |    13 |     0 |    13 |   100% |
| application_sdk/testing/harness/_poll.py                                                       |    15 |     0 |    15 |   100% |
| application_sdk/testing/harness/bridge.py                                                      |     5 |     0 |     5 |   100% |
| application_sdk/testing/harness/budgets.py                                                     |     6 |     0 |     6 |   100% |
| application_sdk/testing/harness/evidence.py                                                    |    15 |     1 |    14 |    93% |
| application_sdk/testing/harness/expectations.py                                                |     9 |     0 |     9 |   100% |
| application_sdk/testing/harness/fixtures.py                                                    |    43 |     4 |    39 |    91% |
| application_sdk/testing/harness/identity.py                                                    |    11 |     1 |    10 |    91% |
| application_sdk/testing/harness/outcome.py                                                     |    14 |     0 |    14 |   100% |
| application_sdk/testing/harness/preconditions.py                                               |    19 |     4 |    15 |    79% |
| application_sdk/testing/harness/spec.py                                                        |     2 |     0 |     2 |   100% |
| application_sdk/testing/harness/substrate.py                                                   |     3 |     0 |     3 |   100% |
| application_sdk/testing/harness/teardown.py                                                    |     8 |     0 |     8 |   100% |
| application_sdk/testing/harness/waiting.py                                                     |     8 |     0 |     8 |   100% |
| application_sdk/testing/harness/atlas/__init__.py                                              |    19 |     4 |    15 |    79% |
| application_sdk/testing/harness/atlas/_errors.py                                               |     2 |     0 |     2 |   100% |
| application_sdk/testing/harness/automation_engine/__init__.py                                  |     1 |     0 |     1 |   100% |
| application_sdk/testing/harness/automation_engine/_errors.py                                   |    10 |     0 |    10 |   100% |
| application_sdk/testing/harness/automation_engine/client.py                                    |    34 |     4 |    30 |    88% |
| application_sdk/testing/harness/automation_engine/retry.py                                     |    17 |     1 |    16 |    94% |
| application_sdk/testing/harness/automation_engine/wire.py                                      |    24 |     2 |    22 |    92% |
| application_sdk/testing/harness/cluster/__init__.py                                            |     1 |     0 |     1 |   100% |
| application_sdk/testing/harness/cluster/_errors.py                                             |     4 |     0 |     4 |   100% |
| application_sdk/testing/harness/cluster/_portforward.py                                        |    15 |     2 |    13 |    87% |
| application_sdk/testing/harness/cluster/_protocols.py                                          |     9 |     0 |     9 |   100% |
| application_sdk/testing/harness/cluster/_states.py                                             |     9 |     0 |     9 |   100% |
| application_sdk/testing/harness/cluster/kube.py                                                |    50 |     7 |    43 |    86% |
| application_sdk/testing/harness/starters/__init__.py                                           |     2 |     0 |     2 |   100% |
| application_sdk/testing/harness/starters/_ae.py                                                |     4 |     0 |     4 |   100% |
| application_sdk/testing/harness/starters/_errors.py                                            |     4 |     0 |     4 |   100% |
| application_sdk/testing/harness/starters/_queue.py                                             |     3 |     0 |     3 |   100% |
| application_sdk/testing/harness/starters/_specs.py                                             |    12 |     0 |    12 |   100% |
| application_sdk/testing/harness/temporal/__init__.py                                           |     1 |     0 |     1 |   100% |
| application_sdk/testing/harness/temporal/_errors.py                                            |     5 |     0 |     5 |   100% |
| application_sdk/testing/harness/temporal/_protocols.py                                         |     4 |     0 |     4 |   100% |
| application_sdk/testing/harness/temporal/_states.py                                            |     6 |     0 |     6 |   100% |
| application_sdk/testing/harness/temporal/client.py                                             |    23 |     1 |    22 |    96% |
| application_sdk/testing/hypothesis/__init__.py                                                 |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/__init__.py                                      |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/sql_client.py                                    |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/clients/__init__.py                              |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/clients/sql.py                                   |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/common/__init__.py                               |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/common/logger.py                                 |     3 |     0 |     3 |   100% |
| application_sdk/testing/hypothesis/strategies/handlers/__init__.py                             |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/handlers/sql/__init__.py                         |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/handlers/sql/sql_metadata.py                     |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/handlers/sql/sql_preflight.py                    |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/inputs/__init__.py                               |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/inputs/json_input.py                             |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/inputs/parquet_input.py                          |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/outputs/__init__.py                              |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/outputs/json_output.py                           |     2 |     1 |     1 |    50% |
| application_sdk/testing/hypothesis/strategies/outputs/statestore.py                            |     3 |     1 |     2 |    67% |
| application_sdk/testing/hypothesis/strategies/server/__init__.py                               |     1 |     1 |     0 |     0% |
| application_sdk/testing/hypothesis/strategies/server/fastapi/__init__.py                       |     1 |     1 |     0 |     0% |
| application_sdk/testing/integration/__init__.py                                                |     3 |     1 |     2 |    67% |
| application_sdk/testing/integration/_errors.py                                                 |    15 |     0 |    15 |   100% |
| application_sdk/testing/integration/assertions.py                                              |    55 |    25 |    30 |    55% |
| application_sdk/testing/integration/client.py                                                  |    18 |     0 |    18 |   100% |
| application_sdk/testing/integration/comparison.py                                              |    12 |     1 |    11 |    92% |
| application_sdk/testing/integration/corpus.py                                                  |    25 |     7 |    18 |    72% |
| application_sdk/testing/integration/fixtures.py                                                |    23 |     1 |    22 |    96% |
| application_sdk/testing/integration/lazy.py                                                    |    10 |     0 |    10 |   100% |
| application_sdk/testing/integration/models.py                                                  |     9 |     0 |     9 |   100% |
| application_sdk/testing/integration/runner.py                                                  |    27 |     2 |    25 |    93% |
| application_sdk/testing/integration/source.py                                                  |     8 |     0 |     8 |   100% |
| application_sdk/testing/integration/validation.py                                              |     7 |     0 |     7 |   100% |
| application_sdk/testing/parity/__init__.py                                                     |     1 |     0 |     1 |   100% |
| application_sdk/testing/parity/__main__.py                                                     |     2 |     1 |     1 |    50% |
| application_sdk/testing/parity/comparator.py                                                   |     8 |     0 |     8 |   100% |
| application_sdk/testing/parity/models.py                                                       |     5 |     1 |     4 |    80% |
| application_sdk/testing/parity/report.py                                                       |     4 |     0 |     4 |   100% |
| application_sdk/testing/scale_data_generator/__init__.py                                       |     1 |     0 |     1 |   100% |
| application_sdk/testing/scale_data_generator/config_loader.py                                  |    11 |     4 |     7 |    64% |
| application_sdk/testing/scale_data_generator/data_generator.py                                 |    10 |     3 |     7 |    70% |
| application_sdk/testing/scale_data_generator/driver.py                                         |     3 |     3 |     0 |     0% |
| application_sdk/testing/scale_data_generator/output_handler/__init__.py                        |     1 |     1 |     0 |     0% |
| application_sdk/testing/scale_data_generator/output_handler/base.py                            |     7 |     3 |     4 |    57% |
| application_sdk/testing/scale_data_generator/output_handler/csv_handler.py                     |     6 |     6 |     0 |     0% |
| application_sdk/testing/scale_data_generator/output_handler/json_handler.py                    |     5 |     5 |     0 |     0% |
| application_sdk/testing/scale_data_generator/output_handler/parquet_handler.py                 |     6 |     6 |     0 |     0% |
| application_sdk/testing/sdr/__init__.py                                                        |     1 |     0 |     1 |   100% |
| application_sdk/testing/sdr/base.py                                                            |    14 |     3 |    11 |    79% |
| application_sdk/tools/__init__.py                                                              |     1 |     1 |     0 |     0% |
| application_sdk/tools/provision_credentials.py                                                 |     2 |     1 |     1 |    50% |
| application_sdk/transformers/__init__.py                                                       |     4 |     2 |     2 |    50% |
| application_sdk/transformers/errors.py                                                         |     2 |     1 |     1 |    50% |
| application_sdk/transformers/atlas/__init__.py                                                 |     6 |     1 |     5 |    83% |
| application_sdk/transformers/atlas/errors.py                                                   |     8 |     7 |     1 |    12% |
| application_sdk/transformers/atlas/sql.py                                                      |    25 |     4 |    21 |    84% |
| application_sdk/transformers/common/__init__.py                                                |     1 |     1 |     0 |     0% |
| application_sdk/transformers/common/last_sync.py                                               |     5 |     0 |     5 |   100% |
| application_sdk/transformers/common/utils.py                                                   |     6 |     0 |     6 |   100% |
| application_sdk/transformers/query/__init__.py                                                 |    19 |     2 |    17 |    89% |
| application_sdk/transformers/query/errors.py                                                   |     5 |     3 |     2 |    40% |
| application_sdk/validation/__init__.py                                                         |     1 |     0 |     1 |   100% |
| application_sdk/validation/artifacts.py                                                        |    24 |     1 |    23 |    96% |
| application_sdk/validation/assets.py                                                           |    23 |     2 |    21 |    91% |
| application_sdk/validation/interceptor.py                                                      |    15 |     0 |    15 |   100% |
| application_sdk/validation/ndjson.py                                                           |    22 |     4 |    18 |    82% |
| application_sdk/validation/parquet.py                                                          |    15 |     0 |    15 |   100% |
| application_sdk/validation/protocols.py                                                        |     9 |     0 |     9 |   100% |
| application_sdk/validation/sources.py                                                          |    15 |     0 |    15 |   100% |
| application_sdk/validation/wrapper.py                                                          |     8 |     0 |     8 |   100% |
| contract-toolkit/examples/agent-e2e/app/generated/__init__.py                                  |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/agent-e2e/app/generated/_e2e_base.py                                 |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/agent-e2e/app/generated/_e2e_credential.py                           |     3 |     3 |     0 |     0% |
| contract-toolkit/examples/agent-e2e/app/generated/_e2e_substitutions.py                        |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/agent-e2e/app/generated/_input.py                                    |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/artifact-schemas/app/generated/__init__.py                           |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/artifact-schemas/app/generated/_e2e_base.py                          |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/artifact-schemas/app/generated/_e2e_substitutions.py                 |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/artifact-schemas/app/generated/_input.py                             |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/behind-the-scenes/app/generated/__init__.py                          |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/behind-the-scenes/app/generated/_e2e_base.py                         |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/behind-the-scenes/app/generated/_e2e_substitutions.py                |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/behind-the-scenes/app/generated/_input.py                            |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/crawler/__init__.py                             |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/crawler/_e2e_base.py                            |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/crawler/_e2e_credential.py                      |     3 |     3 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/crawler/_input.py                               |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/miner/__init__.py                               |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/miner/_e2e_base.py                              |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/miner/_e2e_substitutions.py                     |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/bundle/app/generated/miner/_input.py                                 |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/connection-ref/app/generated/__init__.py                             |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/connection-ref/app/generated/_e2e_base.py                            |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/connection-ref/app/generated/_input.py                               |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/deploy/app/generated/__init__.py                                     |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/deploy/app/generated/_e2e_base.py                                    |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/deploy/app/generated/_e2e_substitutions.py                           |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/deploy/app/generated/_input.py                                       |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/fanin/app/generated/__init__.py                                      |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/fanin/app/generated/_e2e_base.py                                     |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/fanin/app/generated/_e2e_credential.py                               |     3 |     3 |     0 |     0% |
| contract-toolkit/examples/fanin/app/generated/_input.py                                        |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/__init__.py                                       |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/_e2e_base.py                                      |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/_e2e_credential.py                                |     3 |     3 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/_e2e_substitutions.py                             |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/full/app/generated/_input.py                                         |     3 |     3 |     0 |     0% |
| contract-toolkit/examples/minimal/app/generated/__init__.py                                    |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/minimal/app/generated/_e2e_base.py                                   |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/minimal/app/generated/_e2e_substitutions.py                          |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/minimal/app/generated/_input.py                                      |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/pools/app/generated/__init__.py                                      |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/pools/app/generated/_e2e_base.py                                     |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/pools/app/generated/_e2e_substitutions.py                            |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/pools/app/generated/_input.py                                        |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/__init__.py                           |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/_e2e_base.py                          |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/_e2e_credential.py                    |     3 |     3 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/_e2e_substitutions.py                 |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/publish-controls/app/generated/_input.py                             |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/scheduled/app/generated/__init__.py                                  |     1 |     1 |     0 |     0% |
| contract-toolkit/examples/scheduled/app/generated/_e2e_base.py                                 |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/scheduled/app/generated/_e2e_substitutions.py                        |     2 |     2 |     0 |     0% |
| contract-toolkit/examples/scheduled/app/generated/_input.py                                    |     2 |     2 |     0 |     0% |
| contract-toolkit/scripts/test-sdk-import.py                                                    |     5 |     1 |     4 |    80% |
| packages/conformance/conformance/__init__.py                                                   |     1 |     0 |     1 |   100% |
| packages/conformance/conformance/cli.py                                                        |    14 |    12 |     2 |    14% |
| packages/conformance/conformance/bootstrap/__init__.py                                         |     1 |     0 |     1 |   100% |
| packages/conformance/conformance/bootstrap/args.py                                             |     5 |     0 |     5 |   100% |
| packages/conformance/conformance/bootstrap/autodetect.py                                       |    10 |     0 |    10 |   100% |
| packages/conformance/conformance/bootstrap/command.py                                          |    14 |     1 |    13 |    93% |
| packages/conformance/conformance/bootstrap/extract.py                                          |    24 |     0 |    24 |   100% |
| packages/conformance/conformance/bootstrap/render.py                                           |     3 |     0 |     3 |   100% |
| packages/conformance/conformance/bootstrap/templates/build_conformance_args.py                 |     3 |     0 |     3 |   100% |
| packages/conformance/conformance/bootstrap/templates/probe_code_scanning.py                    |     6 |     0 |     6 |   100% |
| packages/conformance/conformance/renovate/__init__.py                                          |     1 |     0 |     1 |   100% |
| packages/conformance/conformance/renovate/classify.py                                          |    17 |     1 |    16 |    94% |
| packages/conformance/conformance/renovate/models.py                                            |    11 |     2 |     9 |    82% |
| packages/conformance/conformance/renovate/scan.py                                              |    11 |     6 |     5 |    45% |
| packages/conformance/conformance/scorecard/__init__.py                                         |     1 |     0 |     1 |   100% |
| packages/conformance/conformance/scorecard/cli.py                                              |     7 |     3 |     4 |    57% |
| packages/conformance/conformance/scorecard/compute.py                                          |     9 |     3 |     6 |    67% |
| packages/conformance/conformance/scorecard/readers.py                                          |    11 |     0 |    11 |   100% |
| packages/conformance/conformance/scorecard/rubric.py                                           |    10 |     5 |     5 |    50% |
| packages/conformance/conformance/scorecard/schema.py                                           |    15 |     2 |    13 |    87% |
| packages/conformance/conformance/scorecard/validate.py                                         |     4 |     1 |     3 |    75% |
| packages/conformance/conformance/suite/__init__.py                                             |     1 |     0 |     1 |   100% |
| packages/conformance/conformance/suite/runner.py                                               |    10 |     2 |     8 |    80% |
| packages/conformance/conformance/suite/checks/__init__.py                                      |     1 |     1 |     0 |     0% |
| packages/conformance/conformance/suite/checks/_entrypoint_contract_classes.py                  |     7 |     0 |     7 |   100% |
| packages/conformance/conformance/suite/checks/_entrypoint_contract_fields.py                   |    13 |     4 |     9 |    69% |
| packages/conformance/conformance/suite/checks/_sdk_contract_mixins.py                          |     2 |     0 |     2 |   100% |
| packages/conformance/conformance/suite/checks/_toolkit_baseline.py                             |     6 |     1 |     5 |    83% |
| packages/conformance/conformance/suite/checks/_version.py                

This message was truncated. Download full message

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

📦 Trivy Vulnerability Scan Results

Schema Version Created At Artifact Type
2 2026-09-01T23:17:00.342920262Z . repository

Report Summary

Could not generate summary table (data length mismatch: 9 vs 8).

Scan Result Details

packages/conformance/uv.lock
uv.lock

@github-actions

github-actions Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

📦 Trivy Secret Scan Results

Schema Version Created At Artifact Type
2 2026-09-01T23:17:04.623231533Z . repository

Report Summary

Could not generate summary table (data length mismatch: 9 vs 8).

Scan Result Details

packages/conformance/uv.lock
uv.lock

@atlan-app-fleet

atlan-app-fleet Bot commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

☂️ Code Coverage

current status: ✅

Overall Coverage

Statements Covered Coverage Threshold Status
28114 26289 94% 0% 🟢

New Files

No new covered files...

Modified Files

No covered modified files...

updated for commit: 5a10c0b by action🐍

@cmgrote cmgrote left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Verdict: additive in mechanism, but 4 defects — 2 of them blocking

First, the reassuring part. This is additive to the recent preflight work. It touches zero files that #3521 or the last-48h merges (8f65ab4, a57bfce, 22d2095, c3ade68) changed in preflight_gate.py. The only merge conflict — against both main and #3521 — is packages/conformance/conformance/docs/rules/prescriptions.md, which is auto-generated (gen-rule-docs regenerates it). That's noise, not overlap.

Two other things check out, so nobody needs to re-litigate them:

  • RateLimitedError really is the only SDK leaf with a gate-broken category and audience=USER. The "eight of nine" claim in the rule docs holds.
  • No SDK code branches on audience — it is wire/telemetry metadata only. So the flip changes attribution and the customer-facing voice, not control flow.

Now the problems.


1. (blocking) P041 is a retired ID, and the package forbids reusing it

packages/conformance/conformance/suite/rules/prescriptions.py:9-16 states the policy explicitly:

Rule-id stability (non-migration policy)
P-ids are a permanent public contract: each is exposed in SARIF help_uri and referenced by inline # conformance: ignore[Pxxx] suppressions across the fleet. A P-id therefore never migrates and never changes … the original P-id is never reused or reassigned.

P041 was a live SDR rule until it was retired 9 days ago in ca5861749 ("fix(conformance): remove obsolete P041 rule", #3367). Reassigning it means:

  • any # conformance: ignore[P041] still sitting in a fleet app repo, written for the old SDR rule, now silently suppresses this new and unrelated rule;
  • SARIF history and any dashboard keyed on rule id conflates two different rules.

Fix: take the next free id (P052+) and leave P041 retired.


2. (blocking) The checker fires 4 false positives on the SDK's own tree

scope=BOTH, so this runs against application_sdk/ too. I ran the PR's checker over the SDK error modules on current main:

Class P041 fires Real MRO category actually gate-broken?
errors/leaves.py::RateLimitedError yes RATE_LIMITED yes — correct hit
storage/errors.py::StorageNotFoundError yes NOT_FOUND no
storage/errors.py::StoragePermissionError yes PERMISSION no
storage/errors.py::StorageConfigError yes INVALID_INPUT no
infrastructure/secrets.py::SecretNotFoundError yes NOT_FOUND no

Verified against the real classes rather than inferred:

StorageNotFoundError    FailureCategory.NOT_FOUND      Audience.USER  gate_broken=False
StoragePermissionError  FailureCategory.PERMISSION     Audience.USER  gate_broken=False
StorageConfigError      FailureCategory.INVALID_INPUT  Audience.USER  gate_broken=False
SecretNotFoundError     FailureCategory.NOT_FOUND      Audience.USER  gate_broken=False

Cause: _gate_broken_audience.py:107 (_carries_gate_broken_category) resolves an inherited category with

return any(b in derived for b in _base_names(cls, aliases))

which ignores base order. StorageNotFoundError(NotFoundError, StorageError) takes its category from its first base (NOT_FOUND), but StorageError descends from DependencyUnavailableError, so the any() matches anyway. Same shape for the other three: a non-gate-broken first base plus a StorageError/SecretStoreError mixin.

These four are exactly the classes the rule should stay silent on — the gate does not treat them as plumbing, and USER is the right audience for a missing bucket or a bad config.

Fix: resolve the inherited category MRO-first rather than with any(). suite/checks/_entrypoint_contract_fields.py:287 already has the MRO-ordered, cycle-safe walk to model this on.

Worth noting the green Conformance / Prescriptions check does not clear this: the leg runs soft, so these four would ship as unnoticed warnings.


3. Two docs still contradict the leaves.py change

The RateLimitedError audience flip is not propagated to:

  • docs/adr/0013-error-hierarchy-and-failure-taxonomy.md:105 — the table row still reads USER. This ADR is the taxonomy's source of truth, so it should not be the last thing to learn about a taxonomy change.
  • docs/concepts/common.md:55 — the hierarchy tree still renders audience=USER.

4. (non-blocking) Reconcile the wording against #3521

#3521, about to merge, adds _CLIENT_FAULT_CATEGORIES (preflight_gate.py:863) containing RATE_LIMITED and CANCELLED, and emits outcome="client_fault" for them on interactive surfaces. This PR argues the same two categories are not the customer's, and bans audience=USER on them.

Both can be right — #3521's "client" is the caller of the HTTP/SDR surface, not the customer — but once both land, a 429 on an interactive surface emits outcome=client_fault next to failure.audience=APP_OWNER, and whoever reads that dashboard will have to work out that the two words mean different things. A one-line note at either definition site would settle it. No code change needed here.


Summary

1 and 2 need fixing before merge. 3 is a small follow-through in the same PR. 4 is a note to coordinate with #3521.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants