726 lines
29 KiB
Markdown
726 lines
29 KiB
Markdown
# A1–A8 Interactive Architecture Viewpoints
|
||
|
||
Status: design contract, version 0.2, 2026-07-18.
|
||
|
||
This document defines how STEM cards describe architecture, code and runtime
|
||
evidence. It is a house convention, not a new UML standard. The convention is
|
||
organized in the spirit of ISO/IEC/IEEE 42010:2022, uses UML 2.5.1 notation,
|
||
adds selected MARTE 1.3 concepts for real-time systems, and uses PlantUML as
|
||
the textual source of rendered diagrams.
|
||
|
||
## Scope and rollout
|
||
|
||
A1–A8 is runtime-independent. The fixed viewpoints are intended to support
|
||
embedded RTOS software, ordinary C++ object models, POSIX or standard threads,
|
||
and asynchronous Boost.Asio applications without changing the navigation
|
||
grammar.
|
||
|
||
The rollout is deliberately staged:
|
||
|
||
1. **current application:** FreeRTOS C++ cards on RV32I/Hazard3;
|
||
2. **later application:** `std::thread`/`std::jthread` and Boost.Asio;
|
||
3. **not yet scheduled:** concrete Asio/thread card repositories and lesson
|
||
numbering.
|
||
|
||
The later profile is specified below so current diagrams do not bake in RTOS-
|
||
only assumptions. It is a compatibility target, not a claim that the current
|
||
FreeRTOS card already implements or teaches Asio.
|
||
|
||
## Standards boundary
|
||
|
||
- **ISO/IEC/IEEE 42010:2022** supplies the concepts of architecture
|
||
descriptions, viewpoints, views and model kinds. A1–A8 is our concrete set
|
||
of viewpoints. We do not claim full ISO conformance merely because a card
|
||
uses these labels.
|
||
- **UML 2.5.1** supplies the notation for classes, objects, components,
|
||
interactions, activities and state machines. It does not prescribe A1–A8.
|
||
- **MARTE 1.3** may annotate schedulable resources, time, hardware and
|
||
allocation in RTOS cards. A MARTE property must come from configuration,
|
||
code or measurement; authors must not invent period, deadline or execution
|
||
time merely to fill a box.
|
||
- **arc42** is a useful wider documentation template. A1–A8 is the smaller,
|
||
interactive teaching slice used inside a card, not a replacement for an
|
||
architecture description of the whole product.
|
||
- **PlantUML** is the text-first renderer. The `.puml` source, not a manually
|
||
edited SVG, is authoritative.
|
||
|
||
Primary references:
|
||
|
||
- <https://www.iso.org/standard/74393.html>
|
||
- <https://www.omg.org/spec/UML/2.5.1>
|
||
- <https://www.omg.org/spec/MARTE/1.3>
|
||
- <https://arc42.org/overview>
|
||
- <https://plantuml.com/class-diagram>
|
||
- <https://plantuml.com/sequence-diagram>
|
||
- <https://plantuml.com/ascii-art>
|
||
|
||
## The fixed navigation model
|
||
|
||
The tab names remain stable across cards. A subtitle identifies the actual
|
||
mechanism being taught.
|
||
|
||
```text
|
||
A1 CONTEXT
|
||
A2 STRUCTURE
|
||
A3 DISPATCH
|
||
A4 APPLICATION
|
||
A5 FLOW
|
||
A6 STATE
|
||
A7 RUNTIME
|
||
A8 PATTERNS
|
||
```
|
||
|
||
These eight tabs ask eight different questions:
|
||
|
||
| ID | Question | Typical model kind |
|
||
|---|---|---|
|
||
| A1 CONTEXT | Where is the subject and what lies outside its boundary? | component, package or deployment view |
|
||
| A2 STRUCTURE | What static elements and relationships construct it? | class, component or object structure |
|
||
| A3 DISPATCH | How is an abstract call bound to the actual implementation? | class plus sequence/call-path view |
|
||
| A4 APPLICATION | How does application code specialize or compose it? | application class/object view |
|
||
| A5 FLOW | What happens in what order? | sequence or activity view |
|
||
| A6 STATE | Which lifecycles and state transitions exist? | state machine, never an unlabeled flowchart |
|
||
| A7 RUNTIME | What actually exists in memory and in the debugger now? | object diagram plus evidence overlay |
|
||
| A8 PATTERNS | Which design roles and trade-offs explain the construction? | participant map plus decision record |
|
||
|
||
Not every card needs all eight views. The top-level navigation keeps all eight
|
||
positions stable; an omitted view is visibly unavailable and states why. A
|
||
small card should not create decorative diagrams to fill empty tabs.
|
||
|
||
## Viewpoint contracts
|
||
|
||
### A1 CONTEXT
|
||
|
||
**Purpose:** establish system boundary and dependency direction before class
|
||
details appear.
|
||
|
||
Required content:
|
||
|
||
- subject under study;
|
||
- upstream application actor or component;
|
||
- wrapped platform/API;
|
||
- runtime platform, hardware or simulator when relevant;
|
||
- one verb on every boundary-crossing relation.
|
||
|
||
For an RTOS wrapper this normally reads:
|
||
|
||
```text
|
||
Application task
|
||
│ specializes / uses
|
||
▼
|
||
C++ wrapper
|
||
│ calls
|
||
▼
|
||
FreeRTOS C API
|
||
│ schedules on
|
||
▼
|
||
Hazard3 simulator
|
||
```
|
||
|
||
A1 must not list every method. It is a map, not a class reference.
|
||
|
||
### A2 STRUCTURE
|
||
|
||
**Purpose:** show the static construction that the compiler sees.
|
||
|
||
Required content:
|
||
|
||
- class/interface/component names;
|
||
- relevant fields and operations only;
|
||
- visibility where it is part of the lesson;
|
||
- precise relationship type: generalization, realization, composition,
|
||
aggregation or dependency;
|
||
- storage/ownership role when the structure owns a resource.
|
||
|
||
Class rows receive semantic anchors only when a card can connect them to a
|
||
source line or a compile-time proof. Inheritance, `friend`, templates and
|
||
visibility are CODE facts; they are never presented as runtime events.
|
||
|
||
### A3 DISPATCH
|
||
|
||
**Purpose:** explain the binding mechanism between the generic boundary and
|
||
the concrete implementation.
|
||
|
||
The title is fixed; the subtitle is mechanism-specific. Examples:
|
||
|
||
```text
|
||
A3 DISPATCH · CRTP static dispatch
|
||
A3 DISPATCH · virtual dispatch through vtable
|
||
A3 DISPATCH · C callback and function pointer
|
||
A3 DISPATCH · event to subscriber
|
||
A3 DISPATCH · executor and completion handler
|
||
```
|
||
|
||
The diagram must identify:
|
||
|
||
1. the call origin;
|
||
2. the erased or abstract boundary;
|
||
3. the cast, lookup or binding operation;
|
||
4. the concrete target;
|
||
5. whether the decision is compile-time or runtime;
|
||
6. the ABI proof that distinguishes the mechanism.
|
||
|
||
This viewpoint prevents a wrapper from being mislabeled. A CRTP wrapper must
|
||
show `static_cast<Derived*>` and the absence of virtual dispatch. A dynamic
|
||
wrapper must show object address, `vptr`, vtable entry and indirect call.
|
||
|
||
### A4 APPLICATION
|
||
|
||
**Purpose:** show one concrete use without repeating the complete library.
|
||
|
||
The generic mechanism is collapsed to its public contract. The view maps every
|
||
pattern or framework role to the names used in the exercise, for example
|
||
`Strategy -> PaymentStrategy` and `Context -> ShoppingCart`.
|
||
|
||
At least one application invariant is printed next to the model. Example:
|
||
"`ShoppingCart` depends on the strategy interface, not a payment variant."
|
||
|
||
### A5 FLOW
|
||
|
||
**Purpose:** show causal order for one named scenario.
|
||
|
||
Rules:
|
||
|
||
- state the precondition and observable postcondition;
|
||
- use sequence diagrams for collaborating participants and activity diagrams
|
||
for algorithmic branching;
|
||
- number messages in the same order as interactive steps;
|
||
- show returns only when they carry teaching information;
|
||
- split construction, scheduling and callback dispatch into phases when one
|
||
page would hide the boundary.
|
||
|
||
A5 is the primary home of RUN steps and deterministic checkpoints.
|
||
|
||
### A6 STATE
|
||
|
||
**Purpose:** separate lifecycle from execution flow.
|
||
|
||
When two state domains exist, draw two explicit lanes rather than merging them.
|
||
For a FreeRTOS C++ task these are commonly:
|
||
|
||
```text
|
||
C++ object lifetime: absent -> constructed -> alive -> destroyed
|
||
Kernel task state: Ready <-> Running <-> Blocked; Suspended; Deleted
|
||
```
|
||
|
||
Every transition has a trigger, guard or event. Values returned by platform
|
||
APIs are platform states, not invented wrapper states. A wrapper-specific state
|
||
machine is allowed only when the code really stores and enforces it.
|
||
|
||
### A7 RUNTIME
|
||
|
||
**Purpose:** connect the model to a reproducible observation.
|
||
|
||
A7 is deliberately a hybrid, not pure UML. It combines an object diagram with
|
||
selected debugger facts:
|
||
|
||
- object and subobject addresses;
|
||
- `this`, callback context and handles;
|
||
- fields, ownership pointers, TCB and stack interval;
|
||
- PC, SP and relevant argument registers;
|
||
- vptr/vtable target for dynamic dispatch;
|
||
- symbol/absence-of-symbol proof for static dispatch;
|
||
- timestamp, target, ELF revision and checkpoint identity.
|
||
|
||
Every value is either captured from a deterministic run or marked as a
|
||
symbolic example. A screenshot without target, source revision and timestamp is
|
||
illustration, not evidence.
|
||
|
||
### A8 PATTERNS
|
||
|
||
**Purpose:** explain why the design has its shape and what it costs.
|
||
|
||
Each claimed pattern records:
|
||
|
||
- intent and problem;
|
||
- forces/constraints;
|
||
- canonical participant roles;
|
||
- exact mapping from role to project class/function;
|
||
- collaboration that makes the pattern real;
|
||
- invariant or test;
|
||
- benefit and cost;
|
||
- rejected alternative;
|
||
- conditions in which the pattern should not be used.
|
||
|
||
Pattern names are not decorative stereotypes. `Facade` is valid only when a
|
||
simpler boundary to a subsystem can be identified. `RAII` is valid only when
|
||
acquisition and release are safely paired for every legal lifetime. A callback
|
||
bridge may be an Adapter without making the whole wrapper an Adapter.
|
||
|
||
## Authored viewpoint record
|
||
|
||
The future machine-readable form should preserve this conceptual record. This
|
||
is a design target, not yet a required `card_source.json` schema extension:
|
||
|
||
```json
|
||
{
|
||
"id": "a3-dispatch",
|
||
"number": "A3",
|
||
"label": "DISPATCH",
|
||
"subtitle": "Dynamic polymorphism through vtable",
|
||
"purpose": "Trace the C callback to the concrete C++ override.",
|
||
"stakeholders": ["student", "teacher", "embedded developer"],
|
||
"concerns": ["C-to-C++ bridge", "void* context", "vtable", "ABI"],
|
||
"model_kind": "uml-sequence",
|
||
"source": "doc/assets/a3-dispatch.puml",
|
||
"fallback_text": "doc/assets/a3-dispatch.txt",
|
||
"spread_group": "task-dispatch",
|
||
"steps": [
|
||
{
|
||
"id": "dispatch-vptr",
|
||
"number": 4,
|
||
"mode": "RUN",
|
||
"svg_target": "dispatch-vptr",
|
||
"code_ref": "include/FreeRTOS/Task.hpp:110",
|
||
"snapshot_ref": "task.dispatch.vptr",
|
||
"evidence": "a0, object address, vptr, vtable entry and jalr target"
|
||
}
|
||
]
|
||
}
|
||
```
|
||
|
||
Required semantics:
|
||
|
||
- `id`, `number` and `label` are stable teaching identity;
|
||
- `subtitle` names the actual mechanism and may differ between cards;
|
||
- `source` is the text source of the rendered asset;
|
||
- `fallback_text` is a compact readable map, not generated alt text;
|
||
- `code_ref` is repository-relative and validated;
|
||
- CODE steps may have no snapshot and never reset the program;
|
||
- RUN steps require a deterministic replay target;
|
||
- `evidence` says what proves the claim, not merely what should be visible;
|
||
- `spread_group` joins logical continuations without changing A4 print pages.
|
||
|
||
## Plain technical rendering profile
|
||
|
||
"Plain text UML" means two related things in this project:
|
||
|
||
1. diagrams are authored as reviewable text;
|
||
2. their rendered form resembles a restrained technical drawing rather than a
|
||
presentation slide.
|
||
|
||
The default profile therefore uses:
|
||
|
||
- white background, black/charcoal strokes and no shadows;
|
||
- square or nearly square corners;
|
||
- one monospaced family for identifiers, fields, methods and evidence;
|
||
- one sans-serif family only for explanatory prose;
|
||
- orthogonal relations where the renderer can keep labels legible;
|
||
- left-aligned members and short, explicit verbs on relations;
|
||
- no gradients, icons, ornamental colors or oversized titles;
|
||
- line weight and spacing, not color, as the primary print hierarchy;
|
||
- visible step anchors such as `01`–`08` that remain useful in SVG and print;
|
||
- two muted selectable tones in HTML and one subtle active outline;
|
||
- non-selectable content in neutral gray, never confused with a selectable
|
||
inactive element.
|
||
|
||
PlantUML can generate ASCII/Unicode text output for sequence diagrams. We may
|
||
ship that output as the fallback for sequences. Other diagram kinds receive a
|
||
small hand-maintained text map because PlantUML's ASCII renderer does not cover
|
||
all UML kinds. The fallback communicates topology and reading order; SVG and
|
||
TeX remain the visual outputs.
|
||
|
||
## Orientation, type scale and page visibility
|
||
|
||
The default reading direction is vertical. A horizontal layout is reserved for
|
||
a genuine sequence or timeline whose primary fact is execution order over
|
||
time. A binding chain is vertical unless time or participant lifelines are
|
||
being modelled explicitly.
|
||
|
||
| Viewpoint | Default orientation | Reason |
|
||
|---|---|---|
|
||
| A1 CONTEXT | vertical | responsibility descends from application to platform |
|
||
| A2 STRUCTURE | vertical | base types, specializations and dependencies form tiers |
|
||
| A3 DISPATCH | vertical | binding stages form a top-to-bottom chain; use horizontal only for a genuine sequence |
|
||
| A4 APPLICATION | vertical | application objects lead to observers and invariants |
|
||
| A5 FLOW | horizontal | messages and time advance in reading order |
|
||
| A6 STATE | vertical | lifecycle transitions form explicit top-to-bottom paths |
|
||
| A7 RUNTIME | geometry-dependent | use vertical for an ownership descent, horizontal for a memory/CPU evidence pipeline |
|
||
| A8 PATTERNS | geometry-dependent | use vertical for tiers and horizontal for a short chain of roles and consequences |
|
||
|
||
Use `top to bottom direction` unless the diagram is a genuine sequence or
|
||
timeline (normally A5). A diagram must not be made horizontal merely to fill
|
||
page width.
|
||
|
||
Physical page orientation follows the rendered model rather than the viewpoint
|
||
name: use one portrait page, one landscape page, or an explicit semantic page
|
||
composition. Prefer a single page after a deliberate layout change; introduce
|
||
tiles only when readable labels and complete semantic blocks still cannot fit.
|
||
|
||
The default PlantUML type scale is `14` for ordinary labels, `15` for class
|
||
names and `13` for class attributes. A smaller value is allowed only when the
|
||
diagram remains readable at the normal A4 viewer scale. Prefer fewer words,
|
||
shorter relation labels and a second logical page over shrinking text.
|
||
|
||
All diagrams belonging to one card use one shared PlantUML style include. The
|
||
style is print-first and keeps the following invariants:
|
||
|
||
- one monospaced family for nodes, relations and sequence messages;
|
||
- a `190 px` minimum class width, while content may make a node wider;
|
||
- `1.5 px` node borders and `1.3 px` arrows;
|
||
- a near-white node fill, blue-grey borders and dark text with sufficient
|
||
monochrome-print contrast;
|
||
- the same base styling for class, state and sequence diagrams;
|
||
- no shadows, decorative gradients or per-diagram colour inventions.
|
||
|
||
Interactive selection is an overlay owned by the viewer. The source diagram
|
||
must remain fully legible with no selection, while selectable nodes receive a
|
||
clearer idle treatment than non-interactive context nodes. Selection changes
|
||
emphasis, not geometry: it must not resize a node, move a label or alter the
|
||
diagram layout.
|
||
|
||
At `content scale = 100%`, the HTML viewer preserves the intrinsic PlantUML
|
||
scale. A diagram that exceeds the declared A4-safe viewport is split into
|
||
semantic tiles; it is not silently compressed to `width: 100%`. The joined
|
||
HTML spread reconstructs the logical page in a CSS grid, while ordinary view
|
||
and print retain separate physical A4 sheets. Canvas zoom remains an explicit
|
||
viewer action and may be used to inspect the joined overview.
|
||
|
||
Every diagram starts on a new A4 page in HTML and TeX. Its SVG must fit within
|
||
the page-safe margins with all labels, arrowheads and numbered anchors visible.
|
||
Long diagrams continue on a new page with stable global step numbers and may be
|
||
joined by the HTML spread view. Every physical tile remains legible on its own,
|
||
but its `part`, row and column identify its exact position in the logical model.
|
||
|
||
## Large diagrams and page continuity
|
||
|
||
A viewpoint is one logical model even when it needs several A4 pages.
|
||
|
||
- `page_grid` declares columns, rows and explicit semantic `cuts_x`/`cuts_y`;
|
||
- a cut may cross whitespace or a connector, but never a class, object, state,
|
||
participant, note, numbered anchor or other closed semantic block;
|
||
- the generator validates the rendered SVG geometry and rejects a colliding
|
||
seam instead of shrinking the diagram or accepting a broken print;
|
||
- every interactive step belongs to exactly one tile through `step_tiles`;
|
||
- all tiles use one logical figure number and one global navigation cursor;
|
||
- each page carries `A<n>`, the same viewpoint title, `part x/y`, and a shared
|
||
`spread_group`;
|
||
- duplicated participants at a page boundary are marked `continued`, not
|
||
treated as new objects;
|
||
- step numbers remain global across parts;
|
||
- connectors leaving a page use a named continuation token, for example
|
||
`D3 -> A5.2`;
|
||
- HTML can join the parts side by side; print keeps independent A4 pages;
|
||
- the joined HTML view fits the complete logical row into the viewport, keeps
|
||
page tops aligned and centers the semantic join rather than either sheet;
|
||
- a screen-only continuation cue in every part header indicates available
|
||
neighbours to the left, right, above and below;
|
||
- selecting a step scrolls to the correct part and preserves one cursor;
|
||
- no information is encoded only in the physical proximity of two pages.
|
||
|
||
The source diagram may use a modest, explicit PlantUML `scale` when that is
|
||
necessary to place a semantic seam inside the A4-safe viewport. This is a
|
||
design decision, not automatic fit-to-width. The resulting normal print must
|
||
still meet the shared type-scale readability gate; HTML hover/canvas zoom is a
|
||
convenience and never a substitute for readable print.
|
||
|
||
## Interaction and correspondence rules
|
||
|
||
The diagram, source tree and debugger share one navigation identity:
|
||
|
||
```text
|
||
SERIES -> CARD -> TASK -> BLOCK -> VIEWPOINT/PHASE -> STEP -> SNAPSHOT
|
||
```
|
||
|
||
For every selectable anchor:
|
||
|
||
- its visible step number occurs exactly once inside that diagram;
|
||
- click and keyboard navigation select the same step;
|
||
- CODE opens the exact code or binary proof and does not mutate runtime;
|
||
- RUN opens code and may replay only after explicit activation;
|
||
- compile-time relations use code, `nm`, `readelf` or disassembly evidence;
|
||
- runtime messages use checkpoint evidence;
|
||
- focus is a subtle overlay; unselected selectable targets stay visible;
|
||
- a missing `snapshot_ref` is valid for CODE and invalid for RUN;
|
||
- the authored SVG target is validated after PlantUML rendering.
|
||
|
||
## Diagram-first teaching contract
|
||
|
||
The diagram is the primary entry point into an example. A printed card must
|
||
teach the algorithm, responsibility boundary, state transition or dispatch
|
||
mechanism before it exposes implementation syntax. Complete source listings
|
||
do not belong on the card. The card carries the repository URL/QR code, while
|
||
an interactive CODE anchor opens only the relevant symbol or source range in
|
||
Neovim.
|
||
|
||
The intended learning path is:
|
||
|
||
```text
|
||
goal and scope
|
||
-> relevant A1-A8 viewpoint
|
||
-> numbered diagram element
|
||
-> CODE source anchor or RUN checkpoint
|
||
-> Neovim / Termdebug / Hazard3 evidence
|
||
-> timestamped snapshot
|
||
```
|
||
|
||
Consequently:
|
||
|
||
- a card uses only the A1-A8 viewpoints which materially explain the subject;
|
||
- the diagram explains the mechanism, source confirms its implementation and
|
||
the debugger supplies evidence;
|
||
- CODE navigation does not restart or mutate the program;
|
||
- RUN navigation may replay only to a declared deterministic checkpoint;
|
||
- source excerpts may appear temporarily in the interactive Neovim view, but
|
||
are not duplicated as full static listings in HTML, TeX or print;
|
||
- every source jump is attached to a concrete diagram element, relation,
|
||
message or state rather than to an unrelated code catalogue;
|
||
- the repository link remains the canonical route to the complete source.
|
||
|
||
This order is deliberate: students first reason about algorithms, states and
|
||
responsibilities, then inspect the C or C++ syntax that implements them.
|
||
|
||
## Editable UML layout and JSON persistence
|
||
|
||
Interactive UML views may expose an explicit `EDIT` mode. It applies only to
|
||
UML/model assets; it must not turn the whole card page into a free-form editor
|
||
or interfere with normal CODE/RUN navigation.
|
||
|
||
PlantUML remains the authoritative semantic source for participants,
|
||
relationships and diagram kind. Manual visual decisions are stored in a
|
||
sidecar JSON document named after the source, for example:
|
||
|
||
```text
|
||
doc/assets/a2-structure.puml
|
||
doc/assets/a2-structure.layout.json
|
||
```
|
||
|
||
Saving a layout persists the complete authored presentation state, not only a
|
||
temporary browser transform. At minimum the sidecar records:
|
||
|
||
- diagram identity, source revision and layout schema version;
|
||
- canvas size, page orientation, scale and optional page-grid metadata;
|
||
- stable element identity (`id`/`svg_target`), position and stacking order;
|
||
- width, height, local scale and rotation when the model kind allows it;
|
||
- displayed name, stereotype, short description and member text overrides;
|
||
- font family, font size, weight, style, line height and text alignment;
|
||
- fill, stroke, border width, corner treatment and semantic style role;
|
||
- group membership, collapsed state and explicit grouping/ungrouping;
|
||
- relation endpoints, labels and manually placed routing points;
|
||
- numbered CODE/RUN anchor placement without changing its teaching identity;
|
||
- editor metadata such as update timestamp and optional author.
|
||
|
||
A representative record is:
|
||
|
||
```json
|
||
{
|
||
"schema": "stem.uml-layout/v1",
|
||
"diagram_id": "task01.a2-structure",
|
||
"source": "a2-structure.puml",
|
||
"source_digest": "sha256:...",
|
||
"canvas": {
|
||
"width": 1120,
|
||
"height": 760,
|
||
"orientation": "landscape",
|
||
"scale": 1
|
||
},
|
||
"elements": {
|
||
"task-base": {
|
||
"x": 310,
|
||
"y": 72,
|
||
"width": 360,
|
||
"height": 290,
|
||
"z": 2,
|
||
"text": {
|
||
"title": "Task<Derived>",
|
||
"description": "Static task wrapper",
|
||
"font_family": "IBM Plex Mono",
|
||
"font_size": 14,
|
||
"font_weight": 500,
|
||
"align": "left"
|
||
},
|
||
"style": {
|
||
"role": "wrapper",
|
||
"fill": "#eef5f8",
|
||
"stroke": "#397c99",
|
||
"stroke_width": 1.5
|
||
}
|
||
}
|
||
},
|
||
"relations": {
|
||
"task-to-api": {
|
||
"from": "task-base",
|
||
"to": "freertos-api",
|
||
"label": "calls",
|
||
"points": [[490, 362], [490, 430], [690, 430]]
|
||
}
|
||
},
|
||
"updated_at": "2026-07-19T12:00:00+02:00"
|
||
}
|
||
```
|
||
|
||
Editor requirements:
|
||
|
||
- dragging, resizing, text editing, grouping and relation routing update an
|
||
in-memory draft first;
|
||
- `Save layout` validates stable IDs and writes the sidecar atomically;
|
||
- `Cancel` restores the last saved sidecar without changing PlantUML;
|
||
- `Reset layout` removes visual overrides and returns to the generated
|
||
PlantUML geometry only after explicit confirmation;
|
||
- rerendering PlantUML reapplies compatible overrides by stable ID and reports
|
||
orphaned overrides instead of silently discarding them;
|
||
- a source digest mismatch is visible to the editor but does not destroy the
|
||
saved layout;
|
||
- normal view and print consume the same saved JSON, so the authored geometry
|
||
is reproducible outside the editing session;
|
||
- CODE/RUN step IDs, source references and snapshot identities cannot be
|
||
renamed accidentally by a visual edit.
|
||
|
||
Exact manual coordinates cannot be represented reliably through PlantUML
|
||
layout hints alone. The sidecar is therefore the canonical manual presentation
|
||
layer, while `.puml` remains the canonical semantic layer.
|
||
|
||
## Two valid A3 profiles for FreeRTOS wrappers
|
||
|
||
The viewpoint set intentionally supports both of these designs.
|
||
|
||
### Current teaching wrapper in K02
|
||
|
||
```text
|
||
A2 STRUCTURE Task<Derived>, SumTask, SupervisorTask
|
||
A3 DISPATCH CRTP static dispatch
|
||
void* -> Task<Derived>* -> Derived* -> run()
|
||
A7 RUNTIME same object address; direct/inlined target; no vtable symbol
|
||
```
|
||
|
||
This matches the current K02 acceptance gate: no virtual dispatch, vtable,
|
||
RTTI or hosted runtime.
|
||
|
||
### `jonenz/FreeRTOS-Cpp` reference design
|
||
|
||
```text
|
||
A2 STRUCTURE TaskBase <- Task / StaticTask<N> <- application task
|
||
A3 DISPATCH dynamic dispatch
|
||
void* -> TaskBase* -> taskEntry() -> virtual taskFunction()
|
||
A7 RUNTIME object address, vptr, vtable entry and indirect target
|
||
```
|
||
|
||
The upstream `Task.hpp` creates dynamic/static kernel tasks in constructors,
|
||
passes `this` to `callTaskFunction(void*)`, and uses a virtual
|
||
`taskFunction()`. Its `TaskBase` destructor may call `vTaskDelete(handle)` when
|
||
configured. These are reference facts, not automatic design choices for our
|
||
teaching wrapper. Adopting that design would require changing K02's lifecycle,
|
||
ABI and no-vtable acceptance contracts explicitly.
|
||
|
||
Reference:
|
||
<https://github.com/jonenz/FreeRTOS-Cpp/blob/develop/FreeRTOS-Cpp/include/FreeRTOS/Task.hpp>
|
||
|
||
## Target profile: Boost.Asio and standard threads
|
||
|
||
This is the required future compatibility profile. It does not rename the
|
||
fixed tabs. Mechanism-specific wording belongs in subtitles:
|
||
|
||
```text
|
||
A1 CONTEXT · application, Asio, io_context, worker threads, OS
|
||
A2 STRUCTURE · Server, Session, socket, strand and ThreadPool
|
||
A3 DISPATCH · executor and completion-handler dispatch
|
||
A4 APPLICATION · one concrete Session or Client
|
||
A5 FLOW · asynchronous initiation and completion
|
||
A6 STATE · operation, session and thread lifecycles
|
||
A7 RUNTIME · threads, executors, handlers and owned buffers
|
||
A8 PATTERNS · Proactor and verified collaboration roles
|
||
```
|
||
|
||
The fixed label remains `A5 FLOW`, not `A5 ASYNC FLOW`; the UI subtitle may be
|
||
`Async completion flow`. Likewise the fixed label remains `A7 RUNTIME`, with
|
||
`Threads / executors` as a subtitle. This keeps cards comparable while still
|
||
naming the actual mechanism.
|
||
|
||
### A1–A8 mapping
|
||
|
||
**A1 CONTEXT** shows this dependency/execution stack:
|
||
|
||
```text
|
||
Application Session / Server
|
||
│ initiates
|
||
▼
|
||
Boost.Asio async operations, executors and strands
|
||
│ queue completions in
|
||
▼
|
||
io_context
|
||
│ run() is called by
|
||
▼
|
||
std::thread / std::jthread workers
|
||
│ use
|
||
▼
|
||
operating-system sockets and scheduling
|
||
```
|
||
|
||
**A2 STRUCTURE** shows the static ownership and dependency graph: `Server`,
|
||
`Session`, `tcp::socket`, executor/strand, buffers, `io_context` and the worker
|
||
collection. It must make lifetime ownership explicit, especially when a
|
||
session uses `shared_from_this()` to outlive an initiating call.
|
||
|
||
**A3 DISPATCH** traces an initiating function through the outstanding
|
||
operation, associated executor, completion queue and selected handler. It must
|
||
not draw `async_read` as if it created a user thread. Completion handlers are
|
||
invoked only by threads currently running `io_context::run()`; several such
|
||
threads form a pool from which `io_context` may choose. A strand adds strictly
|
||
sequential handler invocation, not physical affinity to one thread.
|
||
|
||
**A4 APPLICATION** collapses Asio infrastructure and shows one concrete
|
||
protocol/session contract, for example `EchoSession::start/read/onRead/write`.
|
||
|
||
**A5 FLOW** uses the explicit sequence:
|
||
|
||
```text
|
||
initiate -> outstanding -> operation completes -> handler queued
|
||
-> one run() thread invokes handler -> next operation or completion
|
||
```
|
||
|
||
**A6 STATE** separates at least three domains when present:
|
||
|
||
```text
|
||
jthread object: absent -> joinable -> stop requested -> joined
|
||
async operation: initiated -> outstanding -> queued -> running -> done
|
||
application Session: Created -> Reading -> Processing -> Writing -> Closed
|
||
```
|
||
|
||
The `std::jthread` destructor requests stop and joins when the object is still
|
||
joinable. A session state is application data; it must not be inferred merely
|
||
from a handler being present in a queue.
|
||
|
||
**A7 RUNTIME** records `io_context`, worker IDs, current handler and thread,
|
||
executor/strand identity, socket descriptor, operation kind, session address,
|
||
buffer lifetime and relevant smart-pointer ownership. The evidence view uses
|
||
`info threads`, backtraces and object inspection rather than RTOS TCB fields.
|
||
|
||
**A8 PATTERNS** may identify Proactor, callback/continuation, serialized
|
||
execution through a strand, thread pool, RAII thread ownership and lifetime
|
||
management. These are classified carefully: `std::jthread` ownership is a C++
|
||
idiom, a thread pool is a concurrency architecture, and not every completion
|
||
handler constitutes a GoF Command. Boost.Asio documents its asynchronous model
|
||
as Proactor; the card must still map each claimed role to project code.
|
||
|
||
The central invariant for every future Asio card is:
|
||
|
||
```text
|
||
asynchronous operation != thread
|
||
|
||
operation completion -> associated executor -> io_context
|
||
-> one thread currently executing run()
|
||
```
|
||
|
||
Primary references for this profile:
|
||
|
||
- <https://www.boost.org/doc/libs/latest/doc/html/boost_asio/overview/core/threads.html>
|
||
- <https://www.boost.org/doc/libs/latest/doc/html/boost_asio/overview/core/strands.html>
|
||
- <https://www.boost.org/doc/libs/latest/doc/html/boost_asio/overview/core/async.html>
|
||
- <https://eel.is/c++draft/thread.thread.class>
|
||
- <https://eel.is/c++draft/thread.jthread.class>
|
||
|
||
## Definition of done for a card view
|
||
|
||
A viewpoint is ready when:
|
||
|
||
1. its purpose and question are stated;
|
||
2. the chosen UML/model kind fits that question;
|
||
3. every relation has one unambiguous meaning;
|
||
4. every selectable item has a stable anchor and code reference;
|
||
5. runtime claims have reproducible evidence;
|
||
6. compile-time claims use compiler/binary evidence rather than fake runtime;
|
||
7. the text fallback remains understandable without SVG;
|
||
8. the view prints in monochrome and works as an interactive HTML asset;
|
||
9. continuation across pages preserves identity and step order;
|
||
10. A8 names costs and rejected alternatives, not only benefits.
|