fffiloni commited on
Commit
79010d8
·
verified ·
1 Parent(s): cd7d610

Upload 8 files

Browse files
web/static/app.css CHANGED
@@ -2314,7 +2314,7 @@ conic-gradient(from -90deg
2314
  .expert-acceptance-card textarea{margin-top:5px;min-height:64px;resize:vertical}
2315
  .expert-acceptance-card .expert-note{margin:0;color:#7a5d12;background:transparent;border:0;padding:0}
2316
 
2317
- /* v198.26.123 — Target Space override edit stability and spacing. */
2318
  .target-override-card{
2319
  margin:18px 0 20px!important;
2320
  padding:12px 14px 14px!important;
@@ -2334,3 +2334,32 @@ conic-gradient(from -90deg
2334
  .target-override-card .button-row{margin-top:10px!important;margin-bottom:6px!important}
2335
  .target-override-card+#spaceTestAdvanced,
2336
  .target-override-card+details.space-test-advanced{margin-top:16px!important}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2314
  .expert-acceptance-card textarea{margin-top:5px;min-height:64px;resize:vertical}
2315
  .expert-acceptance-card .expert-note{margin:0;color:#7a5d12;background:transparent;border:0;padding:0}
2316
 
2317
+ /* v198.26.124 — Target Space override edit stability and spacing. */
2318
  .target-override-card{
2319
  margin:18px 0 20px!important;
2320
  padding:12px 14px 14px!important;
 
2334
  .target-override-card .button-row{margin-top:10px!important;margin-bottom:6px!important}
2335
  .target-override-card+#spaceTestAdvanced,
2336
  .target-override-card+details.space-test-advanced{margin-top:16px!important}
2337
+
2338
+ /* v198.26.124 — Expert validation UI polish. */
2339
+ .run-row.run-list-item .run-status-pill{
2340
+ max-width:78px!important;
2341
+ }
2342
+ .linked-validation-run-row.expert-validation{
2343
+ border-color:rgba(34,197,94,.26);
2344
+ background:linear-gradient(180deg,#ffffff 0%,#f7fefb 100%);
2345
+ }
2346
+ .linked-validation-run-row.just-loaded{
2347
+ animation:linked-validation-loaded-pulse .9s ease-out;
2348
+ }
2349
+ .linked-validation-run-row .expert-validation-chip{
2350
+ margin-left:6px;
2351
+ padding:4px 8px;
2352
+ font-size:11px;
2353
+ border-radius:999px;
2354
+ background:#eef2ff;
2355
+ color:#344054;
2356
+ border:1px solid #dbe4ff;
2357
+ }
2358
+ @keyframes linked-validation-loaded-pulse{
2359
+ 0%{box-shadow:0 0 0 0 rgba(37,99,235,.22);background:#eff6ff;transform:translateY(-1px)}
2360
+ 55%{box-shadow:0 0 0 5px rgba(37,99,235,.10);background:#f0fdf4}
2361
+ 100%{box-shadow:0 0 0 0 rgba(37,99,235,0);background:inherit;transform:none}
2362
+ }
2363
+ @media (prefers-reduced-motion:reduce){
2364
+ .linked-validation-run-row.just-loaded{animation:none!important}
2365
+ }
web/static/app.js CHANGED
@@ -1,4 +1,4 @@
1
- const state={runId:null,targetSpaceOverrideSaving:false,targetSpaceOverrideDraftDirty:false,targetSpaceOverrideInputRunId:'',validationRunId:null,validationPoll:null,validationPollToken:null,validationRequestSeq:0,validationMode:'idle',validationArgsDirty:false,validationFieldState:null,validationEndpointOverride:false,validationEndpointOverrideSourceRunId:'',validationPollErrors:0,validationLastJobLogPoll:0,validationDetail:null,validationPrefillDraft:null,linkedValidationParent:null,validationTerminalByRun:{},validationProgressByRun:{},centerTab:'active',spaceLinksUnlockedFor:null,bucketName:'space-factory-runs',bucketSource:null,bucketReady:false,poll:null,activeLinks:{},activeRunProgress:null,selectedRunDetail:null,runStatusFilter:'all',runSearch:'',runPage:0,runsPerPage:5,runsCache:[],runsLastLoaded:0,lastRunsRefreshFromPoll:0,lastJobLogPoll:0,lastReportRefreshRunId:null,terminalRunsRefreshTimer:null,terminalRunsRefreshRunId:null,runReportRefreshInFlight:{},runReportRefreshQueued:{},pollErrors:0,busy:false,user:null,currentView:'onepage',modelScan:null,runDetailCache:{},runDetailCacheTtlMs:300000,runSelectionLoadingId:null,runSelectionSeq:0,deleteModalPromise:null,deleteModalRunId:null,deletingRuns:{},deletedRuns:{}};
2
  const TERMINAL_STATUSES=new Set(['done','success','failed','full_inference_success','full_inference_candidate_health_passed','manual_hardware_required','generated_needs_manual_hardware','technical_blocker','health_only','partial','partial_validation','completed_with_warnings','demo_usable_full_promise_not_verified','interactive_app_available_smoke_failed','manual_test_required_smoke_failed','placeholder_scaffold_deployed','validated','validated_after_space_test','validated_after_manual_space_test','manual_validation_passed','manual_validated','recovered_by_space_test','recovered_by_manual_validation','success_with_expert_intervention','expert_intervention_validation_passed','repair_success','repair_failed','succeeded','waiting_manual_action','blocked','stale','cancelled','canceled','stopped','auth_refresh_required']);
3
  const DEFAULT_TIMELINE=[{label:'Bootstrap',status:'pending'},{label:'Dependencies',status:'pending'},{label:'Auth',status:'pending'},{label:'Model analysis',status:'pending'},{label:'Workspace',status:'pending'},{label:'Node/npm',status:'pending'},{label:'Pi install',status:'pending'},{label:'Pi config',status:'pending'},{label:'Pi run',status:'pending'},{label:'Pi verification',status:'pending'},{label:'Metadata sanitize',status:'pending'},{label:'Requirements sanitize',status:'pending'},{label:'Hardware strategy',status:'pending'},{label:'Create with hardware',status:'pending'},{label:'Create Space',status:'pending'},{label:'Repair pass',status:'pending'},{label:'Upload files',status:'pending'},{label:'Space runtime',status:'pending'},{label:'Space logs',status:'pending'},{label:'API validation',status:'pending'},{label:'Live wait',status:'pending'},{label:'Generation smoke',status:'pending'},{label:'Inference gate',status:'pending'},{label:'Report',status:'pending'},{label:'Done',status:'pending'},{label:'Failure',status:'pending'}];
4
 
@@ -1796,6 +1796,38 @@ function renderSpaceTestReadiness(){
1796
  note.textContent=resolved.error||'Space Test is not ready to launch.';
1797
  }
1798
  }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1799
  function renderValidationStatus(data={}){
1800
  const candidateRunId=validationDetailRunId(data)||state.validationRunId;
1801
  data=mergeValidationWithTerminalLock(data||state.validationDetail||{},candidateRunId);
@@ -1811,7 +1843,8 @@ function renderValidationStatus(data={}){
1811
  if(runIdForState)rememberTerminalValidation(data);
1812
  applyEffectiveValidationArgs(data);
1813
  const badge=$('spaceTestStatus');
1814
- if(badge){badge.textContent=badgeLabel(displayStatus);badge.className='badge '+klass}
 
1815
  const tabDot=$('spaceTestTabDot');
1816
  if(tabDot)tabDot.className='tab-status-dot '+(isRunning?'running':klass);
1817
  const card=$('spaceTestPreview');
@@ -1825,7 +1858,8 @@ function renderValidationStatus(data={}){
1825
  setText('spaceTestLatency',isIdle?'—':(latency?formatLatencySeconds(latency):(canonical==='running'?'—':'Not recorded')));
1826
  const diagnosis=data.validation_failure_diagnosis||data.summary?.validation_failure_diagnosis||data.state?.validation_failure_diagnosis||smoke.validation_failure_diagnosis||{};
1827
  const diagnosisMsg=diagnosis.message||diagnosis.error||diagnosis.failure_reason||diagnosis.failure_type||smoke.error||summary.error||data.error||'';
1828
- 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));
 
1829
  setText('spaceTestVerdict',verdictText);
1830
  const launchBtn=$('launchValidate');
1831
  if(launchBtn&&!(launchBtn.classList?.contains&&launchBtn.classList.contains('is-busy'))){
@@ -2105,9 +2139,13 @@ function renderSpaceTestLinkedValidationRuns(){
2105
  const jobUrl=validationJobUrlFromDetail(row);
2106
  const latency=firstPositiveNumber(row.latency_seconds,row.observed_latency_seconds,row.summary?.latency_seconds,row.summary?.observed_latency_seconds);
2107
  const when=formatTime(row.updated_at||row.validated_at||row.created_at);
2108
- return `<div class="linked-validation-run-row ${state.validationRunId===runId?'selected':''}" data-linked-validation-run="${escapeHtml(runId)}">
 
 
 
 
2109
  <div class="linked-validation-run-main">
2110
- <span class="badge ${klass}">${escapeHtml(badgeLabel(status))}</span>
2111
  <strong><code>${escapeHtml(runId)}</code></strong>
2112
  <em>${escapeHtml([endpoint,latency?formatLatencySeconds(latency):'',when].filter(Boolean).join(' · ')||'No runtime details recorded')}</em>
2113
  </div>
@@ -2144,6 +2182,8 @@ function renderSpaceTestLinkedValidationRuns(){
2144
  row.classList.add('loading');
2145
  try{
2146
  const detail=await fetchRunViewSnapshotOnce(runId,{includeJobLogs:false});
 
 
2147
  showValidationRunDetail(detailWithLinkedValidationParent(detail||{run_id:runId,kind:'linked_space_validation'},parentId));
2148
  }catch(err){
2149
  showMessage(`Could not load validation run ${runId}: ${err.message}`,'error');
 
1
+ const state={runId:null,targetSpaceOverrideSaving:false,targetSpaceOverrideDraftDirty:false,targetSpaceOverrideInputRunId:'',lastLoadedLinkedValidationRunId:'',lastLoadedLinkedValidationAt:0,validationRunId:null,validationPoll:null,validationPollToken:null,validationRequestSeq:0,validationMode:'idle',validationArgsDirty:false,validationFieldState:null,validationEndpointOverride:false,validationEndpointOverrideSourceRunId:'',validationPollErrors:0,validationLastJobLogPoll:0,validationDetail:null,validationPrefillDraft:null,linkedValidationParent:null,validationTerminalByRun:{},validationProgressByRun:{},centerTab:'active',spaceLinksUnlockedFor:null,bucketName:'space-factory-runs',bucketSource:null,bucketReady:false,poll:null,activeLinks:{},activeRunProgress:null,selectedRunDetail:null,runStatusFilter:'all',runSearch:'',runPage:0,runsPerPage:5,runsCache:[],runsLastLoaded:0,lastRunsRefreshFromPoll:0,lastJobLogPoll:0,lastReportRefreshRunId:null,terminalRunsRefreshTimer:null,terminalRunsRefreshRunId:null,runReportRefreshInFlight:{},runReportRefreshQueued:{},pollErrors:0,busy:false,user:null,currentView:'onepage',modelScan:null,runDetailCache:{},runDetailCacheTtlMs:300000,runSelectionLoadingId:null,runSelectionSeq:0,deleteModalPromise:null,deleteModalRunId:null,deletingRuns:{},deletedRuns:{}};
2
  const TERMINAL_STATUSES=new Set(['done','success','failed','full_inference_success','full_inference_candidate_health_passed','manual_hardware_required','generated_needs_manual_hardware','technical_blocker','health_only','partial','partial_validation','completed_with_warnings','demo_usable_full_promise_not_verified','interactive_app_available_smoke_failed','manual_test_required_smoke_failed','placeholder_scaffold_deployed','validated','validated_after_space_test','validated_after_manual_space_test','manual_validation_passed','manual_validated','recovered_by_space_test','recovered_by_manual_validation','success_with_expert_intervention','expert_intervention_validation_passed','repair_success','repair_failed','succeeded','waiting_manual_action','blocked','stale','cancelled','canceled','stopped','auth_refresh_required']);
3
  const DEFAULT_TIMELINE=[{label:'Bootstrap',status:'pending'},{label:'Dependencies',status:'pending'},{label:'Auth',status:'pending'},{label:'Model analysis',status:'pending'},{label:'Workspace',status:'pending'},{label:'Node/npm',status:'pending'},{label:'Pi install',status:'pending'},{label:'Pi config',status:'pending'},{label:'Pi run',status:'pending'},{label:'Pi verification',status:'pending'},{label:'Metadata sanitize',status:'pending'},{label:'Requirements sanitize',status:'pending'},{label:'Hardware strategy',status:'pending'},{label:'Create with hardware',status:'pending'},{label:'Create Space',status:'pending'},{label:'Repair pass',status:'pending'},{label:'Upload files',status:'pending'},{label:'Space runtime',status:'pending'},{label:'Space logs',status:'pending'},{label:'API validation',status:'pending'},{label:'Live wait',status:'pending'},{label:'Generation smoke',status:'pending'},{label:'Inference gate',status:'pending'},{label:'Report',status:'pending'},{label:'Done',status:'pending'},{label:'Failure',status:'pending'}];
4
 
 
1796
  note.textContent=resolved.error||'Space Test is not ready to launch.';
1797
  }
1798
  }
1799
+
1800
+ function validationHasExpertAcceptance(detail={}){
1801
+ const candidates=[
1802
+ detail,
1803
+ detail.summary,
1804
+ detail.state,
1805
+ detail.launch,
1806
+ detail.post_build_validation,
1807
+ detail.summary?.post_build_validation,
1808
+ detail.manual_validation_status,
1809
+ detail.summary?.manual_validation_status,
1810
+ detail.effective_run_status,
1811
+ detail.summary?.effective_run_status,
1812
+ detail.validation_result,
1813
+ detail.summary?.validation_result,
1814
+ ].filter(Boolean);
1815
+ return candidates.some(item=>{
1816
+ const mode=String(item.validation_mode||item.mode||item.launch_mode||'').toLowerCase();
1817
+ const expert=String(item.expert_intervention_required||item.expert_required||'').toLowerCase();
1818
+ const outcome=String(item.accepted_outcome||item.effective_status||item.display_status||item.status||item.verdict||'').toLowerCase();
1819
+ return mode==='expert_acceptance'||expert==='true'||expert==='1'||['success_with_expert_intervention','expert_intervention_validation_passed'].includes(outcome);
1820
+ });
1821
+ }
1822
+ function validationExpertAcceptanceLabel(detail={},canonical=''){
1823
+ if(!validationHasExpertAcceptance(detail))return '';
1824
+ const s=String(canonical||validationCanonicalStatus(detail)||'').toLowerCase();
1825
+ if(['full_inference_success','success','passed','validated','done','completed'].includes(s))return 'Passed · Expert acceptance';
1826
+ if(s==='failed')return 'Failed · Expert acceptance';
1827
+ if(s==='running')return 'Running · Expert acceptance';
1828
+ return 'Expert acceptance';
1829
+ }
1830
+
1831
  function renderValidationStatus(data={}){
1832
  const candidateRunId=validationDetailRunId(data)||state.validationRunId;
1833
  data=mergeValidationWithTerminalLock(data||state.validationDetail||{},candidateRunId);
 
1843
  if(runIdForState)rememberTerminalValidation(data);
1844
  applyEffectiveValidationArgs(data);
1845
  const badge=$('spaceTestStatus');
1846
+ const expertAcceptanceLabel=validationExpertAcceptanceLabel(data,canonical);
1847
+ if(badge){badge.textContent=expertAcceptanceLabel||badgeLabel(displayStatus);badge.className='badge '+klass}
1848
  const tabDot=$('spaceTestTabDot');
1849
  if(tabDot)tabDot.className='tab-status-dot '+(isRunning?'running':klass);
1850
  const card=$('spaceTestPreview');
 
1858
  setText('spaceTestLatency',isIdle?'—':(latency?formatLatencySeconds(latency):(canonical==='running'?'—':'Not recorded')));
1859
  const diagnosis=data.validation_failure_diagnosis||data.summary?.validation_failure_diagnosis||data.state?.validation_failure_diagnosis||smoke.validation_failure_diagnosis||{};
1860
  const diagnosisMsg=diagnosis.message||diagnosis.error||diagnosis.failure_reason||diagnosis.failure_type||smoke.error||summary.error||data.error||'';
1861
+ const baseVerdict=expertAcceptanceLabel||badgeLabel(displayStatus);
1862
+ const verdictText=isIdle?(data.message||'No validation run selected.'):data._refreshing?`${baseVerdict} · Refreshing…`:(canonical==='failed'&&diagnosisMsg?`${baseVerdict} · ${String(diagnosisMsg).slice(0,220)}`:baseVerdict);
1863
  setText('spaceTestVerdict',verdictText);
1864
  const launchBtn=$('launchValidate');
1865
  if(launchBtn&&!(launchBtn.classList?.contains&&launchBtn.classList.contains('is-busy'))){
 
2139
  const jobUrl=validationJobUrlFromDetail(row);
2140
  const latency=firstPositiveNumber(row.latency_seconds,row.observed_latency_seconds,row.summary?.latency_seconds,row.summary?.observed_latency_seconds);
2141
  const when=formatTime(row.updated_at||row.validated_at||row.created_at);
2142
+ const expert=validationHasExpertAcceptance(row);
2143
+ const justLoaded=state.lastLoadedLinkedValidationRunId===runId&&Date.now()-(state.lastLoadedLinkedValidationAt||0)<1400;
2144
+ const rowClasses=['linked-validation-run-row',state.validationRunId===runId?'selected':'',expert?'expert-validation':'',justLoaded?'just-loaded':''].filter(Boolean).join(' ');
2145
+ const rowStatusLabel=expert&&linkedValidationPassedForAccounting(row)?'Passed · Expert':badgeLabel(status);
2146
+ return `<div class="${rowClasses}" data-linked-validation-run="${escapeHtml(runId)}">
2147
  <div class="linked-validation-run-main">
2148
+ <span class="badge ${klass}">${escapeHtml(rowStatusLabel)}</span>${expert?'<span class="badge neutral expert-validation-chip">Expert</span>':''}
2149
  <strong><code>${escapeHtml(runId)}</code></strong>
2150
  <em>${escapeHtml([endpoint,latency?formatLatencySeconds(latency):'',when].filter(Boolean).join(' · ')||'No runtime details recorded')}</em>
2151
  </div>
 
2182
  row.classList.add('loading');
2183
  try{
2184
  const detail=await fetchRunViewSnapshotOnce(runId,{includeJobLogs:false});
2185
+ state.lastLoadedLinkedValidationRunId=runId;
2186
+ state.lastLoadedLinkedValidationAt=Date.now();
2187
  showValidationRunDetail(detailWithLinkedValidationParent(detail||{run_id:runId,kind:'linked_space_validation'},parentId));
2188
  }catch(err){
2189
  showMessage(`Could not load validation run ${runId}: ${err.message}`,'error');
web/static/progress.js CHANGED
@@ -463,7 +463,7 @@ function canonicalRunUiState(payload={}){
463
  (lower.includes('success')||lower==='succeeded'||lower==='done'?'success':lower)));
464
  if(PROGRESS_SUCCESS_TERMINAL_STATUSES.has(lower)||PROGRESS_SUCCESS_TERMINAL_STATUSES.has(effectiveStatusLower))visual='success';
465
  let label=effectiveRunStatus.display_label||modelProgress.label||header.display_label||header.status_label||badgeLabel(status);
466
- if(['success_with_expert_intervention','expert_intervention_validation_passed'].includes(String(status||'').toLowerCase()))label='Recovered · Expert';
467
  if(terminal&&String(label||'').toLowerCase()==='running')label=badgeLabel(status);
468
  return {status, statusLower:lower, label, visual_status:visual, isTerminal:terminal||PROGRESS_TERMINAL_STATUSES.has(lower)};
469
  }
 
463
  (lower.includes('success')||lower==='succeeded'||lower==='done'?'success':lower)));
464
  if(PROGRESS_SUCCESS_TERMINAL_STATUSES.has(lower)||PROGRESS_SUCCESS_TERMINAL_STATUSES.has(effectiveStatusLower))visual='success';
465
  let label=effectiveRunStatus.display_label||modelProgress.label||header.display_label||header.status_label||badgeLabel(status);
466
+ if(['success_with_expert_intervention','expert_intervention_validation_passed'].includes(String(status||'').toLowerCase()))label='Recovered after expert intervention';
467
  if(terminal&&String(label||'').toLowerCase()==='running')label=badgeLabel(status);
468
  return {status, statusLower:lower, label, visual_status:visual, isTerminal:terminal||PROGRESS_TERMINAL_STATUSES.has(lower)};
469
  }
web/static/runs.js CHANGED
@@ -400,7 +400,7 @@ function runCardKind(run={}){return isValidationRunSummary(run)?'Linked test':'B
400
  function runCompactStatusLabel(status){
401
  // v193 compact labels still include legacy branch semantics: return 'Success' and return 'Failed'.
402
  const s=normalizeExplorerStatusValue(status||'unknown');
403
- if(['success_with_expert_intervention','expert_intervention_validation_passed'].includes(s))return 'Recovered · Expert';
404
  if(['recovered_by_space_test','recovered_by_manual_validation'].includes(s))return 'Recovered';
405
  if(['validated_after_space_test','validated_after_manual_space_test','manual_validation_passed','manual_validated','validated'].includes(s))return 'Validated';
406
  return explorerDisplayLabel(s);
 
400
  function runCompactStatusLabel(status){
401
  // v193 compact labels still include legacy branch semantics: return 'Success' and return 'Failed'.
402
  const s=normalizeExplorerStatusValue(status||'unknown');
403
+ if(['success_with_expert_intervention','expert_intervention_validation_passed'].includes(s))return 'Expert';
404
  if(['recovered_by_space_test','recovered_by_manual_validation'].includes(s))return 'Recovered';
405
  if(['validated_after_space_test','validated_after_manual_space_test','manual_validation_passed','manual_validated','validated'].includes(s))return 'Validated';
406
  return explorerDisplayLabel(s);