Repository navigation
feat(planner): live retune from recorded traces through DGDR v1beta2 - #17483
Conversation
❌ Dynamo PR CI failed — run 41680495672 (attempt 1) on
|
| Framework | Snapshot |
|---|---|
| vLLM | ❌ 1 |
| Other | Jobs |
|---|---|
| dynamo-runtime | ❌ 1 ✅ 6 |
Failure details
2 jobs failed: the vLLM Snapshot vCluster setup timed out in helm waiting for a DaemonSet (infrastructure), and the dynamo-runtime CPU test job had 5 planner/common tests fail after retries before the runner's custom container implementation died mid-run, so no tracebacks were printed.
❌ vLLM Snapshot Operator Setup: helm "context deadline exceeded" waiting for vcluster-hpm-hostpath-mapper DaemonSet (4/5 ready)
Job: vLLM Snapshot Operator Setup · Failed step: Setup vCluster and operator · Logs: gh run view --job 126086337590 -R ai-dynamo/dynamo --log-failed
ready.go:336: [debug] DaemonSet is not ready: gh-id-41680495672-checkpoint-vllm-dt/vcluster-hpm-hostpath-mapper. 4 out of 5 expected pods are ready
ready.go:336: [debug] DaemonSet is not ready: gh-id-41680495672-checkpoint-vllm-dt/vcluster-hpm-hostpath-mapper. 4 out of 5 expected pods are ready
wait.go:87: [debug] Error received when checking status of resource vcluster-hpm-hostpath-mapper. Error: 'client rate limiter Wait returned an error: context deadline exceeded'
Error: context deadline exceeded
helm.go:86: [debug] context deadline exceeded
##[error]Process completed with exit code 1.
The vCluster helm install waited ~10 minutes for the vcluster-hpm-hostpath-mapper DaemonSet, but one of its 5 pods never became ready, so helm hit its deadline. This happened during K8s cluster setup, before any PR code was deployed. It is an infrastructure (K8s scheduling/pod readiness) timeout, and rerunning the failed jobs is likely enough.
❌ dynamo-runtime / test / sequential cuda13.0, amd64: 5 tests FAILED, then "Executing the custom container implementation failed"
Job: dynamo-runtime / test / sequential cuda13.0, amd64 · Failed step: Run CPU-only tests (parallelized) · Logs: gh run view --job 126092066722 -R ai-dynamo/dynamo --log-failed
components/src/dynamo/common/tests/http/test_proxy_connections.py::test_one_time_budget_covers_every_redirect_hop FAILED [ 9%]
components/src/dynamo/planner/tests/integration/test_fpm_event_delivery.py::test_endpoint_fpm_reaches_planner_and_drives_scale_up FAILED [ 29%]
components/src/dynamo/planner/tests/integration/test_live_retune_e2e.py::test_advisory_records_recommendations_and_never_writes FAILED [ 29%]
components/src/dynamo/planner/tests/integration/test_retune_sweep_workers.py::test_a_dead_worker_fails_only_its_candidate FAILED [ 29%]
components/src/dynamo/planner/tests/unit/test_system_control_api.py::test_planner_control_uses_the_actual_system_listener FAILED [ 64%]
...
components/src/dynamo/profiler/tests/integration/test_profile_sla_dgdr.py::TestAutoBackend::test_no_planner_no_load
##[error]Executing the custom container implementation failed. Please contact your self hosted runner administrator.
...
❌ pre_merge_cpu: step outcome 'failure'
##[error]A pytest stage did not record a passing result. See this step's log for the stage.
In the pre_merge_cpu stage, 5 tests failed on every attempt (3 auto-retries each). At 67%, during test_profile_sla_dgdr.py::TestAutoBackend::test_no_planner_no_load, the runner's container hook (/home/runner/k8s/index.js) stopped the test container. pytest never reached its summary, so the log has no tracebacks or assertion messages for the 5 failures. To get them, run the tests listed here locally, e.g. python3 -m pytest components/src/dynamo/planner/tests/integration/test_live_retune_e2e.py::test_advisory_records_recommendations_and_never_writes -v. The container dying looks like a runner infrastructure problem, but a rerun will not fix the 5 tests if they fail on their own.
For agents
{"pr": 17483, "run_id": 41680495672, "run_attempt": 1, "head_sha": "143a8375bbad500cd6aa659168051fabd51ad444",
"failures": [
{"job": "vLLM Snapshot Operator Setup", "job_id": 126086337590, "failed_step": "Setup vCluster and operator", "signature": "helm context deadline exceeded: DaemonSet vcluster-hpm-hostpath-mapper 4/5 pods ready (infra)", "tests": [], "log_cmd": "gh run view --job 126086337590 -R ai-dynamo/dynamo --log-failed"},
{"job": "dynamo-runtime / test / sequential cuda13.0, amd64", "job_id": 126092066722, "failed_step": "Run CPU-only tests (parallelized)", "signature": "5 pytest FAILED (after retries); then 'Executing the custom container implementation failed' killed the run before the summary", "tests": [
"components/src/dynamo/common/tests/http/test_proxy_connections.py::test_one_time_budget_covers_every_redirect_hop",
"components/src/dynamo/planner/tests/integration/test_fpm_event_delivery.py::test_endpoint_fpm_reaches_planner_and_drives_scale_up",
"components/src/dynamo/planner/tests/integration/test_live_retune_e2e.py::test_advisory_records_recommendations_and_never_writes",
"components/src/dynamo/planner/tests/integration/test_retune_sweep_workers.py::test_a_dead_worker_fails_only_its_candidate",
"components/src/dynamo/planner/tests/unit/test_system_control_api.py::test_planner_control_uses_the_actual_system_listener"], "log_cmd": "gh run view --job 126092066722 -R ai-dynamo/dynamo --log-failed"}
]}Posted automatically by Devin for run 41680495672. Updated on every full-CI run of this PR.
d8d5ee2 to
e2d17ad
Compare
e2d17ad to
a3d4cf8
Compare
Port the standalone CI fix from ai-dynamo#17483 without its DGDR changes. Original fix by hongkuanz in 934ceb3. Ignore only the unset fixture-loop-scope notice so pytest 9.2 can configure plugins under filterwarnings=error while preserving existing fixture scopes. (cherry picked from commit 934ceb3) Signed-off-by: Pranjul Gupta <pranjulgupta0203@gmail.com>
a3d4cf8 to
30884c7
Compare
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Rereviewing as contents has materially changed.
sttts
left a comment
There was a problem hiding this comment.
Six P2 findings from the combined live-retune review. The inline comments describe each trigger, production failure path, focused correction and regression coverage.
…adline - lease_duration_seconds must be at least 37 s: the 15 s lease margin plus two 11 s renewal I/O budgets with the 5 s Kubernetes request timeout. One timing policy in planner_config (the live_retune_*_seconds helpers) backs SupervisorSettings and the DgdrExecutorConfig validator, and the schema states the minimum. - While leading, the lease loop starts the next renewal at least one I/O budget before leader_until (LeaseLeadership.renewal_wait_s), so a renewal that uses its whole budget still lands inside the term. A failed renewal is retried one request timeout after it started. - Initialization keeps renewing the lease: a keepalive shares the lease loop's schedule and step lock, and ends even when the initializing task is cancelled. A lapse during initialization (LeaseLeadership acquisitions / leads_since) aborts it, and the next round initializes the new term. - LeaseLeadership no longer caps the margin at two thirds of the lease; it rejects a margin that is not below the lease duration. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Live retune fixes its scoring SLA when its controller and state fingerprint are built, and a runtime configuration update does not rebuild them. With retune.sla_ttft_ms or retune.sla_itl_ms unset, a runtime update of ttft_ms or itl_ms was accepted and reported while live retune kept scoring and creating Requests with the old SLA. While live retune runs, runtime candidate validation rejects (HTTP 422) an update that changes the effective scoring SLA and leaves the config untouched. The message says to restart the planner with the new values, or with the unset retune SLA overrides set to keep those fields changeable at runtime. Planners without live retune are unaffected. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
… selection Window files and Requests were keyed by the window end alone, so a sweep with another window start or as_of could reuse a file or Request cut for a different trace selection. - Window files are named <windows_dir>/<dgd>/<end_ms>-<selection>.jsonl.gz, where the selection is the first 12 hex digits of a SHA-256 over the window start, end and as_of. build_request takes window_start_ms and as_of_ms, so the Request's subPath, spec hash and name follow the selection, and Requests of another selection are deleted, not adopted. - The cut records the selection in the gzip header and reuses a published file only for the same selection. - The reconciler recognizes the new names as well as the old ones. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
… args in P4 P4 reads worker commands the way the operator runs them and fails closed when a value it cannot read could form a router option. - A worker without a command runs /bin/sh -c (the operator's getCommonContainer default) unless the pod runs the native "runtime" sidecar, so its one-string script is split into shell words before the router parser runs. - Env is readable, inert (POD_*, non-annotation fieldRef, resourceFieldRef) or dangerous (ConfigMap, Secret, annotation fieldRef, and names only an envFrom source may define). In exec form a dangerous reference passes only attached to its option (--opt=$(VAR)) or as the value of --speculative-config. - Shell scripts are scanned after Kubernetes substitution: readable env is substituted, an unquoted dangerous $VAR fails, and a quoted one fails as a standalone argument of the worker module, eval or a nested sh -c. A script's own assignment does not clear explicit dangerous env. Shells behind launchers (env, tini, dumb-init) and shell options with operands (-o pipefail) are recognized. - Command substitution and backticks are not evaluated; the live retune guide's Limitations table lists what P4 does not read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
The workers take envFrom from a Secret without a prefix, so live retune's P4 cannot rule out that the Secret defines LD_LIBRARY_PATH or PATH, and an unquoted reference in an export could split into more words in a shell that does not treat export as a declaration. Quoting changes nothing for bash and keeps the examples eligible for live retune. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
…annot run The pinned AISimulate's ParallelismPresetConfig has no decode_context, and its parallel mapping rejects prefill_context above 1 as predict-only, so such a preset passed P5 and then failed the Run. - P5 accepts prefill_context only when omitted or 1, and rejects decode_context with its own message. - A comment lists what to widen together when the pin moves. - The pytest marker report stubs aisimulate.config.engine. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
…s them P4 misjudged several worker shapes: - Operator env (DYN_NAMESPACE, DYN_COMPONENT, a worker's DYN_SYSTEM_*, NIXL_TELEMETRY_* and DYN_FORWARDPASS_METRIC_PORT, a multinode component's DYNAMO_RANK and DYNAMO_LEADER_ADDRESS) counts as inert container env, never as an envFrom value. - A worker whose launches are only in role pod templates is checked role by role, and P7 reads its model flags there too. - A native-sidecar worker is skipped: its main runs the engine. - An unreadable value right after --model, --model-path, --served-model-name or --model-name is that option's value; on the frontend, only --tool-call-parser, --reasoning-parser and --chat-template exempt a separate value. - The script scan sees env, export, source, eval and shells by path and behind exec, nohup, command or builtin, and a redirection target other than a here-string is never an option. - Messages name a script variable's source, give shell-form $(VAR) its own advice and say when an option's name is unreadable; the docs list the stdin, xargs and su -c forms P4 does not read. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
A renewal thread still running when stop() released the Lease could take it over again, so the successor waited a full lease duration. LeaseLeadership.release() is now final: a step that reads the Lease after it stands by and writes nothing. - The cancelled-initialization test runs the late step in a real thread. - New tests cover a lapse reported after initialization and the step lock between a rebuild and the lease loop. - The live_retune_sla_errors docstring says when an inherited SLA change would reach the controller. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: hongkuanz <hongkuanz@nvidia.com>
#17483 added live-retune test cases that pass --router-mode power-of-two to the frontend and a worker. #17899 removed that mode, and the two merged 29 minutes apart, so main's planner unit tests fail on both cases. Use least-loaded for the frontend case and drop the worker case, which the random, least-loaded and --router-mode=kv cases already cover. Refs DYN-5265 Signed-off-by: Karen Chung <karenc@nvidia.com> Signed-off-by: tanmayv25 <tanmay2592@gmail.com>
Check every row and note of the Metrics Catalog against the code, and fix what differed: - Add the 16 dynamo_planner_retune_* metrics, which #17483 added without catalog entries, as Experimental rows under Planner Metrics. - Correct descriptions that did not match the code, among them drain time, the failover switch counters, KV event ID gaps, routing overhead under queueing, the approximate cache policies, planner plugin latency and overrides, and the System One, Model Metrics, and Global Frontend notes. - Correct label and exposure claims: the model labels each backend adds, the router's component labels, the router queue labels, the mocker's engine labels, what --kserve-grpc-server exposes, and which processes emit dynamo_component_uptime_seconds. - python -m dynamo.vllm forces disable_log_stats off, so the page no longer says that --disable-log-stats turns its metrics off. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Signed-off-by: Jie Hao <jihao@nvidia.com>
Note
This PR now carries the whole live retune stack. It started as the DGDR v1beta2 trace workload (the operator part below). The five PRs stacked on it were reviewed separately and merged into this branch on 2026-11-02:
spec.workload.tracereplays a recorded trace from a PVC in DGDR v1beta2 Runsretune.executor: dgdrconfiguration and deployment premises; frontend parser builderEach layer's PR keeps its detailed description and its review follow-ups. This description summarizes the combined change, which lands on
mainas one squash commit.Overview
Periodic retune (#17095, #17540) runs only inside offline planner replay today. This PR lets a live Planner on Kubernetes retune its KV router with
retune.executor: dgdr:retune.objective.PATCH /router_policy.Live retune is EXPERIMENTAL, for development clusters only. It searches the three router knobs a DGDR Request can express (
overlap_score_credit,prefill_load_scale,temperature) with fixed replicas, so the Planner must run retune-only, with load and throughput scaling off. The defaultexecutor: localkeeps today's behavior, and the Planner's Helm RBAC is gated by the new valuedgdrV1Beta2.plannerLiveRetune(defaultfalse).User guides:
docs/fern/pages/kubernetes/auto-deployment/planner-live-retune.md(new) and the "Replay a recorded trace (v1beta2)" section of the DGDR reference.Key Changes
99 files, +34.1k/−0.3k lines, including regenerated CRDs and API reference.
Operator: DGDR v1beta2 trace workload (
deploy/operator)spec.workload.trace{format, source.persistentVolumeClaim{claimName, subPath}, replay.arrivalSpeedupRatio}, exclusive withstatic, following the trace workload in DEP DEP: Evolve DGDR for replay-backed multi-candidate search #13092.formatis optional, with the enum value and CRD defaultDynamo; lowering translates it to AISimulate's nativedynamo. CEL and the shared schema check thatclaimNameis a DNS-1123 subdomain, thatsubPathis relative with no empty,.or..segment, no NUL and at most 1024 characters, and that the speedup is greater than 0. The Run snapshot rule from feat(operator): integrate DGDR v1beta2 candidate flow #17308 now acceptsstaticortrace.+optionalor+required(no schema change for existing fields). kube-api-linter'soptionalorrequiredrule enforces it:make lint-api(part ofmake lint) and the operator Dockerfile's linter stage run it overapi/v1beta2with.golangci-kal.yml.shared_v1beta2.gomirror the CRD rules for a v1beta1 carrier stored without admission.inputOverridesstay authoritative: they are applied last as a JSON Merge Patch and may restate, replace or delete any traffic the trace lowers; the operator restores nothing. The typed claim alone decides the Job's mount and the claim the Run depends on. The Request controller no longer validates the trace; a Run create the CRD rejects as Invalid reportsInvalidSpecinstead of retrying.traffic.source{type: trace, format: dynamo, paths: [<fixed mount path>]},traffic.load.type: trace_timestamps, andtraffic.load.speedupwhen set, as an underlay for the overrides.subPathat/var/run/aisimulate/trace/trace.jsonl.gz(ortrace.jsonl), into the sweeper alone. NofsGroup; a trace Job's pod gets group 65532 as a supplemental group.nvidia.com/dgdr-run-<run-uid>to the claim with an optimistic-lock patch. Deleting the claim cancels the Run through the foreground stop path (stopAndCompleteRun); the Run fails withTraceSourceDeletedonly once the Job is gone, then releases its finalizer. A missing claim keeps the RunPending(TraceSourceMissing) until it appears; a block or lost claim fails it (TraceSourceUnavailable). A waiting sweeper or publisher container only sets theContainerWaitingdiagnostic. The newDynamoGraphDeploymentRunTraceClaimReconcilerreleases finalizers of deleted Runs once none of their Jobs is left.persistentvolumeclaimsget;list;watch;patch,podsget;list;watch,jobsdelete.internal/aisimulate/testdata/trace_request_lowering.golden.jsonpins the Planner's shard Request and the Run input it lowers to.TestDGDRV1beta2TraceRequestLoweringGoldenadmits that Request through the webhooks and CRD schema and lowers its Run; a mismatch writes<golden>.new. The planner's executor tests read the same file.Replay: common random numbers (
components/src/dynamo/replay)DynamoReplayRunner, which AISimulate's Sweeper loads and every DGDR trace Run executes, passes_deterministic=True(ordinal request ids, the canonical router seed) to both trace replay calls. This applies to every DGDR trace Run, not only the Planner's: a Run's scores no longer depend on the other candidates or the Run's parallelism. Synthetic workloads are unchanged.Planner configuration and premises (
planner/config,planner/retune, frontend and common configuration)RetuneConfig.executor(localby default, ordgdr) andRetuneConfig.dgdr(DgdrExecutorConfig,DgdrRunConfig), required if and only if the executor isdgdr.dgdr: P1 (Kubernetes, decision latency, explicittimeout_seconds ≤ interval_seconds − 600), P2 (retune-only), P3 (only the three DGDR knobs,prefill_load_model: none), P5 (an all-scalar engine with one parallelism preset and no replicas), P13 (the grid fitsrun.max_shardsshards of at most 100 points within the timeout), and safe claim paths. P13 and the executor share one shard planner (balanced_shard_parts,largest_shard_points,dgdr_rounds,dgdr_need_seconds).retune/live/frontend_config.pyparses the DGD's frontend command, args and env into the startupKvRouterConfigand evaluates the spec premises P4 and P6–P10 (evaluate_premises(dgd, *, planner_config)).retune.controller.startup_router_domainholds the router checks that depend on the frontend startup; the controller and P4 both call it.ArgEnvandfrontend_args.build_frontend_parser(env); the router, KV router and frontend argument groups take an optionalenv. Existing callers pass none and are unchanged.executor: dgdr(replay/api.py); replay retune runsexecutor: local.Window cut and reconciler (
planner/retune/live)window_cut.pymerges each frontend pod'srequest_endjsonl.gz segments into<windows_dir>/<dgd>/<window_end_ms>.jsonl.gz, with the same rows asretune.window.read_trace_window. It runs in a niced, budgeted child process, validates each gzip member (CRC32, ISIZE), excuses a truncated tail at the end of any segment, fails a mostly corrupt window (trace_corrupt), bounds memory bymax_window_rows, and publishes atomically with mode0644(the Run's sweeper reads as uid 1000 with group 65532). The output's gzip header comment holds the cut's counts, so a later leader reuses a published window without reading segments again.reconciler.pygarbage-collects finished Requests, window files no live pod reads, cut temp files and old segments, asking the caller before every delete or Kubernetes read so a round stops when leadership is lost. It is also the ref-countedSweepRegistrythat protects in-flight windows.DGDR sweep executor (
planner/retune/live)dgdr.py(run_dgdr_sweep) splits the router grid into balanced shards and creates one Request per shard with the trace workload, the pinnedretune.dgdr.engine, the DGD's replica counts and their GPU total, andgenerator: direct. An off-grid baseline gets its own Request, and a common-random-numbers probe re-scores one grid point (relative error ≤ 1e-9, elsecrn_mismatch).status.aisimulate.inputagainst the Request with a subset check (the operator golden is the oracle), waits on Runs, and scores Candidates withretune.objective. Open-Run reasons (ContainerWaiting,TraceSourceMissing,RunNameConflict, …) show up in the shard status and errors. It never raises and never deletes; on shutdown or lost leadership it returns at once and leaves the Requests to the next leader.kube.py(KubernetesRetuneKube) implements the Kubernetes calls over the official client with request timeouts and status-carrying errors; Leases round-trip without model deserialization.Live retune on the Planner (
planner, Helm, docs)supervisor.py(LiveRetuneSupervisor) runs each window: epoch-aligned windows that survive restarts, leadership, premise and time-budget checks, advisory and active modes, and a two-phase rollback to the startup parameters. Each decision is persisted before any router sees it, and each router's latched initial before the actuator moves that router.stopaborts the sweep and releases leadership before the engine shuts down.state.py: the leadership Lease<dgd>-planner-retuneand the state Lease<dgd>-planner-retune-state, with writes fenced by leader term and deploy sequence, resourceVersion preconditions on decommission deletes, and an unknown format version refusing initialization.actuator.pyreads and sets the eight/router_policyparameters on every frontend router with revision-checked PATCH and reset, reverts manual changes outside advisory mode, and treats a router as gone only once every pod instance it ran on is gone, finished or restarted.metrics.pyandbootstrap.pyadd the Prometheus metrics and the wiring.retune/controller.pygains optional hooks (externalsweep_fn, launch and harvest gates, generation, a shared single-thread executor); the replay path passes none and is unchanged.engine_adapter.py,core/base.pyand__main__.pywire the supervisor; a live Planner now rejects onlyexecutor: local. A Kubernetes Planner withoutretunechecks in the background whether a removed live retune left its Leases and cleans up. SIGTERM cancels the run so the Lease is released before exit.planner.yaml: withdgdrV1Beta2.enabledanddgdrV1Beta2.plannerLiveRetune, the Planner Role and ClusterRole gaincreate/get/list/deleteon DGDR Requests,geton Runs,liston Candidates andget/create/update/deleteon Leases, with helm-unittest cases.retune.executorandretune.dgdrinplanner-configuration.mdx, and executor notes in the planner guide (en and zh-CN),planner-design.mdandaisimulate-planner-replay.mdx.Behavior notes
--router-modeorDYN_ROUTER_MODEon a worker, such as minimax-m3 and solar-open2) fail P4 by design: the Run replays only the frontend's configuration./router_policyis the frontend's unauthenticated admin API; the guide explains how to deny it at L7.plannerLiveRetune=truePlanners withoutretuneget the live retune rules too. The guide lists what that allows.Validation
CI on this head (
08c5eb9661) runs the whole stack together for the first time. Local checks from the last review follow-up:go build,go vet(no tags andclustertest)03106cf4d3go test ./api/... ./internal/aisimulate/... ./internal/webhook/... ./internal/controller/(envtest, golden in compare mode)03106cf4d3make lint(golangci-lint andlint-api)03106cf4d3integration/test_live_retune_e2e.py, frontend parser builder and common configuration tests08c5eb9661pre-commitover every layer's follow-ups08c5eb9661docs_lint.py08c5eb9661The operator code did not change above
03106cf4d3. The Helm RBAC tests were checked againsthelm templateoutput; helm-unittest was not run locally after the follow-ups. Each layer's PR has its per-layer runs.Development cluster. Before the review follow-ups, the pre-split branch ran on an H200 development cluster (vcluster, operator with
dgdrV1Beta2.enabled=true,Qwen/Qwen3-0.6Bon vLLM, one KV-router frontend recording traces,interval_seconds: 1200,run.parallelism: 2,max_shards: 3):overlap_score_credit: {choices: [0.5, 1.0]}, objectiveGoodputPerGPUkept(one worker makes the knobs irrelevant). A manualPATCH /router_policywas reverted within 10 s.DYN_ROUTER_TEMPERATURE=1.0, gridtemperature: {choices: [0.0, 1.0]}, objectiveTTFTapplied: simulated mean TTFT 4.493 ms at 1.0 and 3.778 ms at 0.0 (−15.9 %). The frontend applied temperature 0.0 at revision 1 two seconds later.That run used the earlier trace fields (
source.pvc.path,format: dynamo) and a chart withoutplannerLiveRetune; it has not been repeated since.Not verified:
applieddecision, the advisory →promote_last_advisorypath, and several frontends.system:mastersinstall.Issues and Ongoing Work
ContainerWaitinguntil the cause is fixed or the Run is cancelled. On a volume type whose node directory the kubelet can write, such as hostPath, a missing file becomes an empty directory and the Run fails in AISimulate.Terminatingthroughkubernetes.io/pvc-protectionuntil their Runs are retired. If the operator is removed while trace Runs are in flight, their finalizers stay on the claim; the DGDR reference shows how to remove them.kv_cache.block_sizefails in the default AIC generator. The Planner's Requests usegenerator: direct.Pull Request Checklist
/pr-checklistskill.🤖 Generated with Claude Code