This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1280" viewBox="0 0 1200 1280" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Совместимость writer и reader для контракта profile.settings</title>
|
||||
<desc id="desc">Writer v1 и v2 записывают настройки профиля. Writer v2 добавляет необязательный timezone. Reader v1 игнорирует неизвестный optional ключ, reader v2 различает absent, null и строковое значение. Внизу показаны запрещённые сужение значений и смена смысла.</desc>
|
||||
<rect width="1200" height="1280" fill="#0b1220"/>
|
||||
<rect x="48" y="42" width="1104" height="108" rx="24" fill="#13233e" stroke="#5dd6ff" stroke-width="3"/>
|
||||
<text x="92" y="94" font-family="Arial, sans-serif" font-size="42" font-weight="700" fill="#f8fbff">Контракт profile.settings: совместимость</text>
|
||||
<text x="92" y="127" font-family="Arial, sans-serif" font-size="25" fill="#b7c9df">Проверяем конкретную пару writer → reader</text>
|
||||
<rect x="70" y="220" width="420" height="226" rx="22" fill="#1a304d" stroke="#72b9ff" stroke-width="3"/>
|
||||
<text x="104" y="274" font-family="Arial, sans-serif" font-size="35" font-weight="700" fill="#ffffff">writer v1</text>
|
||||
<text x="104" y="319" font-family="Arial, sans-serif" font-size="27" fill="#dcecff">id · name · settings</text>
|
||||
<text x="104" y="360" font-family="Arial, sans-serif" font-size="25" fill="#9ec6eb">timezone: absent</text>
|
||||
<text x="104" y="405" font-family="Arial, sans-serif" font-size="23" fill="#f9d889">digest: off / weekly / daily</text>
|
||||
<rect x="710" y="220" width="420" height="226" rx="22" fill="#173c39" stroke="#64e2b8" stroke-width="3"/>
|
||||
<text x="744" y="274" font-family="Arial, sans-serif" font-size="35" font-weight="700" fill="#ffffff">writer v2</text>
|
||||
<text x="744" y="319" font-family="Arial, sans-serif" font-size="27" fill="#d7fff0">тот же core</text>
|
||||
<text x="744" y="360" font-family="Arial, sans-serif" font-size="25" fill="#a4e4d0">+ optional timezone</text>
|
||||
<text x="744" y="405" font-family="Arial, sans-serif" font-size="23" fill="#f9d889">absent / null / string</text>
|
||||
<path d="M490 333 H690" stroke="#7ee5c5" stroke-width="8" fill="none" marker-end="url(#arrowGreen)"/>
|
||||
<text x="510" y="304" font-family="Arial, sans-serif" font-size="23" fill="#b9f3df">additive key</text>
|
||||
<rect x="70" y="560" width="420" height="244" rx="22" fill="#1b2c47" stroke="#84aefa" stroke-width="3"/>
|
||||
<text x="104" y="616" font-family="Arial, sans-serif" font-size="35" font-weight="700" fill="#ffffff">reader v1</text>
|
||||
<text x="104" y="662" font-family="Arial, sans-serif" font-size="26" fill="#dcecff">читает именованный core</text>
|
||||
<text x="104" y="703" font-family="Arial, sans-serif" font-size="25" fill="#b4c9e8">unknown optional: ignore</text>
|
||||
<text x="104" y="751" font-family="Arial, sans-serif" font-size="23" fill="#f9d889">timezone не required</text>
|
||||
<rect x="710" y="560" width="420" height="244" rx="22" fill="#16433b" stroke="#70e6be" stroke-width="3"/>
|
||||
<text x="744" y="616" font-family="Arial, sans-serif" font-size="35" font-weight="700" fill="#ffffff">reader v2</text>
|
||||
<text x="744" y="662" font-family="Arial, sans-serif" font-size="26" fill="#d7fff0">читает core + timezone</text>
|
||||
<text x="744" y="703" font-family="Arial, sans-serif" font-size="25" fill="#a4e4d0">absent ≠ null ≠ string</text>
|
||||
<text x="744" y="751" font-family="Arial, sans-serif" font-size="23" fill="#f9d889">старый record читаем</text>
|
||||
<path d="M280 446 V540" stroke="#75d9ff" stroke-width="8" fill="none" marker-end="url(#arrowBlue)"/>
|
||||
<path d="M920 446 V540" stroke="#7ee5c5" stroke-width="8" fill="none" marker-end="url(#arrowGreen)"/>
|
||||
<path d="M490 676 H690" stroke="#7ee5c5" stroke-width="8" fill="none" marker-end="url(#arrowGreen)"/>
|
||||
<text x="530" y="646" font-family="Arial, sans-serif" font-size="22" fill="#b9f3df">доказанная пара</text>
|
||||
<rect x="70" y="915" width="1060" height="280" rx="24" fill="#392432" stroke="#ff8fa4" stroke-width="3"/>
|
||||
<text x="108" y="970" font-family="Arial, sans-serif" font-size="34" font-weight="700" fill="#fff5f7">Красная граница: тест обязан остановить изменение</text>
|
||||
<circle cx="130" cy="1038" r="12" fill="#ff8fa4"/>
|
||||
<text x="164" y="1048" font-family="Arial, sans-serif" font-size="27" fill="#ffe0e6">narrowing: новый reader отвергает legacy значение daily</text>
|
||||
<circle cx="130" cy="1100" r="12" fill="#ff8fa4"/>
|
||||
<text x="164" y="1110" font-family="Arial, sans-serif" font-size="27" fill="#ffe0e6">semantic change: weekly остаётся строкой, но меняет смысл</text>
|
||||
<circle cx="130" cy="1162" r="12" fill="#ff8fa4"/>
|
||||
<text x="164" y="1172" font-family="Arial, sans-serif" font-size="27" fill="#ffe0e6">presence break: старому writer нельзя внезапно потребовать timezone</text>
|
||||
<defs>
|
||||
<marker id="arrowGreen" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 z" fill="#7ee5c5"/></marker>
|
||||
<marker id="arrowBlue" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 z" fill="#75d9ff"/></marker>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.4 KiB |
@@ -0,0 +1,46 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1280" viewBox="0 0 1200 1280" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Диагностика падения reader после записи</title>
|
||||
<desc id="desc">Дерево диагностики: зафиксировать безопасное evidence, различить неверный тип, absent и null, сужение старых значений и смену смысла. При несовместимой активной паре остановить producer, сохранить sample и добавить проверку в compatibility matrix.</desc>
|
||||
<rect width="1200" height="1280" fill="#0b1322"/>
|
||||
<rect x="48" y="42" width="1104" height="110" rx="24" fill="#342537" stroke="#ff9ab0" stroke-width="3"/>
|
||||
<text x="92" y="96" font-family="Arial, sans-serif" font-size="42" font-weight="700" fill="#ffffff">Reader упал после записи: диагностика</text>
|
||||
<text x="92" y="130" font-family="Arial, sans-serif" font-size="25" fill="#ffd5dd">Сначала evidence, затем rollback или остановка producer</text>
|
||||
<rect x="170" y="210" width="860" height="130" rx="22" fill="#193555" stroke="#77bcff" stroke-width="3"/>
|
||||
<text x="212" y="264" font-family="Arial, sans-serif" font-size="32" font-weight="700" fill="#ffffff">1. Собрать безопасное evidence</text>
|
||||
<text x="212" y="305" font-family="Arial, sans-serif" font-size="24" fill="#d5eaff">record id · writer/reader · field names · error path · state key</text>
|
||||
<path d="M600 340 V414" stroke="#9fc8f0" stroke-width="7" fill="none" marker-end="url(#arrow)"/>
|
||||
<polygon points="600,416 800,500 600,584 400,500" fill="#244b49" stroke="#78e1be" stroke-width="3"/>
|
||||
<text x="510" y="493" font-family="Arial, sans-serif" font-size="28" font-weight="700" fill="#ffffff">Какой разрыв?</text>
|
||||
<text x="496" y="528" font-family="Arial, sans-serif" font-size="21" fill="#cef8e9">type · presence · narrowing · semantic</text>
|
||||
<path d="M472 555 L310 654" stroke="#ffb069" stroke-width="6" fill="none" marker-end="url(#arrowOrange)"/>
|
||||
<path d="M558 580 L505 654" stroke="#80c4ff" stroke-width="6" fill="none" marker-end="url(#arrow)"/>
|
||||
<path d="M642 580 L695 654" stroke="#f6d06f" stroke-width="6" fill="none" marker-end="url(#arrowYellow)"/>
|
||||
<path d="M728 555 L890 654" stroke="#ff94a9" stroke-width="6" fill="none" marker-end="url(#arrowPink)"/>
|
||||
<rect x="70" y="675" width="500" height="146" rx="20" fill="#4a3022" stroke="#ffb069" stroke-width="3"/>
|
||||
<text x="104" y="727" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#fff6ee">Type break</text>
|
||||
<text x="104" y="766" font-family="Arial, sans-serif" font-size="24" fill="#ffe2ca">timezone: number → stop writer path</text>
|
||||
<rect x="630" y="675" width="500" height="146" rx="20" fill="#1d3555" stroke="#80c4ff" stroke-width="3"/>
|
||||
<text x="664" y="727" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#ffffff">Presence</text>
|
||||
<text x="664" y="766" font-family="Arial, sans-serif" font-size="24" fill="#d8efff">absent ≠ null → вернуть ветку reader</text>
|
||||
<rect x="70" y="860" width="500" height="146" rx="20" fill="#4a3b21" stroke="#f6d06f" stroke-width="3"/>
|
||||
<text x="104" y="912" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#ffffff">Narrowing</text>
|
||||
<text x="104" y="951" font-family="Arial, sans-serif" font-size="24" fill="#fff0bc">legacy daily rejected → restore range</text>
|
||||
<rect x="630" y="860" width="500" height="146" rx="20" fill="#482633" stroke="#ff94a9" stroke-width="3"/>
|
||||
<text x="664" y="912" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#ffffff">Semantic</text>
|
||||
<text x="664" y="951" font-family="Arial, sans-serif" font-size="24" fill="#ffe0e6">same string, new meaning → stop producer</text>
|
||||
<path d="M320 821 V1037" stroke="#ffb069" stroke-width="6" fill="none" marker-end="url(#arrowOrange)"/>
|
||||
<path d="M880 821 V1037" stroke="#80c4ff" stroke-width="6" fill="none" marker-end="url(#arrow)"/>
|
||||
<path d="M320 1006 V1037" stroke="#f6d06f" stroke-width="6" fill="none" marker-end="url(#arrowYellow)"/>
|
||||
<path d="M880 1006 V1037" stroke="#ff94a9" stroke-width="6" fill="none" marker-end="url(#arrowPink)"/>
|
||||
<rect x="135" y="1060" width="930" height="146" rx="24" fill="#183b38" stroke="#79e1bd" stroke-width="3"/>
|
||||
<text x="178" y="1110" font-family="Arial, sans-serif" font-size="33" font-weight="700" fill="#ffffff">2. Безопасное действие</text>
|
||||
<text x="178" y="1150" font-family="Arial, sans-serif" font-size="25" fill="#d7fff0">Сохранить sample и добавить accept/reject в compatibility matrix.</text>
|
||||
<text x="178" y="1184" font-family="Arial, sans-serif" font-size="22" fill="#aee8d4">Не переписывать record наугад: сначала проверить active writer → reader pair.</text>
|
||||
<defs>
|
||||
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 z" fill="#9fc8f0"/></marker>
|
||||
<marker id="arrowOrange" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 z" fill="#ffb069"/></marker>
|
||||
<marker id="arrowYellow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 z" fill="#f6d06f"/></marker>
|
||||
<marker id="arrowPink" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 z" fill="#ff94a9"/></marker>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="1280" viewBox="0 0 1200 1280" role="img" aria-labelledby="title desc">
|
||||
<title id="title">Безопасная эволюция контракта profile.settings</title>
|
||||
<desc id="desc">Вертикальная последовательность: зафиксировать version one и samples, добавить reader version two с различением absent и null, затем добавить writer version two с optional timezone и проверить матрицу. Внизу показан запрет на narrowing старых значений и смену семантики.</desc>
|
||||
<rect width="1200" height="1280" fill="#0c1424"/>
|
||||
<rect x="48" y="44" width="1104" height="112" rx="24" fill="#162946" stroke="#8ec5ff" stroke-width="3"/>
|
||||
<text x="92" y="98" font-family="Arial, sans-serif" font-size="42" font-weight="700" fill="#ffffff">Эволюция договора: reader раньше writer</text>
|
||||
<text x="92" y="132" font-family="Arial, sans-serif" font-size="25" fill="#bed3ed">Каждый шаг имеет sample и проверяемый verdict</text>
|
||||
<line x1="600" y1="226" x2="600" y2="1020" stroke="#7899bf" stroke-width="10" stroke-linecap="round"/>
|
||||
<circle cx="600" cy="260" r="31" fill="#71b9ff"/>
|
||||
<rect x="112" y="198" width="420" height="150" rx="20" fill="#1b3557" stroke="#71b9ff" stroke-width="3"/>
|
||||
<text x="144" y="252" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#ffffff">1. Зафиксировать v1</text>
|
||||
<text x="144" y="292" font-family="Arial, sans-serif" font-size="24" fill="#d7e9ff">core-поля, samples, owner, daily</text>
|
||||
<text x="144" y="325" font-family="Arial, sans-serif" font-size="22" fill="#aac9e8">не менять meaning задним числом</text>
|
||||
<circle cx="600" cy="468" r="31" fill="#77e2bd"/>
|
||||
<rect x="668" y="404" width="420" height="154" rx="20" fill="#19443d" stroke="#77e2bd" stroke-width="3"/>
|
||||
<text x="700" y="458" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#ffffff">2. Добавить reader v2</text>
|
||||
<text x="700" y="498" font-family="Arial, sans-serif" font-size="24" fill="#dbfff2">v1 → timezone: absent</text>
|
||||
<text x="700" y="531" font-family="Arial, sans-serif" font-size="22" fill="#aee8d4">null остаётся explicit clear</text>
|
||||
<circle cx="600" cy="680" r="31" fill="#77e2bd"/>
|
||||
<rect x="112" y="616" width="420" height="154" rx="20" fill="#19443d" stroke="#77e2bd" stroke-width="3"/>
|
||||
<text x="144" y="670" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#ffffff">3. Добавить writer v2</text>
|
||||
<text x="144" y="710" font-family="Arial, sans-serif" font-size="24" fill="#dbfff2">+ optional timezone</text>
|
||||
<text x="144" y="743" font-family="Arial, sans-serif" font-size="22" fill="#aee8d4">старый core и meaning сохранены</text>
|
||||
<circle cx="600" cy="892" r="31" fill="#f5c768"/>
|
||||
<rect x="668" y="828" width="420" height="154" rx="20" fill="#4b3b21" stroke="#f5c768" stroke-width="3"/>
|
||||
<text x="700" y="882" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#ffffff">4. Проверить matrix</text>
|
||||
<text x="700" y="922" font-family="Arial, sans-serif" font-size="24" fill="#fff0bf">v1→v1, v1→v2, v2→v1, v2→v2</text>
|
||||
<text x="700" y="955" font-family="Arial, sans-serif" font-size="22" fill="#f6d982">negative case: reject</text>
|
||||
<path d="M600 300 V428" stroke="#71b9ff" stroke-width="7" fill="none" marker-end="url(#arrow)"/>
|
||||
<path d="M600 508 V640" stroke="#77e2bd" stroke-width="7" fill="none" marker-end="url(#arrow)"/>
|
||||
<path d="M600 720 V852" stroke="#f5c768" stroke-width="7" fill="none" marker-end="url(#arrow)"/>
|
||||
<rect x="70" y="1070" width="1060" height="150" rx="24" fill="#3a2431" stroke="#ff91a8" stroke-width="3"/>
|
||||
<text x="108" y="1128" font-family="Arial, sans-serif" font-size="31" font-weight="700" fill="#fff5f7">Стоп до rollout</text>
|
||||
<text x="350" y="1128" font-family="Arial, sans-serif" font-size="27" fill="#ffe0e6">narrowing · required вместо optional</text>
|
||||
<text x="108" y="1176" font-family="Arial, sans-serif" font-size="24" fill="#ffbecb">Новый смысл старого key: сначала transition и owner decision.</text>
|
||||
<defs>
|
||||
<marker id="arrow" markerWidth="12" markerHeight="12" refX="10" refY="6" orient="auto"><path d="M0,0 L12,6 L0,12 z" fill="#b9d4f3"/></marker>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.5 KiB |
Reference in New Issue
Block a user