diff --git a/docs/design-system.md b/docs/design-system.md index 007304d..9e5d50f 100644 --- a/docs/design-system.md +++ b/docs/design-system.md @@ -23,6 +23,8 @@ Zaati OS is a decision interface, not a marketing dashboard. Repeated facts belong in a table or row. Empty cards, decorative KPIs, arbitrary bold text, and chart-shaped wallpaper do not belong. +Long lists and tables disclose an initial decision-sized set, with the remaining validated content available on demand. Metric values wrap without truncation. Line charts use a data-relative domain so meaningful change stays visible; categorical bar charts retain a zero baseline. + Complexity should come from hierarchy, not ornament. Use `dashboard` for a dominant view plus supporting evidence, `focus` for one leading decision, and `timeline` for a narrow sequence. A block may span one, two, or all dashboard columns. Do not simulate complexity with nested cards, arbitrary component trees, or repeated metrics. ## Components diff --git a/docs/llm-contract.md b/docs/llm-contract.md index 1e26ed0..171975c 100644 --- a/docs/llm-contract.md +++ b/docs/llm-contract.md @@ -45,6 +45,8 @@ Each source-specific domain schema requires stable `data.facts`. Facts carry dur | `notice` | One caveat, risk, or insight | Repeating normal content | | `text` | Short analysis that loses meaning when structured | Executable Markdown or HTML | +Calendar events that cover a date without a meaningful time should set `all_day: true`. Keep the required ISO `start` and optional `end` values for ordering and provenance; the renderer presents the event as “All day” instead of inventing a midnight appointment. + ## Safety limits The schema rejects unknown properties and limits block, row, point, item, series, text, and URL sizes. Links require HTTPS. Snapshots cannot contain scripts, HTML execution, private-key blocks, secret-shaped values, authentication links, raw messages, or source-specific forbidden content. Validation reports field paths and rule names without repeating the suspect value. The app never evaluates snapshot text. diff --git a/schemas/ui-blocks.schema.json b/schemas/ui-blocks.schema.json index 3448f36..0f1bbc3 100644 --- a/schemas/ui-blocks.schema.json +++ b/schemas/ui-blocks.schema.json @@ -184,6 +184,7 @@ "title": { "type": "string", "minLength": 1, "maxLength": 120 }, "start": { "type": "string", "format": "date-time" }, "end": { "type": "string", "format": "date-time" }, + "all_day": { "type": "boolean" }, "location": { "type": "string", "maxLength": 100 }, "tone": { "$ref": "#/$defs/tone" } } diff --git a/src/App.tsx b/src/App.tsx index 5fd9bb6..8eee83c 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -260,7 +260,7 @@ function DashboardApp({ data }: { data: DashboardData }) { onSelect={select} selectedId={selectedId} /> -
+
-
+
{selectedId === START_ID ? ( }>
-
+

{snapshot.data.title}

{snapshot.data.summary}

- + -
+
+ {snapshot.quality.warnings.length ? ( +
+

Evidence notes

+
    + {snapshot.quality.warnings.map((warning) => ( +
  • +
  • + ))} +
+
+ ) : null}
Generated
{formatTimestamp(snapshot.generated_at, instance)}
@@ -640,27 +658,14 @@ function DashboardPage({
- {snapshot.quality.warnings.length ? ( -
- -
-

Evidence note

- {snapshot.quality.warnings.map((warning) => ( -

- {warning} -

- ))} -
-
- ) : null} -
+
{snapshot.data.presentation.blocks.map((block, index) => ( ))}