UX Considerations and Guidelines
This document describes the user experience principles, terminology conventions, and design decisions for the kbpy web interface.
Personas
The interface serves five personas, each with distinct information needs. Every page should be designed with a clear primary persona in mind.
1. Expector
The person or entity who holds expectations. They define what should be true and monitor whether it is.
Key question: "Are my expectations being met?"
Needs: Expectation status, what's unmet, what's uncertain, outstanding questions, who is responsible for fixing misalignments.
Pages: Expectors index, expector detail, expectations index.
2. Expectee
The person or entity responsible for meeting expectations. When expectations are not met, the expectee should take action.
Key question: "What's expected of me, and where am I falling short?"
Needs: What expectations they're responsible for, which are unmet and why, what actions to take, what questions to answer.
Pages: Expectees index, expectee detail, actions index.
3. Attestor
The person or entity who provides data. They are the "who to ask" when questions arise from missing data.
Key question: "What data do I need to provide?"
Needs: All questions addressed to them, what data is needed and why, which expectations and expectees are blocked.
Pages: Attestors index, attestor detail, questions index.
4. Alignment Campaign Operator
The person running the alignment campaign — defining expectations, collecting attestations, understanding the domain, and driving resolution.
Key question: "What's the full picture, and what do I need to do next?"
Needs: Everything. Domain model, definitions, source code, entity data, expectations, questions, actions. Nearly every page is relevant.
Pages: Dashboard, all Domain section pages, definitions, source viewer.
5. Subject Entity
An entity being evaluated. The entity detail page serves this "persona" by showing everything known about a specific entity.
Key question: "What's my status across all expectations?"
Needs: Which expectations apply, alignment status with reason chains, data fields with provenance, relationships.
Pages: Entity detail.
Terminology
Consistent, human-readable terminology throughout the interface. These terms replace internal/technical names.
Canonical terms
| Concept | UI Term | NOT | Notes |
|---|---|---|---|
| Person who holds expectations | Expector | Expector, Holder | Always "Expector" in labels, descriptions, links |
| Person responsible for meeting expectations | Expectee | Expectee, Party | "Expectee" in headers and summary cards. "Responsible" as inline label on entity lists is acceptable |
| Person who provides data | Attestor | Data Source (ambiguous) | Clear distinction from attestation source (the data pipeline) |
| The rules that determine misalignment | Misaligned when | Expects Empty | Human-readable label showing which branches trigger misalignment |
| Entities where data is insufficient | Entities with missing data | Entities with unknown predicate result | Avoid exposing "predicate" as a user-facing concept |
| Partition branch descriptions | is true, is false, is unknown, is void | is_true, is_false, is_unknown, is_void | Use ` |
The | readable filter
All snake_case identifiers displayed to users should pass through the | readable Jinja2 filter, which converts snake_case_name to snake case name. This applies to:
- Page titles and h1 headers
- Sidebar labels
- Breadcrumbs and navigation
- Table column headers
- Link text for entity sets, partitions, expectations, relationships
- Source names and entity set names on source pages
- Back-link labels
Exception: Identifiers inside source code blocks (<pre><code>) should remain as-is — they represent actual code.
Exception: Entity IDs (like Alice, SVC_001) are proper nouns and should be displayed as-is, not through | readable.
Domain names vs identifiers
Domain names and campaign names in page titles use | replace('_', ' ') | title for proper-noun casing (e.g., "Service Ownership" not "service ownership"). Regular identifiers use | readable for lowercase (e.g., "all it services" not "All It Services").
Design Principles
Complete and Sufficient
The set-scoped view is an evaluation context, not a filter. Everything shown is relevant, and everything relevant is shown.
- "This is all you need" — every entity, relationship, and attestation that bears on these expectations is present
- "Nothing is hidden" — unknown values and unresolvable references are shown with reason chains
- "Nothing is extraneous" — no entities or model elements that don't contribute to evaluation
Reason Chains as First-Class UI
Every value carries a reason chain explaining its provenance. The interface promotes reason chains from hidden metadata to visible context:
- Unknown/void values: Reason chains shown inline by default. "Why don't we know this?" is the most important question for driving resolution.
- Known values: Reason chains available on hover/click (present but not competing for attention).
- Misaligned entities: Reason chains shown inline — the user needs to understand why the entity is misaligned.
- Partition membership: Why an entity ended up in a particular branch should be traceable.
Actionable Information First
On pages where both "good news" (aligned entities) and "action items" (questions, actions, misaligned entities) coexist, action items come first:
- Misaligned entities (need attention)
- Questions (need answering)
- Actions (need doing)
- Aligned entities (for reference)
This ensures users see what needs their attention before scrolling through potentially long lists of compliant entities.
Readable Language Throughout
Use readable, human-friendly forms rather than code-style identifiers:
- "Service Ownership" not
service_ownership - "All Employees" not
all_employees - "has owner" not
has_owner - "entity → owner" not
SELF->owner
Expectations, questions, and actions should read as natural language sentences. The expectation_description macro generates these from structured description parts.
Information Architecture
URL Structure
/ Domain selection
/d/{domain} Domain overview (campaign cards)
/d/{domain}/x/{campaign}/ Campaign dashboard
/d/{domain}/x/{campaign}/expectations All expectations
/d/{domain}/x/{campaign}/expectors All expectors
/d/{domain}/x/{campaign}/expectees All expectees
/d/{domain}/x/{campaign}/attestors All attestors
/d/{domain}/x/{campaign}/questions All questions
/d/{domain}/x/{campaign}/actions All actions
/d/{domain}/x/{campaign}/entity_sets Entity sets
/d/{domain}/x/{campaign}/entity_types Entity types
/d/{domain}/x/{campaign}/partitions Partitions
/d/{domain}/x/{campaign}/relationships Relationships
/d/{domain}/x/{campaign}/sources Attestation sources
/d/{domain}/x/{campaign}/definitions Definitions
/d/{domain}/x/{campaign}/model Domain model graph
Sidebar Organisation
The sidebar groups pages by persona concern:
ALIGNMENT
Dashboard
Expectations
Questions
Actions
ACTORS
Expectors
Expectees
Attestors
DOMAIN
Model
Entity Sets
Entity Types
Partitions
Relationships
Attestations
Definitions
Switchers
The sidebar includes three context switchers:
- Domain switcher — navigates to new domain's overview
- Version switcher — reloads current page with different version
- Campaign switcher — navigates to equivalent page in new campaign, preserving
page_suffix
Page-Level Guidelines
Expectations Index
Each expectation card shows:
- Readable name and auto-generated description
- Expector (linked to expector detail page)
- Partition (linked to partition detail)
- Aligned/misaligned/unknown counts
- Question count (if > 0)
Removed: "Expects empty: is_false, is_void" — replaced by "Misaligned when" on the expectation detail definition section.
Expectation Detail
Section order (top to bottom):
- Header with status indicator border
- Summary counts (aligned, misaligned, unknown)
- Misaligned entities with reason chains inline
- Questions with reason chains inline
- Actions
- Aligned entities
- Definition (Expector, Partition, Expectee, Misaligned when)
- Domain context graph
Definition section labels:
- "Expector" (not "Expector")
- "Expectee" (not "Expectee")
- "Misaligned when" (not "Expects Empty")
Hidden from definition: Raw qualified names (expector_ref, partition_ref, expectee.path). Only human-readable resolved values are shown.
Entity Detail
Shows the entity's full evaluation picture:
- Expectations (misaligned first with reason chains, then aligned)
- Expectations held by this entity (expector role)
- Expectations this entity is responsible for (expectee role)
- Data fields with inline reason chains for unknown/void values
- Relationships with links to target entities
- Partitions with membership reason chains
- Reverse relationships
- Entity set membership reason chain
- Back link to parent entity set
Partition Detail
- Uses "Misaligned when:" instead of "Expects empty:"
- Uses "Entities are sorted into four branches based on the answer to this question" instead of "based on the predicate result"
- Branch names displayed via
| readablefilter
Actions Index
- Groups actions by expectee (not "expectee")
- Unassigned actions show readable traversal path (e.g., "entity → owner") not raw path (e.g.,
SELF->owner)
Questions Index
- Groups questions by attestor
- Questions phrased as "what is the {attribute}?" not "what is the value of '{attribute}'?"
- Context fields shown inline with entity links
Sources
- Source names shown via
| readablefilter (not rawfont-mono) - Entity set names shown via
| readablefilter
Relationships
- Page title and h1 use
| readableon entity set name - Relationship headers use
| readableon attribute and target names - Back link uses
| readable
Template Conventions
Macro imports with with context
When importing macros that reference template context variables (like url_prefix), always use with context:
{% from "partials/expectation_description.html" import expectation_description with context %}
Without with context, macros cannot access url_prefix and will generate broken links.
Entity set table column headers
Use | readable on field names in table headers so users see "has owner" instead of "has_owner".
Definition section in expectation detail
The definition section uses a 2-column grid (grid-cols-2) showing:
- Expector (resolved entity with link, or "Could not resolve" with reason chain)
- Partition (resolved with link to partition and source entity set)
- Expectee (resolved entity with link and readable traversal path)
- Misaligned when (branch badges with colour coding)
- Predicate source (code block, for campaign operators)
Status badges and colours
| Status | Colour | CSS class |
|---|---|---|
| Met | Green | text-known-true, bg-green-*, border-green-* |
| Not met | Red | text-void, bg-red-*, border-red-* |
| Uncertain | Amber | text-unknown, bg-amber-*, border-amber-* |
| Known true | Green | text-known-true |
| Known false | Grey/muted | text-known-false |
| Unknown value | Amber | text-unknown |
| Void value | Red | text-void |
Terminology note: "unknown" vs "uncertain"
These terms describe different things:
- "Unknown" describes data values where information is missing
- "Uncertain" describes expectation status when we can't determine if it's met
An expectation is "uncertain" because some underlying data is "unknown". Both terms are correct in their respective contexts.
WRIT Docs