617 lines
20 KiB
HTML
617 lines
20 KiB
HTML
<!doctype html>
|
|
<html lang="zh-CN">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Local G2 最小曲率越界可行性验证|结果可视化</title>
|
|
<style>
|
|
:root {
|
|
color-scheme: light;
|
|
--ink: #172a36;
|
|
--muted: #62727b;
|
|
--paper: #f4f7f6;
|
|
--panel: #ffffff;
|
|
--line: #c8d4d5;
|
|
--teal: #126d70;
|
|
--teal-pale: #e0f1ef;
|
|
--green: #257a4d;
|
|
--green-pale: #e7f4eb;
|
|
--amber: #9b5f13;
|
|
--amber-pale: #fff1dc;
|
|
--red: #b1373e;
|
|
--red-pale: #fbe9ea;
|
|
--slate: #596b75;
|
|
}
|
|
|
|
* { box-sizing: border-box; }
|
|
|
|
body {
|
|
margin: 0;
|
|
background: var(--paper);
|
|
color: var(--ink);
|
|
font: 16px/1.6 system-ui, -apple-system, "Segoe UI", sans-serif;
|
|
}
|
|
|
|
main {
|
|
width: min(1120px, 100%);
|
|
margin: 0 auto;
|
|
padding: 32px 24px 48px;
|
|
}
|
|
|
|
header {
|
|
border-bottom: 2px solid var(--ink);
|
|
padding-bottom: 22px;
|
|
}
|
|
|
|
.eyebrow {
|
|
margin: 0 0 6px;
|
|
color: var(--teal);
|
|
font-weight: 800;
|
|
}
|
|
|
|
h1, h2, h3, p { margin-top: 0; }
|
|
|
|
h1 {
|
|
margin-bottom: 10px;
|
|
font-size: 2.25rem;
|
|
line-height: 1.18;
|
|
}
|
|
|
|
h2 {
|
|
margin-bottom: 12px;
|
|
font-size: 1.45rem;
|
|
line-height: 1.3;
|
|
}
|
|
|
|
h3 {
|
|
margin-bottom: 6px;
|
|
font-size: 1.05rem;
|
|
line-height: 1.35;
|
|
}
|
|
|
|
.subtitle {
|
|
max-width: 780px;
|
|
margin-bottom: 16px;
|
|
color: var(--muted);
|
|
font-size: 1.03rem;
|
|
}
|
|
|
|
.badges {
|
|
display: flex;
|
|
flex-wrap: wrap;
|
|
gap: 8px;
|
|
}
|
|
|
|
.badge {
|
|
border: 1px solid currentColor;
|
|
border-radius: 6px;
|
|
padding: 4px 9px;
|
|
font-size: 0.9rem;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.badge.red { color: var(--red); background: var(--red-pale); }
|
|
.badge.green { color: var(--green); background: var(--green-pale); }
|
|
.badge.teal { color: var(--teal); background: var(--teal-pale); }
|
|
|
|
.report-nav {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 8px;
|
|
margin: 24px 0 0;
|
|
}
|
|
|
|
button {
|
|
min-height: 44px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 6px;
|
|
padding: 9px 12px;
|
|
color: var(--ink);
|
|
background: var(--panel);
|
|
font: inherit;
|
|
font-weight: 700;
|
|
cursor: pointer;
|
|
}
|
|
|
|
button:hover { border-color: var(--teal); }
|
|
button:focus-visible { outline: 3px solid #f0b535; outline-offset: 2px; }
|
|
button[aria-pressed="true"] { border-color: var(--teal); color: #ffffff; background: var(--teal); }
|
|
|
|
.visual-band {
|
|
margin-top: 16px;
|
|
border-top: 1px solid var(--line);
|
|
border-bottom: 1px solid var(--line);
|
|
background: var(--panel);
|
|
}
|
|
|
|
.view-copy {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) auto;
|
|
gap: 20px;
|
|
align-items: end;
|
|
padding: 22px 22px 12px;
|
|
}
|
|
|
|
.view-copy p {
|
|
margin-bottom: 0;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.view-state {
|
|
margin: 0;
|
|
color: var(--teal);
|
|
font-weight: 800;
|
|
text-align: right;
|
|
}
|
|
|
|
.visual-stage { padding: 0 22px 24px; }
|
|
|
|
.visual-view { display: none; }
|
|
[data-view="funnel"] .visual-view[data-view="funnel"],
|
|
[data-view="gates"] .visual-view[data-view="gates"],
|
|
[data-view="performance"] .visual-view[data-view="performance"] { display: block; }
|
|
|
|
.funnel {
|
|
display: grid;
|
|
grid-template-columns: repeat(5, minmax(0, 1fr));
|
|
align-items: stretch;
|
|
gap: 10px;
|
|
padding: 0;
|
|
margin: 0;
|
|
list-style: none;
|
|
}
|
|
|
|
.funnel li {
|
|
position: relative;
|
|
min-height: 142px;
|
|
border: 1px solid var(--line);
|
|
border-top: 5px solid var(--slate);
|
|
border-radius: 6px;
|
|
padding: 16px 12px;
|
|
background: #fbfcfc;
|
|
}
|
|
|
|
.funnel li:not(:last-child)::after {
|
|
position: absolute;
|
|
top: 58px;
|
|
right: -9px;
|
|
z-index: 1;
|
|
width: 17px;
|
|
color: var(--muted);
|
|
background: var(--panel);
|
|
content: "→";
|
|
font-size: 1.25rem;
|
|
text-align: center;
|
|
}
|
|
|
|
.funnel li.physical { border-top-color: var(--green); }
|
|
.funnel li.blocked { border-top-color: var(--red); }
|
|
.funnel li.final { border-top-color: var(--slate); }
|
|
|
|
.metric {
|
|
display: block;
|
|
margin-bottom: 4px;
|
|
color: var(--ink);
|
|
font-size: 2.25rem;
|
|
font-weight: 800;
|
|
line-height: 1;
|
|
}
|
|
|
|
.funnel strong, .funnel small { display: block; }
|
|
.funnel small { margin-top: 4px; color: var(--muted); }
|
|
|
|
.gate-grid {
|
|
display: grid;
|
|
grid-template-columns: repeat(4, minmax(0, 1fr));
|
|
gap: 10px;
|
|
}
|
|
|
|
.gate {
|
|
min-height: 154px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 6px;
|
|
padding: 16px;
|
|
background: #fbfcfc;
|
|
}
|
|
|
|
.gate .step {
|
|
display: block;
|
|
margin-bottom: 8px;
|
|
color: var(--muted);
|
|
font-weight: 800;
|
|
}
|
|
|
|
.gate p { margin-bottom: 0; color: var(--muted); }
|
|
.gate.accepted { border-top: 5px solid var(--green); }
|
|
.gate.blocked { border-top: 5px solid var(--red); }
|
|
.gate.measurement { border-top: 5px solid var(--amber); }
|
|
.gate.output { border-top: 5px solid var(--slate); }
|
|
|
|
.gate-result {
|
|
display: inline-block;
|
|
margin-top: 12px;
|
|
border-radius: 5px;
|
|
padding: 3px 7px;
|
|
font-size: 0.9rem;
|
|
font-weight: 800;
|
|
}
|
|
|
|
.gate-result.green { color: var(--green); background: var(--green-pale); }
|
|
.gate-result.red { color: var(--red); background: var(--red-pale); }
|
|
.gate-result.amber { color: var(--amber); background: var(--amber-pale); }
|
|
.gate-result.slate { color: var(--slate); background: #e9eef0; }
|
|
|
|
.measurement-note {
|
|
margin: 14px 0 0;
|
|
border-left: 4px solid var(--amber);
|
|
padding: 10px 12px;
|
|
color: #6e4915;
|
|
background: var(--amber-pale);
|
|
}
|
|
|
|
.performance-layout {
|
|
display: grid;
|
|
grid-template-columns: minmax(0, 1fr) 250px;
|
|
gap: 28px;
|
|
align-items: stretch;
|
|
}
|
|
|
|
.timing-list {
|
|
display: grid;
|
|
gap: 14px;
|
|
}
|
|
|
|
.timing-row {
|
|
display: grid;
|
|
grid-template-columns: 132px minmax(0, 1fr);
|
|
gap: 12px;
|
|
align-items: center;
|
|
}
|
|
|
|
.timing-label { font-weight: 800; }
|
|
|
|
.timing-bar {
|
|
display: grid;
|
|
grid-template-columns: var(--median) var(--worst) 1fr;
|
|
min-height: 40px;
|
|
overflow: hidden;
|
|
border: 1px solid var(--line);
|
|
border-radius: 5px;
|
|
background: #f6f8f8;
|
|
}
|
|
|
|
.timing-bar span {
|
|
display: grid;
|
|
place-items: center;
|
|
min-width: 0;
|
|
padding: 3px;
|
|
color: #ffffff;
|
|
font-size: 0.78rem;
|
|
font-weight: 800;
|
|
white-space: nowrap;
|
|
}
|
|
|
|
.timing-bar .median { background: var(--teal); }
|
|
.timing-bar .worst { background: var(--green); }
|
|
.timing-bar .remaining { color: var(--muted); background: #edf2f1; }
|
|
|
|
.determinism {
|
|
display: grid;
|
|
align-content: center;
|
|
border-left: 1px solid var(--line);
|
|
padding-left: 24px;
|
|
}
|
|
|
|
.determinism strong {
|
|
display: block;
|
|
color: var(--teal);
|
|
font-size: 2.85rem;
|
|
line-height: 1;
|
|
}
|
|
|
|
.determinism p { margin: 8px 0 0; color: var(--muted); }
|
|
|
|
.section {
|
|
padding: 30px 0;
|
|
border-bottom: 1px solid var(--line);
|
|
}
|
|
|
|
.section-intro {
|
|
max-width: 780px;
|
|
color: var(--muted);
|
|
}
|
|
|
|
.facts {
|
|
display: grid;
|
|
grid-template-columns: repeat(3, minmax(0, 1fr));
|
|
gap: 16px;
|
|
}
|
|
|
|
.fact {
|
|
border-left: 4px solid var(--teal);
|
|
padding: 4px 0 4px 14px;
|
|
}
|
|
|
|
.fact:nth-child(2) { border-left-color: var(--red); }
|
|
.fact:nth-child(3) { border-left-color: var(--amber); }
|
|
.fact p { margin-bottom: 0; color: var(--muted); }
|
|
|
|
table {
|
|
width: 100%;
|
|
border-collapse: collapse;
|
|
background: var(--panel);
|
|
}
|
|
|
|
th, td {
|
|
border-bottom: 1px solid var(--line);
|
|
padding: 11px 12px;
|
|
vertical-align: top;
|
|
text-align: left;
|
|
}
|
|
|
|
th { color: var(--muted); font-size: 0.9rem; }
|
|
tr:last-child td { border-bottom: 0; }
|
|
|
|
.actions {
|
|
display: grid;
|
|
gap: 10px;
|
|
padding: 0;
|
|
margin: 0;
|
|
list-style: none;
|
|
counter-reset: action;
|
|
}
|
|
|
|
.actions li {
|
|
counter-increment: action;
|
|
position: relative;
|
|
padding-left: 42px;
|
|
}
|
|
|
|
.actions li::before {
|
|
position: absolute;
|
|
left: 0;
|
|
width: 28px;
|
|
height: 28px;
|
|
border: 1px solid var(--line);
|
|
border-radius: 50%;
|
|
color: var(--teal);
|
|
background: var(--panel);
|
|
content: counter(action);
|
|
font-weight: 800;
|
|
line-height: 26px;
|
|
text-align: center;
|
|
}
|
|
|
|
footer {
|
|
padding-top: 24px;
|
|
color: var(--muted);
|
|
font-size: 0.9rem;
|
|
}
|
|
|
|
@media (max-width: 760px) {
|
|
main { padding: 24px 14px 38px; }
|
|
h1 { font-size: 1.85rem; }
|
|
.report-nav, .facts { grid-template-columns: 1fr; }
|
|
.view-copy, .performance-layout { grid-template-columns: 1fr; }
|
|
.view-state { text-align: left; }
|
|
.funnel, .gate-grid { grid-template-columns: 1fr; }
|
|
.funnel li:not(:last-child)::after {
|
|
top: auto;
|
|
right: auto;
|
|
bottom: -16px;
|
|
left: calc(50% - 9px);
|
|
content: "↓";
|
|
}
|
|
.determinism {
|
|
border-top: 1px solid var(--line);
|
|
border-left: 0;
|
|
padding-top: 20px;
|
|
padding-left: 0;
|
|
}
|
|
.timing-row { grid-template-columns: 1fr; gap: 5px; }
|
|
}
|
|
</style>
|
|
</head>
|
|
<body>
|
|
<main id="excursion-report" data-view="funnel">
|
|
<header>
|
|
<p class="eyebrow">离线结果可视化 · Local G2</p>
|
|
<h1>最小曲率越界探测:没有新的可采纳路径</h1>
|
|
<p class="subtitle">固定 SingleTurn 场景中,候选搜索、性能和确定性验证均已完成;但严格接纳条件下没有候选通过,预平滑管线保持原样。</p>
|
|
<div class="badges" aria-label="结论状态">
|
|
<span class="badge red">QUALITY_RED</span>
|
|
<span class="badge green">性能通过</span>
|
|
<span class="badge teal">生产 evaluator 不变</span>
|
|
</div>
|
|
</header>
|
|
|
|
<nav class="report-nav" aria-label="选择结果视图">
|
|
<button type="button" class="view-button" data-view="funnel" aria-pressed="true">候选结果漏斗</button>
|
|
<button type="button" class="view-button" data-view="gates" aria-pressed="false">质量门阻断链路</button>
|
|
<button type="button" class="view-button" data-view="performance" aria-pressed="false">性能与确定性</button>
|
|
</nav>
|
|
|
|
<section class="visual-band" aria-live="polite">
|
|
<div class="view-copy">
|
|
<div>
|
|
<h2 id="view-title">候选已经生成,但没有进入最终输出</h2>
|
|
<p id="view-description">6 个候选中有 3 个达到车辆物理约束层;严格 raw 曲率范围合格数仍为 0,因此不能把任何候选当作可发布的平滑路径。</p>
|
|
</div>
|
|
<p id="view-state" class="view-state">结果:Unchanged</p>
|
|
</div>
|
|
|
|
<div class="visual-stage">
|
|
<div class="visual-view" data-view="funnel">
|
|
<ol class="funnel" aria-label="候选审核结果漏斗">
|
|
<li><span class="metric">6</span><strong>已生成候选</strong><small>30 次 solver 调用</small></li>
|
|
<li class="physical"><span class="metric">3</span><strong>物理约束合格</strong><small>基础几何层</small></li>
|
|
<li class="blocked"><span class="metric">0</span><strong>严格范围合格</strong><small>raw 曲率范围</small></li>
|
|
<li class="blocked"><span class="metric">0</span><strong>越界合格</strong><small>无最小值可报告</small></li>
|
|
<li class="final"><span class="metric">0</span><strong>替换输出</strong><small>管线 Unchanged</small></li>
|
|
</ol>
|
|
</div>
|
|
|
|
<div class="visual-view" data-view="gates">
|
|
<div class="gate-grid" aria-label="严格与测量路径的质量门状态">
|
|
<article class="gate accepted">
|
|
<span class="step">步骤 1</span>
|
|
<h3>候选生成</h3>
|
|
<p>局部替换曲线被构造并进入审核。</p>
|
|
<span class="gate-result green">6 个候选</span>
|
|
</article>
|
|
<article class="gate blocked">
|
|
<span class="step">步骤 2</span>
|
|
<h3>Strict raw 曲率范围</h3>
|
|
<p>严格路径首先判定候选是否保持原有接纳语义。</p>
|
|
<span class="gate-result red">0 个严格合格</span>
|
|
</article>
|
|
<article class="gate measurement">
|
|
<span class="step">步骤 3</span>
|
|
<h3>Measurement trace</h3>
|
|
<p>只为取证而继续记录后续质量门,不改变 Strict 结论。</p>
|
|
<span class="gate-result amber">一次性测量路径</span>
|
|
</article>
|
|
<article class="gate output">
|
|
<span class="step">步骤 4</span>
|
|
<h3>净空与最终输出</h3>
|
|
<p>3 个物理约束合格候选在净空门阻断,未被接受。</p>
|
|
<span class="gate-result slate">原路径保持</span>
|
|
</article>
|
|
</div>
|
|
<p class="measurement-note">Measurement 的作用是把阻断位置记录完整,不是放宽生产质量门。它不能授权修改 evaluator,也不能让候选进入正式输出。</p>
|
|
</div>
|
|
|
|
<div class="visual-view" data-view="performance">
|
|
<div class="performance-layout">
|
|
<div class="timing-list" aria-label="性能汇总,单位为毫秒">
|
|
<div class="timing-row">
|
|
<span class="timing-label">Solver 中位 / 限制</span>
|
|
<div class="timing-bar" style="--median: 49%; --worst: 0%;">
|
|
<span class="median">4.94 ms</span>
|
|
<span class="worst"></span>
|
|
<span class="remaining">限制 10 ms</span>
|
|
</div>
|
|
</div>
|
|
<div class="timing-row">
|
|
<span class="timing-label">Solver 最坏 / 限制</span>
|
|
<div class="timing-bar" style="--median: 31%; --worst: 0%;">
|
|
<span class="median">7.74 ms</span>
|
|
<span class="worst"></span>
|
|
<span class="remaining">限制 25 ms</span>
|
|
</div>
|
|
</div>
|
|
<div class="timing-row">
|
|
<span class="timing-label">Region 中位 / 限制</span>
|
|
<div class="timing-bar" style="--median: 40%; --worst: 0%;">
|
|
<span class="median">10.09 ms</span>
|
|
<span class="worst"></span>
|
|
<span class="remaining">限制 25 ms</span>
|
|
</div>
|
|
</div>
|
|
<div class="timing-row">
|
|
<span class="timing-label">Region 最坏 / 限制</span>
|
|
<div class="timing-bar" style="--median: 46%; --worst: 0%;">
|
|
<span class="median">23.22 ms</span>
|
|
<span class="worst"></span>
|
|
<span class="remaining">限制 50 ms</span>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
<aside class="determinism">
|
|
<strong>1</strong>
|
|
<p>个确定性签名<br>5 次预热 + 30 次测量<br>性能超限:False</p>
|
|
</aside>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="section">
|
|
<h2>如何理解“平滑方案效果”</h2>
|
|
<p class="section-intro">本次结果不是“完全没有曲线”,也不能直接写成“所有候选曲率都比原路径更大”。真正的结论是,候选在不同质量层的状态不同,且没有一个最终满足现有严格接纳条件。</p>
|
|
<div class="facts">
|
|
<article class="fact">
|
|
<h3>候选层确实执行</h3>
|
|
<p>系统生成了 6 个局部候选,并对它们完成了有界搜索和账本审计。</p>
|
|
</article>
|
|
<article class="fact">
|
|
<h3>严格接纳没有通过</h3>
|
|
<p>raw 曲率范围严格合格数为 0,因此不能把任何候选写成可发布的路径平滑结果。</p>
|
|
</article>
|
|
<article class="fact">
|
|
<h3>输出没有变化</h3>
|
|
<p>Measurement 继续记录后,候选仍被净空门阻断;管线最终保持 Unchanged。</p>
|
|
</article>
|
|
</div>
|
|
</section>
|
|
|
|
<section class="section">
|
|
<h2>本轮修改边界</h2>
|
|
<table>
|
|
<thead>
|
|
<tr><th>范围</th><th>改动</th><th>结论</th></tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td>一次性 probe core</td><td>候选搜索、账本、严格审计与证据生成。</td><td>只用于验证,不回写生产源码。</td></tr>
|
|
<tr><td>Measurement root</td><td>LocalG2CandidateEvaluator.cs 的测量延续与 trace 捕获。</td><td>只用于取证,不是生产 evaluator 变更。</td></tr>
|
|
<tr><td>共享分支</td><td>发布正式证据报告。</td><td>没有提交 probe 源码,也没有修改 evaluator。</td></tr>
|
|
<tr><td>本日报目录</td><td>新增本页及对应 Markdown 摘要。</td><td>仅整理事实与证据入口,不改变路径平滑行为。</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</section>
|
|
|
|
<section class="section">
|
|
<h2>后续边界</h2>
|
|
<ol class="actions">
|
|
<li>保持 QUALITY_RED 对应的授权结论:不把 Measurement 改动复制到生产 evaluator。</li>
|
|
<li>不为了得到绿色结果而放宽 raw 曲率范围、净空或其他质量门。</li>
|
|
<li>继续按已有优先级处理基线复验、窗口长度语义与多区域弧长定位风险。</li>
|
|
<li>新的几何策略或场景范围需要独立计划和新的验收证据,不能从本次 SingleTurn 结果直接推导发布结论。</li>
|
|
</ol>
|
|
</section>
|
|
|
|
<footer>
|
|
对应主报告:03-local-g2-curvature-excursion-feasibility-report.md。数据来源:docs/superpowers/reports/2026-08-01-local-g2-minimum-curvature-excursion-feasibility-report.md。单文件离线 HTML,无外部资源依赖。
|
|
</footer>
|
|
</main>
|
|
|
|
<script>
|
|
'use strict';
|
|
|
|
const views = Object.freeze({
|
|
funnel: Object.freeze({
|
|
title: '候选已经生成,但没有进入最终输出',
|
|
description: '6 个候选中有 3 个达到车辆物理约束层;严格 raw 曲率范围合格数仍为 0,因此不能把任何候选当作可发布的平滑路径。',
|
|
state: '结果:Unchanged'
|
|
}),
|
|
gates: Object.freeze({
|
|
title: '严格路径阻断,测量路径只补全证据',
|
|
description: 'Strict 保持共享 evaluator 语义并在 raw 曲率范围处拒绝候选。Measurement 仅为追踪后续质量门,不能改变严格结论或生产代码。',
|
|
state: '授权:不修改 evaluator'
|
|
}),
|
|
performance: Object.freeze({
|
|
title: '时间预算与结果确定性均通过',
|
|
description: '5 次预热和 30 次测量均在既定性能阈值内完成,且只产生 1 个确定性签名;这些结果不覆盖严格接纳失败。',
|
|
state: '性能超限:False'
|
|
})
|
|
});
|
|
|
|
const buttons = Array.from(document.querySelectorAll('.view-button'));
|
|
|
|
function selectView(viewId) {
|
|
const view = views[viewId];
|
|
if (!view) return;
|
|
const root = document.getElementById('excursion-report');
|
|
root.dataset.view = viewId;
|
|
document.getElementById('view-title').textContent = view.title;
|
|
document.getElementById('view-description').textContent = view.description;
|
|
document.getElementById('view-state').textContent = view.state;
|
|
buttons.forEach((button) => button.setAttribute('aria-pressed', String(button.dataset.view === viewId)));
|
|
}
|
|
|
|
buttons.forEach((button) => button.addEventListener('click', () => selectView(button.dataset.view)));
|
|
selectView('funnel');
|
|
</script>
|
|
</body>
|
|
</html>
|