<!-- ephemeral -->

# Java Assist — Debug and SQL evidence

Install one `DebugEvidence.Sink` as the trusted `RuntimeLogSink` when building
`TeaQLRuntime`. Application diagnostics should consume `safeEvidence()`, which
contains parameterized SQL and bounded outcome metadata but never raw bind
values or interpolated `debugQuery` text.

```java
package com.doublechaintech.crmerpservice;

import io.teaql.core.DataServiceOperation;
import io.teaql.core.ExecutionMetadata;
import io.teaql.core.UserContext;
import io.teaql.runtime.RuntimeLogSink;
import java.util.ArrayList;
import java.util.EnumSet;
import java.util.List;
import java.util.Objects;

public final class DebugEvidence {
    private DebugEvidence() {}

    public record SafeSqlEvidence(
            String operation,
            String parameterizedSql,
            int parameterCount,
            long elapsedMicros,
            Integer resultCount,
            Long affectedRows,
            String resultSummary,
            List<io.teaql.core.TraceNode> traceChain,
            List<io.teaql.core.TraceNode> tracePath) {}

    public static final class Sink implements RuntimeLogSink {
        private final List<ExecutionMetadata> entries = new ArrayList<>();
        private EnumSet<DataServiceOperation> enabled =
                EnumSet.of(DataServiceOperation.QUERY, DataServiceOperation.MUTATION);

        @Override
        public synchronized void writeExecutionLog(
                UserContext context, ExecutionMetadata metadata) {
            if (enabled.contains(metadata.getOperation())) {
                entries.add(metadata);
            }
        }

        public synchronized void enableAllSqlEvidence() {
            enabled = EnumSet.of(DataServiceOperation.QUERY, DataServiceOperation.MUTATION);
            entries.clear();
        }

        public synchronized void enableSelectSqlEvidence() {
            enabled = EnumSet.of(DataServiceOperation.QUERY);
            entries.clear();
        }

        public synchronized void enableMutationSqlEvidence() {
            enabled = EnumSet.of(DataServiceOperation.MUTATION);
            entries.clear();
        }

        public synchronized void disableSqlEvidence() {
            enabled = EnumSet.noneOf(DataServiceOperation.class);
            entries.clear();
        }

        public synchronized List<SafeSqlEvidence> safeEvidence() {
            return entries.stream().map(entry -> new SafeSqlEvidence(
                    entry.getOperation().name().toLowerCase(),
                    entry.getParameterizedQuery() == null ? "" : entry.getParameterizedQuery(),
                    entry.getParameterCount(),
                    entry.getElapsedUs(),
                    entry.getResultCount(),
                    entry.getAffectedRows(),
                    entry.getResultSummary(),
                    entry.getRequestTraceChain(),
                    entry.getTracePath())).toList();
        }

        /** Trusted operator output only; contains values and must not enter telemetry or errors. */
        public synchronized List<String> diagnosticSql() {
            return entries.stream().map(ExecutionMetadata::getDebugQuery)
                    .filter(Objects::nonNull).toList();
        }
    }
}
```

Every generated query must still carry non-empty `comment(...)` and
`purpose(...)`; every mutation must carry `auditAs(...)`. Missing intent,
not-found, checker/validation, optimistic-conflict, and provider failures must
remain failures rather than being converted into empty successful results.

The runtime log formatter recognizes `TEAQL_SQL_LOG`,
`TEAQL_SQL_LOG_TABLES`, `TEAQL_AUDIT_LOG`, and
`TEAQL_AUDIT_LOG_ENTITIES`. Supported levels are `_silent`, `_summary`,
`_full`, and `_full_with_payload`. Payload logging is trusted-boundary output.

Query and mutation execution logging are both enabled by default. Configure
them independently with
`TeaQLRuntime.builder().queryExecutionLogging(false)` and
`.mutationExecutionLogging(false)`. Every `ExecutionMetadata` retains
structured comment, purpose, audit reason, business Request ancestry and physical trace,
parameterized SQL, copy-paste debug SQL, elapsed time, result count, and
affected rows. `getDebugQuery()` is operator-only output; never return it in
HTTP errors, ordinary telemetry, or safe evidence.

`getRequestTraceChain()` is the business chain; `getTracePath()` is the physical
request/relation/provider/SQL route. Legacy `getTraceChain()` means that physical
path, not business ancestry. Read the runtime's already-projected structured
fields; never infer the native Q operation from SQL, aliases or relation names.

---

## TeaQL seven-language assist contract

Apply the verified Rust semantic ceiling while using only the exact JAVA generated and
runtime APIs. Discover APIs through the generated application AGENTS.md and progressive
model-aware Assist. Do not inspect generated domain-library source.

- Do not create plurals by appending `s` or `es`; use the centralized generated plural.
- Human and non-human entities use different generated predicate vocabularies. Preserve
  forms such as “who are active” and “whose email is”; never infer them from English.
- Configure filters, projection, paging, and other query options before `purpose(...)`.
  Comment may appear anywhere in the chain. Purpose enters the executable stage; execution
  requires both values, but comment does not have to immediately precede purpose.
- Every execute/list/stream and every save accepts exactly one context argument:
  `UserContext`. Name that argument `context`, never `runtime`; data services and global
  policy are injected when the context is built. Reserve `runtime` for process-level
  runtime ownership, provider/pool setup, and module assembly.
- Tenant, merchant, identity, permissions, request policy, purpose policy, hard limit,
  and continuous-page cursor policy come only from trusted context, never dynamic JSON or TFP.
- If the required operation is absent after current entity/action and required field
  Assist, stop that path and report MISSING_ASSIST. Do not guess an API or search the
  generated library as a fallback.
- Create each application-owned source file once. After its first compile attempt,
  repair only the smallest block identified by the exact compiler or test diagnostic.
  Preserve unrelated code; do not rewrite the complete file as an error-recovery loop.
- Before a repair that would replace more than 25% of an existing application file,
  stop and report LARGE_REWRITE_REQUEST with the file, exact diagnostic, reason, and
  estimated scope. Initial creation and model-driven regeneration are not repairs.

Capability: `debug`.

- Capture purpose, comment, trace/correlation id, runtime-projected expanded masked
  SQL and its masking mode, duration, row count, provider and the native response.
- Preserve the immutable row audit event and the customizable App Audit Sink as
  separate paths. Redact credentials, tokens, connection strings, and customer data.
- Document only switches and hooks present in the selected runtime source.


## Standard OpenTelemetry module

Use the optional standard module supplied by the selected TeaQL runtime. Match
its version to the runtime dependency selected by the model and workspace;
keep local source or internal Registry overrides during development. Do not
upgrade to an unrelated public release just to enable telemetry. A runtime
without this module reports `module_unavailable`; package installation alone
does not enable export.

On a supported backend, configure these trusted process variables before startup, never
through a query, JSON or TFP payload:

```bash
export TEAQL_TELEMETRY_ENABLED=true
export TEAQL_TELEMETRY_SERVICE_NAME=payment-service
export TEAQL_TELEMETRY_OTLP_ENDPOINT=http://localhost:4318
```

Without enablement, startup reports `disabled` and all three activation variables;
no SDK export resources are created. Enabled startup reports safe effective
settings, full recording and masking. Invalid settings produce a fixed safe
diagnostic, not a claim of successful export. Never print credentials or raw
configuration values.

The module automatically records supported Q, graph mutation and physical SQL
operations as traces, logs and metrics. SQL is expanded with masked parameters;
plaintext debugging never authorizes plaintext telemetry export. Full recording
does not promise lossless delivery when bounded queues or exporters fail.
Do not add per-method spans or replace the customer's global SDK providers.

Keep schema reconciliation explicit. Run the generated ensure-schema and seed
flow through the same configured runtime to observe startup settings and audited,
idempotent seeding. Telemetry setup must not run ensure-schema implicitly.
Flush and shut down the owned pipeline at application shutdown, not per query.
Exporter failures do not change business results; durable business audit remains
an independent path.


### Java assembly

Add the optional Maven artifact `io.teaql:teaql-opentelemetry` to the application,
using the exact same version as its TeaQL runtime dependency. Keep it out of the
generated domain library's mandatory dependencies. TeaQLRuntime discovers the
module through ServiceLoader at startup; no application SDK initialization is
required. Set the three variables before starting the JVM.
