docs: consolidate design documentation and standardize crate English
This commit is contained in:
@@ -1,104 +0,0 @@
|
||||
# Workspace Web Application Architecture
|
||||
|
||||
この文書は、Workspace Webのapplication shell、Header、Sidebar、nested
|
||||
layoutのcomposition authorityを定義する。Navigation
|
||||
IAは[`product-ux.md`](product-ux.md)、視覚とinteractionの共通規則は[`design-language.md`](design-language.md)、具体的なsource
|
||||
pathとCSS
|
||||
ownershipは[`../../../web/workspace/README.md`](../../../web/workspace/README.md)を参照する。
|
||||
|
||||
## Application shell
|
||||
|
||||
root layoutが唯一のapplication shellを所有する。
|
||||
|
||||
- Sidebar frame
|
||||
- global fallback navigation
|
||||
- Header frame
|
||||
- main content
|
||||
- SidebarとHeaderのoverride context
|
||||
|
||||
page routeはapplication shell、global Header、Sidebar、fold
|
||||
controlを再実装しない。Pageのmarkupは標準shellのmainへ配置するcontentから始める。
|
||||
|
||||
## Header composition
|
||||
|
||||
Headerはroot shellが一度だけrenderする。Nested
|
||||
layoutは`HeaderOverride`を通じて現在scopeのlocation contentを登録する。
|
||||
|
||||
- page componentはHeader frameを作らない。
|
||||
- 最も深いactive overrideを表示する。
|
||||
- layoutが破棄されたら直前のoverrideへ戻る。
|
||||
- overrideがなければroot fallbackを表示する。
|
||||
- route titleをmain contentへ複製しない。
|
||||
|
||||
## Sidebar composition
|
||||
|
||||
### Root
|
||||
|
||||
root shellは`SidebarFrame`と`GlobalSidebar`を一度だけrenderし、root
|
||||
`SidebarController`を提供する。Overrideがない場合、`GlobalNavSections`がfallbackになる。
|
||||
|
||||
### Workspace
|
||||
|
||||
Workspace layoutは、親のroot
|
||||
slotへ`WorkspaceSidebar`を登録する。同時に、さらに深いlayoutが使う新しい`SidebarController`をcontextへ設定する。
|
||||
|
||||
`WorkspaceSidebar`はWorkspace shortcut headerを保持し、その下へchild
|
||||
slotをrenderする。Child overrideがない場合だけ、Workspace navigation
|
||||
fallbackを表示する。
|
||||
|
||||
### Settings
|
||||
|
||||
Settings layoutは、Workspace layoutが提供したchild
|
||||
slotへ`SettingsSidebar`を登録する。Workspace shortcut headerは残り、Workspace
|
||||
navigation fallbackだけがSettings navigationへ置き換わる。
|
||||
|
||||
さらに深いscopeも同じcontractを使う。
|
||||
|
||||
## Override stack
|
||||
|
||||
`HeaderOverride`と`SidebarOverride`は、layout lifecycleにbindしたLIFO
|
||||
stackとして扱う。
|
||||
|
||||
1. Layout mount時にparent controllerへregisterする。
|
||||
2. Controllerは最も新しいactive registrationを表示する。
|
||||
3. Nested layoutはchild controllerを新しく提供する。
|
||||
4. Layout destroy時に自分のregistrationをremoveする。
|
||||
5. 一つ前のregistrationがあれば復元する。
|
||||
6. Stackが空ならfallbackへ戻る。
|
||||
|
||||
同じregistrationを複数回removeしても結果を変えない。古いcleanupが新しいactive
|
||||
registrationを削除してはならない。
|
||||
|
||||
## Ownership
|
||||
|
||||
- `SidebarFrame`だけが`aside`、外枠、scroll領域、fold controlを所有する。
|
||||
- `GlobalSidebar`、`WorkspaceSidebar`、`SettingsSidebar`は各scopeのcontentを所有する。
|
||||
- `SidebarOverride`を登録できるのはscopeを定義するlayoutだけとする。
|
||||
- page component、一時的なwidget、dialogはSidebarを差し替えない。
|
||||
- child layoutは親navigationをcopyせず、自分のsidebar layerだけをregisterする。
|
||||
- Global、Workspace、Settingsを一つのsnippetへ平坦化しない。
|
||||
|
||||
## Data authority
|
||||
|
||||
Sidebar compositionはnavigation
|
||||
structureを決めるが、Workspace、permission、Worker
|
||||
stateのauthorityにはならない。
|
||||
|
||||
- Workspace identityとpermissionはBackend projectionを使う。
|
||||
- Worker listとstateはWorkspace protocol projectionを使う。
|
||||
- route pathやdisplay labelからauthorityを推測しない。
|
||||
- unavailable dataを架空の正常stateで置き換えない。
|
||||
- permissionにより利用できないnavigationは、権威あるpermission
|
||||
projectionに基づいて除外する。
|
||||
|
||||
## Design-lab
|
||||
|
||||
認証不要のstatic design-labはroot shellを再利用し、実際と同じnested
|
||||
controllerとoverride stackを構成する。
|
||||
|
||||
Live Workspace protocolへbindするresource listだけは、同じscope layer内のstatic
|
||||
fixtureへ置き換えてよい。Static fixtureへ別scopeのnavigationを混ぜず、production
|
||||
componentと同じ順序、state表現を使う。
|
||||
|
||||
Design-lab固有のswitch controlでSidebarを差し替えず、route
|
||||
hierarchyによってlayout lifecycleを発生させる。
|
||||
@@ -1,196 +0,0 @@
|
||||
# Workspace Web Design Language
|
||||
|
||||
この文書は、Workspace Webのrendered resultが満たす設計規則を定義する。Product固有のresource構成は[`product-ux.md`](product-ux.md)、application shellとSidebar slotの実装構造は[`application-architecture.md`](application-architecture.md)、CSSとsource配置は[`../../../web/workspace/README.md`](../../../web/workspace/README.md)、visual review手順は[`visual-review.md`](visual-review.md)をauthorityとする。
|
||||
|
||||
一つの規則は最も具体的な一箇所だけをauthorityとする。具体的な二案の一方を棄却できない文は規則として残さない。
|
||||
|
||||
## 1. Principles
|
||||
|
||||
複数の規則や要求が競合した場合だけ、この章の優先原理を使う。
|
||||
|
||||
### Task before explanation
|
||||
|
||||
次の有効なactionへ到達する前の操作、scroll、常設説明が少ない案を選ぶ。ただし、説明を省くと対象、結果、permission、不可逆性を誤認する場合は説明をactionより前に置く。
|
||||
|
||||
### Meaning before decoration
|
||||
|
||||
情報の関係、重要度、操作可能性、stateのいずれも変えない視覚差を追加しない。
|
||||
|
||||
### Authority before convenience
|
||||
|
||||
Backend authorityが確定していないdata、state、permission、actionを、UIの都合で補完または推測する案を棄却する。
|
||||
|
||||
## 2. Semantics / Grammar
|
||||
|
||||
### Information structure
|
||||
|
||||
- pageと、page内で一つのtaskまたは判断を完結させる領域をscopeとする。
|
||||
- 各scopeで最も強い視覚要素はheading、現在判断が必要なattention、filled actionのいずれか一つだけにする。同じ強さのheading、attention、filled actionを複数置かない。
|
||||
- hierarchyをcolorだけで表現しない。DOMと画面上の配置順を一致させた上で、size、weight、contrastを使う。
|
||||
- scopeを識別するprimary titleは、一つのscopeにつき一度だけ表示する。
|
||||
- actionは、そのactionが影響するscope内に置く。
|
||||
- DTOにfieldが存在するという理由だけで表示せず、current taskの判断またはactionを変える値だけを常設する。
|
||||
|
||||
**Disclosure**
|
||||
|
||||
- Raw dataやデバッグ情報など、通常は必要としない詳細な情報は折りたたみ領域に隠す。
|
||||
- 作成または編集のformを表示用screenへ常時同居させず、明示的なactionで開く折りたたみ領域または別pageに置く。
|
||||
|
||||
### Interaction and state
|
||||
|
||||
- actionにはbutton、navigationにはlink、選択には対応するform controlを使う。
|
||||
- interactive elementはhover、focus、active、disabledを視覚的に区別する。
|
||||
- staticなstatus、key、metadataをbuttonやpillの形にしない。
|
||||
- clickable rowは遷移先を一つだけ持ち、row全体で同じ遷移を実行する。
|
||||
- permissionがないactionをdisabled controlとして表示しない。
|
||||
|
||||
**State and operation**
|
||||
|
||||
- stateの違いによってユーザーの判断または利用できるactionが変わる場合、その違いを一つの表示へ統合しない。
|
||||
- UI stateはそのstateを所有するauthorityから取得し、別domainやtransportのsignalから推測しない。
|
||||
- 非同期mutationでは楽観的更新か悲観的更新を選ぶ。楽観的更新は暫定stateを明示し、failure時のrollbackまたは再取得を定義できる場合だけ使う。それ以外は確定済みstateを維持し、operationのpending stateを別に表示する。
|
||||
- loading、failure、unavailableの表示は利用不能になった最小のscopeだけを置き換え、利用可能な親scopeとsibling scopeを残す。
|
||||
- destructive actionは対象と結果を明記し、復元できない場合だけconfirmationを要求する。
|
||||
|
||||
### Language / Copy
|
||||
|
||||
- title、navigation label、control labelで明らかな内容を説明文で繰り返さない。
|
||||
- 常設proseは、対象またはactionの選択を変えるwarning、permission、validation constraint、error recoveryに必要な内容だけにする。
|
||||
- button labelには具体的なactionを表す動詞を使い、`Submit`と`OK`を使わない。
|
||||
- identifier、API名、type名を別の語へ言い換えない。
|
||||
|
||||
### Responsive behavior
|
||||
|
||||
- page全体にhorizontal scrollを発生させない。
|
||||
- wrappingまたはstack化によって情報の対応関係が失われる場合だけ、その領域内にbounded horizontal scrollを持たせる。それ以外のside-by-side layoutは一列にする。
|
||||
- primary actionを初期viewportから追い出さない。
|
||||
- contentをtruncateする場合、完全な値をcopyまたはdetailで取得できるようにする。
|
||||
|
||||
### Accessibility
|
||||
|
||||
- action、navigation、form controlを非semantic elementだけで実装しない。
|
||||
- すべてのcontrolにaccessible nameを与える。
|
||||
- keyboard focusを不可視にしない。
|
||||
- tab orderを画面上の順序と一致させる。
|
||||
- stateをcolorだけで区別しない。
|
||||
- horizontal scroll regionをkeyboard focus可能にし、accessible nameを与える。
|
||||
|
||||
## 3. Primitives / Tokens
|
||||
|
||||
### Color / Theme
|
||||
|
||||
colorはCSS custom propertyをauthorityとし、通常のWorkspace colorはOKLCHで定義する。lightとdarkは同じsemantic token名を使う。
|
||||
|
||||
```css
|
||||
--bg
|
||||
--bg-raised
|
||||
--bg-subtle
|
||||
--line
|
||||
--line-strong
|
||||
--text
|
||||
--text-strong
|
||||
--text-muted
|
||||
--text-faint
|
||||
--code
|
||||
--accent
|
||||
--accent-muted
|
||||
--success
|
||||
--warning
|
||||
--danger
|
||||
--interactive-hover
|
||||
--interactive-selected
|
||||
--shadow-overlay
|
||||
```
|
||||
|
||||
- `--bg`、`--bg-raised`、`--bg-subtle`へhueを持たせない。
|
||||
- accentはfocus、current navigation、current selectionだけに使い、通常本文や通常actionの背景へ使わない。
|
||||
- success、warning、dangerを、それぞれ対応するstate以外へ使わない。
|
||||
- componentへraw colorを追加せず、上記semantic tokenを使う。
|
||||
- ConsoleとterminalのANSI paletteを通常のstatusやformへ流用しない。
|
||||
|
||||
### Typography
|
||||
|
||||
font sizeは、その領域でユーザーが行う読み方によって選ぶ。
|
||||
|
||||
- defaultは`14px / 20px`とし、個々のtextを読むこと自体がtaskの中心になる領域に使う。
|
||||
- 同じ構造の反復を一覧として走査する領域と、位置、順序、形、選択状態を中心に識別するUI chromeには`12px / 16px`を使う。textを読まなければactionの意味や結果を判断できない場合は`14px / 20px`を使う。
|
||||
- `24px / 32px`はページまたはdocument内で唯一かつ最大のheadingだけに使う。
|
||||
- 収めるため、または情報を弱く見せるためにfont sizeを下げない。`12px`未満と`13px`を使わない。
|
||||
- 機械的な値にはmonospace familyを使う。
|
||||
|
||||
```css
|
||||
--font-sans
|
||||
--font-mono
|
||||
--font-size-title /* 24px */
|
||||
--line-height-title /* 32px */
|
||||
--font-size-body /* 14px */
|
||||
--line-height-body /* 20px */
|
||||
--font-size-compact /* 12px */
|
||||
--line-height-compact /* 16px */
|
||||
```
|
||||
|
||||
### Spacing / Shape
|
||||
|
||||
```css
|
||||
--space-1 /* 4px */
|
||||
--space-2 /* 8px */
|
||||
--space-3 /* 12px */
|
||||
--space-4 /* 16px */
|
||||
--space-5 /* 24px */
|
||||
--space-6 /* 32px */
|
||||
--radius-soft
|
||||
```
|
||||
|
||||
- 一つの境界にspacing、line、surface backgroundを重ねず、primary cueを一つだけ使う。
|
||||
- 汎用的な`Card` primitiveを設けない。
|
||||
- nested surfaceでparentと同じ境界表現を繰り返さない。
|
||||
- shadowは通常flowから浮くmenu、popover、Tooltipだけに使う。
|
||||
- radiusはinteractive controlだけに使う。
|
||||
|
||||
### Motion
|
||||
|
||||
- motion完了をactionの受付、state change、content理解の条件にしない。
|
||||
- 繰り返しまたは連続animationを、`prefers-reduced-motion: reduce`で停止する。
|
||||
|
||||
## 4. Components / Patterns
|
||||
|
||||
### Border / Structural edge
|
||||
|
||||
- `Bevel`は1pxの単色borderを描くvisual wrapperであり、照明、raised/inset、ridge/grooveを表現しない。
|
||||
- `Bevel`自体へbackgroundやsurface toneを与えず、必要なbackgroundは内側のsemantic childが持つtext/content areaへ適用する。
|
||||
- 隣接するsurfaceでは、実際に境界となる辺だけを有効にする。
|
||||
- standaloneな閉じた領域は全辺を`Bevel`で囲う。Desktop shellではHeaderのbottom edgeとSidebarのright edgeだけを有効にし、viewport外周のtop/left edgeを描かない。
|
||||
- `BevelLine`は開いた領域内の1px separatorだけに使う。同じlayerではheading、本文、Lineの端を揃え、Lineだけに端方向のpaddingやmarginを追加しない。
|
||||
- nested layerでは親layoutがそのlayer全体へinline方向の余白を与え、content、row、Lineを一緒に移動する。Lineだけを短くしない。
|
||||
- control自身のborder、focus ring、status marker、table gridを`Bevel`または`BevelLine`で置き換えない。
|
||||
|
||||
### Sidebar
|
||||
|
||||
- Desktop幅は`clamp(220px, 20vw, 280px)`とする。
|
||||
- navigation contentだけをscrollさせる。
|
||||
- Desktopのfold controlはSidebar下部、Mobileのfold controlはHeaderに置く。
|
||||
- MobileでSidebarを表示するときはHeader下の残りviewport全体を使い、main contentと同時表示しない。
|
||||
- navigationとscope control以外を置かない。
|
||||
- navigation linkはSidebar幅全体を使うflat rowとする。
|
||||
- active routeは一つの視覚cueと`aria-current="page"`で示す。
|
||||
- iconだけでnavigation labelを置き換えない。
|
||||
- fold controlは一つだけ置き、current stateに対応するaccessible nameを使う。
|
||||
|
||||
### Tooltip / Contextual help
|
||||
|
||||
- operationやtable全体を説明する常設proseを置く前に、button labelとcolumn headingだけで識別できるようにする。
|
||||
- labelだけでは表現できない補助説明だけを、対象へbindしたTooltipに入れる。
|
||||
- pointer hoverとkeyboard focusの両方で開く。
|
||||
- triggerとTooltipを`aria-describedby`で関連付ける。
|
||||
- hoverはdelay後、focusは直ちに表示する。
|
||||
- `Escape`で閉じ、triggerからfocusを移動しない。
|
||||
- 複数paragraph、form、link、buttonを入れない。
|
||||
- error、permission、validation constraint、不可逆操作の結果、current stateをTooltipへ入れない。
|
||||
- touch環境ではTooltipだけを説明への到達手段にしない。
|
||||
|
||||
### Generic component patterns
|
||||
|
||||
- **Form field**: label、control、constraintまたはhelp、field errorの順に配置する。
|
||||
- **Key-value**: 一つのresourceの属性には`dl`を使う。
|
||||
|
||||
Design-labではcomponent名と実際のsampleだけを表示する。規則とrationaleをUIへ書かない。
|
||||
@@ -1,156 +0,0 @@
|
||||
# Workspace Web Product UX
|
||||
|
||||
この文書は、Workspace Webで扱うresource、navigationのinformation
|
||||
architecture、resourceごとの主要taskを定義する。見せ方の共通文法は[`design-language.md`](design-language.md)、application
|
||||
shellとSidebar
|
||||
slotは[`application-architecture.md`](application-architecture.md)を参照する。
|
||||
|
||||
## Product position
|
||||
|
||||
Workspace
|
||||
Webは、Workspace内の権威ある状態を確認し、注意が必要な箇所を判断し、一度に一つの操作を行うための作業面である。Marketing
|
||||
dashboard、analytics画面、Backend DTOのraw viewerにはしない。
|
||||
|
||||
基本的な操作の流れは次とする。
|
||||
|
||||
```text
|
||||
scopeを選ぶ
|
||||
→ resourceを選ぶ
|
||||
→ current stateを確認する
|
||||
→ 次の有効なactionを行う
|
||||
→ 結果を確認する
|
||||
```
|
||||
|
||||
## Resource
|
||||
|
||||
主要resourceは次のとおり。
|
||||
|
||||
- Workspace
|
||||
- Ticket
|
||||
- Objective
|
||||
- Merge Request
|
||||
- Memory
|
||||
- Worker
|
||||
- Workdir
|
||||
- Runtime
|
||||
- Repository
|
||||
|
||||
通常の表示とURLにはcanonical resource keyを使う。内部UUIDをlabelやfallback
|
||||
linkとして露出しない。
|
||||
|
||||
## Navigation IA
|
||||
|
||||
### Global
|
||||
|
||||
Workspaceを選ぶ前のscopeを扱う。
|
||||
|
||||
- Workspace catalog
|
||||
- Account
|
||||
- Device Login
|
||||
- Workspace作成
|
||||
|
||||
### Workspace
|
||||
|
||||
一つのWorkspace内で日常的に扱うresourceを置く。
|
||||
|
||||
1. Tickets
|
||||
2. Objectives
|
||||
3. Merge Requests
|
||||
4. Memory
|
||||
- Subjects
|
||||
- Surface
|
||||
- Committed Memory
|
||||
- Changes
|
||||
- Sources
|
||||
5. Workers
|
||||
|
||||
### Settings
|
||||
|
||||
Workspaceの管理と構成を扱う。
|
||||
|
||||
- Runtimes
|
||||
- Configuration Sources
|
||||
- Repositories
|
||||
- Repository Access
|
||||
- Profile Sources
|
||||
- Workspace Identity
|
||||
|
||||
`Runtimes`、`Repositories`、`Repository Access`をWorkspace primary
|
||||
navigationへ混ぜない。permissionにより利用できないSettings itemは表示しない。
|
||||
|
||||
## Page model
|
||||
|
||||
各routeは、主要な目的を一つだけ持つ。その目的は「Ticketを選ぶ」「このWorkerを確認する」「Repository
|
||||
accessを設定する」のように、動詞と対象を一つずつ使って表現できなければならない。
|
||||
|
||||
Workspace pageは、次のいずれかを基本形とする。
|
||||
|
||||
1. **一覧またはboard** — resourceを探し、注意が必要な項目を見つける。
|
||||
2. **詳細** — 一つのresourceを理解し、現在実行できる次の操作を行う。
|
||||
3. **formまたはeditor** — 範囲の明確な設定変更を行う。
|
||||
4. **Console** — 一つのWorkerを操作しながら、履歴とcurrent controlを確認する。
|
||||
|
||||
同じ目的を支える場合に限り、一つのrouteで複数の基本形を組み合わせてよい。
|
||||
|
||||
## Product pattern
|
||||
|
||||
### Tickets
|
||||
|
||||
- boardを一つの横方向の作業面として扱う。
|
||||
- laneはworkflow stateを表し、隣接laneとの関係を維持する。
|
||||
- Ticketはlane内でDesign Languageの`Resource row` patternを使う。
|
||||
- Ticket key、title、優先判断を変えるmetadataだけを表示する。
|
||||
- blockerとattentionはtextでも示す。
|
||||
- narrow viewportでは、bounded horizontal scrollでlane比較を維持する。
|
||||
|
||||
### Resource index
|
||||
|
||||
- 同じfieldをresource間で比較する場合、flat listまたはtableを使う。
|
||||
- 人が読むnameとcanonical keyを最初のcolumnに置く。
|
||||
- columnは判断に必要な値だけに絞る。
|
||||
- provider detail、変更ID、digestはdetailまたはtechnical disclosureへ移す。
|
||||
|
||||
### Resource detail
|
||||
|
||||
- identity、current state、attentionを最初に置く。
|
||||
- narrativeまたはhistoryをprimary領域に置く。
|
||||
- relation、target、review、workflowが別のauthorityを持つ場合、それぞれを独立したsectionにする。
|
||||
- raw metadataはtechnical disclosureへ置く。
|
||||
|
||||
### Settingsとform
|
||||
|
||||
- 一つのSettings routeは一つの設定関心事を所有する。
|
||||
- edit actionの前または同時に、現在有効な値を示す。
|
||||
- 一つの判断に必要なfieldをgroup化する。
|
||||
- narrow viewportでは一列にする。
|
||||
- form内でfilled actionにするのはsave actionだけとする。
|
||||
|
||||
### Memory
|
||||
|
||||
- Memoryの入口はWorkspace全体のlegacy `Document` / `Staging`ではなく、明示的に選択したsubjectとする。
|
||||
- subject detailではcurrent Workerをkeyed-singleton projectionとして表示し、historical Worker/Session attributionをcurrent authorityとして扱わない。
|
||||
- `Surface`はresident contextのcurrent stateを表示する。`ready`、`ready-empty`、`ungenerated`、`stale`、`failed`を区別し、空表示やrequest failureへまとめない。
|
||||
- `Committed Memory`はcurrent confirmed Memoryの一覧とdetailを持つ。変更履歴はappend-only viewとして分離し、過去の変更内容をcurrentへ暗黙fallbackしない。
|
||||
- `Sources`は候補、resolution、exact `{memory_id, change_id}` refs、Host-recorded Session attribution、閲覧可能なSession sourceをたどるviewとする。source IDをpermissionとして扱わず、現在のWorkspace/subject authorizationを毎回適用する。
|
||||
- legacy `/memory` の`Document` / `Staging` viewはdeprecated compatibility surfaceとして明示し、新しいsubject viewへ同じinputを別の意味で転送しない。
|
||||
- Markdown本文とdetail presentationはT-661の共有rendererを再利用する。Memory route独自のrenderer、application shell、Header、Sidebarを再実装せず、既存shellのmain contentとnested navigationを保つ。
|
||||
|
||||
### Worker Console
|
||||
|
||||
- transcriptをprimary surfaceとする。
|
||||
- direct SubWorkerを表示している場合も、Composerとrun
|
||||
controlは親Workerへbindしたままにする。
|
||||
- OverviewとNormalはpresentationだけを変え、authorityを変えない。
|
||||
- command outputはterminalに近いcompactな表示とし、prose messageから分離する。
|
||||
- live stateは権威あるWorker snapshotから導出する。
|
||||
- connection stateやtransient eventでcurrent stateを置き換えない。
|
||||
- hidden reasoningとraw system promptはdebug modeでも表示しない。
|
||||
|
||||
## Stateとpermission
|
||||
|
||||
- 存在しない、閲覧できない、読み込みに失敗したWorkspaceを別の状態として扱う。
|
||||
- 別のWorkspaceへ暗黙に切り替えない。
|
||||
- owner-only mutation controlをnon-ownerへ表示しない。
|
||||
- read-onlyの場合は、有用なread viewを残す。
|
||||
- Workerのdomain stateとWebSocket connection stateを混同しない。
|
||||
- Mergeなど不可逆または重要なoperationは、対象と結果を明示してから実行する。
|
||||
@@ -1,135 +0,0 @@
|
||||
# Subject / Memory information audit (T-692)
|
||||
|
||||
This document records T-692's UI decisions and validation at the commits cited below. Its counter values describe that historical implementation, not the current API. Obsolete UI labels are paraphrased by purpose below, not quoted as current copy. Current Memory uses immutable `change_id` references, `memory_fingerprint` and `built_from_memory_fingerprint`; see [the current store contract](../../design/subjektiv-store.md). Historical validation results are not new executions.
|
||||
|
||||
## Decision and scope
|
||||
|
||||
The previous Subjects index exposed a committed-Memory update counter alongside identity, state and
|
||||
update time; Subject detail led with technical metadata and raw surface states.
|
||||
These numbers require implementation knowledge before they help a user choose a
|
||||
Subject or understand what is available. The revised hierarchy starts with
|
||||
identity, connection, committed records and generated-context availability.
|
||||
|
||||
This is a presentation change, not a change to storage, freshness comparisons,
|
||||
permissions, generation, or Worker history. T-688's ordinary Worker launch and
|
||||
T-689's independent Subject creation remain the actual operation paths. T-693
|
||||
owns editable user-managed behavior: that content must remain distinct from this
|
||||
page's context generated from committed Memories. A successful read or a current
|
||||
surface does not attest what is already in any running Worker's history.
|
||||
|
||||
## Field classification and before/after priorities
|
||||
|
||||
| Information | Classification and reason | Presentation decision |
|
||||
| --- | --- | --- |
|
||||
| Subject role and ID | Normal identification. Similar or identical roles need a stable identifier for selection and comparison. | Keep role as heading and the complete wrapping ID visible in index and detail. |
|
||||
| Subject active/retired state | Normal operation decision: whether a new Worker connection can use the Subject. | Replace raw `active` with `Available`; keep `Retired`. Detail explains connection eligibility, not an assertion that a Worker is running. |
|
||||
| Current Worker | Normal connection decision, derived from the existing Backend singleton projection. | Promote `Connected` / `Not connected` and display name. Do not infer ownership from historical store counter or claim all Workers received current Memory. Worker start remains the ordinary launch form. |
|
||||
| Committed-Memory presence | Normal reading decision, independent from surface generation or candidates. | Show `Available` / `None` only on the successful first bounded page. On later pages say `N on this page`; errors say `Unavailable`. Never infer counts from an update counter or scan all pages. |
|
||||
| List counts | Normal navigation context, not a store-wide statistic. | Label `N shown` and `more available`, preserving existing bounded cursor pagination. |
|
||||
| Resident availability | Normal context decision. A missing surface is not missing committed Memory. | `Ready to use`, `Ready, no context`, `Not generated`, `Needs refresh`, `Generation failed`, and request `Unavailable` are distinct. These describe the current generated store artifact, not content truth or Worker-history propagation. |
|
||||
| Resident body and generated time | Normal content/read freshness context. | Keep the shared Markdown renderer, generated date and exact snapshot reference count. Ready-empty explains that a valid snapshot has no body; stale/failed do not display a partial or old snapshot. |
|
||||
| Historical Subject store counter | Diagnostic only: internal committed-Memory change number, not record count, schema version or quality score. | Remove it from the index's normal columns. Retain the exact value under detail's `Technical details`, with its meaning explained. Backend comparisons are untouched. |
|
||||
| Subject update time | Secondary metadata; not a context-injection or generation completion timestamp. | Label `Last changed`; on detail put it with Subject diagnostics rather than competing with the availability summary. |
|
||||
| Snapshot ID and historical built-from counter | Diagnostic correlation, distinct from individual Memory history entries. | Retain under `Surface sources and diagnostics`, labelled the historical generated-from counter label and explained. |
|
||||
| Surface Memory references | Detailed audit/reachability. | Preserve reference IDs, immutable history references and Memory links in the disclosure. |
|
||||
| Memory claim, kind, lifecycle state, excerpt and body | Normal content decision. Active, resolved and retracted are not interchangeable. | Retain list scanning and body reading. Keep the Markdown renderer and current/historical distinction. |
|
||||
| Individual Memory history entries | Detailed content comparison, also useful for identifying a selected version. | The historical UI labelled each Memory history entry separately from Subject counters. Preserve immutable history, selected history-entry links and history pagination. |
|
||||
| Candidate provenance, evidence, origin, source refs and derivations | Detailed audit, required to understand why a record exists. | Retain IDs, ranges, summaries, excerpts, origins and derived-history-entry links. Counts say `shown` except where the API provides exact per-candidate totals. Preserve body and evidence continuation links. |
|
||||
| Raw field names / duplicated general update-counter terminology | Unnecessary in the normal hierarchy; multiple unrelated counters are misleading. | Replace bare counter labels and raw surface enums with purpose-specific labels. Do not delete API fields, stored information, diagnostics or their detailed access. |
|
||||
|
||||
No diagnostic datum was removed from Subject detail, surface detail or Memory
|
||||
provenance/history. The index no longer shows a historical store counter, but the exact
|
||||
value remains one click away in Subject detail. No invented regeneration,
|
||||
editing or recovery action was added; `Needs refresh` does not mean an update job
|
||||
is running. Creation still creates only a Subject, and selection still uses the
|
||||
existing ordinary launch contract.
|
||||
|
||||
## Candidate-only verification
|
||||
|
||||
Candidates are not committed records and are not an input to this page. The
|
||||
Subject loader performs just three bounded reads: Subject, resident surface and
|
||||
`/memories?limit=100[&cursor=...]`. It does not read or count staging records.
|
||||
|
||||
The existing real-store regression
|
||||
`subjektiv::tests::candidate_decisions_reject_conflicts_and_roll_back_partial_writes`
|
||||
stages a candidate and attempts an invalid apply. It asserts the candidate has no
|
||||
resolution and the committed Memory list remains empty. The component regression
|
||||
`candidate-only Subjects show no committed Memories, not an inferred candidate count`
|
||||
uses that read projection (historical store counter 0, ungenerated surface, empty successful
|
||||
committed list) and checks `None`, `No committed Memories yet.`, `Not connected`
|
||||
and `Not generated`, with no resident body. Thus a staged candidate does not turn
|
||||
into a committed-Memory count or a claim that context has been generated.
|
||||
|
||||
The store test proves the persistence boundary; the component test proves the
|
||||
rendering of its public projection. These are separate boundary tests, **not** a
|
||||
live browser-to-Backend candidate-creation E2E. The existing `ungenerated` capture
|
||||
represents the same visible projection, but does not itself stage a candidate.
|
||||
|
||||
## Visual review and validation evidence
|
||||
|
||||
The restored implementation is in `fbb09e65` and `4cf6c130`; this report/test
|
||||
supplement does not change rendered markup, styling, copy or data contracts.
|
||||
|
||||
- Scenarios: `tools/web-ux/scenarios/memory-subjects-{light,dark}.json`.
|
||||
- Before: `target/web-ux/t-692-before-{light,dark}` at `cc979874`.
|
||||
- After: `target/web-ux/t-692-final2-{light,dark}` at clean `4cf6c130`.
|
||||
- Comparisons: `target/web-ux/t-692-final2-{light,dark}-comparison`.
|
||||
- Browser interactions: `target/web-ux/t-692-browser-interactions`.
|
||||
- Persona: synthetic Workspace fixture; permitted creation and intentional
|
||||
permission-rejection responses. No real account or private store data used.
|
||||
- Viewports: 1440, 768, 390 and 320px; light and dark themes.
|
||||
- States: connected/unconnected, active/retired, successful empty lists, ready
|
||||
long Markdown, ready-empty, ungenerated, stale, failed, unavailable HTTP503,
|
||||
create form and create permission error; expanded technical disclosures.
|
||||
- The takeover implementer personally inspected individual before/after images
|
||||
for index at 768px, representative detail at desktop/mobile and Memory detail,
|
||||
then ready-empty mobile, ungenerated narrow, stale desktop, failed mobile,
|
||||
endpoint error at 320px, mobile surface sources, compact Subject diagnostics
|
||||
and mobile permission error. Oversized contact sheets were rejected by the
|
||||
image provider; individual viewport PNGs were inspected instead.
|
||||
- Findings/result: primary state groups replace counters without losing IDs or
|
||||
document access; long IDs wrap, status is textual rather than color-only,
|
||||
mobile groups stack, diagnostics remain readable, and error state regions stay
|
||||
separate. No new visual defect identified. **Pass for the audited scope.**
|
||||
- Final bundles contain 64 captures each. `completed-with-errors` is expected:
|
||||
intentional creation HTTP403, endpoint HTTP503/associated aborted requests,
|
||||
and the deliberately failed surface's alert are retained as evidence. Healthy
|
||||
capture states have empty error arrays; this is not a blanket claim that all
|
||||
captures were error-free. Review-context diagnostics are empty.
|
||||
- The focused production-shell browser test proves main-owned vertical scrolling
|
||||
with wheel/keyboard/touch, 320px/mobile shell behavior, no page-wide overflow,
|
||||
local table/code scroll, Markdown safety, creation/launch separation, bounded
|
||||
pagination and Memory/source/history-entry reachability.
|
||||
|
||||
Independent review at source `4cf6c130` ran root `cargo check`,
|
||||
`cargo fmt --all -- --check`, diff hygiene, Web check (0 errors/warnings), 12
|
||||
Memory API tests, 452 full Web unit tests, 134 component tests (8 Memory tests),
|
||||
production build, the focused production-shell browser test (1), and Web-UX unit
|
||||
tests (16), all passing.
|
||||
|
||||
The takeover implementer then validated this report/test supplement with:
|
||||
|
||||
- `cargo test -p yoi-workspace-server --lib candidate_decisions_reject_conflicts_and_roll_back_partial_writes`: 1 passed.
|
||||
- Root `cargo check`, `cargo fmt --all -- --check`, and `git diff --check HEAD`: passed.
|
||||
- Targeted Memory component tests: 9 passed, including the added candidate-only projection test.
|
||||
- Web `deno task check`: 0 errors/warnings; `deno task test`: 452 passed;
|
||||
`deno task test:component`: 135 passed.
|
||||
- Scoped `deno fmt --check` on the changed TypeScript test: passed.
|
||||
- JSON audit of both final2 bundles: 64 captures each, exact clean source
|
||||
`4cf6c130`, and no errors outside the deliberate permission/error/failed routes.
|
||||
|
||||
The supplement changes only a document and a test, so it does not require new
|
||||
rendered-UI captures. Rereview records and the final approved Ticket handoff link
|
||||
this report to the new exact source.
|
||||
|
||||
Known non-blocking validation diagnostics: component runs emitted incidental
|
||||
localhost:3000 connection-refused messages while passing; the production build
|
||||
warned about a large chunk. A broader Web-UX typecheck fails in unchanged
|
||||
`tools/web-ux/src/processes.ts:44` on a `TextDecoderStream` generic incompatibility;
|
||||
this report does not claim that broad check passed.
|
||||
|
||||
No live-Backend browser interactions, real Worker model-request propagation,
|
||||
regeneration, or server/runtime process E2E were performed. No Rust production
|
||||
crate changed in T-692; the supplemental store test exercises an existing
|
||||
contract without changing that contract. Backend counters, comparison logic,
|
||||
storage schema and feature behavior remain intact.
|
||||
@@ -1,272 +1,32 @@
|
||||
# Web visual review
|
||||
# Web UI変更の目視確認
|
||||
|
||||
この文書は、Web UIを変更する実装者が完了前に行うvisual
|
||||
reviewの必須手順を定義する。Visual reviewは任意のpolish工程ではなく、type
|
||||
check、linter、testと並ぶvalidationである。
|
||||
描画結果が変わる変更は、実装者自身が変更前後を目視する。type check、linter、testと別の検証であり、後段Reviewerや利用者に最初の発見を委ねない。画像生成やHTTP成功だけでは確認済みにならない。
|
||||
|
||||
[`design-language.md`](design-language.md)はWorkspace
|
||||
Webが満たす視覚とinteractionの共通規則を定義する。Product固有の構成は[`product-ux.md`](product-ux.md)を参照する。[`tools/web-ux/README.md`](../../../tools/web-ux/README.md)はcapture
|
||||
toolの操作方法を定義する。この文書は、誰が、いつ、何を目視し、どの証拠を残さなければ実装完了とみなせないかを定義する。
|
||||
## 対象と条件
|
||||
|
||||
## 実装者の責任
|
||||
page、layout、navigation、componentのmarkup・style、色・書体・余白、文言・状態表示、可変幅、keyboard操作、表示に影響するAPI projectionを変えた場合に行う。描画に影響しない文書・型・Backend変更だけなら省略できるが、影響しない理由を検証記録に残す。
|
||||
|
||||
Visual
|
||||
reviewは、後段のReviewerやユーザーへ最初の発見を委ねない。UIを変更した実装者自身が、同じ変更の中で次を行う。
|
||||
変更箇所に関係する条件を選び、都合のよい一画面だけで済ませない。
|
||||
|
||||
1. 変更前をcaptureする。
|
||||
2. 変更後を同じ条件でcaptureする。
|
||||
3. screenshotとbrowser evidenceを自分で確認する。
|
||||
4. 発見した問題を修正する。
|
||||
5. 修正後を再captureして確認する。
|
||||
6. 変更と無関係な既存問題は、根拠を付けて分離する。
|
||||
- 権限やデータが表示を変える場合は、owner、non-owner、anonymous、read-onlyなど該当する利用主体を分ける。
|
||||
- 幅はdesktop `1440px`、狭い幅`768px`、mobile `390px`を基準とする。`320px`対応やbreakpoint付近が変更対象なら追加し、Sidebarなどを除いた実内容幅も確認する。
|
||||
- 色・背景・線・focus・状態・code・terminalを変える場合はlightとdarkを確認する。
|
||||
- 通常、空、読込み中、失敗、権限不足、長文・長い識別子、少数・多数の一覧など、該当するデータ状態を用意する。
|
||||
|
||||
Agentが実装者の場合、そのAgent自身が`ViewImage`または同等のVLM入力で実画面を確認する。captureを生成しただけ、別のAgentへ画像を渡しただけ、HTTP
|
||||
200を確認しただけでは完了しない。
|
||||
## 実施と確認項目
|
||||
|
||||
## 適用範囲
|
||||
1. route、利用主体、幅、theme、データ状態、撮影点を固定する。既存scenarioを再利用し、不足分は同じ変更で更新する。
|
||||
2. 変更前を撮影して画像を開き、既存問題と変更対象を把握する。
|
||||
3. [Design Language](../../principle/design-language.md)と[UX設計](../../principle/ux-design.md)に沿って実装する。撮影専用のCSS・shellや、本番と異なる権限判定で見栄えを整えない。
|
||||
4. 同条件で変更後を撮影し、実装者自身が画像と`review-context.json`を確認する。Agentも`ViewImage`などで実画像を見る。
|
||||
5. 発見した新規問題を修正し、再撮影して確認する。既存の無関係な問題は根拠を付けて分離する。
|
||||
|
||||
次の変更ではvisual reviewを必須とする。
|
||||
画像では、情報のまとまり、区切り線の役割、余白の大小、重複見出し、文字の強弱、折返し、欠落、overflow、主要操作の位置を確認する。DOM・表示・keyboardの順、focusの維持、色以外の状態表現、必須情報への到達も確認する。画素差の大小だけで合否を決めない。
|
||||
|
||||
- page、layout、navigation、Sidebar、Header、Console、dialog
|
||||
- componentのmarkupまたはstyle
|
||||
- color、typography、spacing、border、radius、shadow、theme token
|
||||
- copy、label、status、empty/loading/error/permission表示
|
||||
- responsive breakpoint、container、overflow、scroll
|
||||
- 表示dataの追加、削除、並び替え、progressive disclosure
|
||||
- icon、focus、keyboard interaction、motion
|
||||
- UIへ影響するgenerated typeまたはAPI projection
|
||||
`review-context.json`では、document status、可視エラー、console・page・requestエラー、accessibility snapshot、撮影点と画像hashを確認する。HTTP 200でも画面が権限エラーなら成功ではない。意図的な障害fixtureは予期したエラーと予期しないエラーを分けて判定する。
|
||||
|
||||
型、Backend、CLI、文書だけの変更でrendered Web
|
||||
UIが変わらない場合は省略できる。省略する場合は、UIへ影響しない理由をvalidation
|
||||
evidenceへ一文で残す。
|
||||
## 証拠と合否
|
||||
|
||||
## 必須の確認条件
|
||||
引継ぎにはscenario、変更前後のartifact、source、確認した条件、修正した問題、根拠付きの既存問題、最終の`pass | fail`を残す。必要な条件を自分で確認し、新規問題を修正し、意図しない描画回帰がない場合だけ合格とする。自動テストと目視確認のどちらも、他方の代替にはしない。
|
||||
|
||||
変更したsurfaceに関係する条件だけを選ぶが、都合のよい一画面だけに限定しない。
|
||||
|
||||
### Persona
|
||||
|
||||
権限やdataが表示を変える場合は、該当するpersonaを分ける。
|
||||
|
||||
- owner
|
||||
- non-owner
|
||||
- anonymous
|
||||
- read-onlyまたは操作権限なし
|
||||
|
||||
owner表示だけでpermission-aware UIを承認しない。
|
||||
|
||||
### Viewport
|
||||
|
||||
最低限、次を確認する。
|
||||
|
||||
- desktop: `1440px`幅を基準
|
||||
- narrow: Sidebarとmainが競合する幅。現在は`768px`を基準
|
||||
- mobile: `390px`幅を基準
|
||||
|
||||
`320px`対応、table、long form、Console、Sidebar
|
||||
foldなどが変更対象なら、その境界も追加する。media
|
||||
queryのviewport幅だけでなく、Sidebarやpanelを差し引いた実際のcontent幅を確認する。
|
||||
|
||||
### Theme
|
||||
|
||||
color、border、background、focus、status、code、terminalを変更した場合はlightとdarkの両方を確認する。片方のthemeで読めることを、もう片方のcontrastの証拠にしない。
|
||||
|
||||
### Data state
|
||||
|
||||
該当するstateを明示的に用意する。
|
||||
|
||||
- representative data
|
||||
- empty
|
||||
- loading
|
||||
- error
|
||||
- permission deniedまたはread-only
|
||||
- long title、long key、long error、複数行content
|
||||
- collectionの最小件数と、実際に起こりうる多い件数
|
||||
|
||||
happy pathだけでcomponentを承認しない。
|
||||
|
||||
## 目視確認の観点
|
||||
|
||||
### 情報のまとまり
|
||||
|
||||
- 同じ判断に使う情報がproximity、alignment、typographyによって一つのgroupに見えるか。
|
||||
- 別の意味を持つ情報が、十分な距離または一つの明確なboundaryで分離されているか。
|
||||
- 親子、peer、metadata、actionの関係が、DOMを読まなくても判別できるか。
|
||||
- card、background、border、shadow、余白を重ねて同じgroupingを重複表現していないか。
|
||||
- page title、Header、breadcrumb、section
|
||||
heading、説明文が同じ意味を繰り返していないか。
|
||||
|
||||
### Separatorとborder
|
||||
|
||||
画面上のすべての線について、何と何を区切る線か説明できなければならない。
|
||||
|
||||
- Headerの終端、peer row間、section開始、table
|
||||
cellなど、線の役割が一つに定まっているか。
|
||||
- 近接した二本の線が同じboundaryを重複表現していないか。
|
||||
- 線の上下の余白から、その線が前後どちらのgroupに属するか分かるか。
|
||||
- すべてのsectionへ機械的に同じ線を置き、hierarchyを平坦化していないか。
|
||||
- borderがなくてもspacingだけで十分な箇所へ線を追加していないか。
|
||||
|
||||
### Spacingとdensity
|
||||
|
||||
- 余白がtoken scaleに沿い、近い関係ほど狭く、別groupほど広くなっているか。
|
||||
- labelとvalue、headingとcontent、rowとrow、sectionとsectionの間に一貫した大小関係があるか。
|
||||
- 線の前後へ同程度の大きな余白を置き、boundaryの所属を曖昧にしていないか。
|
||||
- 初期viewportにprimary contentまたは主要操作が存在するか。
|
||||
- 空きすぎた領域が情報不足やhierarchyの弱さを隠していないか。
|
||||
- 密度を上げるためにfont、touch target、line heightを過度に縮めていないか。
|
||||
|
||||
### Wrapping、overflow、可変長content
|
||||
|
||||
- 実際に起こりうる最長のlabel、title、key、ref、error、翻訳で確認したか。
|
||||
- 一行を前提とするcontrolが意図せず二行にならないか。
|
||||
- button labelが折り返されたとき、row heightとalignmentが壊れないか。
|
||||
- title、metadata、code、URLが隣接actionを押し出さないか。
|
||||
- truncateする場合、完全な値へaccessできるか。
|
||||
- horizontal
|
||||
scrollはtable、board、terminalなど、その意味を所有する領域だけに閉じているか。
|
||||
- page全体へhorizontal overflowが発生していないか。
|
||||
- `overflow-wrap`だけで問題を隠さず、可読性と比較可能性を維持しているか。
|
||||
|
||||
### Responsive layout
|
||||
|
||||
- DOM順、視覚順、keyboard順が一致しているか。
|
||||
- Sidebar、Header、primary contentの順序がmobileでも目的に合うか。
|
||||
- Sidebarだけで初期viewportを占有していないか。
|
||||
- breakpoint直前と直後の両方で、content幅とcontrol配置が成立するか。
|
||||
- viewport
|
||||
queryだけでなく、containerの実幅に応じて一列化またはscrollを選べているか。
|
||||
- desktopの比較関係を、理由なくmobile cardへ変換していないか。
|
||||
|
||||
### Typographyとcopy
|
||||
|
||||
- route titleが画面上で一度だけ表示されているか。
|
||||
- page purpose、componentの存在理由、設計意図を説明するmeta
|
||||
copyが残っていないか。
|
||||
- proseが判断、warning、constraint、permission、recoveryのいずれかに実際に必要か。
|
||||
- heading level、font size、weight、colorが同じhierarchyで揃っているか。
|
||||
- metadataがbodyより強く見えていないか。
|
||||
- uppercase、letter spacing、monospaceを装飾目的で多用していないか。
|
||||
|
||||
### State、permission、action
|
||||
|
||||
- loading、empty、error、permission denied、unavailableが見分けられるか。
|
||||
- statusがcolorだけに依存していないか。
|
||||
- 利用できないowner-only actionをdisabledで並べるのではなく、page
|
||||
compositionから除外できているか。
|
||||
- filled primary actionが同じscopeに複数ないか。
|
||||
- destructive actionが通常のprimary pathと誤認されないか。
|
||||
- errorとrecovery actionが、失敗したsurfaceの近くにあるか。
|
||||
|
||||
### Interactionとaccessibility
|
||||
|
||||
- keyboard focusが全controlで見えるか。
|
||||
- focus順が画面の作業順と一致するか。
|
||||
- fold、disclosure、dialog、menuを操作した後にfocusが失われないか。
|
||||
- hoverでしか得られない必須情報がないか。
|
||||
- scroll region、icon-only control、status markerにaccessible
|
||||
nameまたはtextがあるか。
|
||||
- reduced motionで意味が失われないか。
|
||||
|
||||
## 実行手順
|
||||
|
||||
### 1. Scenarioを決める
|
||||
|
||||
変更対象route、persona、viewport、theme、data state、capture
|
||||
pointを列挙する。既存scenarioが目的を満たす場合は再利用し、満たさない場合は同じ変更内で追加または更新する。
|
||||
|
||||
### 2. 変更前をcaptureする
|
||||
|
||||
`tools/web-ux`を使い、変更前のsourceとscenarioを固定する。出力はrepositoryのproduction
|
||||
sourceへ混ぜず、`target/web-ux`などの開発artifact領域へ置く。
|
||||
|
||||
### 3. 変更前を目視する
|
||||
|
||||
既存問題も含め、変更対象付近のgrouping、separator、spacing、wrapping、responsive、stateを確認する。変更前を見ずに、変更後の印象だけで改善を主張しない。
|
||||
|
||||
### 4. 実装する
|
||||
|
||||
発見した問題と、適用するUX規則を対応付けて修正する。screenshotだけを整えるfixture固有hackや、productionと異なるshell、CSS、data
|
||||
authorityを作らない。
|
||||
|
||||
### 5. 同条件で再captureする
|
||||
|
||||
persona、route、viewport、theme、data
|
||||
stateを揃える。変更後だけ別の好条件へ変えない。
|
||||
|
||||
### 6. Screenshotとreview contextを確認する
|
||||
|
||||
実装者自身が画像を開き、`review-context.json`も読む。次を確認する。
|
||||
|
||||
- document status
|
||||
- visible UI error
|
||||
- console error
|
||||
- page error
|
||||
- failed request
|
||||
- accessibility snapshot
|
||||
- screenshot hashとcapture point
|
||||
|
||||
HTTP 200でも画面に`401 Unauthorized`などが表示されていれば失敗とする。
|
||||
|
||||
### 7. Compareする
|
||||
|
||||
before/afterを比較し、差分が意図した領域に限定されているか確認する。pixel
|
||||
differenceの大小だけで合否を決めない。意図しない移動、折返し、欠落、色変化を目視する。
|
||||
|
||||
### 8. Testとevidenceを揃える
|
||||
|
||||
source test、component test、E2E、type checkを実行し、visual
|
||||
evidenceと一緒に記録する。test成功はvisual reviewの代替ではなく、visual
|
||||
review成功もtestの代替ではない。
|
||||
|
||||
## 合格条件
|
||||
|
||||
次をすべて満たした場合だけvisual reviewを合格とする。
|
||||
|
||||
- 実装者自身がbefore/afterを目視した。
|
||||
- 必要なpersona、viewport、theme、data stateを確認した。
|
||||
- grouping、separator、spacing、wrapping、responsiveを確認した。
|
||||
- visible、console、page、request errorが解決または明確にdispositionされた。
|
||||
- 発見した新規問題を修正し、修正後を再captureした。
|
||||
- 意図しないvisual regressionがない。
|
||||
- artifact path、scenario、確認結果をhandoffへ記録した。
|
||||
|
||||
次は不合格である。
|
||||
|
||||
- capture commandが成功しただけ。
|
||||
- screenshotを生成したが開いていない。
|
||||
- desktopだけ、ownerだけ、happy pathだけを見た。
|
||||
- 後段Reviewerまたはユーザーが目視する前提でhandoffした。
|
||||
- 「好みの問題」として、説明できないseparator、spacing、overflowを未確認のまま残した。
|
||||
- testまたはlinterが成功したため、visual reviewを省略した。
|
||||
|
||||
## Evidenceの記録
|
||||
|
||||
handoffには最低限、次を記録する。
|
||||
|
||||
```text
|
||||
Visual review
|
||||
- Scenario: <scenario path>
|
||||
- Before: <run id or artifact path>
|
||||
- After: <run id or artifact path>
|
||||
- Personas: <list>
|
||||
- Viewports: <list>
|
||||
- Themes: <list>
|
||||
- Data states: <list>
|
||||
- Findings fixed: <bounded list>
|
||||
- Known issues: <bounded list with disposition>
|
||||
- Result: pass | fail
|
||||
```
|
||||
|
||||
画像をTicketやGitへ大量にcommitしない。artifact pathとsource
|
||||
commitを結び付け、必要なreviewerが同じ条件を再現できるようにする。認証profile、cookie、token、secret、private
|
||||
response bodyをartifactやhandoffへ含めない。
|
||||
|
||||
## Toolの位置付け
|
||||
|
||||
`tools/web-ux`はbrowser起動、scenario再現、capture、review
|
||||
context、compareを提供する。Toolは視覚的な良否を自動決定しない。
|
||||
|
||||
Linterが構文規則を検査し、testが特定のbehaviorを検査するのと同様に、visual
|
||||
reviewはrendered
|
||||
resultの関係性を検査する。三者は補完関係であり、どれか一つで他を代替しない。
|
||||
成果物は`target/web-ux`などの開発artifact領域へ置き、画像を大量にGitやTicketへ保存しない。認証profile、cookie、token、秘密情報、非公開response bodyを含めない。確認支援ツールは[tools/web-ux](../../../tools/web-ux/README.md)が所有し、合否判断は実装者が行う。
|
||||
|
||||
Reference in New Issue
Block a user