Fix gaps in the abstract shell to concrete migration for FF_SCRIPTS_TO_STEPS
## Summary
The concrete runner (step-runner builtin counterpart to the abstract shell) has several behavioural gaps compared to the abstract shell. These must be resolved for the `FF_SCRIPTS_TO_STEPS` migration to reach parity.
All fixes are in !6688.
## Fixes
### Shell semantics
1. **pre/post_build_script folded into each user step** — previously emitted as standalone steps (separate shell processes), breaking shell state sharing (exports, `cd`, `set` options). Now spliced via `slices.Concat` to match abstract shell's `writeUserScript`.
### Section names & trace
2. **Section names aligned with abstract shell** — replaced indexed names (`restore_cache_0`, `step_0_script`, etc.) with `BuildStage` values (`restore_cache`, `step_<name>`, `archive_cache` / `archive_cache_on_failure`, `upload_artifacts_on_success` / `upload_artifacts_on_failure`).
3. **Trace section markers gated on `Features.TraceSections`** — abstract shell only emits `section_start`/`section_end` when GitLab advertises the feature; concrete now does the same.
### Missing guards
4. **Artifact upload skipped when `BaseURL` is empty** — matches abstract shell's `ErrSkipBuildStage` guard.
5. **Cache extract `--header` flag dropped** — `cache-extractor` doesn't accept `--header` (only `cache-archiver` does); was causing unrecognised flag errors.
### Variable expansion
6. **`cache.policy` expanded before classification** — `$MY_POLICY` was falling into the default arm and silently skipping the cache stage.
7. **`--expire-in` expanded for artifact upload** — `artifacts-uploader` doesn't expand `$VAR` in `--expire-in`, so literal `$ART_EXPIRE` was rejected.
### Env var naming
8. **Aligned env var names with abstract shell** — `GIT_CLONE_FLAGS` → `GIT_CLONE_EXTRA_FLAGS`, `GIT_FETCH_FLAGS` → `GIT_FETCH_EXTRA_FLAGS`, `GENERATE_ARTIFACTS_METADATA` → `RUNNER_GENERATE_ARTIFACTS_METADATA`.
### TLS / git
9. **`GIT_SSL_CAINFO` set alongside `SSL_CERT_FILE`** — libcurl (bundled git's TLS backend) ignores `SSL_CERT_FILE`; without `GIT_SSL_CAINFO`, HTTPS clones against custom CAs failed TLS verification.
### Error classification
10. **User-cancel error wraps `context.Canceled`** — step-runner uses `errors.Is(err, context.Canceled)` to classify cancellations; without the unwrap chain it fell through to `UnknownFailure`.
11. **Timeout classified as `JobExecutionTimeout`** — bumps step-runner to v0.36.0 which exposes `context.DeadlineExceeded` as a distinct error kind; wired through `wrapStepStageErr`.
### Metrics
12. **Concrete jobs recorded in `JobExecutionMode` metrics** — `executeScript`'s concrete branch now marks steps-dispatch and fires `OnJobExecutionModeDispatchedFn`.
### Cache optimisation
13. **Cache HEAD URL plumbed to `cache-archiver --check-url`** — allows skipping upload when the object already exists; was previously dropped.
### Dead code removal & documentation
14. **Dead `FF_CLEAN_UP_FAILED_CACHE_EXTRACT` wiring removed** — documented as intentional divergence in package doc (failure mode doesn't apply to concrete).
15. **File-based variable cleanup documented as intentional divergence** — step-runner owns the lifecycle; no equivalent needed in concrete.
## Acceptance criteria
- [x] pre/post_build_script folded into user steps; after_script not wrapped
- [x] Section names match abstract shell's `BuildStage` values
- [x] Trace sections gated on `Features.TraceSections`
- [x] Artifact upload skipped when `BaseURL` is empty
- [x] Cache extract does not pass `--header`
- [x] Cache policy and artifact `expire_in` expanded before use
- [x] Env var names match documented names
- [x] `GIT_SSL_CAINFO` set for bundled git
- [x] User-cancel unwraps `context.Canceled`
- [x] Timeout classified as `JobExecutionTimeout`
- [x] Concrete dispatch recorded in `JobExecutionMode` metrics
- [x] Cache HEAD URL forwarded to `--check-url`
- [x] Dead `FF_CLEAN_UP_FAILED_CACHE_EXTRACT` wiring removed; divergence documented
- [x] File-based variable cleanup divergence documented
- [x] Tests cover all of the above
issue