<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Priority on Tarragon</title><link>https://tarrragon.github.io/blog/tags/priority/</link><description>Recent content in Priority on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Sat, 20 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/priority/index.xml" rel="self" type="application/rss+xml"/><item><title>降級策略</title><link>https://tarrragon.github.io/blog/devops/07-burst-traffic/degradation-strategy/</link><pubDate>Sat, 20 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/devops/07-burst-traffic/degradation-strategy/</guid><description>&lt;p>降級策略的核心決策是「超載時犧牲什麼保住什麼」。犧牲的是精度、延遲或非核心功能；保住的是核心功能的可用性。沒有降級策略的系統在超載時整體崩潰 — 所有功能同時不可用。&lt;/p>
&lt;h2 id="動態取樣">動態取樣&lt;/h2>
&lt;p>流量超過閾值時自動降低取樣率。平時 100% 收集、超載時降到 10% — 仍有資料可分析，只是精度下降。&lt;/p>
&lt;h3 id="觸發條件">觸發條件&lt;/h3>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>訊號&lt;/th>
 &lt;th>動作&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Collector 回 429 次數 &amp;gt; N / 分鐘&lt;/td>
 &lt;td>SDK 降低取樣率 50%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>連續 429 超過 M 分鐘&lt;/td>
 &lt;td>SDK 再降到 10%&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>429 消失且 buffer 清空&lt;/td>
 &lt;td>SDK 恢復 100%&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;h3 id="取樣的公平性">取樣的公平性&lt;/h3>
&lt;p>動態取樣不應該只丟新事件保留舊事件（FIFO 丟棄）— 這會讓取樣偏向「burst 初期的事件」。更好的策略是隨機取樣（每個事件有 sampling_rate 的機率被保留），讓取樣後的資料仍然能代表整體分佈。&lt;/p>
&lt;p>取樣後的事件帶 &lt;code>_sampling_rate&lt;/code> 欄位，分析時用 &lt;code>1 / sampling_rate&lt;/code> 做加權還原。&lt;/p>
&lt;h2 id="事件優先級">事件優先級&lt;/h2>
&lt;p>不同事件類型的 debug 價值不同。超載時先丟價值低的，保留價值高的。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>優先級&lt;/th>
 &lt;th>事件類型&lt;/th>
 &lt;th>理由&lt;/th>
 &lt;th>超載時處理&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>最高&lt;/td>
 &lt;td>error&lt;/td>
 &lt;td>debug 核心 — 丟了就查不到問題&lt;/td>
 &lt;td>全部保留&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>高&lt;/td>
 &lt;td>lifecycle&lt;/td>
 &lt;td>session 邊界 — 影響 session 分析&lt;/td>
 &lt;td>全部保留&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>中&lt;/td>
 &lt;td>metric&lt;/td>
 &lt;td>趨勢可從取樣還原&lt;/td>
 &lt;td>降低取樣率&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>低&lt;/td>
 &lt;td>event&lt;/td>
 &lt;td>行為分析可接受精度損失&lt;/td>
 &lt;td>降低取樣率或暫停&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>優先級的判斷原則：「這個事件丟了、要花多少時間從其他來源補回相同資訊」。Error 的 stack trace 丟了幾乎不可能從其他來源補回；event 的 click 計數可以從後續資料的趨勢推測。&lt;/p>
&lt;h2 id="功能降級">功能降級&lt;/h2>
&lt;p>非核心功能暫時關閉或降低更新頻率，把資源留給核心功能。&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>功能&lt;/th>
 &lt;th>正常模式&lt;/th>
 &lt;th>降級模式&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>Dashboard 即時刷新&lt;/td>
 &lt;td>每秒查詢&lt;/td>
 &lt;td>每 30 秒查詢&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>Rule engine 評估&lt;/td>
 &lt;td>每筆事件即時評估&lt;/td>
 &lt;td>累積 10 筆批次評估&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>JSONL 匯出&lt;/td>
 &lt;td>隨時可匯出&lt;/td>
 &lt;td>暫停（避免 I/O 競爭）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>降採樣 job&lt;/td>
 &lt;td>每小時跑&lt;/td>
 &lt;td>延後到流量恢復後補跑&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>降級的觸發和恢復應該自動化 — 用 collector 的內部 metric（goroutine pool 使用率、寫入延遲）作為訊號。&lt;/p>
&lt;h2 id="聚合前移">聚合前移&lt;/h2>
&lt;p>讓 SDK 端做預聚合，減少送到 collector 的事件數量。&lt;/p>
&lt;p>平時：每次 click 送一筆 &lt;code>button.clicked&lt;/code> 事件 → 100 次 click = 100 筆事件。
聚合前移：SDK 累積 10 秒內的 click → 送一筆 &lt;code>button.clicked&lt;/code> 帶 &lt;code>count: 17&lt;/code> → 100 次 click = ~10 筆事件。&lt;/p>
&lt;p>聚合前移犧牲的是事件粒度（失去每次 click 的精確時間戳），換取的是 10x 的事件量減少。適用於高頻但單筆資訊量低的事件（click、scroll、mousemove）。&lt;/p>
&lt;p>聚合前移的觸發也可以是動態的 — collector 回 429 時 SDK 自動啟用聚合前移，流量恢復後關閉。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>突發流量的分類 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/burst-classification/" data-link-title="突發流量的分類" data-link-desc="可預期 vs 不可預期的突發流量 — 不同來源、持續時間和倍率決定不同的應對策略">突發流量的分類&lt;/a>&lt;/li>
&lt;li>Queue 做更大規模的緩衝 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/queue-buffering/" data-link-title="Queue 緩衝" data-link-desc="在 ingestion 和 processing 之間加 message queue 做 burst 緩衝 — Kafka / NATS / Redis Streams 的選型和引入條件">Queue 緩衝&lt;/a>&lt;/li>
&lt;li>不同規模的應對方案 → &lt;a href="https://tarrragon.github.io/blog/devops/07-burst-traffic/scale-tier-response/" data-link-title="規模分級應對表" data-link-desc="自用級 → 中型 → 大型 → 商業網站級的四級應對方案 — 每級的觸發條件、架構組成和成本">規模分級應對表&lt;/a>&lt;/li>
&lt;li>背壓和 rate limit 的基礎 → &lt;a href="https://tarrragon.github.io/blog/devops/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>降級策略的核心決策是「超載時犧牲什麼保住什麼」。犧牲的是精度、延遲或非核心功能；保住的是核心功能的可用性。沒有降級策略的系統在超載時整體崩潰 — 所有功能同時不可用。</p>
<h2 id="動態取樣">動態取樣</h2>
<p>流量超過閾值時自動降低取樣率。平時 100% 收集、超載時降到 10% — 仍有資料可分析，只是精度下降。</p>
<h3 id="觸發條件">觸發條件</h3>
<table>
  <thead>
      <tr>
          <th>訊號</th>
          <th>動作</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Collector 回 429 次數 &gt; N / 分鐘</td>
          <td>SDK 降低取樣率 50%</td>
      </tr>
      <tr>
          <td>連續 429 超過 M 分鐘</td>
          <td>SDK 再降到 10%</td>
      </tr>
      <tr>
          <td>429 消失且 buffer 清空</td>
          <td>SDK 恢復 100%</td>
      </tr>
  </tbody>
</table>
<h3 id="取樣的公平性">取樣的公平性</h3>
<p>動態取樣不應該只丟新事件保留舊事件（FIFO 丟棄）— 這會讓取樣偏向「burst 初期的事件」。更好的策略是隨機取樣（每個事件有 sampling_rate 的機率被保留），讓取樣後的資料仍然能代表整體分佈。</p>
<p>取樣後的事件帶 <code>_sampling_rate</code> 欄位，分析時用 <code>1 / sampling_rate</code> 做加權還原。</p>
<h2 id="事件優先級">事件優先級</h2>
<p>不同事件類型的 debug 價值不同。超載時先丟價值低的，保留價值高的。</p>
<table>
  <thead>
      <tr>
          <th>優先級</th>
          <th>事件類型</th>
          <th>理由</th>
          <th>超載時處理</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>最高</td>
          <td>error</td>
          <td>debug 核心 — 丟了就查不到問題</td>
          <td>全部保留</td>
      </tr>
      <tr>
          <td>高</td>
          <td>lifecycle</td>
          <td>session 邊界 — 影響 session 分析</td>
          <td>全部保留</td>
      </tr>
      <tr>
          <td>中</td>
          <td>metric</td>
          <td>趨勢可從取樣還原</td>
          <td>降低取樣率</td>
      </tr>
      <tr>
          <td>低</td>
          <td>event</td>
          <td>行為分析可接受精度損失</td>
          <td>降低取樣率或暫停</td>
      </tr>
  </tbody>
</table>
<p>優先級的判斷原則：「這個事件丟了、要花多少時間從其他來源補回相同資訊」。Error 的 stack trace 丟了幾乎不可能從其他來源補回；event 的 click 計數可以從後續資料的趨勢推測。</p>
<h2 id="功能降級">功能降級</h2>
<p>非核心功能暫時關閉或降低更新頻率，把資源留給核心功能。</p>
<table>
  <thead>
      <tr>
          <th>功能</th>
          <th>正常模式</th>
          <th>降級模式</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>Dashboard 即時刷新</td>
          <td>每秒查詢</td>
          <td>每 30 秒查詢</td>
      </tr>
      <tr>
          <td>Rule engine 評估</td>
          <td>每筆事件即時評估</td>
          <td>累積 10 筆批次評估</td>
      </tr>
      <tr>
          <td>JSONL 匯出</td>
          <td>隨時可匯出</td>
          <td>暫停（避免 I/O 競爭）</td>
      </tr>
      <tr>
          <td>降採樣 job</td>
          <td>每小時跑</td>
          <td>延後到流量恢復後補跑</td>
      </tr>
  </tbody>
</table>
<p>降級的觸發和恢復應該自動化 — 用 collector 的內部 metric（goroutine pool 使用率、寫入延遲）作為訊號。</p>
<h2 id="聚合前移">聚合前移</h2>
<p>讓 SDK 端做預聚合，減少送到 collector 的事件數量。</p>
<p>平時：每次 click 送一筆 <code>button.clicked</code> 事件 → 100 次 click = 100 筆事件。
聚合前移：SDK 累積 10 秒內的 click → 送一筆 <code>button.clicked</code> 帶 <code>count: 17</code> → 100 次 click = ~10 筆事件。</p>
<p>聚合前移犧牲的是事件粒度（失去每次 click 的精確時間戳），換取的是 10x 的事件量減少。適用於高頻但單筆資訊量低的事件（click、scroll、mousemove）。</p>
<p>聚合前移的觸發也可以是動態的 — collector 回 429 時 SDK 自動啟用聚合前移，流量恢復後關閉。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>突發流量的分類 → <a href="/blog/devops/07-burst-traffic/burst-classification/" data-link-title="突發流量的分類" data-link-desc="可預期 vs 不可預期的突發流量 — 不同來源、持續時間和倍率決定不同的應對策略">突發流量的分類</a></li>
<li>Queue 做更大規模的緩衝 → <a href="/blog/devops/07-burst-traffic/queue-buffering/" data-link-title="Queue 緩衝" data-link-desc="在 ingestion 和 processing 之間加 message queue 做 burst 緩衝 — Kafka / NATS / Redis Streams 的選型和引入條件">Queue 緩衝</a></li>
<li>不同規模的應對方案 → <a href="/blog/devops/07-burst-traffic/scale-tier-response/" data-link-title="規模分級應對表" data-link-desc="自用級 → 中型 → 大型 → 商業網站級的四級應對方案 — 每級的觸發條件、架構組成和成本">規模分級應對表</a></li>
<li>背壓和 rate limit 的基礎 → <a href="/blog/devops/03-traffic-management/" data-link-title="模組三：流量管控" data-link-desc="收到的流量超過處理能力時怎麼辦 — 背壓、rate limit、熔斷、bulkhead 四種防護機制">模組三 流量管控</a></li>
</ul>
]]></content:encoded></item><item><title>Sibling Coverage Asymmetry Blindspot：Priority 評估漏掉的「對稱性維度」</title><link>https://tarrragon.github.io/blog/report/sibling-coverage-asymmetry-blindspot-in-priority/</link><pubDate>Tue, 19 May 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/report/sibling-coverage-asymmetry-blindspot-in-priority/</guid><description>&lt;h2 id="核心priority-評估的-sibling-對稱性盲點">核心：Priority 評估的 sibling 對稱性盲點&lt;/h2>
&lt;p>當批量 A 跟批量 B 是 &lt;em>sibling&lt;/em>（同類 vendor / 同類角色 / 應有對等 coverage）、但 A 後寫卻超過 B、心智模型容易 collapse 到「A 是 reference template / B 是 baseline」的角色分配、忽略 &lt;em>B 才該 ≥ A coverage 的對稱性 priority&lt;/em>。Priority 列表往往跳過 B、列其他「新領域擴張」選項。&lt;/p>
&lt;p>問題不在 &lt;em>推某個 vendor&lt;/em>、在 &lt;em>priority 評估維度漏掉 sibling symmetry&lt;/em>。&lt;/p>
&lt;h2 id="casemysql-18-篇-vs-pg-11-篇後的-priority-列表">Case：MySQL 18 篇 vs PG 11 篇後的 priority 列表&lt;/h2>
&lt;p>時間線：&lt;/p>
&lt;ol>
&lt;li>PG 11 篇先寫完（autovacuum-tuning / declarative-partitioning / patroni-ha / pgbouncer-config / pitr-wal-archiving / logical-replication-debezium + 5 migration playbook）&lt;/li>
&lt;li>MySQL 從 0 開始、user 要求「第一個示範服務、儘量都寫」、寫到 17 篇 deep article + migration playbook + 既有 migrate-to-postgresql = 18 篇 / 5715 行&lt;/li>
&lt;li>推薦下一步 priority 時、列「DynamoDB / Aurora / SQLite / MongoDB / CockroachDB / Spanner / Cosmos DB」、PG &lt;strong>不在列表&lt;/strong>&lt;/li>
&lt;li>User 問：「為什麼這裡列的選項沒有 PG？我們做完了嗎？」&lt;/li>
&lt;/ol>
&lt;p>實際盤點：&lt;/p>
&lt;ul>
&lt;li>PG 11 篇 vs MySQL 18 篇、PG 缺 &lt;strong>7 個 MySQL sibling deep article&lt;/strong>（replication-topology / online-schema-change-tools / query-optimization / lock-contention / vitess-sharding 對應 Citus / group-replication 對應 BDR / modern-sql-features 反向視角）&lt;/li>
&lt;li>PG 還缺 &lt;strong>4 個 PG-only 議題&lt;/strong>（JSONB deep dive / Extension ecosystem / Full-text search / Replication slot management）&lt;/li>
&lt;/ul>
&lt;p>User 直覺 catch 到 &lt;em>coverage asymmetry&lt;/em>、但我 priority 列表沒提供這個視角。&lt;/p>
&lt;h2 id="機制為什麼會忽略">機制：為什麼會忽略&lt;/h2>
&lt;p>至少 5 個 priority bias 共同貢獻：&lt;/p>
&lt;h3 id="1-先存在就-mature隱性假設">1. 「先存在就 mature」隱性假設&lt;/h3>
&lt;p>PG 11 篇先存在 → 直覺映射「PG 已 mature」。沒做 &lt;em>cross-sectional 對比&lt;/em>：&lt;/p>
&lt;ul>
&lt;li>PG 11 篇 vs MySQL 18 篇、絕對量比較&lt;/li>
&lt;li>議題覆蓋對應：MySQL 有哪些 deep article、PG 對應的是否都有&lt;/li>
&lt;/ul>
&lt;p>「11 篇」這個絕對數字 &lt;em>看起來合理&lt;/em>、但跟 MySQL 18 篇對比後 &lt;em>結構性不足&lt;/em>。心智模型把「合理」當成「mature」、跳過了相對性 audit。&lt;/p></description><content:encoded><![CDATA[<h2 id="核心priority-評估的-sibling-對稱性盲點">核心：Priority 評估的 sibling 對稱性盲點</h2>
<p>當批量 A 跟批量 B 是 <em>sibling</em>（同類 vendor / 同類角色 / 應有對等 coverage）、但 A 後寫卻超過 B、心智模型容易 collapse 到「A 是 reference template / B 是 baseline」的角色分配、忽略 <em>B 才該 ≥ A coverage 的對稱性 priority</em>。Priority 列表往往跳過 B、列其他「新領域擴張」選項。</p>
<p>問題不在 <em>推某個 vendor</em>、在 <em>priority 評估維度漏掉 sibling symmetry</em>。</p>
<h2 id="casemysql-18-篇-vs-pg-11-篇後的-priority-列表">Case：MySQL 18 篇 vs PG 11 篇後的 priority 列表</h2>
<p>時間線：</p>
<ol>
<li>PG 11 篇先寫完（autovacuum-tuning / declarative-partitioning / patroni-ha / pgbouncer-config / pitr-wal-archiving / logical-replication-debezium + 5 migration playbook）</li>
<li>MySQL 從 0 開始、user 要求「第一個示範服務、儘量都寫」、寫到 17 篇 deep article + migration playbook + 既有 migrate-to-postgresql = 18 篇 / 5715 行</li>
<li>推薦下一步 priority 時、列「DynamoDB / Aurora / SQLite / MongoDB / CockroachDB / Spanner / Cosmos DB」、PG <strong>不在列表</strong></li>
<li>User 問：「為什麼這裡列的選項沒有 PG？我們做完了嗎？」</li>
</ol>
<p>實際盤點：</p>
<ul>
<li>PG 11 篇 vs MySQL 18 篇、PG 缺 <strong>7 個 MySQL sibling deep article</strong>（replication-topology / online-schema-change-tools / query-optimization / lock-contention / vitess-sharding 對應 Citus / group-replication 對應 BDR / modern-sql-features 反向視角）</li>
<li>PG 還缺 <strong>4 個 PG-only 議題</strong>（JSONB deep dive / Extension ecosystem / Full-text search / Replication slot management）</li>
</ul>
<p>User 直覺 catch 到 <em>coverage asymmetry</em>、但我 priority 列表沒提供這個視角。</p>
<h2 id="機制為什麼會忽略">機制：為什麼會忽略</h2>
<p>至少 5 個 priority bias 共同貢獻：</p>
<h3 id="1-先存在就-mature隱性假設">1. 「先存在就 mature」隱性假設</h3>
<p>PG 11 篇先存在 → 直覺映射「PG 已 mature」。沒做 <em>cross-sectional 對比</em>：</p>
<ul>
<li>PG 11 篇 vs MySQL 18 篇、絕對量比較</li>
<li>議題覆蓋對應：MySQL 有哪些 deep article、PG 對應的是否都有</li>
</ul>
<p>「11 篇」這個絕對數字 <em>看起來合理</em>、但跟 MySQL 18 篇對比後 <em>結構性不足</em>。心智模型把「合理」當成「mature」、跳過了相對性 audit。</p>
<h3 id="2-新領域擴張優於既有領域對齊的-progress-bias">2. 「新領域擴張」優於「既有領域對齊」的 progress bias</h3>
<p>Priority 列表時、DynamoDB / Aurora / SQLite 等 vendor <em>看起來進度感強</em> — 從 0 推到 N、新領域擴張。PG 補齊看起來 <em>重複勞動</em> — 從 11 推到 18、改善舊領域。</p>
<p>實際上：</p>
<ul>
<li>新領域擴張 <em>增加 surface area</em>、但不改善既有結構</li>
<li>既有領域對齊 <em>修補 baseline</em>、是 reference template 成立的前提</li>
</ul>
<p>當 baseline 跟 reference template 不對稱時、後者作為 <em>示範服務</em> 的價值打折扣 — 「MySQL 怎麼寫 vendor article」沒法 fully 套到 PG、因為 PG 本身不對稱。</p>
<h3 id="3-priority-評估維度漏-sibling-symmetry">3. Priority 評估維度漏 sibling symmetry</h3>
<p>我用的 priority 評估維度：</p>
<ul>
<li>T1 vs T2 vendor 分類</li>
<li>領域重要度</li>
<li>已有量</li>
<li>新領域 vs 既有領域</li>
</ul>
<p><strong>漏掉的維度</strong>：</p>
<ul>
<li>Sibling vendor 對稱性（A 跟 B 同類、A 寫完後 B coverage 是否對齊）</li>
<li>Reference template 跟 baseline 的關係（後寫的 reference template 應 ≤ baseline）</li>
</ul>
<p>「Sibling 對稱性」這個維度不在預設 priority 評估清單、就被自動忽略。</p>
<h3 id="4-reference-template-vs-baseline-角色混淆">4. Reference template vs Baseline 角色混淆</h3>
<p>寫 vendor article 時、<em>哪個是 baseline、哪個是 reference template</em> 的心智模型可能反轉：</p>
<ul>
<li>直覺：「先寫的 = baseline、後寫的 = reference / extension」</li>
<li>真實：「baseline 應 ≥ reference template coverage、不該倒過來」</li>
</ul>
<p>MySQL 18 篇是 <em>user-driven 要求</em> — user 明說「第一個示範服務、儘量都寫」。所以 MySQL 寫得多不是錯。但 <em>PG 沒對齊到同水準</em> 才是漏掉的紀律。</p>
<p>當 MySQL 寫到 reference template 規模、PG 還在 11 篇、心智模型容易 collapse 到「MySQL 是新 baseline、PG 是 legacy partial」、其實是 <em>baseline 應該升級到 reference template 水準</em>。</p>
<h3 id="5-sequential-vs-cross-sectional-coverage-評估">5. Sequential vs cross-sectional coverage 評估</h3>
<p>寫作過程是 sequential —寫 MySQL 17 篇是一段時間、寫完看 git diff stat 確認進度、然後 priority 下一步。<strong>Coverage 評估是 point-in-time 的</strong>：</p>
<ul>
<li>Point-in-time（sequential）：「我這 batch 寫了多少」</li>
<li>Cross-sectional（symmetric）：「我寫的這個跟 sibling 是否對齊」</li>
</ul>
<p>寫 MySQL 第 17 篇時 self-cross-check：「PG 對應有沒有？」是 cross-sectional 行為、不是預設行為。</p>
<p>Priority 列表階段沒回頭跑 cross-sectional audit、就把 PG 排除。</p>
<h2 id="修法">修法</h2>
<h3 id="1-priority-candidate-list-必須跑-sibling-symmetry-audit">1. Priority candidate list 必須跑 sibling symmetry audit</h3>
<p>提 priority 列表時、強制 cross-check：</p>
<ul>
<li>列出該批量影響的 <em>sibling vendor / sibling role</em></li>
<li>對比每個 sibling 的 coverage（篇數 + 議題覆蓋 mapping）</li>
<li>若有 asymmetry、把「補齊 sibling」加進 priority 列表 <em>跟新領域並列</em></li>
</ul>
<h3 id="2-vendors_index內容覆蓋進度表加對稱性視角">2. Vendors/_index「內容覆蓋進度」表加對稱性視角</h3>
<p>當前內容覆蓋進度只列「已寫 / 未寫」、不列 <em>sibling 之間相對進度</em>。改善：</p>
<ul>
<li>加 <em>「跟 sibling 對應」欄</em>：每個 article 標 sibling vendor 是否有對應</li>
<li>加 <em>總計篇數 + sibling 對比</em> 欄：直觀看到 asymmetry</li>
</ul>
<h3 id="3-先-mature-baseline再擴張紀律">3. 「先 mature baseline、再擴張」紀律</h3>
<p>寫 vendor batch 時、紀律：</p>
<ul>
<li>確認 <em>baseline vendor 對齊到 reference template 水準</em>、再推下一個 vendor</li>
<li>例外：user 明確要求先擴張某 vendor 時、加註 <em>baseline 待對齊</em> 為 known limitation</li>
</ul>
<h3 id="4-audit-dimension-list-加-coverage-symmetry">4. Audit dimension list 加 <em>Coverage symmetry</em></h3>
<p>跟 <a href="../data-topology-as-audit-dimension/">Data Topology as Audit Dimension</a> 同型 —audit 維度可擴張。把 <em>sibling coverage symmetry</em> 加進 priority audit 維度：</p>
<ul>
<li>既有維度：T1 / 領域 / 已有量 / 新 vs 既有</li>
<li>新增維度：<strong>sibling 對稱性</strong>（A 跟 B 同類時、coverage 對齊度）</li>
</ul>
<h2 id="跟既有原則的關係">跟既有原則的關係</h2>
<ul>
<li><a href="../data-topology-as-audit-dimension/">Data Topology as Audit Dimension</a>：本卡是 <em>priority 評估維度漏一個</em>、同型但不同 axis</li>
<li><a href="../collapse-is-implicit-default/">Collapse is Implicit Default</a>：priority 評估 collapse 到「新領域擴張」維度、是其變體</li>
<li><a href="../multi-pass-review-frame-granularity-blindspot/">Multi-Pass Review Frame Granularity Blindspot</a>：multi-pass review 漏 catch 的同型、但本卡是 <em>priority assessment 漏 catch</em>、不是 <em>review 漏 catch</em></li>
</ul>
<h2 id="反向驗證">反向驗證</h2>
<p>不該誤用本卡：</p>
<ul>
<li><em>Sibling vendor 對稱性</em> 不等於 <em>每個 vendor 都該寫到同篇數</em>。MySQL 18 篇對 PG 合理（兩大 SQL OLTP baseline），但 SQLite / DynamoDB / Spanner 各 18 篇不合理（領域窄 / niche audience）</li>
<li>對稱性 audit 是 <em>對 baseline / reference template 雙方適用</em>、不是擴張到所有 sibling</li>
<li>真正 niche vendor（如 Spanner / Cosmos DB 對小團隊）可以 <em>明確 backlog 標記 minimum coverage</em>、不必對齊 baseline</li>
</ul>
<h2 id="觸發再評估">觸發再評估</h2>
<p>未來累積到以下情境、本卡應重新 review：</p>
<ul>
<li>寫第二個 baseline pair（02 cache Redis vs Memcached / 03 queue Kafka vs NATS 等）時、是否同樣踩 asymmetry blindspot</li>
<li>多 reviewer audit 是否能 catch coverage asymmetry（4-reviewer 沒設計這軸、之後 batch 可加 reviewer E <em>coverage symmetry</em>）</li>
<li>Sibling 對稱性 audit 進工具化（vendors/_index 自動產 asymmetry warning）後是否解決</li>
</ul>
]]></content:encoded></item></channel></rss>