Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
363 commits
Select commit Hold shift + click to select a range
897f208
redesign(phase3): Battery Level Gauge (battery-radial-gauge)
atulmgupta Oct 22, 2026
9e11178
redesign(phase3): Battery Degradation Trend (battery-degradation-trend)
atulmgupta Oct 23, 2026
b62dcb6
chore(i18n): regenerate after Phase 3 wave 1 (battery)
atulmgupta Oct 23, 2026
cb7a52d
redesign(phase3): Projected Range (projected-range)
atulmgupta Oct 23, 2026
571bd47
redesign(phase3): Range Bar (range-bar)
atulmgupta Oct 23, 2026
58d3f03
redesign(phase3): Charge Cost Tracker (charge-cost-tracker)
atulmgupta Oct 23, 2026
6418186
redesign(phase3): Range Estimate (range-estimate)
atulmgupta Oct 23, 2026
b81a338
redesign(phase3): Energy Flow (energy-flow)
atulmgupta Oct 23, 2026
db81c97
chore(i18n): regenerate after Phase 3 wave 2 + checkpoint pinned widgets
atulmgupta Oct 23, 2026
c51fe02
wip: unverified handoff - recover four Phase 3 charging widgets
Copilot Oct 23, 2026
274ae6f
feat(dashboard): redesign route-efficiency widget
Copilot Oct 23, 2026
a741649
feat(dashboard): redesign regen-efficiency widget
Copilot Oct 23, 2026
73cb3ea
feat(dashboard): redesign weather-at-car widget
Copilot Oct 23, 2026
63b84d6
feat(dashboard): redesign energy-flow-animated widget
Copilot Oct 23, 2026
eefd843
feat(dashboard): redesign driving-coach widget
Copilot Oct 23, 2026
ca8f38d
feat(dashboard): redesign charge-plans widget
Copilot Oct 23, 2026
bcbd012
feat(dashboard): redesign sleep-efficiency widget
Copilot Oct 23, 2026
a938135
feat(dashboard): redesign vampire-drain widget
Copilot Oct 23, 2026
84769dd
feat(dashboard): redesign trip-summary widget
Copilot Oct 23, 2026
0c92ed7
feat(dashboard): redesign drive-score-gauge widget
Copilot Oct 23, 2026
670d5d2
feat(dashboard): redesign driving-dynamics widget
Copilot Oct 23, 2026
13ac140
feat(dashboard): redesign drive-efficiency-chart widget
Copilot Oct 23, 2026
d5cf46f
feat(dashboard): redesign drive-telemetry widget
Copilot Oct 23, 2026
51a0e1f
feat(dashboard): redesign speed-profile widget
Copilot Oct 23, 2026
c78f841
feat(dashboard): redesign cost-forecast widget
Copilot Oct 23, 2026
925c878
test(dashboard): update drive-telemetry continuation coverage
Copilot Oct 23, 2026
3afd3d0
feat(dashboard): redesign supercharger-history widget
Copilot Oct 23, 2026
721df67
feat(dashboard): redesign backup-history widget
Copilot Oct 23, 2026
c8614eb
feat(dashboard): redesign charge-status-live widget
Copilot Oct 23, 2026
50cba52
feat(dashboard): redesign climate-control-panel widget
Copilot Oct 23, 2026
60db7f7
feat(dashboard): redesign charging-telemetry widget
Copilot Oct 23, 2026
84d7238
feat(dashboard): redesign location-map widget
Copilot Oct 23, 2026
71aefd9
feat(dashboard): redesign wall-connector widget
Copilot Oct 23, 2026
0a08c39
feat(dashboard): redesign next-charge-decision widget
Copilot Oct 23, 2026
6df0b8b
feat(dashboard): redesign charge-session-chart widget
Copilot Oct 23, 2026
afa9b4f
feat(dashboard): redesign drive-score widget
Copilot Oct 23, 2026
ce3f0d8
feat(dashboard): redesign charging-session-detail widget
Copilot Oct 23, 2026
bb9d607
feat(dashboard): redesign power-flow-history widget
Copilot Oct 23, 2026
fdde9c8
feat(dashboard): redesign geofence-status widget
Copilot Oct 23, 2026
3343f94
feat(dashboard): redesign charging-schedule widget
Copilot Oct 23, 2026
57ea524
feat(dashboard): redesign charge-history widget
Copilot Oct 23, 2026
700a5bb
feat(dashboard): redesign position-heatmap widget
Copilot Oct 23, 2026
b4769d2
feat(dashboard): redesign live-power-flow widget
Copilot Oct 23, 2026
e390be3
feat(dashboard): redesign energy-stats widget
Copilot Oct 23, 2026
70e25a8
feat(dashboard): redesign climate-history widget
Copilot Oct 23, 2026
2180cde
feat(dashboard): redesign charging-optimizer widget
Copilot Oct 23, 2026
10689a5
feat(dashboard): redesign solar-production widget
Copilot Oct 23, 2026
3d3a804
feat(dashboard): redesign sentry-event-log widget
Copilot Oct 23, 2026
83bcf7b
feat(dashboard): redesign fleet-stats widget
Copilot Oct 23, 2026
9b002a4
feat(dashboard): redesign door-window-status widget
Copilot Oct 23, 2026
96f7afc
feat(dashboard): redesign command-history widget
Copilot Oct 23, 2026
1811484
feat(dashboard): redesign recent-drives-list widget
Copilot Oct 23, 2026
aace10d
feat(dashboard): redesign fleet-stats-bar widget
Copilot Oct 23, 2026
ea21c05
feat(dashboard): redesign destination-eta widget
Copilot Oct 23, 2026
768d400
feat(dashboard): redesign media-now-playing widget
Copilot Oct 23, 2026
8325319
feat(dashboard): redesign speed-heatmap widget
Copilot Oct 23, 2026
c52bea8
feat(dashboard): redesign media-history widget
Copilot Oct 23, 2026
f025c0e
feat(dashboard): redesign weekly-summary-card widget
Copilot Oct 23, 2026
de77aa9
feat(dashboard): redesign location-favorites widget
Copilot Oct 23, 2026
d6f8d9e
feat(dashboard): redesign tire-pressure-history widget
Copilot Oct 23, 2026
ad6fa7a
feat(dashboard): redesign command-quick-actions widget
Copilot Oct 23, 2026
c7aa9c1
feat(dashboard): redesign tire-pressure-visual widget
Copilot Oct 23, 2026
97d01e7
feat(dashboard): redesign lifetime-stats widget
Copilot Oct 23, 2026
1a8867d
feat(dashboard): redesign safety-history widget
Copilot Oct 23, 2026
79e15c3
feat(dashboard): redesign monthly-mileage widget
Copilot Oct 23, 2026
b909cd3
feat(dashboard): redesign alert-feed widget
Copilot Oct 23, 2026
0d6a9f9
feat(dashboard): redesign automation-status widget
Copilot Oct 23, 2026
7abd2cf
feat(dashboard): redesign notification-stats widget
Copilot Oct 23, 2026
98e4933
feat(dashboard): redesign state-timeline widget
Copilot Oct 23, 2026
805b9fe
feat(dashboard): redesign automation-history widget
Copilot Oct 23, 2026
8049404
feat(dashboard): redesign safety-features widget
Copilot Oct 23, 2026
f402614
feat(dashboard): redesign fsd-weekly widget
Copilot Oct 23, 2026
eaa9d28
feat(dashboard): redesign weekly-digest widget
Copilot Oct 23, 2026
64958be
feat(dashboard): redesign vehicle-access widget
Copilot Oct 23, 2026
58c527d
wip: unverified handoff - redesign charging-session-detail
Copilot Oct 23, 2026
91ee776
feat(dashboard): redesign software-update-status widget
atulmgupta Oct 23, 2026
e5aab65
feat(dashboard): redesign software-update-history widget
atulmgupta Oct 23, 2026
7199315
feat(dashboard): redesign odometer-counter widget
atulmgupta Oct 23, 2026
bfd12d2
feat(dashboard): redesign drivetrain-health widget
atulmgupta Oct 23, 2026
03bb105
feat(dashboard): redesign motor-performance widget
atulmgupta Oct 23, 2026
4853cc5
feat(dashboard): redesign motor-history widget
atulmgupta Oct 23, 2026
bd0681e
feat(dashboard): redesign vehicle-specs widget
atulmgupta Oct 23, 2026
ca7e55b
feat(dashboard): redesign energy-site-info widget
atulmgupta Oct 23, 2026
0ab2cd5
feat(dashboard): redesign guard-mode widget
atulmgupta Oct 23, 2026
f5093b6
feat(dashboard): redesign mileage-stats widget
atulmgupta Oct 23, 2026
879c989
feat(dashboard): redesign fsm-distribution widget
atulmgupta Oct 23, 2026
7479eda
feat(dashboard): redesign cost-breakdown widget
atulmgupta Oct 23, 2026
4e47c7a
feat(dashboard): redesign year-review widget
atulmgupta Oct 23, 2026
80dfb4a
feat(dashboard): redesign analytics-summary widget
atulmgupta Oct 23, 2026
8a763c4
feat(dashboard): redesign recently-unlocked-achievements widget
atulmgupta Oct 23, 2026
0ee6135
feat(dashboard): redesign live-signals widget
atulmgupta Oct 23, 2026
9983d19
feat(dashboard): redesign live-signal-sparklines widget
atulmgupta Oct 23, 2026
d777525
feat(dashboard): redesign signal-health widget
atulmgupta Oct 23, 2026
4100805
feat(dashboard): redesign signal-catalog widget
atulmgupta Oct 23, 2026
ef2a7c6
feat(dashboard): redesign signal-log widget
atulmgupta Oct 23, 2026
22a7d37
feat(dashboard): redesign uptime-monitor widget
atulmgupta Oct 23, 2026
b21fe10
feat(dashboard): redesign mqtt-status widget
atulmgupta Oct 23, 2026
6eacab2
feat(dashboard): redesign api-usage widget
atulmgupta Oct 23, 2026
bdd3a31
feat(dashboard): redesign system-health widget
atulmgupta Oct 23, 2026
777f338
feat(dashboard): redesign telemetry-errors widget
atulmgupta Oct 23, 2026
03bb7f6
feat(dashboard): redesign audit-log widget
atulmgupta Oct 23, 2026
e30adcf
feat(dashboard): redesign export-status widget
atulmgupta Oct 23, 2026
a4928e1
feat(dashboard): redesign version-info widget
atulmgupta Oct 23, 2026
e8e396c
feat(dashboard): redesign dashboard-stats widget
atulmgupta Oct 23, 2026
6db6a11
feat(dashboard): redesign vehicle-hero-card widget
atulmgupta Oct 23, 2026
2cee9a0
feat(dashboard): redesign backup-monitor widget
atulmgupta Oct 23, 2026
aeadfda
feat(dashboard): redesign vehicle-hero widget
atulmgupta Oct 23, 2026
aadc089
feat(dashboard): redesign watch-summary widget
atulmgupta Oct 23, 2026
6767dc2
feat(dashboard): redesign subscriptions widget
atulmgupta Oct 23, 2026
e4f2eaf
feat(dashboard): redesign vehicle-upgrades widget
atulmgupta Oct 23, 2026
782ebec
feat(dashboard): redesign range-estimate widget
atulmgupta Oct 23, 2026
92fe7c9
feat(dashboard): redesign range-bar widget
atulmgupta Oct 23, 2026
04d98e7
feat(dashboard): redesign battery-radial-gauge widget
atulmgupta Oct 23, 2026
0687b65
feat(dashboard): redesign battery-degradation-trend widget
atulmgupta Oct 23, 2026
198e8b5
feat(dashboard): redesign energy-flow widget
atulmgupta Oct 23, 2026
ce07262
feat(dashboard): redesign maintenance-tracker widget
atulmgupta Oct 23, 2026
86c1794
feat(dashboard): redesign warranty-status widget
atulmgupta Oct 23, 2026
db8e701
feat(dashboard): redesign anomaly-detector widget
atulmgupta Oct 23, 2026
3ecd790
fix(dashboard): repair widget Phase 4 type contracts
atulmgupta Oct 23, 2026
2a7508c
fix(dashboard): repair widget acceptance trust and empty states
Copilot Oct 23, 2026
f9f15cb
fix(dashboard): repair redesign widget acceptance contracts
Copilot Oct 23, 2026
fdabef4
fix(dashboard): repair widget source contracts
Copilot Oct 23, 2026
ddae0c5
fix(dashboard): repair widget phase four contracts
Copilot Oct 23, 2026
eb7f2d1
fix(dashboard): repair widget phase four source contracts
Copilot Oct 23, 2026
1b610f5
fix(dashboard): repair timeline and warranty contracts
Copilot Oct 23, 2026
cb85054
docs(queue): hand off widget Phase 4 blockers
atulmgupta Oct 23, 2026
64f86b2
fix(dashboard): repair backup history Phase 4 contract
atulmgupta Oct 23, 2026
8b03154
fix(dashboard): repair drivetrain health Phase 4 contract
atulmgupta Oct 23, 2026
b4b5306
fix(dashboard): repair warranty status Phase 4 contract
atulmgupta Oct 23, 2026
df8a027
fix(dashboard): repair automation and status grid Phase 4 contracts
atulmgupta Oct 23, 2026
7a523f0
fix(dashboard): preserve SI charging session detail contracts
atulmgupta Oct 23, 2026
248c9d1
Merge remote-tracking branch 'origin/feat/widget-redesign' into fix/p…
atulmgupta Oct 23, 2026
a0bfe54
docs(queue): merge widget track into one track
atulmgupta Oct 23, 2026
6f82c79
fix(dashboard): resolve Phase 4 worker repair batch
atulmgupta Oct 23, 2026
2b077de
fix(dashboard): repair verified Phase 4 widget clusters
atulmgupta Oct 23, 2026
823c880
fix(dashboard): repair maintenance and signal catalog widgets
Copilot Oct 23, 2026
16bf49e
fix(dashboard): repair charging system and warranty widgets
Copilot Oct 23, 2026
7b3fabb
test(dashboard): repair phase four widget clusters
Copilot Oct 23, 2026
6aa4d95
docs(queue): record recovery and dashboard gate
Copilot Oct 23, 2026
4d97148
fix(dashboard): remove legacy weekly energy fields
Copilot Oct 23, 2026
ebc0c9a
fix(dashboard): remove nonexistent vehicle state namespace lookup
Copilot Oct 24, 2026
47cec22
fix(dashboard): repair lint and chart guard findings
atulmgupta Oct 24, 2026
d31e666
fix(dashboard): add chart legend controls
atulmgupta Oct 24, 2026
ab52bd2
fix(dashboard): repair typography and freshness guards
atulmgupta Oct 24, 2026
2260748
chore(i18n): regenerate split catalog handoff
atulmgupta Oct 24, 2026
45ba799
chore(i18n): refresh frozen producer checkpoints
atulmgupta Oct 24, 2026
863980a
test(web): align dashboard checkpoint expectations
atulmgupta Oct 24, 2026
213c52c
fix(web): align kiosk accessible copy
atulmgupta Oct 24, 2026
4942dfa
docs(shared): add shared patterns plan and state
Copilot Oct 24, 2026
911709f
refactor(shared): add canonical beta statistics module
Copilot Oct 24, 2026
772a233
refactor(shared): add canonical charger site identity
Copilot Oct 24, 2026
e2ce661
refactor(shared): add canonical HTTP identity helpers
Copilot Oct 24, 2026
892035d
refactor(shared): add canonical validation contracts
Copilot Oct 24, 2026
020c18c
refactor(shared): add canonical ML statistics
Copilot Oct 24, 2026
fa37d3b
refactor(shared): add strict SLO catalog parser
Copilot Oct 24, 2026
d6db557
refactor(shared): add canonical CSV validation
Copilot Oct 24, 2026
f32bdeb
refactor(shared): add shared frontend test fixtures
Copilot Oct 24, 2026
db9d151
refactor(shared): consolidate React test harness utilities
Copilot Oct 24, 2026
9ce805a
test(shared): add shared pattern guard scripts
Copilot Oct 24, 2026
64f9eb1
docs(shared): record completed Phase 1 modules
Copilot Oct 24, 2026
aad7485
refactor(shared): adopt beta statistics in firmware impact
Copilot Oct 24, 2026
965c20d
refactor(shared): adopt shared charger site identity
Copilot Oct 24, 2026
85817ed
refactor(shared): adopt prompt validation contracts
Copilot Oct 24, 2026
261b0e2
refactor(shared): adopt canonical CSV export validation
Copilot Oct 24, 2026
6397bc7
refactor(shared): adopt HTTP identity helper in audit paths
Copilot Oct 24, 2026
132c5b5
refactor(shared): adopt canonical ML statistics
Copilot Oct 24, 2026
ddf12a1
refactor(shared): expand canonical icon registry
Copilot Oct 24, 2026
a8cb693
docs(shared): record Phase 2 call-site progress
Copilot Oct 24, 2026
2254834
fix(shared): remove unused icon and harness fields
Copilot Oct 24, 2026
0e7c9df
fix(shared): satisfy package architecture guards
Copilot Oct 24, 2026
55faa83
docs(shared): record final verification state
Copilot Oct 24, 2026
f542d60
feat(web): refresh chart color palette tokens
Copilot Oct 24, 2026
a82b0af
docs(web): document chart palette and add preview swatches
atulmgupta Oct 24, 2026
e65d2b8
refactor(web): switch charts to shared palette tokens
atulmgupta Oct 24, 2026
bc94618
fix(web): harden shared pattern test setup
Copilot Oct 24, 2026
d8b91a4
docs(web): capture chart palette route review
atulmgupta Oct 25, 2026
dc0b826
refactor(shared): adopt strict SLO parser call sites
Copilot Oct 25, 2026
066c8cf
refactor(shared): adopt canonical date patterns
Copilot Oct 25, 2026
69b059b
refactor(shared): harden canonical backend helpers
Copilot Oct 25, 2026
81cb608
refactor(shared): adopt canonical unit conversions
Copilot Oct 25, 2026
d2b0f28
refactor(shared): adopt canonical query patterns
Copilot Oct 25, 2026
01c58c6
refactor(shared): adopt validation contracts broadly
Copilot Oct 25, 2026
dde0589
feat(shared): add canonical TOU and charge window engine
Copilot Oct 25, 2026
79600c4
refactor(shared): adopt admin icons and UI primitives
Copilot Oct 25, 2026
0ec2f87
refactor(shared): adopt canonical test harnesses
Copilot Oct 25, 2026
b4da448
refactor(shared): adopt AI and settings fixtures
Copilot Oct 25, 2026
719faf7
refactor(shared): adopt canonical HTTP identity wrappers
Copilot Oct 25, 2026
dab8ab3
test(shared): pin TOU planner autopilot parity
Copilot Oct 25, 2026
6f881f0
test(shared): tighten category guards and state accounting
Copilot Oct 25, 2026
8d26e38
fix(shared): resolve final gate lint and doc errors
Copilot Oct 25, 2026
61c25a1
feat(web): migrate data and status colors to palette tokens
Copilot Oct 25, 2026
8a83ce0
chore(shared): record final gate verification state
Copilot Oct 25, 2026
96ad7e9
feat(web): refine chart palette with vivid professional colors
Copilot Oct 25, 2026
0c81f26
fix(i18n): re-pin presentation-migrated producer checkpoints
Copilot Oct 25, 2026
d821743
docs(shared): record merge-base E2E attribution
atulmgupta Oct 25, 2026
6f03f7e
fix(shared): clear branch-only lint and mutation gates
Copilot Oct 25, 2026
c199554
revert(shared): drop startup icon registry adoption item
Copilot Oct 25, 2026
e69d34a
fix(i18n): restore direct-icon presentation checkpoints
Copilot Oct 25, 2026
c2d4ae5
docs(shared): record frozen-contract and CI attribution completion
Copilot Oct 25, 2026
a230888
fix(web): finish recovered Zod 4 compatibility upgrade
atulmgupta Oct 25, 2026
b235484
merge: integrate shared patterns before combined followups
atulmgupta Oct 25, 2026
11d3fd5
merge: integrate chart palette with shared conversion patterns
atulmgupta Oct 25, 2026
0f45d02
refactor(web): use canonical helpers for remaining feature conversions
atulmgupta Oct 25, 2026
725355f
fix(web): correct timezone visibility and hero battery semantics
atulmgupta Oct 25, 2026
54a115d
fix(web): preserve palette contracts and distinct chart signals
atulmgupta Oct 25, 2026
354deb1
docs: record merge repair results and clean handoff
atulmgupta Oct 25, 2026
e71d532
fix(web): remove redundant climate and vehicle zone captions
atulmgupta Oct 25, 2026
54ade03
perf(web): keep route-only query modules outside startup
atulmgupta Oct 25, 2026
9c6fbb9
fix(web): preserve accessible readings in redesigned vehicle heroes
atulmgupta Oct 25, 2026
ec53fca
docs: record verified repairs and incomplete replica handoff
atulmgupta Oct 25, 2026
2f6aba7
fix(web): contain cost chart and align exact CI contracts
atulmgupta Oct 25, 2026
d2c6d9f
fix(web): honor departure zone and disclose source bounds once
atulmgupta Oct 25, 2026
03a5484
test(web): bind charging evidence to the exact current source
atulmgupta Oct 25, 2026
80e71dd
test(web): assert exact weekly readings through recovery states
atulmgupta Oct 25, 2026
bfecead
test(web): refresh reviewed Windows redesign snapshots
atulmgupta Oct 25, 2026
065314d
docs: record read-only Windows baseline verification
atulmgupta Oct 25, 2026
664b02a
fix(web): reserve chart caption and legend height
atulmgupta Oct 25, 2026
f57f163
fix(web): localize requested location and parking windows
atulmgupta Oct 25, 2026
3ca29a4
docs: hand off ten verified CI repair fixes
atulmgupta Oct 25, 2026
6092735
fix(web): bound chart allocations and preserve measured reference
atulmgupta Oct 25, 2026
3206414
fix(web): clean up toast dismissal timers on provider teardown
atulmgupta Oct 25, 2026
2d7cd8f
fix(web): restore measured dashboard charts and bounded layouts
atulmgupta Oct 25, 2026
f943f3c
test(web): bind source drawers to localized date contracts
atulmgupta Oct 25, 2026
55fe660
fix(web): preserve localized day-ledger interval provenance
atulmgupta Oct 25, 2026
f6ab2f3
test(web): require saved timezone in exact cost forecast source query
atulmgupta Oct 25, 2026
fd3c156
fix(web): localize advisor business dates without shifting scenarios
atulmgupta Oct 25, 2026
bc841f3
fix(web): preserve localized notification interval provenance
atulmgupta Oct 25, 2026
b4c9429
fix(web): allocate full signal rows to history recovery
atulmgupta Oct 25, 2026
7fbfb8a
test(web): bind fleet layouts to native posture evidence
atulmgupta Oct 25, 2026
98e23be
wip: signal catalogue - native observer binding remains unverified
atulmgupta Oct 25, 2026
e53cd34
fix(web): restore native catalogue source and layout contracts
atulmgupta Oct 25, 2026
6d1e451
fix(web): preserve header layout and native widget precision
atulmgupta Oct 25, 2026
c1ceae7
test(web): restore native vehicle catalogue coverage
atulmgupta Oct 25, 2026
000dcd1
fix(web): apply selected clock to home energy planning
atulmgupta Oct 25, 2026
33b7c01
fix(web): preserve timestamp meaning without redundant zone captions
atulmgupta Oct 25, 2026
3117522
fix(web): group milestone months in the selected calendar
atulmgupta Oct 25, 2026
a1723ab
test(web): regenerate verified catalog addition receipts
atulmgupta Oct 25, 2026
968047c
fix(api): group automation history by the selected clock
atulmgupta Oct 25, 2026
47b4fa5
fix(web): account for utilization in the selected calendar
atulmgupta Oct 25, 2026
4922899
fix(api): honor selected-calendar queued export bounds
atulmgupta Oct 25, 2026
98cbb1a
fix(web): preserve exact selected-clock sleep windows
atulmgupta Oct 25, 2026
e5174b3
fix(api): score insurance exposure in the selected clock
atulmgupta Oct 25, 2026
5be78d1
test(web): pin selected-clock sleep and planning contracts
atulmgupta Oct 25, 2026
02d31f2
test(web): verify redesigned quick-action catalogue controls
atulmgupta Oct 25, 2026
dae94b1
fix(web): align remaining health and mileage calendar evidence
atulmgupta Oct 26, 2026
4b24bb6
fix(api): group observed Tesla usage in the selected calendar
atulmgupta Oct 26, 2026
39bf131
fix(web): preserve certificate calendar facts in localized passport e…
atulmgupta Oct 26, 2026
3ae15d4
test(web): pin fixed-calendar passport presentation contracts
atulmgupta Oct 26, 2026
25d47ba
test(web): drain mocked dashboard documents before closing
atulmgupta Oct 26, 2026
6ca0774
docs: record green PR 202 source gate and deferred follow-ups
atulmgupta Oct 26, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
304 changes: 6 additions & 298 deletions cmd/slogen/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,48 +21,19 @@
package main

import (
"bufio"
"fmt"
"os"
"regexp"
"strconv"
"strings"
)

const (
requiredVersion = 1
indentUnit = " "
"github.com/ev-dev-labs/teslasync/internal/slo/catalogparser"
)

// Catalog mirrors the strict YAML subset described above and the JSON
// Schema in slo/catalog.schema.json.
type Catalog struct {
Version int
SLOs []SLO
}
type Catalog = catalogparser.Catalog

type SLO struct {
Name string
Description string
SLI SLI
Objective float64
Window string
Owner string
FastBurnSeverity string
Tags []string
type SLO = catalogparser.SLO

line int // 1-based line number of the `- name:` marker, used in errors.
}

type SLI struct {
GoodEvents string
ValidEvents string
}

var (
nameRE = regexp.MustCompile(`^[a-z][a-z0-9_]*$`)
windowRE = regexp.MustCompile(`^[0-9]+[mhdw]$`)
)
type SLI = catalogparser.SLI

func main() {
if len(os.Args) < 2 {
Expand Down Expand Up @@ -116,272 +87,9 @@ func validateFile(path string) error {
}

func validateCatalog(c *Catalog) error {
if c.Version != requiredVersion {
return fmt.Errorf("version: got %d want %d", c.Version, requiredVersion)
}
if len(c.SLOs) == 0 {
return fmt.Errorf("slos: at least one entry required")
}
seen := make(map[string]struct{}, len(c.SLOs))
for i, s := range c.SLOs {
if err := validateSLO(i, s); err != nil {
return err
}
if _, dup := seen[s.Name]; dup {
return fmt.Errorf("slos[%d] (line %d).name: %q duplicates earlier entry", i, s.line, s.Name)
}
seen[s.Name] = struct{}{}
}
return nil
return catalogparser.Validate(c)
}

func validateSLO(idx int, s SLO) error {
tag := func(field string) string {
return fmt.Sprintf("slos[%d] (line %d).%s", idx, s.line, field)
}
if !nameRE.MatchString(s.Name) {
return fmt.Errorf("%s: %q must match %s", tag("name"), s.Name, nameRE)
}
if len(s.Description) < 10 {
return fmt.Errorf("%s: must be >= 10 chars", tag("description"))
}
if s.SLI.GoodEvents == "" {
return fmt.Errorf("%s: required", tag("sli.good_events"))
}
if s.SLI.ValidEvents == "" {
return fmt.Errorf("%s: required", tag("sli.valid_events"))
}
if s.Objective <= 0 || s.Objective >= 100 {
return fmt.Errorf("%s: %v must be in (0, 100)", tag("objective"), s.Objective)
}
if !windowRE.MatchString(s.Window) {
return fmt.Errorf("%s: %q must match %s", tag("window"), s.Window, windowRE)
}
if s.Owner == "" {
return fmt.Errorf("%s: required", tag("owner"))
}
if s.FastBurnSeverity != "" && s.FastBurnSeverity != "page" && s.FastBurnSeverity != "ticket" {
return fmt.Errorf("%s: %q must be page or ticket", tag("fast_burn_severity"), s.FastBurnSeverity)
}
tagSet := make(map[string]struct{}, len(s.Tags))
for _, t := range s.Tags {
if t == "" {
return fmt.Errorf("%s: empty tag forbidden", tag("tags"))
}
if _, dup := tagSet[t]; dup {
return fmt.Errorf("%s: duplicate %q", tag("tags"), t)
}
tagSet[t] = struct{}{}
}
return nil
}

// parseCatalog implements a small, strict YAML parser tailored to the
// catalogue layout. The parser rejects any structure that does not match
// the documented subset (no block scalars, no flow maps, two-space
// indentation only).
func parseCatalog(text string) (*Catalog, error) {
c := &Catalog{}
scanner := bufio.NewScanner(strings.NewReader(text))
scanner.Buffer(make([]byte, 0, 64*1024), 1<<20)

versionSeen := false
inSLOs := false
var current *SLO
var inSLI bool
lineNum := 0

for scanner.Scan() {
lineNum++
raw := scanner.Text()
line := stripComment(raw)
if strings.TrimSpace(line) == "" {
continue
}

// Top-level keys: version: / slos:
if !strings.HasPrefix(line, " ") {
head, val, _ := strings.Cut(line, ":")
head = strings.TrimSpace(head)
val = strings.TrimSpace(val)
switch head {
case "version":
if val == "" {
return nil, fmt.Errorf("line %d: version requires a value", lineNum)
}
v, err := strconv.Atoi(val)
if err != nil {
return nil, fmt.Errorf("line %d: version: %w", lineNum, err)
}
c.Version = v
versionSeen = true
inSLOs = false
current = nil
case "slos":
if val != "" {
return nil, fmt.Errorf("line %d: slos must be a block mapping (no inline value)", lineNum)
}
inSLOs = true
current = nil
default:
return nil, fmt.Errorf("line %d: unknown top-level key %q", lineNum, head)
}
continue
}

if !inSLOs {
return nil, fmt.Errorf("line %d: indented content outside slos block", lineNum)
}

// Item start: ` - name: <value>`
if strings.HasPrefix(line, indentUnit+"- ") {
if current != nil {
c.SLOs = append(c.SLOs, *current)
}
rest := strings.TrimPrefix(line, indentUnit+"- ")
head, val, _ := strings.Cut(rest, ":")
head = strings.TrimSpace(head)
val = unquote(strings.TrimSpace(val))
if head != "name" {
return nil, fmt.Errorf("line %d: SLO item must start with `- name:`, got %q", lineNum, head)
}
current = &SLO{Name: val, line: lineNum}
inSLI = false
continue
}

if current == nil {
return nil, fmt.Errorf("line %d: SLO field before any `- name:`", lineNum)
}

// Field lines must use 4-space indentation (one level deeper than `-`).
const fieldIndent = indentUnit + indentUnit
const subFieldIndent = fieldIndent + indentUnit

if strings.HasPrefix(line, subFieldIndent) {
if !inSLI {
return nil, fmt.Errorf("line %d: nested field outside `sli:` not supported", lineNum)
}
rest := strings.TrimPrefix(line, subFieldIndent)
head, val, _ := strings.Cut(rest, ":")
head = strings.TrimSpace(head)
val = unquote(strings.TrimSpace(val))
switch head {
case "good_events":
current.SLI.GoodEvents = val
case "valid_events":
current.SLI.ValidEvents = val
default:
return nil, fmt.Errorf("line %d: unknown sli field %q", lineNum, head)
}
continue
}

if !strings.HasPrefix(line, fieldIndent) {
return nil, fmt.Errorf("line %d: unexpected indentation %q", lineNum, line)
}

rest := strings.TrimPrefix(line, fieldIndent)
head, val, _ := strings.Cut(rest, ":")
head = strings.TrimSpace(head)
val = strings.TrimSpace(val)

switch head {
case "description":
current.Description = unquote(val)
inSLI = false
case "sli":
if val != "" {
return nil, fmt.Errorf("line %d: sli must be a block mapping (no inline value)", lineNum)
}
inSLI = true
case "objective":
f, err := strconv.ParseFloat(val, 64)
if err != nil {
return nil, fmt.Errorf("line %d: objective: %w", lineNum, err)
}
current.Objective = f
inSLI = false
case "window":
current.Window = unquote(val)
inSLI = false
case "owner":
current.Owner = unquote(val)
inSLI = false
case "fast_burn_severity":
current.FastBurnSeverity = unquote(val)
inSLI = false
case "tags":
tags, err := parseInlineArray(val)
if err != nil {
return nil, fmt.Errorf("line %d: tags: %w", lineNum, err)
}
current.Tags = tags
inSLI = false
default:
return nil, fmt.Errorf("line %d: unknown SLO field %q", lineNum, head)
}
}
if err := scanner.Err(); err != nil {
return nil, fmt.Errorf("scan: %w", err)
}
if current != nil {
c.SLOs = append(c.SLOs, *current)
}
if !versionSeen {
return nil, fmt.Errorf("missing top-level version key")
}
return c, nil
}

func stripComment(line string) string {
// A `#` outside a quoted string starts a comment. Walk the line and
// honour double-quoted scalars (the only quoting style the catalogue
// uses) so a `#` inside a PromQL label value is preserved.
out := make([]byte, 0, len(line))
inQuote := false
for i := 0; i < len(line); i++ {
ch := line[i]
if ch == '"' && (i == 0 || line[i-1] != '\\') {
inQuote = !inQuote
}
if ch == '#' && !inQuote {
break
}
out = append(out, ch)
}
return strings.TrimRight(string(out), " \t\r")
}

func unquote(v string) string {
if len(v) >= 2 && v[0] == '"' && v[len(v)-1] == '"' {
s, err := strconv.Unquote(v)
if err == nil {
return s
}
}
if len(v) >= 2 && v[0] == '\'' && v[len(v)-1] == '\'' {
return v[1 : len(v)-1]
}
return v
}

func parseInlineArray(v string) ([]string, error) {
v = strings.TrimSpace(v)
if v == "" {
return nil, nil
}
if v[0] != '[' || v[len(v)-1] != ']' {
return nil, fmt.Errorf("expected inline array `[a, b]`, got %q", v)
}
body := strings.TrimSpace(v[1 : len(v)-1])
if body == "" {
return []string{}, nil
}
parts := strings.Split(body, ",")
out := make([]string, 0, len(parts))
for _, p := range parts {
out = append(out, unquote(strings.TrimSpace(p)))
}
return out, nil
return catalogparser.Parse(text)
}
4 changes: 3 additions & 1 deletion cmd/slogen/main_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import (
"path/filepath"
"strings"
"testing"

"github.com/ev-dev-labs/teslasync/internal/slo/catalogparser"
)

func TestValidateRealCatalog(t *testing.T) {
Expand Down Expand Up @@ -153,7 +155,7 @@ func TestValidateCatalog_BadFastBurnSeverity(t *testing.T) {

func TestStripComment_PreservesHashInsideQuotes(t *testing.T) {
t.Parallel()
got := stripComment(`good_events: "rate(x{tag=\"#foo\"}[5m])" # tail`)
got := catalogparser.StripComment(`good_events: "rate(x{tag=\"#foo\"}[5m])" # tail`)
want := `good_events: "rate(x{tag=\"#foo\"}[5m])"`
if got != want {
t.Fatalf("got %q, want %q", got, want)
Expand Down
26 changes: 11 additions & 15 deletions docs/.vitepress/config.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,10 @@
import { defineConfig } from 'vitepress'
import { withMermaid } from 'vitepress-plugin-mermaid'

// teslasync.dev serves the site from /. Forks without a custom domain can
// set DOCS_BASE to their GitHub Pages project path (e.g. /teslasync/).
const base = process.env.DOCS_BASE || '/'

export default withMermaid(defineConfig({
export default defineConfig({
title: 'TeslaSync Docs',
titleTemplate: ':title — TeslaSync Docs',
description:
Expand Down Expand Up @@ -76,6 +75,15 @@ export default withMermaid(defineConfig({
},

markdown: {
config(md) {
const fence = md.renderer.rules.fence!
md.renderer.rules.fence = (tokens, index, options, env, self) => {
if (tokens[index].info.trim() === 'mermaid') {
return `<MermaidDiagram :source="${md.utils.escapeHtml(JSON.stringify(tokens[index].content))}" />`
}
return fence(tokens, index, options, env, self)
}
},
theme: { light: 'github-light', dark: 'github-dark' },
image: { lazyLoading: true },
},
Expand Down Expand Up @@ -219,16 +227,4 @@ export default withMermaid(defineConfig({
lastUpdatedText: 'Updated',
},

mermaid: {
theme: 'neutral',
themeVariables: {
fontFamily: 'Inter, ui-sans-serif, system-ui, sans-serif',
primaryColor: '#f5f4f0',
primaryTextColor: '#1c1917',
primaryBorderColor: '#e82127',
lineColor: '#78716c',
secondaryColor: '#fafaf9',
tertiaryColor: '#ffffff',
},
},
}))
})
Loading
Loading