feat/energia-ux
needs attentionviewing older commitbf33cdf · fullPR #301reviewed 2026-07-11 06:02 UTC2H · 6M · 6L · 5I- Purpose
- Design/UX exploration for a new Energía enterprise energy management module serving multi-site Mexican companies billed by CFE
- Goal
- Produce a 7-screen minimal prototype + JTBD map + design principles to validate the UX direction before implementation
- Sub-goals
- SG-1: Establish psychology-of-design principles (one anchor/screen, loss framing, progressive disclosure, Hick's Law)
- SG-2: Ground screen designs in a rigorous JTBD map covering Finance, FP&A, Operations, Procurement, ESG, and Executive stakeholders
- SG-3: Document detector verdict ledger — kill false-positive bill-audit detectors before they reach customers
- SG-4: Build 7-screen HTML prototype from a shared design system (ds.css) assembled by a build script
- What
- Added 15 new files under docs/design/: 3 design/research docs (principles, JTBD map, detector ledger), a screen-builder CONTRACT, a Node.js assembler script, a shared CSS design system, an app shell, 7 HTML screen fragments, and the assembled output
- Why
- Validate UX direction for a corporate energy management platform (Energía module) before committing engineering resources; establish shared design vocabulary and screen specification for agent-assisted parallel screen construction
- Areas
- docs/design/ (design docs)+604−0docs/design/energia-prototype/ (build infra: assembler, CSS, shell)+322−0docs/design/energia-prototype/screens/ (7 screen fragments)+1435−0docs/design/energia-prototype/energia-platform-full.html (assembled output)+1735−0
- Blast
- 15 new files, +4096 lines, all under docs/design/ — zero production code, zero schema changes, zero TypeScript. No blast radius on the running platform.
Findings · 17
correctness4
CONTRACT.md prose says 'Six screens' but 7 are specified and built
docs/design/energia-prototype/CONTRACT.md:3
Line 3: 'Six screens are built in parallel by different agents.' The screen list in the same file and assemble.mjs both enumerate 7 screens (portfolio, findings, budget, payments, site, carbon, sites). Off-by-one in the prose will confuse future agents reading the contract.
Assembled output renders in quirks mode — missing DOCTYPE, html, head, body
docs/design/energia-prototype/energia-platform-full.html:1
shell.html has no `<!DOCTYPE html>`, `<html>`, `<head>`, or `<body>` tags. The assembled file opens directly with `<title>`. Browsers fall back to quirks mode, which alters box-model behaviour and can break CSS custom property inheritance. Fix: wrap shell.html in `<!DOCTYPE html><html lang='es-MX'><head>…</head><body>…</body></html>`.
JTBD §3 lists 17 product screens; prototype covers 7 — selection rationale undocumented
docs/design/energia-jtbd-map.md:301
The JTBD map's §3 enumerates 17 distinct screens as the full product vision. The 7 prototype screens are a chosen subset but neither document explains the selection criteria or maps prototype slugs to JTBD screen numbers. A comment in CONTRACT.md cross-referencing the JTBD would prevent scope confusion.
`h2.sect` listed in CONTRACT.md allowed classes but not defined in ds.css
docs/design/energia-prototype/ds.css
CONTRACT.md rule 2 lists `h2.sect` as a composable class. Grepping ds.css for `.sect` returns no match. Screens that use `<h2 class='sect'>` receive plain unstyled `<h2>` rendering instead of the expected section-header treatment.
security2
Real brand name (Grupo Axo) used as persona with fabricated financials in committed prototype
docs/design/energia-prototype/shell.html
The prototype uses Grupo Axo (a real Mexican retailer) as the illustrative client, with invented but plausible figures ($45.26M MXN annual spend, $1.55M savings). No real PII or credentials present; repo is private and the UI labels it 'maqueta · datos ilustrativos'. Low risk as-is, but if the repo ever goes public this could be misread as disclosing a real engagement.
Static HTML prototype — no external requests, no XSS vectors, no credentials
docs/design/energia-prototype/
All security checks passed: zero external CDN/network URLs, no innerHTML/eval/document.write, all JS uses classList and setAttribute with hardcoded values, assemble.mjs reads from a fixed array with no path traversal, no real PII or credentials. The prototype is clean.
conventions3
Generated artifact `energia-platform-full.html` committed without gitignore entry
docs/design/energia-prototype/energia-platform-full.html
assemble.mjs writes this file as its output. No .gitignore entry exists for it. If a screen is edited without re-running the assembler, the committed output silently drifts from the sources. If committed intentionally as a shareable snapshot, add a `<!-- generated by assemble.mjs -->` header comment and document in CONTRACT.md.
Prototype token vocabulary (`--spend`, `--value`, `--ink`) undocumented as distinct from platform tokens
docs/design/energia-prototype/ds.css:1
Platform tokens use Shadcn/Radix semantics (`--primary`, `--accent`, `--card`). The prototype intentionally uses a different grammar and reserves green differently. CONTRACT.md should note that ds.css is NOT a 1:1 port to the platform — otherwise an implementer might assume the classes translate directly.
Design docs in English — appropriate for internal engineering/design artifacts
docs/design/energia-jtbd-map.md
CLAUDE.md's Spanish (es-MX) requirement applies to the marketing website (apps/web). Internal design/research docs in English are consistent with the project convention for developer communication. No issue.
tests2
No script or CI step to verify assemble.mjs runs clean after screen edits
docs/design/energia-prototype/assemble.mjs
assemble.mjs must be run manually; no package.json script or workflow invokes it. The built-in guards (ID check, style/script count) are good, but without a CI trigger the committed energia-platform-full.html can drift from sources silently. A one-liner npm script would make verification trivial.
assemble.mjs built-in guards are adequate — self-testing script
docs/design/energia-prototype/assemble.mjs:13
The script validates all 7 screen IDs, asserts exactly 1 `<style>` and 1 `<script>` in output, and throws loudly on violations. For a design prototype build tool, this is sufficient test coverage.
improvement6
Mobile nav hidden below 940px with no fallback — prototype unusable on tablet/phone
docs/design/energia-prototype/ds.css:237
`.side{display:none}` at 940px removes the entire sidebar with zero replacement — no hamburger, no bottom tab bar, no drawer. Every screen becomes inaccessible since screen-switching is sidebar-only. A sticky bottom tab strip with the 4 primary nav items would satisfy Hick's Law and fix the dead-end.
`fp_chronic_penalty` finding tagged 'Error CFE' with green — violates color grammar and detector taxonomy
docs/design/energia-prototype/screens/findings.html:165
The FP-penalty finding (FP 0.82, CEDIS Toluca) uses `<span class='tag cfe'>Error CFE</span>` and green coloring. Per the detector ledger, `fp_chronic_penalty` is Category B — operational (client action), not a recoverable CFE billing error. Green is reserved strictly for value Batu recovers. This misleads Finance users into thinking CFE owes them money. Correct tag: `.tag.ops` ('Optimización').
`.stats` and `.statgrid` are near-duplicate — `.stats .cell` is undefined, used in site.html
docs/design/energia-prototype/ds.css:122
Both classes share identical grid, gap, and s-v/s-l typography. The only difference is `.statgrid .cell` adds background/padding resets. `screens/site.html` uses `.stats > .cell` children whose styling is never defined. Merge into one component or explicitly define `.stats .cell` to avoid accidental layout dependency.
Carbon screen missing market-based Scope 2 figure — JTBD §4 item 14 unmet
docs/design/energia-prototype/screens/carbon.html:9
JTBD requires dual Scope 2 display: location-based and market-based side by side. The screen shows only the location-based anchor and mentions market-based only as a grey sub-caption with no number. For the IFRS S2 demo use-case, even a 'market-based: N/D — sin CELs' secondary stat would satisfy the dual-method requirement that is the prototype's stated differentiator.
Green (`--value`) applied to CFE error count in portfolio — color grammar violation
docs/design/energia-prototype/screens/portfolio.html:42
`<div class='k-v' style='color:var(--value)'>14</div>` colors the count '14 Errores de CFE' in green. Color grammar (CONTRACT.md rule 3, ds.css header) reserves green strictly for value Batu recovers — not for unresolved open findings. A user scanning quickly reads '14 (green)' as something completed/positive. Use `--ink` or `--warn` instead.
`energia-detector-ledger.md` misplaced in docs/design/ — it is an engineering product decision artifact
docs/design/energia-detector-ledger.md:1
The ledger records corpus backtesting verdicts with XML field references (`LECT_MANUAL`, `CANT_MED_RET`), sample counts, and kill/ship decisions for bill-audit detectors. This is engineering-facing, not UX-facing. Engineers working on domains/utility/ would not naturally look in docs/design/. Better home: docs/architecture/ or a pointer from the domain CLAUDE.md.