# Environment Script Packs

These scripts prepare environment-specific `spec.yaml` files and invoke the
public `tipoc init` command. They do not start `prepare`, `run`, `cleanup`,
SSH bootstrap, cloud resources, object-store cleanup, or TiUP clusters by
default.

## Script Families

| environment | entry script | intended use |
| --- | --- | --- |
| `tiup` | `scripts/env/tiup/init-attempt.sh` | Local TiUP or local object-store tests. Use `--scale 10G` or `--scale 50G` with the same script family. |
| `premium` | `scripts/env/premium/init-attempt.sh` | TiDB Cloud premium tests with replaceable cluster, S3, generation-node, and pressure-node bindings. |
| `premium/d10-a005` | `scripts/env/premium/d10-a005/README.md` | Current D10 staging premium `1T` run-operation profile with fixed four-node launch, evidence collection, SQL evidence, and Clinic metric paths. |
| `essential` | `scripts/env/essential/init-attempt.sh` | Future essential tests. The template is intentionally present before live bindings exist. |
| `dedicated` | `scripts/env/dedicated/init-attempt.sh` | Future dedicated tests. The template is intentionally present before live bindings exist. |

## Safe Render Flow

Render a local `50G` TiUP attempt without running `tipoc init`:

```bash
scripts/env/tiup/init-attempt.sh --scale 50G --out runs/local-50g/attempt-001 --render-only
```

On machines without a local S3-compatible object store, render a local-file
attempt by disabling object-store source publication and target-managed Global
Sort explicitly:

```bash
TIPOC_OBJECT_STORE_URI=none \
TIPOC_GLOBAL_SORT_URI_REF=none \
TIPOC_BR_ENABLED=false \
TIPOC_PREPARE_OPS=generate,import,add-index \
scripts/env/tiup/init-attempt.sh --scale 1G --out runs/local-1g/attempt-001 --render-only
```

After reviewing and editing `runs/local-50g/attempt-001/spec.yaml`, initialize
the attempt:

```bash
tipoc init --spec runs/local-50g/attempt-001/spec.yaml --out runs/local-50g/attempt-001 --remote-bootstrap plan
```

Or render and initialize in one step:

```bash
scripts/env/tiup/init-attempt.sh --scale 10G --out runs/local-10g/attempt-001
```

The generated attempt then exposes the normal command bundle:

```bash
runs/local-10g/attempt-001/commands/prepare.sh
runs/local-10g/attempt-001/commands/run.sh
runs/local-10g/attempt-001/commands/cleanup.sh
```

## Securities Order Lifecycle

The environment wrappers can render the complete Issue #95 order lifecycle
without hand-editing `spec.yaml`. Omit all `TIPOC_SECURITIES_*` variables to
preserve the legacy fixed market-buy contract. Enable all normal market/limit
and buy/sell paths with:

```bash
TIPOC_SECURITIES_ORDER_FLOW_MODE=lifecycle_coverage \
TIPOC_SECURITIES_ORDER_FLOW_SEED=20260811 \
TIPOC_SECURITIES_TMB_WEIGHT=1 \
TIPOC_SECURITIES_TMS_WEIGHT=1 \
TIPOC_SECURITIES_TLB_WEIGHT=1 \
TIPOC_SECURITIES_TLS_WEIGHT=1 \
TIPOC_SECURITIES_TSL_WEIGHT=1 \
TIPOC_SECURITIES_ORDER_QUANTITIES='100=1' \
TIPOC_SECURITIES_CASH_PERCENT=100 \
TIPOC_SECURITIES_LIFO_PERCENT=50 \
TIPOC_SECURITIES_SELL_PROBE_LIMIT=16 \
scripts/env/tiup/init-attempt.sh \
  --scale 1G \
  --out /absolute/path/to/securities-lifecycle-1g/attempt-001 \
  --render-only
```

`lifecycle_coverage` defaults to the values shown above, so the required form
is only `TIPOC_SECURITIES_ORDER_FLOW_MODE=lifecycle_coverage`. Explicit values
are recommended in retained E2E command evidence. `TIPOC_SECURITIES_ORDER_QUANTITIES`
uses comma-separated `quantity=weight` entries. The wrapper rejects a missing
mode, invalid numeric values, zero lifecycle trade-type weights, and lifecycle
settings on non-securities workload mixes before writing a spec.

The full run and acceptance procedure is documented in
[`../../docs/securities-order-lifecycle-sop.md`](../../docs/securities-order-lifecycle-sop.md).

## Query Cost E2E

Query Cost remains absent from the rendered spec by default. Enable it through
the same TiUP init SOP only when an operator/deployer attestation has already
been written and SHA-pinned:

```bash
TIPOC_QUERY_COST_MODE=latency_and_statement_ru \
TIPOC_QUERY_COST_ATTEMPT_RU_SOURCE=tidb_last_query_info \
TIPOC_QUERY_COST_ATTEMPT_RU_TIMEOUT_MILLISECONDS=500 \
TIPOC_QUERY_COST_ATTEMPT_RU_FAILURE_BUDGET=100 \
TIPOC_QUERY_COST_DEPLOYMENT_ATTESTATION_PATH=/absolute/path/deployment-attestation.json \
TIPOC_QUERY_COST_DEPLOYMENT_ATTESTATION_SHA256=sha256:<64-lowercase-hex> \
TIPOC_QUERY_COST_POLL_INTERVAL_SECONDS=5 \
TIPOC_QUERY_COST_POLL_TIMEOUT_SECONDS=2 \
TIPOC_QUERY_COST_ISOLATION_STATUS=verified_test_environment \
TIPOC_QUERY_COST_ISOLATION_REASON=dedicated_tiup_cluster_and_exclusive_campaign_process_audit \
scripts/env/tiup/init-attempt.sh \
  --scale 1G \
  --out /absolute/path/to/1g/attempt-001 \
  --render-only
```

Valid modes are `off`, `latency_only`, and
`latency_and_statement_ru`. Mode `off` rejects attestation inputs so stale
pins cannot be carried into an apparently disabled attempt. Enabled modes
require both the absolute attestation path and a lowercase SHA-256 pin. The
compiler consumes the mutable path/ref during `init`; the compiled manifest
retains only frozen attestation evidence.

`TIPOC_QUERY_COST_ATTEMPT_RU_SOURCE` defaults to `off`, preserving the existing
latency/Statement Summary path. Set it to `tidb_last_query_info` only together
with `TIPOC_QUERY_COST_MODE=latency_and_statement_ru`; this pins one worker
session and reads `SELECT @@tidb_last_query_info` immediately after each
eligible business statement. Its timeout defaults to `500` milliseconds and
must be from `1` through `30000`; its run-wide failure budget defaults to `100`
and must be from `1` through `1000000`. Timeout or failure-budget inputs are
rejected while the source is `off`. Query Cost mode `off` rejects all three
attempt-RU variables so a disabled Fresh attempt remains an exact bypass.

The periodic Statement Summary side path defaults to a 30-second interval and
5-second timeout. Set the two polling variables above for a 5-second campaign;
the interval must be at least 5 seconds and the timeout must be positive and
strictly smaller than the interval. Poll settings are rejected when mode is
`off`, preventing stale collection policy from leaking into another workload.
`verified_test_environment` must include a bounded operator reason and is only
appropriate when the complete pressure window is controlled against foreign
same-digest traffic. Omitting the isolation variables freezes `unverified`;
TiPOC never promotes isolation from Statement Summary or Grafana telemetry.

## Premium Example

```bash
TIPOC_SQL_ENDPOINT='privatelink-example:4000' \
TIPOC_PD_ENDPOINT='pd-example:2379' \
TIPOC_OBJECT_STORE_URI='s3://user-bucket/tipoc/1t/attempt-001' \
TIPOC_GENERATION_NODES='node-a=10.0.0.10:15,node-b=10.0.0.11:15' \
TIPOC_PRESSURE_NODES='node-a=10.0.0.10:1:512,node-b=10.0.0.11:1:512' \
scripts/env/premium/init-attempt.sh --scale 1T --out runs/premium-1t/attempt-001 --render-only
```

Edit the rendered `spec.yaml` to bind credentials and cluster values, then run
`tipoc init --spec ... --remote-bootstrap plan`. Use
`--remote-bootstrap execute` only after SSH credentials and all node addresses
are confirmed.

## Node List Format

Generation nodes:

```bash
TIPOC_GENERATION_NODES='node-a=10.0.0.10:15,node-b=10.0.0.11:15'
```

Pressure nodes:

```bash
TIPOC_PRESSURE_NODES='node-a=10.0.0.10:1:512,node-b=10.0.0.11:1:512'
```

The pressure tuple is `node-id=address:capacity-units:sql-pool-size`.
It may include an optional CE worker limit as
`node-id=address:capacity-units:sql-pool-size:ce-worker-limit`.

## Workload Selection

The default rendered pressure workload remains standard canonical TPC-E:

```bash
TIPOC_WORKLOAD_MIX=tpce
TIPOC_WORKLOAD_PROFILE=canonical
```

Render the second write-heavy exchange-matching simulation load:

```bash
TIPOC_WORKLOAD_MIX=exchange_matching \
TIPOC_WORKLOAD_PROFILE=canonical \
TIPOC_EXCHANGE_MATCHING_WRITE_PERCENT=90 \
TIPOC_EXCHANGE_MATCHING_SQL_WRITE_PERCENT=80 \
TIPOC_PRESSURE_CONCURRENCY=512 \
TIPOC_PRESSURE_NODES='node-a=10.0.0.10:1:128:256,node-b=10.0.0.11:1:128:256' \
scripts/env/essential/init-attempt.sh --scale 10G --out runs/essential-exchange-c512/attempt-001 --render-only
```

`TIPOC_EXCHANGE_MATCHING_WRITE_PERCENT` controls the percentage of
exchange_matching CE tokens that select the `Trade-Order` chain. The supported
range is `20` through `90`; the default remains `80` when the variable is
omitted. This is a transaction-family selector ratio rather than an observed
SQL statement write ratio, because `Trade-Order` still performs prerequisite
reads before emitting its write-side byproducts.

`TIPOC_EXCHANGE_MATCHING_SQL_WRITE_PERCENT` controls the target observed SQL
write statement share for exchange_matching only:
`(Insert + Update + Delete) / (Select + Insert + Update + Delete)`. The
supported explicit range is `10` through `90`, so examples such as `30`, `50`,
`80`, and `90` are valid. When omitted or set to `0`, the runtime preserves the
CE-selector behavior without SQL-level ratio control. This setting is rejected
for the standard `tpce` workload so canonical TPC-E manifests cannot be
mislabeled as a fitted exchange-matching simulation.

For reruns, `scripts/rerun/run-again.sh` exposes the same split as
`--exchange-matching-write-percent` for the CE selector and
`--exchange-matching-sql-write-percent` for the observed SQL write statement
target. Those flags are accepted only when the final rerun workload mix is
`exchange_matching`.

When reruns are explicitly synced to pressure nodes and the source manifest
declares a remote attempt root or remote manifest path, the generated try
manifest uses that remote attempt root for `evidence_root`, reporting output,
runtime output, remote manifest, and remote log paths. Local dry-runs without
explicit sync keep local output paths, and local non-dry execution is blocked
when the generated manifest is remote-compatible.

Render an exchange-matching hotspot profile by declaring the profile parameters
that the scenario compiler requires:

```bash
TIPOC_WORKLOAD_MIX=exchange_matching \
TIPOC_WORKLOAD_PROFILE=hot-symbol \
TIPOC_WORKLOAD_HOT_DIMENSIONS='symbol,security' \
TIPOC_WORKLOAD_HOT_SET_SIZE=2048 \
TIPOC_WORKLOAD_SKEW_PERCENT=80 \
TIPOC_WORKLOAD_SKEW_FUNCTION=hotset_uniform \
TIPOC_WORKLOAD_LINEAGE_SEED=1106 \
scripts/env/essential/init-attempt.sh --scale 10G --out runs/essential-hot-symbol/attempt-001 --render-only
```

## Preserved Product Semantics

1. The public flow remains `init -> prepare -> run -> cleanup`.
2. `prepare` keeps generated TPC-E CSV source objects and TiDB `IMPORT INTO`.
3. The default CSV object target remains `536870912` bytes.
4. The Global Sort setting is a base workspace binding. Users must not provide
   per-table internal Global Sort paths because the import planner derives them.
5. TiDB capability actions should be added to `spec.yaml` only when a real
   test plan needs them. The script templates do not declare fake actions.
6. Environment labels stay in scripts and specs only. They are not Go package
   names or runtime abstractions.
7. `exchange_matching` is a second configurable simulation load for write-heavy
   trading pressure. It is not the canonical TPC-E workload, and it does not
   replace the default `tpce` workload.
