Upload 8 files
Browse files- web/static/app.css +10 -0
- web/static/app.js +105 -15
- web/static/runs.js +55 -6
web/static/app.css
CHANGED
|
@@ -3041,3 +3041,13 @@ strong,p,h1,h2,h3,h4,span,a,button,div,li{overflow-wrap:break-word;word-break:no
|
|
| 3041 |
/* v190.24 — Build-first Runs Explorer polish */
|
| 3042 |
/* v190.24 — Build-first compatibility cleanup */
|
| 3043 |
/* v190.24 — Delete cascade clarity */
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3041 |
/* v190.24 — Build-first Runs Explorer polish */
|
| 3042 |
/* v190.24 — Build-first compatibility cleanup */
|
| 3043 |
/* v190.24 — Delete cascade clarity */
|
| 3044 |
+
|
| 3045 |
+
/* v190.28 — Space Test Validation reliability */
|
| 3046 |
+
.space-test-reset-state .validation-progress-bar,
|
| 3047 |
+
.space-test-reset-state #spaceTestTimeline{display:none!important;}
|
| 3048 |
+
.validation-args-note.launch-readiness.blocked{background:#fff7ed;border-color:#fed7aa;color:#9a3412;}
|
| 3049 |
+
.validation-args-note.launch-readiness.ready{background:#ecfdf5;border-color:#bbf7d0;color:#166534;}
|
| 3050 |
+
/* v190.28 — Build-first Runs Explorer polish */
|
| 3051 |
+
/* v190.28 — Build-first compatibility cleanup */
|
| 3052 |
+
/* v190.28 — Delete cascade clarity */
|
| 3053 |
+
/* v190.28 — Effective eval and linked validation provenance */
|
web/static/app.js
CHANGED
|
@@ -559,7 +559,70 @@ function resetRunDetails(){
|
|
| 559 |
renderActiveRunEmptyState();
|
| 560 |
} function prepareNewBuild(){if(state.poll){clearInterval(state.poll);state.poll=null}state.runId=null;state.activeRunProgress=null;state.selectedRunDetail=null;state.documentCache={};state.latencyCache={};state.activeLinks={};state.pollErrors=0;clearSavedRun();document.querySelectorAll('.run-row').forEach(r=>r.classList.remove('selected'));setBuildModeNew();resetRunDetails();setText('progressPercent','0%');const cap=$('progressCaptionLabel');if(cap)cap.textContent='Overall progress';const sem=$('progressSemantics');if(sem){sem.hidden=true;sem.innerHTML=''}const fill=$('progressFill');if(fill)fill.style.width='0%';setText('currentStep','Ready');setText('lastEvent','Choose a model card and launch a build.');setText('elapsed','—');if(typeof elapsedClock!=='undefined')elapsedClock.isRunning=false;setText('lastPolled','—');setText('hardwarePlan',hardwarePlanLabel());renderMetrics({});showMessage('New build mode ready.','info')}
|
| 561 |
function renderQuietLaunchState(result={}){setText('progressTitle','Starting build Job…');setText('progressStatus','Running');const statusEl=$('progressStatus');if(statusEl)statusEl.className='badge '+statusClass('running');setText('progressPercent','1%');const fill=$('progressFill');if(fill)fill.style.width='1%';setText('lastEvent','Build Job launched; waiting for the first canonical run snapshot.');setText('elapsed','—');setText('lastPolled','—');const timeline=$('timeline');if(timeline){timeline.innerHTML='<div class="timeline-skeleton">Waiting for first run snapshot…</div>';timeline.classList.remove('timeline-canonical');timeline.style.gridTemplateColumns=''}const note=$('timelineTraceNote');if(note){note.hidden=true;note.innerHTML=''}const details=$('timelinePhaseDetails');if(details){details.hidden=true;details.innerHTML='';details.className='timeline-phase-details'}}
|
| 562 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 563 |
function startPolling(runId,options={}){
|
| 564 |
if(!runId)return;
|
| 565 |
const sameRun=state.runId===runId;
|
|
@@ -754,13 +817,23 @@ function validationPrefillFromDetail(detail={}){
|
|
| 754 |
const gate={...(detail.inference_gate||{}),...(progress.inference_gate||{})};
|
| 755 |
const gateSmoke=gate.generation_smoke&&typeof gate.generation_smoke==='object'?gate.generation_smoke:{};
|
| 756 |
const smoke={...(detail.state?.generation_smoke||{}),...(detail.tests?.generation_smoke||{}),...(detail.generation_smoke||{}),...(progress.generation_smoke||{}),...(progress.state?.generation_smoke||{}),...gateSmoke};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 757 |
const launch={...(detail.launch||{}),...(progress.launch||{})};
|
| 758 |
const stateObj={...(detail.state||{}),...(progress.state||{})};
|
| 759 |
const expected=smoke.expected_output_type||gate.expected_output_type||launch.expected_output_type||summary.expected_output_type||stateObj.expected_output_type||formValue('buildExpectedOutput')||'text';
|
| 760 |
const endpointParameters=smoke.parameters||smoke.endpoint_parameters||gate.endpoint_parameters||gate.smoke_parameters||[];
|
| 761 |
-
let args=firstArrayPath(smoke.effective_args,smoke.test_args,smoke.args,gate.effective_args,gate.test_args,gateSmoke.effective_args,gateSmoke.test_args,launch.test_args_json,summary.test_args_json);
|
| 762 |
if(!Array.isArray(args))args=testPayloadFromEndpointParameters(endpointParameters,expected);
|
| 763 |
-
let kwargs=firstObjectPath(smoke.effective_kwargs,smoke.test_kwargs,smoke.kwargs,gate.effective_kwargs,gate.test_kwargs,gateSmoke.effective_kwargs,gateSmoke.test_kwargs,launch.test_kwargs_json,summary.test_kwargs_json);
|
| 764 |
if(!Array.isArray(args))args=defaultValidationArgs(expected);
|
| 765 |
if(!kwargs||Array.isArray(kwargs)||typeof kwargs!=='object')kwargs={};
|
| 766 |
const policy=detail.space_test_policy||detail.view?.space_test_policy||detail.space_test?.policy||progress.view?.space_test_policy||progress.view?.space_test?.policy||{};
|
|
@@ -768,8 +841,9 @@ function validationPrefillFromDetail(detail={}){
|
|
| 768 |
const api=policy.requires_endpoint_discovery?'':normalizeApiName(policy.endpoint||smoke.api_name||gate.api_name||launch.api_name||gateSmoke.api_name||progress.api_name||'/generate');
|
| 769 |
const parentBuildRunId=policy.parent_build_run_id||detail.run_id||detail.summary?.run_id||state.runId||progress.run_id||'';
|
| 770 |
const automaticSmokePassed=Boolean(smoke.ok||smoke.status==='success'||policy.mode==='replay');
|
| 771 |
-
const
|
| 772 |
-
|
|
|
|
| 773 |
}
|
| 774 |
function setValidationProgressVisible(visible){
|
| 775 |
const show=Boolean(visible);
|
|
@@ -867,7 +941,10 @@ function renderValidationStatus(data={}){
|
|
| 867 |
setText('validationStartedAt',isIdle?'Not launched':formatTime(data.updated_at||summary.updated_at||data.state?.updated_at||data.created_at||summary.created_at||new Date().toISOString()));
|
| 868 |
const latency=firstPositiveNumber(smoke.latency_seconds,smoke.observed_latency_seconds,summary.latency_seconds,summary.observed_latency_seconds,data.latency_seconds,data.observed_latency_seconds);
|
| 869 |
setText('spaceTestLatency',isIdle?'—':(latency?formatLatencySeconds(latency):(canonical==='running'?'—':'Not recorded')));
|
| 870 |
-
|
|
|
|
|
|
|
|
|
|
| 871 |
const launchBtn=$('launchValidate');
|
| 872 |
if(launchBtn&&!(launchBtn.classList?.contains&&launchBtn.classList.contains('is-busy'))){
|
| 873 |
const draft=state.validationPrefillDraft||{};
|
|
@@ -1002,6 +1079,8 @@ function renderValidationPrefillDraft(prefill={},sourceLabel='selected Space'){
|
|
| 1002 |
const readiness=prefill.requiresEndpointDiscovery?'Discovery first':'Ready to launch';
|
| 1003 |
endpoints.innerHTML=`<div class="linked-context-card linked-context-card--pretty"><span>Linked Build Run</span><strong><code>${escapeHtml(state.validationPrefillDraft.parentBuildRunId||'—')}</code></strong><span>Target Space</span><strong>${targetLine}</strong><span>Mode</span><strong>${modeLabel}</strong><span>Endpoint</span><strong>${endpointLine}</strong><span>Payload source</span><strong>${payloadSource}</strong><span>Automatic smoke</span><strong>${latencyLine}</strong><span>Launch readiness</span><strong>${escapeHtml(readiness)}</strong></div>`;
|
| 1004 |
}
|
|
|
|
|
|
|
| 1005 |
const launchBtn=$('launchValidate');
|
| 1006 |
if(launchBtn&&!launchBtn.classList.contains('is-busy'))launchBtn.textContent=spaceTestLaunchLabel(prefill);
|
| 1007 |
setValidationLaunchEnabled();
|
|
@@ -1030,18 +1109,27 @@ function prepareValidationFromActiveRun(){
|
|
| 1030 |
function contextualizeSpaceTestFromBuildRun(detail={}){
|
| 1031 |
if(!detail||typeof detail!=='object')return;
|
| 1032 |
if(typeof isValidationRunDetail==='function'&&isValidationRunDetail(detail))return;
|
| 1033 |
-
if(state.validationMode==='running')return;
|
| 1034 |
const prefill=validationPrefillFromDetail(detail);
|
| 1035 |
if(!prefill.parentBuildRunId||!prefill.target||prefill.target==='—')return;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1036 |
state.validationPrefillDraft={...prefill,sourceLabel:'selected Build Run',parentBuildRunId:prefill.parentBuildRunId,sourceRunId:prefill.parentBuildRunId,linkedTargetSpace:prefill.target};
|
| 1037 |
state.linkedValidationParent=prefill.parentBuildRunId;
|
| 1038 |
-
|
| 1039 |
-
|
| 1040 |
-
|
| 1041 |
-
|
| 1042 |
-
|
| 1043 |
-
|
| 1044 |
-
}
|
| 1045 |
if(state.centerTab==='validate'){
|
| 1046 |
renderValidationPrefillDraft(prefill,'selected Build Run');
|
| 1047 |
}else{
|
|
@@ -1078,7 +1166,9 @@ async function launchValidate(){
|
|
| 1078 |
test_kwargs_json:prettyJson(resolved.kwargs),
|
| 1079 |
live_timeout_seconds:resolved.timeout,
|
| 1080 |
validation_mode:resolved.validationMode,
|
| 1081 |
-
payload_source:resolved.payloadSource
|
|
|
|
|
|
|
| 1082 |
};
|
| 1083 |
const result=await apiPost('/api/validate',payload);
|
| 1084 |
state.validationArgsDirty=false;
|
|
|
|
| 559 |
renderActiveRunEmptyState();
|
| 560 |
} function prepareNewBuild(){if(state.poll){clearInterval(state.poll);state.poll=null}state.runId=null;state.activeRunProgress=null;state.selectedRunDetail=null;state.documentCache={};state.latencyCache={};state.activeLinks={};state.pollErrors=0;clearSavedRun();document.querySelectorAll('.run-row').forEach(r=>r.classList.remove('selected'));setBuildModeNew();resetRunDetails();setText('progressPercent','0%');const cap=$('progressCaptionLabel');if(cap)cap.textContent='Overall progress';const sem=$('progressSemantics');if(sem){sem.hidden=true;sem.innerHTML=''}const fill=$('progressFill');if(fill)fill.style.width='0%';setText('currentStep','Ready');setText('lastEvent','Choose a model card and launch a build.');setText('elapsed','—');if(typeof elapsedClock!=='undefined')elapsedClock.isRunning=false;setText('lastPolled','—');setText('hardwarePlan',hardwarePlanLabel());renderMetrics({});showMessage('New build mode ready.','info')}
|
| 561 |
function renderQuietLaunchState(result={}){setText('progressTitle','Starting build Job…');setText('progressStatus','Running');const statusEl=$('progressStatus');if(statusEl)statusEl.className='badge '+statusClass('running');setText('progressPercent','1%');const fill=$('progressFill');if(fill)fill.style.width='1%';setText('lastEvent','Build Job launched; waiting for the first canonical run snapshot.');setText('elapsed','—');setText('lastPolled','—');const timeline=$('timeline');if(timeline){timeline.innerHTML='<div class="timeline-skeleton">Waiting for first run snapshot…</div>';timeline.classList.remove('timeline-canonical');timeline.style.gridTemplateColumns=''}const note=$('timelineTraceNote');if(note){note.hidden=true;note.innerHTML=''}const details=$('timelinePhaseDetails');if(details){details.hidden=true;details.innerHTML='';details.className='timeline-phase-details'}}
|
| 562 |
+
|
| 563 |
+
function resetSpaceTestForNewBuild(runId=''){
|
| 564 |
+
if(typeof stopValidationPolling==='function')stopValidationPolling();
|
| 565 |
+
state.validationRequestSeq=(state.validationRequestSeq||0)+1;
|
| 566 |
+
state.validationPollToken=null;
|
| 567 |
+
state.validationRunId=null;
|
| 568 |
+
state.validationDetail=null;
|
| 569 |
+
state.validationMode='idle';
|
| 570 |
+
state.validationPollErrors=0;
|
| 571 |
+
state.validationPrefillDraft=null;
|
| 572 |
+
state.linkedValidationParent=null;
|
| 573 |
+
state.validationArgsDirty=false;
|
| 574 |
+
const note=$('spaceTestArgsNote');if(note)note.hidden=true;
|
| 575 |
+
const readiness=$('spaceTestLaunchReadiness');if(readiness){readiness.hidden=false;readiness.className='validation-args-note launch-readiness blocked';readiness.textContent='Space Test will be available after this build reaches a final Space state.';}
|
| 576 |
+
setInputValue('validateSpace','');
|
| 577 |
+
setInputValue('validateApi','');
|
| 578 |
+
setInputValue('testArgs',prettyJson(defaultValidationArgs(formValue('buildExpectedOutput')||'image')));
|
| 579 |
+
setInputValue('testKwargs','{}');
|
| 580 |
+
setText('spaceTestEndpoint','—');
|
| 581 |
+
setText('spaceTestOutput','Not launched');
|
| 582 |
+
setText('validationStartedAt','Not launched');
|
| 583 |
+
setText('spaceTestLatency','—');
|
| 584 |
+
setText('spaceTestVerdict',runId?`Waiting for Build Run ${runId} to finish.`:'Waiting for a Build Run to finish.');
|
| 585 |
+
const badge=$('spaceTestStatus');if(badge){badge.textContent='Blocked';badge.className='badge neutral';}
|
| 586 |
+
const tabDot=$('spaceTestTabDot');if(tabDot)tabDot.className='tab-status-dot neutral';
|
| 587 |
+
const timeline=$('spaceTestTimeline');if(timeline){timeline.hidden=true;timeline.innerHTML='';}
|
| 588 |
+
setValidationProgressVisible(false);
|
| 589 |
+
const deleteBtn=$('deleteValidationRun');if(deleteBtn)deleteBtn.disabled=true;
|
| 590 |
+
const launchBtn=$('launchValidate');if(launchBtn){launchBtn.textContent='Run linked validation';launchBtn.disabled=true;launchBtn.title='Available after the build reaches a final Space state.';}
|
| 591 |
+
const endpoints=$('spaceTestEndpoints');if(endpoints){endpoints.innerHTML='<div class="linked-context-card linked-context-card--compact"><span>Space Test</span><strong>Waiting for current Build Run to finish</strong></div>';}
|
| 592 |
+
}
|
| 593 |
+
|
| 594 |
+
|
| 595 |
+
function clearValidationRunStateForBuildContext(parentRunId='',reason='build_selection'){
|
| 596 |
+
if(typeof stopValidationPolling==='function')stopValidationPolling();
|
| 597 |
+
state.validationRequestSeq=(state.validationRequestSeq||0)+1;
|
| 598 |
+
state.validationPollToken=null;
|
| 599 |
+
state.validationRunId=null;
|
| 600 |
+
state.validationDetail=null;
|
| 601 |
+
state.validationMode='idle';
|
| 602 |
+
state.validationPollErrors=0;
|
| 603 |
+
state.validationArgsDirty=false;
|
| 604 |
+
state.validationPrefillDraft=null;
|
| 605 |
+
state.linkedValidationParent=parentRunId||null;
|
| 606 |
+
const note=$('spaceTestArgsNote');if(note)note.hidden=true;
|
| 607 |
+
setText('spaceTestOutput','Not launched');
|
| 608 |
+
setText('validationStartedAt','Not launched');
|
| 609 |
+
setText('spaceTestLatency','—');
|
| 610 |
+
setText('spaceTestVerdict',parentRunId?`Linked to Build Run ${parentRunId}. No validation run launched yet.`:'Select a Build Run to prepare Space Test.');
|
| 611 |
+
setText('spaceTestEndpoint','—');
|
| 612 |
+
const timeline=$('spaceTestTimeline');if(timeline){timeline.hidden=true;timeline.innerHTML='';timeline.dataset.parentRunId=parentRunId||'';}
|
| 613 |
+
setValidationProgressVisible(false);
|
| 614 |
+
const deleteBtn=$('deleteValidationRun');if(deleteBtn){deleteBtn.disabled=true;deleteBtn.onclick=null;}
|
| 615 |
+
const tabDot=$('spaceTestTabDot');if(tabDot){tabDot.className='tab-status-dot neutral';tabDot.title='No active linked validation';}
|
| 616 |
+
const badge=$('spaceTestStatus');if(badge){badge.textContent='Preparing';badge.className='badge neutral';}
|
| 617 |
+
const card=$('spaceTestPreview');if(card){card.classList.remove('validation-running','validation-success','validation-error');card.classList.add('space-test-context-only');}
|
| 618 |
+
const readiness=$('spaceTestLaunchReadiness');if(readiness){readiness.hidden=false;readiness.className='validation-args-note launch-readiness blocked';readiness.textContent='Preparing Space Test context for the selected Build Run.';}
|
| 619 |
+
return true;
|
| 620 |
+
}
|
| 621 |
+
function requestSpaceTestContextResetForBuild(runId){
|
| 622 |
+
state.spaceTestContextResetForRun=runId||true;
|
| 623 |
+
}
|
| 624 |
+
|
| 625 |
+
function setActiveRun(result){if(state.poll){clearInterval(state.poll);state.poll=null}resetSpaceTestForNewBuild(result?.run_id||'');resetRunDetails();state.documentCache={};state.latencyCache={};state.runId=result.run_id;state.spaceLinksUnlockedFor=null;if(Array.isArray(state.runsCache)&&typeof sortRunsNewestFirst==='function'){state.runsCache=sortRunsNewestFirst([{...result,run_id:result.run_id,status:result.status||'running',created_at:result.created_at||new Date().toISOString()},...state.runsCache.filter(r=>r.run_id!==result.run_id)]);renderRunsFromCache();if(typeof renderRunStats==='function')renderRunStats();}if(result.bucket_source)state.bucketSource=result.bucket_source;setText('detailRunId',result.run_id);setText('detailJobStatus',result.status||'RUNNING');setText('detailGateStatus',result.kind||'running');setText('detailSpace',result.target_space||'—');setText('detailHardware',result.selected_hardware||result.preferred_space_hardware||'—');renderActiveRunMeta({summary:result,state:result,launch:result});renderQuietLaunchState(result);setText('homeRunDetailStatus',result.status||'Running');setBuildModeInspecting(result.run_id);setQuickLinks({...result.links,bucket_source:result.bucket_source,run_id:result.run_id,job_id:result.job_id,job_owner:state.user?.username,target_space_url:result.target_space_url},result);saveActiveRun();markPendingActiveFields();startPolling(result.run_id)}
|
| 626 |
function startPolling(runId,options={}){
|
| 627 |
if(!runId)return;
|
| 628 |
const sameRun=state.runId===runId;
|
|
|
|
| 817 |
const gate={...(detail.inference_gate||{}),...(progress.inference_gate||{})};
|
| 818 |
const gateSmoke=gate.generation_smoke&&typeof gate.generation_smoke==='object'?gate.generation_smoke:{};
|
| 819 |
const smoke={...(detail.state?.generation_smoke||{}),...(detail.tests?.generation_smoke||{}),...(detail.generation_smoke||{}),...(progress.generation_smoke||{}),...(progress.state?.generation_smoke||{}),...gateSmoke};
|
| 820 |
+
const smokePayload=firstObjectPath(
|
| 821 |
+
detail.generation_smoke_payload_retry,
|
| 822 |
+
detail.tests?.generation_smoke_payload_retry,
|
| 823 |
+
progress.generation_smoke_payload_retry,
|
| 824 |
+
progress.tests?.generation_smoke_payload_retry,
|
| 825 |
+
detail.generation_smoke_payload,
|
| 826 |
+
detail.tests?.generation_smoke_payload,
|
| 827 |
+
progress.generation_smoke_payload,
|
| 828 |
+
progress.tests?.generation_smoke_payload
|
| 829 |
+
)||{};
|
| 830 |
const launch={...(detail.launch||{}),...(progress.launch||{})};
|
| 831 |
const stateObj={...(detail.state||{}),...(progress.state||{})};
|
| 832 |
const expected=smoke.expected_output_type||gate.expected_output_type||launch.expected_output_type||summary.expected_output_type||stateObj.expected_output_type||formValue('buildExpectedOutput')||'text';
|
| 833 |
const endpointParameters=smoke.parameters||smoke.endpoint_parameters||gate.endpoint_parameters||gate.smoke_parameters||[];
|
| 834 |
+
let args=firstArrayPath(smoke.effective_args,smoke.test_args,smoke.args,smokePayload.effective_args,smokePayload.test_args,smokePayload.args,gate.effective_args,gate.test_args,gateSmoke.effective_args,gateSmoke.test_args,launch.test_args_json,summary.test_args_json);
|
| 835 |
if(!Array.isArray(args))args=testPayloadFromEndpointParameters(endpointParameters,expected);
|
| 836 |
+
let kwargs=firstObjectPath(smoke.effective_kwargs,smoke.test_kwargs,smoke.kwargs,smokePayload.effective_kwargs,smokePayload.test_kwargs,smokePayload.kwargs,gate.effective_kwargs,gate.test_kwargs,gateSmoke.effective_kwargs,gateSmoke.test_kwargs,launch.test_kwargs_json,summary.test_kwargs_json);
|
| 837 |
if(!Array.isArray(args))args=defaultValidationArgs(expected);
|
| 838 |
if(!kwargs||Array.isArray(kwargs)||typeof kwargs!=='object')kwargs={};
|
| 839 |
const policy=detail.space_test_policy||detail.view?.space_test_policy||detail.space_test?.policy||progress.view?.space_test_policy||progress.view?.space_test?.policy||{};
|
|
|
|
| 841 |
const api=policy.requires_endpoint_discovery?'':normalizeApiName(policy.endpoint||smoke.api_name||gate.api_name||launch.api_name||gateSmoke.api_name||progress.api_name||'/generate');
|
| 842 |
const parentBuildRunId=policy.parent_build_run_id||detail.run_id||detail.summary?.run_id||state.runId||progress.run_id||'';
|
| 843 |
const automaticSmokePassed=Boolean(smoke.ok||smoke.status==='success'||policy.mode==='replay');
|
| 844 |
+
const smokeArtifactHasPayload=Boolean(smokePayload.effective_args||smokePayload.test_args||smokePayload.args);
|
| 845 |
+
const payloadSource=policy.requires_endpoint_discovery?'endpoint_discovery_first':((smoke.effective_args||smoke.test_args||smoke.args||smokeArtifactHasPayload)?'automatic_smoke_artifact':(endpointParameters.length?'gradio_schema_defaults':'default_payload'));
|
| 846 |
+
return {target,api,expected,args,kwargs,parentBuildRunId,sourceRunId:parentBuildRunId,linkedTargetSpace:target,automaticSmokePassed,smokeLatency:smoke.latency_seconds||smoke.observed_latency_seconds,spaceTestPolicy:policy,requiresEndpointDiscovery:Boolean(policy.requires_endpoint_discovery),payloadSource,smokeArtifactPayloadAvailable:smokeArtifactHasPayload};
|
| 847 |
}
|
| 848 |
function setValidationProgressVisible(visible){
|
| 849 |
const show=Boolean(visible);
|
|
|
|
| 941 |
setText('validationStartedAt',isIdle?'Not launched':formatTime(data.updated_at||summary.updated_at||data.state?.updated_at||data.created_at||summary.created_at||new Date().toISOString()));
|
| 942 |
const latency=firstPositiveNumber(smoke.latency_seconds,smoke.observed_latency_seconds,summary.latency_seconds,summary.observed_latency_seconds,data.latency_seconds,data.observed_latency_seconds);
|
| 943 |
setText('spaceTestLatency',isIdle?'—':(latency?formatLatencySeconds(latency):(canonical==='running'?'—':'Not recorded')));
|
| 944 |
+
const diagnosis=data.validation_failure_diagnosis||data.summary?.validation_failure_diagnosis||data.state?.validation_failure_diagnosis||smoke.validation_failure_diagnosis||{};
|
| 945 |
+
const diagnosisMsg=diagnosis.message||diagnosis.error||diagnosis.failure_reason||diagnosis.failure_type||smoke.error||summary.error||data.error||'';
|
| 946 |
+
const verdictText=isIdle?(data.message||'No validation run selected.'):data._refreshing?`${badgeLabel(displayStatus)} · Refreshing…`:(canonical==='failed'&&diagnosisMsg?`Failed · ${String(diagnosisMsg).slice(0,220)}`:badgeLabel(displayStatus));
|
| 947 |
+
setText('spaceTestVerdict',verdictText);
|
| 948 |
const launchBtn=$('launchValidate');
|
| 949 |
if(launchBtn&&!(launchBtn.classList?.contains&&launchBtn.classList.contains('is-busy'))){
|
| 950 |
const draft=state.validationPrefillDraft||{};
|
|
|
|
| 1079 |
const readiness=prefill.requiresEndpointDiscovery?'Discovery first':'Ready to launch';
|
| 1080 |
endpoints.innerHTML=`<div class="linked-context-card linked-context-card--pretty"><span>Linked Build Run</span><strong><code>${escapeHtml(state.validationPrefillDraft.parentBuildRunId||'—')}</code></strong><span>Target Space</span><strong>${targetLine}</strong><span>Mode</span><strong>${modeLabel}</strong><span>Endpoint</span><strong>${endpointLine}</strong><span>Payload source</span><strong>${payloadSource}</strong><span>Automatic smoke</span><strong>${latencyLine}</strong><span>Launch readiness</span><strong>${escapeHtml(readiness)}</strong></div>`;
|
| 1081 |
}
|
| 1082 |
+
const note=$('spaceTestArgsNote');
|
| 1083 |
+
if(note){note.hidden=false;note.textContent=`Payload source: ${String(prefill.payloadSource||'linked_payload').replace(/_/g,' ')}.`;}
|
| 1084 |
const launchBtn=$('launchValidate');
|
| 1085 |
if(launchBtn&&!launchBtn.classList.contains('is-busy'))launchBtn.textContent=spaceTestLaunchLabel(prefill);
|
| 1086 |
setValidationLaunchEnabled();
|
|
|
|
| 1109 |
function contextualizeSpaceTestFromBuildRun(detail={}){
|
| 1110 |
if(!detail||typeof detail!=='object')return;
|
| 1111 |
if(typeof isValidationRunDetail==='function'&&isValidationRunDetail(detail))return;
|
|
|
|
| 1112 |
const prefill=validationPrefillFromDetail(detail);
|
| 1113 |
if(!prefill.parentBuildRunId||!prefill.target||prefill.target==='—')return;
|
| 1114 |
+
const nextParent=String(prefill.parentBuildRunId||'');
|
| 1115 |
+
const currentParent=String(state.linkedValidationParent||state.validationPrefillDraft?.parentBuildRunId||'');
|
| 1116 |
+
const explicitReset=state.spaceTestContextResetForRun===true||state.spaceTestContextResetForRun===nextParent;
|
| 1117 |
+
const parentChanged=Boolean(currentParent&&nextParent&¤tParent!==nextParent);
|
| 1118 |
+
if(explicitReset||parentChanged){
|
| 1119 |
+
clearValidationRunStateForBuildContext(nextParent,'build_selection');
|
| 1120 |
+
state.spaceTestContextResetForRun=null;
|
| 1121 |
+
}else if(state.validationMode==='running'&¤tParent===nextParent){
|
| 1122 |
+
return;
|
| 1123 |
+
}
|
| 1124 |
state.validationPrefillDraft={...prefill,sourceLabel:'selected Build Run',parentBuildRunId:prefill.parentBuildRunId,sourceRunId:prefill.parentBuildRunId,linkedTargetSpace:prefill.target};
|
| 1125 |
state.linkedValidationParent=prefill.parentBuildRunId;
|
| 1126 |
+
state.validationArgsDirty=false;
|
| 1127 |
+
setInputValue('validateSpace',prefill.target);
|
| 1128 |
+
setInputValue('expectedOutput',prefill.expected);
|
| 1129 |
+
setInputValue('validateApi',prefill.api);
|
| 1130 |
+
setInputValue('testArgs',prettyJson(prefill.args));
|
| 1131 |
+
setInputValue('testKwargs',prettyJson(prefill.kwargs));
|
| 1132 |
+
const note=$('spaceTestArgsNote');if(note){note.hidden=false;note.textContent=`Payload source: ${String(prefill.payloadSource||'linked_payload').replace(/_/g,' ')}.`;}
|
| 1133 |
if(state.centerTab==='validate'){
|
| 1134 |
renderValidationPrefillDraft(prefill,'selected Build Run');
|
| 1135 |
}else{
|
|
|
|
| 1166 |
test_kwargs_json:prettyJson(resolved.kwargs),
|
| 1167 |
live_timeout_seconds:resolved.timeout,
|
| 1168 |
validation_mode:resolved.validationMode,
|
| 1169 |
+
payload_source:resolved.payloadSource,
|
| 1170 |
+
ui_payload_arg_count:Array.isArray(resolved.args)?resolved.args.length:0,
|
| 1171 |
+
ui_payload_kwargs_keys:resolved.kwargs&&typeof resolved.kwargs==='object'?Object.keys(resolved.kwargs):[]
|
| 1172 |
};
|
| 1173 |
const result=await apiPost('/api/validate',payload);
|
| 1174 |
state.validationArgsDirty=false;
|
web/static/runs.js
CHANGED
|
@@ -255,14 +255,60 @@ function runNeedsLinkedValidation(run={}){
|
|
| 255 |
return ['complete','recover'].includes(String(policy.mode||'').toLowerCase())&&policy.enabled!==false&&!buildManualValidationStatus(run).passed;
|
| 256 |
}
|
| 257 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 258 |
function buildManualValidationStatus(run={}){
|
| 259 |
run=safeRunObject(run);
|
| 260 |
const explicit=run.manual_validation_status||run.summary?.manual_validation_status||{};
|
| 261 |
-
const
|
| 262 |
-
const
|
| 263 |
-
const
|
| 264 |
-
const
|
| 265 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 266 |
}
|
| 267 |
function buildEffectiveStatus(run={}){
|
| 268 |
run=safeRunObject(run);
|
|
@@ -566,6 +612,7 @@ function renderRunSelectionPreview(runId){
|
|
| 566 |
const detail=optimisticDetailFromSummary(cached);
|
| 567 |
if(isValidationRunDetail(detail)){const parent=linkedValidationParentId(cached)||detail.summary?.parent_build_run_id||detail.state?.parent_build_run_id;if(parent){selectRun(parent);return;}showValidationRunDetail(detail);return}
|
| 568 |
switchCenterTab('active');
|
|
|
|
| 569 |
renderRunDetail(detail);
|
| 570 |
setText('progressTitle',runId);
|
| 571 |
setText('progressStatus',badgeLabel(cached.status||'loading'));
|
|
@@ -651,7 +698,7 @@ async function selectRun(runId){
|
|
| 651 |
showMessage(`Opening parent Build Run for linked validation ${runId}.`,'info');
|
| 652 |
runId=parentId;
|
| 653 |
}else if(isValidationRunDetail(localDetail))showValidationRunDetail(localDetail);
|
| 654 |
-
else{switchCenterTab('active');setBuildModeInspecting(runId);state.runId=runId;renderRunDetail(localDetail);}
|
| 655 |
}else{
|
| 656 |
renderRunSelectionPreview(runId);
|
| 657 |
}
|
|
@@ -667,6 +714,7 @@ async function selectRun(runId){
|
|
| 667 |
switchCenterTab('active');
|
| 668 |
setBuildModeInspecting(parentId);
|
| 669 |
state.runId=parentId;
|
|
|
|
| 670 |
renderRunViewSnapshot(parentSnapshot);
|
| 671 |
}else showValidationRunDetail(snapshot);
|
| 672 |
return;
|
|
@@ -674,6 +722,7 @@ async function selectRun(runId){
|
|
| 674 |
switchCenterTab('active');
|
| 675 |
setBuildModeInspecting(runId);
|
| 676 |
state.runId=runId;
|
|
|
|
| 677 |
renderRunViewSnapshot(snapshot);
|
| 678 |
const status=String(snapshot.view?.header?.status||snapshot.status||snapshot.summary?.status||snapshot.state?.status||'').toLowerCase();
|
| 679 |
if(runCanBeDeleted(status)||TERMINAL_STATUSES.has(status)){
|
|
|
|
| 255 |
return ['complete','recover'].includes(String(policy.mode||'').toLowerCase())&&policy.enabled!==false&&!buildManualValidationStatus(run).passed;
|
| 256 |
}
|
| 257 |
|
| 258 |
+
function linkedValidationRowsFromMetadata(run={}){
|
| 259 |
+
run=safeRunObject(run);
|
| 260 |
+
const candidates=[
|
| 261 |
+
run.linked_validations,
|
| 262 |
+
run.summary?.linked_validations,
|
| 263 |
+
run.manual_validation_status?.linked_validations,
|
| 264 |
+
run.summary?.manual_validation_status?.linked_validations
|
| 265 |
+
].filter(Boolean);
|
| 266 |
+
const rows=[];
|
| 267 |
+
for(const item of candidates){
|
| 268 |
+
if(Array.isArray(item))rows.push(...item);
|
| 269 |
+
else if(Array.isArray(item.validations))rows.push(...item.validations);
|
| 270 |
+
else if(item.latest_validation)rows.push(item.latest_validation);
|
| 271 |
+
else if(item.validation_run_id||item.run_id||item.status)rows.push(item);
|
| 272 |
+
}
|
| 273 |
+
return rows.filter(x=>x&&typeof x==='object');
|
| 274 |
+
}
|
| 275 |
+
function linkedValidationCountFromMetadata(run={},rows=[]){
|
| 276 |
+
const counts=[
|
| 277 |
+
run.linked_validation_count,
|
| 278 |
+
run.summary?.linked_validation_count,
|
| 279 |
+
run.linked_validations_count,
|
| 280 |
+
run.summary?.linked_validations_count,
|
| 281 |
+
run.manual_validation_status?.linked_count,
|
| 282 |
+
run.summary?.manual_validation_status?.linked_count,
|
| 283 |
+
run.linked_validations?.count,
|
| 284 |
+
run.summary?.linked_validations?.count
|
| 285 |
+
].map(Number).filter(n=>Number.isFinite(n)&&n>0);
|
| 286 |
+
return Math.max(rows.length,...counts,0);
|
| 287 |
+
}
|
| 288 |
+
function linkedValidationRowStatus(row={}){
|
| 289 |
+
row=safeRunObject(row);
|
| 290 |
+
return String(row.status||row.validation_status||row.result_status||row.verdict||row.effective_status||row.summary?.status||'').toLowerCase();
|
| 291 |
+
}
|
| 292 |
function buildManualValidationStatus(run={}){
|
| 293 |
run=safeRunObject(run);
|
| 294 |
const explicit=run.manual_validation_status||run.summary?.manual_validation_status||{};
|
| 295 |
+
const metadataRows=linkedValidationRowsFromMetadata(run);
|
| 296 |
+
const cacheRows=linkedValidationsForBuild(run.run_id).filter(v=>!runMatchesStatus(v,'running'));
|
| 297 |
+
const rows=[...metadataRows,...cacheRows];
|
| 298 |
+
const explicitStatus=String(explicit.status||explicit.validation_status||explicit.result_status||explicit.verdict||'').toLowerCase();
|
| 299 |
+
const metadataCount=linkedValidationCountFromMetadata(run,metadataRows);
|
| 300 |
+
const linkedCount=Math.max(metadataCount,cacheRows.length,explicitStatus?1:0);
|
| 301 |
+
const passed=Boolean(
|
| 302 |
+
run.manual_validation_passed||run.summary?.manual_validation_passed||
|
| 303 |
+
explicitStatus==='success'||explicitStatus==='passed'||explicitStatus==='full_inference_success'||
|
| 304 |
+
rows.some(v=>{const st=linkedValidationRowStatus(v);return st==='success'||st==='passed'||st==='full_inference_success'||runMatchesStatus(v,'full_inference_success');})
|
| 305 |
+
);
|
| 306 |
+
const failed=Boolean(
|
| 307 |
+
explicitStatus==='failed'||explicitStatus==='failure'||explicitStatus==='error'||
|
| 308 |
+
rows.some(v=>{const st=linkedValidationRowStatus(v);return st==='failed'||st==='failure'||st==='error'||runMatchesStatus(v,'failed');})
|
| 309 |
+
);
|
| 310 |
+
const latest=rows[0]||{};
|
| 311 |
+
return {passed,failed,linkedCount,latest,explicit,metadataRows,cacheRows};
|
| 312 |
}
|
| 313 |
function buildEffectiveStatus(run={}){
|
| 314 |
run=safeRunObject(run);
|
|
|
|
| 612 |
const detail=optimisticDetailFromSummary(cached);
|
| 613 |
if(isValidationRunDetail(detail)){const parent=linkedValidationParentId(cached)||detail.summary?.parent_build_run_id||detail.state?.parent_build_run_id;if(parent){selectRun(parent);return;}showValidationRunDetail(detail);return}
|
| 614 |
switchCenterTab('active');
|
| 615 |
+
if(typeof requestSpaceTestContextResetForBuild==='function')requestSpaceTestContextResetForBuild(runId);
|
| 616 |
renderRunDetail(detail);
|
| 617 |
setText('progressTitle',runId);
|
| 618 |
setText('progressStatus',badgeLabel(cached.status||'loading'));
|
|
|
|
| 698 |
showMessage(`Opening parent Build Run for linked validation ${runId}.`,'info');
|
| 699 |
runId=parentId;
|
| 700 |
}else if(isValidationRunDetail(localDetail))showValidationRunDetail(localDetail);
|
| 701 |
+
else{switchCenterTab('active');setBuildModeInspecting(runId);state.runId=runId;if(typeof requestSpaceTestContextResetForBuild==='function')requestSpaceTestContextResetForBuild(runId);renderRunDetail(localDetail);}
|
| 702 |
}else{
|
| 703 |
renderRunSelectionPreview(runId);
|
| 704 |
}
|
|
|
|
| 714 |
switchCenterTab('active');
|
| 715 |
setBuildModeInspecting(parentId);
|
| 716 |
state.runId=parentId;
|
| 717 |
+
if(typeof requestSpaceTestContextResetForBuild==='function')requestSpaceTestContextResetForBuild(parentId);
|
| 718 |
renderRunViewSnapshot(parentSnapshot);
|
| 719 |
}else showValidationRunDetail(snapshot);
|
| 720 |
return;
|
|
|
|
| 722 |
switchCenterTab('active');
|
| 723 |
setBuildModeInspecting(runId);
|
| 724 |
state.runId=runId;
|
| 725 |
+
if(typeof requestSpaceTestContextResetForBuild==='function')requestSpaceTestContextResetForBuild(runId);
|
| 726 |
renderRunViewSnapshot(snapshot);
|
| 727 |
const status=String(snapshot.view?.header?.status||snapshot.status||snapshot.summary?.status||snapshot.state?.status||'').toLowerCase();
|
| 728 |
if(runCanBeDeleted(status)||TERMINAL_STATUSES.has(status)){
|