Forge
markdowndeeb25a2
1<!-- English translation of adr/0037-pfd-surface-invariants-and-roslyn-enforcement.md. Canonical Russian: ../../adr/0037-pfd-surface-invariants-and-roslyn-enforcement.md -->
2
3# ADR 0037: PFD — surface invariants and Roslyn enforcement (weight, input lock, channels)
4
5**Status:** Proposed
6**Date:** 2026-04-12
7**Updated:** 2026-04-16 — [naming canon](#adr0037-naming) for strict surface: `[PfdStrict]`, `PfdStrictControl`. Details — [§ History](#adr0037-history).
8
9## Related ADRs
10
11| ADR | Role |
12|-----|------|
13| [0021](0021-pfd-mfd-cockpit-attention-model.md) | PFD zone in attention model |
14| [0036](0036-cds-channel-compositor-surface-pipeline.md) | channel → CDS → compositor → surface |
15| [0025](0025-sdk-attention-zones-and-capabilities.md) | capabilities and zones |
16| [0039](0039-workspace-navigation-affordances.md) | navigation affordances in attention zone |
17
18## Summary
19
20- **PFD strict surface:** weight/input lock invariants; Roslyn analyzers.
21- Canon **`[PfdStrict]`** / `PfdStrictControl` — attention zone geography vs strict surface ([0021](0021-pfd-mfd-cockpit-attention-model.md#adr0037-zone-vs-surface)).
22
23### Outside ADR
24
25| Document | Role |
26|----------|------|
27| [`CascadeIDE.ArchitectureAnalyzers/README.md`](../CascadeIDE.ArchitectureAnalyzers/README.md) | CASCOPE*; extension — per this ADR |
28
29---
30## Context
31
32In the aviation metaphor **PFD** is the primary “instrument”: dense, authoritative context picture without tab hunting ([0021](0021-pfd-mfd-cockpit-attention-model.md)). At **pure code** level Roslyn does **not** know whether a widget is “light”: weight is product policy, not an IL property.
33
34To **formalize** PFD discipline in code we need **explicit contracts** (attributes, base types, narrow channel subscription interfaces). Then analyzers become **invariant guards**, not heuristics on class names.
35
36Already fixed: layer boundaries **channel / CDS / compositor** without Avalonia in `Cockpit/Channels`, `Cds`, `Composition` ([0036](0036-cds-channel-compositor-surface-pipeline.md), CASCOPE001/002). This ADR adds a layer for components **declared as strict PFD surface** (see below: this is **not** all PFD region geography).
37
38<a id="adr0037-zone-vs-surface"></a>
39
40## Attention zone vs strict surface (0021 vs 0037)
41
42**Two axes that must not be mixed:**
43
44| Axis | What it is | Where fixed |
45|------|------------|-------------|
46| **Attention zone (screen geography)** | Which **region** is the gaze anchor: forward, **PFD**, MFD, EICAS as channel, etc. What **physically** sits left/next to the editor per preset. | [0021](0021-pfd-mfd-cockpit-attention-model.md) (“Zone architecture”, anchors vs attention flow). |
47| **Strict PFD surface (engineering contract)** | Which **code component** voluntarily takes the primary-contour “instrument” role: indicators only, allowed weight, allowed data channels. | This ADR (§1–§3), explicit markers in code. |
48
49**Why separate:** aviation strictness must not turn the IDE into an ascetic terminal where “you cannot even click a file in the PFD region”. Solution navigation is **“where am I”** context; banishing it to MFD only for formal “PFD = read-only” raises **tax** on gaze and context switches ([0021](0021-pfd-mfd-cockpit-attention-model.md) — switches as productivity cost).
50
51**Hybrid picture (“layer cake”):** in the **same** PFD attention region on screen you can have:
52
53- **Interactive navigation** (e.g. solution explorer, workspace anchor): user **clicks, expands nodes, picks files** — **navigation context**, not a “second forward”. These components do **not** get mandatory strict PFD surface marker **0037**; the **Roslyn analyzer for this ADR does not touch them** (no marker — no §1–§3 contract).
54- **Strict PFD surfaces** — critical-contour indicators: agent status, EICAS/alerts, compact workspace health, etc. Mark with **`[PfdStrict]`** and/or base type **`PfdStrictControl`** ([naming canon](#adr0037-naming)). **Inside** such types the analyzer **forbids** arbitrary input, **WebView**, and other **Input Lock** and **Weight** violations (§1–§2): “slap on the wrist” for extra interactivity and heavy embeds where policy demands instruments only.
55
56**One line for contributors:** PFD **attention zone** may contain **interactive** navigation; components **explicitly** marked strict PFD surface (**`[PfdStrict]`** or inherit **`PfdStrictControl`**) **must** obey this ADR’s **Input Lock** and **Weight Limit** invariants. The analyzer acts **only** on the marker, not on “drawn on the left”.
57
58<a id="adr0037-glossary-pfd-dual"></a>
59
60### Glossary (two meanings of “PFD”)
61
62| Term | One line |
63|------|----------|
64| **PFD as attention zone** | Screen region in preset ([0021](0021-pfd-mfd-cockpit-attention-model.md)): *where* the “flight context” anchor lies. Geography alone does **not** auto-apply 0037 invariants. |
65| **Strict PFD surface** | Code component with explicit [`[PfdStrict]`](#adr0037-naming) or base `PfdStrictControl`: §1–§3 and Roslyn apply. **Not** synonymous with “everything drawn in the PFD column”. |
66
67**Link phrasing:** “lies in PFD zone” ≠ “under 0037 contract” until the type is marked strict.
68
69**“Where am I in code” navigation:** examples use **solution explorer** as a familiar anchor; not the only form. Navigation by **symbols**, **type hierarchy**, **breadcrumbs**, **file structure**, etc. can be **more effective** for some tasks — still **“where am I”** anchor per [0021](0021-pfd-mfd-cockpit-attention-model.md), not [0037](0037-pfd-surface-invariants-and-roslyn-enforcement.md) instruments until the widget is marked strict. Concrete tools and presets are **product** choice; this ADR only separates **zone geography** and **marker contract**. Product direction “multiple views and related files” — [0039](0039-workspace-navigation-affordances.md).
70
71## Solution
72
73PFD surface invariants are set in **three** rule classes. Concrete **diagnostic IDs**, forbidden type lists, and **exceptions** come at implementation (separate commits); **meaning** of invariants is fixed here.
74
75<a id="adr0037-naming"></a>
76
77### Naming canon for strict surface (for repo code)
78
79**Adopted for implementation:**
80
81| Element | Name | Note |
82|---------|------|------|
83| Attribute (use) | **`[PfdStrict]`** | Full C# type name: **`PfdStrictAttribute`**, PascalCase; **not** `[PFD_Strict]` — consistent with .NET and other repo attributes. |
84| Base type (optional) | **`PfdStrictControl`** | Avalonia `Control` base; descendants are strict PFD surface **without** duplicating attribute on every subtype (analyzer treats **attribute on type** or **inheritance from `PfdStrictControl`** — same semantics). |
85| Do not confuse with | **`PfdSurface`** | “surface” in ADR text is **role** in UI; no separate **`[PfdSurface]`** for “any panel in zone”; without strict marker the analyzer does not apply. |
86
87**In-code glossary:** XML docs on `PfdStrictAttribute` and `PfdStrictControl` should link this ADR and briefly repeat [dual PFD meaning](#adr0037-glossary-pfd-dual) (attention zone ≠ automatic contract).
88
89<a id="adr0037-p1"></a>
90
91### 1. Weight control / dependency allowlist
92
93**Rule:** a view or class **explicitly marked** as **strict** PFD surface (see [above](#adr0037-zone-vs-surface); [`[PfdStrict]`](#adr0037-naming) or [`PfdStrictControl`](#adr0037-naming)) **must not** directly use known heavy containers and embeds: e.g. **virtualized grids as PFD substitute**, **WebView**, **rich ItemsControl** with arbitrary templates where policy wants primitives only.
94
95**Logic:** PFD in product is a **dense indicator** (text, icons, simple shapes, compact progress), not a secondary work area. The analyzer does **not** score FPS; it checks **forbidden types/namespaces** in the marked type and related AXAML (if `.axaml` / codegen analysis is wired).
96
97**Caveat:** generic **`Grid`** as layout is often needed; banning “all Grid” is not the goal — only a **concrete list** of heavy types and scenarios agreed with the team (allowlist of permitted controls — optional phase two).
98
99<a id="adr0037-p2"></a>
100
101### 2. Input lock / read-only display
102
103**Rule:** for **strict** PFD surface (by marker) in the aviation analogy — **read display** in the typical scenario; arbitrary input and focus capture in such a component **competes** with **forward** (editor, terminal) and breaks attention model. (Navigation in PFD **without** marker — outside this rule; see [above](#adr0037-zone-vs-surface).)
104
105For **so marked** components the analyzer **must** flag explicit **pointer, keyboard, and focus** handlers (e.g. Avalonia input event subscriptions), except **explicitly listed** product-policy exceptions (one confirm button, safety — separate ADR/checklist).
106
107**Why:** keep **strict** PFD surface an **indicator**, not an interactive panel stealing input from the primary work surface.
108
109<a id="adr0037-p3"></a>
110
111### 3. Data graph restriction (channels / streams)
112
113**Rule:** a **strictly marked** PFD component **may** subscribe only to **allowed** primary-contour data streams (working names: e.g. **workspace health**, **agent status**, **next step** — exact types and interfaces fixed in code and [cds-contract-v0](../design/cds-contract-v0.md) as they stabilize).
114
115Subscribing to **secondary** saturation streams (e.g. long **git history**, **full solution tree as sole instrument source**, **full filesystem dump** as main source for **strict** PFD surface) is **instrument role mismatch**: that content belongs to **MFD / unmarked navigation / side panels**. (Separately: **solution explorer** in PFD without 0037 marker is **not** bound to this channel list — it does not claim instrument role.)
116
117**Logic:** analyzer checks **types** of subscription / channel factory calls in the marked component **if** channels are **stable compile-time API** (interfaces, generic factories). String DI keys, reflection, and untyped “general bus” are **outside** this ADR — need review tests, not Roslyn-only.
118
119## Consequences
120
121- Split **[0021](0021-pfd-mfd-cockpit-attention-model.md) (zone geography)** and **0037 (marker contract)** removes false “PFD interactive vs PFD read-only only”: interactivity is allowed in the attention region; **strictness** only on explicitly marked instruments.
122- **Explicit** “strict PFD surface in code” discipline: without marker the analyzer is silent — **conscious** contract.
123- Rules migrate in stages to [`CascadeIDE.ArchitectureAnalyzers`](../CascadeIDE.ArchitectureAnalyzers/README.md) (new IDs beside CASCOPE*) and **unit tests** for diagnostics like the existing test project.
124- UX conflicts (e.g. one “OK” on PFD) resolved via **exception list** or attribute subtype, not canceling base invariant.
125
126## Non-goals
127
128- Avionics certification or full **ARINC 661** / hardware **CDS** reproduction.
129- Replacing **human** design review: analyzer catches **known violation classes**, not “pretty/ugly”.
130- Automatic **`Grid`** ban without exceptions and without agreed type list.
131
132## Open questions (before Accepted)
133
1341. Minimal **allowlist** of channels for PFD v1 and mapping to existing `Cockpit/Channels`.
1352. Whether **separate** `.axaml` analysis is needed or partial class + codegen suffices.
136
137**Naming off the table:** canon — [`[PfdStrict]` / `PfdStrictAttribute`](#adr0037-naming) and optional [`PfdStrictControl`](#adr0037-naming); see table in that section.
138
139---
140
141## Change history
142
143<a id="adr0037-history"></a>
144
145| Date | Change |
146|------|--------|
147| — | [glossary](#adr0037-glossary-pfd-dual); navigation and [0039](0039-workspace-navigation-affordances.md). |
148| — | “Attention zone vs strict surface” ([0021](0021-pfd-mfd-cockpit-attention-model.md)). |
149| 2026-04-16 | [naming canon](#adr0037-naming) for strict surface: `[PfdStrict]`, `PfdStrictControl`. |
150
View only · write via MCP/CIDE