[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill-grafana-k6-manage":3,"mdc-3bqmiv-key":36,"related-org-grafana-k6-manage":10591,"related-repo-grafana-k6-manage":10778},{"slug":4,"name":4,"fn":5,"description":6,"org":7,"tags":11,"stars":26,"repoUrl":27,"updatedAt":28,"license":29,"forks":30,"topics":31,"repo":32,"sourceUrl":34,"mdContent":35},"k6-manage","manage Grafana Cloud k6 load tests","Interact with Grafana Cloud k6 (GCk6) — manage load tests, test runs, scripts, projects, schedules, env vars, fetch metrics or logs, and run scripts locally — using the `gcx` CLI (or direct curl when gcx is unavailable). Use this skill whenever the user mentions a k6 cloud test or run, asks to list\u002Fedit\u002Fcreate\u002Fstart\u002Fabort k6 load tests, wants to fetch logs or metrics for a test run, manage k6 project limits or schedules, run a k6 script locally or via `k6 cloud run`, or needs to call any `\u002Fcloud\u002Fv6\u002F`, `\u002Fcloud\u002Fv5\u002F`, or k6-app Loki endpoint against a Grafana Cloud stack. Trigger even when the user doesn't explicitly say \"gcx\" or \"API\" — phrases like \"why did my k6 test fail\", \"show me logs for run X\", \"bump VUh limit on project Y\", or \"update my k6 script\" all qualify.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},"grafana","Grafana","https:\u002F\u002Fpexgzepcugksgbtrxkhf.supabase.co\u002Fstorage\u002Fv1\u002Fobject\u002Fpublic\u002Forg-logos\u002Fgrafana.jpg",[12,16,19,22,23],{"name":13,"slug":14,"type":15},"Performance","performance","tag",{"name":17,"slug":18,"type":15},"Automation","automation",{"name":20,"slug":21,"type":15},"CLI","cli",{"name":9,"slug":8,"type":15},{"name":24,"slug":25,"type":15},"Testing","testing",189,"https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fskills","2026-07-12T07:44:07.960401",null,16,[],{"repoUrl":27,"stars":26,"forks":30,"topics":33,"description":29},[],"https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fskills\u002Ftree\u002FHEAD\u002Fskills\u002Fgrafana-k6\u002Fk6-manage","---\nname: k6-manage\ndescription: Interact with Grafana Cloud k6 (GCk6) — manage load tests, test runs, scripts, projects, schedules, env vars, fetch metrics or logs, and run scripts locally — using the `gcx` CLI (or direct curl when gcx is unavailable). Use this skill whenever the user mentions a k6 cloud test or run, asks to list\u002Fedit\u002Fcreate\u002Fstart\u002Fabort k6 load tests, wants to fetch logs or metrics for a test run, manage k6 project limits or schedules, run a k6 script locally or via `k6 cloud run`, or needs to call any `\u002Fcloud\u002Fv6\u002F`, `\u002Fcloud\u002Fv5\u002F`, or k6-app Loki endpoint against a Grafana Cloud stack. Trigger even when the user doesn't explicitly say \"gcx\" or \"API\" — phrases like \"why did my k6 test fail\", \"show me logs for run X\", \"bump VUh limit on project Y\", or \"update my k6 script\" all qualify. \n---\n\n# Grafana Cloud k6 — interaction reference\n\nThe default path is the `gcx` CLI. When gcx isn't installed, every\nendpoint here is still reachable via direct curl against k6's public\nhosts — see §1.2 for the auth-header and host-translation rules. Two\nprinciples shape the rest:\n\n- **gcx owns Grafana-side auth (when present).** It injects the right\n  headers on every call, so you should not set auth headers yourself.\n  The only header you ever set by hand is `X-K6TestRun-Id`, on Loki\n  log queries (§4), browser screenshot\u002Ffile fetches (§6), and Tempo\n  trace queries (§7) — anything else gets overwritten or causes\n  conflicts. In curl mode the auth headers are manual; see §1.2.\n- **Reach for `gcx k6 ...` subcommands first.** They wrap the common\n  paths with friendlier ergonomics and handle pagination. Discover\n  what's available with `gcx help-tree k6` (and drill in further with\n  `gcx help-tree k6 \u003Csubcommand>`); fall back to `gcx api` only when\n  no subcommand exists for what you need.\n\n---\n\n## 1. Authentication\n\n### 1.1 With gcx (default)\n\n```bash\ngcx login --context \u003Cctx>                # one-time OAuth, browser flow\ngcx --context \u003Cctx> config check         # expect \"✔ Connectivity: online\"\n```\n\nOnce a context is logged in, every `gcx api ...` and `gcx k6 ...` call\ninherits its auth state. If a call returns *\"Invalid or expired token —\nrun gcx login to refresh\"*, the OAuth session has lapsed — re-run\n`gcx login --context \u003Cctx>`.\n\n### 1.2 Without gcx — direct curl\n\nCheck `command -v gcx` first. If it's missing, every endpoint in this\nskill is still reachable directly against k6's public hosts — three\nthings change versus the gcx examples elsewhere:\n\n- **Auth headers are manual.** Set both on every call:\n  - `Authorization: Bearer \u003Ck6_token>`\n  - `X-Stack-ID: \u003Cint>`\n- **Hosts replace the plugin proxy.**\n  - REST (`\u002Fcloud\u002Fv6\u002F...`, `\u002Fcloud\u002Fv5\u002F...`, `\u002Fcloud-resources\u002Fv1\u002F...`,\n    `\u002Finsights\u002F...`) → `https:\u002F\u002Fapi.k6.io`\n  - Logs (Loki) and traces (Tempo) → `https:\u002F\u002Fcloudlogs.k6.io`\n- **No `\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002F{cloud,logs,insights}` prefix.**\n  Drop it; everything after that prefix in the gcx examples is the\n  real k6 path. The doubled `cloud\u002Fcloud\u002F` quirk from §2 collapses to\n  a single `\u002Fcloud\u002F` — the first one was just the proxy route.\n\n#### Obtaining the credentials\n\nDon't guess these — prompt the user once per session for:\n\n1. **k6 API token** — long-lived bearer; the same value\n   `gcx k6 auth token` would print when gcx is configured.\n2. **Stack** — either the integer **stack ID** (used directly in\n   `X-Stack-ID`) or a Grafana **stack URL** (e.g.\n   `https:\u002F\u002Fmyorg.grafana.net`). If the user supplies a URL, resolve\n   it to an ID once with `GET \u002Fcloud\u002Fv6\u002Fauth`, which takes the URL in\n   the `X-Stack-Url` header and returns `{stack_id, default_project_id}`:\n\n   ```bash\n   STACK_ID=$(curl -sS https:\u002F\u002Fapi.k6.io\u002Fcloud\u002Fv6\u002Fauth \\\n     -H \"Authorization: Bearer $K6_TOKEN\" \\\n     -H \"X-Stack-Url: $STACK_URL\" \\\n     | jq -r '.stack_id')\n   ```\n\n   Cache the resolved ID for the session — every subsequent call\n   needs it in `X-Stack-ID`. (Note: `\u002Fcloud\u002Fv6\u002Fauth` is the *only*\n   endpoint that takes `X-Stack-Url` instead of `X-Stack-ID` — it's\n   how you cross the gap from \"user-known URL\" to \"API-required ID\".)\n\n#### Translation cheat-sheet\n\n| gcx form (plugin proxy)                                                                  | curl form (direct)                                                       |\n|------------------------------------------------------------------------------------------|--------------------------------------------------------------------------|\n| `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F123`                     | `curl https:\u002F\u002Fapi.k6.io\u002Fcloud\u002Fv6\u002Ftest_runs\u002F123 -H ...`                   |\n| `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv5\u002Ftest_runs\u002F\u003Cid>\u002Fmetrics`            | `curl https:\u002F\u002Fapi.k6.io\u002Fcloud\u002Fv5\u002Ftest_runs\u002F\u003Cid>\u002Fmetrics -H ...`          |\n| `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Findex`             | `curl https:\u002F\u002Fapi.k6.io\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Findex -H ...`           |\n| `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Finsights\u002Finsights\u002Fapi\u002Fv1\u002Ftestrun\u002F\u003Cid>\u002Fexecutions` | `curl https:\u002F\u002Fapi.k6.io\u002Finsights\u002Fapi\u002Fv1\u002Ftestrun\u002F\u003Cid>\u002Fexecutions -H ...`  |\n| `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Fquery_range?...`                      | `curl https:\u002F\u002Fcloudlogs.k6.io\u002Fapi\u002Fv1\u002Fquery_range?... -H ...`             |\n| `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Fsearch?...`                 | `curl https:\u002F\u002Fcloudlogs.k6.io\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Fsearch?... -H ...`        |\n\nIn every `-H ...` slot above, send both auth headers:\n`-H \"Authorization: Bearer $K6_TOKEN\" -H \"X-Stack-ID: $STACK_ID\"`.\n\nNotes:\n- Endpoint-specific headers gcx leaves to you — `X-K6TestRun-Id` on\n  log, trace, and files endpoints (§4, §6, §7) — are still required\n  *in addition* to the auth pair.\n- The `gcx api` flag quirks in §2 (spill envelope, `--json field`\n  filtering, `-o` for output format) don't apply to curl. Use plain\n  curl flags: `-o file` to save body, `--data-binary @file` for PUT\n  payloads, `-w '%{http_code}'` for status code, etc.\n- Pagination semantics (`$orderby`, `$top`, `$skip`, `@nextLink`\n  from §3) are properties of the v6 endpoints themselves and work\n  identically over curl. The `@nextLink` URL returned by the server\n  is already an absolute `https:\u002F\u002Fapi.k6.io\u002F...` URL — pass it back\n  to curl unchanged; the plugin-proxy reshape in §3 isn't needed.\n\n---\n\n## 2. How `gcx api` paths are shaped\n\nWhen no subcommand exists, fall back to `gcx api` against the Grafana\nplugin-proxy routes:\n\n- **REST API** (`\u002Fcloud\u002Fv6\u002F`, `\u002Fcloud\u002Fv5\u002F`) — prefix with\n  `\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002F\u003Ck6-path>`.\n- **Logs (Loki)** — prefix with\n  `\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002F\u003Cloki-path>`.\n\n| k6 path                                   | gcx invocation                                                                    |\n|-------------------------------------------|-----------------------------------------------------------------------------------|\n| `\u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}`                | `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}`             |\n| `\u002Fcloud\u002Fv5\u002Ftest_runs\u002F{id}\u002Fmetrics`        | `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv5\u002Ftest_runs\u002F{id}\u002Fmetrics`     |\n| Loki `\u002Fapi\u002Fv1\u002Fquery_range?...`            | `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Fquery_range?...`               |\n\nNote the doubled `cloud\u002Fcloud\u002F` in every REST path — the first `cloud`\nis the proxy route, the second is k6's `\u002Fcloud\u002Fv{N}\u002F` namespace.\n\n### `gcx api` flag quirks\n\n`gcx api` is not a curl clone — a few flags differ from what curl muscle\nmemory suggests:\n\n- **Response body** is written to stdout. There is no `-o \u003Cfile>` flag\n  for saving the body; `-o` selects output *format* (`json`, `yaml`,\n  `agents`). Use shell redirection (`> file`) or `$(...)` capture\n  instead.\n- **Request body** uses `-d \u003Cstring>`, `-d @file`, or `-d @-` (stdin).\n  There is no `--data-binary`; `-d @file` already preserves bytes.\n- **Field selection without jq**: `--json field1,field2,...` returns\n  only the listed fields, and `--json list` (or `--json '?'`)\n  discovers what's available. Often cleaner than piping into jq for\n  shallow extractions.\n- **Stderr noise**: gcx prints a one-line `hint:` to stderr on most\n  invocations. Pipelines into `jq` should redirect with `2>\u002Fdev\u002Fnull`\n  to avoid surprises.\n- **Response headers** are not directly exposed by `gcx api`. When a\n  branch in the workflow hinges on `Content-Type` (e.g. script GET in\n  §5), inspect the downloaded body with `file \u003Cpath>` instead.\n- **Large responses spill to a temp file**, with stdout reduced to a\n  wrapper envelope. The threshold is a few tens of KB, so even\n  moderately-sized list endpoints trigger it. The envelope looks like\n  this:\n  ```json\n  {\"spilled_to\":\"\u002Fvar\u002Ffolders\u002F...\u002Fgcx-results-\u003Cn>.json\",\n   \"bytes\":2365037,\n   \"preview_sample\":[\"@nextLink\",\"value\"],\n   \"message\":\"Response too large for stdout...\"}\n  ```\n  Naive `json.loads(stdout).get('value', [])` patterns silently return\n  empty in this case — the envelope has no `value` key. Two reliable\n  fixes:\n  - **Pass `-o json`** to force inline output regardless of size\n    (recommended for scripts that parse the body). The agent-mode\n    default formatting is what triggers the spill; `-o json` opts out.\n  - **Or detect the envelope and re-read from the spilled file**:\n    ```python\n    d = json.loads(stdout)\n    if 'spilled_to' in d:\n        d = json.load(open(d['spilled_to']))\n    ```\n  Either works; `-o json` is fewer lines.\n\n- **The Grafana plugin proxy rewrites `Content-Type: multipart\u002F...`\n  to `application\u002Fjson`.** `gcx api` itself forwards your\n  `-H \"Content-Type: ...\"` header correctly (visible in\n  `--log-http-payload` traces), but the upstream plugin proxy\n  rewrites multipart Content-Types to JSON before they reach k6's\n  API. The net effect: endpoints that require multipart bodies —\n  notably `POST \u002Fcloud\u002Fv6\u002Fprojects\u002F{id}\u002Fload_tests` for test\n  creation, which takes `name` + `script` as form parts — return\n  `HTTP 415 \"Unsupported media type \\\"application\u002Fjson\\\"\"` no\n  matter what header you set on the gcx side. Fall back to direct\n  curl against `api.k6.io` (§1.2) for these endpoints —\n  `curl -F name=... -F script=@...` builds the multipart body for\n  you and bypasses the plugin proxy. Other Content-Type values\n  (e.g. `application\u002Foctet-stream` for the script-update PUT in §5)\n  are forwarded through the proxy unchanged.\n\n---\n\n## 3. Discovering and calling endpoints\n\n`gcx k6` subcommands (see `gcx help-tree k6`) cover the common reads.\nFor everything else — mutations, niche reads, endpoints not surfaced as\nsubcommands — the k6 Cloud API surface is large and changes over time.\nRather than rely on a cheat-sheet that goes stale, discover the\noperation you need from the OpenAPI spec at request time.\n\n### Workflow\n\n1. **Fetch the spec once per session** (it's large; cache to `\u002Ftmp`):\n\n   ```bash\n   gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fopenapi > \u002Ftmp\u002Fk6-openapi.json\n   ```\n\n2. **Index by `operationId` + `description` first** — this keeps the\n   working payload small while you search:\n\n   ```bash\n   jq '[.paths | to_entries[] | .key as $p | .value | to_entries[]\n        | {path: $p, method: .key,\n           operationId: .value.operationId,\n           description: .value.description}]' \u002Ftmp\u002Fk6-openapi.json\n   ```\n\n   Grep this for the action you need (\"abort\", \"limits\", \"schedule\", …).\n\n3. **Pull the chosen operation's full schema** — parameters, request\n   body, response — resolving any `$ref` indirections:\n\n   ```bash\n   jq '.paths[\"\u003Cpath>\"][\"\u003Cmethod>\"]' \u002Ftmp\u002Fk6-openapi.json\n   # Then for each \"$ref\": \"#\u002Fcomponents\u002Fschemas\u002FFoo\":\n   jq '.components.schemas.Foo' \u002Ftmp\u002Fk6-openapi.json\n   ```\n\n4. **Build the `gcx api` call** against the same path, prefixed per §2.\n   Authorization is already injected by gcx — do not add it yourself.\n\n### List requests\n\nWhen the operation you're calling is a list endpoint, default to\n**ordering by `created` descending** (newest first) and **paginating\nby 20** — both via whatever query parameter names the OpenAPI schema\nfor that operation exposes. Names vary (`ordering=-created`,\n`order_by=created.desc`, `sort=-created`, `limit=20`, `page_size=20`),\nwhich is exactly why discovering them from the spec in step 3 matters.\nNewest-first means the entries the user usually cares about land in\nthe first page; a page size of 20 keeps the response small enough to\nsummarise without burning context.\n\n#### Full enumeration: paginating with `@nextLink`\n\nWhen you need to enumerate *all* rows (not just the newest page), the\nv6 list endpoints cap each response at **1000 rows** (the default\n`$top`) and return an `@nextLink` field pointing at the next page.\n**`gcx k6 runs list --limit 0` does NOT auto-follow** `@nextLink` and\ndefaults to ascending order — for tests with >1000 historical runs it\nsilently returns the **oldest** 1000, not the newest. The\npractical effect: `(first\u002Flast_run)` summarised from this output can\nbe wildly stale (e.g. a daily-scheduled test that's been running for\nyears will show a `last_run` from ~3 years ago). Use `gcx api`\nagainst the v6 endpoint with `$orderby=created desc` for the\nnewest-first slice, or loop on `@nextLink` until it's absent for full\nenumeration.\n\nThe v6 list endpoints expose OData-style query parameters:\n\n| Param      | Purpose                                                              |\n|------------|----------------------------------------------------------------------|\n| `$orderby` | Ordering — value must be `\u003Cfield> \u003Cdirection>` (e.g. `created desc`). The allowed fields are operation-specific; `created` is the common one. Default is ascending. |\n| `$top`     | Page size, default 1000 (also the cap)                              |\n| `$skip`    | Offset (`@nextLink` already encodes this for you)                   |\n| `$count`   | Include total count in response                                     |\n\nTwo practical defaults for the loop: `$orderby=created desc` so the\nfirst page contains the newest runs (most of the time the agent only\ncares about those), and `-o json` to opt out of the spill envelope\n(see §2) so the parsing is uniform across pages.\n\n```python\nimport json, subprocess, urllib.parse\n\nCTX = \"\u003Cstack>\"\nTEST_ID = \"\u003Ctest_id>\"\nPROXY = \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\"\n\nall_runs = []\n# Start with newest first; -o json keeps the body inline for clean json.loads().\npath = (\n    f\"{PROXY}\u002Fcloud\u002Fv6\u002Fload_tests\u002F{TEST_ID}\u002Ftest_runs\"\n    \"?%24orderby=created%20desc&%24top=1000\"\n)\nwhile path:\n    r = subprocess.run([\"gcx\", \"--context\", CTX, \"api\", path, \"-o\", \"json\"],\n                       capture_output=True, text=True, timeout=60)\n    d = json.loads(r.stdout)\n    all_runs.extend(d.get(\"value\", []))\n    nxt = d.get(\"@nextLink\")\n    if not nxt:\n        path = None\n        continue\n    # @nextLink comes back as an absolute http:\u002F\u002Fapi.k6.io\u002F... URL with\n    # OData params already encoded ($skip, $top, $orderby). Reshape its\n    # path+query into the plugin-proxy prefix:\n    p = urllib.parse.urlparse(nxt)\n    path = f\"{PROXY}{p.path}\" + (f\"?{p.query}\" if p.query else \"\")\n```\n\nSame pattern works for any v6 list endpoint that returns `@nextLink`,\nnot just `\u002Ftest_runs`. If you only need the few most-recent items,\nstop the loop after the first page — with `$orderby=created desc` that\npage is already the newest 1000.\n\n### Metrics\n\nTime-series and aggregate metrics live on the **v5** API\n(`\u002Fcloud\u002Fv5\u002F...`) — Prometheus-like query semantics inside OData-style\nURL function-calls (`query_range_k6(query='...',metric='...')`), not\ncaptured by the v6 OpenAPI. The full endpoint reference, selector\nsyntax, query methods per metric type, and worked examples are inlined\nin [`references\u002Fmetrics.md`](references\u002Fmetrics.md) — read that before\nconstructing a metrics query.\n\n### Logs\n\nSee §4.\n\n---\n\n## 4. Logs (Loki via `gcx api`)\n\nThe plugin proxies Loki under `\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002F`. The\nonly header you supply by hand is `X-K6TestRun-Id`; gcx handles\nauthorization.\n\n```bash\nRUN_ID=\"\u003Crun_id>\"\n\n# Scope the log window to the run itself: `created` for start, `ended`\n# for end. If `ended` is null the run is still in progress — fall back\n# to \"now\". Use a wider hard-coded window only when the run object's\n# timestamps don't fit what you're investigating.\nRUN=$(gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F$RUN_ID 2>\u002Fdev\u002Fnull)\n# k6 emits sub-second precision (e.g. \"...:58.984041Z\"); jq's\n# fromdateiso8601 only accepts whole seconds, so strip the fraction.\nSTART=$(echo \"$RUN\" | jq -r '.created | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601')\nEND=$(echo \"$RUN\"   | jq -r 'if .ended then (.ended | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601) else (now | floor) end')\n\nQUERY=$(printf '{test_run_id=\"%s\"}' \"$RUN_ID\" | jq -sRr @uri)\n\n# Save the raw response to \u002Ftmp\u002F — log payloads can be large; streaming\n# them inline burns context. Summarise from the file, then jq into\n# specific entries only when needed.\ngcx api \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Fquery_range?query=${QUERY}&direction=backward&start=${START}&end=${END}&limit=1000\" \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Frun_${RUN_ID}_logs.json\n\n# Tight summary — counts and stream labels only:\njq '{status, streams: (.data.result | length),\n     total_entries: ([.data.result[].values | length] | add),\n     stream_labels: [.data.result[].stream]}' \u002Ftmp\u002Frun_${RUN_ID}_logs.json\n```\n\nPull individual entries from `\u002Ftmp\u002Frun_${RUN_ID}_logs.json` as needed\n(e.g. `jq '.data.result[].values[]' …`) rather than re-running the\nquery.\n\nEvery LogQL query **must** include the `{test_run_id=\"\u003Crun_id>\"}` stream\nselector — the plugin proxy partitions logs by run and rejects (or\nreturns nothing for) queries without it. Layer additional filters on\ntop of that selector:\n\n- `{test_run_id=\"\u003Crun_id>\"}` — everything\n- `{test_run_id=\"\u003Crun_id>\"} | level=~\"(error|warn)\"` — errors and warnings only\n- `{test_run_id=\"\u003Crun_id>\"} |= \"specific text\"` — substring filter\n\nDirection & window tips:\n\n- **Scope `start`\u002F`end` to the run's `created`\u002F`ended` fields**, not to\n  wall-clock \"last hour\" — otherwise queries silently miss anything\n  older than the window. The only reason to deviate is when you\n  specifically want a different interval (e.g. surrounding context).\n- `direction=forward` with `start = run.created` to find the *first* errors.\n- `direction=backward` with `end = run.ended` (or now, if still running)\n  to find the *most recent* output.\n- Loki retention typically outlives k6's cascade-delete, so logs of a\n  deleted child run may still be queryable for a while.\n\n---\n\n## 5. Editing a test script safely\n\n### Two distinct script endpoints\n\nThere are two GET endpoints that return a k6 script body, and they are\nnot interchangeable:\n\n| Endpoint                                    | What it returns                           | When to use                                            |\n|---------------------------------------------|-------------------------------------------|--------------------------------------------------------|\n| `\u002Fcloud\u002Fv6\u002Fload_tests\u002F\u003Ctest_id>\u002Fscript`     | The **current** load-test script (mutable; supports PUT) | Editing the script; reading current state              |\n| `\u002Fcloud\u002Fv6\u002Ftest_runs\u002F\u003Crun_id>\u002Fscript`       | The script **snapshot bundled into a specific run** (read-only) | Investigating what a past run actually executed; diffing across versions |\n\nThe two can drift apart: if the load-test script is edited after a\nrun completes, that run's bundled snapshot stays frozen at what it\nexecuted, while the load-test endpoint serves the new current version.\nThe bundled-snapshot endpoint is GET-only — you cannot mutate\nhistorical bytes.\n\nThe safe-edit recipe below uses the load-test endpoint (the editable\none). For run-vs-run script diffs (e.g. \"did the script change between\nthe last passing and first failing run?\"), GET both runs'\n`\u002Ftest_runs\u002F\u003Cid>\u002Fscript` and diff them locally.\n\n### Script body format\n\nThe script GET endpoint returns one of two shapes — always detect which\nbefore assuming the format:\n\n- **Single js\u002Fts file**. The recipe below handles this case directly.\n- **k6 tar archive** (plain tar or gzipped). A multi-file project\n  bundle (entry script + imported modules + assets). To edit: extract\n  the JS file, modify it, then use `k6 archive` to rebuild the\n  archive from the modified JS. Do **not** manually repack with\n  `tar` — the archive contains a `metadata.json` with parsed options\n  (projectID, thresholds, scenarios) that `k6 archive` regenerates\n  correctly from the script source. Manual repacking preserves stale\n  metadata and causes runtime errors (e.g. projectID mismatch).\n\n  ```bash\n  # Edit a k6 tar archive\n  tar -xf \u002Ftmp\u002Fscript_body -C \u002Ftmp\u002Fextracted\u002F   # extract\n  # ... edit the JS file ...\n  k6 archive \u002Ftmp\u002Fedited_script.js -O \u002Ftmp\u002Fnew_archive.tar  # rebuild\n  ```\n\n`gcx api` doesn't expose response headers (see §2), so detect the shape\nby inspecting the downloaded body with `file(1)`:\n\n```bash\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F$ID\u002Fscript \\\n  > \u002Ftmp\u002Fscript_body\nfile \u002Ftmp\u002Fscript_body\n# Expected output (examples):\n#   ASCII text          → js\u002Fts source\n#   POSIX tar archive   → k6 tar bundle\n#   gzip compressed data → gzipped tar bundle\n```\n\nThe PUT body must be the raw script (or archive) bytes\n(`application\u002Foctet-stream`). gcx forwards the request to k6 unchanged.\n\n```bash\nID=\"\u003Cload_test_id>\"\n\n# 1. Pull current script (single-file js\u002Fts case)\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F$ID\u002Fscript \\\n  > \u002Ftmp\u002Fscript_current.js\n\n# 2. Backup\ncp \u002Ftmp\u002Fscript_current.js \u002Ftmp\u002Fscript_backup_$(date +%s).js\n\n# 3. Edit → \u002Ftmp\u002Fscript_new.js\n\n# 4. Local parse-only sanity check\nk6 inspect \u002Ftmp\u002Fscript_new.js | head -20\n\n# 5. 1-iteration smoke (edit IN-FILE; --iterations CLI flag breaks browser scenarios)\nsed 's\u002Fiterations: [0-9]\\+\u002Fiterations: 1\u002F' \u002Ftmp\u002Fscript_new.js > \u002Ftmp\u002Fscript_1iter.js\nk6 run --quiet \u002Ftmp\u002Fscript_1iter.js   # exit 0 = pass, 99 = threshold fail\n\n# 6. PUT — Content-Type must be application\u002Foctet-stream\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F$ID\u002Fscript \\\n  -X PUT \\\n  -H \"Content-Type: application\u002Foctet-stream\" \\\n  -d \"@\u002Ftmp\u002Fscript_new.js\"\n\n# 7. Verify by re-fetching and comparing sha256 — the two hashes MUST match.\n#    Do not rely on the `updated` timestamp; it does not bump on script PUT.\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F$ID\u002Fscript \\\n  > \u002Ftmp\u002Fscript_verify.js\nshasum -a 256 \u002Ftmp\u002Fscript_new.js \u002Ftmp\u002Fscript_verify.js\n```\n\nIf the PUT returns 415, double-check that `-H \"Content-Type:\napplication\u002Foctet-stream\"` made it through (some shell quoting mistakes\ncan drop it). Pass `-vvv` to `gcx api` for the request\u002Fresponse trace\nwhen debugging.\n\n---\n\n## 6. Browser screenshots\n\nBrowser-module runs write screenshot PNGs to per-run S3 storage —\nthat's the only artifact type the files API surfaces today. They're\nnot exposed via `\u002Fcloud\u002Fv6\u002F`; retrieval goes through a separate\n`cloud-resources\u002Fv1\u002Ffiles\u002F` plugin route in a two-step flow. Both\ncalls require the same `X-K6TestRun-Id` header used for log queries\n(§4) — gcx still handles auth, but the run ID must be supplied by\nhand or the endpoint rejects with HTTP 422.\n\n```bash\nRUN_ID=\"\u003Crun_id>\"\n\n# 1. Index — JSON array of screenshot paths owned by this run. Empty\n#    array if the run took none (e.g. non-browser tests, or browser\n#    runs that didn't call page.screenshot()).\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Findex \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" -o json 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Ffiles_${RUN_ID}.json\n\n# Each entry looks like:\n#   \"7542817\u002Ffiles\u002Fscreenshots\u002Fscreenshots\u002Flogin-success.png\"\n# The doubled \"screenshots\u002Fscreenshots\u002F\" segment is real, not a typo —\n# pass the path back unchanged to step 2.\n\n# 2. Request pre-signed download URLs for the files you want. The\n#    request body must be JSON; Content-Type matters.\nFILES=$(jq -c '[.[] | {name: .}]' \u002Ftmp\u002Ffiles_${RUN_ID}.json)\nPAYLOAD=$(jq -nc --argjson files \"$FILES\" \\\n  '{service:\"aws_s3\", operation:\"download\", files:$files}')\n\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Fgenerate-pre-signed-url \\\n  -X POST \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d \"$PAYLOAD\" -o json 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Fpresigned_${RUN_ID}.json\n\n# 3. Download each pre-signed URL directly — they're plain S3 GETs, no\n#    gcx and no auth header (the signature is in the URL). The URLs\n#    are valid for 24h (X-Amz-Expires=86400); re-run step 2 if they\n#    expire.\nmkdir -p \u002Ftmp\u002Frun_${RUN_ID}_files\njq -r '.urls[] | [.name, .pre_signed_url] | @tsv' \u002Ftmp\u002Fpresigned_${RUN_ID}.json |\n  while IFS=$'\\t' read -r NAME URL; do\n    curl -sS -o \"\u002Ftmp\u002Frun_${RUN_ID}_files\u002F$(basename \"$NAME\")\" \"$URL\"\n  done\n```\n\n### Notes worth knowing\n\n- **Index before signing.** `generate-pre-signed-url` does *not*\n  validate that the file exists — it will happily mint a URL for any\n  key, and the 404 only surfaces when you try to download (S3 returns\n  `\u003CError>\u003CCode>NoSuchKey\u003C\u002FCode>...`). Always derive the file list\n  from `files\u002Findex`, not from a guess at the path shape.\n- **Batch the sign request.** `files` is an array, so request all the\n  URLs you need in one POST rather than one call per file — same\n  24h expiry covers the whole batch.\n- **Browser tests vs. protocol tests.** Only runs that called\n  `page.screenshot()` have entries in the index; a pure protocol\u002FHTTP\n  run will return `[]`. Don't assume the index is non-empty.\n\n---\n\n## 7. Browser traces (Tempo via `gcx api`)\n\nBrowser-module runs emit OTel spans for every iteration, navigation,\nlocator click, screenshot, web-vital observation, etc. The plugin\nproxies a Tempo backend under `\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002F`\n(same prefix as Loki — see §4), and the same `X-K6TestRun-Id` header\nis required on every call. Without it, both search and fetch return\nHTTP 401 `\"Test run ID missing\"`.\n\nRetrieval is a two-step flow: TraceQL search → fetch full trace by\nID. The full trace is large (≈100 KB on disk for a 120-span iteration\nbecause `-o json` pretty-prints; ~50 KB compact), so the\njoin+summarise step is what keeps agent context lean.\n\n```bash\nRUN_ID=\"\u003Crun_id>\"\n\n# 1. Find the run's start\u002Fend window and pick the scenario name.\n#    Same caveat as §4: strip the sub-second fraction before\n#    fromdateiso8601, and fall back to \"now\" if the run is still\n#    running. Add a small buffer because spans can land slightly\n#    after the run object reports `ended`.\nRUN=$(gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F$RUN_ID 2>\u002Fdev\u002Fnull)\nSTART=$(echo \"$RUN\" | jq -r '.created | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601')\nEND=$(  echo \"$RUN\" | jq -r 'if .ended then (.ended | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601) else (now|floor) end')\nSTART=$((START - 60))\nEND=$((END + 60))\n\nSCENARIO=\"ui\"  # whatever your scenario is named; check run.ui.exec \u002F k6 script\n\n# 2. Search for iteration root spans. TraceQL goes in `q`; URL-encode\n#    it. `start`\u002F`end` must be unix seconds — RFC3339 returns\n#    HTTP 400 `invalid start: strconv.ParseUint`. limit=500 caps the\n#    result, enough to cover several thousand iterations.\nQ=$(printf '{ name = \"iteration\" && span.test.iteration.number >= 0 && span.test.vu >= 0 && span.test.scenario = \"%s\" }' \"$SCENARIO\")\nQE=$(printf '%s' \"$Q\" | jq -sRr @uri)\n\ngcx api \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Fsearch?start=${START}&end=${END}&q=${QE}&limit=500\" \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" -o json 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Ftraces_${RUN_ID}.json\n\n# Each entry has: traceID (32-char hex), rootServiceName (\"k6\"),\n# rootTraceName (\"iteration\"), durationMs, startTimeUnixNano, and a\n# spanSet preview of the iteration root span's attributes\n# (test.iteration.number, test.vu, test.scenario).\n\n# 3. Fetch a full trace. The response is OTLP-shaped:\n#    { \"batches\": [ { \"resource\": {...}, \"scopeSpans\": [ { \"spans\": [...] } ] } ] }\nTRACE_ID=$(jq -r '.traces[0].traceID' \u002Ftmp\u002Ftraces_${RUN_ID}.json)\ngcx api \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Ftraces\u002F$TRACE_ID\" \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" -o json 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Ftrace_${TRACE_ID}.json\n```\n\n### Compact summary for an agent\n\nThe OTLP body for a single iteration can run ~100 KB pretty-printed.\nDumping it verbatim into context is wasteful — most of the useful\nsignal lives in the span-name distribution, the slowest individual\nspans, and the web-vital ratings. The pipeline below collapses a\ntrace into ~1–2 KB of plain text:\n\n```bash\njq -r '\n  # OTel value envelope: pick by key presence, not \u002F\u002F-chaining — jq's \u002F\u002F\n  # treats `false` as missing and would drop legitimate boolValue:false.\n  def attrval:\n    if   has(\"stringValue\") then .stringValue\n    elif has(\"intValue\")    then .intValue\n    elif has(\"boolValue\")   then .boolValue\n    elif has(\"doubleValue\") then .doubleValue\n    else null end;\n  def attrs: [.attributes[] | {(.key): (.value | attrval)}] | add \u002F\u002F {};\n  def dur:   (((.endTimeUnixNano|tonumber) - (.startTimeUnixNano|tonumber)) \u002F 1000000 | floor);\n\n  [.batches[].scopeSpans[].spans[] | {name, dur: dur, a: attrs, status: (.status.code \u002F\u002F \"OK\")}] as $spans\n\n  | \"── span-name rollup (count · total ms · max ms) ──\",\n    ([$spans[] | {name, dur}]\n       | group_by(.name) | map({name: .[0].name, n: length,\n                                t: (map(.dur)|add), m: (map(.dur)|max)})\n       | sort_by(-.t)[]\n       | \"  \\(.n|tostring|.+\"      \"|.[0:4])  \\(.t|tostring|.+\"        \"|.[0:7])  \\(.m|tostring|.+\"      \"|.[0:6])  \\(.name)\"),\n\n    \"\\n── slowest spans (ms · name · navigation.url \u002F page.goto.url) ──\",\n    ([$spans[] | select(.name != \"iteration\")] | sort_by(-.dur) | .[0:8][]\n       | \"  \\(.dur|tostring|.+\"        \"|.[0:7])  \\(.name)\\(if .a[\"navigation.url\"] \u002F\u002F .a[\"page.goto.url\"] then \"  \" + (.a[\"navigation.url\"] \u002F\u002F .a[\"page.goto.url\"]) else \"\" end)\"),\n\n    \"\\n── web-vital ratings ──\",\n    ([$spans[] | select(.name == \"web_vital\")\n       | {n: .a[\"web_vital.name\"], v: .a[\"web_vital.value\"], r: .a[\"web_vital.rating\"]}]\n       | group_by(.n) | map({name: .[0].n,\n                             ratings: ([.[].r] | group_by(.) | map({(.[0]): length}) | add)})[]\n       | \"  \\(.name)  \\(.ratings)\"),\n\n    \"\\n── span errors ──\",\n    ([$spans[] | select(.status != \"OK\" and .status != null)] | length | \"  count: \\(.)\")\n' \u002Ftmp\u002Ftrace_${TRACE_ID}.json\n```\n\nOn a run like 7542817 the output is something like:\n\n```\n── span-name rollup (count · total ms · max ms) ──\n  1     154552   154552  iteration\n  37    153391   17746   navigation\n  11    21778    5168    page.waitForNavigation\n  ...\n\n── slowest spans (ms · name · navigation.url \u002F page.goto.url) ──\n  17746    navigation  https:\u002F\u002Fk6e2etests.grafana-dev.net\u002Fa\u002Fk6-app\u002Fprojects\n  14992    navigation  https:\u002F\u002Fk6e2etests.grafana-dev.net\u002Fa\u002Fk6-app\u002Fprojects\u002F58195\n  ...\n\n── web-vital ratings ──\n  LCP   {\"poor\":5,\"needs-improvement\":1}\n  CLS   {\"good\":2}\n  ...\n```\n\nTwo paragraphs of text capture which navigations are slow, which\nweb vitals are regressing, and the overall span-name distribution\n— enough to reason about browser performance without paging through\nthe OTLP tree.\n\n### Notes worth knowing\n\n- **Header is mandatory.** Both `\u002Fsearch` and `\u002Ftraces\u002F\u003Cid>` return\n  HTTP 401 without `X-K6TestRun-Id`. The header scopes the query to\n  the run's tenant.\n- **`start`\u002F`end` are unix seconds.** RFC3339 ISO strings get\n  `HTTP 400 invalid start: strconv.ParseUint`. They're technically\n  optional — search works without them — but providing a window\n  matching the run's `created`\u002F`ended` (plus ~60s buffer) keeps the\n  query fast and avoids matching unrelated runs that share the\n  scenario name.\n- **TraceQL, not LogQL.** The `q` parameter uses TraceQL — span\n  predicates are written as `span.\u003Cattribute>` and combined with\n  `&&`. The suggested query filters iteration root spans for a\n  specific scenario; broaden by dropping `test.scenario`, narrow by\n  adding e.g. `span.test.vu = 3 && span.test.iteration.number = 5`\n  to pinpoint a single iteration on a single VU.\n- **Scenario names come from the run.** They're the *keys* of\n  `.options.scenarios` on the run object —\n  `gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F$RUN_ID\n  --json options 2>\u002Fdev\u002Fnull | jq -r '.options.scenarios | keys[]'`\n  lists them. The default scenario is named `default`; browser tests\n  often name it `ui`, `browser`, etc.\n- **Span IDs in the OTLP body are base64.** The `traceID` in the\n  search response is hex (the form `\u002Ftraces\u002F\u003Cid>` accepts); the\n  inner `traceId`\u002F`spanId`\u002F`parentSpanId` fields inside the OTLP\n  batch are base64-encoded bytes. Cross-correlate parent\u002Fchild via\n  `parentSpanId == spanId`, both in base64 — no need to decode.\n- **Useful attribute keys** on browser-test spans: `navigation.url`,\n  `page.goto.url`, `screenshot.path`, `web_vital.name`,\n  `web_vital.value`, `web_vital.rating`, `test.scenario`, `test.vu`,\n  `test.iteration.number`, `k6.test_run_id`. These are the ones\n  worth surfacing in summaries; the OTel value envelope is\n  `{stringValue|intValue|boolValue|doubleValue}` (the jq\n  `attrval` helper above handles all four).\n\n---\n\n## 8. Cloud Insights (audit results for a run)\n\nCloud Insights runs heuristics against a finished test — checks for\nhigh cardinality, web-vital regressions, missing thresholds,\noverutilised load generators, and so on — and exposes the results\nthrough a separate `\u002Fresources\u002Finsights\u002F` plugin route (not\n`\u002Fcloud\u002Fv{N}\u002F`). gcx still handles auth; no extra header is needed.\n\nThree calls produce the data, and the agent-useful output is a join\nacross two of them:\n\n```bash\nRUN_ID=\"\u003Crun_id>\"\nBASE=\"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Finsights\u002Finsights\u002Fapi\u002Fv1\u002Ftestrun\u002F$RUN_ID\"\n\n# 1. List executions for the run, take the most recent. The response\n#    is { \"executions\": [ {id, version}, ... ] } — NOT a bare array.\n#    Pick the last entry; insights re-runs append, and the newest one\n#    reflects the current set of audits\u002Fscores.\nEXEC_ID=$(gcx api \"$BASE\u002Fexecutions\" -o json 2>\u002Fdev\u002Fnull \\\n  | jq -r '.executions[-1].id')\n\n# 2. Audit definitions (id, title, description, weight). ~15 items.\ngcx api \"$BASE\u002Fexecutions\u002F$EXEC_ID\u002Faudits\" -o json 2>\u002Fdev\u002Fnull \\\n  > \u002Ftmp\u002Finsights_audits_${RUN_ID}.json\n\n# 3. Audit results (audit_id, status, score, explanation, actions).\ngcx api \"$BASE\u002Fexecutions\u002F$EXEC_ID\u002Faudits\u002Fresults\" -o json 2>\u002Fdev\u002Fnull \\\n  > \u002Ftmp\u002Finsights_results_${RUN_ID}.json\n```\n\nBoth responses use the same top-level key — `audits` — but the\n*contents* differ: step 2 is the catalog of what each audit checks,\nstep 3 is what that audit found on this particular run. Cross-join\nthem via `result.audit_id == audit.id` (1:1 in practice).\n\n### Joining into a compact, agent-readable summary\n\nThe raw audit + results JSON together is ~10 KB. Dumping both into\ncontext just to read out three lines per audit is wasteful — do the\njoin in `jq` and emit a single tight block. The pipeline below is\nthe recommended shape:\n\n```bash\njq -nr \\\n  --slurpfile a \u002Ftmp\u002Finsights_audits_${RUN_ID}.json \\\n  --slurpfile r \u002Ftmp\u002Finsights_results_${RUN_ID}.json '\n  ($a[0].audits | INDEX(.id)) as $defs\n  | $r[0].audits\n  | map({\n      title:         ($defs[.audit_id].title \u002F\u002F \"?\"),\n      description:   ($defs[.audit_id].description \u002F\u002F \"\"),\n      status:        .status,\n      status_reason: .status_reason,\n      score: (\n        if .score == null            then \"n\u002Fa\"\n        elif .score.type == \"binary\" then (if .score.value then \"pass\" else \"fail\" end)\n        else (.score.value | tostring)\n        end),\n      explanation: (.explanation \u002F\u002F \"\" | gsub(\"\\n+\"; \" \") | .[0:300]),\n      actions:     (.actions \u002F\u002F [])\n    })\n  | .[]\n  | \"── \\(.title) — score: \\(.score)\\(if .status == \"failed\" then \" [audit did not run: \\(.status_reason \u002F\u002F \"unknown\")]\" else \"\" end)\\n  \\(.description)\\n  → \\(.explanation)\\(if (.actions|length) > 0 then \"\\n  actions:\\n    - \" + (.actions|join(\"\\n    - \")) else \"\" end)\\n\"\n'\n```\n\nFor a 15-audit run this emits ~5 KB of plain text — title, score,\none-line description, one-line explanation, and any action items.\nThat's enough for the agent to reason about the test's health\nwithout re-reading either JSON blob.\n\n### Notes worth knowing\n\n- **`status` ≠ verdict.** `status: \"succeeded\"` means *the audit\n  executed*. The verdict lives in `score` (`binary` true\u002Ffalse, or\n  `numeric` 0…1 where 1 is best). `status: \"failed\"` means the audit\n  itself could not run (typically `status_reason: \"missing data\"` —\n  e.g. the HTTP Spans audit on a non-tracing test); the `score` field\n  is absent. Treat these as \"no signal\", not as failures.\n- **Score thresholds vary per audit.** A `numeric` 0.94 might be\n  fine for one audit and concerning for another — there's no global\n  cutoff. The `explanation` is authoritative for what the score\n  means; surface it verbatim rather than inventing a pass\u002Ffail rule.\n- **`actions` is the actionable bit.** Only present when the audit\n  has concrete recommendations (e.g. \"Reduce the cardinality of the\n  `url` label …\"). When summarising a run for a user who's trying to\n  improve it, lead with audits that have a non-empty `actions` array.\n- **Pick the last execution, not the first.** `.executions[]` is in\n  chronological order; re-runs append. Older executions reflect\n  older audit logic and may have stale results.\n- **Insights is a post-run analysis.** If the run hasn't finished\n  (or never produced enough data for insights to compute), the\n  executions list may be empty — bail out gracefully on\n  `length == 0`.\n\n---\n\n## 9. Local k6 CLI (smoke tests and `k6 cloud run`)\n\nThe local `k6` CLI is the right tool for parse checks and 1-iteration\nsmoke runs before pushing to cloud:\n\n```bash\nk6 inspect script.js | head -20      # parse-only sanity\nk6 run --quiet script.js             # run locally\n```\n\nFor `k6 cloud run` (uploads + runs in cloud from your laptop), authenticate\n`k6 cloud login` with the token and stack URL pulled from gcx — token\ncomes from `gcx k6 auth token`, stack URL from the active gcx context's\n`grafana.server` field:\n\n```bash\nTOKEN=$(gcx --context \u003Cctx> k6 auth token)\nSTACK=$(gcx --context \u003Cctx> config view --minify -o json | jq -r '.contexts[].grafana.server')\nk6 cloud login --token \"$TOKEN\" --stack \"$STACK\"\nk6 cloud run script.js\n```\n\nk6's cloud config (`~\u002F.config\u002Fk6\u002Fcloud.json`) is single-context, so\nre-run `k6 cloud login` whenever you switch gcx contexts — otherwise\n`k6 cloud run` will keep targeting the previous stack.\n\nExit codes: `0` pass, `99` threshold fail, anything else = script\u002Fruntime error.\n\n---\n\n## 10. Gotchas\n\n| Symptom                                                                              | Cause                                                                | Fix |\n|--------------------------------------------------------------------------------------|----------------------------------------------------------------------|-----|\n| `401 \"Invalid or expired token — run gcx login to refresh\"`                          | gcx OAuth session expired                                            | `gcx login --context \u003Cctx>` |\n| `403 \u002F 404` on a path that looks right                                               | Forgot the doubled `cloud\u002Fcloud\u002F` for a REST endpoint                | Use `…\u002Fresources\u002Fcloud\u002Fcloud\u002Fv{N}\u002F…` |\n| `415 unsupported media type` on script PUT                                           | Missing `-H \"Content-Type: application\u002Foctet-stream\"`                | Add it; pass `-vvv` (or `--log-http-payload`) to `gcx api` to inspect the request |\n| Script PUT returns 200 but doesn't take effect                                       | `updated` timestamp does not bump on script change                   | Verify by sha256 of GET (§5 step 7) |\n| Run status `passed` but checks failed                                                | Zero-observation thresholds report as pass; `check()` alone never fails a run | Add `'checks{check:\u003Cname>}': ['rate==1.0']`; in catch blocks, `check(null, {\"script completed\":()=>false})` to force an observation |\n| Loki query returns nothing for a recent run                                          | `X-K6TestRun-Id` header missing                                      | Always pass `-H \"X-K6TestRun-Id: \u003Crun_id>\"` on log queries |\n| `gcx k6 runs list --limit 0` returns the **oldest** 1000 rows, not the newest        | Subcommand doesn't follow `@nextLink` and defaults to ascending order — for >1000 runs the `first\u002Flast` you see are the start of the history, not the recent activity | Use `gcx api` with `$orderby=created desc` for a newest-first slice, or the full `@nextLink` loop in §3 |\n| `gcx k6 load-tests update -f` returns `✔ Updated` but the change doesn't take effect | Fields outside the v6 PATCH schema (`PatchLoadTestApiModel` allows only `name`, `baseline_test_run_id` — `additionalProperties: false`) are silently dropped. Notably `project_id` is NOT updatable this way | For project moves use the dedicated `\u002Fmove` endpoint (§11); for other mutations cross-check the PATCH schema in the OpenAPI spec. Always re-GET to confirm |\n| `gcx k6 load-tests list --project-id \u003Cid>` returns tests from all projects           | The flag is accepted but never filters — `\u002Fcloud\u002Fv6\u002Fload_tests` has no project query param | Use `GET \u002Fcloud\u002Fv6\u002Fprojects\u002F{id}\u002Fload_tests` via `gcx api`, or filter client-side with `select(.project_id == X)` in jq |\n| `HTTP 415 \"Unsupported media type \\\"application\u002Fjson\\\"\"` on a multipart POST through `gcx api` | The Grafana plugin proxy rewrites multipart Content-Types to `application\u002Fjson` before forwarding (gcx itself sends the header you set; the proxy strips it) | Fall back to direct curl against `api.k6.io` (§1.2). Affects test creation (`POST \u002Fcloud\u002Fv6\u002Fprojects\u002F{id}\u002Fload_tests`) and any other multipart endpoint |\n| `401 Unauthorized` calling `api.k6.io` \u002F `cloudlogs.k6.io` directly (curl mode)      | Missing\u002Fwrong `Authorization: Bearer …` or `X-Stack-ID` header       | Re-check both headers; resolve `X-Stack-ID` from a stack URL via `\u002Fcloud\u002Fv6\u002Fauth` (§1.2) |\n| `404` calling `api.k6.io\u002Fapi\u002Fplugins\u002F...` (curl mode)                                | Left the plugin-proxy prefix in by mistake                           | Strip `\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002F{cloud,logs,insights}` — see §1.2 |\n\n---\n\n## 11. Mutations not covered by `update -f`\n\n`gcx k6 \u003Cresource> update -f` follows the v6 PATCH schema for that\nresource. Fields outside the schema are silently dropped while gcx\nstill prints `✔ Updated \u003Cresource> \u003Cid>` — see the §10 row. Several\ncommon mutations have **dedicated endpoints instead**, and the PATCH\nroute will no-op on them.\n\n| Mutation                              | Endpoint                                              | Body                          |\n|---------------------------------------|-------------------------------------------------------|-------------------------------|\n| Move test to another project          | `PUT \u002Fcloud\u002Fv6\u002Fload_tests\u002F{id}\u002Fmove`                  | `{\"project_id\": \u003Cint>}`       |\n| Start a test run                      | `POST \u002Fcloud\u002Fv6\u002Fload_tests\u002F{id}\u002Fstart`                | `{}` (or run options)         |\n\n**Polling a started run:** After starting a run, poll\n`GET \u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}` until `status` reaches `completed` or\n`aborted`. Always check the `result` field alongside `status` —\n`status: completed` with `result: error` means a configuration or\ninfrastructure failure (not a threshold breach). On any non-`passed`\nresult, immediately fetch logs (§4) to surface the error rather than\nwaiting for the user to report it.\n\n| Abort a running test                  | `POST \u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}\u002Fabort`                 | empty                         |\n| Set \u002F overwrite a schedule            | `POST \u002Fcloud\u002Fv6\u002Fload_tests\u002F{id}\u002Fschedule`             | Schedule body (recurrence_rule or cron) |\n| Deactivate \u002F reactivate a schedule    | `POST \u002Fcloud\u002Fv6\u002Fschedules\u002F{id}\u002F{deactivate,activate}` | empty                         |\n| Create a load test (multipart!)       | `POST \u002Fcloud\u002Fv6\u002Fprojects\u002F{id}\u002Fload_tests`             | multipart: `name` + `script`  |\n| Persist a run past retention          | `POST \u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}\u002Fsave`                  | empty (paired with `\u002Funsave`) |\n\nThe PATCH-style updates that *do* work via `update -f`:\n\n| Resource     | Updatable fields                                              |\n|--------------|---------------------------------------------------------------|\n| load test    | `name`, `baseline_test_run_id` (per `PatchLoadTestApiModel`)  |\n| project      | `name` only (per `PatchProjectApiModel`)                      |\n\nBoth schemas declare `additionalProperties: false` — any other field\nyou put in the manifest is silently filtered out before the PATCH is\nsent, even though gcx still reports `✔ Updated`. Don't try to flip\n`is_default` or move a `grafana_folder_uid` through `update -f`;\nthey're not exposed for mutation on the v6 PATCH.\n\nCross-check by reading the operation's request schema in the OpenAPI\nspec (workflow in §3) before assuming a field is mutable.\n\n### Worked example — move a test between projects\n\n```bash\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F\u003Ctest_id>\u002Fmove \\\n  -X PUT \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"project_id\": \u003Cnew_project_id>}'\n\n# Verify — re-GET and check project_id reflects the new value.\n# Do not trust the absence of an error from the PUT; HTTP 204 with\n# empty body is the success shape but gcx api prints nothing.\ngcx --context \u003Cctx> k6 load-tests get \u003Ctest_id> -o json | jq '{id, name, project_id}'\n```\n\nThe OpenAPI description for this endpoint is explicit: *\"Move a load\ntest to a different project of the same organization. All respective\ntest runs will be also moved to the new project.\"* You don't need to\nmigrate runs separately.\n\n### Cascade behavior worth knowing\n\n- **Deleting a load test cascade-deletes its schedule.** The schedule\n  is gone from `\u002Fcloud\u002Fv6\u002Fschedules` and `\u002Fcloud\u002Fv6\u002Fload_tests\u002F{id}\u002Fschedule`\n  immediately. No need to `gcx k6 schedules delete \u003Cload-test-id>`\n  first as a defensive step.\n- **Deleting a project with a running test fails with HTTP 409**\n  (\"Cannot delete project with a running test.\" per the OpenAPI\n  spec). Non-running tests appear to be removed with the project,\n  but if you want to inventory a project's contents before deleting\n  it, use `GET \u002Fcloud\u002Fv6\u002Fprojects\u002F{id}\u002Fload_tests` (NOT\n  `gcx k6 load-tests list --project-id \u003Cid>`, which doesn't filter —\n  see §10).\n- **Moving a test moves its runs and run history with it.** Schedule\n  attachment also follows the test (it's keyed by `load_test_id`,\n  not by project).\n\n### Verification rule of thumb\n\nThe recurring pattern in this skill is *\"gcx confirms success even\nwhen the underlying call no-ops\"*. Whenever you mutate state:\n\n1. Note what you expected to change (field, count, status).\n2. Re-GET the resource and confirm the change is reflected.\n3. If it isn't, check whether the mutation needed a dedicated\n   endpoint (this section) rather than `update -f`.\n",{"data":37,"body":38},{"name":4,"description":6},{"type":39,"children":40},"root",[41,50,65,131,135,142,149,253,289,295,308,440,447,452,721,727,881,901,906,1029,1032,1045,1057,1109,1195,1223,1234,1244,1855,1858,1864,1882,1888,2126,2132,2195,2206,2303,2308,2425,2444,2679,2706,2712,2751,2757,2762,2765,2778,2798,3364,3385,3405,3440,3445,3544,3547,3553,3559,3564,3648,3653,3666,3672,3677,3826,3843,3937,3949,4424,4452,4455,4461,4488,5255,5261,5346,5349,5361,5387,5399,6236,6242,6247,7573,7578,7588,7593,7598,7925,7928,7934,7954,7959,8347,8375,8381,8393,8633,8638,8643,8812,8815,8828,8840,8905,8940,9161,9188,9209,9212,9218,9811,9814,9826,9852,9932,10010,10075,10093,10170,10212,10217,10223,10447,10459,10465,10543,10549,10561,10585],{"type":42,"tag":43,"props":44,"children":46},"element","h1",{"id":45},"grafana-cloud-k6-interaction-reference",[47],{"type":48,"value":49},"text","Grafana Cloud k6 — interaction reference",{"type":42,"tag":51,"props":52,"children":53},"p",{},[54,56,63],{"type":48,"value":55},"The default path is the ",{"type":42,"tag":57,"props":58,"children":60},"code",{"className":59},[],[61],{"type":48,"value":62},"gcx",{"type":48,"value":64}," CLI. When gcx isn't installed, every\nendpoint here is still reachable via direct curl against k6's public\nhosts — see §1.2 for the auth-header and host-translation rules. Two\nprinciples shape the rest:",{"type":42,"tag":66,"props":67,"children":68},"ul",{},[69,89],{"type":42,"tag":70,"props":71,"children":72},"li",{},[73,79,81,87],{"type":42,"tag":74,"props":75,"children":76},"strong",{},[77],{"type":48,"value":78},"gcx owns Grafana-side auth (when present).",{"type":48,"value":80}," It injects the right\nheaders on every call, so you should not set auth headers yourself.\nThe only header you ever set by hand is ",{"type":42,"tag":57,"props":82,"children":84},{"className":83},[],[85],{"type":48,"value":86},"X-K6TestRun-Id",{"type":48,"value":88},", on Loki\nlog queries (§4), browser screenshot\u002Ffile fetches (§6), and Tempo\ntrace queries (§7) — anything else gets overwritten or causes\nconflicts. In curl mode the auth headers are manual; see §1.2.",{"type":42,"tag":70,"props":90,"children":91},{},[92,105,107,113,115,121,123,129],{"type":42,"tag":74,"props":93,"children":94},{},[95,97,103],{"type":48,"value":96},"Reach for ",{"type":42,"tag":57,"props":98,"children":100},{"className":99},[],[101],{"type":48,"value":102},"gcx k6 ...",{"type":48,"value":104}," subcommands first.",{"type":48,"value":106}," They wrap the common\npaths with friendlier ergonomics and handle pagination. Discover\nwhat's available with ",{"type":42,"tag":57,"props":108,"children":110},{"className":109},[],[111],{"type":48,"value":112},"gcx help-tree k6",{"type":48,"value":114}," (and drill in further with\n",{"type":42,"tag":57,"props":116,"children":118},{"className":117},[],[119],{"type":48,"value":120},"gcx help-tree k6 \u003Csubcommand>",{"type":48,"value":122},"); fall back to ",{"type":42,"tag":57,"props":124,"children":126},{"className":125},[],[127],{"type":48,"value":128},"gcx api",{"type":48,"value":130}," only when\nno subcommand exists for what you need.",{"type":42,"tag":132,"props":133,"children":134},"hr",{},[],{"type":42,"tag":136,"props":137,"children":139},"h2",{"id":138},"_1-authentication",[140],{"type":48,"value":141},"1. Authentication",{"type":42,"tag":143,"props":144,"children":146},"h3",{"id":145},"_11-with-gcx-default",[147],{"type":48,"value":148},"1.1 With gcx (default)",{"type":42,"tag":150,"props":151,"children":156},"pre",{"className":152,"code":153,"language":154,"meta":155,"style":155},"language-bash shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","gcx login --context \u003Cctx>                # one-time OAuth, browser flow\ngcx --context \u003Cctx> config check         # expect \"✔ Connectivity: online\"\n","bash","",[157],{"type":42,"tag":57,"props":158,"children":159},{"__ignoreMap":155},[160,210],{"type":42,"tag":161,"props":162,"children":165},"span",{"class":163,"line":164},"line",1,[166,171,177,182,188,193,199,204],{"type":42,"tag":161,"props":167,"children":169},{"style":168},"--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B",[170],{"type":48,"value":62},{"type":42,"tag":161,"props":172,"children":174},{"style":173},"--shiki-light:#91B859;--shiki-default:#C3E88D;--shiki-dark:#C3E88D",[175],{"type":48,"value":176}," login",{"type":42,"tag":161,"props":178,"children":179},{"style":173},[180],{"type":48,"value":181}," --context",{"type":42,"tag":161,"props":183,"children":185},{"style":184},"--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF",[186],{"type":48,"value":187}," \u003C",{"type":42,"tag":161,"props":189,"children":190},{"style":173},[191],{"type":48,"value":192},"ct",{"type":42,"tag":161,"props":194,"children":196},{"style":195},"--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8",[197],{"type":48,"value":198},"x",{"type":42,"tag":161,"props":200,"children":201},{"style":184},[202],{"type":48,"value":203},">",{"type":42,"tag":161,"props":205,"children":207},{"style":206},"--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#546E7A;--shiki-default-font-style:italic;--shiki-dark:#676E95;--shiki-dark-font-style:italic",[208],{"type":48,"value":209},"                # one-time OAuth, browser flow\n",{"type":42,"tag":161,"props":211,"children":213},{"class":163,"line":212},2,[214,218,222,226,230,234,238,243,248],{"type":42,"tag":161,"props":215,"children":216},{"style":168},[217],{"type":48,"value":62},{"type":42,"tag":161,"props":219,"children":220},{"style":173},[221],{"type":48,"value":181},{"type":42,"tag":161,"props":223,"children":224},{"style":184},[225],{"type":48,"value":187},{"type":42,"tag":161,"props":227,"children":228},{"style":173},[229],{"type":48,"value":192},{"type":42,"tag":161,"props":231,"children":232},{"style":195},[233],{"type":48,"value":198},{"type":42,"tag":161,"props":235,"children":236},{"style":184},[237],{"type":48,"value":203},{"type":42,"tag":161,"props":239,"children":240},{"style":173},[241],{"type":48,"value":242}," config",{"type":42,"tag":161,"props":244,"children":245},{"style":173},[246],{"type":48,"value":247}," check",{"type":42,"tag":161,"props":249,"children":250},{"style":206},[251],{"type":48,"value":252},"         # expect \"✔ Connectivity: online\"\n",{"type":42,"tag":51,"props":254,"children":255},{},[256,258,264,266,271,273,279,281,287],{"type":48,"value":257},"Once a context is logged in, every ",{"type":42,"tag":57,"props":259,"children":261},{"className":260},[],[262],{"type":48,"value":263},"gcx api ...",{"type":48,"value":265}," and ",{"type":42,"tag":57,"props":267,"children":269},{"className":268},[],[270],{"type":48,"value":102},{"type":48,"value":272}," call\ninherits its auth state. If a call returns ",{"type":42,"tag":274,"props":275,"children":276},"em",{},[277],{"type":48,"value":278},"\"Invalid or expired token —\nrun gcx login to refresh\"",{"type":48,"value":280},", the OAuth session has lapsed — re-run\n",{"type":42,"tag":57,"props":282,"children":284},{"className":283},[],[285],{"type":48,"value":286},"gcx login --context \u003Cctx>",{"type":48,"value":288},".",{"type":42,"tag":143,"props":290,"children":292},{"id":291},"_12-without-gcx-direct-curl",[293],{"type":48,"value":294},"1.2 Without gcx — direct curl",{"type":42,"tag":51,"props":296,"children":297},{},[298,300,306],{"type":48,"value":299},"Check ",{"type":42,"tag":57,"props":301,"children":303},{"className":302},[],[304],{"type":48,"value":305},"command -v gcx",{"type":48,"value":307}," first. If it's missing, every endpoint in this\nskill is still reachable directly against k6's public hosts — three\nthings change versus the gcx examples elsewhere:",{"type":42,"tag":66,"props":309,"children":310},{},[311,342,406],{"type":42,"tag":70,"props":312,"children":313},{},[314,319,321],{"type":42,"tag":74,"props":315,"children":316},{},[317],{"type":48,"value":318},"Auth headers are manual.",{"type":48,"value":320}," Set both on every call:\n",{"type":42,"tag":66,"props":322,"children":323},{},[324,333],{"type":42,"tag":70,"props":325,"children":326},{},[327],{"type":42,"tag":57,"props":328,"children":330},{"className":329},[],[331],{"type":48,"value":332},"Authorization: Bearer \u003Ck6_token>",{"type":42,"tag":70,"props":334,"children":335},{},[336],{"type":42,"tag":57,"props":337,"children":339},{"className":338},[],[340],{"type":48,"value":341},"X-Stack-ID: \u003Cint>",{"type":42,"tag":70,"props":343,"children":344},{},[345,350],{"type":42,"tag":74,"props":346,"children":347},{},[348],{"type":48,"value":349},"Hosts replace the plugin proxy.",{"type":42,"tag":66,"props":351,"children":352},{},[353,395],{"type":42,"tag":70,"props":354,"children":355},{},[356,358,364,366,372,373,379,381,387,389],{"type":48,"value":357},"REST (",{"type":42,"tag":57,"props":359,"children":361},{"className":360},[],[362],{"type":48,"value":363},"\u002Fcloud\u002Fv6\u002F...",{"type":48,"value":365},", ",{"type":42,"tag":57,"props":367,"children":369},{"className":368},[],[370],{"type":48,"value":371},"\u002Fcloud\u002Fv5\u002F...",{"type":48,"value":365},{"type":42,"tag":57,"props":374,"children":376},{"className":375},[],[377],{"type":48,"value":378},"\u002Fcloud-resources\u002Fv1\u002F...",{"type":48,"value":380},",\n",{"type":42,"tag":57,"props":382,"children":384},{"className":383},[],[385],{"type":48,"value":386},"\u002Finsights\u002F...",{"type":48,"value":388},") → ",{"type":42,"tag":57,"props":390,"children":392},{"className":391},[],[393],{"type":48,"value":394},"https:\u002F\u002Fapi.k6.io",{"type":42,"tag":70,"props":396,"children":397},{},[398,400],{"type":48,"value":399},"Logs (Loki) and traces (Tempo) → ",{"type":42,"tag":57,"props":401,"children":403},{"className":402},[],[404],{"type":48,"value":405},"https:\u002F\u002Fcloudlogs.k6.io",{"type":42,"tag":70,"props":407,"children":408},{},[409,422,424,430,432,438],{"type":42,"tag":74,"props":410,"children":411},{},[412,414,420],{"type":48,"value":413},"No ",{"type":42,"tag":57,"props":415,"children":417},{"className":416},[],[418],{"type":48,"value":419},"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002F{cloud,logs,insights}",{"type":48,"value":421}," prefix.",{"type":48,"value":423},"\nDrop it; everything after that prefix in the gcx examples is the\nreal k6 path. The doubled ",{"type":42,"tag":57,"props":425,"children":427},{"className":426},[],[428],{"type":48,"value":429},"cloud\u002Fcloud\u002F",{"type":48,"value":431}," quirk from §2 collapses to\na single ",{"type":42,"tag":57,"props":433,"children":435},{"className":434},[],[436],{"type":48,"value":437},"\u002Fcloud\u002F",{"type":48,"value":439}," — the first one was just the proxy route.",{"type":42,"tag":441,"props":442,"children":444},"h4",{"id":443},"obtaining-the-credentials",[445],{"type":48,"value":446},"Obtaining the credentials",{"type":42,"tag":51,"props":448,"children":449},{},[450],{"type":48,"value":451},"Don't guess these — prompt the user once per session for:",{"type":42,"tag":453,"props":454,"children":455},"ol",{},[456,474],{"type":42,"tag":70,"props":457,"children":458},{},[459,464,466,472],{"type":42,"tag":74,"props":460,"children":461},{},[462],{"type":48,"value":463},"k6 API token",{"type":48,"value":465}," — long-lived bearer; the same value\n",{"type":42,"tag":57,"props":467,"children":469},{"className":468},[],[470],{"type":48,"value":471},"gcx k6 auth token",{"type":48,"value":473}," would print when gcx is configured.",{"type":42,"tag":70,"props":475,"children":476},{},[477,482,484,489,491,497,499,504,506,512,514,520,522,528,530,536,538,679,683,685,690,692,698,700,705,707,712,714,719],{"type":42,"tag":74,"props":478,"children":479},{},[480],{"type":48,"value":481},"Stack",{"type":48,"value":483}," — either the integer ",{"type":42,"tag":74,"props":485,"children":486},{},[487],{"type":48,"value":488},"stack ID",{"type":48,"value":490}," (used directly in\n",{"type":42,"tag":57,"props":492,"children":494},{"className":493},[],[495],{"type":48,"value":496},"X-Stack-ID",{"type":48,"value":498},") or a Grafana ",{"type":42,"tag":74,"props":500,"children":501},{},[502],{"type":48,"value":503},"stack URL",{"type":48,"value":505}," (e.g.\n",{"type":42,"tag":57,"props":507,"children":509},{"className":508},[],[510],{"type":48,"value":511},"https:\u002F\u002Fmyorg.grafana.net",{"type":48,"value":513},"). If the user supplies a URL, resolve\nit to an ID once with ",{"type":42,"tag":57,"props":515,"children":517},{"className":516},[],[518],{"type":48,"value":519},"GET \u002Fcloud\u002Fv6\u002Fauth",{"type":48,"value":521},", which takes the URL in\nthe ",{"type":42,"tag":57,"props":523,"children":525},{"className":524},[],[526],{"type":48,"value":527},"X-Stack-Url",{"type":48,"value":529}," header and returns ",{"type":42,"tag":57,"props":531,"children":533},{"className":532},[],[534],{"type":48,"value":535},"{stack_id, default_project_id}",{"type":48,"value":537},":",{"type":42,"tag":150,"props":539,"children":541},{"className":152,"code":540,"language":154,"meta":155,"style":155},"STACK_ID=$(curl -sS https:\u002F\u002Fapi.k6.io\u002Fcloud\u002Fv6\u002Fauth \\\n  -H \"Authorization: Bearer $K6_TOKEN\" \\\n  -H \"X-Stack-Url: $STACK_URL\" \\\n  | jq -r '.stack_id')\n",[542],{"type":42,"tag":57,"props":543,"children":544},{"__ignoreMap":155},[545,578,610,640],{"type":42,"tag":161,"props":546,"children":547},{"class":163,"line":164},[548,553,558,563,568,573],{"type":42,"tag":161,"props":549,"children":550},{"style":195},[551],{"type":48,"value":552},"STACK_ID",{"type":42,"tag":161,"props":554,"children":555},{"style":184},[556],{"type":48,"value":557},"=$(",{"type":42,"tag":161,"props":559,"children":560},{"style":168},[561],{"type":48,"value":562},"curl",{"type":42,"tag":161,"props":564,"children":565},{"style":173},[566],{"type":48,"value":567}," -sS",{"type":42,"tag":161,"props":569,"children":570},{"style":173},[571],{"type":48,"value":572}," https:\u002F\u002Fapi.k6.io\u002Fcloud\u002Fv6\u002Fauth",{"type":42,"tag":161,"props":574,"children":575},{"style":195},[576],{"type":48,"value":577}," \\\n",{"type":42,"tag":161,"props":579,"children":580},{"class":163,"line":212},[581,586,591,596,601,606],{"type":42,"tag":161,"props":582,"children":583},{"style":173},[584],{"type":48,"value":585},"  -H",{"type":42,"tag":161,"props":587,"children":588},{"style":184},[589],{"type":48,"value":590}," \"",{"type":42,"tag":161,"props":592,"children":593},{"style":173},[594],{"type":48,"value":595},"Authorization: Bearer ",{"type":42,"tag":161,"props":597,"children":598},{"style":195},[599],{"type":48,"value":600},"$K6_TOKEN",{"type":42,"tag":161,"props":602,"children":603},{"style":184},[604],{"type":48,"value":605},"\"",{"type":42,"tag":161,"props":607,"children":608},{"style":195},[609],{"type":48,"value":577},{"type":42,"tag":161,"props":611,"children":613},{"class":163,"line":612},3,[614,618,622,627,632,636],{"type":42,"tag":161,"props":615,"children":616},{"style":173},[617],{"type":48,"value":585},{"type":42,"tag":161,"props":619,"children":620},{"style":184},[621],{"type":48,"value":590},{"type":42,"tag":161,"props":623,"children":624},{"style":173},[625],{"type":48,"value":626},"X-Stack-Url: ",{"type":42,"tag":161,"props":628,"children":629},{"style":195},[630],{"type":48,"value":631},"$STACK_URL",{"type":42,"tag":161,"props":633,"children":634},{"style":184},[635],{"type":48,"value":605},{"type":42,"tag":161,"props":637,"children":638},{"style":195},[639],{"type":48,"value":577},{"type":42,"tag":161,"props":641,"children":643},{"class":163,"line":642},4,[644,649,654,659,664,669,674],{"type":42,"tag":161,"props":645,"children":646},{"style":184},[647],{"type":48,"value":648},"  |",{"type":42,"tag":161,"props":650,"children":651},{"style":168},[652],{"type":48,"value":653}," jq",{"type":42,"tag":161,"props":655,"children":656},{"style":173},[657],{"type":48,"value":658}," -r",{"type":42,"tag":161,"props":660,"children":661},{"style":184},[662],{"type":48,"value":663}," '",{"type":42,"tag":161,"props":665,"children":666},{"style":173},[667],{"type":48,"value":668},".stack_id",{"type":42,"tag":161,"props":670,"children":671},{"style":184},[672],{"type":48,"value":673},"'",{"type":42,"tag":161,"props":675,"children":676},{"style":184},[677],{"type":48,"value":678},")\n",{"type":42,"tag":680,"props":681,"children":682},"br",{},[],{"type":48,"value":684},"Cache the resolved ID for the session — every subsequent call\nneeds it in ",{"type":42,"tag":57,"props":686,"children":688},{"className":687},[],[689],{"type":48,"value":496},{"type":48,"value":691},". (Note: ",{"type":42,"tag":57,"props":693,"children":695},{"className":694},[],[696],{"type":48,"value":697},"\u002Fcloud\u002Fv6\u002Fauth",{"type":48,"value":699}," is the ",{"type":42,"tag":274,"props":701,"children":702},{},[703],{"type":48,"value":704},"only",{"type":48,"value":706},"\nendpoint that takes ",{"type":42,"tag":57,"props":708,"children":710},{"className":709},[],[711],{"type":48,"value":527},{"type":48,"value":713}," instead of ",{"type":42,"tag":57,"props":715,"children":717},{"className":716},[],[718],{"type":48,"value":496},{"type":48,"value":720}," — it's\nhow you cross the gap from \"user-known URL\" to \"API-required ID\".)",{"type":42,"tag":441,"props":722,"children":724},{"id":723},"translation-cheat-sheet",[725],{"type":48,"value":726},"Translation cheat-sheet",{"type":42,"tag":728,"props":729,"children":730},"table",{},[731,750],{"type":42,"tag":732,"props":733,"children":734},"thead",{},[735],{"type":42,"tag":736,"props":737,"children":738},"tr",{},[739,745],{"type":42,"tag":740,"props":741,"children":742},"th",{},[743],{"type":48,"value":744},"gcx form (plugin proxy)",{"type":42,"tag":740,"props":746,"children":747},{},[748],{"type":48,"value":749},"curl form (direct)",{"type":42,"tag":751,"props":752,"children":753},"tbody",{},[754,776,797,818,839,860],{"type":42,"tag":736,"props":755,"children":756},{},[757,767],{"type":42,"tag":758,"props":759,"children":760},"td",{},[761],{"type":42,"tag":57,"props":762,"children":764},{"className":763},[],[765],{"type":48,"value":766},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F123",{"type":42,"tag":758,"props":768,"children":769},{},[770],{"type":42,"tag":57,"props":771,"children":773},{"className":772},[],[774],{"type":48,"value":775},"curl https:\u002F\u002Fapi.k6.io\u002Fcloud\u002Fv6\u002Ftest_runs\u002F123 -H ...",{"type":42,"tag":736,"props":777,"children":778},{},[779,788],{"type":42,"tag":758,"props":780,"children":781},{},[782],{"type":42,"tag":57,"props":783,"children":785},{"className":784},[],[786],{"type":48,"value":787},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv5\u002Ftest_runs\u002F\u003Cid>\u002Fmetrics",{"type":42,"tag":758,"props":789,"children":790},{},[791],{"type":42,"tag":57,"props":792,"children":794},{"className":793},[],[795],{"type":48,"value":796},"curl https:\u002F\u002Fapi.k6.io\u002Fcloud\u002Fv5\u002Ftest_runs\u002F\u003Cid>\u002Fmetrics -H ...",{"type":42,"tag":736,"props":798,"children":799},{},[800,809],{"type":42,"tag":758,"props":801,"children":802},{},[803],{"type":42,"tag":57,"props":804,"children":806},{"className":805},[],[807],{"type":48,"value":808},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Findex",{"type":42,"tag":758,"props":810,"children":811},{},[812],{"type":42,"tag":57,"props":813,"children":815},{"className":814},[],[816],{"type":48,"value":817},"curl https:\u002F\u002Fapi.k6.io\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Findex -H ...",{"type":42,"tag":736,"props":819,"children":820},{},[821,830],{"type":42,"tag":758,"props":822,"children":823},{},[824],{"type":42,"tag":57,"props":825,"children":827},{"className":826},[],[828],{"type":48,"value":829},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Finsights\u002Finsights\u002Fapi\u002Fv1\u002Ftestrun\u002F\u003Cid>\u002Fexecutions",{"type":42,"tag":758,"props":831,"children":832},{},[833],{"type":42,"tag":57,"props":834,"children":836},{"className":835},[],[837],{"type":48,"value":838},"curl https:\u002F\u002Fapi.k6.io\u002Finsights\u002Fapi\u002Fv1\u002Ftestrun\u002F\u003Cid>\u002Fexecutions -H ...",{"type":42,"tag":736,"props":840,"children":841},{},[842,851],{"type":42,"tag":758,"props":843,"children":844},{},[845],{"type":42,"tag":57,"props":846,"children":848},{"className":847},[],[849],{"type":48,"value":850},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Fquery_range?...",{"type":42,"tag":758,"props":852,"children":853},{},[854],{"type":42,"tag":57,"props":855,"children":857},{"className":856},[],[858],{"type":48,"value":859},"curl https:\u002F\u002Fcloudlogs.k6.io\u002Fapi\u002Fv1\u002Fquery_range?... -H ...",{"type":42,"tag":736,"props":861,"children":862},{},[863,872],{"type":42,"tag":758,"props":864,"children":865},{},[866],{"type":42,"tag":57,"props":867,"children":869},{"className":868},[],[870],{"type":48,"value":871},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Fsearch?...",{"type":42,"tag":758,"props":873,"children":874},{},[875],{"type":42,"tag":57,"props":876,"children":878},{"className":877},[],[879],{"type":48,"value":880},"curl https:\u002F\u002Fcloudlogs.k6.io\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Fsearch?... -H ...",{"type":42,"tag":51,"props":882,"children":883},{},[884,886,892,894,900],{"type":48,"value":885},"In every ",{"type":42,"tag":57,"props":887,"children":889},{"className":888},[],[890],{"type":48,"value":891},"-H ...",{"type":48,"value":893}," slot above, send both auth headers:\n",{"type":42,"tag":57,"props":895,"children":897},{"className":896},[],[898],{"type":48,"value":899},"-H \"Authorization: Bearer $K6_TOKEN\" -H \"X-Stack-ID: $STACK_ID\"",{"type":48,"value":288},{"type":42,"tag":51,"props":902,"children":903},{},[904],{"type":48,"value":905},"Notes:",{"type":42,"tag":66,"props":907,"children":908},{},[909,928,980],{"type":42,"tag":70,"props":910,"children":911},{},[912,914,919,921,926],{"type":48,"value":913},"Endpoint-specific headers gcx leaves to you — ",{"type":42,"tag":57,"props":915,"children":917},{"className":916},[],[918],{"type":48,"value":86},{"type":48,"value":920}," on\nlog, trace, and files endpoints (§4, §6, §7) — are still required\n",{"type":42,"tag":274,"props":922,"children":923},{},[924],{"type":48,"value":925},"in addition",{"type":48,"value":927}," to the auth pair.",{"type":42,"tag":70,"props":929,"children":930},{},[931,933,938,940,946,948,954,956,962,964,970,972,978],{"type":48,"value":932},"The ",{"type":42,"tag":57,"props":934,"children":936},{"className":935},[],[937],{"type":48,"value":128},{"type":48,"value":939}," flag quirks in §2 (spill envelope, ",{"type":42,"tag":57,"props":941,"children":943},{"className":942},[],[944],{"type":48,"value":945},"--json field",{"type":48,"value":947},"\nfiltering, ",{"type":42,"tag":57,"props":949,"children":951},{"className":950},[],[952],{"type":48,"value":953},"-o",{"type":48,"value":955}," for output format) don't apply to curl. Use plain\ncurl flags: ",{"type":42,"tag":57,"props":957,"children":959},{"className":958},[],[960],{"type":48,"value":961},"-o file",{"type":48,"value":963}," to save body, ",{"type":42,"tag":57,"props":965,"children":967},{"className":966},[],[968],{"type":48,"value":969},"--data-binary @file",{"type":48,"value":971}," for PUT\npayloads, ",{"type":42,"tag":57,"props":973,"children":975},{"className":974},[],[976],{"type":48,"value":977},"-w '%{http_code}'",{"type":48,"value":979}," for status code, etc.",{"type":42,"tag":70,"props":981,"children":982},{},[983,985,991,992,998,999,1005,1006,1012,1014,1019,1021,1027],{"type":48,"value":984},"Pagination semantics (",{"type":42,"tag":57,"props":986,"children":988},{"className":987},[],[989],{"type":48,"value":990},"$orderby",{"type":48,"value":365},{"type":42,"tag":57,"props":993,"children":995},{"className":994},[],[996],{"type":48,"value":997},"$top",{"type":48,"value":365},{"type":42,"tag":57,"props":1000,"children":1002},{"className":1001},[],[1003],{"type":48,"value":1004},"$skip",{"type":48,"value":365},{"type":42,"tag":57,"props":1007,"children":1009},{"className":1008},[],[1010],{"type":48,"value":1011},"@nextLink",{"type":48,"value":1013},"\nfrom §3) are properties of the v6 endpoints themselves and work\nidentically over curl. The ",{"type":42,"tag":57,"props":1015,"children":1017},{"className":1016},[],[1018],{"type":48,"value":1011},{"type":48,"value":1020}," URL returned by the server\nis already an absolute ",{"type":42,"tag":57,"props":1022,"children":1024},{"className":1023},[],[1025],{"type":48,"value":1026},"https:\u002F\u002Fapi.k6.io\u002F...",{"type":48,"value":1028}," URL — pass it back\nto curl unchanged; the plugin-proxy reshape in §3 isn't needed.",{"type":42,"tag":132,"props":1030,"children":1031},{},[],{"type":42,"tag":136,"props":1033,"children":1035},{"id":1034},"_2-how-gcx-api-paths-are-shaped",[1036,1038,1043],{"type":48,"value":1037},"2. How ",{"type":42,"tag":57,"props":1039,"children":1041},{"className":1040},[],[1042],{"type":48,"value":128},{"type":48,"value":1044}," paths are shaped",{"type":42,"tag":51,"props":1046,"children":1047},{},[1048,1050,1055],{"type":48,"value":1049},"When no subcommand exists, fall back to ",{"type":42,"tag":57,"props":1051,"children":1053},{"className":1052},[],[1054],{"type":48,"value":128},{"type":48,"value":1056}," against the Grafana\nplugin-proxy routes:",{"type":42,"tag":66,"props":1058,"children":1059},{},[1060,1092],{"type":42,"tag":70,"props":1061,"children":1062},{},[1063,1068,1070,1076,1077,1083,1085,1091],{"type":42,"tag":74,"props":1064,"children":1065},{},[1066],{"type":48,"value":1067},"REST API",{"type":48,"value":1069}," (",{"type":42,"tag":57,"props":1071,"children":1073},{"className":1072},[],[1074],{"type":48,"value":1075},"\u002Fcloud\u002Fv6\u002F",{"type":48,"value":365},{"type":42,"tag":57,"props":1078,"children":1080},{"className":1079},[],[1081],{"type":48,"value":1082},"\u002Fcloud\u002Fv5\u002F",{"type":48,"value":1084},") — prefix with\n",{"type":42,"tag":57,"props":1086,"children":1088},{"className":1087},[],[1089],{"type":48,"value":1090},"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002F\u003Ck6-path>",{"type":48,"value":288},{"type":42,"tag":70,"props":1093,"children":1094},{},[1095,1100,1102,1108],{"type":42,"tag":74,"props":1096,"children":1097},{},[1098],{"type":48,"value":1099},"Logs (Loki)",{"type":48,"value":1101}," — prefix with\n",{"type":42,"tag":57,"props":1103,"children":1105},{"className":1104},[],[1106],{"type":48,"value":1107},"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002F\u003Cloki-path>",{"type":48,"value":288},{"type":42,"tag":728,"props":1110,"children":1111},{},[1112,1128],{"type":42,"tag":732,"props":1113,"children":1114},{},[1115],{"type":42,"tag":736,"props":1116,"children":1117},{},[1118,1123],{"type":42,"tag":740,"props":1119,"children":1120},{},[1121],{"type":48,"value":1122},"k6 path",{"type":42,"tag":740,"props":1124,"children":1125},{},[1126],{"type":48,"value":1127},"gcx invocation",{"type":42,"tag":751,"props":1129,"children":1130},{},[1131,1152,1173],{"type":42,"tag":736,"props":1132,"children":1133},{},[1134,1143],{"type":42,"tag":758,"props":1135,"children":1136},{},[1137],{"type":42,"tag":57,"props":1138,"children":1140},{"className":1139},[],[1141],{"type":48,"value":1142},"\u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}",{"type":42,"tag":758,"props":1144,"children":1145},{},[1146],{"type":42,"tag":57,"props":1147,"children":1149},{"className":1148},[],[1150],{"type":48,"value":1151},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}",{"type":42,"tag":736,"props":1153,"children":1154},{},[1155,1164],{"type":42,"tag":758,"props":1156,"children":1157},{},[1158],{"type":42,"tag":57,"props":1159,"children":1161},{"className":1160},[],[1162],{"type":48,"value":1163},"\u002Fcloud\u002Fv5\u002Ftest_runs\u002F{id}\u002Fmetrics",{"type":42,"tag":758,"props":1165,"children":1166},{},[1167],{"type":42,"tag":57,"props":1168,"children":1170},{"className":1169},[],[1171],{"type":48,"value":1172},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv5\u002Ftest_runs\u002F{id}\u002Fmetrics",{"type":42,"tag":736,"props":1174,"children":1175},{},[1176,1187],{"type":42,"tag":758,"props":1177,"children":1178},{},[1179,1181],{"type":48,"value":1180},"Loki ",{"type":42,"tag":57,"props":1182,"children":1184},{"className":1183},[],[1185],{"type":48,"value":1186},"\u002Fapi\u002Fv1\u002Fquery_range?...",{"type":42,"tag":758,"props":1188,"children":1189},{},[1190],{"type":42,"tag":57,"props":1191,"children":1193},{"className":1192},[],[1194],{"type":48,"value":850},{"type":42,"tag":51,"props":1196,"children":1197},{},[1198,1200,1205,1207,1213,1215,1221],{"type":48,"value":1199},"Note the doubled ",{"type":42,"tag":57,"props":1201,"children":1203},{"className":1202},[],[1204],{"type":48,"value":429},{"type":48,"value":1206}," in every REST path — the first ",{"type":42,"tag":57,"props":1208,"children":1210},{"className":1209},[],[1211],{"type":48,"value":1212},"cloud",{"type":48,"value":1214},"\nis the proxy route, the second is k6's ",{"type":42,"tag":57,"props":1216,"children":1218},{"className":1217},[],[1219],{"type":48,"value":1220},"\u002Fcloud\u002Fv{N}\u002F",{"type":48,"value":1222}," namespace.",{"type":42,"tag":143,"props":1224,"children":1226},{"id":1225},"gcx-api-flag-quirks",[1227,1232],{"type":42,"tag":57,"props":1228,"children":1230},{"className":1229},[],[1231],{"type":48,"value":128},{"type":48,"value":1233}," flag quirks",{"type":42,"tag":51,"props":1235,"children":1236},{},[1237,1242],{"type":42,"tag":57,"props":1238,"children":1240},{"className":1239},[],[1241],{"type":48,"value":128},{"type":48,"value":1243}," is not a curl clone — a few flags differ from what curl muscle\nmemory suggests:",{"type":42,"tag":66,"props":1245,"children":1246},{},[1247,1316,1364,1398,1432,1465,1751],{"type":42,"tag":70,"props":1248,"children":1249},{},[1250,1255,1257,1263,1265,1270,1272,1277,1278,1284,1285,1291,1292,1298,1300,1306,1308,1314],{"type":42,"tag":74,"props":1251,"children":1252},{},[1253],{"type":48,"value":1254},"Response body",{"type":48,"value":1256}," is written to stdout. There is no ",{"type":42,"tag":57,"props":1258,"children":1260},{"className":1259},[],[1261],{"type":48,"value":1262},"-o \u003Cfile>",{"type":48,"value":1264}," flag\nfor saving the body; ",{"type":42,"tag":57,"props":1266,"children":1268},{"className":1267},[],[1269],{"type":48,"value":953},{"type":48,"value":1271}," selects output ",{"type":42,"tag":274,"props":1273,"children":1274},{},[1275],{"type":48,"value":1276},"format",{"type":48,"value":1069},{"type":42,"tag":57,"props":1279,"children":1281},{"className":1280},[],[1282],{"type":48,"value":1283},"json",{"type":48,"value":365},{"type":42,"tag":57,"props":1286,"children":1288},{"className":1287},[],[1289],{"type":48,"value":1290},"yaml",{"type":48,"value":380},{"type":42,"tag":57,"props":1293,"children":1295},{"className":1294},[],[1296],{"type":48,"value":1297},"agents",{"type":48,"value":1299},"). Use shell redirection (",{"type":42,"tag":57,"props":1301,"children":1303},{"className":1302},[],[1304],{"type":48,"value":1305},"> file",{"type":48,"value":1307},") or ",{"type":42,"tag":57,"props":1309,"children":1311},{"className":1310},[],[1312],{"type":48,"value":1313},"$(...)",{"type":48,"value":1315}," capture\ninstead.",{"type":42,"tag":70,"props":1317,"children":1318},{},[1319,1324,1326,1332,1333,1339,1341,1347,1349,1355,1357,1362],{"type":42,"tag":74,"props":1320,"children":1321},{},[1322],{"type":48,"value":1323},"Request body",{"type":48,"value":1325}," uses ",{"type":42,"tag":57,"props":1327,"children":1329},{"className":1328},[],[1330],{"type":48,"value":1331},"-d \u003Cstring>",{"type":48,"value":365},{"type":42,"tag":57,"props":1334,"children":1336},{"className":1335},[],[1337],{"type":48,"value":1338},"-d @file",{"type":48,"value":1340},", or ",{"type":42,"tag":57,"props":1342,"children":1344},{"className":1343},[],[1345],{"type":48,"value":1346},"-d @-",{"type":48,"value":1348}," (stdin).\nThere is no ",{"type":42,"tag":57,"props":1350,"children":1352},{"className":1351},[],[1353],{"type":48,"value":1354},"--data-binary",{"type":48,"value":1356},"; ",{"type":42,"tag":57,"props":1358,"children":1360},{"className":1359},[],[1361],{"type":48,"value":1338},{"type":48,"value":1363}," already preserves bytes.",{"type":42,"tag":70,"props":1365,"children":1366},{},[1367,1372,1374,1380,1382,1388,1390,1396],{"type":42,"tag":74,"props":1368,"children":1369},{},[1370],{"type":48,"value":1371},"Field selection without jq",{"type":48,"value":1373},": ",{"type":42,"tag":57,"props":1375,"children":1377},{"className":1376},[],[1378],{"type":48,"value":1379},"--json field1,field2,...",{"type":48,"value":1381}," returns\nonly the listed fields, and ",{"type":42,"tag":57,"props":1383,"children":1385},{"className":1384},[],[1386],{"type":48,"value":1387},"--json list",{"type":48,"value":1389}," (or ",{"type":42,"tag":57,"props":1391,"children":1393},{"className":1392},[],[1394],{"type":48,"value":1395},"--json '?'",{"type":48,"value":1397},")\ndiscovers what's available. Often cleaner than piping into jq for\nshallow extractions.",{"type":42,"tag":70,"props":1399,"children":1400},{},[1401,1406,1408,1414,1416,1422,1424,1430],{"type":42,"tag":74,"props":1402,"children":1403},{},[1404],{"type":48,"value":1405},"Stderr noise",{"type":48,"value":1407},": gcx prints a one-line ",{"type":42,"tag":57,"props":1409,"children":1411},{"className":1410},[],[1412],{"type":48,"value":1413},"hint:",{"type":48,"value":1415}," to stderr on most\ninvocations. Pipelines into ",{"type":42,"tag":57,"props":1417,"children":1419},{"className":1418},[],[1420],{"type":48,"value":1421},"jq",{"type":48,"value":1423}," should redirect with ",{"type":42,"tag":57,"props":1425,"children":1427},{"className":1426},[],[1428],{"type":48,"value":1429},"2>\u002Fdev\u002Fnull",{"type":48,"value":1431},"\nto avoid surprises.",{"type":42,"tag":70,"props":1433,"children":1434},{},[1435,1440,1442,1447,1449,1455,1457,1463],{"type":42,"tag":74,"props":1436,"children":1437},{},[1438],{"type":48,"value":1439},"Response headers",{"type":48,"value":1441}," are not directly exposed by ",{"type":42,"tag":57,"props":1443,"children":1445},{"className":1444},[],[1446],{"type":48,"value":128},{"type":48,"value":1448},". When a\nbranch in the workflow hinges on ",{"type":42,"tag":57,"props":1450,"children":1452},{"className":1451},[],[1453],{"type":48,"value":1454},"Content-Type",{"type":48,"value":1456}," (e.g. script GET in\n§5), inspect the downloaded body with ",{"type":42,"tag":57,"props":1458,"children":1460},{"className":1459},[],[1461],{"type":48,"value":1462},"file \u003Cpath>",{"type":48,"value":1464}," instead.",{"type":42,"tag":70,"props":1466,"children":1467},{},[1468,1473,1475,1650,1653,1655,1661,1663,1668,1670,1739,1742,1744,1749],{"type":42,"tag":74,"props":1469,"children":1470},{},[1471],{"type":48,"value":1472},"Large responses spill to a temp file",{"type":48,"value":1474},", with stdout reduced to a\nwrapper envelope. The threshold is a few tens of KB, so even\nmoderately-sized list endpoints trigger it. The envelope looks like\nthis:",{"type":42,"tag":150,"props":1476,"children":1479},{"className":1477,"code":1478,"language":1283,"meta":155,"style":155},"language-json shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","{\"spilled_to\":\"\u002Fvar\u002Ffolders\u002F...\u002Fgcx-results-\u003Cn>.json\",\n \"bytes\":2365037,\n \"preview_sample\":[\"@nextLink\",\"value\"],\n \"message\":\"Response too large for stdout...\"}\n",[1480],{"type":42,"tag":57,"props":1481,"children":1482},{"__ignoreMap":155},[1483,1526,1556,1612],{"type":42,"tag":161,"props":1484,"children":1485},{"class":163,"line":164},[1486,1491,1495,1501,1505,1509,1513,1518,1522],{"type":42,"tag":161,"props":1487,"children":1488},{"style":184},[1489],{"type":48,"value":1490},"{",{"type":42,"tag":161,"props":1492,"children":1493},{"style":184},[1494],{"type":48,"value":605},{"type":42,"tag":161,"props":1496,"children":1498},{"style":1497},"--shiki-light:#9C3EDA;--shiki-default:#C792EA;--shiki-dark:#C792EA",[1499],{"type":48,"value":1500},"spilled_to",{"type":42,"tag":161,"props":1502,"children":1503},{"style":184},[1504],{"type":48,"value":605},{"type":42,"tag":161,"props":1506,"children":1507},{"style":184},[1508],{"type":48,"value":537},{"type":42,"tag":161,"props":1510,"children":1511},{"style":184},[1512],{"type":48,"value":605},{"type":42,"tag":161,"props":1514,"children":1515},{"style":173},[1516],{"type":48,"value":1517},"\u002Fvar\u002Ffolders\u002F...\u002Fgcx-results-\u003Cn>.json",{"type":42,"tag":161,"props":1519,"children":1520},{"style":184},[1521],{"type":48,"value":605},{"type":42,"tag":161,"props":1523,"children":1524},{"style":184},[1525],{"type":48,"value":380},{"type":42,"tag":161,"props":1527,"children":1528},{"class":163,"line":212},[1529,1533,1538,1542,1546,1552],{"type":42,"tag":161,"props":1530,"children":1531},{"style":184},[1532],{"type":48,"value":590},{"type":42,"tag":161,"props":1534,"children":1535},{"style":1497},[1536],{"type":48,"value":1537},"bytes",{"type":42,"tag":161,"props":1539,"children":1540},{"style":184},[1541],{"type":48,"value":605},{"type":42,"tag":161,"props":1543,"children":1544},{"style":184},[1545],{"type":48,"value":537},{"type":42,"tag":161,"props":1547,"children":1549},{"style":1548},"--shiki-light:#F76D47;--shiki-default:#F78C6C;--shiki-dark:#F78C6C",[1550],{"type":48,"value":1551},"2365037",{"type":42,"tag":161,"props":1553,"children":1554},{"style":184},[1555],{"type":48,"value":380},{"type":42,"tag":161,"props":1557,"children":1558},{"class":163,"line":612},[1559,1563,1568,1572,1577,1581,1585,1589,1594,1598,1603,1607],{"type":42,"tag":161,"props":1560,"children":1561},{"style":184},[1562],{"type":48,"value":590},{"type":42,"tag":161,"props":1564,"children":1565},{"style":1497},[1566],{"type":48,"value":1567},"preview_sample",{"type":42,"tag":161,"props":1569,"children":1570},{"style":184},[1571],{"type":48,"value":605},{"type":42,"tag":161,"props":1573,"children":1574},{"style":184},[1575],{"type":48,"value":1576},":[",{"type":42,"tag":161,"props":1578,"children":1579},{"style":184},[1580],{"type":48,"value":605},{"type":42,"tag":161,"props":1582,"children":1583},{"style":173},[1584],{"type":48,"value":1011},{"type":42,"tag":161,"props":1586,"children":1587},{"style":184},[1588],{"type":48,"value":605},{"type":42,"tag":161,"props":1590,"children":1591},{"style":184},[1592],{"type":48,"value":1593},",",{"type":42,"tag":161,"props":1595,"children":1596},{"style":184},[1597],{"type":48,"value":605},{"type":42,"tag":161,"props":1599,"children":1600},{"style":173},[1601],{"type":48,"value":1602},"value",{"type":42,"tag":161,"props":1604,"children":1605},{"style":184},[1606],{"type":48,"value":605},{"type":42,"tag":161,"props":1608,"children":1609},{"style":184},[1610],{"type":48,"value":1611},"],\n",{"type":42,"tag":161,"props":1613,"children":1614},{"class":163,"line":642},[1615,1619,1624,1628,1632,1636,1641,1645],{"type":42,"tag":161,"props":1616,"children":1617},{"style":184},[1618],{"type":48,"value":590},{"type":42,"tag":161,"props":1620,"children":1621},{"style":1497},[1622],{"type":48,"value":1623},"message",{"type":42,"tag":161,"props":1625,"children":1626},{"style":184},[1627],{"type":48,"value":605},{"type":42,"tag":161,"props":1629,"children":1630},{"style":184},[1631],{"type":48,"value":537},{"type":42,"tag":161,"props":1633,"children":1634},{"style":184},[1635],{"type":48,"value":605},{"type":42,"tag":161,"props":1637,"children":1638},{"style":173},[1639],{"type":48,"value":1640},"Response too large for stdout...",{"type":42,"tag":161,"props":1642,"children":1643},{"style":184},[1644],{"type":48,"value":605},{"type":42,"tag":161,"props":1646,"children":1647},{"style":184},[1648],{"type":48,"value":1649},"}\n",{"type":42,"tag":680,"props":1651,"children":1652},{},[],{"type":48,"value":1654},"Naive ",{"type":42,"tag":57,"props":1656,"children":1658},{"className":1657},[],[1659],{"type":48,"value":1660},"json.loads(stdout).get('value', [])",{"type":48,"value":1662}," patterns silently return\nempty in this case — the envelope has no ",{"type":42,"tag":57,"props":1664,"children":1666},{"className":1665},[],[1667],{"type":48,"value":1602},{"type":48,"value":1669}," key. Two reliable\nfixes:",{"type":42,"tag":66,"props":1671,"children":1672},{},[1673,1696],{"type":42,"tag":70,"props":1674,"children":1675},{},[1676,1687,1689,1694],{"type":42,"tag":74,"props":1677,"children":1678},{},[1679,1681],{"type":48,"value":1680},"Pass ",{"type":42,"tag":57,"props":1682,"children":1684},{"className":1683},[],[1685],{"type":48,"value":1686},"-o json",{"type":48,"value":1688}," to force inline output regardless of size\n(recommended for scripts that parse the body). The agent-mode\ndefault formatting is what triggers the spill; ",{"type":42,"tag":57,"props":1690,"children":1692},{"className":1691},[],[1693],{"type":48,"value":1686},{"type":48,"value":1695}," opts out.",{"type":42,"tag":70,"props":1697,"children":1698},{},[1699,1704,1706],{"type":42,"tag":74,"props":1700,"children":1701},{},[1702],{"type":48,"value":1703},"Or detect the envelope and re-read from the spilled file",{"type":48,"value":1705},":\n",{"type":42,"tag":150,"props":1707,"children":1711},{"className":1708,"code":1709,"language":1710,"meta":155,"style":155},"language-python shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","d = json.loads(stdout)\nif 'spilled_to' in d:\n    d = json.load(open(d['spilled_to']))\n","python",[1712],{"type":42,"tag":57,"props":1713,"children":1714},{"__ignoreMap":155},[1715,1723,1731],{"type":42,"tag":161,"props":1716,"children":1717},{"class":163,"line":164},[1718],{"type":42,"tag":161,"props":1719,"children":1720},{},[1721],{"type":48,"value":1722},"d = json.loads(stdout)\n",{"type":42,"tag":161,"props":1724,"children":1725},{"class":163,"line":212},[1726],{"type":42,"tag":161,"props":1727,"children":1728},{},[1729],{"type":48,"value":1730},"if 'spilled_to' in d:\n",{"type":42,"tag":161,"props":1732,"children":1733},{"class":163,"line":612},[1734],{"type":42,"tag":161,"props":1735,"children":1736},{},[1737],{"type":48,"value":1738},"    d = json.load(open(d['spilled_to']))\n",{"type":42,"tag":680,"props":1740,"children":1741},{},[],{"type":48,"value":1743},"Either works; ",{"type":42,"tag":57,"props":1745,"children":1747},{"className":1746},[],[1748],{"type":48,"value":1686},{"type":48,"value":1750}," is fewer lines.",{"type":42,"tag":70,"props":1752,"children":1753},{},[1754,1774,1776,1781,1783,1789,1791,1797,1799,1805,1807,1813,1815,1821,1823,1829,1831,1837,1839,1845,1847,1853],{"type":42,"tag":74,"props":1755,"children":1756},{},[1757,1759,1765,1767,1773],{"type":48,"value":1758},"The Grafana plugin proxy rewrites ",{"type":42,"tag":57,"props":1760,"children":1762},{"className":1761},[],[1763],{"type":48,"value":1764},"Content-Type: multipart\u002F...",{"type":48,"value":1766},"\nto ",{"type":42,"tag":57,"props":1768,"children":1770},{"className":1769},[],[1771],{"type":48,"value":1772},"application\u002Fjson",{"type":48,"value":288},{"type":48,"value":1775}," ",{"type":42,"tag":57,"props":1777,"children":1779},{"className":1778},[],[1780],{"type":48,"value":128},{"type":48,"value":1782}," itself forwards your\n",{"type":42,"tag":57,"props":1784,"children":1786},{"className":1785},[],[1787],{"type":48,"value":1788},"-H \"Content-Type: ...\"",{"type":48,"value":1790}," header correctly (visible in\n",{"type":42,"tag":57,"props":1792,"children":1794},{"className":1793},[],[1795],{"type":48,"value":1796},"--log-http-payload",{"type":48,"value":1798}," traces), but the upstream plugin proxy\nrewrites multipart Content-Types to JSON before they reach k6's\nAPI. The net effect: endpoints that require multipart bodies —\nnotably ",{"type":42,"tag":57,"props":1800,"children":1802},{"className":1801},[],[1803],{"type":48,"value":1804},"POST \u002Fcloud\u002Fv6\u002Fprojects\u002F{id}\u002Fload_tests",{"type":48,"value":1806}," for test\ncreation, which takes ",{"type":42,"tag":57,"props":1808,"children":1810},{"className":1809},[],[1811],{"type":48,"value":1812},"name",{"type":48,"value":1814}," + ",{"type":42,"tag":57,"props":1816,"children":1818},{"className":1817},[],[1819],{"type":48,"value":1820},"script",{"type":48,"value":1822}," as form parts — return\n",{"type":42,"tag":57,"props":1824,"children":1826},{"className":1825},[],[1827],{"type":48,"value":1828},"HTTP 415 \"Unsupported media type \\\"application\u002Fjson\\\"\"",{"type":48,"value":1830}," no\nmatter what header you set on the gcx side. Fall back to direct\ncurl against ",{"type":42,"tag":57,"props":1832,"children":1834},{"className":1833},[],[1835],{"type":48,"value":1836},"api.k6.io",{"type":48,"value":1838}," (§1.2) for these endpoints —\n",{"type":42,"tag":57,"props":1840,"children":1842},{"className":1841},[],[1843],{"type":48,"value":1844},"curl -F name=... -F script=@...",{"type":48,"value":1846}," builds the multipart body for\nyou and bypasses the plugin proxy. Other Content-Type values\n(e.g. ",{"type":42,"tag":57,"props":1848,"children":1850},{"className":1849},[],[1851],{"type":48,"value":1852},"application\u002Foctet-stream",{"type":48,"value":1854}," for the script-update PUT in §5)\nare forwarded through the proxy unchanged.",{"type":42,"tag":132,"props":1856,"children":1857},{},[],{"type":42,"tag":136,"props":1859,"children":1861},{"id":1860},"_3-discovering-and-calling-endpoints",[1862],{"type":48,"value":1863},"3. Discovering and calling endpoints",{"type":42,"tag":51,"props":1865,"children":1866},{},[1867,1873,1875,1880],{"type":42,"tag":57,"props":1868,"children":1870},{"className":1869},[],[1871],{"type":48,"value":1872},"gcx k6",{"type":48,"value":1874}," subcommands (see ",{"type":42,"tag":57,"props":1876,"children":1878},{"className":1877},[],[1879],{"type":48,"value":112},{"type":48,"value":1881},") cover the common reads.\nFor everything else — mutations, niche reads, endpoints not surfaced as\nsubcommands — the k6 Cloud API surface is large and changes over time.\nRather than rely on a cheat-sheet that goes stale, discover the\noperation you need from the OpenAPI spec at request time.",{"type":42,"tag":143,"props":1883,"children":1885},{"id":1884},"workflow",[1886],{"type":48,"value":1887},"Workflow",{"type":42,"tag":453,"props":1889,"children":1890},{},[1891,1943,2028,2109],{"type":42,"tag":70,"props":1892,"children":1893},{},[1894,1899,1901,1907,1909],{"type":42,"tag":74,"props":1895,"children":1896},{},[1897],{"type":48,"value":1898},"Fetch the spec once per session",{"type":48,"value":1900}," (it's large; cache to ",{"type":42,"tag":57,"props":1902,"children":1904},{"className":1903},[],[1905],{"type":48,"value":1906},"\u002Ftmp",{"type":48,"value":1908},"):",{"type":42,"tag":150,"props":1910,"children":1912},{"className":152,"code":1911,"language":154,"meta":155,"style":155},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fopenapi > \u002Ftmp\u002Fk6-openapi.json\n",[1913],{"type":42,"tag":57,"props":1914,"children":1915},{"__ignoreMap":155},[1916],{"type":42,"tag":161,"props":1917,"children":1918},{"class":163,"line":164},[1919,1923,1928,1933,1938],{"type":42,"tag":161,"props":1920,"children":1921},{"style":168},[1922],{"type":48,"value":62},{"type":42,"tag":161,"props":1924,"children":1925},{"style":173},[1926],{"type":48,"value":1927}," api",{"type":42,"tag":161,"props":1929,"children":1930},{"style":173},[1931],{"type":48,"value":1932}," \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fopenapi",{"type":42,"tag":161,"props":1934,"children":1935},{"style":184},[1936],{"type":48,"value":1937}," >",{"type":42,"tag":161,"props":1939,"children":1940},{"style":173},[1941],{"type":48,"value":1942}," \u002Ftmp\u002Fk6-openapi.json\n",{"type":42,"tag":70,"props":1944,"children":1945},{},[1946,1966,1968,2023,2026],{"type":42,"tag":74,"props":1947,"children":1948},{},[1949,1951,1957,1958,1964],{"type":48,"value":1950},"Index by ",{"type":42,"tag":57,"props":1952,"children":1954},{"className":1953},[],[1955],{"type":48,"value":1956},"operationId",{"type":48,"value":1814},{"type":42,"tag":57,"props":1959,"children":1961},{"className":1960},[],[1962],{"type":48,"value":1963},"description",{"type":48,"value":1965}," first",{"type":48,"value":1967}," — this keeps the\nworking payload small while you search:",{"type":42,"tag":150,"props":1969,"children":1971},{"className":152,"code":1970,"language":154,"meta":155,"style":155},"jq '[.paths | to_entries[] | .key as $p | .value | to_entries[]\n     | {path: $p, method: .key,\n        operationId: .value.operationId,\n        description: .value.description}]' \u002Ftmp\u002Fk6-openapi.json\n",[1972],{"type":42,"tag":57,"props":1973,"children":1974},{"__ignoreMap":155},[1975,1991,1999,2007],{"type":42,"tag":161,"props":1976,"children":1977},{"class":163,"line":164},[1978,1982,1986],{"type":42,"tag":161,"props":1979,"children":1980},{"style":168},[1981],{"type":48,"value":1421},{"type":42,"tag":161,"props":1983,"children":1984},{"style":184},[1985],{"type":48,"value":663},{"type":42,"tag":161,"props":1987,"children":1988},{"style":173},[1989],{"type":48,"value":1990},"[.paths | to_entries[] | .key as $p | .value | to_entries[]\n",{"type":42,"tag":161,"props":1992,"children":1993},{"class":163,"line":212},[1994],{"type":42,"tag":161,"props":1995,"children":1996},{"style":173},[1997],{"type":48,"value":1998},"     | {path: $p, method: .key,\n",{"type":42,"tag":161,"props":2000,"children":2001},{"class":163,"line":612},[2002],{"type":42,"tag":161,"props":2003,"children":2004},{"style":173},[2005],{"type":48,"value":2006},"        operationId: .value.operationId,\n",{"type":42,"tag":161,"props":2008,"children":2009},{"class":163,"line":642},[2010,2015,2019],{"type":42,"tag":161,"props":2011,"children":2012},{"style":173},[2013],{"type":48,"value":2014},"        description: .value.description}]",{"type":42,"tag":161,"props":2016,"children":2017},{"style":184},[2018],{"type":48,"value":673},{"type":42,"tag":161,"props":2020,"children":2021},{"style":173},[2022],{"type":48,"value":1942},{"type":42,"tag":680,"props":2024,"children":2025},{},[],{"type":48,"value":2027},"Grep this for the action you need (\"abort\", \"limits\", \"schedule\", …).",{"type":42,"tag":70,"props":2029,"children":2030},{},[2031,2036,2038,2044,2046],{"type":42,"tag":74,"props":2032,"children":2033},{},[2034],{"type":48,"value":2035},"Pull the chosen operation's full schema",{"type":48,"value":2037}," — parameters, request\nbody, response — resolving any ",{"type":42,"tag":57,"props":2039,"children":2041},{"className":2040},[],[2042],{"type":48,"value":2043},"$ref",{"type":48,"value":2045}," indirections:",{"type":42,"tag":150,"props":2047,"children":2049},{"className":152,"code":2048,"language":154,"meta":155,"style":155},"jq '.paths[\"\u003Cpath>\"][\"\u003Cmethod>\"]' \u002Ftmp\u002Fk6-openapi.json\n# Then for each \"$ref\": \"#\u002Fcomponents\u002Fschemas\u002FFoo\":\njq '.components.schemas.Foo' \u002Ftmp\u002Fk6-openapi.json\n",[2050],{"type":42,"tag":57,"props":2051,"children":2052},{"__ignoreMap":155},[2053,2077,2085],{"type":42,"tag":161,"props":2054,"children":2055},{"class":163,"line":164},[2056,2060,2064,2069,2073],{"type":42,"tag":161,"props":2057,"children":2058},{"style":168},[2059],{"type":48,"value":1421},{"type":42,"tag":161,"props":2061,"children":2062},{"style":184},[2063],{"type":48,"value":663},{"type":42,"tag":161,"props":2065,"children":2066},{"style":173},[2067],{"type":48,"value":2068},".paths[\"\u003Cpath>\"][\"\u003Cmethod>\"]",{"type":42,"tag":161,"props":2070,"children":2071},{"style":184},[2072],{"type":48,"value":673},{"type":42,"tag":161,"props":2074,"children":2075},{"style":173},[2076],{"type":48,"value":1942},{"type":42,"tag":161,"props":2078,"children":2079},{"class":163,"line":212},[2080],{"type":42,"tag":161,"props":2081,"children":2082},{"style":206},[2083],{"type":48,"value":2084},"# Then for each \"$ref\": \"#\u002Fcomponents\u002Fschemas\u002FFoo\":\n",{"type":42,"tag":161,"props":2086,"children":2087},{"class":163,"line":612},[2088,2092,2096,2101,2105],{"type":42,"tag":161,"props":2089,"children":2090},{"style":168},[2091],{"type":48,"value":1421},{"type":42,"tag":161,"props":2093,"children":2094},{"style":184},[2095],{"type":48,"value":663},{"type":42,"tag":161,"props":2097,"children":2098},{"style":173},[2099],{"type":48,"value":2100},".components.schemas.Foo",{"type":42,"tag":161,"props":2102,"children":2103},{"style":184},[2104],{"type":48,"value":673},{"type":42,"tag":161,"props":2106,"children":2107},{"style":173},[2108],{"type":48,"value":1942},{"type":42,"tag":70,"props":2110,"children":2111},{},[2112,2124],{"type":42,"tag":74,"props":2113,"children":2114},{},[2115,2117,2122],{"type":48,"value":2116},"Build the ",{"type":42,"tag":57,"props":2118,"children":2120},{"className":2119},[],[2121],{"type":48,"value":128},{"type":48,"value":2123}," call",{"type":48,"value":2125}," against the same path, prefixed per §2.\nAuthorization is already injected by gcx — do not add it yourself.",{"type":42,"tag":143,"props":2127,"children":2129},{"id":2128},"list-requests",[2130],{"type":48,"value":2131},"List requests",{"type":42,"tag":51,"props":2133,"children":2134},{},[2135,2137,2150,2152,2157,2159,2165,2166,2172,2173,2179,2180,2186,2187,2193],{"type":48,"value":2136},"When the operation you're calling is a list endpoint, default to\n",{"type":42,"tag":74,"props":2138,"children":2139},{},[2140,2142,2148],{"type":48,"value":2141},"ordering by ",{"type":42,"tag":57,"props":2143,"children":2145},{"className":2144},[],[2146],{"type":48,"value":2147},"created",{"type":48,"value":2149}," descending",{"type":48,"value":2151}," (newest first) and ",{"type":42,"tag":74,"props":2153,"children":2154},{},[2155],{"type":48,"value":2156},"paginating\nby 20",{"type":48,"value":2158}," — both via whatever query parameter names the OpenAPI schema\nfor that operation exposes. Names vary (",{"type":42,"tag":57,"props":2160,"children":2162},{"className":2161},[],[2163],{"type":48,"value":2164},"ordering=-created",{"type":48,"value":380},{"type":42,"tag":57,"props":2167,"children":2169},{"className":2168},[],[2170],{"type":48,"value":2171},"order_by=created.desc",{"type":48,"value":365},{"type":42,"tag":57,"props":2174,"children":2176},{"className":2175},[],[2177],{"type":48,"value":2178},"sort=-created",{"type":48,"value":365},{"type":42,"tag":57,"props":2181,"children":2183},{"className":2182},[],[2184],{"type":48,"value":2185},"limit=20",{"type":48,"value":365},{"type":42,"tag":57,"props":2188,"children":2190},{"className":2189},[],[2191],{"type":48,"value":2192},"page_size=20",{"type":48,"value":2194},"),\nwhich is exactly why discovering them from the spec in step 3 matters.\nNewest-first means the entries the user usually cares about land in\nthe first page; a page size of 20 keeps the response small enough to\nsummarise without burning context.",{"type":42,"tag":441,"props":2196,"children":2198},{"id":2197},"full-enumeration-paginating-with-nextlink",[2199,2201],{"type":48,"value":2200},"Full enumeration: paginating with ",{"type":42,"tag":57,"props":2202,"children":2204},{"className":2203},[],[2205],{"type":48,"value":1011},{"type":42,"tag":51,"props":2207,"children":2208},{},[2209,2211,2216,2218,2223,2225,2230,2232,2237,2239,2250,2251,2256,2258,2263,2265,2271,2273,2279,2281,2286,2288,2294,2296,2301],{"type":48,"value":2210},"When you need to enumerate ",{"type":42,"tag":274,"props":2212,"children":2213},{},[2214],{"type":48,"value":2215},"all",{"type":48,"value":2217}," rows (not just the newest page), the\nv6 list endpoints cap each response at ",{"type":42,"tag":74,"props":2219,"children":2220},{},[2221],{"type":48,"value":2222},"1000 rows",{"type":48,"value":2224}," (the default\n",{"type":42,"tag":57,"props":2226,"children":2228},{"className":2227},[],[2229],{"type":48,"value":997},{"type":48,"value":2231},") and return an ",{"type":42,"tag":57,"props":2233,"children":2235},{"className":2234},[],[2236],{"type":48,"value":1011},{"type":48,"value":2238}," field pointing at the next page.\n",{"type":42,"tag":74,"props":2240,"children":2241},{},[2242,2248],{"type":42,"tag":57,"props":2243,"children":2245},{"className":2244},[],[2246],{"type":48,"value":2247},"gcx k6 runs list --limit 0",{"type":48,"value":2249}," does NOT auto-follow",{"type":48,"value":1775},{"type":42,"tag":57,"props":2252,"children":2254},{"className":2253},[],[2255],{"type":48,"value":1011},{"type":48,"value":2257}," and\ndefaults to ascending order — for tests with >1000 historical runs it\nsilently returns the ",{"type":42,"tag":74,"props":2259,"children":2260},{},[2261],{"type":48,"value":2262},"oldest",{"type":48,"value":2264}," 1000, not the newest. The\npractical effect: ",{"type":42,"tag":57,"props":2266,"children":2268},{"className":2267},[],[2269],{"type":48,"value":2270},"(first\u002Flast_run)",{"type":48,"value":2272}," summarised from this output can\nbe wildly stale (e.g. a daily-scheduled test that's been running for\nyears will show a ",{"type":42,"tag":57,"props":2274,"children":2276},{"className":2275},[],[2277],{"type":48,"value":2278},"last_run",{"type":48,"value":2280}," from ~3 years ago). Use ",{"type":42,"tag":57,"props":2282,"children":2284},{"className":2283},[],[2285],{"type":48,"value":128},{"type":48,"value":2287},"\nagainst the v6 endpoint with ",{"type":42,"tag":57,"props":2289,"children":2291},{"className":2290},[],[2292],{"type":48,"value":2293},"$orderby=created desc",{"type":48,"value":2295}," for the\nnewest-first slice, or loop on ",{"type":42,"tag":57,"props":2297,"children":2299},{"className":2298},[],[2300],{"type":48,"value":1011},{"type":48,"value":2302}," until it's absent for full\nenumeration.",{"type":42,"tag":51,"props":2304,"children":2305},{},[2306],{"type":48,"value":2307},"The v6 list endpoints expose OData-style query parameters:",{"type":42,"tag":728,"props":2309,"children":2310},{},[2311,2327],{"type":42,"tag":732,"props":2312,"children":2313},{},[2314],{"type":42,"tag":736,"props":2315,"children":2316},{},[2317,2322],{"type":42,"tag":740,"props":2318,"children":2319},{},[2320],{"type":48,"value":2321},"Param",{"type":42,"tag":740,"props":2323,"children":2324},{},[2325],{"type":48,"value":2326},"Purpose",{"type":42,"tag":751,"props":2328,"children":2329},{},[2330,2369,2385,2408],{"type":42,"tag":736,"props":2331,"children":2332},{},[2333,2341],{"type":42,"tag":758,"props":2334,"children":2335},{},[2336],{"type":42,"tag":57,"props":2337,"children":2339},{"className":2338},[],[2340],{"type":48,"value":990},{"type":42,"tag":758,"props":2342,"children":2343},{},[2344,2346,2352,2354,2360,2362,2367],{"type":48,"value":2345},"Ordering — value must be ",{"type":42,"tag":57,"props":2347,"children":2349},{"className":2348},[],[2350],{"type":48,"value":2351},"\u003Cfield> \u003Cdirection>",{"type":48,"value":2353}," (e.g. ",{"type":42,"tag":57,"props":2355,"children":2357},{"className":2356},[],[2358],{"type":48,"value":2359},"created desc",{"type":48,"value":2361},"). The allowed fields are operation-specific; ",{"type":42,"tag":57,"props":2363,"children":2365},{"className":2364},[],[2366],{"type":48,"value":2147},{"type":48,"value":2368}," is the common one. Default is ascending.",{"type":42,"tag":736,"props":2370,"children":2371},{},[2372,2380],{"type":42,"tag":758,"props":2373,"children":2374},{},[2375],{"type":42,"tag":57,"props":2376,"children":2378},{"className":2377},[],[2379],{"type":48,"value":997},{"type":42,"tag":758,"props":2381,"children":2382},{},[2383],{"type":48,"value":2384},"Page size, default 1000 (also the cap)",{"type":42,"tag":736,"props":2386,"children":2387},{},[2388,2396],{"type":42,"tag":758,"props":2389,"children":2390},{},[2391],{"type":42,"tag":57,"props":2392,"children":2394},{"className":2393},[],[2395],{"type":48,"value":1004},{"type":42,"tag":758,"props":2397,"children":2398},{},[2399,2401,2406],{"type":48,"value":2400},"Offset (",{"type":42,"tag":57,"props":2402,"children":2404},{"className":2403},[],[2405],{"type":48,"value":1011},{"type":48,"value":2407}," already encodes this for you)",{"type":42,"tag":736,"props":2409,"children":2410},{},[2411,2420],{"type":42,"tag":758,"props":2412,"children":2413},{},[2414],{"type":42,"tag":57,"props":2415,"children":2417},{"className":2416},[],[2418],{"type":48,"value":2419},"$count",{"type":42,"tag":758,"props":2421,"children":2422},{},[2423],{"type":48,"value":2424},"Include total count in response",{"type":42,"tag":51,"props":2426,"children":2427},{},[2428,2430,2435,2437,2442],{"type":48,"value":2429},"Two practical defaults for the loop: ",{"type":42,"tag":57,"props":2431,"children":2433},{"className":2432},[],[2434],{"type":48,"value":2293},{"type":48,"value":2436}," so the\nfirst page contains the newest runs (most of the time the agent only\ncares about those), and ",{"type":42,"tag":57,"props":2438,"children":2440},{"className":2439},[],[2441],{"type":48,"value":1686},{"type":48,"value":2443}," to opt out of the spill envelope\n(see §2) so the parsing is uniform across pages.",{"type":42,"tag":150,"props":2445,"children":2447},{"className":1708,"code":2446,"language":1710,"meta":155,"style":155},"import json, subprocess, urllib.parse\n\nCTX = \"\u003Cstack>\"\nTEST_ID = \"\u003Ctest_id>\"\nPROXY = \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\"\n\nall_runs = []\n# Start with newest first; -o json keeps the body inline for clean json.loads().\npath = (\n    f\"{PROXY}\u002Fcloud\u002Fv6\u002Fload_tests\u002F{TEST_ID}\u002Ftest_runs\"\n    \"?%24orderby=created%20desc&%24top=1000\"\n)\nwhile path:\n    r = subprocess.run([\"gcx\", \"--context\", CTX, \"api\", path, \"-o\", \"json\"],\n                       capture_output=True, text=True, timeout=60)\n    d = json.loads(r.stdout)\n    all_runs.extend(d.get(\"value\", []))\n    nxt = d.get(\"@nextLink\")\n    if not nxt:\n        path = None\n        continue\n    # @nextLink comes back as an absolute http:\u002F\u002Fapi.k6.io\u002F... URL with\n    # OData params already encoded ($skip, $top, $orderby). Reshape its\n    # path+query into the plugin-proxy prefix:\n    p = urllib.parse.urlparse(nxt)\n    path = f\"{PROXY}{p.path}\" + (f\"?{p.query}\" if p.query else \"\")\n",[2448],{"type":42,"tag":57,"props":2449,"children":2450},{"__ignoreMap":155},[2451,2459,2468,2476,2484,2493,2501,2510,2519,2528,2537,2546,2554,2563,2572,2581,2589,2598,2607,2616,2625,2634,2643,2652,2661,2670],{"type":42,"tag":161,"props":2452,"children":2453},{"class":163,"line":164},[2454],{"type":42,"tag":161,"props":2455,"children":2456},{},[2457],{"type":48,"value":2458},"import json, subprocess, urllib.parse\n",{"type":42,"tag":161,"props":2460,"children":2461},{"class":163,"line":212},[2462],{"type":42,"tag":161,"props":2463,"children":2465},{"emptyLinePlaceholder":2464},true,[2466],{"type":48,"value":2467},"\n",{"type":42,"tag":161,"props":2469,"children":2470},{"class":163,"line":612},[2471],{"type":42,"tag":161,"props":2472,"children":2473},{},[2474],{"type":48,"value":2475},"CTX = \"\u003Cstack>\"\n",{"type":42,"tag":161,"props":2477,"children":2478},{"class":163,"line":642},[2479],{"type":42,"tag":161,"props":2480,"children":2481},{},[2482],{"type":48,"value":2483},"TEST_ID = \"\u003Ctest_id>\"\n",{"type":42,"tag":161,"props":2485,"children":2487},{"class":163,"line":2486},5,[2488],{"type":42,"tag":161,"props":2489,"children":2490},{},[2491],{"type":48,"value":2492},"PROXY = \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\"\n",{"type":42,"tag":161,"props":2494,"children":2496},{"class":163,"line":2495},6,[2497],{"type":42,"tag":161,"props":2498,"children":2499},{"emptyLinePlaceholder":2464},[2500],{"type":48,"value":2467},{"type":42,"tag":161,"props":2502,"children":2504},{"class":163,"line":2503},7,[2505],{"type":42,"tag":161,"props":2506,"children":2507},{},[2508],{"type":48,"value":2509},"all_runs = []\n",{"type":42,"tag":161,"props":2511,"children":2513},{"class":163,"line":2512},8,[2514],{"type":42,"tag":161,"props":2515,"children":2516},{},[2517],{"type":48,"value":2518},"# Start with newest first; -o json keeps the body inline for clean json.loads().\n",{"type":42,"tag":161,"props":2520,"children":2522},{"class":163,"line":2521},9,[2523],{"type":42,"tag":161,"props":2524,"children":2525},{},[2526],{"type":48,"value":2527},"path = (\n",{"type":42,"tag":161,"props":2529,"children":2531},{"class":163,"line":2530},10,[2532],{"type":42,"tag":161,"props":2533,"children":2534},{},[2535],{"type":48,"value":2536},"    f\"{PROXY}\u002Fcloud\u002Fv6\u002Fload_tests\u002F{TEST_ID}\u002Ftest_runs\"\n",{"type":42,"tag":161,"props":2538,"children":2540},{"class":163,"line":2539},11,[2541],{"type":42,"tag":161,"props":2542,"children":2543},{},[2544],{"type":48,"value":2545},"    \"?%24orderby=created%20desc&%24top=1000\"\n",{"type":42,"tag":161,"props":2547,"children":2549},{"class":163,"line":2548},12,[2550],{"type":42,"tag":161,"props":2551,"children":2552},{},[2553],{"type":48,"value":678},{"type":42,"tag":161,"props":2555,"children":2557},{"class":163,"line":2556},13,[2558],{"type":42,"tag":161,"props":2559,"children":2560},{},[2561],{"type":48,"value":2562},"while path:\n",{"type":42,"tag":161,"props":2564,"children":2566},{"class":163,"line":2565},14,[2567],{"type":42,"tag":161,"props":2568,"children":2569},{},[2570],{"type":48,"value":2571},"    r = subprocess.run([\"gcx\", \"--context\", CTX, \"api\", path, \"-o\", \"json\"],\n",{"type":42,"tag":161,"props":2573,"children":2575},{"class":163,"line":2574},15,[2576],{"type":42,"tag":161,"props":2577,"children":2578},{},[2579],{"type":48,"value":2580},"                       capture_output=True, text=True, timeout=60)\n",{"type":42,"tag":161,"props":2582,"children":2583},{"class":163,"line":30},[2584],{"type":42,"tag":161,"props":2585,"children":2586},{},[2587],{"type":48,"value":2588},"    d = json.loads(r.stdout)\n",{"type":42,"tag":161,"props":2590,"children":2592},{"class":163,"line":2591},17,[2593],{"type":42,"tag":161,"props":2594,"children":2595},{},[2596],{"type":48,"value":2597},"    all_runs.extend(d.get(\"value\", []))\n",{"type":42,"tag":161,"props":2599,"children":2601},{"class":163,"line":2600},18,[2602],{"type":42,"tag":161,"props":2603,"children":2604},{},[2605],{"type":48,"value":2606},"    nxt = d.get(\"@nextLink\")\n",{"type":42,"tag":161,"props":2608,"children":2610},{"class":163,"line":2609},19,[2611],{"type":42,"tag":161,"props":2612,"children":2613},{},[2614],{"type":48,"value":2615},"    if not nxt:\n",{"type":42,"tag":161,"props":2617,"children":2619},{"class":163,"line":2618},20,[2620],{"type":42,"tag":161,"props":2621,"children":2622},{},[2623],{"type":48,"value":2624},"        path = None\n",{"type":42,"tag":161,"props":2626,"children":2628},{"class":163,"line":2627},21,[2629],{"type":42,"tag":161,"props":2630,"children":2631},{},[2632],{"type":48,"value":2633},"        continue\n",{"type":42,"tag":161,"props":2635,"children":2637},{"class":163,"line":2636},22,[2638],{"type":42,"tag":161,"props":2639,"children":2640},{},[2641],{"type":48,"value":2642},"    # @nextLink comes back as an absolute http:\u002F\u002Fapi.k6.io\u002F... URL with\n",{"type":42,"tag":161,"props":2644,"children":2646},{"class":163,"line":2645},23,[2647],{"type":42,"tag":161,"props":2648,"children":2649},{},[2650],{"type":48,"value":2651},"    # OData params already encoded ($skip, $top, $orderby). Reshape its\n",{"type":42,"tag":161,"props":2653,"children":2655},{"class":163,"line":2654},24,[2656],{"type":42,"tag":161,"props":2657,"children":2658},{},[2659],{"type":48,"value":2660},"    # path+query into the plugin-proxy prefix:\n",{"type":42,"tag":161,"props":2662,"children":2664},{"class":163,"line":2663},25,[2665],{"type":42,"tag":161,"props":2666,"children":2667},{},[2668],{"type":48,"value":2669},"    p = urllib.parse.urlparse(nxt)\n",{"type":42,"tag":161,"props":2671,"children":2673},{"class":163,"line":2672},26,[2674],{"type":42,"tag":161,"props":2675,"children":2676},{},[2677],{"type":48,"value":2678},"    path = f\"{PROXY}{p.path}\" + (f\"?{p.query}\" if p.query else \"\")\n",{"type":42,"tag":51,"props":2680,"children":2681},{},[2682,2684,2689,2691,2697,2699,2704],{"type":48,"value":2683},"Same pattern works for any v6 list endpoint that returns ",{"type":42,"tag":57,"props":2685,"children":2687},{"className":2686},[],[2688],{"type":48,"value":1011},{"type":48,"value":2690},",\nnot just ",{"type":42,"tag":57,"props":2692,"children":2694},{"className":2693},[],[2695],{"type":48,"value":2696},"\u002Ftest_runs",{"type":48,"value":2698},". If you only need the few most-recent items,\nstop the loop after the first page — with ",{"type":42,"tag":57,"props":2700,"children":2702},{"className":2701},[],[2703],{"type":48,"value":2293},{"type":48,"value":2705}," that\npage is already the newest 1000.",{"type":42,"tag":143,"props":2707,"children":2709},{"id":2708},"metrics",[2710],{"type":48,"value":2711},"Metrics",{"type":42,"tag":51,"props":2713,"children":2714},{},[2715,2717,2722,2724,2729,2731,2737,2739,2749],{"type":48,"value":2716},"Time-series and aggregate metrics live on the ",{"type":42,"tag":74,"props":2718,"children":2719},{},[2720],{"type":48,"value":2721},"v5",{"type":48,"value":2723}," API\n(",{"type":42,"tag":57,"props":2725,"children":2727},{"className":2726},[],[2728],{"type":48,"value":371},{"type":48,"value":2730},") — Prometheus-like query semantics inside OData-style\nURL function-calls (",{"type":42,"tag":57,"props":2732,"children":2734},{"className":2733},[],[2735],{"type":48,"value":2736},"query_range_k6(query='...',metric='...')",{"type":48,"value":2738},"), not\ncaptured by the v6 OpenAPI. The full endpoint reference, selector\nsyntax, query methods per metric type, and worked examples are inlined\nin ",{"type":42,"tag":2740,"props":2741,"children":2743},"a",{"href":2742},"references\u002Fmetrics.md",[2744],{"type":42,"tag":57,"props":2745,"children":2747},{"className":2746},[],[2748],{"type":48,"value":2742},{"type":48,"value":2750}," — read that before\nconstructing a metrics query.",{"type":42,"tag":143,"props":2752,"children":2754},{"id":2753},"logs",[2755],{"type":48,"value":2756},"Logs",{"type":42,"tag":51,"props":2758,"children":2759},{},[2760],{"type":48,"value":2761},"See §4.",{"type":42,"tag":132,"props":2763,"children":2764},{},[],{"type":42,"tag":136,"props":2766,"children":2768},{"id":2767},"_4-logs-loki-via-gcx-api",[2769,2771,2776],{"type":48,"value":2770},"4. Logs (Loki via ",{"type":42,"tag":57,"props":2772,"children":2774},{"className":2773},[],[2775],{"type":48,"value":128},{"type":48,"value":2777},")",{"type":42,"tag":51,"props":2779,"children":2780},{},[2781,2783,2789,2791,2796],{"type":48,"value":2782},"The plugin proxies Loki under ",{"type":42,"tag":57,"props":2784,"children":2786},{"className":2785},[],[2787],{"type":48,"value":2788},"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002F",{"type":48,"value":2790},". The\nonly header you supply by hand is ",{"type":42,"tag":57,"props":2792,"children":2794},{"className":2793},[],[2795],{"type":48,"value":86},{"type":48,"value":2797},"; gcx handles\nauthorization.",{"type":42,"tag":150,"props":2799,"children":2801},{"className":152,"code":2800,"language":154,"meta":155,"style":155},"RUN_ID=\"\u003Crun_id>\"\n\n# Scope the log window to the run itself: `created` for start, `ended`\n# for end. If `ended` is null the run is still in progress — fall back\n# to \"now\". Use a wider hard-coded window only when the run object's\n# timestamps don't fit what you're investigating.\nRUN=$(gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F$RUN_ID 2>\u002Fdev\u002Fnull)\n# k6 emits sub-second precision (e.g. \"...:58.984041Z\"); jq's\n# fromdateiso8601 only accepts whole seconds, so strip the fraction.\nSTART=$(echo \"$RUN\" | jq -r '.created | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601')\nEND=$(echo \"$RUN\"   | jq -r 'if .ended then (.ended | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601) else (now | floor) end')\n\nQUERY=$(printf '{test_run_id=\"%s\"}' \"$RUN_ID\" | jq -sRr @uri)\n\n# Save the raw response to \u002Ftmp\u002F — log payloads can be large; streaming\n# them inline burns context. Summarise from the file, then jq into\n# specific entries only when needed.\ngcx api \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Fquery_range?query=${QUERY}&direction=backward&start=${START}&end=${END}&limit=1000\" \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Frun_${RUN_ID}_logs.json\n\n# Tight summary — counts and stream labels only:\njq '{status, streams: (.data.result | length),\n     total_entries: ([.data.result[].values | length] | add),\n     stream_labels: [.data.result[].stream]}' \u002Ftmp\u002Frun_${RUN_ID}_logs.json\n",[2802],{"type":42,"tag":57,"props":2803,"children":2804},{"__ignoreMap":155},[2805,2832,2839,2847,2855,2863,2871,2915,2923,2931,2992,3050,3057,3122,3129,3137,3145,3153,3234,3293,3300,3308,3324,3332],{"type":42,"tag":161,"props":2806,"children":2807},{"class":163,"line":164},[2808,2813,2818,2822,2827],{"type":42,"tag":161,"props":2809,"children":2810},{"style":195},[2811],{"type":48,"value":2812},"RUN_ID",{"type":42,"tag":161,"props":2814,"children":2815},{"style":184},[2816],{"type":48,"value":2817},"=",{"type":42,"tag":161,"props":2819,"children":2820},{"style":184},[2821],{"type":48,"value":605},{"type":42,"tag":161,"props":2823,"children":2824},{"style":173},[2825],{"type":48,"value":2826},"\u003Crun_id>",{"type":42,"tag":161,"props":2828,"children":2829},{"style":184},[2830],{"type":48,"value":2831},"\"\n",{"type":42,"tag":161,"props":2833,"children":2834},{"class":163,"line":212},[2835],{"type":42,"tag":161,"props":2836,"children":2837},{"emptyLinePlaceholder":2464},[2838],{"type":48,"value":2467},{"type":42,"tag":161,"props":2840,"children":2841},{"class":163,"line":612},[2842],{"type":42,"tag":161,"props":2843,"children":2844},{"style":206},[2845],{"type":48,"value":2846},"# Scope the log window to the run itself: `created` for start, `ended`\n",{"type":42,"tag":161,"props":2848,"children":2849},{"class":163,"line":642},[2850],{"type":42,"tag":161,"props":2851,"children":2852},{"style":206},[2853],{"type":48,"value":2854},"# for end. If `ended` is null the run is still in progress — fall back\n",{"type":42,"tag":161,"props":2856,"children":2857},{"class":163,"line":2486},[2858],{"type":42,"tag":161,"props":2859,"children":2860},{"style":206},[2861],{"type":48,"value":2862},"# to \"now\". Use a wider hard-coded window only when the run object's\n",{"type":42,"tag":161,"props":2864,"children":2865},{"class":163,"line":2495},[2866],{"type":42,"tag":161,"props":2867,"children":2868},{"style":206},[2869],{"type":48,"value":2870},"# timestamps don't fit what you're investigating.\n",{"type":42,"tag":161,"props":2872,"children":2873},{"class":163,"line":2503},[2874,2879,2883,2887,2891,2896,2901,2906,2911],{"type":42,"tag":161,"props":2875,"children":2876},{"style":195},[2877],{"type":48,"value":2878},"RUN",{"type":42,"tag":161,"props":2880,"children":2881},{"style":184},[2882],{"type":48,"value":557},{"type":42,"tag":161,"props":2884,"children":2885},{"style":168},[2886],{"type":48,"value":62},{"type":42,"tag":161,"props":2888,"children":2889},{"style":173},[2890],{"type":48,"value":1927},{"type":42,"tag":161,"props":2892,"children":2893},{"style":173},[2894],{"type":48,"value":2895}," \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F",{"type":42,"tag":161,"props":2897,"children":2898},{"style":195},[2899],{"type":48,"value":2900},"$RUN_ID ",{"type":42,"tag":161,"props":2902,"children":2903},{"style":184},[2904],{"type":48,"value":2905},"2>",{"type":42,"tag":161,"props":2907,"children":2908},{"style":173},[2909],{"type":48,"value":2910},"\u002Fdev\u002Fnull",{"type":42,"tag":161,"props":2912,"children":2913},{"style":184},[2914],{"type":48,"value":678},{"type":42,"tag":161,"props":2916,"children":2917},{"class":163,"line":2512},[2918],{"type":42,"tag":161,"props":2919,"children":2920},{"style":206},[2921],{"type":48,"value":2922},"# k6 emits sub-second precision (e.g. \"...:58.984041Z\"); jq's\n",{"type":42,"tag":161,"props":2924,"children":2925},{"class":163,"line":2521},[2926],{"type":42,"tag":161,"props":2927,"children":2928},{"style":206},[2929],{"type":48,"value":2930},"# fromdateiso8601 only accepts whole seconds, so strip the fraction.\n",{"type":42,"tag":161,"props":2932,"children":2933},{"class":163,"line":2530},[2934,2939,2943,2949,2953,2958,2962,2967,2971,2975,2979,2984,2988],{"type":42,"tag":161,"props":2935,"children":2936},{"style":195},[2937],{"type":48,"value":2938},"START",{"type":42,"tag":161,"props":2940,"children":2941},{"style":184},[2942],{"type":48,"value":557},{"type":42,"tag":161,"props":2944,"children":2946},{"style":2945},"--shiki-light:#6182B8;--shiki-default:#82AAFF;--shiki-dark:#82AAFF",[2947],{"type":48,"value":2948},"echo",{"type":42,"tag":161,"props":2950,"children":2951},{"style":184},[2952],{"type":48,"value":590},{"type":42,"tag":161,"props":2954,"children":2955},{"style":195},[2956],{"type":48,"value":2957},"$RUN",{"type":42,"tag":161,"props":2959,"children":2960},{"style":184},[2961],{"type":48,"value":605},{"type":42,"tag":161,"props":2963,"children":2964},{"style":184},[2965],{"type":48,"value":2966}," |",{"type":42,"tag":161,"props":2968,"children":2969},{"style":168},[2970],{"type":48,"value":653},{"type":42,"tag":161,"props":2972,"children":2973},{"style":173},[2974],{"type":48,"value":658},{"type":42,"tag":161,"props":2976,"children":2977},{"style":184},[2978],{"type":48,"value":663},{"type":42,"tag":161,"props":2980,"children":2981},{"style":173},[2982],{"type":48,"value":2983},".created | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601",{"type":42,"tag":161,"props":2985,"children":2986},{"style":184},[2987],{"type":48,"value":673},{"type":42,"tag":161,"props":2989,"children":2990},{"style":184},[2991],{"type":48,"value":678},{"type":42,"tag":161,"props":2993,"children":2994},{"class":163,"line":2539},[2995,3000,3004,3008,3012,3016,3020,3025,3029,3033,3037,3042,3046],{"type":42,"tag":161,"props":2996,"children":2997},{"style":195},[2998],{"type":48,"value":2999},"END",{"type":42,"tag":161,"props":3001,"children":3002},{"style":184},[3003],{"type":48,"value":557},{"type":42,"tag":161,"props":3005,"children":3006},{"style":2945},[3007],{"type":48,"value":2948},{"type":42,"tag":161,"props":3009,"children":3010},{"style":184},[3011],{"type":48,"value":590},{"type":42,"tag":161,"props":3013,"children":3014},{"style":195},[3015],{"type":48,"value":2957},{"type":42,"tag":161,"props":3017,"children":3018},{"style":184},[3019],{"type":48,"value":605},{"type":42,"tag":161,"props":3021,"children":3022},{"style":184},[3023],{"type":48,"value":3024},"   |",{"type":42,"tag":161,"props":3026,"children":3027},{"style":168},[3028],{"type":48,"value":653},{"type":42,"tag":161,"props":3030,"children":3031},{"style":173},[3032],{"type":48,"value":658},{"type":42,"tag":161,"props":3034,"children":3035},{"style":184},[3036],{"type":48,"value":663},{"type":42,"tag":161,"props":3038,"children":3039},{"style":173},[3040],{"type":48,"value":3041},"if .ended then (.ended | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601) else (now | floor) end",{"type":42,"tag":161,"props":3043,"children":3044},{"style":184},[3045],{"type":48,"value":673},{"type":42,"tag":161,"props":3047,"children":3048},{"style":184},[3049],{"type":48,"value":678},{"type":42,"tag":161,"props":3051,"children":3052},{"class":163,"line":2548},[3053],{"type":42,"tag":161,"props":3054,"children":3055},{"emptyLinePlaceholder":2464},[3056],{"type":48,"value":2467},{"type":42,"tag":161,"props":3058,"children":3059},{"class":163,"line":2556},[3060,3065,3069,3074,3078,3083,3087,3091,3096,3100,3104,3108,3113,3118],{"type":42,"tag":161,"props":3061,"children":3062},{"style":195},[3063],{"type":48,"value":3064},"QUERY",{"type":42,"tag":161,"props":3066,"children":3067},{"style":184},[3068],{"type":48,"value":557},{"type":42,"tag":161,"props":3070,"children":3071},{"style":2945},[3072],{"type":48,"value":3073},"printf",{"type":42,"tag":161,"props":3075,"children":3076},{"style":184},[3077],{"type":48,"value":663},{"type":42,"tag":161,"props":3079,"children":3080},{"style":173},[3081],{"type":48,"value":3082},"{test_run_id=\"%s\"}",{"type":42,"tag":161,"props":3084,"children":3085},{"style":184},[3086],{"type":48,"value":673},{"type":42,"tag":161,"props":3088,"children":3089},{"style":184},[3090],{"type":48,"value":590},{"type":42,"tag":161,"props":3092,"children":3093},{"style":195},[3094],{"type":48,"value":3095},"$RUN_ID",{"type":42,"tag":161,"props":3097,"children":3098},{"style":184},[3099],{"type":48,"value":605},{"type":42,"tag":161,"props":3101,"children":3102},{"style":184},[3103],{"type":48,"value":2966},{"type":42,"tag":161,"props":3105,"children":3106},{"style":168},[3107],{"type":48,"value":653},{"type":42,"tag":161,"props":3109,"children":3110},{"style":173},[3111],{"type":48,"value":3112}," -sRr",{"type":42,"tag":161,"props":3114,"children":3115},{"style":173},[3116],{"type":48,"value":3117}," @uri",{"type":42,"tag":161,"props":3119,"children":3120},{"style":184},[3121],{"type":48,"value":678},{"type":42,"tag":161,"props":3123,"children":3124},{"class":163,"line":2565},[3125],{"type":42,"tag":161,"props":3126,"children":3127},{"emptyLinePlaceholder":2464},[3128],{"type":48,"value":2467},{"type":42,"tag":161,"props":3130,"children":3131},{"class":163,"line":2574},[3132],{"type":42,"tag":161,"props":3133,"children":3134},{"style":206},[3135],{"type":48,"value":3136},"# Save the raw response to \u002Ftmp\u002F — log payloads can be large; streaming\n",{"type":42,"tag":161,"props":3138,"children":3139},{"class":163,"line":30},[3140],{"type":42,"tag":161,"props":3141,"children":3142},{"style":206},[3143],{"type":48,"value":3144},"# them inline burns context. Summarise from the file, then jq into\n",{"type":42,"tag":161,"props":3146,"children":3147},{"class":163,"line":2591},[3148],{"type":42,"tag":161,"props":3149,"children":3150},{"style":206},[3151],{"type":48,"value":3152},"# specific entries only when needed.\n",{"type":42,"tag":161,"props":3154,"children":3155},{"class":163,"line":2600},[3156,3160,3164,3168,3173,3178,3182,3187,3192,3196,3200,3204,3209,3213,3217,3221,3226,3230],{"type":42,"tag":161,"props":3157,"children":3158},{"style":168},[3159],{"type":48,"value":62},{"type":42,"tag":161,"props":3161,"children":3162},{"style":173},[3163],{"type":48,"value":1927},{"type":42,"tag":161,"props":3165,"children":3166},{"style":184},[3167],{"type":48,"value":590},{"type":42,"tag":161,"props":3169,"children":3170},{"style":173},[3171],{"type":48,"value":3172},"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Fquery_range?query=",{"type":42,"tag":161,"props":3174,"children":3175},{"style":184},[3176],{"type":48,"value":3177},"${",{"type":42,"tag":161,"props":3179,"children":3180},{"style":195},[3181],{"type":48,"value":3064},{"type":42,"tag":161,"props":3183,"children":3184},{"style":184},[3185],{"type":48,"value":3186},"}",{"type":42,"tag":161,"props":3188,"children":3189},{"style":173},[3190],{"type":48,"value":3191},"&direction=backward&start=",{"type":42,"tag":161,"props":3193,"children":3194},{"style":184},[3195],{"type":48,"value":3177},{"type":42,"tag":161,"props":3197,"children":3198},{"style":195},[3199],{"type":48,"value":2938},{"type":42,"tag":161,"props":3201,"children":3202},{"style":184},[3203],{"type":48,"value":3186},{"type":42,"tag":161,"props":3205,"children":3206},{"style":173},[3207],{"type":48,"value":3208},"&end=",{"type":42,"tag":161,"props":3210,"children":3211},{"style":184},[3212],{"type":48,"value":3177},{"type":42,"tag":161,"props":3214,"children":3215},{"style":195},[3216],{"type":48,"value":2999},{"type":42,"tag":161,"props":3218,"children":3219},{"style":184},[3220],{"type":48,"value":3186},{"type":42,"tag":161,"props":3222,"children":3223},{"style":173},[3224],{"type":48,"value":3225},"&limit=1000",{"type":42,"tag":161,"props":3227,"children":3228},{"style":184},[3229],{"type":48,"value":605},{"type":42,"tag":161,"props":3231,"children":3232},{"style":195},[3233],{"type":48,"value":577},{"type":42,"tag":161,"props":3235,"children":3236},{"class":163,"line":2609},[3237,3241,3245,3250,3254,3258,3263,3267,3271,3276,3280,3284,3288],{"type":42,"tag":161,"props":3238,"children":3239},{"style":173},[3240],{"type":48,"value":585},{"type":42,"tag":161,"props":3242,"children":3243},{"style":184},[3244],{"type":48,"value":590},{"type":42,"tag":161,"props":3246,"children":3247},{"style":173},[3248],{"type":48,"value":3249},"X-K6TestRun-Id: ",{"type":42,"tag":161,"props":3251,"children":3252},{"style":195},[3253],{"type":48,"value":3095},{"type":42,"tag":161,"props":3255,"children":3256},{"style":184},[3257],{"type":48,"value":605},{"type":42,"tag":161,"props":3259,"children":3260},{"style":184},[3261],{"type":48,"value":3262}," 2>",{"type":42,"tag":161,"props":3264,"children":3265},{"style":173},[3266],{"type":48,"value":2910},{"type":42,"tag":161,"props":3268,"children":3269},{"style":184},[3270],{"type":48,"value":1937},{"type":42,"tag":161,"props":3272,"children":3273},{"style":173},[3274],{"type":48,"value":3275}," \u002Ftmp\u002Frun_",{"type":42,"tag":161,"props":3277,"children":3278},{"style":184},[3279],{"type":48,"value":3177},{"type":42,"tag":161,"props":3281,"children":3282},{"style":195},[3283],{"type":48,"value":2812},{"type":42,"tag":161,"props":3285,"children":3286},{"style":184},[3287],{"type":48,"value":3186},{"type":42,"tag":161,"props":3289,"children":3290},{"style":173},[3291],{"type":48,"value":3292},"_logs.json\n",{"type":42,"tag":161,"props":3294,"children":3295},{"class":163,"line":2618},[3296],{"type":42,"tag":161,"props":3297,"children":3298},{"emptyLinePlaceholder":2464},[3299],{"type":48,"value":2467},{"type":42,"tag":161,"props":3301,"children":3302},{"class":163,"line":2627},[3303],{"type":42,"tag":161,"props":3304,"children":3305},{"style":206},[3306],{"type":48,"value":3307},"# Tight summary — counts and stream labels only:\n",{"type":42,"tag":161,"props":3309,"children":3310},{"class":163,"line":2636},[3311,3315,3319],{"type":42,"tag":161,"props":3312,"children":3313},{"style":168},[3314],{"type":48,"value":1421},{"type":42,"tag":161,"props":3316,"children":3317},{"style":184},[3318],{"type":48,"value":663},{"type":42,"tag":161,"props":3320,"children":3321},{"style":173},[3322],{"type":48,"value":3323},"{status, streams: (.data.result | length),\n",{"type":42,"tag":161,"props":3325,"children":3326},{"class":163,"line":2645},[3327],{"type":42,"tag":161,"props":3328,"children":3329},{"style":173},[3330],{"type":48,"value":3331},"     total_entries: ([.data.result[].values | length] | add),\n",{"type":42,"tag":161,"props":3333,"children":3334},{"class":163,"line":2654},[3335,3340,3344,3348,3352,3356,3360],{"type":42,"tag":161,"props":3336,"children":3337},{"style":173},[3338],{"type":48,"value":3339},"     stream_labels: [.data.result[].stream]}",{"type":42,"tag":161,"props":3341,"children":3342},{"style":184},[3343],{"type":48,"value":673},{"type":42,"tag":161,"props":3345,"children":3346},{"style":173},[3347],{"type":48,"value":3275},{"type":42,"tag":161,"props":3349,"children":3350},{"style":184},[3351],{"type":48,"value":3177},{"type":42,"tag":161,"props":3353,"children":3354},{"style":195},[3355],{"type":48,"value":2812},{"type":42,"tag":161,"props":3357,"children":3358},{"style":184},[3359],{"type":48,"value":3186},{"type":42,"tag":161,"props":3361,"children":3362},{"style":173},[3363],{"type":48,"value":3292},{"type":42,"tag":51,"props":3365,"children":3366},{},[3367,3369,3375,3377,3383],{"type":48,"value":3368},"Pull individual entries from ",{"type":42,"tag":57,"props":3370,"children":3372},{"className":3371},[],[3373],{"type":48,"value":3374},"\u002Ftmp\u002Frun_${RUN_ID}_logs.json",{"type":48,"value":3376}," as needed\n(e.g. ",{"type":42,"tag":57,"props":3378,"children":3380},{"className":3379},[],[3381],{"type":48,"value":3382},"jq '.data.result[].values[]' …",{"type":48,"value":3384},") rather than re-running the\nquery.",{"type":42,"tag":51,"props":3386,"children":3387},{},[3388,3390,3395,3397,3403],{"type":48,"value":3389},"Every LogQL query ",{"type":42,"tag":74,"props":3391,"children":3392},{},[3393],{"type":48,"value":3394},"must",{"type":48,"value":3396}," include the ",{"type":42,"tag":57,"props":3398,"children":3400},{"className":3399},[],[3401],{"type":48,"value":3402},"{test_run_id=\"\u003Crun_id>\"}",{"type":48,"value":3404}," stream\nselector — the plugin proxy partitions logs by run and rejects (or\nreturns nothing for) queries without it. Layer additional filters on\ntop of that selector:",{"type":42,"tag":66,"props":3406,"children":3407},{},[3408,3418,3429],{"type":42,"tag":70,"props":3409,"children":3410},{},[3411,3416],{"type":42,"tag":57,"props":3412,"children":3414},{"className":3413},[],[3415],{"type":48,"value":3402},{"type":48,"value":3417}," — everything",{"type":42,"tag":70,"props":3419,"children":3420},{},[3421,3427],{"type":42,"tag":57,"props":3422,"children":3424},{"className":3423},[],[3425],{"type":48,"value":3426},"{test_run_id=\"\u003Crun_id>\"} | level=~\"(error|warn)\"",{"type":48,"value":3428}," — errors and warnings only",{"type":42,"tag":70,"props":3430,"children":3431},{},[3432,3438],{"type":42,"tag":57,"props":3433,"children":3435},{"className":3434},[],[3436],{"type":48,"value":3437},"{test_run_id=\"\u003Crun_id>\"} |= \"specific text\"",{"type":48,"value":3439}," — substring filter",{"type":42,"tag":51,"props":3441,"children":3442},{},[3443],{"type":48,"value":3444},"Direction & window tips:",{"type":42,"tag":66,"props":3446,"children":3447},{},[3448,3488,3514,3539],{"type":42,"tag":70,"props":3449,"children":3450},{},[3451,3486],{"type":42,"tag":74,"props":3452,"children":3453},{},[3454,3456,3462,3464,3470,3472,3477,3478,3484],{"type":48,"value":3455},"Scope ",{"type":42,"tag":57,"props":3457,"children":3459},{"className":3458},[],[3460],{"type":48,"value":3461},"start",{"type":48,"value":3463},"\u002F",{"type":42,"tag":57,"props":3465,"children":3467},{"className":3466},[],[3468],{"type":48,"value":3469},"end",{"type":48,"value":3471}," to the run's ",{"type":42,"tag":57,"props":3473,"children":3475},{"className":3474},[],[3476],{"type":48,"value":2147},{"type":48,"value":3463},{"type":42,"tag":57,"props":3479,"children":3481},{"className":3480},[],[3482],{"type":48,"value":3483},"ended",{"type":48,"value":3485}," fields",{"type":48,"value":3487},", not to\nwall-clock \"last hour\" — otherwise queries silently miss anything\nolder than the window. The only reason to deviate is when you\nspecifically want a different interval (e.g. surrounding context).",{"type":42,"tag":70,"props":3489,"children":3490},{},[3491,3497,3499,3505,3507,3512],{"type":42,"tag":57,"props":3492,"children":3494},{"className":3493},[],[3495],{"type":48,"value":3496},"direction=forward",{"type":48,"value":3498}," with ",{"type":42,"tag":57,"props":3500,"children":3502},{"className":3501},[],[3503],{"type":48,"value":3504},"start = run.created",{"type":48,"value":3506}," to find the ",{"type":42,"tag":274,"props":3508,"children":3509},{},[3510],{"type":48,"value":3511},"first",{"type":48,"value":3513}," errors.",{"type":42,"tag":70,"props":3515,"children":3516},{},[3517,3523,3524,3530,3532,3537],{"type":42,"tag":57,"props":3518,"children":3520},{"className":3519},[],[3521],{"type":48,"value":3522},"direction=backward",{"type":48,"value":3498},{"type":42,"tag":57,"props":3525,"children":3527},{"className":3526},[],[3528],{"type":48,"value":3529},"end = run.ended",{"type":48,"value":3531}," (or now, if still running)\nto find the ",{"type":42,"tag":274,"props":3533,"children":3534},{},[3535],{"type":48,"value":3536},"most recent",{"type":48,"value":3538}," output.",{"type":42,"tag":70,"props":3540,"children":3541},{},[3542],{"type":48,"value":3543},"Loki retention typically outlives k6's cascade-delete, so logs of a\ndeleted child run may still be queryable for a while.",{"type":42,"tag":132,"props":3545,"children":3546},{},[],{"type":42,"tag":136,"props":3548,"children":3550},{"id":3549},"_5-editing-a-test-script-safely",[3551],{"type":48,"value":3552},"5. Editing a test script safely",{"type":42,"tag":143,"props":3554,"children":3556},{"id":3555},"two-distinct-script-endpoints",[3557],{"type":48,"value":3558},"Two distinct script endpoints",{"type":42,"tag":51,"props":3560,"children":3561},{},[3562],{"type":48,"value":3563},"There are two GET endpoints that return a k6 script body, and they are\nnot interchangeable:",{"type":42,"tag":728,"props":3565,"children":3566},{},[3567,3588],{"type":42,"tag":732,"props":3568,"children":3569},{},[3570],{"type":42,"tag":736,"props":3571,"children":3572},{},[3573,3578,3583],{"type":42,"tag":740,"props":3574,"children":3575},{},[3576],{"type":48,"value":3577},"Endpoint",{"type":42,"tag":740,"props":3579,"children":3580},{},[3581],{"type":48,"value":3582},"What it returns",{"type":42,"tag":740,"props":3584,"children":3585},{},[3586],{"type":48,"value":3587},"When to use",{"type":42,"tag":751,"props":3589,"children":3590},{},[3591,3619],{"type":42,"tag":736,"props":3592,"children":3593},{},[3594,3603,3614],{"type":42,"tag":758,"props":3595,"children":3596},{},[3597],{"type":42,"tag":57,"props":3598,"children":3600},{"className":3599},[],[3601],{"type":48,"value":3602},"\u002Fcloud\u002Fv6\u002Fload_tests\u002F\u003Ctest_id>\u002Fscript",{"type":42,"tag":758,"props":3604,"children":3605},{},[3606,3607,3612],{"type":48,"value":932},{"type":42,"tag":74,"props":3608,"children":3609},{},[3610],{"type":48,"value":3611},"current",{"type":48,"value":3613}," load-test script (mutable; supports PUT)",{"type":42,"tag":758,"props":3615,"children":3616},{},[3617],{"type":48,"value":3618},"Editing the script; reading current state",{"type":42,"tag":736,"props":3620,"children":3621},{},[3622,3631,3643],{"type":42,"tag":758,"props":3623,"children":3624},{},[3625],{"type":42,"tag":57,"props":3626,"children":3628},{"className":3627},[],[3629],{"type":48,"value":3630},"\u002Fcloud\u002Fv6\u002Ftest_runs\u002F\u003Crun_id>\u002Fscript",{"type":42,"tag":758,"props":3632,"children":3633},{},[3634,3636,3641],{"type":48,"value":3635},"The script ",{"type":42,"tag":74,"props":3637,"children":3638},{},[3639],{"type":48,"value":3640},"snapshot bundled into a specific run",{"type":48,"value":3642}," (read-only)",{"type":42,"tag":758,"props":3644,"children":3645},{},[3646],{"type":48,"value":3647},"Investigating what a past run actually executed; diffing across versions",{"type":42,"tag":51,"props":3649,"children":3650},{},[3651],{"type":48,"value":3652},"The two can drift apart: if the load-test script is edited after a\nrun completes, that run's bundled snapshot stays frozen at what it\nexecuted, while the load-test endpoint serves the new current version.\nThe bundled-snapshot endpoint is GET-only — you cannot mutate\nhistorical bytes.",{"type":42,"tag":51,"props":3654,"children":3655},{},[3656,3658,3664],{"type":48,"value":3657},"The safe-edit recipe below uses the load-test endpoint (the editable\none). For run-vs-run script diffs (e.g. \"did the script change between\nthe last passing and first failing run?\"), GET both runs'\n",{"type":42,"tag":57,"props":3659,"children":3661},{"className":3660},[],[3662],{"type":48,"value":3663},"\u002Ftest_runs\u002F\u003Cid>\u002Fscript",{"type":48,"value":3665}," and diff them locally.",{"type":42,"tag":143,"props":3667,"children":3669},{"id":3668},"script-body-format",[3670],{"type":48,"value":3671},"Script body format",{"type":42,"tag":51,"props":3673,"children":3674},{},[3675],{"type":48,"value":3676},"The script GET endpoint returns one of two shapes — always detect which\nbefore assuming the format:",{"type":42,"tag":66,"props":3678,"children":3679},{},[3680,3690],{"type":42,"tag":70,"props":3681,"children":3682},{},[3683,3688],{"type":42,"tag":74,"props":3684,"children":3685},{},[3686],{"type":48,"value":3687},"Single js\u002Fts file",{"type":48,"value":3689},". The recipe below handles this case directly.",{"type":42,"tag":70,"props":3691,"children":3692},{},[3693,3698,3700,3706,3708,3713,3715,3721,3723,3729,3731,3736,3738],{"type":42,"tag":74,"props":3694,"children":3695},{},[3696],{"type":48,"value":3697},"k6 tar archive",{"type":48,"value":3699}," (plain tar or gzipped). A multi-file project\nbundle (entry script + imported modules + assets). To edit: extract\nthe JS file, modify it, then use ",{"type":42,"tag":57,"props":3701,"children":3703},{"className":3702},[],[3704],{"type":48,"value":3705},"k6 archive",{"type":48,"value":3707}," to rebuild the\narchive from the modified JS. Do ",{"type":42,"tag":74,"props":3709,"children":3710},{},[3711],{"type":48,"value":3712},"not",{"type":48,"value":3714}," manually repack with\n",{"type":42,"tag":57,"props":3716,"children":3718},{"className":3717},[],[3719],{"type":48,"value":3720},"tar",{"type":48,"value":3722}," — the archive contains a ",{"type":42,"tag":57,"props":3724,"children":3726},{"className":3725},[],[3727],{"type":48,"value":3728},"metadata.json",{"type":48,"value":3730}," with parsed options\n(projectID, thresholds, scenarios) that ",{"type":42,"tag":57,"props":3732,"children":3734},{"className":3733},[],[3735],{"type":48,"value":3705},{"type":48,"value":3737}," regenerates\ncorrectly from the script source. Manual repacking preserves stale\nmetadata and causes runtime errors (e.g. projectID mismatch).",{"type":42,"tag":150,"props":3739,"children":3741},{"className":152,"code":3740,"language":154,"meta":155,"style":155},"# Edit a k6 tar archive\ntar -xf \u002Ftmp\u002Fscript_body -C \u002Ftmp\u002Fextracted\u002F   # extract\n# ... edit the JS file ...\nk6 archive \u002Ftmp\u002Fedited_script.js -O \u002Ftmp\u002Fnew_archive.tar  # rebuild\n",[3742],{"type":42,"tag":57,"props":3743,"children":3744},{"__ignoreMap":155},[3745,3753,3785,3793],{"type":42,"tag":161,"props":3746,"children":3747},{"class":163,"line":164},[3748],{"type":42,"tag":161,"props":3749,"children":3750},{"style":206},[3751],{"type":48,"value":3752},"# Edit a k6 tar archive\n",{"type":42,"tag":161,"props":3754,"children":3755},{"class":163,"line":212},[3756,3760,3765,3770,3775,3780],{"type":42,"tag":161,"props":3757,"children":3758},{"style":168},[3759],{"type":48,"value":3720},{"type":42,"tag":161,"props":3761,"children":3762},{"style":173},[3763],{"type":48,"value":3764}," -xf",{"type":42,"tag":161,"props":3766,"children":3767},{"style":173},[3768],{"type":48,"value":3769}," \u002Ftmp\u002Fscript_body",{"type":42,"tag":161,"props":3771,"children":3772},{"style":173},[3773],{"type":48,"value":3774}," -C",{"type":42,"tag":161,"props":3776,"children":3777},{"style":173},[3778],{"type":48,"value":3779}," \u002Ftmp\u002Fextracted\u002F",{"type":42,"tag":161,"props":3781,"children":3782},{"style":206},[3783],{"type":48,"value":3784},"   # extract\n",{"type":42,"tag":161,"props":3786,"children":3787},{"class":163,"line":612},[3788],{"type":42,"tag":161,"props":3789,"children":3790},{"style":206},[3791],{"type":48,"value":3792},"# ... edit the JS file ...\n",{"type":42,"tag":161,"props":3794,"children":3795},{"class":163,"line":642},[3796,3801,3806,3811,3816,3821],{"type":42,"tag":161,"props":3797,"children":3798},{"style":168},[3799],{"type":48,"value":3800},"k6",{"type":42,"tag":161,"props":3802,"children":3803},{"style":173},[3804],{"type":48,"value":3805}," archive",{"type":42,"tag":161,"props":3807,"children":3808},{"style":173},[3809],{"type":48,"value":3810}," \u002Ftmp\u002Fedited_script.js",{"type":42,"tag":161,"props":3812,"children":3813},{"style":173},[3814],{"type":48,"value":3815}," -O",{"type":42,"tag":161,"props":3817,"children":3818},{"style":173},[3819],{"type":48,"value":3820}," \u002Ftmp\u002Fnew_archive.tar",{"type":42,"tag":161,"props":3822,"children":3823},{"style":206},[3824],{"type":48,"value":3825},"  # rebuild\n",{"type":42,"tag":51,"props":3827,"children":3828},{},[3829,3834,3836,3842],{"type":42,"tag":57,"props":3830,"children":3832},{"className":3831},[],[3833],{"type":48,"value":128},{"type":48,"value":3835}," doesn't expose response headers (see §2), so detect the shape\nby inspecting the downloaded body with ",{"type":42,"tag":57,"props":3837,"children":3839},{"className":3838},[],[3840],{"type":48,"value":3841},"file(1)",{"type":48,"value":537},{"type":42,"tag":150,"props":3844,"children":3846},{"className":152,"code":3845,"language":154,"meta":155,"style":155},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F$ID\u002Fscript \\\n  > \u002Ftmp\u002Fscript_body\nfile \u002Ftmp\u002Fscript_body\n# Expected output (examples):\n#   ASCII text          → js\u002Fts source\n#   POSIX tar archive   → k6 tar bundle\n#   gzip compressed data → gzipped tar bundle\n",[3847],{"type":42,"tag":57,"props":3848,"children":3849},{"__ignoreMap":155},[3850,3880,3893,3905,3913,3921,3929],{"type":42,"tag":161,"props":3851,"children":3852},{"class":163,"line":164},[3853,3857,3861,3866,3871,3876],{"type":42,"tag":161,"props":3854,"children":3855},{"style":168},[3856],{"type":48,"value":62},{"type":42,"tag":161,"props":3858,"children":3859},{"style":173},[3860],{"type":48,"value":1927},{"type":42,"tag":161,"props":3862,"children":3863},{"style":173},[3864],{"type":48,"value":3865}," \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F",{"type":42,"tag":161,"props":3867,"children":3868},{"style":195},[3869],{"type":48,"value":3870},"$ID",{"type":42,"tag":161,"props":3872,"children":3873},{"style":173},[3874],{"type":48,"value":3875},"\u002Fscript",{"type":42,"tag":161,"props":3877,"children":3878},{"style":195},[3879],{"type":48,"value":577},{"type":42,"tag":161,"props":3881,"children":3882},{"class":163,"line":212},[3883,3888],{"type":42,"tag":161,"props":3884,"children":3885},{"style":184},[3886],{"type":48,"value":3887},"  >",{"type":42,"tag":161,"props":3889,"children":3890},{"style":173},[3891],{"type":48,"value":3892}," \u002Ftmp\u002Fscript_body\n",{"type":42,"tag":161,"props":3894,"children":3895},{"class":163,"line":612},[3896,3901],{"type":42,"tag":161,"props":3897,"children":3898},{"style":168},[3899],{"type":48,"value":3900},"file",{"type":42,"tag":161,"props":3902,"children":3903},{"style":173},[3904],{"type":48,"value":3892},{"type":42,"tag":161,"props":3906,"children":3907},{"class":163,"line":642},[3908],{"type":42,"tag":161,"props":3909,"children":3910},{"style":206},[3911],{"type":48,"value":3912},"# Expected output (examples):\n",{"type":42,"tag":161,"props":3914,"children":3915},{"class":163,"line":2486},[3916],{"type":42,"tag":161,"props":3917,"children":3918},{"style":206},[3919],{"type":48,"value":3920},"#   ASCII text          → js\u002Fts source\n",{"type":42,"tag":161,"props":3922,"children":3923},{"class":163,"line":2495},[3924],{"type":42,"tag":161,"props":3925,"children":3926},{"style":206},[3927],{"type":48,"value":3928},"#   POSIX tar archive   → k6 tar bundle\n",{"type":42,"tag":161,"props":3930,"children":3931},{"class":163,"line":2503},[3932],{"type":42,"tag":161,"props":3933,"children":3934},{"style":206},[3935],{"type":48,"value":3936},"#   gzip compressed data → gzipped tar bundle\n",{"type":42,"tag":51,"props":3938,"children":3939},{},[3940,3942,3947],{"type":48,"value":3941},"The PUT body must be the raw script (or archive) bytes\n(",{"type":42,"tag":57,"props":3943,"children":3945},{"className":3944},[],[3946],{"type":48,"value":1852},{"type":48,"value":3948},"). gcx forwards the request to k6 unchanged.",{"type":42,"tag":150,"props":3950,"children":3952},{"className":152,"code":3951,"language":154,"meta":155,"style":155},"ID=\"\u003Cload_test_id>\"\n\n# 1. Pull current script (single-file js\u002Fts case)\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F$ID\u002Fscript \\\n  > \u002Ftmp\u002Fscript_current.js\n\n# 2. Backup\ncp \u002Ftmp\u002Fscript_current.js \u002Ftmp\u002Fscript_backup_$(date +%s).js\n\n# 3. Edit → \u002Ftmp\u002Fscript_new.js\n\n# 4. Local parse-only sanity check\nk6 inspect \u002Ftmp\u002Fscript_new.js | head -20\n\n# 5. 1-iteration smoke (edit IN-FILE; --iterations CLI flag breaks browser scenarios)\nsed 's\u002Fiterations: [0-9]\\+\u002Fiterations: 1\u002F' \u002Ftmp\u002Fscript_new.js > \u002Ftmp\u002Fscript_1iter.js\nk6 run --quiet \u002Ftmp\u002Fscript_1iter.js   # exit 0 = pass, 99 = threshold fail\n\n# 6. PUT — Content-Type must be application\u002Foctet-stream\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F$ID\u002Fscript \\\n  -X PUT \\\n  -H \"Content-Type: application\u002Foctet-stream\" \\\n  -d \"@\u002Ftmp\u002Fscript_new.js\"\n\n# 7. Verify by re-fetching and comparing sha256 — the two hashes MUST match.\n#    Do not rely on the `updated` timestamp; it does not bump on script PUT.\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F$ID\u002Fscript \\\n  > \u002Ftmp\u002Fscript_verify.js\nshasum -a 256 \u002Ftmp\u002Fscript_new.js \u002Ftmp\u002Fscript_verify.js\n",[3953],{"type":42,"tag":57,"props":3954,"children":3955},{"__ignoreMap":155},[3956,3981,3988,3996,4023,4035,4042,4050,4092,4099,4107,4114,4122,4153,4160,4168,4202,4229,4236,4244,4271,4288,4312,4333,4340,4348,4356,4384,4397],{"type":42,"tag":161,"props":3957,"children":3958},{"class":163,"line":164},[3959,3964,3968,3972,3977],{"type":42,"tag":161,"props":3960,"children":3961},{"style":195},[3962],{"type":48,"value":3963},"ID",{"type":42,"tag":161,"props":3965,"children":3966},{"style":184},[3967],{"type":48,"value":2817},{"type":42,"tag":161,"props":3969,"children":3970},{"style":184},[3971],{"type":48,"value":605},{"type":42,"tag":161,"props":3973,"children":3974},{"style":173},[3975],{"type":48,"value":3976},"\u003Cload_test_id>",{"type":42,"tag":161,"props":3978,"children":3979},{"style":184},[3980],{"type":48,"value":2831},{"type":42,"tag":161,"props":3982,"children":3983},{"class":163,"line":212},[3984],{"type":42,"tag":161,"props":3985,"children":3986},{"emptyLinePlaceholder":2464},[3987],{"type":48,"value":2467},{"type":42,"tag":161,"props":3989,"children":3990},{"class":163,"line":612},[3991],{"type":42,"tag":161,"props":3992,"children":3993},{"style":206},[3994],{"type":48,"value":3995},"# 1. Pull current script (single-file js\u002Fts case)\n",{"type":42,"tag":161,"props":3997,"children":3998},{"class":163,"line":642},[3999,4003,4007,4011,4015,4019],{"type":42,"tag":161,"props":4000,"children":4001},{"style":168},[4002],{"type":48,"value":62},{"type":42,"tag":161,"props":4004,"children":4005},{"style":173},[4006],{"type":48,"value":1927},{"type":42,"tag":161,"props":4008,"children":4009},{"style":173},[4010],{"type":48,"value":3865},{"type":42,"tag":161,"props":4012,"children":4013},{"style":195},[4014],{"type":48,"value":3870},{"type":42,"tag":161,"props":4016,"children":4017},{"style":173},[4018],{"type":48,"value":3875},{"type":42,"tag":161,"props":4020,"children":4021},{"style":195},[4022],{"type":48,"value":577},{"type":42,"tag":161,"props":4024,"children":4025},{"class":163,"line":2486},[4026,4030],{"type":42,"tag":161,"props":4027,"children":4028},{"style":184},[4029],{"type":48,"value":3887},{"type":42,"tag":161,"props":4031,"children":4032},{"style":173},[4033],{"type":48,"value":4034}," \u002Ftmp\u002Fscript_current.js\n",{"type":42,"tag":161,"props":4036,"children":4037},{"class":163,"line":2495},[4038],{"type":42,"tag":161,"props":4039,"children":4040},{"emptyLinePlaceholder":2464},[4041],{"type":48,"value":2467},{"type":42,"tag":161,"props":4043,"children":4044},{"class":163,"line":2503},[4045],{"type":42,"tag":161,"props":4046,"children":4047},{"style":206},[4048],{"type":48,"value":4049},"# 2. Backup\n",{"type":42,"tag":161,"props":4051,"children":4052},{"class":163,"line":2512},[4053,4058,4063,4068,4073,4078,4083,4087],{"type":42,"tag":161,"props":4054,"children":4055},{"style":168},[4056],{"type":48,"value":4057},"cp",{"type":42,"tag":161,"props":4059,"children":4060},{"style":173},[4061],{"type":48,"value":4062}," \u002Ftmp\u002Fscript_current.js",{"type":42,"tag":161,"props":4064,"children":4065},{"style":173},[4066],{"type":48,"value":4067}," \u002Ftmp\u002Fscript_backup_",{"type":42,"tag":161,"props":4069,"children":4070},{"style":184},[4071],{"type":48,"value":4072},"$(",{"type":42,"tag":161,"props":4074,"children":4075},{"style":168},[4076],{"type":48,"value":4077},"date",{"type":42,"tag":161,"props":4079,"children":4080},{"style":173},[4081],{"type":48,"value":4082}," +%s",{"type":42,"tag":161,"props":4084,"children":4085},{"style":184},[4086],{"type":48,"value":2777},{"type":42,"tag":161,"props":4088,"children":4089},{"style":173},[4090],{"type":48,"value":4091},".js\n",{"type":42,"tag":161,"props":4093,"children":4094},{"class":163,"line":2521},[4095],{"type":42,"tag":161,"props":4096,"children":4097},{"emptyLinePlaceholder":2464},[4098],{"type":48,"value":2467},{"type":42,"tag":161,"props":4100,"children":4101},{"class":163,"line":2530},[4102],{"type":42,"tag":161,"props":4103,"children":4104},{"style":206},[4105],{"type":48,"value":4106},"# 3. Edit → \u002Ftmp\u002Fscript_new.js\n",{"type":42,"tag":161,"props":4108,"children":4109},{"class":163,"line":2539},[4110],{"type":42,"tag":161,"props":4111,"children":4112},{"emptyLinePlaceholder":2464},[4113],{"type":48,"value":2467},{"type":42,"tag":161,"props":4115,"children":4116},{"class":163,"line":2548},[4117],{"type":42,"tag":161,"props":4118,"children":4119},{"style":206},[4120],{"type":48,"value":4121},"# 4. Local parse-only sanity check\n",{"type":42,"tag":161,"props":4123,"children":4124},{"class":163,"line":2556},[4125,4129,4134,4139,4143,4148],{"type":42,"tag":161,"props":4126,"children":4127},{"style":168},[4128],{"type":48,"value":3800},{"type":42,"tag":161,"props":4130,"children":4131},{"style":173},[4132],{"type":48,"value":4133}," inspect",{"type":42,"tag":161,"props":4135,"children":4136},{"style":173},[4137],{"type":48,"value":4138}," \u002Ftmp\u002Fscript_new.js",{"type":42,"tag":161,"props":4140,"children":4141},{"style":184},[4142],{"type":48,"value":2966},{"type":42,"tag":161,"props":4144,"children":4145},{"style":168},[4146],{"type":48,"value":4147}," head",{"type":42,"tag":161,"props":4149,"children":4150},{"style":173},[4151],{"type":48,"value":4152}," -20\n",{"type":42,"tag":161,"props":4154,"children":4155},{"class":163,"line":2565},[4156],{"type":42,"tag":161,"props":4157,"children":4158},{"emptyLinePlaceholder":2464},[4159],{"type":48,"value":2467},{"type":42,"tag":161,"props":4161,"children":4162},{"class":163,"line":2574},[4163],{"type":42,"tag":161,"props":4164,"children":4165},{"style":206},[4166],{"type":48,"value":4167},"# 5. 1-iteration smoke (edit IN-FILE; --iterations CLI flag breaks browser scenarios)\n",{"type":42,"tag":161,"props":4169,"children":4170},{"class":163,"line":30},[4171,4176,4180,4185,4189,4193,4197],{"type":42,"tag":161,"props":4172,"children":4173},{"style":168},[4174],{"type":48,"value":4175},"sed",{"type":42,"tag":161,"props":4177,"children":4178},{"style":184},[4179],{"type":48,"value":663},{"type":42,"tag":161,"props":4181,"children":4182},{"style":173},[4183],{"type":48,"value":4184},"s\u002Fiterations: [0-9]\\+\u002Fiterations: 1\u002F",{"type":42,"tag":161,"props":4186,"children":4187},{"style":184},[4188],{"type":48,"value":673},{"type":42,"tag":161,"props":4190,"children":4191},{"style":173},[4192],{"type":48,"value":4138},{"type":42,"tag":161,"props":4194,"children":4195},{"style":184},[4196],{"type":48,"value":1937},{"type":42,"tag":161,"props":4198,"children":4199},{"style":173},[4200],{"type":48,"value":4201}," \u002Ftmp\u002Fscript_1iter.js\n",{"type":42,"tag":161,"props":4203,"children":4204},{"class":163,"line":2591},[4205,4209,4214,4219,4224],{"type":42,"tag":161,"props":4206,"children":4207},{"style":168},[4208],{"type":48,"value":3800},{"type":42,"tag":161,"props":4210,"children":4211},{"style":173},[4212],{"type":48,"value":4213}," run",{"type":42,"tag":161,"props":4215,"children":4216},{"style":173},[4217],{"type":48,"value":4218}," --quiet",{"type":42,"tag":161,"props":4220,"children":4221},{"style":173},[4222],{"type":48,"value":4223}," \u002Ftmp\u002Fscript_1iter.js",{"type":42,"tag":161,"props":4225,"children":4226},{"style":206},[4227],{"type":48,"value":4228},"   # exit 0 = pass, 99 = threshold fail\n",{"type":42,"tag":161,"props":4230,"children":4231},{"class":163,"line":2600},[4232],{"type":42,"tag":161,"props":4233,"children":4234},{"emptyLinePlaceholder":2464},[4235],{"type":48,"value":2467},{"type":42,"tag":161,"props":4237,"children":4238},{"class":163,"line":2609},[4239],{"type":42,"tag":161,"props":4240,"children":4241},{"style":206},[4242],{"type":48,"value":4243},"# 6. PUT — Content-Type must be application\u002Foctet-stream\n",{"type":42,"tag":161,"props":4245,"children":4246},{"class":163,"line":2618},[4247,4251,4255,4259,4263,4267],{"type":42,"tag":161,"props":4248,"children":4249},{"style":168},[4250],{"type":48,"value":62},{"type":42,"tag":161,"props":4252,"children":4253},{"style":173},[4254],{"type":48,"value":1927},{"type":42,"tag":161,"props":4256,"children":4257},{"style":173},[4258],{"type":48,"value":3865},{"type":42,"tag":161,"props":4260,"children":4261},{"style":195},[4262],{"type":48,"value":3870},{"type":42,"tag":161,"props":4264,"children":4265},{"style":173},[4266],{"type":48,"value":3875},{"type":42,"tag":161,"props":4268,"children":4269},{"style":195},[4270],{"type":48,"value":577},{"type":42,"tag":161,"props":4272,"children":4273},{"class":163,"line":2627},[4274,4279,4284],{"type":42,"tag":161,"props":4275,"children":4276},{"style":173},[4277],{"type":48,"value":4278},"  -X",{"type":42,"tag":161,"props":4280,"children":4281},{"style":173},[4282],{"type":48,"value":4283}," PUT",{"type":42,"tag":161,"props":4285,"children":4286},{"style":195},[4287],{"type":48,"value":577},{"type":42,"tag":161,"props":4289,"children":4290},{"class":163,"line":2636},[4291,4295,4299,4304,4308],{"type":42,"tag":161,"props":4292,"children":4293},{"style":173},[4294],{"type":48,"value":585},{"type":42,"tag":161,"props":4296,"children":4297},{"style":184},[4298],{"type":48,"value":590},{"type":42,"tag":161,"props":4300,"children":4301},{"style":173},[4302],{"type":48,"value":4303},"Content-Type: application\u002Foctet-stream",{"type":42,"tag":161,"props":4305,"children":4306},{"style":184},[4307],{"type":48,"value":605},{"type":42,"tag":161,"props":4309,"children":4310},{"style":195},[4311],{"type":48,"value":577},{"type":42,"tag":161,"props":4313,"children":4314},{"class":163,"line":2645},[4315,4320,4324,4329],{"type":42,"tag":161,"props":4316,"children":4317},{"style":173},[4318],{"type":48,"value":4319},"  -d",{"type":42,"tag":161,"props":4321,"children":4322},{"style":184},[4323],{"type":48,"value":590},{"type":42,"tag":161,"props":4325,"children":4326},{"style":173},[4327],{"type":48,"value":4328},"@\u002Ftmp\u002Fscript_new.js",{"type":42,"tag":161,"props":4330,"children":4331},{"style":184},[4332],{"type":48,"value":2831},{"type":42,"tag":161,"props":4334,"children":4335},{"class":163,"line":2654},[4336],{"type":42,"tag":161,"props":4337,"children":4338},{"emptyLinePlaceholder":2464},[4339],{"type":48,"value":2467},{"type":42,"tag":161,"props":4341,"children":4342},{"class":163,"line":2663},[4343],{"type":42,"tag":161,"props":4344,"children":4345},{"style":206},[4346],{"type":48,"value":4347},"# 7. Verify by re-fetching and comparing sha256 — the two hashes MUST match.\n",{"type":42,"tag":161,"props":4349,"children":4350},{"class":163,"line":2672},[4351],{"type":42,"tag":161,"props":4352,"children":4353},{"style":206},[4354],{"type":48,"value":4355},"#    Do not rely on the `updated` timestamp; it does not bump on script PUT.\n",{"type":42,"tag":161,"props":4357,"children":4359},{"class":163,"line":4358},27,[4360,4364,4368,4372,4376,4380],{"type":42,"tag":161,"props":4361,"children":4362},{"style":168},[4363],{"type":48,"value":62},{"type":42,"tag":161,"props":4365,"children":4366},{"style":173},[4367],{"type":48,"value":1927},{"type":42,"tag":161,"props":4369,"children":4370},{"style":173},[4371],{"type":48,"value":3865},{"type":42,"tag":161,"props":4373,"children":4374},{"style":195},[4375],{"type":48,"value":3870},{"type":42,"tag":161,"props":4377,"children":4378},{"style":173},[4379],{"type":48,"value":3875},{"type":42,"tag":161,"props":4381,"children":4382},{"style":195},[4383],{"type":48,"value":577},{"type":42,"tag":161,"props":4385,"children":4387},{"class":163,"line":4386},28,[4388,4392],{"type":42,"tag":161,"props":4389,"children":4390},{"style":184},[4391],{"type":48,"value":3887},{"type":42,"tag":161,"props":4393,"children":4394},{"style":173},[4395],{"type":48,"value":4396}," \u002Ftmp\u002Fscript_verify.js\n",{"type":42,"tag":161,"props":4398,"children":4400},{"class":163,"line":4399},29,[4401,4406,4411,4416,4420],{"type":42,"tag":161,"props":4402,"children":4403},{"style":168},[4404],{"type":48,"value":4405},"shasum",{"type":42,"tag":161,"props":4407,"children":4408},{"style":173},[4409],{"type":48,"value":4410}," -a",{"type":42,"tag":161,"props":4412,"children":4413},{"style":1548},[4414],{"type":48,"value":4415}," 256",{"type":42,"tag":161,"props":4417,"children":4418},{"style":173},[4419],{"type":48,"value":4138},{"type":42,"tag":161,"props":4421,"children":4422},{"style":173},[4423],{"type":48,"value":4396},{"type":42,"tag":51,"props":4425,"children":4426},{},[4427,4429,4435,4437,4443,4445,4450],{"type":48,"value":4428},"If the PUT returns 415, double-check that ",{"type":42,"tag":57,"props":4430,"children":4432},{"className":4431},[],[4433],{"type":48,"value":4434},"-H \"Content-Type: application\u002Foctet-stream\"",{"type":48,"value":4436}," made it through (some shell quoting mistakes\ncan drop it). Pass ",{"type":42,"tag":57,"props":4438,"children":4440},{"className":4439},[],[4441],{"type":48,"value":4442},"-vvv",{"type":48,"value":4444}," to ",{"type":42,"tag":57,"props":4446,"children":4448},{"className":4447},[],[4449],{"type":48,"value":128},{"type":48,"value":4451}," for the request\u002Fresponse trace\nwhen debugging.",{"type":42,"tag":132,"props":4453,"children":4454},{},[],{"type":42,"tag":136,"props":4456,"children":4458},{"id":4457},"_6-browser-screenshots",[4459],{"type":48,"value":4460},"6. Browser screenshots",{"type":42,"tag":51,"props":4462,"children":4463},{},[4464,4466,4471,4473,4479,4481,4486],{"type":48,"value":4465},"Browser-module runs write screenshot PNGs to per-run S3 storage —\nthat's the only artifact type the files API surfaces today. They're\nnot exposed via ",{"type":42,"tag":57,"props":4467,"children":4469},{"className":4468},[],[4470],{"type":48,"value":1075},{"type":48,"value":4472},"; retrieval goes through a separate\n",{"type":42,"tag":57,"props":4474,"children":4476},{"className":4475},[],[4477],{"type":48,"value":4478},"cloud-resources\u002Fv1\u002Ffiles\u002F",{"type":48,"value":4480}," plugin route in a two-step flow. Both\ncalls require the same ",{"type":42,"tag":57,"props":4482,"children":4484},{"className":4483},[],[4485],{"type":48,"value":86},{"type":48,"value":4487}," header used for log queries\n(§4) — gcx still handles auth, but the run ID must be supplied by\nhand or the endpoint rejects with HTTP 422.",{"type":42,"tag":150,"props":4489,"children":4491},{"className":152,"code":4490,"language":154,"meta":155,"style":155},"RUN_ID=\"\u003Crun_id>\"\n\n# 1. Index — JSON array of screenshot paths owned by this run. Empty\n#    array if the run took none (e.g. non-browser tests, or browser\n#    runs that didn't call page.screenshot()).\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Findex \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" -o json 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Ffiles_${RUN_ID}.json\n\n# Each entry looks like:\n#   \"7542817\u002Ffiles\u002Fscreenshots\u002Fscreenshots\u002Flogin-success.png\"\n# The doubled \"screenshots\u002Fscreenshots\u002F\" segment is real, not a typo —\n# pass the path back unchanged to step 2.\n\n# 2. Request pre-signed download URLs for the files you want. The\n#    request body must be JSON; Content-Type matters.\nFILES=$(jq -c '[.[] | {name: .}]' \u002Ftmp\u002Ffiles_${RUN_ID}.json)\nPAYLOAD=$(jq -nc --argjson files \"$FILES\" \\\n  '{service:\"aws_s3\", operation:\"download\", files:$files}')\n\ngcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Fgenerate-pre-signed-url \\\n  -X POST \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d \"$PAYLOAD\" -o json 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Fpresigned_${RUN_ID}.json\n\n# 3. Download each pre-signed URL directly — they're plain S3 GETs, no\n#    gcx and no auth header (the signature is in the URL). The URLs\n#    are valid for 24h (X-Amz-Expires=86400); re-run step 2 if they\n#    expire.\nmkdir -p \u002Ftmp\u002Frun_${RUN_ID}_files\njq -r '.urls[] | [.name, .pre_signed_url] | @tsv' \u002Ftmp\u002Fpresigned_${RUN_ID}.json |\n  while IFS=$'\\t' read -r NAME URL; do\n    curl -sS -o \"\u002Ftmp\u002Frun_${RUN_ID}_files\u002F$(basename \"$NAME\")\" \"$URL\"\n  done\n",[4492],{"type":42,"tag":57,"props":4493,"children":4494},{"__ignoreMap":155},[4495,4518,4525,4533,4541,4549,4569,4636,4643,4651,4659,4667,4675,4682,4690,4698,4757,4805,4826,4833,4853,4869,4896,4920,4981,4988,4996,5004,5012,5020,5055,5105,5167,5246],{"type":42,"tag":161,"props":4496,"children":4497},{"class":163,"line":164},[4498,4502,4506,4510,4514],{"type":42,"tag":161,"props":4499,"children":4500},{"style":195},[4501],{"type":48,"value":2812},{"type":42,"tag":161,"props":4503,"children":4504},{"style":184},[4505],{"type":48,"value":2817},{"type":42,"tag":161,"props":4507,"children":4508},{"style":184},[4509],{"type":48,"value":605},{"type":42,"tag":161,"props":4511,"children":4512},{"style":173},[4513],{"type":48,"value":2826},{"type":42,"tag":161,"props":4515,"children":4516},{"style":184},[4517],{"type":48,"value":2831},{"type":42,"tag":161,"props":4519,"children":4520},{"class":163,"line":212},[4521],{"type":42,"tag":161,"props":4522,"children":4523},{"emptyLinePlaceholder":2464},[4524],{"type":48,"value":2467},{"type":42,"tag":161,"props":4526,"children":4527},{"class":163,"line":612},[4528],{"type":42,"tag":161,"props":4529,"children":4530},{"style":206},[4531],{"type":48,"value":4532},"# 1. Index — JSON array of screenshot paths owned by this run. Empty\n",{"type":42,"tag":161,"props":4534,"children":4535},{"class":163,"line":642},[4536],{"type":42,"tag":161,"props":4537,"children":4538},{"style":206},[4539],{"type":48,"value":4540},"#    array if the run took none (e.g. non-browser tests, or browser\n",{"type":42,"tag":161,"props":4542,"children":4543},{"class":163,"line":2486},[4544],{"type":42,"tag":161,"props":4545,"children":4546},{"style":206},[4547],{"type":48,"value":4548},"#    runs that didn't call page.screenshot()).\n",{"type":42,"tag":161,"props":4550,"children":4551},{"class":163,"line":2495},[4552,4556,4560,4565],{"type":42,"tag":161,"props":4553,"children":4554},{"style":168},[4555],{"type":48,"value":62},{"type":42,"tag":161,"props":4557,"children":4558},{"style":173},[4559],{"type":48,"value":1927},{"type":42,"tag":161,"props":4561,"children":4562},{"style":173},[4563],{"type":48,"value":4564}," \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Findex",{"type":42,"tag":161,"props":4566,"children":4567},{"style":195},[4568],{"type":48,"value":577},{"type":42,"tag":161,"props":4570,"children":4571},{"class":163,"line":2503},[4572,4576,4580,4584,4588,4592,4597,4602,4606,4610,4614,4619,4623,4627,4631],{"type":42,"tag":161,"props":4573,"children":4574},{"style":173},[4575],{"type":48,"value":585},{"type":42,"tag":161,"props":4577,"children":4578},{"style":184},[4579],{"type":48,"value":590},{"type":42,"tag":161,"props":4581,"children":4582},{"style":173},[4583],{"type":48,"value":3249},{"type":42,"tag":161,"props":4585,"children":4586},{"style":195},[4587],{"type":48,"value":3095},{"type":42,"tag":161,"props":4589,"children":4590},{"style":184},[4591],{"type":48,"value":605},{"type":42,"tag":161,"props":4593,"children":4594},{"style":173},[4595],{"type":48,"value":4596}," -o",{"type":42,"tag":161,"props":4598,"children":4599},{"style":173},[4600],{"type":48,"value":4601}," json",{"type":42,"tag":161,"props":4603,"children":4604},{"style":184},[4605],{"type":48,"value":3262},{"type":42,"tag":161,"props":4607,"children":4608},{"style":173},[4609],{"type":48,"value":2910},{"type":42,"tag":161,"props":4611,"children":4612},{"style":184},[4613],{"type":48,"value":1937},{"type":42,"tag":161,"props":4615,"children":4616},{"style":173},[4617],{"type":48,"value":4618}," \u002Ftmp\u002Ffiles_",{"type":42,"tag":161,"props":4620,"children":4621},{"style":184},[4622],{"type":48,"value":3177},{"type":42,"tag":161,"props":4624,"children":4625},{"style":195},[4626],{"type":48,"value":2812},{"type":42,"tag":161,"props":4628,"children":4629},{"style":184},[4630],{"type":48,"value":3186},{"type":42,"tag":161,"props":4632,"children":4633},{"style":173},[4634],{"type":48,"value":4635},".json\n",{"type":42,"tag":161,"props":4637,"children":4638},{"class":163,"line":2512},[4639],{"type":42,"tag":161,"props":4640,"children":4641},{"emptyLinePlaceholder":2464},[4642],{"type":48,"value":2467},{"type":42,"tag":161,"props":4644,"children":4645},{"class":163,"line":2521},[4646],{"type":42,"tag":161,"props":4647,"children":4648},{"style":206},[4649],{"type":48,"value":4650},"# Each entry looks like:\n",{"type":42,"tag":161,"props":4652,"children":4653},{"class":163,"line":2530},[4654],{"type":42,"tag":161,"props":4655,"children":4656},{"style":206},[4657],{"type":48,"value":4658},"#   \"7542817\u002Ffiles\u002Fscreenshots\u002Fscreenshots\u002Flogin-success.png\"\n",{"type":42,"tag":161,"props":4660,"children":4661},{"class":163,"line":2539},[4662],{"type":42,"tag":161,"props":4663,"children":4664},{"style":206},[4665],{"type":48,"value":4666},"# The doubled \"screenshots\u002Fscreenshots\u002F\" segment is real, not a typo —\n",{"type":42,"tag":161,"props":4668,"children":4669},{"class":163,"line":2548},[4670],{"type":42,"tag":161,"props":4671,"children":4672},{"style":206},[4673],{"type":48,"value":4674},"# pass the path back unchanged to step 2.\n",{"type":42,"tag":161,"props":4676,"children":4677},{"class":163,"line":2556},[4678],{"type":42,"tag":161,"props":4679,"children":4680},{"emptyLinePlaceholder":2464},[4681],{"type":48,"value":2467},{"type":42,"tag":161,"props":4683,"children":4684},{"class":163,"line":2565},[4685],{"type":42,"tag":161,"props":4686,"children":4687},{"style":206},[4688],{"type":48,"value":4689},"# 2. Request pre-signed download URLs for the files you want. The\n",{"type":42,"tag":161,"props":4691,"children":4692},{"class":163,"line":2574},[4693],{"type":42,"tag":161,"props":4694,"children":4695},{"style":206},[4696],{"type":48,"value":4697},"#    request body must be JSON; Content-Type matters.\n",{"type":42,"tag":161,"props":4699,"children":4700},{"class":163,"line":30},[4701,4706,4710,4714,4719,4723,4728,4732,4736,4740,4744,4748,4753],{"type":42,"tag":161,"props":4702,"children":4703},{"style":195},[4704],{"type":48,"value":4705},"FILES",{"type":42,"tag":161,"props":4707,"children":4708},{"style":184},[4709],{"type":48,"value":557},{"type":42,"tag":161,"props":4711,"children":4712},{"style":168},[4713],{"type":48,"value":1421},{"type":42,"tag":161,"props":4715,"children":4716},{"style":173},[4717],{"type":48,"value":4718}," -c",{"type":42,"tag":161,"props":4720,"children":4721},{"style":184},[4722],{"type":48,"value":663},{"type":42,"tag":161,"props":4724,"children":4725},{"style":173},[4726],{"type":48,"value":4727},"[.[] | {name: .}]",{"type":42,"tag":161,"props":4729,"children":4730},{"style":184},[4731],{"type":48,"value":673},{"type":42,"tag":161,"props":4733,"children":4734},{"style":173},[4735],{"type":48,"value":4618},{"type":42,"tag":161,"props":4737,"children":4738},{"style":184},[4739],{"type":48,"value":3177},{"type":42,"tag":161,"props":4741,"children":4742},{"style":195},[4743],{"type":48,"value":2812},{"type":42,"tag":161,"props":4745,"children":4746},{"style":184},[4747],{"type":48,"value":3186},{"type":42,"tag":161,"props":4749,"children":4750},{"style":173},[4751],{"type":48,"value":4752},".json",{"type":42,"tag":161,"props":4754,"children":4755},{"style":184},[4756],{"type":48,"value":678},{"type":42,"tag":161,"props":4758,"children":4759},{"class":163,"line":2591},[4760,4765,4769,4773,4778,4783,4788,4792,4797,4801],{"type":42,"tag":161,"props":4761,"children":4762},{"style":195},[4763],{"type":48,"value":4764},"PAYLOAD",{"type":42,"tag":161,"props":4766,"children":4767},{"style":184},[4768],{"type":48,"value":557},{"type":42,"tag":161,"props":4770,"children":4771},{"style":168},[4772],{"type":48,"value":1421},{"type":42,"tag":161,"props":4774,"children":4775},{"style":173},[4776],{"type":48,"value":4777}," -nc",{"type":42,"tag":161,"props":4779,"children":4780},{"style":173},[4781],{"type":48,"value":4782}," --argjson",{"type":42,"tag":161,"props":4784,"children":4785},{"style":173},[4786],{"type":48,"value":4787}," files",{"type":42,"tag":161,"props":4789,"children":4790},{"style":184},[4791],{"type":48,"value":590},{"type":42,"tag":161,"props":4793,"children":4794},{"style":195},[4795],{"type":48,"value":4796},"$FILES",{"type":42,"tag":161,"props":4798,"children":4799},{"style":184},[4800],{"type":48,"value":605},{"type":42,"tag":161,"props":4802,"children":4803},{"style":195},[4804],{"type":48,"value":577},{"type":42,"tag":161,"props":4806,"children":4807},{"class":163,"line":2600},[4808,4813,4818,4822],{"type":42,"tag":161,"props":4809,"children":4810},{"style":184},[4811],{"type":48,"value":4812},"  '",{"type":42,"tag":161,"props":4814,"children":4815},{"style":173},[4816],{"type":48,"value":4817},"{service:\"aws_s3\", operation:\"download\", files:$files}",{"type":42,"tag":161,"props":4819,"children":4820},{"style":184},[4821],{"type":48,"value":673},{"type":42,"tag":161,"props":4823,"children":4824},{"style":184},[4825],{"type":48,"value":678},{"type":42,"tag":161,"props":4827,"children":4828},{"class":163,"line":2609},[4829],{"type":42,"tag":161,"props":4830,"children":4831},{"emptyLinePlaceholder":2464},[4832],{"type":48,"value":2467},{"type":42,"tag":161,"props":4834,"children":4835},{"class":163,"line":2618},[4836,4840,4844,4849],{"type":42,"tag":161,"props":4837,"children":4838},{"style":168},[4839],{"type":48,"value":62},{"type":42,"tag":161,"props":4841,"children":4842},{"style":173},[4843],{"type":48,"value":1927},{"type":42,"tag":161,"props":4845,"children":4846},{"style":173},[4847],{"type":48,"value":4848}," \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud-resources\u002Fv1\u002Ffiles\u002Fgenerate-pre-signed-url",{"type":42,"tag":161,"props":4850,"children":4851},{"style":195},[4852],{"type":48,"value":577},{"type":42,"tag":161,"props":4854,"children":4855},{"class":163,"line":2627},[4856,4860,4865],{"type":42,"tag":161,"props":4857,"children":4858},{"style":173},[4859],{"type":48,"value":4278},{"type":42,"tag":161,"props":4861,"children":4862},{"style":173},[4863],{"type":48,"value":4864}," POST",{"type":42,"tag":161,"props":4866,"children":4867},{"style":195},[4868],{"type":48,"value":577},{"type":42,"tag":161,"props":4870,"children":4871},{"class":163,"line":2636},[4872,4876,4880,4884,4888,4892],{"type":42,"tag":161,"props":4873,"children":4874},{"style":173},[4875],{"type":48,"value":585},{"type":42,"tag":161,"props":4877,"children":4878},{"style":184},[4879],{"type":48,"value":590},{"type":42,"tag":161,"props":4881,"children":4882},{"style":173},[4883],{"type":48,"value":3249},{"type":42,"tag":161,"props":4885,"children":4886},{"style":195},[4887],{"type":48,"value":3095},{"type":42,"tag":161,"props":4889,"children":4890},{"style":184},[4891],{"type":48,"value":605},{"type":42,"tag":161,"props":4893,"children":4894},{"style":195},[4895],{"type":48,"value":577},{"type":42,"tag":161,"props":4897,"children":4898},{"class":163,"line":2645},[4899,4903,4907,4912,4916],{"type":42,"tag":161,"props":4900,"children":4901},{"style":173},[4902],{"type":48,"value":585},{"type":42,"tag":161,"props":4904,"children":4905},{"style":184},[4906],{"type":48,"value":590},{"type":42,"tag":161,"props":4908,"children":4909},{"style":173},[4910],{"type":48,"value":4911},"Content-Type: application\u002Fjson",{"type":42,"tag":161,"props":4913,"children":4914},{"style":184},[4915],{"type":48,"value":605},{"type":42,"tag":161,"props":4917,"children":4918},{"style":195},[4919],{"type":48,"value":577},{"type":42,"tag":161,"props":4921,"children":4922},{"class":163,"line":2654},[4923,4927,4931,4936,4940,4944,4948,4952,4956,4960,4965,4969,4973,4977],{"type":42,"tag":161,"props":4924,"children":4925},{"style":173},[4926],{"type":48,"value":4319},{"type":42,"tag":161,"props":4928,"children":4929},{"style":184},[4930],{"type":48,"value":590},{"type":42,"tag":161,"props":4932,"children":4933},{"style":195},[4934],{"type":48,"value":4935},"$PAYLOAD",{"type":42,"tag":161,"props":4937,"children":4938},{"style":184},[4939],{"type":48,"value":605},{"type":42,"tag":161,"props":4941,"children":4942},{"style":173},[4943],{"type":48,"value":4596},{"type":42,"tag":161,"props":4945,"children":4946},{"style":173},[4947],{"type":48,"value":4601},{"type":42,"tag":161,"props":4949,"children":4950},{"style":184},[4951],{"type":48,"value":3262},{"type":42,"tag":161,"props":4953,"children":4954},{"style":173},[4955],{"type":48,"value":2910},{"type":42,"tag":161,"props":4957,"children":4958},{"style":184},[4959],{"type":48,"value":1937},{"type":42,"tag":161,"props":4961,"children":4962},{"style":173},[4963],{"type":48,"value":4964}," \u002Ftmp\u002Fpresigned_",{"type":42,"tag":161,"props":4966,"children":4967},{"style":184},[4968],{"type":48,"value":3177},{"type":42,"tag":161,"props":4970,"children":4971},{"style":195},[4972],{"type":48,"value":2812},{"type":42,"tag":161,"props":4974,"children":4975},{"style":184},[4976],{"type":48,"value":3186},{"type":42,"tag":161,"props":4978,"children":4979},{"style":173},[4980],{"type":48,"value":4635},{"type":42,"tag":161,"props":4982,"children":4983},{"class":163,"line":2663},[4984],{"type":42,"tag":161,"props":4985,"children":4986},{"emptyLinePlaceholder":2464},[4987],{"type":48,"value":2467},{"type":42,"tag":161,"props":4989,"children":4990},{"class":163,"line":2672},[4991],{"type":42,"tag":161,"props":4992,"children":4993},{"style":206},[4994],{"type":48,"value":4995},"# 3. Download each pre-signed URL directly — they're plain S3 GETs, no\n",{"type":42,"tag":161,"props":4997,"children":4998},{"class":163,"line":4358},[4999],{"type":42,"tag":161,"props":5000,"children":5001},{"style":206},[5002],{"type":48,"value":5003},"#    gcx and no auth header (the signature is in the URL). The URLs\n",{"type":42,"tag":161,"props":5005,"children":5006},{"class":163,"line":4386},[5007],{"type":42,"tag":161,"props":5008,"children":5009},{"style":206},[5010],{"type":48,"value":5011},"#    are valid for 24h (X-Amz-Expires=86400); re-run step 2 if they\n",{"type":42,"tag":161,"props":5013,"children":5014},{"class":163,"line":4399},[5015],{"type":42,"tag":161,"props":5016,"children":5017},{"style":206},[5018],{"type":48,"value":5019},"#    expire.\n",{"type":42,"tag":161,"props":5021,"children":5023},{"class":163,"line":5022},30,[5024,5029,5034,5038,5042,5046,5050],{"type":42,"tag":161,"props":5025,"children":5026},{"style":168},[5027],{"type":48,"value":5028},"mkdir",{"type":42,"tag":161,"props":5030,"children":5031},{"style":173},[5032],{"type":48,"value":5033}," -p",{"type":42,"tag":161,"props":5035,"children":5036},{"style":173},[5037],{"type":48,"value":3275},{"type":42,"tag":161,"props":5039,"children":5040},{"style":184},[5041],{"type":48,"value":3177},{"type":42,"tag":161,"props":5043,"children":5044},{"style":195},[5045],{"type":48,"value":2812},{"type":42,"tag":161,"props":5047,"children":5048},{"style":184},[5049],{"type":48,"value":3186},{"type":42,"tag":161,"props":5051,"children":5052},{"style":173},[5053],{"type":48,"value":5054},"_files\n",{"type":42,"tag":161,"props":5056,"children":5058},{"class":163,"line":5057},31,[5059,5063,5067,5071,5076,5080,5084,5088,5092,5096,5100],{"type":42,"tag":161,"props":5060,"children":5061},{"style":168},[5062],{"type":48,"value":1421},{"type":42,"tag":161,"props":5064,"children":5065},{"style":173},[5066],{"type":48,"value":658},{"type":42,"tag":161,"props":5068,"children":5069},{"style":184},[5070],{"type":48,"value":663},{"type":42,"tag":161,"props":5072,"children":5073},{"style":173},[5074],{"type":48,"value":5075},".urls[] | [.name, .pre_signed_url] | @tsv",{"type":42,"tag":161,"props":5077,"children":5078},{"style":184},[5079],{"type":48,"value":673},{"type":42,"tag":161,"props":5081,"children":5082},{"style":173},[5083],{"type":48,"value":4964},{"type":42,"tag":161,"props":5085,"children":5086},{"style":184},[5087],{"type":48,"value":3177},{"type":42,"tag":161,"props":5089,"children":5090},{"style":195},[5091],{"type":48,"value":2812},{"type":42,"tag":161,"props":5093,"children":5094},{"style":184},[5095],{"type":48,"value":3186},{"type":42,"tag":161,"props":5097,"children":5098},{"style":173},[5099],{"type":48,"value":4752},{"type":42,"tag":161,"props":5101,"children":5102},{"style":184},[5103],{"type":48,"value":5104}," |\n",{"type":42,"tag":161,"props":5106,"children":5108},{"class":163,"line":5107},32,[5109,5115,5120,5124,5129,5134,5138,5143,5147,5152,5157,5162],{"type":42,"tag":161,"props":5110,"children":5112},{"style":5111},"--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#89DDFF;--shiki-default-font-style:italic;--shiki-dark:#89DDFF;--shiki-dark-font-style:italic",[5113],{"type":48,"value":5114},"  while",{"type":42,"tag":161,"props":5116,"children":5117},{"style":173},[5118],{"type":48,"value":5119}," IFS",{"type":42,"tag":161,"props":5121,"children":5122},{"style":184},[5123],{"type":48,"value":2817},{"type":42,"tag":161,"props":5125,"children":5126},{"style":184},[5127],{"type":48,"value":5128},"$'",{"type":42,"tag":161,"props":5130,"children":5131},{"style":195},[5132],{"type":48,"value":5133},"\\t",{"type":42,"tag":161,"props":5135,"children":5136},{"style":184},[5137],{"type":48,"value":673},{"type":42,"tag":161,"props":5139,"children":5140},{"style":173},[5141],{"type":48,"value":5142}," read",{"type":42,"tag":161,"props":5144,"children":5145},{"style":173},[5146],{"type":48,"value":658},{"type":42,"tag":161,"props":5148,"children":5149},{"style":173},[5150],{"type":48,"value":5151}," NAME",{"type":42,"tag":161,"props":5153,"children":5154},{"style":173},[5155],{"type":48,"value":5156}," URL",{"type":42,"tag":161,"props":5158,"children":5159},{"style":184},[5160],{"type":48,"value":5161},";",{"type":42,"tag":161,"props":5163,"children":5164},{"style":5111},[5165],{"type":48,"value":5166}," do\n",{"type":42,"tag":161,"props":5168,"children":5170},{"class":163,"line":5169},33,[5171,5176,5180,5184,5188,5193,5197,5201,5205,5210,5214,5219,5223,5228,5233,5237,5242],{"type":42,"tag":161,"props":5172,"children":5173},{"style":168},[5174],{"type":48,"value":5175},"    curl",{"type":42,"tag":161,"props":5177,"children":5178},{"style":173},[5179],{"type":48,"value":567},{"type":42,"tag":161,"props":5181,"children":5182},{"style":173},[5183],{"type":48,"value":4596},{"type":42,"tag":161,"props":5185,"children":5186},{"style":184},[5187],{"type":48,"value":590},{"type":42,"tag":161,"props":5189,"children":5190},{"style":173},[5191],{"type":48,"value":5192},"\u002Ftmp\u002Frun_",{"type":42,"tag":161,"props":5194,"children":5195},{"style":184},[5196],{"type":48,"value":3177},{"type":42,"tag":161,"props":5198,"children":5199},{"style":195},[5200],{"type":48,"value":2812},{"type":42,"tag":161,"props":5202,"children":5203},{"style":184},[5204],{"type":48,"value":3186},{"type":42,"tag":161,"props":5206,"children":5207},{"style":173},[5208],{"type":48,"value":5209},"_files\u002F",{"type":42,"tag":161,"props":5211,"children":5212},{"style":184},[5213],{"type":48,"value":4072},{"type":42,"tag":161,"props":5215,"children":5216},{"style":168},[5217],{"type":48,"value":5218},"basename",{"type":42,"tag":161,"props":5220,"children":5221},{"style":184},[5222],{"type":48,"value":590},{"type":42,"tag":161,"props":5224,"children":5225},{"style":195},[5226],{"type":48,"value":5227},"$NAME",{"type":42,"tag":161,"props":5229,"children":5230},{"style":184},[5231],{"type":48,"value":5232},"\")\"",{"type":42,"tag":161,"props":5234,"children":5235},{"style":184},[5236],{"type":48,"value":590},{"type":42,"tag":161,"props":5238,"children":5239},{"style":195},[5240],{"type":48,"value":5241},"$URL",{"type":42,"tag":161,"props":5243,"children":5244},{"style":184},[5245],{"type":48,"value":2831},{"type":42,"tag":161,"props":5247,"children":5249},{"class":163,"line":5248},34,[5250],{"type":42,"tag":161,"props":5251,"children":5252},{"style":5111},[5253],{"type":48,"value":5254},"  done\n",{"type":42,"tag":143,"props":5256,"children":5258},{"id":5257},"notes-worth-knowing",[5259],{"type":48,"value":5260},"Notes worth knowing",{"type":42,"tag":66,"props":5262,"children":5263},{},[5264,5303,5320],{"type":42,"tag":70,"props":5265,"children":5266},{},[5267,5272,5273,5279,5281,5285,5287,5293,5295,5301],{"type":42,"tag":74,"props":5268,"children":5269},{},[5270],{"type":48,"value":5271},"Index before signing.",{"type":48,"value":1775},{"type":42,"tag":57,"props":5274,"children":5276},{"className":5275},[],[5277],{"type":48,"value":5278},"generate-pre-signed-url",{"type":48,"value":5280}," does ",{"type":42,"tag":274,"props":5282,"children":5283},{},[5284],{"type":48,"value":3712},{"type":48,"value":5286},"\nvalidate that the file exists — it will happily mint a URL for any\nkey, and the 404 only surfaces when you try to download (S3 returns\n",{"type":42,"tag":57,"props":5288,"children":5290},{"className":5289},[],[5291],{"type":48,"value":5292},"\u003CError>\u003CCode>NoSuchKey\u003C\u002FCode>...",{"type":48,"value":5294},"). Always derive the file list\nfrom ",{"type":42,"tag":57,"props":5296,"children":5298},{"className":5297},[],[5299],{"type":48,"value":5300},"files\u002Findex",{"type":48,"value":5302},", not from a guess at the path shape.",{"type":42,"tag":70,"props":5304,"children":5305},{},[5306,5311,5312,5318],{"type":42,"tag":74,"props":5307,"children":5308},{},[5309],{"type":48,"value":5310},"Batch the sign request.",{"type":48,"value":1775},{"type":42,"tag":57,"props":5313,"children":5315},{"className":5314},[],[5316],{"type":48,"value":5317},"files",{"type":48,"value":5319}," is an array, so request all the\nURLs you need in one POST rather than one call per file — same\n24h expiry covers the whole batch.",{"type":42,"tag":70,"props":5321,"children":5322},{},[5323,5328,5330,5336,5338,5344],{"type":42,"tag":74,"props":5324,"children":5325},{},[5326],{"type":48,"value":5327},"Browser tests vs. protocol tests.",{"type":48,"value":5329}," Only runs that called\n",{"type":42,"tag":57,"props":5331,"children":5333},{"className":5332},[],[5334],{"type":48,"value":5335},"page.screenshot()",{"type":48,"value":5337}," have entries in the index; a pure protocol\u002FHTTP\nrun will return ",{"type":42,"tag":57,"props":5339,"children":5341},{"className":5340},[],[5342],{"type":48,"value":5343},"[]",{"type":48,"value":5345},". Don't assume the index is non-empty.",{"type":42,"tag":132,"props":5347,"children":5348},{},[],{"type":42,"tag":136,"props":5350,"children":5352},{"id":5351},"_7-browser-traces-tempo-via-gcx-api",[5353,5355,5360],{"type":48,"value":5354},"7. Browser traces (Tempo via ",{"type":42,"tag":57,"props":5356,"children":5358},{"className":5357},[],[5359],{"type":48,"value":128},{"type":48,"value":2777},{"type":42,"tag":51,"props":5362,"children":5363},{},[5364,5366,5371,5373,5378,5380,5386],{"type":48,"value":5365},"Browser-module runs emit OTel spans for every iteration, navigation,\nlocator click, screenshot, web-vital observation, etc. The plugin\nproxies a Tempo backend under ",{"type":42,"tag":57,"props":5367,"children":5369},{"className":5368},[],[5370],{"type":48,"value":2788},{"type":48,"value":5372},"\n(same prefix as Loki — see §4), and the same ",{"type":42,"tag":57,"props":5374,"children":5376},{"className":5375},[],[5377],{"type":48,"value":86},{"type":48,"value":5379}," header\nis required on every call. Without it, both search and fetch return\nHTTP 401 ",{"type":42,"tag":57,"props":5381,"children":5383},{"className":5382},[],[5384],{"type":48,"value":5385},"\"Test run ID missing\"",{"type":48,"value":288},{"type":42,"tag":51,"props":5388,"children":5389},{},[5390,5392,5397],{"type":48,"value":5391},"Retrieval is a two-step flow: TraceQL search → fetch full trace by\nID. The full trace is large (≈100 KB on disk for a 120-span iteration\nbecause ",{"type":42,"tag":57,"props":5393,"children":5395},{"className":5394},[],[5396],{"type":48,"value":1686},{"type":48,"value":5398}," pretty-prints; ~50 KB compact), so the\njoin+summarise step is what keeps agent context lean.",{"type":42,"tag":150,"props":5400,"children":5402},{"className":152,"code":5401,"language":154,"meta":155,"style":155},"RUN_ID=\"\u003Crun_id>\"\n\n# 1. Find the run's start\u002Fend window and pick the scenario name.\n#    Same caveat as §4: strip the sub-second fraction before\n#    fromdateiso8601, and fall back to \"now\" if the run is still\n#    running. Add a small buffer because spans can land slightly\n#    after the run object reports `ended`.\nRUN=$(gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F$RUN_ID 2>\u002Fdev\u002Fnull)\nSTART=$(echo \"$RUN\" | jq -r '.created | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601')\nEND=$(  echo \"$RUN\" | jq -r 'if .ended then (.ended | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601) else (now|floor) end')\nSTART=$((START - 60))\nEND=$((END + 60))\n\nSCENARIO=\"ui\"  # whatever your scenario is named; check run.ui.exec \u002F k6 script\n\n# 2. Search for iteration root spans. TraceQL goes in `q`; URL-encode\n#    it. `start`\u002F`end` must be unix seconds — RFC3339 returns\n#    HTTP 400 `invalid start: strconv.ParseUint`. limit=500 caps the\n#    result, enough to cover several thousand iterations.\nQ=$(printf '{ name = \"iteration\" && span.test.iteration.number >= 0 && span.test.vu >= 0 && span.test.scenario = \"%s\" }' \"$SCENARIO\")\nQE=$(printf '%s' \"$Q\" | jq -sRr @uri)\n\ngcx api \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Fsearch?start=${START}&end=${END}&q=${QE}&limit=500\" \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" -o json 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Ftraces_${RUN_ID}.json\n\n# Each entry has: traceID (32-char hex), rootServiceName (\"k6\"),\n# rootTraceName (\"iteration\"), durationMs, startTimeUnixNano, and a\n# spanSet preview of the iteration root span's attributes\n# (test.iteration.number, test.vu, test.scenario).\n\n# 3. Fetch a full trace. The response is OTLP-shaped:\n#    { \"batches\": [ { \"resource\": {...}, \"scopeSpans\": [ { \"spans\": [...] } ] } ] }\nTRACE_ID=$(jq -r '.traces[0].traceID' \u002Ftmp\u002Ftraces_${RUN_ID}.json)\ngcx api \"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Ftraces\u002F$TRACE_ID\" \\\n  -H \"X-K6TestRun-Id: $RUN_ID\" -o json 2>\u002Fdev\u002Fnull > \u002Ftmp\u002Ftrace_${TRACE_ID}.json\n",[5403],{"type":42,"tag":57,"props":5404,"children":5405},{"__ignoreMap":155},[5406,5429,5436,5444,5452,5460,5468,5476,5515,5570,5627,5658,5686,5693,5723,5730,5738,5746,5754,5762,5808,5870,5877,5955,6019,6026,6034,6042,6050,6058,6065,6073,6081,6138,6171],{"type":42,"tag":161,"props":5407,"children":5408},{"class":163,"line":164},[5409,5413,5417,5421,5425],{"type":42,"tag":161,"props":5410,"children":5411},{"style":195},[5412],{"type":48,"value":2812},{"type":42,"tag":161,"props":5414,"children":5415},{"style":184},[5416],{"type":48,"value":2817},{"type":42,"tag":161,"props":5418,"children":5419},{"style":184},[5420],{"type":48,"value":605},{"type":42,"tag":161,"props":5422,"children":5423},{"style":173},[5424],{"type":48,"value":2826},{"type":42,"tag":161,"props":5426,"children":5427},{"style":184},[5428],{"type":48,"value":2831},{"type":42,"tag":161,"props":5430,"children":5431},{"class":163,"line":212},[5432],{"type":42,"tag":161,"props":5433,"children":5434},{"emptyLinePlaceholder":2464},[5435],{"type":48,"value":2467},{"type":42,"tag":161,"props":5437,"children":5438},{"class":163,"line":612},[5439],{"type":42,"tag":161,"props":5440,"children":5441},{"style":206},[5442],{"type":48,"value":5443},"# 1. Find the run's start\u002Fend window and pick the scenario name.\n",{"type":42,"tag":161,"props":5445,"children":5446},{"class":163,"line":642},[5447],{"type":42,"tag":161,"props":5448,"children":5449},{"style":206},[5450],{"type":48,"value":5451},"#    Same caveat as §4: strip the sub-second fraction before\n",{"type":42,"tag":161,"props":5453,"children":5454},{"class":163,"line":2486},[5455],{"type":42,"tag":161,"props":5456,"children":5457},{"style":206},[5458],{"type":48,"value":5459},"#    fromdateiso8601, and fall back to \"now\" if the run is still\n",{"type":42,"tag":161,"props":5461,"children":5462},{"class":163,"line":2495},[5463],{"type":42,"tag":161,"props":5464,"children":5465},{"style":206},[5466],{"type":48,"value":5467},"#    running. Add a small buffer because spans can land slightly\n",{"type":42,"tag":161,"props":5469,"children":5470},{"class":163,"line":2503},[5471],{"type":42,"tag":161,"props":5472,"children":5473},{"style":206},[5474],{"type":48,"value":5475},"#    after the run object reports `ended`.\n",{"type":42,"tag":161,"props":5477,"children":5478},{"class":163,"line":2512},[5479,5483,5487,5491,5495,5499,5503,5507,5511],{"type":42,"tag":161,"props":5480,"children":5481},{"style":195},[5482],{"type":48,"value":2878},{"type":42,"tag":161,"props":5484,"children":5485},{"style":184},[5486],{"type":48,"value":557},{"type":42,"tag":161,"props":5488,"children":5489},{"style":168},[5490],{"type":48,"value":62},{"type":42,"tag":161,"props":5492,"children":5493},{"style":173},[5494],{"type":48,"value":1927},{"type":42,"tag":161,"props":5496,"children":5497},{"style":173},[5498],{"type":48,"value":2895},{"type":42,"tag":161,"props":5500,"children":5501},{"style":195},[5502],{"type":48,"value":2900},{"type":42,"tag":161,"props":5504,"children":5505},{"style":184},[5506],{"type":48,"value":2905},{"type":42,"tag":161,"props":5508,"children":5509},{"style":173},[5510],{"type":48,"value":2910},{"type":42,"tag":161,"props":5512,"children":5513},{"style":184},[5514],{"type":48,"value":678},{"type":42,"tag":161,"props":5516,"children":5517},{"class":163,"line":2521},[5518,5522,5526,5530,5534,5538,5542,5546,5550,5554,5558,5562,5566],{"type":42,"tag":161,"props":5519,"children":5520},{"style":195},[5521],{"type":48,"value":2938},{"type":42,"tag":161,"props":5523,"children":5524},{"style":184},[5525],{"type":48,"value":557},{"type":42,"tag":161,"props":5527,"children":5528},{"style":2945},[5529],{"type":48,"value":2948},{"type":42,"tag":161,"props":5531,"children":5532},{"style":184},[5533],{"type":48,"value":590},{"type":42,"tag":161,"props":5535,"children":5536},{"style":195},[5537],{"type":48,"value":2957},{"type":42,"tag":161,"props":5539,"children":5540},{"style":184},[5541],{"type":48,"value":605},{"type":42,"tag":161,"props":5543,"children":5544},{"style":184},[5545],{"type":48,"value":2966},{"type":42,"tag":161,"props":5547,"children":5548},{"style":168},[5549],{"type":48,"value":653},{"type":42,"tag":161,"props":5551,"children":5552},{"style":173},[5553],{"type":48,"value":658},{"type":42,"tag":161,"props":5555,"children":5556},{"style":184},[5557],{"type":48,"value":663},{"type":42,"tag":161,"props":5559,"children":5560},{"style":173},[5561],{"type":48,"value":2983},{"type":42,"tag":161,"props":5563,"children":5564},{"style":184},[5565],{"type":48,"value":673},{"type":42,"tag":161,"props":5567,"children":5568},{"style":184},[5569],{"type":48,"value":678},{"type":42,"tag":161,"props":5571,"children":5572},{"class":163,"line":2530},[5573,5577,5581,5586,5590,5594,5598,5602,5606,5610,5614,5619,5623],{"type":42,"tag":161,"props":5574,"children":5575},{"style":195},[5576],{"type":48,"value":2999},{"type":42,"tag":161,"props":5578,"children":5579},{"style":184},[5580],{"type":48,"value":557},{"type":42,"tag":161,"props":5582,"children":5583},{"style":2945},[5584],{"type":48,"value":5585},"  echo",{"type":42,"tag":161,"props":5587,"children":5588},{"style":184},[5589],{"type":48,"value":590},{"type":42,"tag":161,"props":5591,"children":5592},{"style":195},[5593],{"type":48,"value":2957},{"type":42,"tag":161,"props":5595,"children":5596},{"style":184},[5597],{"type":48,"value":605},{"type":42,"tag":161,"props":5599,"children":5600},{"style":184},[5601],{"type":48,"value":2966},{"type":42,"tag":161,"props":5603,"children":5604},{"style":168},[5605],{"type":48,"value":653},{"type":42,"tag":161,"props":5607,"children":5608},{"style":173},[5609],{"type":48,"value":658},{"type":42,"tag":161,"props":5611,"children":5612},{"style":184},[5613],{"type":48,"value":663},{"type":42,"tag":161,"props":5615,"children":5616},{"style":173},[5617],{"type":48,"value":5618},"if .ended then (.ended | sub(\"\\\\.[0-9]+Z$\"; \"Z\") | fromdateiso8601) else (now|floor) end",{"type":42,"tag":161,"props":5620,"children":5621},{"style":184},[5622],{"type":48,"value":673},{"type":42,"tag":161,"props":5624,"children":5625},{"style":184},[5626],{"type":48,"value":678},{"type":42,"tag":161,"props":5628,"children":5629},{"class":163,"line":2539},[5630,5634,5639,5643,5648,5653],{"type":42,"tag":161,"props":5631,"children":5632},{"style":195},[5633],{"type":48,"value":2938},{"type":42,"tag":161,"props":5635,"children":5636},{"style":184},[5637],{"type":48,"value":5638},"=$((",{"type":42,"tag":161,"props":5640,"children":5641},{"style":168},[5642],{"type":48,"value":2938},{"type":42,"tag":161,"props":5644,"children":5645},{"style":173},[5646],{"type":48,"value":5647}," -",{"type":42,"tag":161,"props":5649,"children":5650},{"style":1548},[5651],{"type":48,"value":5652}," 60",{"type":42,"tag":161,"props":5654,"children":5655},{"style":184},[5656],{"type":48,"value":5657},"))\n",{"type":42,"tag":161,"props":5659,"children":5660},{"class":163,"line":2548},[5661,5665,5669,5673,5678,5682],{"type":42,"tag":161,"props":5662,"children":5663},{"style":195},[5664],{"type":48,"value":2999},{"type":42,"tag":161,"props":5666,"children":5667},{"style":184},[5668],{"type":48,"value":5638},{"type":42,"tag":161,"props":5670,"children":5671},{"style":168},[5672],{"type":48,"value":2999},{"type":42,"tag":161,"props":5674,"children":5675},{"style":173},[5676],{"type":48,"value":5677}," +",{"type":42,"tag":161,"props":5679,"children":5680},{"style":1548},[5681],{"type":48,"value":5652},{"type":42,"tag":161,"props":5683,"children":5684},{"style":184},[5685],{"type":48,"value":5657},{"type":42,"tag":161,"props":5687,"children":5688},{"class":163,"line":2556},[5689],{"type":42,"tag":161,"props":5690,"children":5691},{"emptyLinePlaceholder":2464},[5692],{"type":48,"value":2467},{"type":42,"tag":161,"props":5694,"children":5695},{"class":163,"line":2565},[5696,5701,5705,5709,5714,5718],{"type":42,"tag":161,"props":5697,"children":5698},{"style":195},[5699],{"type":48,"value":5700},"SCENARIO",{"type":42,"tag":161,"props":5702,"children":5703},{"style":184},[5704],{"type":48,"value":2817},{"type":42,"tag":161,"props":5706,"children":5707},{"style":184},[5708],{"type":48,"value":605},{"type":42,"tag":161,"props":5710,"children":5711},{"style":173},[5712],{"type":48,"value":5713},"ui",{"type":42,"tag":161,"props":5715,"children":5716},{"style":184},[5717],{"type":48,"value":605},{"type":42,"tag":161,"props":5719,"children":5720},{"style":206},[5721],{"type":48,"value":5722},"  # whatever your scenario is named; check run.ui.exec \u002F k6 script\n",{"type":42,"tag":161,"props":5724,"children":5725},{"class":163,"line":2574},[5726],{"type":42,"tag":161,"props":5727,"children":5728},{"emptyLinePlaceholder":2464},[5729],{"type":48,"value":2467},{"type":42,"tag":161,"props":5731,"children":5732},{"class":163,"line":30},[5733],{"type":42,"tag":161,"props":5734,"children":5735},{"style":206},[5736],{"type":48,"value":5737},"# 2. Search for iteration root spans. TraceQL goes in `q`; URL-encode\n",{"type":42,"tag":161,"props":5739,"children":5740},{"class":163,"line":2591},[5741],{"type":42,"tag":161,"props":5742,"children":5743},{"style":206},[5744],{"type":48,"value":5745},"#    it. `start`\u002F`end` must be unix seconds — RFC3339 returns\n",{"type":42,"tag":161,"props":5747,"children":5748},{"class":163,"line":2600},[5749],{"type":42,"tag":161,"props":5750,"children":5751},{"style":206},[5752],{"type":48,"value":5753},"#    HTTP 400 `invalid start: strconv.ParseUint`. limit=500 caps the\n",{"type":42,"tag":161,"props":5755,"children":5756},{"class":163,"line":2609},[5757],{"type":42,"tag":161,"props":5758,"children":5759},{"style":206},[5760],{"type":48,"value":5761},"#    result, enough to cover several thousand iterations.\n",{"type":42,"tag":161,"props":5763,"children":5764},{"class":163,"line":2618},[5765,5770,5774,5778,5782,5787,5791,5795,5800,5804],{"type":42,"tag":161,"props":5766,"children":5767},{"style":195},[5768],{"type":48,"value":5769},"Q",{"type":42,"tag":161,"props":5771,"children":5772},{"style":184},[5773],{"type":48,"value":557},{"type":42,"tag":161,"props":5775,"children":5776},{"style":2945},[5777],{"type":48,"value":3073},{"type":42,"tag":161,"props":5779,"children":5780},{"style":184},[5781],{"type":48,"value":663},{"type":42,"tag":161,"props":5783,"children":5784},{"style":173},[5785],{"type":48,"value":5786},"{ name = \"iteration\" && span.test.iteration.number >= 0 && span.test.vu >= 0 && span.test.scenario = \"%s\" }",{"type":42,"tag":161,"props":5788,"children":5789},{"style":184},[5790],{"type":48,"value":673},{"type":42,"tag":161,"props":5792,"children":5793},{"style":184},[5794],{"type":48,"value":590},{"type":42,"tag":161,"props":5796,"children":5797},{"style":195},[5798],{"type":48,"value":5799},"$SCENARIO",{"type":42,"tag":161,"props":5801,"children":5802},{"style":184},[5803],{"type":48,"value":605},{"type":42,"tag":161,"props":5805,"children":5806},{"style":184},[5807],{"type":48,"value":678},{"type":42,"tag":161,"props":5809,"children":5810},{"class":163,"line":2627},[5811,5816,5820,5824,5828,5833,5837,5841,5846,5850,5854,5858,5862,5866],{"type":42,"tag":161,"props":5812,"children":5813},{"style":195},[5814],{"type":48,"value":5815},"QE",{"type":42,"tag":161,"props":5817,"children":5818},{"style":184},[5819],{"type":48,"value":557},{"type":42,"tag":161,"props":5821,"children":5822},{"style":2945},[5823],{"type":48,"value":3073},{"type":42,"tag":161,"props":5825,"children":5826},{"style":184},[5827],{"type":48,"value":663},{"type":42,"tag":161,"props":5829,"children":5830},{"style":173},[5831],{"type":48,"value":5832},"%s",{"type":42,"tag":161,"props":5834,"children":5835},{"style":184},[5836],{"type":48,"value":673},{"type":42,"tag":161,"props":5838,"children":5839},{"style":184},[5840],{"type":48,"value":590},{"type":42,"tag":161,"props":5842,"children":5843},{"style":195},[5844],{"type":48,"value":5845},"$Q",{"type":42,"tag":161,"props":5847,"children":5848},{"style":184},[5849],{"type":48,"value":605},{"type":42,"tag":161,"props":5851,"children":5852},{"style":184},[5853],{"type":48,"value":2966},{"type":42,"tag":161,"props":5855,"children":5856},{"style":168},[5857],{"type":48,"value":653},{"type":42,"tag":161,"props":5859,"children":5860},{"style":173},[5861],{"type":48,"value":3112},{"type":42,"tag":161,"props":5863,"children":5864},{"style":173},[5865],{"type":48,"value":3117},{"type":42,"tag":161,"props":5867,"children":5868},{"style":184},[5869],{"type":48,"value":678},{"type":42,"tag":161,"props":5871,"children":5872},{"class":163,"line":2636},[5873],{"type":42,"tag":161,"props":5874,"children":5875},{"emptyLinePlaceholder":2464},[5876],{"type":48,"value":2467},{"type":42,"tag":161,"props":5878,"children":5879},{"class":163,"line":2645},[5880,5884,5888,5892,5897,5901,5905,5909,5913,5917,5921,5925,5930,5934,5938,5942,5947,5951],{"type":42,"tag":161,"props":5881,"children":5882},{"style":168},[5883],{"type":48,"value":62},{"type":42,"tag":161,"props":5885,"children":5886},{"style":173},[5887],{"type":48,"value":1927},{"type":42,"tag":161,"props":5889,"children":5890},{"style":184},[5891],{"type":48,"value":590},{"type":42,"tag":161,"props":5893,"children":5894},{"style":173},[5895],{"type":48,"value":5896},"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Fsearch?start=",{"type":42,"tag":161,"props":5898,"children":5899},{"style":184},[5900],{"type":48,"value":3177},{"type":42,"tag":161,"props":5902,"children":5903},{"style":195},[5904],{"type":48,"value":2938},{"type":42,"tag":161,"props":5906,"children":5907},{"style":184},[5908],{"type":48,"value":3186},{"type":42,"tag":161,"props":5910,"children":5911},{"style":173},[5912],{"type":48,"value":3208},{"type":42,"tag":161,"props":5914,"children":5915},{"style":184},[5916],{"type":48,"value":3177},{"type":42,"tag":161,"props":5918,"children":5919},{"style":195},[5920],{"type":48,"value":2999},{"type":42,"tag":161,"props":5922,"children":5923},{"style":184},[5924],{"type":48,"value":3186},{"type":42,"tag":161,"props":5926,"children":5927},{"style":173},[5928],{"type":48,"value":5929},"&q=",{"type":42,"tag":161,"props":5931,"children":5932},{"style":184},[5933],{"type":48,"value":3177},{"type":42,"tag":161,"props":5935,"children":5936},{"style":195},[5937],{"type":48,"value":5815},{"type":42,"tag":161,"props":5939,"children":5940},{"style":184},[5941],{"type":48,"value":3186},{"type":42,"tag":161,"props":5943,"children":5944},{"style":173},[5945],{"type":48,"value":5946},"&limit=500",{"type":42,"tag":161,"props":5948,"children":5949},{"style":184},[5950],{"type":48,"value":605},{"type":42,"tag":161,"props":5952,"children":5953},{"style":195},[5954],{"type":48,"value":577},{"type":42,"tag":161,"props":5956,"children":5957},{"class":163,"line":2654},[5958,5962,5966,5970,5974,5978,5982,5986,5990,5994,5998,6003,6007,6011,6015],{"type":42,"tag":161,"props":5959,"children":5960},{"style":173},[5961],{"type":48,"value":585},{"type":42,"tag":161,"props":5963,"children":5964},{"style":184},[5965],{"type":48,"value":590},{"type":42,"tag":161,"props":5967,"children":5968},{"style":173},[5969],{"type":48,"value":3249},{"type":42,"tag":161,"props":5971,"children":5972},{"style":195},[5973],{"type":48,"value":3095},{"type":42,"tag":161,"props":5975,"children":5976},{"style":184},[5977],{"type":48,"value":605},{"type":42,"tag":161,"props":5979,"children":5980},{"style":173},[5981],{"type":48,"value":4596},{"type":42,"tag":161,"props":5983,"children":5984},{"style":173},[5985],{"type":48,"value":4601},{"type":42,"tag":161,"props":5987,"children":5988},{"style":184},[5989],{"type":48,"value":3262},{"type":42,"tag":161,"props":5991,"children":5992},{"style":173},[5993],{"type":48,"value":2910},{"type":42,"tag":161,"props":5995,"children":5996},{"style":184},[5997],{"type":48,"value":1937},{"type":42,"tag":161,"props":5999,"children":6000},{"style":173},[6001],{"type":48,"value":6002}," \u002Ftmp\u002Ftraces_",{"type":42,"tag":161,"props":6004,"children":6005},{"style":184},[6006],{"type":48,"value":3177},{"type":42,"tag":161,"props":6008,"children":6009},{"style":195},[6010],{"type":48,"value":2812},{"type":42,"tag":161,"props":6012,"children":6013},{"style":184},[6014],{"type":48,"value":3186},{"type":42,"tag":161,"props":6016,"children":6017},{"style":173},[6018],{"type":48,"value":4635},{"type":42,"tag":161,"props":6020,"children":6021},{"class":163,"line":2663},[6022],{"type":42,"tag":161,"props":6023,"children":6024},{"emptyLinePlaceholder":2464},[6025],{"type":48,"value":2467},{"type":42,"tag":161,"props":6027,"children":6028},{"class":163,"line":2672},[6029],{"type":42,"tag":161,"props":6030,"children":6031},{"style":206},[6032],{"type":48,"value":6033},"# Each entry has: traceID (32-char hex), rootServiceName (\"k6\"),\n",{"type":42,"tag":161,"props":6035,"children":6036},{"class":163,"line":4358},[6037],{"type":42,"tag":161,"props":6038,"children":6039},{"style":206},[6040],{"type":48,"value":6041},"# rootTraceName (\"iteration\"), durationMs, startTimeUnixNano, and a\n",{"type":42,"tag":161,"props":6043,"children":6044},{"class":163,"line":4386},[6045],{"type":42,"tag":161,"props":6046,"children":6047},{"style":206},[6048],{"type":48,"value":6049},"# spanSet preview of the iteration root span's attributes\n",{"type":42,"tag":161,"props":6051,"children":6052},{"class":163,"line":4399},[6053],{"type":42,"tag":161,"props":6054,"children":6055},{"style":206},[6056],{"type":48,"value":6057},"# (test.iteration.number, test.vu, test.scenario).\n",{"type":42,"tag":161,"props":6059,"children":6060},{"class":163,"line":5022},[6061],{"type":42,"tag":161,"props":6062,"children":6063},{"emptyLinePlaceholder":2464},[6064],{"type":48,"value":2467},{"type":42,"tag":161,"props":6066,"children":6067},{"class":163,"line":5057},[6068],{"type":42,"tag":161,"props":6069,"children":6070},{"style":206},[6071],{"type":48,"value":6072},"# 3. Fetch a full trace. The response is OTLP-shaped:\n",{"type":42,"tag":161,"props":6074,"children":6075},{"class":163,"line":5107},[6076],{"type":42,"tag":161,"props":6077,"children":6078},{"style":206},[6079],{"type":48,"value":6080},"#    { \"batches\": [ { \"resource\": {...}, \"scopeSpans\": [ { \"spans\": [...] } ] } ] }\n",{"type":42,"tag":161,"props":6082,"children":6083},{"class":163,"line":5169},[6084,6089,6093,6097,6101,6105,6110,6114,6118,6122,6126,6130,6134],{"type":42,"tag":161,"props":6085,"children":6086},{"style":195},[6087],{"type":48,"value":6088},"TRACE_ID",{"type":42,"tag":161,"props":6090,"children":6091},{"style":184},[6092],{"type":48,"value":557},{"type":42,"tag":161,"props":6094,"children":6095},{"style":168},[6096],{"type":48,"value":1421},{"type":42,"tag":161,"props":6098,"children":6099},{"style":173},[6100],{"type":48,"value":658},{"type":42,"tag":161,"props":6102,"children":6103},{"style":184},[6104],{"type":48,"value":663},{"type":42,"tag":161,"props":6106,"children":6107},{"style":173},[6108],{"type":48,"value":6109},".traces[0].traceID",{"type":42,"tag":161,"props":6111,"children":6112},{"style":184},[6113],{"type":48,"value":673},{"type":42,"tag":161,"props":6115,"children":6116},{"style":173},[6117],{"type":48,"value":6002},{"type":42,"tag":161,"props":6119,"children":6120},{"style":184},[6121],{"type":48,"value":3177},{"type":42,"tag":161,"props":6123,"children":6124},{"style":195},[6125],{"type":48,"value":2812},{"type":42,"tag":161,"props":6127,"children":6128},{"style":184},[6129],{"type":48,"value":3186},{"type":42,"tag":161,"props":6131,"children":6132},{"style":173},[6133],{"type":48,"value":4752},{"type":42,"tag":161,"props":6135,"children":6136},{"style":184},[6137],{"type":48,"value":678},{"type":42,"tag":161,"props":6139,"children":6140},{"class":163,"line":5248},[6141,6145,6149,6153,6158,6163,6167],{"type":42,"tag":161,"props":6142,"children":6143},{"style":168},[6144],{"type":48,"value":62},{"type":42,"tag":161,"props":6146,"children":6147},{"style":173},[6148],{"type":48,"value":1927},{"type":42,"tag":161,"props":6150,"children":6151},{"style":184},[6152],{"type":48,"value":590},{"type":42,"tag":161,"props":6154,"children":6155},{"style":173},[6156],{"type":48,"value":6157},"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Flogs\u002Fapi\u002Fv1\u002Ftempo\u002Fapi\u002Ftraces\u002F",{"type":42,"tag":161,"props":6159,"children":6160},{"style":195},[6161],{"type":48,"value":6162},"$TRACE_ID",{"type":42,"tag":161,"props":6164,"children":6165},{"style":184},[6166],{"type":48,"value":605},{"type":42,"tag":161,"props":6168,"children":6169},{"style":195},[6170],{"type":48,"value":577},{"type":42,"tag":161,"props":6172,"children":6174},{"class":163,"line":6173},35,[6175,6179,6183,6187,6191,6195,6199,6203,6207,6211,6215,6220,6224,6228,6232],{"type":42,"tag":161,"props":6176,"children":6177},{"style":173},[6178],{"type":48,"value":585},{"type":42,"tag":161,"props":6180,"children":6181},{"style":184},[6182],{"type":48,"value":590},{"type":42,"tag":161,"props":6184,"children":6185},{"style":173},[6186],{"type":48,"value":3249},{"type":42,"tag":161,"props":6188,"children":6189},{"style":195},[6190],{"type":48,"value":3095},{"type":42,"tag":161,"props":6192,"children":6193},{"style":184},[6194],{"type":48,"value":605},{"type":42,"tag":161,"props":6196,"children":6197},{"style":173},[6198],{"type":48,"value":4596},{"type":42,"tag":161,"props":6200,"children":6201},{"style":173},[6202],{"type":48,"value":4601},{"type":42,"tag":161,"props":6204,"children":6205},{"style":184},[6206],{"type":48,"value":3262},{"type":42,"tag":161,"props":6208,"children":6209},{"style":173},[6210],{"type":48,"value":2910},{"type":42,"tag":161,"props":6212,"children":6213},{"style":184},[6214],{"type":48,"value":1937},{"type":42,"tag":161,"props":6216,"children":6217},{"style":173},[6218],{"type":48,"value":6219}," \u002Ftmp\u002Ftrace_",{"type":42,"tag":161,"props":6221,"children":6222},{"style":184},[6223],{"type":48,"value":3177},{"type":42,"tag":161,"props":6225,"children":6226},{"style":195},[6227],{"type":48,"value":6088},{"type":42,"tag":161,"props":6229,"children":6230},{"style":184},[6231],{"type":48,"value":3186},{"type":42,"tag":161,"props":6233,"children":6234},{"style":173},[6235],{"type":48,"value":4635},{"type":42,"tag":143,"props":6237,"children":6239},{"id":6238},"compact-summary-for-an-agent",[6240],{"type":48,"value":6241},"Compact summary for an agent",{"type":42,"tag":51,"props":6243,"children":6244},{},[6245],{"type":48,"value":6246},"The OTLP body for a single iteration can run ~100 KB pretty-printed.\nDumping it verbatim into context is wasteful — most of the useful\nsignal lives in the span-name distribution, the slowest individual\nspans, and the web-vital ratings. The pipeline below collapses a\ntrace into ~1–2 KB of plain text:",{"type":42,"tag":150,"props":6248,"children":6250},{"className":152,"code":6249,"language":154,"meta":155,"style":155},"jq -r '\n  # OTel value envelope: pick by key presence, not \u002F\u002F-chaining — jq's \u002F\u002F\n  # treats `false` as missing and would drop legitimate boolValue:false.\n  def attrval:\n    if   has(\"stringValue\") then .stringValue\n    elif has(\"intValue\")    then .intValue\n    elif has(\"boolValue\")   then .boolValue\n    elif has(\"doubleValue\") then .doubleValue\n    else null end;\n  def attrs: [.attributes[] | {(.key): (.value | attrval)}] | add \u002F\u002F {};\n  def dur:   (((.endTimeUnixNano|tonumber) - (.startTimeUnixNano|tonumber)) \u002F 1000000 | floor);\n\n  [.batches[].scopeSpans[].spans[] | {name, dur: dur, a: attrs, status: (.status.code \u002F\u002F \"OK\")}] as $spans\n\n  | \"── span-name rollup (count · total ms · max ms) ──\",\n    ([$spans[] | {name, dur}]\n       | group_by(.name) | map({name: .[0].name, n: length,\n                                t: (map(.dur)|add), m: (map(.dur)|max)})\n       | sort_by(-.t)[]\n       | \"  \\(.n|tostring|.+\"      \"|.[0:4])  \\(.t|tostring|.+\"        \"|.[0:7])  \\(.m|tostring|.+\"      \"|.[0:6])  \\(.name)\"),\n\n    \"\\n── slowest spans (ms · name · navigation.url \u002F page.goto.url) ──\",\n    ([$spans[] | select(.name != \"iteration\")] | sort_by(-.dur) | .[0:8][]\n       | \"  \\(.dur|tostring|.+\"        \"|.[0:7])  \\(.name)\\(if .a[\"navigation.url\"] \u002F\u002F .a[\"page.goto.url\"] then \"  \" + (.a[\"navigation.url\"] \u002F\u002F .a[\"page.goto.url\"]) else \"\" end)\"),\n\n    \"\\n── web-vital ratings ──\",\n    ([$spans[] | select(.name == \"web_vital\")\n       | {n: .a[\"web_vital.name\"], v: .a[\"web_vital.value\"], r: .a[\"web_vital.rating\"]}]\n       | group_by(.n) | map({name: .[0].n,\n                             ratings: ([.[].r] | group_by(.) | map({(.[0]): length}) | add)})[]\n       | \"  \\(.name)  \\(.ratings)\"),\n\n    \"\\n── span errors ──\",\n    ([$spans[] | select(.status != \"OK\" and .status != null)] | length | \"  count: \\(.)\")\n' \u002Ftmp\u002Ftrace_${TRACE_ID}.json\n",[6251],{"type":42,"tag":57,"props":6252,"children":6253},{"__ignoreMap":155},[6254,6270,6292,6300,6313,6346,6378,6408,6437,6460,6550,6616,6623,6718,6725,6741,6772,6818,6868,6889,6947,6954,6966,7049,7171,7178,7190,7243,7337,7370,7443,7459,7466,7478,7565],{"type":42,"tag":161,"props":6255,"children":6256},{"class":163,"line":164},[6257,6261,6265],{"type":42,"tag":161,"props":6258,"children":6259},{"style":168},[6260],{"type":48,"value":1421},{"type":42,"tag":161,"props":6262,"children":6263},{"style":173},[6264],{"type":48,"value":658},{"type":42,"tag":161,"props":6266,"children":6267},{"style":184},[6268],{"type":48,"value":6269}," '\n",{"type":42,"tag":161,"props":6271,"children":6272},{"class":163,"line":212},[6273,6278,6282,6287],{"type":42,"tag":161,"props":6274,"children":6275},{"style":173},[6276],{"type":48,"value":6277},"  # OTel value envelope: pick by key presence, not \u002F\u002F-chaining — jq",{"type":42,"tag":161,"props":6279,"children":6280},{"style":184},[6281],{"type":48,"value":673},{"type":42,"tag":161,"props":6283,"children":6284},{"style":173},[6285],{"type":48,"value":6286},"s",{"type":42,"tag":161,"props":6288,"children":6289},{"style":173},[6290],{"type":48,"value":6291}," \u002F\u002F\n",{"type":42,"tag":161,"props":6293,"children":6294},{"class":163,"line":612},[6295],{"type":42,"tag":161,"props":6296,"children":6297},{"style":206},[6298],{"type":48,"value":6299},"  # treats `false` as missing and would drop legitimate boolValue:false.\n",{"type":42,"tag":161,"props":6301,"children":6302},{"class":163,"line":642},[6303,6308],{"type":42,"tag":161,"props":6304,"children":6305},{"style":168},[6306],{"type":48,"value":6307},"  def",{"type":42,"tag":161,"props":6309,"children":6310},{"style":173},[6311],{"type":48,"value":6312}," attrval:\n",{"type":42,"tag":161,"props":6314,"children":6315},{"class":163,"line":2486},[6316,6321,6326,6331,6336,6341],{"type":42,"tag":161,"props":6317,"children":6318},{"style":5111},[6319],{"type":48,"value":6320},"    if",{"type":42,"tag":161,"props":6322,"children":6323},{"style":168},[6324],{"type":48,"value":6325},"   has(",{"type":42,"tag":161,"props":6327,"children":6328},{"style":168},[6329],{"type":48,"value":6330},"\"stringValue\"",{"type":42,"tag":161,"props":6332,"children":6333},{"style":195},[6334],{"type":48,"value":6335},") ",{"type":42,"tag":161,"props":6337,"children":6338},{"style":5111},[6339],{"type":48,"value":6340},"then",{"type":42,"tag":161,"props":6342,"children":6343},{"style":168},[6344],{"type":48,"value":6345}," .stringValue\n",{"type":42,"tag":161,"props":6347,"children":6348},{"class":163,"line":2495},[6349,6354,6359,6364,6369,6373],{"type":42,"tag":161,"props":6350,"children":6351},{"style":5111},[6352],{"type":48,"value":6353},"    elif",{"type":42,"tag":161,"props":6355,"children":6356},{"style":168},[6357],{"type":48,"value":6358}," has(",{"type":42,"tag":161,"props":6360,"children":6361},{"style":168},[6362],{"type":48,"value":6363},"\"intValue\"",{"type":42,"tag":161,"props":6365,"children":6366},{"style":195},[6367],{"type":48,"value":6368},")    ",{"type":42,"tag":161,"props":6370,"children":6371},{"style":5111},[6372],{"type":48,"value":6340},{"type":42,"tag":161,"props":6374,"children":6375},{"style":168},[6376],{"type":48,"value":6377}," .intValue\n",{"type":42,"tag":161,"props":6379,"children":6380},{"class":163,"line":2503},[6381,6385,6389,6394,6399,6403],{"type":42,"tag":161,"props":6382,"children":6383},{"style":5111},[6384],{"type":48,"value":6353},{"type":42,"tag":161,"props":6386,"children":6387},{"style":168},[6388],{"type":48,"value":6358},{"type":42,"tag":161,"props":6390,"children":6391},{"style":168},[6392],{"type":48,"value":6393},"\"boolValue\"",{"type":42,"tag":161,"props":6395,"children":6396},{"style":195},[6397],{"type":48,"value":6398},")   ",{"type":42,"tag":161,"props":6400,"children":6401},{"style":5111},[6402],{"type":48,"value":6340},{"type":42,"tag":161,"props":6404,"children":6405},{"style":168},[6406],{"type":48,"value":6407}," .boolValue\n",{"type":42,"tag":161,"props":6409,"children":6410},{"class":163,"line":2512},[6411,6415,6419,6424,6428,6432],{"type":42,"tag":161,"props":6412,"children":6413},{"style":5111},[6414],{"type":48,"value":6353},{"type":42,"tag":161,"props":6416,"children":6417},{"style":168},[6418],{"type":48,"value":6358},{"type":42,"tag":161,"props":6420,"children":6421},{"style":168},[6422],{"type":48,"value":6423},"\"doubleValue\"",{"type":42,"tag":161,"props":6425,"children":6426},{"style":195},[6427],{"type":48,"value":6335},{"type":42,"tag":161,"props":6429,"children":6430},{"style":5111},[6431],{"type":48,"value":6340},{"type":42,"tag":161,"props":6433,"children":6434},{"style":168},[6435],{"type":48,"value":6436}," .doubleValue\n",{"type":42,"tag":161,"props":6438,"children":6439},{"class":163,"line":2521},[6440,6445,6450,6455],{"type":42,"tag":161,"props":6441,"children":6442},{"style":5111},[6443],{"type":48,"value":6444},"    else",{"type":42,"tag":161,"props":6446,"children":6447},{"style":168},[6448],{"type":48,"value":6449}," null",{"type":42,"tag":161,"props":6451,"children":6452},{"style":173},[6453],{"type":48,"value":6454}," end",{"type":42,"tag":161,"props":6456,"children":6457},{"style":184},[6458],{"type":48,"value":6459},";\n",{"type":42,"tag":161,"props":6461,"children":6462},{"class":163,"line":2530},[6463,6467,6472,6477,6482,6487,6492,6496,6500,6505,6509,6514,6518,6522,6527,6531,6536,6541,6546],{"type":42,"tag":161,"props":6464,"children":6465},{"style":168},[6466],{"type":48,"value":6307},{"type":42,"tag":161,"props":6468,"children":6469},{"style":173},[6470],{"type":48,"value":6471}," attrs:",{"type":42,"tag":161,"props":6473,"children":6474},{"style":195},[6475],{"type":48,"value":6476}," [.attributes[] ",{"type":42,"tag":161,"props":6478,"children":6479},{"style":184},[6480],{"type":48,"value":6481},"|",{"type":42,"tag":161,"props":6483,"children":6484},{"style":184},[6485],{"type":48,"value":6486}," {(",{"type":42,"tag":161,"props":6488,"children":6489},{"style":168},[6490],{"type":48,"value":6491},".key",{"type":42,"tag":161,"props":6493,"children":6494},{"style":184},[6495],{"type":48,"value":2777},{"type":42,"tag":161,"props":6497,"children":6498},{"style":2945},[6499],{"type":48,"value":537},{"type":42,"tag":161,"props":6501,"children":6502},{"style":195},[6503],{"type":48,"value":6504}," (.value ",{"type":42,"tag":161,"props":6506,"children":6507},{"style":184},[6508],{"type":48,"value":6481},{"type":42,"tag":161,"props":6510,"children":6511},{"style":168},[6512],{"type":48,"value":6513}," attrval",{"type":42,"tag":161,"props":6515,"children":6516},{"style":195},[6517],{"type":48,"value":2777},{"type":42,"tag":161,"props":6519,"children":6520},{"style":184},[6521],{"type":48,"value":3186},{"type":42,"tag":161,"props":6523,"children":6524},{"style":195},[6525],{"type":48,"value":6526},"] ",{"type":42,"tag":161,"props":6528,"children":6529},{"style":184},[6530],{"type":48,"value":6481},{"type":42,"tag":161,"props":6532,"children":6533},{"style":168},[6534],{"type":48,"value":6535}," add",{"type":42,"tag":161,"props":6537,"children":6538},{"style":173},[6539],{"type":48,"value":6540}," \u002F\u002F",{"type":42,"tag":161,"props":6542,"children":6543},{"style":173},[6544],{"type":48,"value":6545}," {}",{"type":42,"tag":161,"props":6547,"children":6548},{"style":184},[6549],{"type":48,"value":6459},{"type":42,"tag":161,"props":6551,"children":6552},{"class":163,"line":2539},[6553,6557,6562,6567,6571,6576,6581,6586,6590,6594,6599,6603,6608,6612],{"type":42,"tag":161,"props":6554,"children":6555},{"style":168},[6556],{"type":48,"value":6307},{"type":42,"tag":161,"props":6558,"children":6559},{"style":173},[6560],{"type":48,"value":6561}," dur:",{"type":42,"tag":161,"props":6563,"children":6564},{"style":195},[6565],{"type":48,"value":6566},"   (((.endTimeUnixNano",{"type":42,"tag":161,"props":6568,"children":6569},{"style":184},[6570],{"type":48,"value":6481},{"type":42,"tag":161,"props":6572,"children":6573},{"style":168},[6574],{"type":48,"value":6575},"tonumber",{"type":42,"tag":161,"props":6577,"children":6578},{"style":195},[6579],{"type":48,"value":6580},") - (",{"type":42,"tag":161,"props":6582,"children":6583},{"style":168},[6584],{"type":48,"value":6585},".startTimeUnixNano",{"type":42,"tag":161,"props":6587,"children":6588},{"style":184},[6589],{"type":48,"value":6481},{"type":42,"tag":161,"props":6591,"children":6592},{"style":168},[6593],{"type":48,"value":6575},{"type":42,"tag":161,"props":6595,"children":6596},{"style":195},[6597],{"type":48,"value":6598},")) \u002F 1000000 ",{"type":42,"tag":161,"props":6600,"children":6601},{"style":184},[6602],{"type":48,"value":6481},{"type":42,"tag":161,"props":6604,"children":6605},{"style":168},[6606],{"type":48,"value":6607}," floor",{"type":42,"tag":161,"props":6609,"children":6610},{"style":195},[6611],{"type":48,"value":2777},{"type":42,"tag":161,"props":6613,"children":6614},{"style":184},[6615],{"type":48,"value":6459},{"type":42,"tag":161,"props":6617,"children":6618},{"class":163,"line":2548},[6619],{"type":42,"tag":161,"props":6620,"children":6621},{"emptyLinePlaceholder":2464},[6622],{"type":48,"value":2467},{"type":42,"tag":161,"props":6624,"children":6625},{"class":163,"line":2556},[6626,6631,6636,6640,6645,6649,6654,6658,6662,6667,6672,6677,6682,6686,6691,6695,6699,6703,6708,6713],{"type":42,"tag":161,"props":6627,"children":6628},{"style":184},[6629],{"type":48,"value":6630},"  [",{"type":42,"tag":161,"props":6632,"children":6633},{"style":195},[6634],{"type":48,"value":6635},".batches",{"type":42,"tag":161,"props":6637,"children":6638},{"style":184},[6639],{"type":48,"value":5343},{"type":42,"tag":161,"props":6641,"children":6642},{"style":195},[6643],{"type":48,"value":6644},".scopeSpans",{"type":42,"tag":161,"props":6646,"children":6647},{"style":184},[6648],{"type":48,"value":5343},{"type":42,"tag":161,"props":6650,"children":6651},{"style":195},[6652],{"type":48,"value":6653},".spans",{"type":42,"tag":161,"props":6655,"children":6656},{"style":184},[6657],{"type":48,"value":5343},{"type":42,"tag":161,"props":6659,"children":6660},{"style":184},[6661],{"type":48,"value":2966},{"type":42,"tag":161,"props":6663,"children":6664},{"style":195},[6665],{"type":48,"value":6666}," {name, dur: dur, a: attrs, status: ",{"type":42,"tag":161,"props":6668,"children":6669},{"style":184},[6670],{"type":48,"value":6671},"(",{"type":42,"tag":161,"props":6673,"children":6674},{"style":195},[6675],{"type":48,"value":6676},".status.code ",{"type":42,"tag":161,"props":6678,"children":6679},{"style":184},[6680],{"type":48,"value":6681},"\u002F\u002F",{"type":42,"tag":161,"props":6683,"children":6684},{"style":184},[6685],{"type":48,"value":590},{"type":42,"tag":161,"props":6687,"children":6688},{"style":173},[6689],{"type":48,"value":6690},"OK",{"type":42,"tag":161,"props":6692,"children":6693},{"style":184},[6694],{"type":48,"value":605},{"type":42,"tag":161,"props":6696,"children":6697},{"style":184},[6698],{"type":48,"value":2777},{"type":42,"tag":161,"props":6700,"children":6701},{"style":195},[6702],{"type":48,"value":3186},{"type":42,"tag":161,"props":6704,"children":6705},{"style":184},[6706],{"type":48,"value":6707},"]",{"type":42,"tag":161,"props":6709,"children":6710},{"style":168},[6711],{"type":48,"value":6712}," as",{"type":42,"tag":161,"props":6714,"children":6715},{"style":195},[6716],{"type":48,"value":6717}," $spans\n",{"type":42,"tag":161,"props":6719,"children":6720},{"class":163,"line":2565},[6721],{"type":42,"tag":161,"props":6722,"children":6723},{"emptyLinePlaceholder":2464},[6724],{"type":48,"value":2467},{"type":42,"tag":161,"props":6726,"children":6727},{"class":163,"line":2574},[6728,6732,6737],{"type":42,"tag":161,"props":6729,"children":6730},{"style":184},[6731],{"type":48,"value":648},{"type":42,"tag":161,"props":6733,"children":6734},{"style":168},[6735],{"type":48,"value":6736}," \"── span-name rollup (count · total ms · max ms) ──\"",{"type":42,"tag":161,"props":6738,"children":6739},{"style":168},[6740],{"type":48,"value":380},{"type":42,"tag":161,"props":6742,"children":6743},{"class":163,"line":30},[6744,6749,6754,6758,6762,6767],{"type":42,"tag":161,"props":6745,"children":6746},{"style":184},[6747],{"type":48,"value":6748},"    ([",{"type":42,"tag":161,"props":6750,"children":6751},{"style":195},[6752],{"type":48,"value":6753},"$spans",{"type":42,"tag":161,"props":6755,"children":6756},{"style":184},[6757],{"type":48,"value":5343},{"type":42,"tag":161,"props":6759,"children":6760},{"style":184},[6761],{"type":48,"value":2966},{"type":42,"tag":161,"props":6763,"children":6764},{"style":195},[6765],{"type":48,"value":6766}," {name, dur}",{"type":42,"tag":161,"props":6768,"children":6769},{"style":184},[6770],{"type":48,"value":6771},"]\n",{"type":42,"tag":161,"props":6773,"children":6774},{"class":163,"line":2591},[6775,6780,6785,6789,6793,6798,6803,6808,6813],{"type":42,"tag":161,"props":6776,"children":6777},{"style":184},[6778],{"type":48,"value":6779},"       |",{"type":42,"tag":161,"props":6781,"children":6782},{"style":168},[6783],{"type":48,"value":6784}," group_by(.name",{"type":42,"tag":161,"props":6786,"children":6787},{"style":184},[6788],{"type":48,"value":2777},{"type":42,"tag":161,"props":6790,"children":6791},{"style":184},[6792],{"type":48,"value":2966},{"type":42,"tag":161,"props":6794,"children":6795},{"style":168},[6796],{"type":48,"value":6797}," map(",{"type":42,"tag":161,"props":6799,"children":6800},{"style":173},[6801],{"type":48,"value":6802},"{name:",{"type":42,"tag":161,"props":6804,"children":6805},{"style":173},[6806],{"type":48,"value":6807}," .[0].name,",{"type":42,"tag":161,"props":6809,"children":6810},{"style":173},[6811],{"type":48,"value":6812}," n:",{"type":42,"tag":161,"props":6814,"children":6815},{"style":173},[6816],{"type":48,"value":6817}," length,\n",{"type":42,"tag":161,"props":6819,"children":6820},{"class":163,"line":2600},[6821,6826,6831,6835,6840,6845,6850,6854,6858,6863],{"type":42,"tag":161,"props":6822,"children":6823},{"style":168},[6824],{"type":48,"value":6825},"                                t:",{"type":42,"tag":161,"props":6827,"children":6828},{"style":195},[6829],{"type":48,"value":6830}," (map(.dur)",{"type":42,"tag":161,"props":6832,"children":6833},{"style":184},[6834],{"type":48,"value":6481},{"type":42,"tag":161,"props":6836,"children":6837},{"style":168},[6838],{"type":48,"value":6839},"add",{"type":42,"tag":161,"props":6841,"children":6842},{"style":195},[6843],{"type":48,"value":6844},"), m: (",{"type":42,"tag":161,"props":6846,"children":6847},{"style":168},[6848],{"type":48,"value":6849},"map(.dur",{"type":42,"tag":161,"props":6851,"children":6852},{"style":195},[6853],{"type":48,"value":2777},{"type":42,"tag":161,"props":6855,"children":6856},{"style":184},[6857],{"type":48,"value":6481},{"type":42,"tag":161,"props":6859,"children":6860},{"style":168},[6861],{"type":48,"value":6862},"max",{"type":42,"tag":161,"props":6864,"children":6865},{"style":195},[6866],{"type":48,"value":6867},")})\n",{"type":42,"tag":161,"props":6869,"children":6870},{"class":163,"line":2609},[6871,6875,6880,6884],{"type":42,"tag":161,"props":6872,"children":6873},{"style":184},[6874],{"type":48,"value":6779},{"type":42,"tag":161,"props":6876,"children":6877},{"style":168},[6878],{"type":48,"value":6879}," sort_by(-.t",{"type":42,"tag":161,"props":6881,"children":6882},{"style":195},[6883],{"type":48,"value":2777},{"type":42,"tag":161,"props":6885,"children":6886},{"style":184},[6887],{"type":48,"value":6888},"[]\n",{"type":42,"tag":161,"props":6890,"children":6891},{"class":163,"line":2618},[6892,6896,6901,6906,6911,6915,6920,6925,6929,6933,6938,6942],{"type":42,"tag":161,"props":6893,"children":6894},{"style":184},[6895],{"type":48,"value":6779},{"type":42,"tag":161,"props":6897,"children":6898},{"style":168},[6899],{"type":48,"value":6900}," \"  \\(.n|tostring|.+\"",{"type":42,"tag":161,"props":6902,"children":6903},{"style":184},[6904],{"type":48,"value":6905},"      \"",{"type":42,"tag":161,"props":6907,"children":6908},{"style":173},[6909],{"type":48,"value":6910},"|.[0:4])  \\(.t|tostring|.+",{"type":42,"tag":161,"props":6912,"children":6913},{"style":184},[6914],{"type":48,"value":605},{"type":42,"tag":161,"props":6916,"children":6917},{"style":184},[6918],{"type":48,"value":6919},"        \"",{"type":42,"tag":161,"props":6921,"children":6922},{"style":173},[6923],{"type":48,"value":6924},"|.[0:7])  \\(.m|tostring|.+",{"type":42,"tag":161,"props":6926,"children":6927},{"style":184},[6928],{"type":48,"value":605},{"type":42,"tag":161,"props":6930,"children":6931},{"style":184},[6932],{"type":48,"value":6905},{"type":42,"tag":161,"props":6934,"children":6935},{"style":173},[6936],{"type":48,"value":6937},"|.[0:6])  \\(.name)",{"type":42,"tag":161,"props":6939,"children":6940},{"style":184},[6941],{"type":48,"value":605},{"type":42,"tag":161,"props":6943,"children":6944},{"style":195},[6945],{"type":48,"value":6946},"),\n",{"type":42,"tag":161,"props":6948,"children":6949},{"class":163,"line":2627},[6950],{"type":42,"tag":161,"props":6951,"children":6952},{"emptyLinePlaceholder":2464},[6953],{"type":48,"value":2467},{"type":42,"tag":161,"props":6955,"children":6956},{"class":163,"line":2636},[6957,6962],{"type":42,"tag":161,"props":6958,"children":6959},{"style":168},[6960],{"type":48,"value":6961},"    \"\\n── slowest spans (ms · name · navigation.url \u002F page.goto.url) ──\"",{"type":42,"tag":161,"props":6963,"children":6964},{"style":168},[6965],{"type":48,"value":380},{"type":42,"tag":161,"props":6967,"children":6968},{"class":163,"line":2645},[6969,6973,6977,6981,6985,6990,6994,6999,7004,7008,7013,7017,7022,7026,7031,7035,7039,7044],{"type":42,"tag":161,"props":6970,"children":6971},{"style":184},[6972],{"type":48,"value":6748},{"type":42,"tag":161,"props":6974,"children":6975},{"style":195},[6976],{"type":48,"value":6753},{"type":42,"tag":161,"props":6978,"children":6979},{"style":184},[6980],{"type":48,"value":5343},{"type":42,"tag":161,"props":6982,"children":6983},{"style":184},[6984],{"type":48,"value":2966},{"type":42,"tag":161,"props":6986,"children":6987},{"style":195},[6988],{"type":48,"value":6989}," select",{"type":42,"tag":161,"props":6991,"children":6992},{"style":184},[6993],{"type":48,"value":6671},{"type":42,"tag":161,"props":6995,"children":6996},{"style":195},[6997],{"type":48,"value":6998},".name ",{"type":42,"tag":161,"props":7000,"children":7001},{"style":184},[7002],{"type":48,"value":7003},"!=",{"type":42,"tag":161,"props":7005,"children":7006},{"style":184},[7007],{"type":48,"value":590},{"type":42,"tag":161,"props":7009,"children":7010},{"style":173},[7011],{"type":48,"value":7012},"iteration",{"type":42,"tag":161,"props":7014,"children":7015},{"style":184},[7016],{"type":48,"value":605},{"type":42,"tag":161,"props":7018,"children":7019},{"style":184},[7020],{"type":48,"value":7021},")]",{"type":42,"tag":161,"props":7023,"children":7024},{"style":184},[7025],{"type":48,"value":2966},{"type":42,"tag":161,"props":7027,"children":7028},{"style":168},[7029],{"type":48,"value":7030}," sort_by(-.dur",{"type":42,"tag":161,"props":7032,"children":7033},{"style":184},[7034],{"type":48,"value":2777},{"type":42,"tag":161,"props":7036,"children":7037},{"style":184},[7038],{"type":48,"value":2966},{"type":42,"tag":161,"props":7040,"children":7041},{"style":2945},[7042],{"type":48,"value":7043}," .",{"type":42,"tag":161,"props":7045,"children":7046},{"style":173},[7047],{"type":48,"value":7048},"[0:8][]\n",{"type":42,"tag":161,"props":7050,"children":7051},{"class":163,"line":2654},[7052,7056,7061,7065,7070,7074,7079,7083,7088,7092,7097,7101,7106,7110,7115,7120,7124,7128,7132,7136,7140,7144,7148,7153,7158,7163,7167],{"type":42,"tag":161,"props":7053,"children":7054},{"style":184},[7055],{"type":48,"value":6779},{"type":42,"tag":161,"props":7057,"children":7058},{"style":168},[7059],{"type":48,"value":7060}," \"  \\(.dur|tostring|.+\"",{"type":42,"tag":161,"props":7062,"children":7063},{"style":184},[7064],{"type":48,"value":6919},{"type":42,"tag":161,"props":7066,"children":7067},{"style":173},[7068],{"type":48,"value":7069},"|.[0:7])  \\(.name)\\(if .a[",{"type":42,"tag":161,"props":7071,"children":7072},{"style":184},[7073],{"type":48,"value":605},{"type":42,"tag":161,"props":7075,"children":7076},{"style":173},[7077],{"type":48,"value":7078},"navigation.url",{"type":42,"tag":161,"props":7080,"children":7081},{"style":184},[7082],{"type":48,"value":605},{"type":42,"tag":161,"props":7084,"children":7085},{"style":173},[7086],{"type":48,"value":7087},"] \u002F\u002F .a[",{"type":42,"tag":161,"props":7089,"children":7090},{"style":184},[7091],{"type":48,"value":605},{"type":42,"tag":161,"props":7093,"children":7094},{"style":173},[7095],{"type":48,"value":7096},"page.goto.url",{"type":42,"tag":161,"props":7098,"children":7099},{"style":184},[7100],{"type":48,"value":605},{"type":42,"tag":161,"props":7102,"children":7103},{"style":173},[7104],{"type":48,"value":7105},"] then ",{"type":42,"tag":161,"props":7107,"children":7108},{"style":184},[7109],{"type":48,"value":605},{"type":42,"tag":161,"props":7111,"children":7112},{"style":184},[7113],{"type":48,"value":7114},"  \"",{"type":42,"tag":161,"props":7116,"children":7117},{"style":173},[7118],{"type":48,"value":7119}," + (.a[",{"type":42,"tag":161,"props":7121,"children":7122},{"style":184},[7123],{"type":48,"value":605},{"type":42,"tag":161,"props":7125,"children":7126},{"style":173},[7127],{"type":48,"value":7078},{"type":42,"tag":161,"props":7129,"children":7130},{"style":184},[7131],{"type":48,"value":605},{"type":42,"tag":161,"props":7133,"children":7134},{"style":173},[7135],{"type":48,"value":7087},{"type":42,"tag":161,"props":7137,"children":7138},{"style":184},[7139],{"type":48,"value":605},{"type":42,"tag":161,"props":7141,"children":7142},{"style":173},[7143],{"type":48,"value":7096},{"type":42,"tag":161,"props":7145,"children":7146},{"style":184},[7147],{"type":48,"value":605},{"type":42,"tag":161,"props":7149,"children":7150},{"style":173},[7151],{"type":48,"value":7152},"]) else ",{"type":42,"tag":161,"props":7154,"children":7155},{"style":184},[7156],{"type":48,"value":7157},"\"\"",{"type":42,"tag":161,"props":7159,"children":7160},{"style":173},[7161],{"type":48,"value":7162}," end)",{"type":42,"tag":161,"props":7164,"children":7165},{"style":184},[7166],{"type":48,"value":605},{"type":42,"tag":161,"props":7168,"children":7169},{"style":195},[7170],{"type":48,"value":6946},{"type":42,"tag":161,"props":7172,"children":7173},{"class":163,"line":2663},[7174],{"type":42,"tag":161,"props":7175,"children":7176},{"emptyLinePlaceholder":2464},[7177],{"type":48,"value":2467},{"type":42,"tag":161,"props":7179,"children":7180},{"class":163,"line":2672},[7181,7186],{"type":42,"tag":161,"props":7182,"children":7183},{"style":168},[7184],{"type":48,"value":7185},"    \"\\n── web-vital ratings ──\"",{"type":42,"tag":161,"props":7187,"children":7188},{"style":168},[7189],{"type":48,"value":380},{"type":42,"tag":161,"props":7191,"children":7192},{"class":163,"line":4358},[7193,7197,7201,7205,7209,7213,7217,7221,7226,7230,7235,7239],{"type":42,"tag":161,"props":7194,"children":7195},{"style":184},[7196],{"type":48,"value":6748},{"type":42,"tag":161,"props":7198,"children":7199},{"style":195},[7200],{"type":48,"value":6753},{"type":42,"tag":161,"props":7202,"children":7203},{"style":184},[7204],{"type":48,"value":5343},{"type":42,"tag":161,"props":7206,"children":7207},{"style":184},[7208],{"type":48,"value":2966},{"type":42,"tag":161,"props":7210,"children":7211},{"style":195},[7212],{"type":48,"value":6989},{"type":42,"tag":161,"props":7214,"children":7215},{"style":184},[7216],{"type":48,"value":6671},{"type":42,"tag":161,"props":7218,"children":7219},{"style":195},[7220],{"type":48,"value":6998},{"type":42,"tag":161,"props":7222,"children":7223},{"style":184},[7224],{"type":48,"value":7225},"==",{"type":42,"tag":161,"props":7227,"children":7228},{"style":184},[7229],{"type":48,"value":590},{"type":42,"tag":161,"props":7231,"children":7232},{"style":173},[7233],{"type":48,"value":7234},"web_vital",{"type":42,"tag":161,"props":7236,"children":7237},{"style":184},[7238],{"type":48,"value":605},{"type":42,"tag":161,"props":7240,"children":7241},{"style":184},[7242],{"type":48,"value":678},{"type":42,"tag":161,"props":7244,"children":7245},{"class":163,"line":4386},[7246,7250,7255,7260,7264,7269,7273,7277,7282,7286,7290,7295,7299,7303,7308,7312,7316,7321,7325,7329,7333],{"type":42,"tag":161,"props":7247,"children":7248},{"style":184},[7249],{"type":48,"value":6779},{"type":42,"tag":161,"props":7251,"children":7252},{"style":195},[7253],{"type":48,"value":7254}," {n: .a",{"type":42,"tag":161,"props":7256,"children":7257},{"style":184},[7258],{"type":48,"value":7259},"[",{"type":42,"tag":161,"props":7261,"children":7262},{"style":184},[7263],{"type":48,"value":605},{"type":42,"tag":161,"props":7265,"children":7266},{"style":173},[7267],{"type":48,"value":7268},"web_vital.name",{"type":42,"tag":161,"props":7270,"children":7271},{"style":184},[7272],{"type":48,"value":605},{"type":42,"tag":161,"props":7274,"children":7275},{"style":184},[7276],{"type":48,"value":6707},{"type":42,"tag":161,"props":7278,"children":7279},{"style":195},[7280],{"type":48,"value":7281},", v: .a",{"type":42,"tag":161,"props":7283,"children":7284},{"style":184},[7285],{"type":48,"value":7259},{"type":42,"tag":161,"props":7287,"children":7288},{"style":184},[7289],{"type":48,"value":605},{"type":42,"tag":161,"props":7291,"children":7292},{"style":173},[7293],{"type":48,"value":7294},"web_vital.value",{"type":42,"tag":161,"props":7296,"children":7297},{"style":184},[7298],{"type":48,"value":605},{"type":42,"tag":161,"props":7300,"children":7301},{"style":184},[7302],{"type":48,"value":6707},{"type":42,"tag":161,"props":7304,"children":7305},{"style":195},[7306],{"type":48,"value":7307},", r: .a",{"type":42,"tag":161,"props":7309,"children":7310},{"style":184},[7311],{"type":48,"value":7259},{"type":42,"tag":161,"props":7313,"children":7314},{"style":184},[7315],{"type":48,"value":605},{"type":42,"tag":161,"props":7317,"children":7318},{"style":173},[7319],{"type":48,"value":7320},"web_vital.rating",{"type":42,"tag":161,"props":7322,"children":7323},{"style":184},[7324],{"type":48,"value":605},{"type":42,"tag":161,"props":7326,"children":7327},{"style":184},[7328],{"type":48,"value":6707},{"type":42,"tag":161,"props":7330,"children":7331},{"style":195},[7332],{"type":48,"value":3186},{"type":42,"tag":161,"props":7334,"children":7335},{"style":184},[7336],{"type":48,"value":6771},{"type":42,"tag":161,"props":7338,"children":7339},{"class":163,"line":4399},[7340,7344,7349,7353,7357,7361,7365],{"type":42,"tag":161,"props":7341,"children":7342},{"style":184},[7343],{"type":48,"value":6779},{"type":42,"tag":161,"props":7345,"children":7346},{"style":168},[7347],{"type":48,"value":7348}," group_by(.n",{"type":42,"tag":161,"props":7350,"children":7351},{"style":184},[7352],{"type":48,"value":2777},{"type":42,"tag":161,"props":7354,"children":7355},{"style":184},[7356],{"type":48,"value":2966},{"type":42,"tag":161,"props":7358,"children":7359},{"style":168},[7360],{"type":48,"value":6797},{"type":42,"tag":161,"props":7362,"children":7363},{"style":173},[7364],{"type":48,"value":6802},{"type":42,"tag":161,"props":7366,"children":7367},{"style":173},[7368],{"type":48,"value":7369}," .[0].n,\n",{"type":42,"tag":161,"props":7371,"children":7372},{"class":163,"line":5022},[7373,7378,7383,7387,7392,7396,7400,7404,7408,7412,7416,7421,7426,7430,7434,7439],{"type":42,"tag":161,"props":7374,"children":7375},{"style":168},[7376],{"type":48,"value":7377},"                             ratings:",{"type":42,"tag":161,"props":7379,"children":7380},{"style":195},[7381],{"type":48,"value":7382}," ([.[].r] ",{"type":42,"tag":161,"props":7384,"children":7385},{"style":184},[7386],{"type":48,"value":6481},{"type":42,"tag":161,"props":7388,"children":7389},{"style":168},[7390],{"type":48,"value":7391}," group_by(.",{"type":42,"tag":161,"props":7393,"children":7394},{"style":195},[7395],{"type":48,"value":6335},{"type":42,"tag":161,"props":7397,"children":7398},{"style":184},[7399],{"type":48,"value":6481},{"type":42,"tag":161,"props":7401,"children":7402},{"style":168},[7403],{"type":48,"value":6797},{"type":42,"tag":161,"props":7405,"children":7406},{"style":173},[7407],{"type":48,"value":1490},{"type":42,"tag":161,"props":7409,"children":7410},{"style":195},[7411],{"type":48,"value":6671},{"type":42,"tag":161,"props":7413,"children":7414},{"style":2945},[7415],{"type":48,"value":288},{"type":42,"tag":161,"props":7417,"children":7418},{"style":173},[7419],{"type":48,"value":7420},"[0]",{"type":42,"tag":161,"props":7422,"children":7423},{"style":195},[7424],{"type":48,"value":7425},"): length}) ",{"type":42,"tag":161,"props":7427,"children":7428},{"style":184},[7429],{"type":48,"value":6481},{"type":42,"tag":161,"props":7431,"children":7432},{"style":168},[7433],{"type":48,"value":6535},{"type":42,"tag":161,"props":7435,"children":7436},{"style":195},[7437],{"type":48,"value":7438},")})",{"type":42,"tag":161,"props":7440,"children":7441},{"style":184},[7442],{"type":48,"value":6888},{"type":42,"tag":161,"props":7444,"children":7445},{"class":163,"line":5057},[7446,7450,7455],{"type":42,"tag":161,"props":7447,"children":7448},{"style":184},[7449],{"type":48,"value":6779},{"type":42,"tag":161,"props":7451,"children":7452},{"style":168},[7453],{"type":48,"value":7454}," \"  \\(.name)  \\(.ratings)\"",{"type":42,"tag":161,"props":7456,"children":7457},{"style":195},[7458],{"type":48,"value":6946},{"type":42,"tag":161,"props":7460,"children":7461},{"class":163,"line":5107},[7462],{"type":42,"tag":161,"props":7463,"children":7464},{"emptyLinePlaceholder":2464},[7465],{"type":48,"value":2467},{"type":42,"tag":161,"props":7467,"children":7468},{"class":163,"line":5169},[7469,7474],{"type":42,"tag":161,"props":7470,"children":7471},{"style":168},[7472],{"type":48,"value":7473},"    \"\\n── span errors ──\"",{"type":42,"tag":161,"props":7475,"children":7476},{"style":168},[7477],{"type":48,"value":380},{"type":42,"tag":161,"props":7479,"children":7480},{"class":163,"line":5248},[7481,7485,7489,7493,7497,7501,7505,7510,7514,7518,7522,7526,7531,7535,7539,7543,7547,7552,7556,7561],{"type":42,"tag":161,"props":7482,"children":7483},{"style":184},[7484],{"type":48,"value":6748},{"type":42,"tag":161,"props":7486,"children":7487},{"style":195},[7488],{"type":48,"value":6753},{"type":42,"tag":161,"props":7490,"children":7491},{"style":184},[7492],{"type":48,"value":5343},{"type":42,"tag":161,"props":7494,"children":7495},{"style":184},[7496],{"type":48,"value":2966},{"type":42,"tag":161,"props":7498,"children":7499},{"style":195},[7500],{"type":48,"value":6989},{"type":42,"tag":161,"props":7502,"children":7503},{"style":184},[7504],{"type":48,"value":6671},{"type":42,"tag":161,"props":7506,"children":7507},{"style":195},[7508],{"type":48,"value":7509},".status ",{"type":42,"tag":161,"props":7511,"children":7512},{"style":184},[7513],{"type":48,"value":7003},{"type":42,"tag":161,"props":7515,"children":7516},{"style":184},[7517],{"type":48,"value":590},{"type":42,"tag":161,"props":7519,"children":7520},{"style":173},[7521],{"type":48,"value":6690},{"type":42,"tag":161,"props":7523,"children":7524},{"style":184},[7525],{"type":48,"value":605},{"type":42,"tag":161,"props":7527,"children":7528},{"style":195},[7529],{"type":48,"value":7530}," and .status ",{"type":42,"tag":161,"props":7532,"children":7533},{"style":184},[7534],{"type":48,"value":7003},{"type":42,"tag":161,"props":7536,"children":7537},{"style":195},[7538],{"type":48,"value":6449},{"type":42,"tag":161,"props":7540,"children":7541},{"style":184},[7542],{"type":48,"value":7021},{"type":42,"tag":161,"props":7544,"children":7545},{"style":184},[7546],{"type":48,"value":2966},{"type":42,"tag":161,"props":7548,"children":7549},{"style":168},[7550],{"type":48,"value":7551}," length",{"type":42,"tag":161,"props":7553,"children":7554},{"style":184},[7555],{"type":48,"value":2966},{"type":42,"tag":161,"props":7557,"children":7558},{"style":168},[7559],{"type":48,"value":7560}," \"  count: \\(.)\"",{"type":42,"tag":161,"props":7562,"children":7563},{"style":184},[7564],{"type":48,"value":678},{"type":42,"tag":161,"props":7566,"children":7567},{"class":163,"line":6173},[7568],{"type":42,"tag":161,"props":7569,"children":7570},{"style":168},[7571],{"type":48,"value":7572},"' \u002Ftmp\u002Ftrace_${TRACE_ID}.json\n",{"type":42,"tag":51,"props":7574,"children":7575},{},[7576],{"type":48,"value":7577},"On a run like 7542817 the output is something like:",{"type":42,"tag":150,"props":7579,"children":7583},{"className":7580,"code":7582,"language":48},[7581],"language-text","── span-name rollup (count · total ms · max ms) ──\n  1     154552   154552  iteration\n  37    153391   17746   navigation\n  11    21778    5168    page.waitForNavigation\n  ...\n\n── slowest spans (ms · name · navigation.url \u002F page.goto.url) ──\n  17746    navigation  https:\u002F\u002Fk6e2etests.grafana-dev.net\u002Fa\u002Fk6-app\u002Fprojects\n  14992    navigation  https:\u002F\u002Fk6e2etests.grafana-dev.net\u002Fa\u002Fk6-app\u002Fprojects\u002F58195\n  ...\n\n── web-vital ratings ──\n  LCP   {\"poor\":5,\"needs-improvement\":1}\n  CLS   {\"good\":2}\n  ...\n",[7584],{"type":42,"tag":57,"props":7585,"children":7586},{"__ignoreMap":155},[7587],{"type":48,"value":7582},{"type":42,"tag":51,"props":7589,"children":7590},{},[7591],{"type":48,"value":7592},"Two paragraphs of text capture which navigations are slow, which\nweb vitals are regressing, and the overall span-name distribution\n— enough to reason about browser performance without paging through\nthe OTLP tree.",{"type":42,"tag":143,"props":7594,"children":7596},{"id":7595},"notes-worth-knowing-1",[7597],{"type":48,"value":5260},{"type":42,"tag":66,"props":7599,"children":7600},{},[7601,7633,7675,7725,7780,7834],{"type":42,"tag":70,"props":7602,"children":7603},{},[7604,7609,7611,7617,7618,7624,7626,7631],{"type":42,"tag":74,"props":7605,"children":7606},{},[7607],{"type":48,"value":7608},"Header is mandatory.",{"type":48,"value":7610}," Both ",{"type":42,"tag":57,"props":7612,"children":7614},{"className":7613},[],[7615],{"type":48,"value":7616},"\u002Fsearch",{"type":48,"value":265},{"type":42,"tag":57,"props":7619,"children":7621},{"className":7620},[],[7622],{"type":48,"value":7623},"\u002Ftraces\u002F\u003Cid>",{"type":48,"value":7625}," return\nHTTP 401 without ",{"type":42,"tag":57,"props":7627,"children":7629},{"className":7628},[],[7630],{"type":48,"value":86},{"type":48,"value":7632},". The header scopes the query to\nthe run's tenant.",{"type":42,"tag":70,"props":7634,"children":7635},{},[7636,7652,7654,7660,7662,7667,7668,7673],{"type":42,"tag":74,"props":7637,"children":7638},{},[7639,7644,7645,7650],{"type":42,"tag":57,"props":7640,"children":7642},{"className":7641},[],[7643],{"type":48,"value":3461},{"type":48,"value":3463},{"type":42,"tag":57,"props":7646,"children":7648},{"className":7647},[],[7649],{"type":48,"value":3469},{"type":48,"value":7651}," are unix seconds.",{"type":48,"value":7653}," RFC3339 ISO strings get\n",{"type":42,"tag":57,"props":7655,"children":7657},{"className":7656},[],[7658],{"type":48,"value":7659},"HTTP 400 invalid start: strconv.ParseUint",{"type":48,"value":7661},". They're technically\noptional — search works without them — but providing a window\nmatching the run's ",{"type":42,"tag":57,"props":7663,"children":7665},{"className":7664},[],[7666],{"type":48,"value":2147},{"type":48,"value":3463},{"type":42,"tag":57,"props":7669,"children":7671},{"className":7670},[],[7672],{"type":48,"value":3483},{"type":48,"value":7674}," (plus ~60s buffer) keeps the\nquery fast and avoids matching unrelated runs that share the\nscenario name.",{"type":42,"tag":70,"props":7676,"children":7677},{},[7678,7683,7685,7691,7693,7699,7701,7707,7709,7715,7717,7723],{"type":42,"tag":74,"props":7679,"children":7680},{},[7681],{"type":48,"value":7682},"TraceQL, not LogQL.",{"type":48,"value":7684}," The ",{"type":42,"tag":57,"props":7686,"children":7688},{"className":7687},[],[7689],{"type":48,"value":7690},"q",{"type":48,"value":7692}," parameter uses TraceQL — span\npredicates are written as ",{"type":42,"tag":57,"props":7694,"children":7696},{"className":7695},[],[7697],{"type":48,"value":7698},"span.\u003Cattribute>",{"type":48,"value":7700}," and combined with\n",{"type":42,"tag":57,"props":7702,"children":7704},{"className":7703},[],[7705],{"type":48,"value":7706},"&&",{"type":48,"value":7708},". The suggested query filters iteration root spans for a\nspecific scenario; broaden by dropping ",{"type":42,"tag":57,"props":7710,"children":7712},{"className":7711},[],[7713],{"type":48,"value":7714},"test.scenario",{"type":48,"value":7716},", narrow by\nadding e.g. ",{"type":42,"tag":57,"props":7718,"children":7720},{"className":7719},[],[7721],{"type":48,"value":7722},"span.test.vu = 3 && span.test.iteration.number = 5",{"type":48,"value":7724},"\nto pinpoint a single iteration on a single VU.",{"type":42,"tag":70,"props":7726,"children":7727},{},[7728,7733,7735,7740,7742,7748,7750,7756,7758,7764,7766,7771,7772,7778],{"type":42,"tag":74,"props":7729,"children":7730},{},[7731],{"type":48,"value":7732},"Scenario names come from the run.",{"type":48,"value":7734}," They're the ",{"type":42,"tag":274,"props":7736,"children":7737},{},[7738],{"type":48,"value":7739},"keys",{"type":48,"value":7741}," of\n",{"type":42,"tag":57,"props":7743,"children":7745},{"className":7744},[],[7746],{"type":48,"value":7747},".options.scenarios",{"type":48,"value":7749}," on the run object —\n",{"type":42,"tag":57,"props":7751,"children":7753},{"className":7752},[],[7754],{"type":48,"value":7755},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Ftest_runs\u002F$RUN_ID --json options 2>\u002Fdev\u002Fnull | jq -r '.options.scenarios | keys[]'",{"type":48,"value":7757},"\nlists them. The default scenario is named ",{"type":42,"tag":57,"props":7759,"children":7761},{"className":7760},[],[7762],{"type":48,"value":7763},"default",{"type":48,"value":7765},"; browser tests\noften name it ",{"type":42,"tag":57,"props":7767,"children":7769},{"className":7768},[],[7770],{"type":48,"value":5713},{"type":48,"value":365},{"type":42,"tag":57,"props":7773,"children":7775},{"className":7774},[],[7776],{"type":48,"value":7777},"browser",{"type":48,"value":7779},", etc.",{"type":42,"tag":70,"props":7781,"children":7782},{},[7783,7788,7789,7795,7797,7802,7804,7810,7811,7817,7818,7824,7826,7832],{"type":42,"tag":74,"props":7784,"children":7785},{},[7786],{"type":48,"value":7787},"Span IDs in the OTLP body are base64.",{"type":48,"value":7684},{"type":42,"tag":57,"props":7790,"children":7792},{"className":7791},[],[7793],{"type":48,"value":7794},"traceID",{"type":48,"value":7796}," in the\nsearch response is hex (the form ",{"type":42,"tag":57,"props":7798,"children":7800},{"className":7799},[],[7801],{"type":48,"value":7623},{"type":48,"value":7803}," accepts); the\ninner ",{"type":42,"tag":57,"props":7805,"children":7807},{"className":7806},[],[7808],{"type":48,"value":7809},"traceId",{"type":48,"value":3463},{"type":42,"tag":57,"props":7812,"children":7814},{"className":7813},[],[7815],{"type":48,"value":7816},"spanId",{"type":48,"value":3463},{"type":42,"tag":57,"props":7819,"children":7821},{"className":7820},[],[7822],{"type":48,"value":7823},"parentSpanId",{"type":48,"value":7825}," fields inside the OTLP\nbatch are base64-encoded bytes. Cross-correlate parent\u002Fchild via\n",{"type":42,"tag":57,"props":7827,"children":7829},{"className":7828},[],[7830],{"type":48,"value":7831},"parentSpanId == spanId",{"type":48,"value":7833},", both in base64 — no need to decode.",{"type":42,"tag":70,"props":7835,"children":7836},{},[7837,7842,7844,7849,7850,7855,7856,7862,7863,7868,7869,7874,7875,7880,7881,7886,7887,7893,7894,7900,7901,7907,7909,7915,7917,7923],{"type":42,"tag":74,"props":7838,"children":7839},{},[7840],{"type":48,"value":7841},"Useful attribute keys",{"type":48,"value":7843}," on browser-test spans: ",{"type":42,"tag":57,"props":7845,"children":7847},{"className":7846},[],[7848],{"type":48,"value":7078},{"type":48,"value":380},{"type":42,"tag":57,"props":7851,"children":7853},{"className":7852},[],[7854],{"type":48,"value":7096},{"type":48,"value":365},{"type":42,"tag":57,"props":7857,"children":7859},{"className":7858},[],[7860],{"type":48,"value":7861},"screenshot.path",{"type":48,"value":365},{"type":42,"tag":57,"props":7864,"children":7866},{"className":7865},[],[7867],{"type":48,"value":7268},{"type":48,"value":380},{"type":42,"tag":57,"props":7870,"children":7872},{"className":7871},[],[7873],{"type":48,"value":7294},{"type":48,"value":365},{"type":42,"tag":57,"props":7876,"children":7878},{"className":7877},[],[7879],{"type":48,"value":7320},{"type":48,"value":365},{"type":42,"tag":57,"props":7882,"children":7884},{"className":7883},[],[7885],{"type":48,"value":7714},{"type":48,"value":365},{"type":42,"tag":57,"props":7888,"children":7890},{"className":7889},[],[7891],{"type":48,"value":7892},"test.vu",{"type":48,"value":380},{"type":42,"tag":57,"props":7895,"children":7897},{"className":7896},[],[7898],{"type":48,"value":7899},"test.iteration.number",{"type":48,"value":365},{"type":42,"tag":57,"props":7902,"children":7904},{"className":7903},[],[7905],{"type":48,"value":7906},"k6.test_run_id",{"type":48,"value":7908},". These are the ones\nworth surfacing in summaries; the OTel value envelope is\n",{"type":42,"tag":57,"props":7910,"children":7912},{"className":7911},[],[7913],{"type":48,"value":7914},"{stringValue|intValue|boolValue|doubleValue}",{"type":48,"value":7916}," (the jq\n",{"type":42,"tag":57,"props":7918,"children":7920},{"className":7919},[],[7921],{"type":48,"value":7922},"attrval",{"type":48,"value":7924}," helper above handles all four).",{"type":42,"tag":132,"props":7926,"children":7927},{},[],{"type":42,"tag":136,"props":7929,"children":7931},{"id":7930},"_8-cloud-insights-audit-results-for-a-run",[7932],{"type":48,"value":7933},"8. Cloud Insights (audit results for a run)",{"type":42,"tag":51,"props":7935,"children":7936},{},[7937,7939,7945,7947,7952],{"type":48,"value":7938},"Cloud Insights runs heuristics against a finished test — checks for\nhigh cardinality, web-vital regressions, missing thresholds,\noverutilised load generators, and so on — and exposes the results\nthrough a separate ",{"type":42,"tag":57,"props":7940,"children":7942},{"className":7941},[],[7943],{"type":48,"value":7944},"\u002Fresources\u002Finsights\u002F",{"type":48,"value":7946}," plugin route (not\n",{"type":42,"tag":57,"props":7948,"children":7950},{"className":7949},[],[7951],{"type":48,"value":1220},{"type":48,"value":7953},"). gcx still handles auth; no extra header is needed.",{"type":42,"tag":51,"props":7955,"children":7956},{},[7957],{"type":48,"value":7958},"Three calls produce the data, and the agent-useful output is a join\nacross two of them:",{"type":42,"tag":150,"props":7960,"children":7962},{"className":152,"code":7961,"language":154,"meta":155,"style":155},"RUN_ID=\"\u003Crun_id>\"\nBASE=\"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Finsights\u002Finsights\u002Fapi\u002Fv1\u002Ftestrun\u002F$RUN_ID\"\n\n# 1. List executions for the run, take the most recent. The response\n#    is { \"executions\": [ {id, version}, ... ] } — NOT a bare array.\n#    Pick the last entry; insights re-runs append, and the newest one\n#    reflects the current set of audits\u002Fscores.\nEXEC_ID=$(gcx api \"$BASE\u002Fexecutions\" -o json 2>\u002Fdev\u002Fnull \\\n  | jq -r '.executions[-1].id')\n\n# 2. Audit definitions (id, title, description, weight). ~15 items.\ngcx api \"$BASE\u002Fexecutions\u002F$EXEC_ID\u002Faudits\" -o json 2>\u002Fdev\u002Fnull \\\n  > \u002Ftmp\u002Finsights_audits_${RUN_ID}.json\n\n# 3. Audit results (audit_id, status, score, explanation, actions).\ngcx api \"$BASE\u002Fexecutions\u002F$EXEC_ID\u002Faudits\u002Fresults\" -o json 2>\u002Fdev\u002Fnull \\\n  > \u002Ftmp\u002Finsights_results_${RUN_ID}.json\n",[7963],{"type":42,"tag":57,"props":7964,"children":7965},{"__ignoreMap":155},[7966,7989,8018,8025,8033,8041,8049,8057,8115,8147,8154,8162,8220,8248,8255,8263,8319],{"type":42,"tag":161,"props":7967,"children":7968},{"class":163,"line":164},[7969,7973,7977,7981,7985],{"type":42,"tag":161,"props":7970,"children":7971},{"style":195},[7972],{"type":48,"value":2812},{"type":42,"tag":161,"props":7974,"children":7975},{"style":184},[7976],{"type":48,"value":2817},{"type":42,"tag":161,"props":7978,"children":7979},{"style":184},[7980],{"type":48,"value":605},{"type":42,"tag":161,"props":7982,"children":7983},{"style":173},[7984],{"type":48,"value":2826},{"type":42,"tag":161,"props":7986,"children":7987},{"style":184},[7988],{"type":48,"value":2831},{"type":42,"tag":161,"props":7990,"children":7991},{"class":163,"line":212},[7992,7997,8001,8005,8010,8014],{"type":42,"tag":161,"props":7993,"children":7994},{"style":195},[7995],{"type":48,"value":7996},"BASE",{"type":42,"tag":161,"props":7998,"children":7999},{"style":184},[8000],{"type":48,"value":2817},{"type":42,"tag":161,"props":8002,"children":8003},{"style":184},[8004],{"type":48,"value":605},{"type":42,"tag":161,"props":8006,"children":8007},{"style":173},[8008],{"type":48,"value":8009},"\u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Finsights\u002Finsights\u002Fapi\u002Fv1\u002Ftestrun\u002F",{"type":42,"tag":161,"props":8011,"children":8012},{"style":195},[8013],{"type":48,"value":3095},{"type":42,"tag":161,"props":8015,"children":8016},{"style":184},[8017],{"type":48,"value":2831},{"type":42,"tag":161,"props":8019,"children":8020},{"class":163,"line":612},[8021],{"type":42,"tag":161,"props":8022,"children":8023},{"emptyLinePlaceholder":2464},[8024],{"type":48,"value":2467},{"type":42,"tag":161,"props":8026,"children":8027},{"class":163,"line":642},[8028],{"type":42,"tag":161,"props":8029,"children":8030},{"style":206},[8031],{"type":48,"value":8032},"# 1. List executions for the run, take the most recent. The response\n",{"type":42,"tag":161,"props":8034,"children":8035},{"class":163,"line":2486},[8036],{"type":42,"tag":161,"props":8037,"children":8038},{"style":206},[8039],{"type":48,"value":8040},"#    is { \"executions\": [ {id, version}, ... ] } — NOT a bare array.\n",{"type":42,"tag":161,"props":8042,"children":8043},{"class":163,"line":2495},[8044],{"type":42,"tag":161,"props":8045,"children":8046},{"style":206},[8047],{"type":48,"value":8048},"#    Pick the last entry; insights re-runs append, and the newest one\n",{"type":42,"tag":161,"props":8050,"children":8051},{"class":163,"line":2503},[8052],{"type":42,"tag":161,"props":8053,"children":8054},{"style":206},[8055],{"type":48,"value":8056},"#    reflects the current set of audits\u002Fscores.\n",{"type":42,"tag":161,"props":8058,"children":8059},{"class":163,"line":2512},[8060,8065,8069,8073,8077,8081,8086,8091,8095,8099,8103,8107,8111],{"type":42,"tag":161,"props":8061,"children":8062},{"style":195},[8063],{"type":48,"value":8064},"EXEC_ID",{"type":42,"tag":161,"props":8066,"children":8067},{"style":184},[8068],{"type":48,"value":557},{"type":42,"tag":161,"props":8070,"children":8071},{"style":168},[8072],{"type":48,"value":62},{"type":42,"tag":161,"props":8074,"children":8075},{"style":173},[8076],{"type":48,"value":1927},{"type":42,"tag":161,"props":8078,"children":8079},{"style":184},[8080],{"type":48,"value":590},{"type":42,"tag":161,"props":8082,"children":8083},{"style":195},[8084],{"type":48,"value":8085},"$BASE",{"type":42,"tag":161,"props":8087,"children":8088},{"style":173},[8089],{"type":48,"value":8090},"\u002Fexecutions",{"type":42,"tag":161,"props":8092,"children":8093},{"style":184},[8094],{"type":48,"value":605},{"type":42,"tag":161,"props":8096,"children":8097},{"style":173},[8098],{"type":48,"value":4596},{"type":42,"tag":161,"props":8100,"children":8101},{"style":173},[8102],{"type":48,"value":4601},{"type":42,"tag":161,"props":8104,"children":8105},{"style":184},[8106],{"type":48,"value":3262},{"type":42,"tag":161,"props":8108,"children":8109},{"style":173},[8110],{"type":48,"value":2910},{"type":42,"tag":161,"props":8112,"children":8113},{"style":195},[8114],{"type":48,"value":577},{"type":42,"tag":161,"props":8116,"children":8117},{"class":163,"line":2521},[8118,8122,8126,8130,8134,8139,8143],{"type":42,"tag":161,"props":8119,"children":8120},{"style":184},[8121],{"type":48,"value":648},{"type":42,"tag":161,"props":8123,"children":8124},{"style":168},[8125],{"type":48,"value":653},{"type":42,"tag":161,"props":8127,"children":8128},{"style":173},[8129],{"type":48,"value":658},{"type":42,"tag":161,"props":8131,"children":8132},{"style":184},[8133],{"type":48,"value":663},{"type":42,"tag":161,"props":8135,"children":8136},{"style":173},[8137],{"type":48,"value":8138},".executions[-1].id",{"type":42,"tag":161,"props":8140,"children":8141},{"style":184},[8142],{"type":48,"value":673},{"type":42,"tag":161,"props":8144,"children":8145},{"style":184},[8146],{"type":48,"value":678},{"type":42,"tag":161,"props":8148,"children":8149},{"class":163,"line":2530},[8150],{"type":42,"tag":161,"props":8151,"children":8152},{"emptyLinePlaceholder":2464},[8153],{"type":48,"value":2467},{"type":42,"tag":161,"props":8155,"children":8156},{"class":163,"line":2539},[8157],{"type":42,"tag":161,"props":8158,"children":8159},{"style":206},[8160],{"type":48,"value":8161},"# 2. Audit definitions (id, title, description, weight). ~15 items.\n",{"type":42,"tag":161,"props":8163,"children":8164},{"class":163,"line":2548},[8165,8169,8173,8177,8181,8186,8191,8196,8200,8204,8208,8212,8216],{"type":42,"tag":161,"props":8166,"children":8167},{"style":168},[8168],{"type":48,"value":62},{"type":42,"tag":161,"props":8170,"children":8171},{"style":173},[8172],{"type":48,"value":1927},{"type":42,"tag":161,"props":8174,"children":8175},{"style":184},[8176],{"type":48,"value":590},{"type":42,"tag":161,"props":8178,"children":8179},{"style":195},[8180],{"type":48,"value":8085},{"type":42,"tag":161,"props":8182,"children":8183},{"style":173},[8184],{"type":48,"value":8185},"\u002Fexecutions\u002F",{"type":42,"tag":161,"props":8187,"children":8188},{"style":195},[8189],{"type":48,"value":8190},"$EXEC_ID",{"type":42,"tag":161,"props":8192,"children":8193},{"style":173},[8194],{"type":48,"value":8195},"\u002Faudits",{"type":42,"tag":161,"props":8197,"children":8198},{"style":184},[8199],{"type":48,"value":605},{"type":42,"tag":161,"props":8201,"children":8202},{"style":173},[8203],{"type":48,"value":4596},{"type":42,"tag":161,"props":8205,"children":8206},{"style":173},[8207],{"type":48,"value":4601},{"type":42,"tag":161,"props":8209,"children":8210},{"style":184},[8211],{"type":48,"value":3262},{"type":42,"tag":161,"props":8213,"children":8214},{"style":173},[8215],{"type":48,"value":2910},{"type":42,"tag":161,"props":8217,"children":8218},{"style":195},[8219],{"type":48,"value":577},{"type":42,"tag":161,"props":8221,"children":8222},{"class":163,"line":2556},[8223,8227,8232,8236,8240,8244],{"type":42,"tag":161,"props":8224,"children":8225},{"style":184},[8226],{"type":48,"value":3887},{"type":42,"tag":161,"props":8228,"children":8229},{"style":173},[8230],{"type":48,"value":8231}," \u002Ftmp\u002Finsights_audits_",{"type":42,"tag":161,"props":8233,"children":8234},{"style":184},[8235],{"type":48,"value":3177},{"type":42,"tag":161,"props":8237,"children":8238},{"style":195},[8239],{"type":48,"value":2812},{"type":42,"tag":161,"props":8241,"children":8242},{"style":184},[8243],{"type":48,"value":3186},{"type":42,"tag":161,"props":8245,"children":8246},{"style":173},[8247],{"type":48,"value":4635},{"type":42,"tag":161,"props":8249,"children":8250},{"class":163,"line":2565},[8251],{"type":42,"tag":161,"props":8252,"children":8253},{"emptyLinePlaceholder":2464},[8254],{"type":48,"value":2467},{"type":42,"tag":161,"props":8256,"children":8257},{"class":163,"line":2574},[8258],{"type":42,"tag":161,"props":8259,"children":8260},{"style":206},[8261],{"type":48,"value":8262},"# 3. Audit results (audit_id, status, score, explanation, actions).\n",{"type":42,"tag":161,"props":8264,"children":8265},{"class":163,"line":30},[8266,8270,8274,8278,8282,8286,8290,8295,8299,8303,8307,8311,8315],{"type":42,"tag":161,"props":8267,"children":8268},{"style":168},[8269],{"type":48,"value":62},{"type":42,"tag":161,"props":8271,"children":8272},{"style":173},[8273],{"type":48,"value":1927},{"type":42,"tag":161,"props":8275,"children":8276},{"style":184},[8277],{"type":48,"value":590},{"type":42,"tag":161,"props":8279,"children":8280},{"style":195},[8281],{"type":48,"value":8085},{"type":42,"tag":161,"props":8283,"children":8284},{"style":173},[8285],{"type":48,"value":8185},{"type":42,"tag":161,"props":8287,"children":8288},{"style":195},[8289],{"type":48,"value":8190},{"type":42,"tag":161,"props":8291,"children":8292},{"style":173},[8293],{"type":48,"value":8294},"\u002Faudits\u002Fresults",{"type":42,"tag":161,"props":8296,"children":8297},{"style":184},[8298],{"type":48,"value":605},{"type":42,"tag":161,"props":8300,"children":8301},{"style":173},[8302],{"type":48,"value":4596},{"type":42,"tag":161,"props":8304,"children":8305},{"style":173},[8306],{"type":48,"value":4601},{"type":42,"tag":161,"props":8308,"children":8309},{"style":184},[8310],{"type":48,"value":3262},{"type":42,"tag":161,"props":8312,"children":8313},{"style":173},[8314],{"type":48,"value":2910},{"type":42,"tag":161,"props":8316,"children":8317},{"style":195},[8318],{"type":48,"value":577},{"type":42,"tag":161,"props":8320,"children":8321},{"class":163,"line":2591},[8322,8326,8331,8335,8339,8343],{"type":42,"tag":161,"props":8323,"children":8324},{"style":184},[8325],{"type":48,"value":3887},{"type":42,"tag":161,"props":8327,"children":8328},{"style":173},[8329],{"type":48,"value":8330}," \u002Ftmp\u002Finsights_results_",{"type":42,"tag":161,"props":8332,"children":8333},{"style":184},[8334],{"type":48,"value":3177},{"type":42,"tag":161,"props":8336,"children":8337},{"style":195},[8338],{"type":48,"value":2812},{"type":42,"tag":161,"props":8340,"children":8341},{"style":184},[8342],{"type":48,"value":3186},{"type":42,"tag":161,"props":8344,"children":8345},{"style":173},[8346],{"type":48,"value":4635},{"type":42,"tag":51,"props":8348,"children":8349},{},[8350,8352,8358,8360,8365,8367,8373],{"type":48,"value":8351},"Both responses use the same top-level key — ",{"type":42,"tag":57,"props":8353,"children":8355},{"className":8354},[],[8356],{"type":48,"value":8357},"audits",{"type":48,"value":8359}," — but the\n",{"type":42,"tag":274,"props":8361,"children":8362},{},[8363],{"type":48,"value":8364},"contents",{"type":48,"value":8366}," differ: step 2 is the catalog of what each audit checks,\nstep 3 is what that audit found on this particular run. Cross-join\nthem via ",{"type":42,"tag":57,"props":8368,"children":8370},{"className":8369},[],[8371],{"type":48,"value":8372},"result.audit_id == audit.id",{"type":48,"value":8374}," (1:1 in practice).",{"type":42,"tag":143,"props":8376,"children":8378},{"id":8377},"joining-into-a-compact-agent-readable-summary",[8379],{"type":48,"value":8380},"Joining into a compact, agent-readable summary",{"type":42,"tag":51,"props":8382,"children":8383},{},[8384,8386,8391],{"type":48,"value":8385},"The raw audit + results JSON together is ~10 KB. Dumping both into\ncontext just to read out three lines per audit is wasteful — do the\njoin in ",{"type":42,"tag":57,"props":8387,"children":8389},{"className":8388},[],[8390],{"type":48,"value":1421},{"type":48,"value":8392}," and emit a single tight block. The pipeline below is\nthe recommended shape:",{"type":42,"tag":150,"props":8394,"children":8396},{"className":152,"code":8395,"language":154,"meta":155,"style":155},"jq -nr \\\n  --slurpfile a \u002Ftmp\u002Finsights_audits_${RUN_ID}.json \\\n  --slurpfile r \u002Ftmp\u002Finsights_results_${RUN_ID}.json '\n  ($a[0].audits | INDEX(.id)) as $defs\n  | $r[0].audits\n  | map({\n      title:         ($defs[.audit_id].title \u002F\u002F \"?\"),\n      description:   ($defs[.audit_id].description \u002F\u002F \"\"),\n      status:        .status,\n      status_reason: .status_reason,\n      score: (\n        if .score == null            then \"n\u002Fa\"\n        elif .score.type == \"binary\" then (if .score.value then \"pass\" else \"fail\" end)\n        else (.score.value | tostring)\n        end),\n      explanation: (.explanation \u002F\u002F \"\" | gsub(\"\\n+\"; \" \") | .[0:300]),\n      actions:     (.actions \u002F\u002F [])\n    })\n  | .[]\n  | \"── \\(.title) — score: \\(.score)\\(if .status == \"failed\" then \" [audit did not run: \\(.status_reason \u002F\u002F \"unknown\")]\" else \"\" end)\\n  \\(.description)\\n  → \\(.explanation)\\(if (.actions|length) > 0 then \"\\n  actions:\\n    - \" + (.actions|join(\"\\n    - \")) else \"\" end)\\n\"\n'\n",[8397],{"type":42,"tag":57,"props":8398,"children":8399},{"__ignoreMap":155},[8400,8416,8453,8489,8497,8505,8513,8521,8529,8537,8545,8553,8561,8569,8577,8585,8593,8601,8609,8617,8625],{"type":42,"tag":161,"props":8401,"children":8402},{"class":163,"line":164},[8403,8407,8412],{"type":42,"tag":161,"props":8404,"children":8405},{"style":168},[8406],{"type":48,"value":1421},{"type":42,"tag":161,"props":8408,"children":8409},{"style":173},[8410],{"type":48,"value":8411}," -nr",{"type":42,"tag":161,"props":8413,"children":8414},{"style":195},[8415],{"type":48,"value":577},{"type":42,"tag":161,"props":8417,"children":8418},{"class":163,"line":212},[8419,8424,8429,8433,8437,8441,8445,8449],{"type":42,"tag":161,"props":8420,"children":8421},{"style":173},[8422],{"type":48,"value":8423},"  --slurpfile",{"type":42,"tag":161,"props":8425,"children":8426},{"style":173},[8427],{"type":48,"value":8428}," a",{"type":42,"tag":161,"props":8430,"children":8431},{"style":173},[8432],{"type":48,"value":8231},{"type":42,"tag":161,"props":8434,"children":8435},{"style":184},[8436],{"type":48,"value":3177},{"type":42,"tag":161,"props":8438,"children":8439},{"style":195},[8440],{"type":48,"value":2812},{"type":42,"tag":161,"props":8442,"children":8443},{"style":184},[8444],{"type":48,"value":3186},{"type":42,"tag":161,"props":8446,"children":8447},{"style":173},[8448],{"type":48,"value":4752},{"type":42,"tag":161,"props":8450,"children":8451},{"style":195},[8452],{"type":48,"value":577},{"type":42,"tag":161,"props":8454,"children":8455},{"class":163,"line":612},[8456,8460,8465,8469,8473,8477,8481,8485],{"type":42,"tag":161,"props":8457,"children":8458},{"style":173},[8459],{"type":48,"value":8423},{"type":42,"tag":161,"props":8461,"children":8462},{"style":173},[8463],{"type":48,"value":8464}," r",{"type":42,"tag":161,"props":8466,"children":8467},{"style":173},[8468],{"type":48,"value":8330},{"type":42,"tag":161,"props":8470,"children":8471},{"style":184},[8472],{"type":48,"value":3177},{"type":42,"tag":161,"props":8474,"children":8475},{"style":195},[8476],{"type":48,"value":2812},{"type":42,"tag":161,"props":8478,"children":8479},{"style":184},[8480],{"type":48,"value":3186},{"type":42,"tag":161,"props":8482,"children":8483},{"style":173},[8484],{"type":48,"value":4752},{"type":42,"tag":161,"props":8486,"children":8487},{"style":184},[8488],{"type":48,"value":6269},{"type":42,"tag":161,"props":8490,"children":8491},{"class":163,"line":642},[8492],{"type":42,"tag":161,"props":8493,"children":8494},{"style":173},[8495],{"type":48,"value":8496},"  ($a[0].audits | INDEX(.id)) as $defs\n",{"type":42,"tag":161,"props":8498,"children":8499},{"class":163,"line":2486},[8500],{"type":42,"tag":161,"props":8501,"children":8502},{"style":173},[8503],{"type":48,"value":8504},"  | $r[0].audits\n",{"type":42,"tag":161,"props":8506,"children":8507},{"class":163,"line":2495},[8508],{"type":42,"tag":161,"props":8509,"children":8510},{"style":173},[8511],{"type":48,"value":8512},"  | map({\n",{"type":42,"tag":161,"props":8514,"children":8515},{"class":163,"line":2503},[8516],{"type":42,"tag":161,"props":8517,"children":8518},{"style":173},[8519],{"type":48,"value":8520},"      title:         ($defs[.audit_id].title \u002F\u002F \"?\"),\n",{"type":42,"tag":161,"props":8522,"children":8523},{"class":163,"line":2512},[8524],{"type":42,"tag":161,"props":8525,"children":8526},{"style":173},[8527],{"type":48,"value":8528},"      description:   ($defs[.audit_id].description \u002F\u002F \"\"),\n",{"type":42,"tag":161,"props":8530,"children":8531},{"class":163,"line":2521},[8532],{"type":42,"tag":161,"props":8533,"children":8534},{"style":173},[8535],{"type":48,"value":8536},"      status:        .status,\n",{"type":42,"tag":161,"props":8538,"children":8539},{"class":163,"line":2530},[8540],{"type":42,"tag":161,"props":8541,"children":8542},{"style":173},[8543],{"type":48,"value":8544},"      status_reason: .status_reason,\n",{"type":42,"tag":161,"props":8546,"children":8547},{"class":163,"line":2539},[8548],{"type":42,"tag":161,"props":8549,"children":8550},{"style":173},[8551],{"type":48,"value":8552},"      score: (\n",{"type":42,"tag":161,"props":8554,"children":8555},{"class":163,"line":2548},[8556],{"type":42,"tag":161,"props":8557,"children":8558},{"style":173},[8559],{"type":48,"value":8560},"        if .score == null            then \"n\u002Fa\"\n",{"type":42,"tag":161,"props":8562,"children":8563},{"class":163,"line":2556},[8564],{"type":42,"tag":161,"props":8565,"children":8566},{"style":173},[8567],{"type":48,"value":8568},"        elif .score.type == \"binary\" then (if .score.value then \"pass\" else \"fail\" end)\n",{"type":42,"tag":161,"props":8570,"children":8571},{"class":163,"line":2565},[8572],{"type":42,"tag":161,"props":8573,"children":8574},{"style":173},[8575],{"type":48,"value":8576},"        else (.score.value | tostring)\n",{"type":42,"tag":161,"props":8578,"children":8579},{"class":163,"line":2574},[8580],{"type":42,"tag":161,"props":8581,"children":8582},{"style":173},[8583],{"type":48,"value":8584},"        end),\n",{"type":42,"tag":161,"props":8586,"children":8587},{"class":163,"line":30},[8588],{"type":42,"tag":161,"props":8589,"children":8590},{"style":173},[8591],{"type":48,"value":8592},"      explanation: (.explanation \u002F\u002F \"\" | gsub(\"\\n+\"; \" \") | .[0:300]),\n",{"type":42,"tag":161,"props":8594,"children":8595},{"class":163,"line":2591},[8596],{"type":42,"tag":161,"props":8597,"children":8598},{"style":173},[8599],{"type":48,"value":8600},"      actions:     (.actions \u002F\u002F [])\n",{"type":42,"tag":161,"props":8602,"children":8603},{"class":163,"line":2600},[8604],{"type":42,"tag":161,"props":8605,"children":8606},{"style":173},[8607],{"type":48,"value":8608},"    })\n",{"type":42,"tag":161,"props":8610,"children":8611},{"class":163,"line":2609},[8612],{"type":42,"tag":161,"props":8613,"children":8614},{"style":173},[8615],{"type":48,"value":8616},"  | .[]\n",{"type":42,"tag":161,"props":8618,"children":8619},{"class":163,"line":2618},[8620],{"type":42,"tag":161,"props":8621,"children":8622},{"style":173},[8623],{"type":48,"value":8624},"  | \"── \\(.title) — score: \\(.score)\\(if .status == \"failed\" then \" [audit did not run: \\(.status_reason \u002F\u002F \"unknown\")]\" else \"\" end)\\n  \\(.description)\\n  → \\(.explanation)\\(if (.actions|length) > 0 then \"\\n  actions:\\n    - \" + (.actions|join(\"\\n    - \")) else \"\" end)\\n\"\n",{"type":42,"tag":161,"props":8626,"children":8627},{"class":163,"line":2627},[8628],{"type":42,"tag":161,"props":8629,"children":8630},{"style":184},[8631],{"type":48,"value":8632},"'\n",{"type":42,"tag":51,"props":8634,"children":8635},{},[8636],{"type":48,"value":8637},"For a 15-audit run this emits ~5 KB of plain text — title, score,\none-line description, one-line explanation, and any action items.\nThat's enough for the agent to reason about the test's health\nwithout re-reading either JSON blob.",{"type":42,"tag":143,"props":8639,"children":8641},{"id":8640},"notes-worth-knowing-2",[8642],{"type":48,"value":5260},{"type":42,"tag":66,"props":8644,"children":8645},{},[8646,8722,8747,8778,8795],{"type":42,"tag":70,"props":8647,"children":8648},{},[8649,8660,8661,8667,8669,8674,8676,8682,8683,8689,8691,8697,8699,8705,8707,8713,8715,8720],{"type":42,"tag":74,"props":8650,"children":8651},{},[8652,8658],{"type":42,"tag":57,"props":8653,"children":8655},{"className":8654},[],[8656],{"type":48,"value":8657},"status",{"type":48,"value":8659}," ≠ verdict.",{"type":48,"value":1775},{"type":42,"tag":57,"props":8662,"children":8664},{"className":8663},[],[8665],{"type":48,"value":8666},"status: \"succeeded\"",{"type":48,"value":8668}," means ",{"type":42,"tag":274,"props":8670,"children":8671},{},[8672],{"type":48,"value":8673},"the audit\nexecuted",{"type":48,"value":8675},". The verdict lives in ",{"type":42,"tag":57,"props":8677,"children":8679},{"className":8678},[],[8680],{"type":48,"value":8681},"score",{"type":48,"value":1069},{"type":42,"tag":57,"props":8684,"children":8686},{"className":8685},[],[8687],{"type":48,"value":8688},"binary",{"type":48,"value":8690}," true\u002Ffalse, or\n",{"type":42,"tag":57,"props":8692,"children":8694},{"className":8693},[],[8695],{"type":48,"value":8696},"numeric",{"type":48,"value":8698}," 0…1 where 1 is best). ",{"type":42,"tag":57,"props":8700,"children":8702},{"className":8701},[],[8703],{"type":48,"value":8704},"status: \"failed\"",{"type":48,"value":8706}," means the audit\nitself could not run (typically ",{"type":42,"tag":57,"props":8708,"children":8710},{"className":8709},[],[8711],{"type":48,"value":8712},"status_reason: \"missing data\"",{"type":48,"value":8714}," —\ne.g. the HTTP Spans audit on a non-tracing test); the ",{"type":42,"tag":57,"props":8716,"children":8718},{"className":8717},[],[8719],{"type":48,"value":8681},{"type":48,"value":8721}," field\nis absent. Treat these as \"no signal\", not as failures.",{"type":42,"tag":70,"props":8723,"children":8724},{},[8725,8730,8732,8737,8739,8745],{"type":42,"tag":74,"props":8726,"children":8727},{},[8728],{"type":48,"value":8729},"Score thresholds vary per audit.",{"type":48,"value":8731}," A ",{"type":42,"tag":57,"props":8733,"children":8735},{"className":8734},[],[8736],{"type":48,"value":8696},{"type":48,"value":8738}," 0.94 might be\nfine for one audit and concerning for another — there's no global\ncutoff. The ",{"type":42,"tag":57,"props":8740,"children":8742},{"className":8741},[],[8743],{"type":48,"value":8744},"explanation",{"type":48,"value":8746}," is authoritative for what the score\nmeans; surface it verbatim rather than inventing a pass\u002Ffail rule.",{"type":42,"tag":70,"props":8748,"children":8749},{},[8750,8761,8763,8769,8771,8776],{"type":42,"tag":74,"props":8751,"children":8752},{},[8753,8759],{"type":42,"tag":57,"props":8754,"children":8756},{"className":8755},[],[8757],{"type":48,"value":8758},"actions",{"type":48,"value":8760}," is the actionable bit.",{"type":48,"value":8762}," Only present when the audit\nhas concrete recommendations (e.g. \"Reduce the cardinality of the\n",{"type":42,"tag":57,"props":8764,"children":8766},{"className":8765},[],[8767],{"type":48,"value":8768},"url",{"type":48,"value":8770}," label …\"). When summarising a run for a user who's trying to\nimprove it, lead with audits that have a non-empty ",{"type":42,"tag":57,"props":8772,"children":8774},{"className":8773},[],[8775],{"type":48,"value":8758},{"type":48,"value":8777}," array.",{"type":42,"tag":70,"props":8779,"children":8780},{},[8781,8786,8787,8793],{"type":42,"tag":74,"props":8782,"children":8783},{},[8784],{"type":48,"value":8785},"Pick the last execution, not the first.",{"type":48,"value":1775},{"type":42,"tag":57,"props":8788,"children":8790},{"className":8789},[],[8791],{"type":48,"value":8792},".executions[]",{"type":48,"value":8794}," is in\nchronological order; re-runs append. Older executions reflect\nolder audit logic and may have stale results.",{"type":42,"tag":70,"props":8796,"children":8797},{},[8798,8803,8805,8811],{"type":42,"tag":74,"props":8799,"children":8800},{},[8801],{"type":48,"value":8802},"Insights is a post-run analysis.",{"type":48,"value":8804}," If the run hasn't finished\n(or never produced enough data for insights to compute), the\nexecutions list may be empty — bail out gracefully on\n",{"type":42,"tag":57,"props":8806,"children":8808},{"className":8807},[],[8809],{"type":48,"value":8810},"length == 0",{"type":48,"value":288},{"type":42,"tag":132,"props":8813,"children":8814},{},[],{"type":42,"tag":136,"props":8816,"children":8818},{"id":8817},"_9-local-k6-cli-smoke-tests-and-k6-cloud-run",[8819,8821,8827],{"type":48,"value":8820},"9. Local k6 CLI (smoke tests and ",{"type":42,"tag":57,"props":8822,"children":8824},{"className":8823},[],[8825],{"type":48,"value":8826},"k6 cloud run",{"type":48,"value":2777},{"type":42,"tag":51,"props":8829,"children":8830},{},[8831,8833,8838],{"type":48,"value":8832},"The local ",{"type":42,"tag":57,"props":8834,"children":8836},{"className":8835},[],[8837],{"type":48,"value":3800},{"type":48,"value":8839}," CLI is the right tool for parse checks and 1-iteration\nsmoke runs before pushing to cloud:",{"type":42,"tag":150,"props":8841,"children":8843},{"className":152,"code":8842,"language":154,"meta":155,"style":155},"k6 inspect script.js | head -20      # parse-only sanity\nk6 run --quiet script.js             # run locally\n",[8844],{"type":42,"tag":57,"props":8845,"children":8846},{"__ignoreMap":155},[8847,8881],{"type":42,"tag":161,"props":8848,"children":8849},{"class":163,"line":164},[8850,8854,8858,8863,8867,8871,8876],{"type":42,"tag":161,"props":8851,"children":8852},{"style":168},[8853],{"type":48,"value":3800},{"type":42,"tag":161,"props":8855,"children":8856},{"style":173},[8857],{"type":48,"value":4133},{"type":42,"tag":161,"props":8859,"children":8860},{"style":173},[8861],{"type":48,"value":8862}," script.js",{"type":42,"tag":161,"props":8864,"children":8865},{"style":184},[8866],{"type":48,"value":2966},{"type":42,"tag":161,"props":8868,"children":8869},{"style":168},[8870],{"type":48,"value":4147},{"type":42,"tag":161,"props":8872,"children":8873},{"style":173},[8874],{"type":48,"value":8875}," -20",{"type":42,"tag":161,"props":8877,"children":8878},{"style":206},[8879],{"type":48,"value":8880},"      # parse-only sanity\n",{"type":42,"tag":161,"props":8882,"children":8883},{"class":163,"line":212},[8884,8888,8892,8896,8900],{"type":42,"tag":161,"props":8885,"children":8886},{"style":168},[8887],{"type":48,"value":3800},{"type":42,"tag":161,"props":8889,"children":8890},{"style":173},[8891],{"type":48,"value":4213},{"type":42,"tag":161,"props":8893,"children":8894},{"style":173},[8895],{"type":48,"value":4218},{"type":42,"tag":161,"props":8897,"children":8898},{"style":173},[8899],{"type":48,"value":8862},{"type":42,"tag":161,"props":8901,"children":8902},{"style":206},[8903],{"type":48,"value":8904},"             # run locally\n",{"type":42,"tag":51,"props":8906,"children":8907},{},[8908,8910,8915,8917,8923,8925,8930,8932,8938],{"type":48,"value":8909},"For ",{"type":42,"tag":57,"props":8911,"children":8913},{"className":8912},[],[8914],{"type":48,"value":8826},{"type":48,"value":8916}," (uploads + runs in cloud from your laptop), authenticate\n",{"type":42,"tag":57,"props":8918,"children":8920},{"className":8919},[],[8921],{"type":48,"value":8922},"k6 cloud login",{"type":48,"value":8924}," with the token and stack URL pulled from gcx — token\ncomes from ",{"type":42,"tag":57,"props":8926,"children":8928},{"className":8927},[],[8929],{"type":48,"value":471},{"type":48,"value":8931},", stack URL from the active gcx context's\n",{"type":42,"tag":57,"props":8933,"children":8935},{"className":8934},[],[8936],{"type":48,"value":8937},"grafana.server",{"type":48,"value":8939}," field:",{"type":42,"tag":150,"props":8941,"children":8943},{"className":152,"code":8942,"language":154,"meta":155,"style":155},"TOKEN=$(gcx --context \u003Cctx> k6 auth token)\nSTACK=$(gcx --context \u003Cctx> config view --minify -o json | jq -r '.contexts[].grafana.server')\nk6 cloud login --token \"$TOKEN\" --stack \"$STACK\"\nk6 cloud run script.js\n",[8944],{"type":42,"tag":57,"props":8945,"children":8946},{"__ignoreMap":155},[8947,9002,9089,9141],{"type":42,"tag":161,"props":8948,"children":8949},{"class":163,"line":164},[8950,8955,8959,8963,8967,8971,8975,8979,8983,8988,8993,8998],{"type":42,"tag":161,"props":8951,"children":8952},{"style":195},[8953],{"type":48,"value":8954},"TOKEN",{"type":42,"tag":161,"props":8956,"children":8957},{"style":184},[8958],{"type":48,"value":557},{"type":42,"tag":161,"props":8960,"children":8961},{"style":168},[8962],{"type":48,"value":62},{"type":42,"tag":161,"props":8964,"children":8965},{"style":173},[8966],{"type":48,"value":181},{"type":42,"tag":161,"props":8968,"children":8969},{"style":184},[8970],{"type":48,"value":187},{"type":42,"tag":161,"props":8972,"children":8973},{"style":173},[8974],{"type":48,"value":192},{"type":42,"tag":161,"props":8976,"children":8977},{"style":195},[8978],{"type":48,"value":198},{"type":42,"tag":161,"props":8980,"children":8981},{"style":184},[8982],{"type":48,"value":203},{"type":42,"tag":161,"props":8984,"children":8985},{"style":173},[8986],{"type":48,"value":8987}," k6",{"type":42,"tag":161,"props":8989,"children":8990},{"style":173},[8991],{"type":48,"value":8992}," auth",{"type":42,"tag":161,"props":8994,"children":8995},{"style":173},[8996],{"type":48,"value":8997}," token",{"type":42,"tag":161,"props":8999,"children":9000},{"style":184},[9001],{"type":48,"value":678},{"type":42,"tag":161,"props":9003,"children":9004},{"class":163,"line":212},[9005,9010,9014,9018,9022,9026,9030,9034,9038,9042,9047,9052,9056,9060,9064,9068,9072,9076,9081,9085],{"type":42,"tag":161,"props":9006,"children":9007},{"style":195},[9008],{"type":48,"value":9009},"STACK",{"type":42,"tag":161,"props":9011,"children":9012},{"style":184},[9013],{"type":48,"value":557},{"type":42,"tag":161,"props":9015,"children":9016},{"style":168},[9017],{"type":48,"value":62},{"type":42,"tag":161,"props":9019,"children":9020},{"style":173},[9021],{"type":48,"value":181},{"type":42,"tag":161,"props":9023,"children":9024},{"style":184},[9025],{"type":48,"value":187},{"type":42,"tag":161,"props":9027,"children":9028},{"style":173},[9029],{"type":48,"value":192},{"type":42,"tag":161,"props":9031,"children":9032},{"style":195},[9033],{"type":48,"value":198},{"type":42,"tag":161,"props":9035,"children":9036},{"style":184},[9037],{"type":48,"value":203},{"type":42,"tag":161,"props":9039,"children":9040},{"style":173},[9041],{"type":48,"value":242},{"type":42,"tag":161,"props":9043,"children":9044},{"style":173},[9045],{"type":48,"value":9046}," view",{"type":42,"tag":161,"props":9048,"children":9049},{"style":173},[9050],{"type":48,"value":9051}," --minify",{"type":42,"tag":161,"props":9053,"children":9054},{"style":173},[9055],{"type":48,"value":4596},{"type":42,"tag":161,"props":9057,"children":9058},{"style":173},[9059],{"type":48,"value":4601},{"type":42,"tag":161,"props":9061,"children":9062},{"style":184},[9063],{"type":48,"value":2966},{"type":42,"tag":161,"props":9065,"children":9066},{"style":168},[9067],{"type":48,"value":653},{"type":42,"tag":161,"props":9069,"children":9070},{"style":173},[9071],{"type":48,"value":658},{"type":42,"tag":161,"props":9073,"children":9074},{"style":184},[9075],{"type":48,"value":663},{"type":42,"tag":161,"props":9077,"children":9078},{"style":173},[9079],{"type":48,"value":9080},".contexts[].grafana.server",{"type":42,"tag":161,"props":9082,"children":9083},{"style":184},[9084],{"type":48,"value":673},{"type":42,"tag":161,"props":9086,"children":9087},{"style":184},[9088],{"type":48,"value":678},{"type":42,"tag":161,"props":9090,"children":9091},{"class":163,"line":612},[9092,9096,9101,9105,9110,9114,9119,9123,9128,9132,9137],{"type":42,"tag":161,"props":9093,"children":9094},{"style":168},[9095],{"type":48,"value":3800},{"type":42,"tag":161,"props":9097,"children":9098},{"style":173},[9099],{"type":48,"value":9100}," cloud",{"type":42,"tag":161,"props":9102,"children":9103},{"style":173},[9104],{"type":48,"value":176},{"type":42,"tag":161,"props":9106,"children":9107},{"style":173},[9108],{"type":48,"value":9109}," --token",{"type":42,"tag":161,"props":9111,"children":9112},{"style":184},[9113],{"type":48,"value":590},{"type":42,"tag":161,"props":9115,"children":9116},{"style":195},[9117],{"type":48,"value":9118},"$TOKEN",{"type":42,"tag":161,"props":9120,"children":9121},{"style":184},[9122],{"type":48,"value":605},{"type":42,"tag":161,"props":9124,"children":9125},{"style":173},[9126],{"type":48,"value":9127}," --stack",{"type":42,"tag":161,"props":9129,"children":9130},{"style":184},[9131],{"type":48,"value":590},{"type":42,"tag":161,"props":9133,"children":9134},{"style":195},[9135],{"type":48,"value":9136},"$STACK",{"type":42,"tag":161,"props":9138,"children":9139},{"style":184},[9140],{"type":48,"value":2831},{"type":42,"tag":161,"props":9142,"children":9143},{"class":163,"line":642},[9144,9148,9152,9156],{"type":42,"tag":161,"props":9145,"children":9146},{"style":168},[9147],{"type":48,"value":3800},{"type":42,"tag":161,"props":9149,"children":9150},{"style":173},[9151],{"type":48,"value":9100},{"type":42,"tag":161,"props":9153,"children":9154},{"style":173},[9155],{"type":48,"value":4213},{"type":42,"tag":161,"props":9157,"children":9158},{"style":173},[9159],{"type":48,"value":9160}," script.js\n",{"type":42,"tag":51,"props":9162,"children":9163},{},[9164,9166,9172,9174,9179,9181,9186],{"type":48,"value":9165},"k6's cloud config (",{"type":42,"tag":57,"props":9167,"children":9169},{"className":9168},[],[9170],{"type":48,"value":9171},"~\u002F.config\u002Fk6\u002Fcloud.json",{"type":48,"value":9173},") is single-context, so\nre-run ",{"type":42,"tag":57,"props":9175,"children":9177},{"className":9176},[],[9178],{"type":48,"value":8922},{"type":48,"value":9180}," whenever you switch gcx contexts — otherwise\n",{"type":42,"tag":57,"props":9182,"children":9184},{"className":9183},[],[9185],{"type":48,"value":8826},{"type":48,"value":9187}," will keep targeting the previous stack.",{"type":42,"tag":51,"props":9189,"children":9190},{},[9191,9193,9199,9201,9207],{"type":48,"value":9192},"Exit codes: ",{"type":42,"tag":57,"props":9194,"children":9196},{"className":9195},[],[9197],{"type":48,"value":9198},"0",{"type":48,"value":9200}," pass, ",{"type":42,"tag":57,"props":9202,"children":9204},{"className":9203},[],[9205],{"type":48,"value":9206},"99",{"type":48,"value":9208}," threshold fail, anything else = script\u002Fruntime error.",{"type":42,"tag":132,"props":9210,"children":9211},{},[],{"type":42,"tag":136,"props":9213,"children":9215},{"id":9214},"_10-gotchas",[9216],{"type":48,"value":9217},"10. Gotchas",{"type":42,"tag":728,"props":9219,"children":9220},{},[9221,9242],{"type":42,"tag":732,"props":9222,"children":9223},{},[9224],{"type":42,"tag":736,"props":9225,"children":9226},{},[9227,9232,9237],{"type":42,"tag":740,"props":9228,"children":9229},{},[9230],{"type":48,"value":9231},"Symptom",{"type":42,"tag":740,"props":9233,"children":9234},{},[9235],{"type":48,"value":9236},"Cause",{"type":42,"tag":740,"props":9238,"children":9239},{},[9240],{"type":48,"value":9241},"Fix",{"type":42,"tag":751,"props":9243,"children":9244},{},[9245,9270,9307,9356,9380,9430,9461,9524,9602,9656,9705,9773],{"type":42,"tag":736,"props":9246,"children":9247},{},[9248,9257,9262],{"type":42,"tag":758,"props":9249,"children":9250},{},[9251],{"type":42,"tag":57,"props":9252,"children":9254},{"className":9253},[],[9255],{"type":48,"value":9256},"401 \"Invalid or expired token — run gcx login to refresh\"",{"type":42,"tag":758,"props":9258,"children":9259},{},[9260],{"type":48,"value":9261},"gcx OAuth session expired",{"type":42,"tag":758,"props":9263,"children":9264},{},[9265],{"type":42,"tag":57,"props":9266,"children":9268},{"className":9267},[],[9269],{"type":48,"value":286},{"type":42,"tag":736,"props":9271,"children":9272},{},[9273,9284,9296],{"type":42,"tag":758,"props":9274,"children":9275},{},[9276,9282],{"type":42,"tag":57,"props":9277,"children":9279},{"className":9278},[],[9280],{"type":48,"value":9281},"403 \u002F 404",{"type":48,"value":9283}," on a path that looks right",{"type":42,"tag":758,"props":9285,"children":9286},{},[9287,9289,9294],{"type":48,"value":9288},"Forgot the doubled ",{"type":42,"tag":57,"props":9290,"children":9292},{"className":9291},[],[9293],{"type":48,"value":429},{"type":48,"value":9295}," for a REST endpoint",{"type":42,"tag":758,"props":9297,"children":9298},{},[9299,9301],{"type":48,"value":9300},"Use ",{"type":42,"tag":57,"props":9302,"children":9304},{"className":9303},[],[9305],{"type":48,"value":9306},"…\u002Fresources\u002Fcloud\u002Fcloud\u002Fv{N}\u002F…",{"type":42,"tag":736,"props":9308,"children":9309},{},[9310,9321,9331],{"type":42,"tag":758,"props":9311,"children":9312},{},[9313,9319],{"type":42,"tag":57,"props":9314,"children":9316},{"className":9315},[],[9317],{"type":48,"value":9318},"415 unsupported media type",{"type":48,"value":9320}," on script PUT",{"type":42,"tag":758,"props":9322,"children":9323},{},[9324,9326],{"type":48,"value":9325},"Missing ",{"type":42,"tag":57,"props":9327,"children":9329},{"className":9328},[],[9330],{"type":48,"value":4434},{"type":42,"tag":758,"props":9332,"children":9333},{},[9334,9336,9341,9342,9347,9349,9354],{"type":48,"value":9335},"Add it; pass ",{"type":42,"tag":57,"props":9337,"children":9339},{"className":9338},[],[9340],{"type":48,"value":4442},{"type":48,"value":1389},{"type":42,"tag":57,"props":9343,"children":9345},{"className":9344},[],[9346],{"type":48,"value":1796},{"type":48,"value":9348},") to ",{"type":42,"tag":57,"props":9350,"children":9352},{"className":9351},[],[9353],{"type":48,"value":128},{"type":48,"value":9355}," to inspect the request",{"type":42,"tag":736,"props":9357,"children":9358},{},[9359,9364,9375],{"type":42,"tag":758,"props":9360,"children":9361},{},[9362],{"type":48,"value":9363},"Script PUT returns 200 but doesn't take effect",{"type":42,"tag":758,"props":9365,"children":9366},{},[9367,9373],{"type":42,"tag":57,"props":9368,"children":9370},{"className":9369},[],[9371],{"type":48,"value":9372},"updated",{"type":48,"value":9374}," timestamp does not bump on script change",{"type":42,"tag":758,"props":9376,"children":9377},{},[9378],{"type":48,"value":9379},"Verify by sha256 of GET (§5 step 7)",{"type":42,"tag":736,"props":9381,"children":9382},{},[9383,9396,9409],{"type":42,"tag":758,"props":9384,"children":9385},{},[9386,9388,9394],{"type":48,"value":9387},"Run status ",{"type":42,"tag":57,"props":9389,"children":9391},{"className":9390},[],[9392],{"type":48,"value":9393},"passed",{"type":48,"value":9395}," but checks failed",{"type":42,"tag":758,"props":9397,"children":9398},{},[9399,9401,9407],{"type":48,"value":9400},"Zero-observation thresholds report as pass; ",{"type":42,"tag":57,"props":9402,"children":9404},{"className":9403},[],[9405],{"type":48,"value":9406},"check()",{"type":48,"value":9408}," alone never fails a run",{"type":42,"tag":758,"props":9410,"children":9411},{},[9412,9414,9420,9422,9428],{"type":48,"value":9413},"Add ",{"type":42,"tag":57,"props":9415,"children":9417},{"className":9416},[],[9418],{"type":48,"value":9419},"'checks{check:\u003Cname>}': ['rate==1.0']",{"type":48,"value":9421},"; in catch blocks, ",{"type":42,"tag":57,"props":9423,"children":9425},{"className":9424},[],[9426],{"type":48,"value":9427},"check(null, {\"script completed\":()=>false})",{"type":48,"value":9429}," to force an observation",{"type":42,"tag":736,"props":9431,"children":9432},{},[9433,9438,9448],{"type":42,"tag":758,"props":9434,"children":9435},{},[9436],{"type":48,"value":9437},"Loki query returns nothing for a recent run",{"type":42,"tag":758,"props":9439,"children":9440},{},[9441,9446],{"type":42,"tag":57,"props":9442,"children":9444},{"className":9443},[],[9445],{"type":48,"value":86},{"type":48,"value":9447}," header missing",{"type":42,"tag":758,"props":9449,"children":9450},{},[9451,9453,9459],{"type":48,"value":9452},"Always pass ",{"type":42,"tag":57,"props":9454,"children":9456},{"className":9455},[],[9457],{"type":48,"value":9458},"-H \"X-K6TestRun-Id: \u003Crun_id>\"",{"type":48,"value":9460}," on log queries",{"type":42,"tag":736,"props":9462,"children":9463},{},[9464,9480,9500],{"type":42,"tag":758,"props":9465,"children":9466},{},[9467,9472,9474,9478],{"type":42,"tag":57,"props":9468,"children":9470},{"className":9469},[],[9471],{"type":48,"value":2247},{"type":48,"value":9473}," returns the ",{"type":42,"tag":74,"props":9475,"children":9476},{},[9477],{"type":48,"value":2262},{"type":48,"value":9479}," 1000 rows, not the newest",{"type":42,"tag":758,"props":9481,"children":9482},{},[9483,9485,9490,9492,9498],{"type":48,"value":9484},"Subcommand doesn't follow ",{"type":42,"tag":57,"props":9486,"children":9488},{"className":9487},[],[9489],{"type":48,"value":1011},{"type":48,"value":9491}," and defaults to ascending order — for >1000 runs the ",{"type":42,"tag":57,"props":9493,"children":9495},{"className":9494},[],[9496],{"type":48,"value":9497},"first\u002Flast",{"type":48,"value":9499}," you see are the start of the history, not the recent activity",{"type":42,"tag":758,"props":9501,"children":9502},{},[9503,9504,9509,9510,9515,9517,9522],{"type":48,"value":9300},{"type":42,"tag":57,"props":9505,"children":9507},{"className":9506},[],[9508],{"type":48,"value":128},{"type":48,"value":3498},{"type":42,"tag":57,"props":9511,"children":9513},{"className":9512},[],[9514],{"type":48,"value":2293},{"type":48,"value":9516}," for a newest-first slice, or the full ",{"type":42,"tag":57,"props":9518,"children":9520},{"className":9519},[],[9521],{"type":48,"value":1011},{"type":48,"value":9523}," loop in §3",{"type":42,"tag":736,"props":9525,"children":9526},{},[9527,9546,9589],{"type":42,"tag":758,"props":9528,"children":9529},{},[9530,9536,9538,9544],{"type":42,"tag":57,"props":9531,"children":9533},{"className":9532},[],[9534],{"type":48,"value":9535},"gcx k6 load-tests update -f",{"type":48,"value":9537}," returns ",{"type":42,"tag":57,"props":9539,"children":9541},{"className":9540},[],[9542],{"type":48,"value":9543},"✔ Updated",{"type":48,"value":9545}," but the change doesn't take effect",{"type":42,"tag":758,"props":9547,"children":9548},{},[9549,9551,9557,9559,9564,9565,9571,9573,9579,9581,9587],{"type":48,"value":9550},"Fields outside the v6 PATCH schema (",{"type":42,"tag":57,"props":9552,"children":9554},{"className":9553},[],[9555],{"type":48,"value":9556},"PatchLoadTestApiModel",{"type":48,"value":9558}," allows only ",{"type":42,"tag":57,"props":9560,"children":9562},{"className":9561},[],[9563],{"type":48,"value":1812},{"type":48,"value":365},{"type":42,"tag":57,"props":9566,"children":9568},{"className":9567},[],[9569],{"type":48,"value":9570},"baseline_test_run_id",{"type":48,"value":9572}," — ",{"type":42,"tag":57,"props":9574,"children":9576},{"className":9575},[],[9577],{"type":48,"value":9578},"additionalProperties: false",{"type":48,"value":9580},") are silently dropped. Notably ",{"type":42,"tag":57,"props":9582,"children":9584},{"className":9583},[],[9585],{"type":48,"value":9586},"project_id",{"type":48,"value":9588}," is NOT updatable this way",{"type":42,"tag":758,"props":9590,"children":9591},{},[9592,9594,9600],{"type":48,"value":9593},"For project moves use the dedicated ",{"type":42,"tag":57,"props":9595,"children":9597},{"className":9596},[],[9598],{"type":48,"value":9599},"\u002Fmove",{"type":48,"value":9601}," endpoint (§11); for other mutations cross-check the PATCH schema in the OpenAPI spec. Always re-GET to confirm",{"type":42,"tag":736,"props":9603,"children":9604},{},[9605,9616,9629],{"type":42,"tag":758,"props":9606,"children":9607},{},[9608,9614],{"type":42,"tag":57,"props":9609,"children":9611},{"className":9610},[],[9612],{"type":48,"value":9613},"gcx k6 load-tests list --project-id \u003Cid>",{"type":48,"value":9615}," returns tests from all projects",{"type":42,"tag":758,"props":9617,"children":9618},{},[9619,9621,9627],{"type":48,"value":9620},"The flag is accepted but never filters — ",{"type":42,"tag":57,"props":9622,"children":9624},{"className":9623},[],[9625],{"type":48,"value":9626},"\u002Fcloud\u002Fv6\u002Fload_tests",{"type":48,"value":9628}," has no project query param",{"type":42,"tag":758,"props":9630,"children":9631},{},[9632,9633,9639,9641,9646,9648,9654],{"type":48,"value":9300},{"type":42,"tag":57,"props":9634,"children":9636},{"className":9635},[],[9637],{"type":48,"value":9638},"GET \u002Fcloud\u002Fv6\u002Fprojects\u002F{id}\u002Fload_tests",{"type":48,"value":9640}," via ",{"type":42,"tag":57,"props":9642,"children":9644},{"className":9643},[],[9645],{"type":48,"value":128},{"type":48,"value":9647},", or filter client-side with ",{"type":42,"tag":57,"props":9649,"children":9651},{"className":9650},[],[9652],{"type":48,"value":9653},"select(.project_id == X)",{"type":48,"value":9655}," in jq",{"type":42,"tag":736,"props":9657,"children":9658},{},[9659,9674,9686],{"type":42,"tag":758,"props":9660,"children":9661},{},[9662,9667,9669],{"type":42,"tag":57,"props":9663,"children":9665},{"className":9664},[],[9666],{"type":48,"value":1828},{"type":48,"value":9668}," on a multipart POST through ",{"type":42,"tag":57,"props":9670,"children":9672},{"className":9671},[],[9673],{"type":48,"value":128},{"type":42,"tag":758,"props":9675,"children":9676},{},[9677,9679,9684],{"type":48,"value":9678},"The Grafana plugin proxy rewrites multipart Content-Types to ",{"type":42,"tag":57,"props":9680,"children":9682},{"className":9681},[],[9683],{"type":48,"value":1772},{"type":48,"value":9685}," before forwarding (gcx itself sends the header you set; the proxy strips it)",{"type":42,"tag":758,"props":9687,"children":9688},{},[9689,9691,9696,9698,9703],{"type":48,"value":9690},"Fall back to direct curl against ",{"type":42,"tag":57,"props":9692,"children":9694},{"className":9693},[],[9695],{"type":48,"value":1836},{"type":48,"value":9697}," (§1.2). Affects test creation (",{"type":42,"tag":57,"props":9699,"children":9701},{"className":9700},[],[9702],{"type":48,"value":1804},{"type":48,"value":9704},") and any other multipart endpoint",{"type":42,"tag":736,"props":9706,"children":9707},{},[9708,9734,9754],{"type":42,"tag":758,"props":9709,"children":9710},{},[9711,9717,9719,9724,9726,9732],{"type":42,"tag":57,"props":9712,"children":9714},{"className":9713},[],[9715],{"type":48,"value":9716},"401 Unauthorized",{"type":48,"value":9718}," calling ",{"type":42,"tag":57,"props":9720,"children":9722},{"className":9721},[],[9723],{"type":48,"value":1836},{"type":48,"value":9725}," \u002F ",{"type":42,"tag":57,"props":9727,"children":9729},{"className":9728},[],[9730],{"type":48,"value":9731},"cloudlogs.k6.io",{"type":48,"value":9733}," directly (curl mode)",{"type":42,"tag":758,"props":9735,"children":9736},{},[9737,9739,9745,9747,9752],{"type":48,"value":9738},"Missing\u002Fwrong ",{"type":42,"tag":57,"props":9740,"children":9742},{"className":9741},[],[9743],{"type":48,"value":9744},"Authorization: Bearer …",{"type":48,"value":9746}," or ",{"type":42,"tag":57,"props":9748,"children":9750},{"className":9749},[],[9751],{"type":48,"value":496},{"type":48,"value":9753}," header",{"type":42,"tag":758,"props":9755,"children":9756},{},[9757,9759,9764,9766,9771],{"type":48,"value":9758},"Re-check both headers; resolve ",{"type":42,"tag":57,"props":9760,"children":9762},{"className":9761},[],[9763],{"type":48,"value":496},{"type":48,"value":9765}," from a stack URL via ",{"type":42,"tag":57,"props":9767,"children":9769},{"className":9768},[],[9770],{"type":48,"value":697},{"type":48,"value":9772}," (§1.2)",{"type":42,"tag":736,"props":9774,"children":9775},{},[9776,9794,9799],{"type":42,"tag":758,"props":9777,"children":9778},{},[9779,9785,9786,9792],{"type":42,"tag":57,"props":9780,"children":9782},{"className":9781},[],[9783],{"type":48,"value":9784},"404",{"type":48,"value":9718},{"type":42,"tag":57,"props":9787,"children":9789},{"className":9788},[],[9790],{"type":48,"value":9791},"api.k6.io\u002Fapi\u002Fplugins\u002F...",{"type":48,"value":9793}," (curl mode)",{"type":42,"tag":758,"props":9795,"children":9796},{},[9797],{"type":48,"value":9798},"Left the plugin-proxy prefix in by mistake",{"type":42,"tag":758,"props":9800,"children":9801},{},[9802,9804,9809],{"type":48,"value":9803},"Strip ",{"type":42,"tag":57,"props":9805,"children":9807},{"className":9806},[],[9808],{"type":48,"value":419},{"type":48,"value":9810}," — see §1.2",{"type":42,"tag":132,"props":9812,"children":9813},{},[],{"type":42,"tag":136,"props":9815,"children":9817},{"id":9816},"_11-mutations-not-covered-by-update-f",[9818,9820],{"type":48,"value":9819},"11. Mutations not covered by ",{"type":42,"tag":57,"props":9821,"children":9823},{"className":9822},[],[9824],{"type":48,"value":9825},"update -f",{"type":42,"tag":51,"props":9827,"children":9828},{},[9829,9835,9837,9843,9845,9850],{"type":42,"tag":57,"props":9830,"children":9832},{"className":9831},[],[9833],{"type":48,"value":9834},"gcx k6 \u003Cresource> update -f",{"type":48,"value":9836}," follows the v6 PATCH schema for that\nresource. Fields outside the schema are silently dropped while gcx\nstill prints ",{"type":42,"tag":57,"props":9838,"children":9840},{"className":9839},[],[9841],{"type":48,"value":9842},"✔ Updated \u003Cresource> \u003Cid>",{"type":48,"value":9844}," — see the §10 row. Several\ncommon mutations have ",{"type":42,"tag":74,"props":9846,"children":9847},{},[9848],{"type":48,"value":9849},"dedicated endpoints instead",{"type":48,"value":9851},", and the PATCH\nroute will no-op on them.",{"type":42,"tag":728,"props":9853,"children":9854},{},[9855,9875],{"type":42,"tag":732,"props":9856,"children":9857},{},[9858],{"type":42,"tag":736,"props":9859,"children":9860},{},[9861,9866,9870],{"type":42,"tag":740,"props":9862,"children":9863},{},[9864],{"type":48,"value":9865},"Mutation",{"type":42,"tag":740,"props":9867,"children":9868},{},[9869],{"type":48,"value":3577},{"type":42,"tag":740,"props":9871,"children":9872},{},[9873],{"type":48,"value":9874},"Body",{"type":42,"tag":751,"props":9876,"children":9877},{},[9878,9904],{"type":42,"tag":736,"props":9879,"children":9880},{},[9881,9886,9895],{"type":42,"tag":758,"props":9882,"children":9883},{},[9884],{"type":48,"value":9885},"Move test to another project",{"type":42,"tag":758,"props":9887,"children":9888},{},[9889],{"type":42,"tag":57,"props":9890,"children":9892},{"className":9891},[],[9893],{"type":48,"value":9894},"PUT \u002Fcloud\u002Fv6\u002Fload_tests\u002F{id}\u002Fmove",{"type":42,"tag":758,"props":9896,"children":9897},{},[9898],{"type":42,"tag":57,"props":9899,"children":9901},{"className":9900},[],[9902],{"type":48,"value":9903},"{\"project_id\": \u003Cint>}",{"type":42,"tag":736,"props":9905,"children":9906},{},[9907,9912,9921],{"type":42,"tag":758,"props":9908,"children":9909},{},[9910],{"type":48,"value":9911},"Start a test run",{"type":42,"tag":758,"props":9913,"children":9914},{},[9915],{"type":42,"tag":57,"props":9916,"children":9918},{"className":9917},[],[9919],{"type":48,"value":9920},"POST \u002Fcloud\u002Fv6\u002Fload_tests\u002F{id}\u002Fstart",{"type":42,"tag":758,"props":9922,"children":9923},{},[9924,9930],{"type":42,"tag":57,"props":9925,"children":9927},{"className":9926},[],[9928],{"type":48,"value":9929},"{}",{"type":48,"value":9931}," (or run options)",{"type":42,"tag":51,"props":9933,"children":9934},{},[9935,9940,9942,9948,9950,9955,9957,9963,9965,9971,9973,9979,9981,9986,9988,9994,9995,10001,10003,10008],{"type":42,"tag":74,"props":9936,"children":9937},{},[9938],{"type":48,"value":9939},"Polling a started run:",{"type":48,"value":9941}," After starting a run, poll\n",{"type":42,"tag":57,"props":9943,"children":9945},{"className":9944},[],[9946],{"type":48,"value":9947},"GET \u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}",{"type":48,"value":9949}," until ",{"type":42,"tag":57,"props":9951,"children":9953},{"className":9952},[],[9954],{"type":48,"value":8657},{"type":48,"value":9956}," reaches ",{"type":42,"tag":57,"props":9958,"children":9960},{"className":9959},[],[9961],{"type":48,"value":9962},"completed",{"type":48,"value":9964}," or\n",{"type":42,"tag":57,"props":9966,"children":9968},{"className":9967},[],[9969],{"type":48,"value":9970},"aborted",{"type":48,"value":9972},". Always check the ",{"type":42,"tag":57,"props":9974,"children":9976},{"className":9975},[],[9977],{"type":48,"value":9978},"result",{"type":48,"value":9980}," field alongside ",{"type":42,"tag":57,"props":9982,"children":9984},{"className":9983},[],[9985],{"type":48,"value":8657},{"type":48,"value":9987}," —\n",{"type":42,"tag":57,"props":9989,"children":9991},{"className":9990},[],[9992],{"type":48,"value":9993},"status: completed",{"type":48,"value":3498},{"type":42,"tag":57,"props":9996,"children":9998},{"className":9997},[],[9999],{"type":48,"value":10000},"result: error",{"type":48,"value":10002}," means a configuration or\ninfrastructure failure (not a threshold breach). On any non-",{"type":42,"tag":57,"props":10004,"children":10006},{"className":10005},[],[10007],{"type":48,"value":9393},{"type":48,"value":10009},"\nresult, immediately fetch logs (§4) to surface the error rather than\nwaiting for the user to report it.",{"type":42,"tag":51,"props":10011,"children":10012},{},[10013,10015,10021,10023,10029,10031,10037,10039,10044,10046,10051,10052,10057,10059,10065,10067,10073],{"type":48,"value":10014},"| Abort a running test                  | ",{"type":42,"tag":57,"props":10016,"children":10018},{"className":10017},[],[10019],{"type":48,"value":10020},"POST \u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}\u002Fabort",{"type":48,"value":10022},"                 | empty                         |\n| Set \u002F overwrite a schedule            | ",{"type":42,"tag":57,"props":10024,"children":10026},{"className":10025},[],[10027],{"type":48,"value":10028},"POST \u002Fcloud\u002Fv6\u002Fload_tests\u002F{id}\u002Fschedule",{"type":48,"value":10030},"             | Schedule body (recurrence_rule or cron) |\n| Deactivate \u002F reactivate a schedule    | ",{"type":42,"tag":57,"props":10032,"children":10034},{"className":10033},[],[10035],{"type":48,"value":10036},"POST \u002Fcloud\u002Fv6\u002Fschedules\u002F{id}\u002F{deactivate,activate}",{"type":48,"value":10038}," | empty                         |\n| Create a load test (multipart!)       | ",{"type":42,"tag":57,"props":10040,"children":10042},{"className":10041},[],[10043],{"type":48,"value":1804},{"type":48,"value":10045},"             | multipart: ",{"type":42,"tag":57,"props":10047,"children":10049},{"className":10048},[],[10050],{"type":48,"value":1812},{"type":48,"value":1814},{"type":42,"tag":57,"props":10053,"children":10055},{"className":10054},[],[10056],{"type":48,"value":1820},{"type":48,"value":10058},"  |\n| Persist a run past retention          | ",{"type":42,"tag":57,"props":10060,"children":10062},{"className":10061},[],[10063],{"type":48,"value":10064},"POST \u002Fcloud\u002Fv6\u002Ftest_runs\u002F{id}\u002Fsave",{"type":48,"value":10066},"                  | empty (paired with ",{"type":42,"tag":57,"props":10068,"children":10070},{"className":10069},[],[10071],{"type":48,"value":10072},"\u002Funsave",{"type":48,"value":10074},") |",{"type":42,"tag":51,"props":10076,"children":10077},{},[10078,10080,10085,10087,10092],{"type":48,"value":10079},"The PATCH-style updates that ",{"type":42,"tag":274,"props":10081,"children":10082},{},[10083],{"type":48,"value":10084},"do",{"type":48,"value":10086}," work via ",{"type":42,"tag":57,"props":10088,"children":10090},{"className":10089},[],[10091],{"type":48,"value":9825},{"type":48,"value":537},{"type":42,"tag":728,"props":10094,"children":10095},{},[10096,10112],{"type":42,"tag":732,"props":10097,"children":10098},{},[10099],{"type":42,"tag":736,"props":10100,"children":10101},{},[10102,10107],{"type":42,"tag":740,"props":10103,"children":10104},{},[10105],{"type":48,"value":10106},"Resource",{"type":42,"tag":740,"props":10108,"children":10109},{},[10110],{"type":48,"value":10111},"Updatable fields",{"type":42,"tag":751,"props":10113,"children":10114},{},[10115,10145],{"type":42,"tag":736,"props":10116,"children":10117},{},[10118,10123],{"type":42,"tag":758,"props":10119,"children":10120},{},[10121],{"type":48,"value":10122},"load test",{"type":42,"tag":758,"props":10124,"children":10125},{},[10126,10131,10132,10137,10139,10144],{"type":42,"tag":57,"props":10127,"children":10129},{"className":10128},[],[10130],{"type":48,"value":1812},{"type":48,"value":365},{"type":42,"tag":57,"props":10133,"children":10135},{"className":10134},[],[10136],{"type":48,"value":9570},{"type":48,"value":10138}," (per ",{"type":42,"tag":57,"props":10140,"children":10142},{"className":10141},[],[10143],{"type":48,"value":9556},{"type":48,"value":2777},{"type":42,"tag":736,"props":10146,"children":10147},{},[10148,10153],{"type":42,"tag":758,"props":10149,"children":10150},{},[10151],{"type":48,"value":10152},"project",{"type":42,"tag":758,"props":10154,"children":10155},{},[10156,10161,10163,10169],{"type":42,"tag":57,"props":10157,"children":10159},{"className":10158},[],[10160],{"type":48,"value":1812},{"type":48,"value":10162}," only (per ",{"type":42,"tag":57,"props":10164,"children":10166},{"className":10165},[],[10167],{"type":48,"value":10168},"PatchProjectApiModel",{"type":48,"value":2777},{"type":42,"tag":51,"props":10171,"children":10172},{},[10173,10175,10180,10182,10187,10189,10195,10197,10203,10205,10210],{"type":48,"value":10174},"Both schemas declare ",{"type":42,"tag":57,"props":10176,"children":10178},{"className":10177},[],[10179],{"type":48,"value":9578},{"type":48,"value":10181}," — any other field\nyou put in the manifest is silently filtered out before the PATCH is\nsent, even though gcx still reports ",{"type":42,"tag":57,"props":10183,"children":10185},{"className":10184},[],[10186],{"type":48,"value":9543},{"type":48,"value":10188},". Don't try to flip\n",{"type":42,"tag":57,"props":10190,"children":10192},{"className":10191},[],[10193],{"type":48,"value":10194},"is_default",{"type":48,"value":10196}," or move a ",{"type":42,"tag":57,"props":10198,"children":10200},{"className":10199},[],[10201],{"type":48,"value":10202},"grafana_folder_uid",{"type":48,"value":10204}," through ",{"type":42,"tag":57,"props":10206,"children":10208},{"className":10207},[],[10209],{"type":48,"value":9825},{"type":48,"value":10211},";\nthey're not exposed for mutation on the v6 PATCH.",{"type":42,"tag":51,"props":10213,"children":10214},{},[10215],{"type":48,"value":10216},"Cross-check by reading the operation's request schema in the OpenAPI\nspec (workflow in §3) before assuming a field is mutable.",{"type":42,"tag":143,"props":10218,"children":10220},{"id":10219},"worked-example-move-a-test-between-projects",[10221],{"type":48,"value":10222},"Worked example — move a test between projects",{"type":42,"tag":150,"props":10224,"children":10226},{"className":152,"code":10225,"language":154,"meta":155,"style":155},"gcx api \u002Fapi\u002Fplugins\u002Fk6-app\u002Fresources\u002Fcloud\u002Fcloud\u002Fv6\u002Fload_tests\u002F\u003Ctest_id>\u002Fmove \\\n  -X PUT \\\n  -H \"Content-Type: application\u002Fjson\" \\\n  -d '{\"project_id\": \u003Cnew_project_id>}'\n\n# Verify — re-GET and check project_id reflects the new value.\n# Do not trust the absence of an error from the PUT; HTTP 204 with\n# empty body is the success shape but gcx api prints nothing.\ngcx --context \u003Cctx> k6 load-tests get \u003Ctest_id> -o json | jq '{id, name, project_id}'\n",[10227],{"type":42,"tag":57,"props":10228,"children":10229},{"__ignoreMap":155},[10230,10272,10287,10310,10330,10337,10345,10353,10361],{"type":42,"tag":161,"props":10231,"children":10232},{"class":163,"line":164},[10233,10237,10241,10245,10250,10255,10260,10264,10268],{"type":42,"tag":161,"props":10234,"children":10235},{"style":168},[10236],{"type":48,"value":62},{"type":42,"tag":161,"props":10238,"children":10239},{"style":173},[10240],{"type":48,"value":1927},{"type":42,"tag":161,"props":10242,"children":10243},{"style":173},[10244],{"type":48,"value":3865},{"type":42,"tag":161,"props":10246,"children":10247},{"style":184},[10248],{"type":48,"value":10249},"\u003C",{"type":42,"tag":161,"props":10251,"children":10252},{"style":173},[10253],{"type":48,"value":10254},"test_i",{"type":42,"tag":161,"props":10256,"children":10257},{"style":195},[10258],{"type":48,"value":10259},"d",{"type":42,"tag":161,"props":10261,"children":10262},{"style":184},[10263],{"type":48,"value":203},{"type":42,"tag":161,"props":10265,"children":10266},{"style":173},[10267],{"type":48,"value":9599},{"type":42,"tag":161,"props":10269,"children":10270},{"style":195},[10271],{"type":48,"value":577},{"type":42,"tag":161,"props":10273,"children":10274},{"class":163,"line":212},[10275,10279,10283],{"type":42,"tag":161,"props":10276,"children":10277},{"style":173},[10278],{"type":48,"value":4278},{"type":42,"tag":161,"props":10280,"children":10281},{"style":173},[10282],{"type":48,"value":4283},{"type":42,"tag":161,"props":10284,"children":10285},{"style":195},[10286],{"type":48,"value":577},{"type":42,"tag":161,"props":10288,"children":10289},{"class":163,"line":612},[10290,10294,10298,10302,10306],{"type":42,"tag":161,"props":10291,"children":10292},{"style":173},[10293],{"type":48,"value":585},{"type":42,"tag":161,"props":10295,"children":10296},{"style":184},[10297],{"type":48,"value":590},{"type":42,"tag":161,"props":10299,"children":10300},{"style":173},[10301],{"type":48,"value":4911},{"type":42,"tag":161,"props":10303,"children":10304},{"style":184},[10305],{"type":48,"value":605},{"type":42,"tag":161,"props":10307,"children":10308},{"style":195},[10309],{"type":48,"value":577},{"type":42,"tag":161,"props":10311,"children":10312},{"class":163,"line":642},[10313,10317,10321,10326],{"type":42,"tag":161,"props":10314,"children":10315},{"style":173},[10316],{"type":48,"value":4319},{"type":42,"tag":161,"props":10318,"children":10319},{"style":184},[10320],{"type":48,"value":663},{"type":42,"tag":161,"props":10322,"children":10323},{"style":173},[10324],{"type":48,"value":10325},"{\"project_id\": \u003Cnew_project_id>}",{"type":42,"tag":161,"props":10327,"children":10328},{"style":184},[10329],{"type":48,"value":8632},{"type":42,"tag":161,"props":10331,"children":10332},{"class":163,"line":2486},[10333],{"type":42,"tag":161,"props":10334,"children":10335},{"emptyLinePlaceholder":2464},[10336],{"type":48,"value":2467},{"type":42,"tag":161,"props":10338,"children":10339},{"class":163,"line":2495},[10340],{"type":42,"tag":161,"props":10341,"children":10342},{"style":206},[10343],{"type":48,"value":10344},"# Verify — re-GET and check project_id reflects the new value.\n",{"type":42,"tag":161,"props":10346,"children":10347},{"class":163,"line":2503},[10348],{"type":42,"tag":161,"props":10349,"children":10350},{"style":206},[10351],{"type":48,"value":10352},"# Do not trust the absence of an error from the PUT; HTTP 204 with\n",{"type":42,"tag":161,"props":10354,"children":10355},{"class":163,"line":2512},[10356],{"type":42,"tag":161,"props":10357,"children":10358},{"style":206},[10359],{"type":48,"value":10360},"# empty body is the success shape but gcx api prints nothing.\n",{"type":42,"tag":161,"props":10362,"children":10363},{"class":163,"line":2521},[10364,10368,10372,10376,10380,10384,10388,10392,10397,10402,10406,10410,10414,10418,10422,10426,10430,10434,10438,10443],{"type":42,"tag":161,"props":10365,"children":10366},{"style":168},[10367],{"type":48,"value":62},{"type":42,"tag":161,"props":10369,"children":10370},{"style":173},[10371],{"type":48,"value":181},{"type":42,"tag":161,"props":10373,"children":10374},{"style":184},[10375],{"type":48,"value":187},{"type":42,"tag":161,"props":10377,"children":10378},{"style":173},[10379],{"type":48,"value":192},{"type":42,"tag":161,"props":10381,"children":10382},{"style":195},[10383],{"type":48,"value":198},{"type":42,"tag":161,"props":10385,"children":10386},{"style":184},[10387],{"type":48,"value":203},{"type":42,"tag":161,"props":10389,"children":10390},{"style":173},[10391],{"type":48,"value":8987},{"type":42,"tag":161,"props":10393,"children":10394},{"style":173},[10395],{"type":48,"value":10396}," load-tests",{"type":42,"tag":161,"props":10398,"children":10399},{"style":173},[10400],{"type":48,"value":10401}," get",{"type":42,"tag":161,"props":10403,"children":10404},{"style":184},[10405],{"type":48,"value":187},{"type":42,"tag":161,"props":10407,"children":10408},{"style":173},[10409],{"type":48,"value":10254},{"type":42,"tag":161,"props":10411,"children":10412},{"style":195},[10413],{"type":48,"value":10259},{"type":42,"tag":161,"props":10415,"children":10416},{"style":184},[10417],{"type":48,"value":203},{"type":42,"tag":161,"props":10419,"children":10420},{"style":173},[10421],{"type":48,"value":4596},{"type":42,"tag":161,"props":10423,"children":10424},{"style":173},[10425],{"type":48,"value":4601},{"type":42,"tag":161,"props":10427,"children":10428},{"style":184},[10429],{"type":48,"value":2966},{"type":42,"tag":161,"props":10431,"children":10432},{"style":168},[10433],{"type":48,"value":653},{"type":42,"tag":161,"props":10435,"children":10436},{"style":184},[10437],{"type":48,"value":663},{"type":42,"tag":161,"props":10439,"children":10440},{"style":173},[10441],{"type":48,"value":10442},"{id, name, project_id}",{"type":42,"tag":161,"props":10444,"children":10445},{"style":184},[10446],{"type":48,"value":8632},{"type":42,"tag":51,"props":10448,"children":10449},{},[10450,10452,10457],{"type":48,"value":10451},"The OpenAPI description for this endpoint is explicit: ",{"type":42,"tag":274,"props":10453,"children":10454},{},[10455],{"type":48,"value":10456},"\"Move a load\ntest to a different project of the same organization. All respective\ntest runs will be also moved to the new project.\"",{"type":48,"value":10458}," You don't need to\nmigrate runs separately.",{"type":42,"tag":143,"props":10460,"children":10462},{"id":10461},"cascade-behavior-worth-knowing",[10463],{"type":48,"value":10464},"Cascade behavior worth knowing",{"type":42,"tag":66,"props":10466,"children":10467},{},[10468,10501,10525],{"type":42,"tag":70,"props":10469,"children":10470},{},[10471,10476,10478,10484,10485,10491,10493,10499],{"type":42,"tag":74,"props":10472,"children":10473},{},[10474],{"type":48,"value":10475},"Deleting a load test cascade-deletes its schedule.",{"type":48,"value":10477}," The schedule\nis gone from ",{"type":42,"tag":57,"props":10479,"children":10481},{"className":10480},[],[10482],{"type":48,"value":10483},"\u002Fcloud\u002Fv6\u002Fschedules",{"type":48,"value":265},{"type":42,"tag":57,"props":10486,"children":10488},{"className":10487},[],[10489],{"type":48,"value":10490},"\u002Fcloud\u002Fv6\u002Fload_tests\u002F{id}\u002Fschedule",{"type":48,"value":10492},"\nimmediately. No need to ",{"type":42,"tag":57,"props":10494,"children":10496},{"className":10495},[],[10497],{"type":48,"value":10498},"gcx k6 schedules delete \u003Cload-test-id>",{"type":48,"value":10500},"\nfirst as a defensive step.",{"type":42,"tag":70,"props":10502,"children":10503},{},[10504,10509,10511,10516,10518,10523],{"type":42,"tag":74,"props":10505,"children":10506},{},[10507],{"type":48,"value":10508},"Deleting a project with a running test fails with HTTP 409",{"type":48,"value":10510},"\n(\"Cannot delete project with a running test.\" per the OpenAPI\nspec). Non-running tests appear to be removed with the project,\nbut if you want to inventory a project's contents before deleting\nit, use ",{"type":42,"tag":57,"props":10512,"children":10514},{"className":10513},[],[10515],{"type":48,"value":9638},{"type":48,"value":10517}," (NOT\n",{"type":42,"tag":57,"props":10519,"children":10521},{"className":10520},[],[10522],{"type":48,"value":9613},{"type":48,"value":10524},", which doesn't filter —\nsee §10).",{"type":42,"tag":70,"props":10526,"children":10527},{},[10528,10533,10535,10541],{"type":42,"tag":74,"props":10529,"children":10530},{},[10531],{"type":48,"value":10532},"Moving a test moves its runs and run history with it.",{"type":48,"value":10534}," Schedule\nattachment also follows the test (it's keyed by ",{"type":42,"tag":57,"props":10536,"children":10538},{"className":10537},[],[10539],{"type":48,"value":10540},"load_test_id",{"type":48,"value":10542},",\nnot by project).",{"type":42,"tag":143,"props":10544,"children":10546},{"id":10545},"verification-rule-of-thumb",[10547],{"type":48,"value":10548},"Verification rule of thumb",{"type":42,"tag":51,"props":10550,"children":10551},{},[10552,10554,10559],{"type":48,"value":10553},"The recurring pattern in this skill is ",{"type":42,"tag":274,"props":10555,"children":10556},{},[10557],{"type":48,"value":10558},"\"gcx confirms success even\nwhen the underlying call no-ops\"",{"type":48,"value":10560},". Whenever you mutate state:",{"type":42,"tag":453,"props":10562,"children":10563},{},[10564,10569,10574],{"type":42,"tag":70,"props":10565,"children":10566},{},[10567],{"type":48,"value":10568},"Note what you expected to change (field, count, status).",{"type":42,"tag":70,"props":10570,"children":10571},{},[10572],{"type":48,"value":10573},"Re-GET the resource and confirm the change is reflected.",{"type":42,"tag":70,"props":10575,"children":10576},{},[10577,10579,10584],{"type":48,"value":10578},"If it isn't, check whether the mutation needed a dedicated\nendpoint (this section) rather than ",{"type":42,"tag":57,"props":10580,"children":10582},{"className":10581},[],[10583],{"type":48,"value":9825},{"type":48,"value":288},{"type":42,"tag":10586,"props":10587,"children":10588},"style",{},[10589],{"type":48,"value":10590},"html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"items":10592,"total":10777},[10593,10614,10633,10652,10666,10682,10695,10708,10725,10740,10753,10765],{"slug":10594,"name":10594,"fn":10595,"description":10596,"org":10597,"tags":10598,"stars":10611,"repoUrl":10612,"updatedAt":10613},"faro-setup-web","instrument web apps with Grafana Faro","Instruments a web app with Grafana Faro Web SDK for frontend observability. Use when setting up error tracking, Web Vitals, session monitoring, or distributed tracing in a browser app.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10599,10602,10605,10608],{"name":10600,"slug":10601,"type":15},"Distributed Tracing","distributed-tracing",{"name":10603,"slug":10604,"type":15},"Frontend","frontend",{"name":10606,"slug":10607,"type":15},"Monitoring","monitoring",{"name":10609,"slug":10610,"type":15},"Observability","observability",1103,"https:\u002F\u002Fgithub.com\u002Fgrafana\u002Ffaro-web-sdk","2026-07-12T07:43:24.63314",{"slug":10615,"name":10615,"fn":10616,"description":10617,"org":10618,"tags":10619,"stars":10630,"repoUrl":10631,"updatedAt":10632},"configuring-yesoreyeram-infinity-datasource","configure Grafana Infinity data source","Configure the Infinity data source — base URL and allowed hosts, the authentication methods (basic, bearer token, API key, digest, OAuth passthrough, OAuth 2.0 client credentials\u002FJWT, Azure, Azure Blob, AWS), TLS, custom HTTP headers, network and security settings, the custom health check, and provisioning with a config file. Use when a user asks how to set up, configure, or change settings for the Infinity data source; how to authenticate to an API; how to allow hosts; how to provision it as YAML; or how to troubleshoot connection, authentication, or health-check issues.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10620,10623,10626,10629],{"name":10621,"slug":10622,"type":15},"API Development","api-development",{"name":10624,"slug":10625,"type":15},"Authentication","authentication",{"name":10627,"slug":10628,"type":15},"Configuration","configuration",{"name":9,"slug":8,"type":15},1056,"https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fgrafana-infinity-datasource","2026-07-12T07:43:25.939136",{"slug":10634,"name":10634,"fn":10635,"description":10636,"org":10637,"tags":10638,"stars":10630,"repoUrl":10631,"updatedAt":10651},"querying-yesoreyeram-infinity-datasource","query data with Infinity datasource","Build queries with the Infinity data source — the query types (JSON, CSV, TSV, XML, GraphQL, HTML, UQL, GROQ, Google Sheets, Series, Transformations), the parsers (Frontend\u002Fsimple, Backend JSONata, JQ, UQL, GROQ) and which support alerting, the sources (URL, Inline, Reference, Azure Blob, Random walk), output formats (table, timeseries, logs, trace, node graph, dataframe), root selector and columns, computed columns\u002Ffilters\u002Fsummarize, pagination, and template variables. Use when a user asks how to query Infinity; how to fetch JSON\u002FCSV\u002FXML\u002FGraphQL\u002FHTML from a URL or inline; how to select rows and columns; how to transform data with UQL\u002FGROQ\u002FJSONata\u002FJQ; how to make a query work with alerting; how to paginate; or how to use variables in a query.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10639,10642,10645,10646,10649],{"name":10640,"slug":10641,"type":15},"CSV","csv",{"name":10643,"slug":10644,"type":15},"Data Analysis","data-analysis",{"name":9,"slug":8,"type":15},{"name":10647,"slug":10648,"type":15},"GraphQL","graphql",{"name":10650,"slug":1283,"type":15},"JSON","2026-07-15T05:34:05.773947",{"slug":10653,"name":10653,"fn":10654,"description":10655,"org":10656,"tags":10657,"stars":10663,"repoUrl":10664,"updatedAt":10665},"agento11y","manage Grafana Agent Observability resources","Inspects and manages Grafana Agent Observability resources via gcx: conversations, generations, evaluators, rules, scores, and templates. Use when the user wants to list or search conversations, inspect generations, manage evaluators (upsert, test, delete), set up evaluation rules, check scores, or browse evaluator templates. Trigger on phrases like \"list conversations\", \"search generations\", \"what did the agent do\", \"debug LLM conversation\", \"create evaluator\", \"set up evaluation rule\", \"test evaluator\", \"check scores\", \"evaluate generation quality\", or \"set up online evaluation\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10658,10660,10661,10662],{"name":10659,"slug":1297,"type":15},"Agents",{"name":9,"slug":8,"type":15},{"name":10606,"slug":10607,"type":15},{"name":10609,"slug":10610,"type":15},430,"https:\u002F\u002Fgithub.com\u002Fgrafana\u002Fgcx","2026-07-25T05:30:40.29622",{"slug":10667,"name":10667,"fn":10668,"description":10669,"org":10670,"tags":10671,"stars":10663,"repoUrl":10664,"updatedAt":10681},"agento11y-instrument","instrument LLM apps for agent observability","Sets up and instruments a developer's own LLM app or agent to send generations and agentic workflow to Grafana Agent Observability (the Agent Observability SDKs) — greenfield setup, fixing broken instrumentation, or filling gaps in existing instrumentation. Uses gcx for the parts a static prompt can't do: `gcx login` \u002F `gcx cloud stacks` to find the stack, and `gcx agento11y agents|conversations|generations` to VERIFY that data actually lands — so it iterates (instrument → run → verify → fix) until generations arrive, not blindly. Reads the app's code, detects language\u002Fframework, classifies instrumentation state (none \u002F partial \u002F broken), then runs a fixed gap checklist whose #1 item is the silent failure no other prompt catches: the SDK emits OTel spans\u002Fmetrics but never creates a TracerProvider\u002FMeterProvider, so without them all metrics go to a no-op and are lost. Also checks agent_version (required for per-version Performance charts), set_result completeness, SYNC vs STREAM, parent_generation_ids DAG links, and workflow-step coverage. Recommends changes citing file:line and, only with explicit confirmation, applies minimal diffs that don't change app behavior. Pulls SDK reference from agento11y's llms.txt rather than restating it, and hands off to `agento11y-test-starter` once data flows. It does NOT write test suites or set up tenant evaluations, rules, or guards — offline test suites are `agento11y-test-starter`, tenant eval rules + guards are `agento11y-prod-setup`; does NOT install coding-agent telemetry plugins (that is llms.txt \"Path A\"); does NOT mint or store credentials or invent endpoints. Trigger on phrases like \"instrument my app\", \"send my agent's traces to Grafana\", \"set up AI observability for my app\", \"my generations aren't showing up\", \"why is Performance empty\", \"add Agent Observability to my code\", \"fix my instrumentation\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10672,10673,10674,10677,10680],{"name":10659,"slug":1297,"type":15},{"name":9,"slug":8,"type":15},{"name":10675,"slug":10676,"type":15},"Instrumentation","instrumentation",{"name":10678,"slug":10679,"type":15},"LLM","llm",{"name":10609,"slug":10610,"type":15},"2026-07-31T05:53:52.580237",{"slug":10683,"name":10683,"fn":10684,"description":10685,"org":10686,"tags":10687,"stars":10663,"repoUrl":10664,"updatedAt":10694},"agento11y-prod-setup","setup production evaluation for AI agents","Sets up production evaluation and guardrails for a DEPLOYED AI agent in Grafana Agent Observability, grounded in the agent's own code and its real ingested traffic. The judgment layer on top of the `agento11y` skill: it reads the agent's source (system prompt, tools, entrypoint) AND samples its live traffic via gcx, checks what evaluators\u002Frules\u002Fguards already exist, then recommends only what's missing — online eval rules (score live conversations for regressions) and guards (warn-first request-path policies that redact \u002F tool-filter and may later be promoted to deny). It drafts reviewable YAML and, only with explicit confirmation, applies via `gcx agento11y`. New guards are drafted in warn mode (safe on live traffic — warn records but never blocks). It DOES create stack-level objects — that is the point — but every write is confirmed. It never rewrites or redeploys the agent. Trigger on phrases like \"set up production evaluation\", \"my agent is in prod what should I evaluate\", \"catch quality regressions\", \"add guardrails to my agent\", \"redact PII from my agent\", \"block dangerous tools\", \"set up online evals and guards\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10688,10689,10692,10693],{"name":10659,"slug":1297,"type":15},{"name":10690,"slug":10691,"type":15},"Evals","evals",{"name":9,"slug":8,"type":15},{"name":10609,"slug":10610,"type":15},"2026-07-31T05:53:53.576347",{"slug":10696,"name":10696,"fn":10697,"description":10698,"org":10699,"tags":10700,"stars":10663,"repoUrl":10664,"updatedAt":10707},"agento11y-test-starter","build and run agent test suites","Use early in an AI-agent project — before ship, before real traffic — to build a starter test suite for the agent and run it offline. Reads the agent's own code (system prompt, tools, task), writes a labeled draft suite of test cases (happy\u002Fedge\u002Fadversarial) grounded in real lines, and recommends how to score each case (the evaluators\u002Fjudges the offline runner uses). Assesses how runnable the agent is: for an easily-invoked agent it generates a runner stub (run_experiment.py) with two holes to fill and can optionally run it (only with permission, only against the endpoint the developer configured); for agents needing a harness or full runtime it points to the existing eval infra. It runs OFFLINE and never creates tenant-level evaluators, rules, or guards — that is `agento11y-prod-setup`, for a deployed agent with real traffic. Trigger on phrases like \"how do I test my agent before shipping\", \"write test cases for my agent\", \"set up tests for my agent\", \"check my agent before prod\", \"I have no traffic yet, how do I evaluate it\", \"test my agent offline\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10701,10702,10703,10706],{"name":10659,"slug":1297,"type":15},{"name":9,"slug":8,"type":15},{"name":10704,"slug":10705,"type":15},"QA","qa",{"name":24,"slug":25,"type":15},"2026-07-31T05:53:51.62785",{"slug":10709,"name":10709,"fn":10710,"description":10711,"org":10712,"tags":10713,"stars":10663,"repoUrl":10664,"updatedAt":10724},"create-dashboard","create Grafana dashboards with gcx","Designs and creates Grafana dashboards with gcx, using `gcx dashboards snapshot` as a visual feedback loop. Use when the user wants to create a new Grafana dashboard, add panels, variables, or annotations to an existing dashboard, design dashboard panels, variables, queries, or layout, or make a material visual redesign. Triggers on \"create dashboard\", \"new dashboard\", \"build dashboard\", \"dashboard for \u003Cservice>\", \"add panels\", \"add variable\", \"add annotation\", \"improve this dashboard\", or \"iterate on a dashboard\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10714,10717,10720,10723],{"name":10715,"slug":10716,"type":15},"Dashboards","dashboards",{"name":10718,"slug":10719,"type":15},"Data Visualization","data-visualization",{"name":10721,"slug":10722,"type":15},"Design","design",{"name":9,"slug":8,"type":15},"2026-07-25T05:30:46.289717",{"slug":10726,"name":10726,"fn":10727,"description":10728,"org":10729,"tags":10730,"stars":10663,"repoUrl":10664,"updatedAt":10739},"debug-with-grafana","investigate application issues with Grafana","Structured workflow for investigating application problems with Grafana observability data (metrics, logs, traces) via gcx. Covers live firefighting AND retrospective incident analysis: incident triage, root-cause analysis, blast-radius checks (did an incident spill into other services), verifying whether a deployment or rollout triggered an incident, finding which service, endpoint, or path owns the most errors or slow requests, checking whether retries or queue backlogs piled up, and quantifying error or latency shares over a time window. Trigger on: \"my API is returning 500 errors\", \"latency is spiking\", \"investigate why requests are failing\", \"triage the incident\", \"blast radius\", \"root cause\", \"did the rollout cause it\", \"which endpoint owns the most 5xx\", \"did retries pile up\", or any request to analyse an earlier incident window using telemetry. For authoring dashboards use create-dashboard; for dashboard inventory use manage-dashboards.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10731,10734,10735,10738],{"name":10732,"slug":10733,"type":15},"Debugging","debugging",{"name":9,"slug":8,"type":15},{"name":10736,"slug":10737,"type":15},"Incident Response","incident-response",{"name":10609,"slug":10610,"type":15},"2026-07-18T05:11:10.445428",{"slug":10741,"name":10741,"fn":10742,"description":10743,"org":10744,"tags":10745,"stars":10663,"repoUrl":10664,"updatedAt":10752},"diagnose-entity-graph","diagnose Grafana Entity Graph issues","Diagnose Entity Graph problems: missing entities, missing edges, disconnected clusters, or filtering issues. Use when the user reports that Entity Graph doesn't look right, services are missing, edges aren't appearing, or environments can't be filtered. Triggers for: \"entity graph is empty\", \"services missing from entity graph\", \"no edges in entity graph\", \"disconnected services\", \"can't filter entity graph\", \"entity graph not working\", \"diagnose entity graph\", \"debug knowledge graph\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10746,10747,10748,10751],{"name":10732,"slug":10733,"type":15},{"name":9,"slug":8,"type":15},{"name":10749,"slug":10750,"type":15},"Graph Analysis","graph-analysis",{"name":10609,"slug":10610,"type":15},"2026-07-25T05:30:39.380934",{"slug":62,"name":62,"fn":10754,"description":10755,"org":10756,"tags":10757,"stars":10663,"repoUrl":10664,"updatedAt":10764},"manage Grafana Cloud resources via gcx","Manages Grafana Cloud resources via the gcx CLI. Trigger when the user wants to inspect, create, update, delete, query, or automate any Grafana resource - dashboards, datasources, alerts, SLOs, synthetic checks, oncall, incidents, fleet, k6, knowledge graph, or adaptive telemetry.\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10758,10759,10760,10761],{"name":20,"slug":21,"type":15},{"name":9,"slug":8,"type":15},{"name":10606,"slug":10607,"type":15},{"name":10762,"slug":10763,"type":15},"Operations","operations","2026-07-31T05:53:50.587304",{"slug":10766,"name":10766,"fn":10767,"description":10768,"org":10769,"tags":10770,"stars":10663,"repoUrl":10664,"updatedAt":10776},"gcx-demo","present gcx demo tours","Run a narrated, read-only demo tour of gcx for customer or colleague presentations. Showcases the breadth of gcx across every Grafana Cloud product area — resources, datasources, metrics, logs, traces, SLOs, alerts, synthetic monitoring, IRM, k6, fleet, and more. All commands are strictly read-only. Trigger when the user says \"demo gcx\", \"show off gcx\", \"customer demo\", \"gcx tour\", or \"\u002Fgcx-demo\".\n",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10771,10772,10773],{"name":20,"slug":21,"type":15},{"name":9,"slug":8,"type":15},{"name":10774,"slug":10775,"type":15},"Presentations","presentations","2026-07-25T05:30:45.282458",80,{"items":10779,"total":10880},[10780,10793,10808,10824,10837,10851,10865],{"slug":10781,"name":10781,"fn":10782,"description":10783,"org":10784,"tags":10785,"stars":26,"repoUrl":27,"updatedAt":10792},"adaptive-metrics","optimize Grafana Cloud metrics costs","Cut Grafana Cloud Metrics cost by shrinking active-series count with Adaptive Metrics aggregation rules — auto-recommendations from query history, custom exact\u002Fregex rules, label-drop config, unused-metric detection, and Alloy remote_write fallback. Use when investigating a high Mimir\u002FGrafana Cloud bill, hunting high-cardinality labels (`pod_uid`, `service_instance_id`, `version`), pre-aggregating counters\u002Fgauges, dropping unused metrics, or measuring `grafanacloud_instance_active_series` before\u002Fafter — even when the user says \"reduce cardinality\", \"too many series\", \"metrics spend\", \"active series count is exploding\", or \"drop the version label\" without naming Adaptive Metrics.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10786,10789,10790,10791],{"name":10787,"slug":10788,"type":15},"Cost Optimization","cost-optimization",{"name":9,"slug":8,"type":15},{"name":2711,"slug":2708,"type":15},{"name":10609,"slug":10610,"type":15},"2026-07-12T07:44:27.451068",{"slug":10794,"name":10794,"fn":10795,"description":10796,"org":10797,"tags":10798,"stars":26,"repoUrl":27,"updatedAt":10807},"admin","manage Grafana Cloud accounts and RBAC","Manage Grafana Cloud accounts — organizations, stacks, RBAC roles and assignments, SSO\u002FSAML\u002FOAuth\u002FGitHub auth, service accounts for CI\u002FCD, user invites, team membership, and API-driven provisioning. Creates stacks via the Cloud API, mints service-account tokens, applies role assignments, configures SSO providers, and provisions teams\u002Ffolders\u002Fdashboards via Terraform. Use when managing Grafana Cloud access, configuring SSO\u002FSAML\u002FOAuth, setting up service accounts for Terraform\u002FCI\u002FCD, assigning RBAC roles, inviting users, managing multiple stacks or organizations, provisioning cloud resources via API or Terraform, or auditing admin actions — even when the user says \"set up SSO\", \"create a stack\", \"make a service account\", or \"onboard a team\" without explicitly saying \"admin\".",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10799,10802,10805,10806],{"name":10800,"slug":10801,"type":15},"Access Control","access-control",{"name":10803,"slug":10804,"type":15},"Auth","auth",{"name":9,"slug":8,"type":15},{"name":10762,"slug":10763,"type":15},"2026-07-12T07:44:12.078436",{"slug":10809,"name":10809,"fn":10810,"description":10811,"org":10812,"tags":10813,"stars":26,"repoUrl":27,"updatedAt":10823},"admission-control","implement admission control webhooks","Use when the user asks to \"write a validator\", \"add validation\", \"implement admission control\", \"write a mutating webhook\", \"add a mutation handler\", \"validate incoming resources\", \"implement admission logic\", \"add admission webhooks\", \"write ingress validation\", or asks how to validate or mutate resources before they are persisted in a grafana-app-sdk app. Provides guidance on implementing validation and mutation admission handlers for grafana-app-sdk apps.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10814,10817,10820],{"name":10815,"slug":10816,"type":15},"Architecture","architecture",{"name":10818,"slug":10819,"type":15},"Security","security",{"name":10821,"slug":10822,"type":15},"Validation","validation","2026-07-12T07:45:06.148973",{"slug":10825,"name":10825,"fn":10826,"description":10827,"org":10828,"tags":10829,"stars":26,"repoUrl":27,"updatedAt":10836},"alerting-irm","configure Grafana Alerting and Incident Management","Configure Grafana Alerting, Incident Response Management (IRM), and SLOs end-to-end — provisions Grafana-managed and data-source-managed alert rules, contact points (Slack\u002FPagerDuty\u002Femail\u002Fwebhook), notification policies with hierarchical matchers, silences, mute timings, on-call schedules and escalation chains, incident-management integrations, and SLOs with multi-window burn-rate alerts. Use when configuring alerts, debugging notification routing, setting up on-call rotations, declaring or managing incidents, defining SLOs, provisioning alerting via YAML or API, picking matchers for a notification policy, building a PagerDuty\u002FSlack webhook receiver, or troubleshooting why an alert isn't firing — even when the user says \"page me on errors\", \"alert me when X happens\", \"route this to the platform team\", or \"set up an SLO\" without naming Alerting or IRM.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10830,10833,10834,10835],{"name":10831,"slug":10832,"type":15},"Alerting","alerting",{"name":9,"slug":8,"type":15},{"name":10736,"slug":10737,"type":15},{"name":10606,"slug":10607,"type":15},"2026-07-12T07:44:02.393397",{"slug":10838,"name":10838,"fn":10839,"description":10840,"org":10841,"tags":10842,"stars":26,"repoUrl":27,"updatedAt":10850},"alloy","build unified telemetry pipelines with Grafana Alloy","Build a unified telemetry pipeline with Grafana Alloy — one OpenTelemetry-compatible binary that collects metrics, logs, traces, and profiles and ships to Grafana Cloud \u002F Prometheus \u002F Loki \u002F Tempo \u002F Pyroscope. Covers the Alloy config language (blocks, `sys.env`, component refs), `prometheus.scrape` → `remote_write`, `loki.source.file` + `loki.process` → `loki.write`, `otelcol.receiver.otlp` → `otelcol.exporter.otlp`, `pyroscope.scrape`, K8s \u002F Docker \u002F EC2 discovery, relabeling, modules (`import.file\u002Fgit\u002Fhttp`), clustering, Fleet Management `remotecfg`, the Alloy UI at `:12345`, and `alloy fmt` \u002F `alloy validate`. Use when writing a `config.alloy`, replacing Grafana Agent \u002F OTel Collector, scraping K8s pods, parsing logs, ingesting OTLP, or debugging \"Alloy isn't sending anything\" — even when the user says \"set up the agent\", \"write me a scrape config\", \"drop these logs before sending\", or \"OTel collector config\" without naming Alloy.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10843,10844,10845,10846,10847],{"name":9,"slug":8,"type":15},{"name":2756,"slug":2753,"type":15},{"name":2711,"slug":2708,"type":15},{"name":10609,"slug":10610,"type":15},{"name":10848,"slug":10849,"type":15},"OpenTelemetry","opentelemetry","2026-07-12T07:43:54.817139",{"slug":10852,"name":10852,"fn":10853,"description":10854,"org":10855,"tags":10856,"stars":26,"repoUrl":27,"updatedAt":10864},"app-observability","monitor application performance in Grafana Cloud","Get RED metrics + service maps + frontend RUM + AI\u002FLLM monitoring out of Grafana Cloud — Application Observability (`traces_spanmetrics_*` from OTel traces, p50\u002Fp95\u002Fp99 latency, exemplar-to-trace, traces-to-logs \u002F profiles), Frontend Observability with the Faro Web SDK (Core Web Vitals, session replay, `pushError`, React + router integration, `TracingInstrumentation` for browser → backend trace correlation), and AI Observability via OpenLIT (token \u002F cost \u002F latency, GPU, hallucination + toxicity evals). Use when standing up APM for a service, wiring an Alloy OTLP receiver + forwarding to Cloud, instrumenting a React frontend for RUM, debugging why service-map edges are missing, monitoring LLM cost drift, or correlating a frontend error to its backend trace — even when the user says \"set up APM\", \"show service map\", \"monitor browser perf\", \"session replay\", \"RUM SDK\", or \"watch our OpenAI bill\" without naming App \u002F Frontend \u002F AI Observability.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10857,10860,10861,10862,10863],{"name":10858,"slug":10859,"type":15},"APM","apm",{"name":10600,"slug":10601,"type":15},{"name":9,"slug":8,"type":15},{"name":10678,"slug":10679,"type":15},{"name":10609,"slug":10610,"type":15},"2026-07-12T07:44:34.500406",{"slug":10866,"name":10866,"fn":10867,"description":10868,"org":10869,"tags":10870,"stars":26,"repoUrl":27,"updatedAt":10879},"app-sdk-concepts","scaffold and configure Grafana apps","Use when starting any grafana-app-sdk work — scaffolding a Grafana app, initializing a Grafana App Platform app, picking a deployment mode (standalone operator \u002F grafana\u002Fapps \u002F frontend-only), wiring app-specific config, or onboarding to the SDK. Covers `grafana-app-sdk` CLI install, `project init` per deployment mode, project layout, the schema-centric workflow (CUE kinds → generated code → reconciler\u002Fadmission logic), and `SpecificConfig` for env-driven app configuration. Use even if the user just says \"make a new app\", \"Grafana app platform\", \"kinds and watchers\", \"operator scaffold\", or asks about `apps\u002F` inside the Grafana repo, without naming the SDK explicitly.",{"slug":8,"name":9,"logoUrl":10,"githubOrg":8},[10871,10872,10875,10878],{"name":10815,"slug":10816,"type":15},{"name":10873,"slug":10874,"type":15},"Deployment","deployment",{"name":10876,"slug":10877,"type":15},"Engineering","engineering",{"name":9,"slug":8,"type":15},"2026-07-12T07:45:08.595757",48]