Claude Code Worklog RSS

Development worklog entries from Claude Code sessions

[agentic-framework] 2026-07-08: Thermostat reset — human-in-the-loop webhook report (feature/thermostat-reset, v1.5.0)
Wed, 08 Jul 2026

Merged PR #14 (thermostat v1.4.2) and PR #15 (account-name fix) to master; tagged framework

v1.2.5. Started feature/thermostat-reset off master for the reset workflow.

Design (agreed with Barry): report by default, act only when a config flag is set.

no email path exists in the framework and a webhook needs no new infra.

write:deviceSettings (added in the next commit), so a resettable deploy carries editor and the

flag gates behavior.

Report-first (this commit, read-only): when reset candidates are found, POST { text, candidates }

to report_webhook_url (Slack renders text; forwarder parses candidates); log-only if unset; a

webhook failure doesn't fail the run. Pure buildReport() unit-tested; thin postReport() fetch

wrapper. Manifest stays viewer. 41 tests pass.

Validated the report against a real Slack webhook (Barry supplied an incoming-webhook URL):

posted a sample built by the real buildReport() — HTTP 200/ok, renders correctly. Then added

asset links per candidate: https://<subdomain>.ubxsystems.com/assets/<uuid> (subdomain =

environment, except production → app); Slack links the thermostat name (<url|name>), and the

structured candidates array carries a plain url. 42 tests pass.

do_resets write path (v1.6.0): when runtime.config.do_resets === true, reset each

candidate by resuming its schedule plan — a single updateDeviceSettings(assetUuid,

{ plan_event }, force: true) downlink. Key finding from the sbp-mono WT201 v2 encoders (which

overrode Barry's earlier "set setpoints + resume" idea): switch_schedule_plan makes the device

re-apply that plan's setpoints itself, and **explicitly writing setpoints is what *creates* an

override** — so the reset is plan_event ONLY. plan_event accepts only WAKE/AWAY/HOME/SLEEP;

OCCUPIED/UNOCCUPIED/ECO candidates are skipped+flagged. Per-candidate outcome (done/failed/

unsupported) rendered in the report; manifest → role: editor + write:deviceSettings. Pure

resetPlanFor + report rendering unit-tested (44 pass). do_resets defaults false → default stays

read-only. Committed + pushed; published v1.6.0 to staging (Barry deployed with do_resets:true +

webhook).

accepted WAKE/AWAY/HOME/SLEEP (so OCCUPIED/UNOCCUPIED/ECO overrides can't be reset — the agent

skips them). The device + driver already support all seven (schedule_plans "last 3 only valid

for tstat2"), so this was a GraphQL-layer oversight. Opened a draft PR widening PLANS to the

full seven + a self-contained encoder unit test. Note: the strawberry-gql backend lives on

develop/feature/macos_support, NOT master (master is ~11k commits behind, old graphql/

server) — made the change via an isolated worktree off origin/develop.

agent resets OCCUPIED/UNOCCUPIED/ECO overrides too (only skips a candidate whose plan can't be

identified). Committed + pushed but not published — deploy only after PR #879 is live;

against an older backend those three resets fail at the API (caught + reported, not fatal).

est. ≈X kWh / ~$Y saved. Coarse by design — only the wasteful override direction counts;

est_kWh = 0.015 kWh/°F·h/1000ft² × Δ°F × hours × zone/1000, flat 2000 ft² zone (≈0.03×Δ°F×h),

hours = time until schedule resumes (minutesUntilNextTransition), $0.13/kWh. Sources: DOE ~1%/°F

rule + DOE Medium Office prototype, EIA CBECS 2018, EIA 2024 commercial rate (researched + cited).

Gauge/cumulative, not precise; refined later. New pure minutesUntilNextTransition +

estimateSavings (unit-tested, 50 pass). Validated the rendered line in Slack. These numbers

become the thermostat.override_reset payload for the planned detected_event store.

vs ~$0.91 — same Δ°F, so the gap was entirely the "time until next plan" window (7356's next

plan ~40 min out, 1511's ~5 days out on a sparse schedule). Unbounded window ballooned it. Fix:

cap the avoided window at 24h (cappedWindowHours) and surface the inputs — the report line now

shows (Δ°F off, ~Nh) and a per-candidate debug log carries expected/actual/window/savings. 52

tests pass. Also confirmed do_resets' reset-write path fires on staging (both resumed WAKE).

Published v1.7.1 to staging.

iterating — read-only detection + Slack reports + savings, no device writes (so the #879

dependency is moot for report-only). First prod publish of this agent, from the unmerged

feature/thermostat-reset branch (merge before it's a settled prod deploy). Flagged: the build

carries role: editor (unused while do_resets false) — offered a viewer-only prod build for

least privilege while iterating. Pushed back on enabling do_resets in prod: the reset write path

hasn't been confirmed even on staging yet.

(keep status/resolved_at; recordDetectedEvent mutation; table detected_event). A

type-discriminated event store: type + JSONB data + first-class indexed

account/building/asset/source/occurred_at, promoted estimated_kwh_savings/estimated_usd_savings

(default 0) + savings_estimated_at (backfilled later by an estimator), status/resolved_at

for ongoing conditions (short-cycling). Mirrored the ui_preference vertical slice: DDL in

create-ubx-tables.sql + hand-run migrations/add-detected-event.sql (no migration framework);

recordDetectedEvent mutation + detectedEvents query; data-access in hvac2/ubx/detected_event.py;

role-based permission YAML entries (record = >=editor, read = any account access); 7 unit tests

(isolation-safe). Built on an isolated worktree off origin/develop; feature/macos_support untouched.

First producer will be thermostat-schedule-checker's thermostat.override_reset events. Migration

is hand-run per cluster before the mutation is usable there.

## Publish state (as of 2026-07-10)

do_resets:false)**. Local branch feature/thermostat-reset (v1.7.0) is unmerged. Framework tag

v1.2.5 on master. Open PRs: agentic-framework #14 (thermostat detection, merged), sbp-mono #879

(widen v2 PLANS), sbp-mono #880 (detected_event).

[agentic-framework] 2026-07-07: Thermostat checker — plan_event was read from the wrong blob (PR #14, v1.4.1)
Tue, 07 Jul 2026

Every online v2 thermostat came back overridden/no_schedule and we never once saw

ok/out_of_sync. Chased two wrong hypotheses first (transition-based history; then

"asset plan_event is unreliable, pivot to propertyHistory") — both wrong. Real root cause,

verified against sbp-mono (ubx_device_property_category table + the buildingAssets

resolver): the backend categorizes plan_event and the live fan_mode as settings

properties, not properties. The agent read them from the properties blob, always got

undefined, and treated every device as "not running the schedule". The setpoint temps

(heating_/cooling_target_temperature) really are in properties, so those were fine.

data was in hand). No query change, no history pivot.

category table, not by "live vs config" — plan_event/fan_mode live in settings.

staging. Diagnosed via a browser-console propertyHistory query (7356 showed SLEEP→WAKE, zero

NOT EXECUTED — it was never overridden) + an sbp-mono resolver deep-dive. Debugging lesson:

confirm which blob a property lives in before trusting a source-derived doc.

H:MM shape + bounds via regex (incomplete/out-of-range times returned NaN and slipped past

findActiveBank's null guard); plan_event case normalized once so NOT EXECUTED matches

case-insensitively like the running plans; overrideDuration error path returns samples: 0 for a

consistent output shape. +2 regression tests (40 pass).

Barry manually overrode 7356 and watched the duration track across runs: overriddenForMinutes

5 → 65 over one hour (exact, from the plan_event history transition), correctly flipping from

info (under 30) to a reset candidate WARN at 65 min (activeBank: 3 = the SLEEP bank Phase 2

would restore). Every status path — ok / overridden+duration / reset-candidate / offline /

skipped_not_v2 — is now exercised on real data. Phase 1 detection is COMPLETE. Phase 2 (the actual

reset: write the active bank's scheduled setpoints + resume plan_event) is the remaining

follow-up and needs write scope + go-ahead.

[agentic-framework] 2026-07-07: Thermostat checker — offline detection + long-override candidates (PR #14, v1.4.0)
Tue, 07 Jul 2026

The v1.3.0 staging run flagged 1 reset candidate but left 2 of 3 overrides as

"duration undetermined". Root cause (confirmed with Barry): propertyHistory returns

transitions, so an override that started before the 3h window returns no samples —

and an offline device (e.g. 1a16110c) looks identical (empty history). Fixed both:

the buildingAssets selection). online = false → status offline, skipped before

override classification (after the v1 skip). Offline devices are never reset candidates

(stale state; a downlink wouldn't reach them).

change in the window** (empty samples), treat it as overridden ≥ window (a lower bound)

→ reset candidate. Extracted the pure overrideDurationFromSamples and unit-tested it.

log line; historySamples + durationIsLowerBound on override logs; summary renders

lower-bound durations as ≥Nm; added an offline summary line.

GraphQL online field validated against the live schema. Next: republish to staging and

confirm 1511 becomes a ≥180m candidate and 1a16110c reports offline.

[agentic-framework] 2026-07-06: Fix "Unknown" account name in agent logs (PR #15)
Mon, 06 Jul 2026

Agent logs showed accountName: "Unknown" on every entry. Root cause: deploy() set

the Lambda ACCOUNT_NAME env var to account_name or '' using only the caller-passed

name, and the runtime logs ACCOUNT_NAME || 'Unknown' — so callers that don't pass a

name (e.g. the Ops Dashboard) leave it empty. Fixed deploy() to resolve the name via

db_client.get_account_by_uuid(account_uuid) when not provided (the record has it and

deploy already has the UUID). Cosmetic/label only — accountUuid was always correct;

takes effect on re-deploy. Tests: 15 pass (2 new). Draft PR #15 off master, independent

of the thermostat work.

Copilot review: the two new tests asserted account_name via a brittle positional

index (_create_or_update_lambda.call_args.args[8]). Fixed by binding the recorded call

against the real method signature (inspect.signature) and asserting on account_name by

name — robust to signature changes. 15 pass. Pushed to the PR branch.

[agentic-framework] 2026-07-06: Reworked thermostat-schedule-checker to read the on-device schedule (PR #14)
Mon, 06 Jul 2026

Reworked the agent to read each thermostat's schedule directly from its device asset

and check it against the device-reported active plan (plan_event), replacing the

unreliable "match a separate schedule config by assignedConfigUuids" approach

(not all thermostats have an assigned config, and it can be out of sync).

targets + fan mode vs live values (±0.5 °C). NOT EXECUTED is ambiguous (no

schedule vs user override), so read the schedule_time slots (building-local time,

weekly carry-over) to classify: active slot → overridden; none → no_schedule.

slots are parsed only to disambiguate NOT EXECUTED.

(incl. findActiveBank wrap-around), and SCHEDULE_FORMAT.md documenting the model.

sbp-mono decoders/drivers. Dropped the unused read:deviceConfig scope. Display

nameless assets as "Unnamed" (codebase convention). Current: v1.2.1 on staging.

1 no_schedule. Confirms the override-vs-no_schedule split and v1-skip against real

data. Still unexercised live: the ok/out_of_sync compare path (no running thermostat

in staging). Assumptions flagged: building timeZone for "current time"; plans carry

over across days.

thermostats overridden >30 min back to their scheduled values. There's no on-device

"overridden since" field (property stamps = last report; physical overrides have no

actor), so the agent reads plan_event history via propertyHistory to find the last

transition into NOT EXECUTED and flags reset candidates (>30 min). Read-only detection;

the reset (write scheduled setpoints/modes + resume plan_event) is Phase 2 (a

separate write-enabled PR needing editor/write scope + idempotency + dry-run). 26 unit

tests; all 3 queries validate live. Draft PR #14.

[agentic-framework] 2026-07-06: Reorganized documentation by audience (PR #13)
Mon, 06 Jul 2026

Reorganized the framework documentation and corrected the deployment model, then

merged it as PR #13.

Highlights

multi-environment support).

docs/FRAMEWORK_DEVELOPERS.md (framework-internals guide); trimmed

hello-world to a concrete example with a dashboard screenshot.

CLI and deployed from the UBX Operations Dashboard** (previously documented

as deploy-agent.py). Documented the (event, context, runtime) handler

signature and runtime.config.

implementation-plan-1-0.md and absorbed agents/DEPLOYMENT_GUIDE.md.

agent-runtime-architecture.md, orchestration/README.md,

orchestration/DEPLOYMENT_FLOW.md, orchestration/SLACK_NOTIFICATIONS.md,

docs/SETUP_MANAGEMENT_API.md, TESTING_GUIDE.md.

publish target) and disambiguated the example uuid8 from the commit sha.

the source tree.

[agentic-framework] 2026-07-06: Fixed deployment-state tests for the repository-based API
Mon, 06 Jul 2026

orchestration/test_deployment_state.py still called deploy()/cleanup() with

the old agent_dir= argument and never mocked self.repository, so all 8

state-machine tests failed. Updated them to the current agent_id +

repository.download_agent API (repository mocked in the fixtures). All 13 tests

pass. Shipped in PR #13.

[agentic-framework] 2026-07-06: Fixed thermostat-schedule-checker GraphQL queries (PR #14)
Mon, 06 Jul 2026

All three GraphQL queries in the agent were written against an assumed schema and

failed against the live API. Validated each against the live schema

(http://127.0.0.1:8000/graphql) and corrected:

Bumped to v1.0.1 and re-published to staging. Opened as draft PR #14 — schema-valid

but still needs an end-to-end staging run to confirm runtime data handling.

Abandoned the building-monitor agent (a non-functional example built on the same

fictional schema).

[sbg-webapp] 2026-07-02 10:08: Dedupe children linked to a fridge under multiple properties
Thu, 02 Jul 2026 10:08
[sbg-webapp] 2026-07-02 09:29: Disable composite grouping during search/filter (Copilot review PR #1555)
Thu, 02 Jul 2026 09:29
[sbg-webapp] 2026-07-01 11:48: Remove margin-right on the show-children pill icon
Wed, 01 Jul 2026 11:48
[sbg-webapp] 2026-06-30 16:53: Enlarge the card-stack pill icon
Tue, 30 Jun 2026 16:53
[sbg-webapp] 2026-06-30 16:45: Highlight the expanded composite parent with elevation
Tue, 30 Jun 2026 16:45
[sbg-webapp] 2026-06-30 16:43: Center the expanded parent card within the group box
Tue, 30 Jun 2026 16:43
[sbg-webapp] 2026-06-30 16:38: Frame expanded composite as one box with a dashed parent/child divider
Tue, 30 Jun 2026 16:38
[sbg-webapp] 2026-06-30 16:28: Animate child-asset reveal; first-pass parent centering
Tue, 30 Jun 2026 16:28
[sbg-webapp] 2026-06-30 16:12: Make child-assets toggle an inline pill next to the set-up chip
Tue, 30 Jun 2026 16:12
[sbg-webapp] 2026-06-30 15:56: Fix Add Fridge — create as a known asset via assetModelUuid
Tue, 30 Jun 2026 15:56
[sbg-webapp] 2026-06-30 13:58: Address code review — search/filter interactions, empty-section entry point
Tue, 30 Jun 2026 13:58
[sbg-webapp] 2026-06-30 13:42: Refetch dashboard once on wizard close, not per step
Tue, 30 Jun 2026 13:42
[sbg-webapp] 2026-06-30 13:40: Guard empty child band; tidy wizard dialog binding
Tue, 30 Jun 2026 13:40
[sbg-webapp] 2026-06-30 13:38: Add Fridge button + setup wizard in the Refrigeration section
Tue, 30 Jun 2026 13:38
[sbg-webapp] 2026-06-30 13:38: Add asset setup wizard dialog
Tue, 30 Jun 2026 13:38
[sbg-webapp] 2026-06-30 13:35: Hide composite children; expand them under the parent card
Tue, 30 Jun 2026 13:35
[sbg-webapp] 2026-06-30 13:32: Add category/type name-to-uuid resolver
Tue, 30 Jun 2026 13:32
[sbg-webapp] 2026-06-30 13:32: Add composite-asset relationship helper
Tue, 30 Jun 2026 13:32
[sbg-webapp] 2026-06-30 13:31: Add implementation plan for composite assets
Tue, 30 Jun 2026 13:31
[sbg-webapp] 2026-06-30 13:22: Add design spec for composite (virtual) assets
Tue, 30 Jun 2026 13:22
[sbg-webapp] 2026-06-30 09:35: Sync inspector spec + PR #1550 description with as-built toolbar
Tue, 30 Jun 2026 09:35
[sbg-webapp] 2026-06-30 09:26: Raise the mobile inspector sheet above floorplan thumbnails
Tue, 30 Jun 2026 09:26
[sbg-webapp] 2026-06-30 09:22: Keep the inspector open after editing an asset
Tue, 30 Jun 2026 09:22
[sbg-webapp] 2026-06-29 16:23: Enlarge the inspector Dashboard button and make it solid
Mon, 29 Jun 2026 16:23
[sbg-webapp] 2026-06-29 16:13: Widen the inspector menu/close gap on mobile
Mon, 29 Jun 2026 16:13
[sbg-webapp] 2026-06-29 16:06: Inspector menu fixes — keep open on overlay clicks; bigger tonal buttons
Mon, 29 Jun 2026 16:06
[sbg-webapp] 2026-06-29 15:15: Move inspector actions into a toolbar overflow menu
Mon, 29 Jun 2026 15:15
[sbg-webapp] 2026-06-29 14:37: Revert the dwell-time pre-fill
Mon, 29 Jun 2026 14:37
[sbg-webapp] 2026-06-29 14:34: Correct LineGraph series-matching comment (PR #1553 review)
Mon, 29 Jun 2026 14:34
[sbg-webapp] 2026-06-29 14:28: Pre-fill dwell time with the minimum when enabling it
Mon, 29 Jun 2026 14:28
[sbg-webapp] 2026-06-29 14:13: Raise the default minimum dwell to 10 minutes
Mon, 29 Jun 2026 14:13
[sbg-webapp] 2026-06-29 10:42: Drop the series ids — constant alert series alone fixes the export
Mon, 29 Jun 2026 10:42
[sbg-webapp] 2026-06-29 10:25: Keep the alert series always present so its bars render
Mon, 29 Jun 2026 10:25
[sbg-webapp] 2026-06-29 10:14: Fix temperature missing from graph CSV export (stable series ids)
Mon, 29 Jun 2026 10:14
[sbg-webapp] 2026-06-25 15:54: Raise the mobile asset inspector sheet to 85%
Thu, 25 Jun 2026 15:54
[sbg-webapp] 2026-06-25 15:43: Raise the mobile asset inspector sheet to 75%
Thu, 25 Jun 2026 15:43
[sbg-webapp] 2026-06-25 15:41: Open the inspector on desktop dashboard property-value click
Thu, 25 Jun 2026 15:41
[sbg-webapp] 2026-06-25 15:35: Consolidate the asset inspector into one responsive wrapper
Thu, 25 Jun 2026 15:35
[sbg-webapp] 2026-06-25 15:16: Shrink and indent the inspector Dashboard button
Thu, 25 Jun 2026 15:16
[sbg-webapp] 2026-06-25 15:14: Outline the inspector Dashboard split button
Thu, 25 Jun 2026 15:14
[sbg-webapp] 2026-06-25 15:13: Make the inspector Dashboard button a split button
Thu, 25 Jun 2026 15:13
[sbg-webapp] 2026-06-25 14:53: Restructure asset inspector toolbar; bottom sheet on mobile
Thu, 25 Jun 2026 14:53
[sbg-webapp] 2026-06-25 14:19: Asset inspector improvements design spec
Thu, 25 Jun 2026 14:19
[standalone-dev-env] 2026-06-25: Fix Linux "dubious ownership" + diagnose coworker's clone-skip
Thu, 25 Jun 2026

A coworker's Linux make setup failed with git "detected dubious ownership in /workspace" — a

Docker-on-Linux issue: bind-mounted files keep the host UID while git runs as root in the

container (Mac's Docker Desktop/colima remap ownership, so it doesn't show there). Fix: added

git config --system --add safe.directory '*' to the Dockerfile so git trusts the mounted repos.

Their secondary symptom — git reporting standalone-dev-env's own setup-graphql.sh as a "sbp-mono

local change" — was because they're on an OLD version whose clone guard (! -d sbp-mono) skipped

the clone on the always-present mount dir, so git walked up to /workspace; the .git-based guard

(edfa39e) already fixes that. So the coworker needs to pull latest + make build + make setup.

Verified: image builds, safe.directory resolves to *. Committed f40661e, pushed to PR #25.

[standalone-dev-env] 2026-06-25: Hardened make setup clear path + ignore Gemfile.lock churn
Thu, 25 Jun 2026

Two setup-graphql.sh fixes Barry asked for: (1) the -c clear path did rm -rf ubx-repos, which

hits the same mount-busy issue (sbp-mono is a bind mount) — changed to empty the checkout's

*contents* (find -mindepth 1 -delete) and guard the re-clone on .git (so it re-clones first-time

AND after a clear, since the mount dir always exists); (2) discard Gemfile.lock changes before the

dirty check so bundler/capistrano churn no longer blocks the branch checkout. Exposed the clear

path via make setup CLEAR=1. Verified: CLEAR=1 passes -c (dry-run), and a modified

capistrano/backend/Gemfile.lock is discarded -> repo clean (in-container test, net no-op). Did NOT

run the destructive full -c (would re-clone Barry's checkout). Committed edfa39e, pushed to PR #25.

[standalone-dev-env] 2026-06-25: Fix make setup venv error (device or resource busy)
Thu, 25 Jun 2026

make setup failed at rm -rf gql-py3 — gql-py3 is the gql-venv volume's mount point, which can't

be unlinked. Switched setup-graphql.sh to python -m venv --clear gql-py3 (empties the volume's

contents, keeps the mount) and moved the venv rebuild to AFTER the source checkout, so a

dirty-repo abort no longer leaves a half-cleared venv. Verified: make setup no longer errors on

the venv; it reaches the checkout and stops cleanly on Barry's dirty sbp-mono (an uncommitted

capistrano/backend/Gemfile.lock) without touching the venv. Rebased onto Barry's readme tweak

(0945f6c "Clarify local machine editing"), pushed 5f20e01 to PR #25. Remaining for Barry: clean

ubx-repos/sbp-mono's uncommitted Gemfile.lock before setup will check out a branch. Latent: the

-c clear flag's rm -rf ubx-repos would hit the same mount-busy issue (not exposed via make

setup, so not fixed).

[standalone-dev-env] 2026-06-24: README quick start — note editing gql_env after setup
Wed, 24 Jun 2026

make setup creates gql_env from defaults, but the DBDSN/AWS creds/cert paths must be filled in

before repave-db and run work. Added that step to the quick start (right after make setup,

pointing to the Secrets and certificates section). Committed b5ed4c5, pushed to PR #25.

[standalone-dev-env] 2026-06-24: Switched the architecture diagram to SVG
Wed, 24 Jun 2026

Barry provided an SVG export (~/Downloads/Dev Environment Architecture.svg). Replaced

docs/architecture.png with docs/architecture.svg (11KB, viewBox 1488x1010, no <script>) and

pointed the README embed at it; removed the PNG. Crisp at any zoom, tiny file. Committed f577f70,

pushed to PR #25. (GitHub renders sanitized SVG via the image tag — worth a glance on the PR.)

[standalone-dev-env] 2026-06-24: Replaced architecture image with a higher-res version
Wed, 24 Jun 2026

The first embed (docs/architecture.png) was 909x540 and rendered blurry. Replaced it with the

2000x1405 export (same path, so the README reference is unchanged). Committed 695e2af, pushed to

PR #25.

[standalone-dev-env] 2026-06-24: Embedded the designed architecture image in the README
Wed, 24 Jun 2026

Barry had Claude Design produce a polished static architecture diagram. Committed it as

docs/architecture.png (909x540, 23KB) and replaced the Mermaid block with

![...](docs/architecture.png). Kept the "Three layers" prose below as the image-independent

description. Tradeoff noted in the commit: a static image won't auto-track topology changes the

way the Mermaid did — refresh docs/architecture.png when the architecture changes. Committed

85ff852, pushed to PR #25. (This ends the long diagram iteration: ASCII -> Mermaid -> stacked

Mermaid -> designed PNG.)

[standalone-dev-env] 2026-06-24: Mermaid spacing config (subgraph title padding)
Wed, 24 Jun 2026

Barry asked how much layout control Mermaid gives + specifically for padding under box titles.

Added an init directive to the diagram: subGraphTitleMargin {top:8, bottom:16} (padding around

subgraph titles — the direct answer) and rankSpacing:55 (more gap between the stacked layers).

Mermaid auto-layouts via dagre (no manual positioning); the available knobs are spacing

(nodeSpacing/rankSpacing/subGraphTitleMargin/padding), direction, node order + invisible links,

and themeVariables. GitHub generally honors flowchart config but I can't render-test locally.

Committed e6ac971, pushed to PR #25.

[standalone-dev-env] 2026-06-24: Stacked the Mermaid architecture diagram vertically
Wed, 24 Jun 2026

First Mermaid attempt rendered messy — auto-layout spread the subgraphs side-by-side with

crossing edges. Restructured to a clean vertical stack (Local -> Container -> Remote): moved the

browser inside the Local layer, made every edge flow downward, and trimmed nodes (dropped the

volume/secret boxes, collapsed the cloud to one node) so each layer is a simple band. Named

volumes now live only in the "Three layers" text. Committed 719762a, pushed to PR #25. Still

can't render-test locally (no mmdc) — Barry verifies on GitHub.

[standalone-dev-env] 2026-06-24: Replaced the ASCII architecture diagram with Mermaid
Wed, 24 Jun 2026

The ASCII diagram rendered cluttered (floating bidirectional arrows, ragged ─── rules). Barry

asked to clean it up, then to use Mermaid. Replaced it with a Mermaid flowchart (GitHub renders

it): browser -> webapp/gql containers (with ports), host bind mounts (dotted, into the

containers), named volumes, and gql -> remote cloud (CockroachDB ×2 + the rest). Couldn't

render-test locally (no mmdc installed) — conservative syntax, Barry to eyeball on GitHub.

Committed 99c43a5, pushed to PR #25.

[standalone-dev-env] 2026-06-24: README: moved ./dev-script out of the Commands table
Wed, 24 Jun 2026

The Commands table is make targets; ./dev-script is a wrapper, so it didn't belong as a row.

Removed the row (left a one-line pointer) and relocated the "Running dev-scripts" section to sit

immediately after Commands, with the -e <env> (Secrets Manager DSN) usage broken out into its

own note. Committed b6d8a66, pushed to PR #25.

[standalone-dev-env] 2026-06-24: Trimmed README + added create-admin step to quick start
Wed, 24 Jun 2026

Removed the login-credentials line from the quick start (edf74be), then dropped the "GraphQL

authentication" and "State-managed fields" sections (d4d4398) — Secrets and certificates is now

the last section. Added a one-time first-admin-user step to the quick start using

./dev-script create_invitation.py you@example.com --account "Test Account 1" --role admin, which

replaces the old admin/standalone01 login note. Pushed to PR #25.

[standalone-dev-env] 2026-06-24: Replaced make dev-script ARGS= with a ./dev-script wrapper
Wed, 24 Jun 2026

Barry questioned whether the make dev-script ARGS= pattern was best practice — it isn't (it's a

known make workaround for forwarding a free-form argv, with awkward double-quoting). Replaced it

with a thin ./dev-script wrapper that forwards "$@" to run-dev-script.sh in the gql container —

idiomatic, natural shell quoting:

./dev-script create_invitation.py you@x.com --account "Test Account 1" --role admin

Removed the make dev-script target (make help now points to ./dev-script). The wrapper cd's to

its own dir and honors COMPOSE/NAME env overrides. Verified create_invitation.py --help runs

through it (no side effects). Updated readme. Committed ea57dcd, pushed to PR #25. (make stays for

the structured lifecycle targets where named args fit; the wrapper is the right tool for free-form

command passthrough.)

[standalone-dev-env] 2026-06-24: Add make dev-script (run sbp-mono dev-scripts in the container)
Wed, 24 Jun 2026

Barry needs to run dev-scripts in the container (common first-setup one: create_invitation.py to

make an admin user). Added a dev-script make target wrapping the existing run-dev-script.sh

launcher (which activates the venv, sources gql_env, resolves the DSN incl. -e env via Secrets

Manager). Usage: make dev-script ARGS='<script.py> [args]'; quoted multi-word args (e.g.

--account "Test Account 1") survive make expansion (verified via make -n). Verified

create_invitation.py --help runs through the launcher in-container with no side effects (printed

the argparse usage). Documented in readme (commands-table row + new "Running dev-scripts"

section). Committed 65fdb0a, pushed to PR #25.

[standalone-dev-env] 2026-06-24: Symmetric frontend mount path
Wed, 24 Jun 2026

Barry noticed the diagram inconsistency: the webapp mounted its source at /webapp while the

backend's was /workspace/ubx-repos/sbp-mono. The asymmetry existed because the gql container

mounts the whole dev-env at /workspace (it runs the dev-env scripts) while the webapp only needs

its own source. Made it symmetric anyway: webapp now mounts at /workspace/ubx-repos/sbg-webapp

(working_dir + source mount + node_modules volume), still only its own source (no .:/workspace).

The webapp-modules volume remounted at the new path with no reinstall. Verified webapp serves

HTTP 200 from the new path; updated the diagram. Committed a506861, pushed to PR #25.

[standalone-dev-env] 2026-06-24: Decoupled DB repave from make setup (added make repave-db)
Wed, 24 Jun 2026

make setup ran initialize_database.sh (ubx_pave.sql DROPS + recreates the schema, re-seeds test

data) on every invocation, so switching branches or rebuilding silently reset the dev DB. Split

it: make setup now only does checkout + venv + install (non-destructive); new make repave-db

runs initialize_database.sh on the current branch behind a y/N prompt that echoes the target DB

(credentials redacted via grep/sed on DBDSN). Verified the guard aborts on N/empty input without

running the pave. Did NOT run the destructive confirm path (it would wipe Barry's dev DB), so the

in-container pave itself is still unverified — but it's the same scripts that worked in his

native setup, and csql + the verify-full cert mount are already proven. Name (repave-db) and

confirmation were Barry's choices. Updated Makefile + readme (quick start, commands table,

backend-dev section). Committed bc55fd1, pushed to PR #25.

[standalone-dev-env] 2026-06-24: Rewrote the README for the two-service environment
Wed, 24 Jun 2026

Rewrote readme.md now that it runs both backend + frontend: intro covering both services, an

ASCII architecture diagram (host bind mounts + named volumes, gql/webapp containers with their

ports, and the remote cloud services), and a "how development works" top-level overview.

Revisited every section for front+back consistency — split into "Developing the backend"

(restart, no hot reload) and "Developing the frontend" (Vite HMR), generalized the

multiple-instances section, and aligned all command/var names (GQL_*/WEBAPP_*, run/run-webapp).

Committed 0df0971, pushed to PR #25.

[standalone-dev-env] 2026-06-24: run-all -> run-webapp (frontend-only)
Wed, 24 Jun 2026

run-all brought up backend + frontend together in one terminal (mixed logs). Barry prefers

running them in separate terminals for independent logs, so renamed run-all -> run-webapp and

made it start ONLY the webapp service (compose --profile webapp up webapp). Workflow: make run

(backend, terminal 1) + make run-webapp (frontend, terminal 2). Verified: run-webapp brings up

the webapp container alone (no gql) and serves the Vite UI (HTTP 200). Makefile + readme updated.

Committed 1b032f7, pushed to PR #25.

[standalone-dev-env] 2026-06-24: Symmetric override env vars (GQL_* / WEBAPP_*)
Wed, 24 Jun 2026

Backend override vars were bare (SRC/PORT/G) while the frontend's were WEBAPP_-prefixed —

asymmetric. Renamed for clarity/symmetry: SRC->GQL_SRC, PORT->GQL_PORT, G->GQL_BRANCH;

WEBAPP_SRC/WEBAPP_PORT/WEBAPP_BRANCH unchanged; NAME stays the shared instance knob. (These are

make-var overrides passed through to docker compose ${...} interpolation.) Updated Makefile,

docker-compose.yml, readme. Verified: make run GQL_PORT=8001 maps host 8001 and serves

introspection HTTP 200. Committed 9f738de, pushed to PR #25.

[standalone-dev-env] 2026-06-24: Renamed gql-repos -> ubx-repos; frontend now a managed checkout
Wed, 24 Jun 2026

Renamed the managed-repos dir gql-repos -> ubx-repos (it now holds both sbp-mono and

sbg-webapp, so the gql- prefix was a misnomer) across 13 files + the gitignored dir; rebuilt

the venv at the new /workspace/ubx-repos path. Made the frontend symmetric with the backend:

make setup-webapp W=<branch> (default main) host-clones sbg-webapp --recursive into

ubx-repos/sbg-webapp, checks out W, submodule-updates, then runs container npm install

--legacy-peer-deps into the webapp-modules volume. WEBAPP_SRC defaults to the managed checkout

(override for an external one). The clone runs on the HOST (uses Barry's git/ssh, avoids the

clone-into-volume-mounted-dir problem, and keeps the node_modules named volume). Verified:

backend make run -> introspection 200 at the new path; make setup-webapp W=main clones +

installs; webapp serves the Vite UI (HTTP 200, <title>UBX</title>). Committed 1350d79, pushed

to PR #25.

[standalone-dev-env] 2026-06-24: Verified the optional frontend (webapp) container service
Wed, 24 Jun 2026

make setup-webapp + the webapp compose service work. Two fixes: (1) install only

modules/vue-ui (dev:all doesn't use the root deps, and a root npm install would write a Linux

node_modules into the bind-mounted host repo); (2) add --legacy-peer-deps — vue-ui has a peer

conflict (eslint-plugin-vue 9 vs @vue/eslint-config-typescript 7) that npm 9 rejects by default

(Barry's native node_modules predates the stricter npm). Verified on host :8091 (to avoid

clobbering his native npm run dev:all on :8090): 1344 packages installed into the isolated

webapp-modules volume (his 969MB host vue-ui modules untouched), Vite v5.4.21 serves the UI

(HTTP 200, <title>UBX</title>). Committed 855f141, pushed to PR #25. Also cleaned up a stray

gql-1 backend I'd orphaned with a botched make run > /dev/null &.

[standalone-dev-env] 2026-06-24: Container-portable MQTT cert paths
Wed, 24 Jun 2026

Confirmed gql_env was NEVER committed (gitignored, and the AWS key id / Snowflake password

never appear in history) — so the earlier "rotate exposed keys" concern was wrong; no key

rotation needed on git-exposure grounds. Made the MQTT cert paths portable: gql_env's

GQL_AWS_MQTT_*_FILENAME now point at /certs/..., and compose mounts the host cert dir

(UBX_CERTS_DIR, default /Users/barry/Projects/ubx/certs) at /certs, replacing the host-absolute

identity mount. UBX_CERTS_DIR is now the only host-specific knob. gql_env edited locally only

(gitignored, not committed); compose + readme committed (06e4d9f), pushed to PR #25. Verified:

make run -> mqtt connected rc=0, host introspection HTTP 200. Skipped optional extras

(gql_env.example template, sourcing secrets from Secrets Manager).

[standalone-dev-env] 2026-06-24: make run one-liner + silenced container syslog spam
Wed, 24 Jun 2026

Fixed the noisy logs: hvac2/log.py adds a SysLogHandler(/dev/log) unconditionally and the

slim image has no syslogd, so every log record errored with a traceback. Added

run-graphql-container.sh, which binds a /dev/log datagram sink (drains it; console logs are

unaffected via run-graphql.py -c) before launching the server. Wired docker-compose.yml to

launch via that script and to mount the MQTT cert dir at the absolute path gql_env references

(UBX_CERTS_DIR, default /Users/barry/Projects/ubx/certs) so AWS/MQTT works by default. Net:

make run is now a complete one-liner — backend with DB + S3 + MQTT and clean logs, no flags.

Verified under gql-main without publishing a port (to avoid clobbering Barry's live :8000): 0

SysLogHandler errors, "Application startup complete", mqtt connected rc=0. Earlier Barry

confirmed his frontend (~/Projects/sbg-webapp, npm run dev:all) works against the AWS-enabled

container backend. Committed 7aa956c, pushed to PR #25. The host-absolute cert-path default is

temporary, pending the secrets/config cleanup.

[standalone-dev-env] 2026-06-24: Verified the backend container end-to-end (and fixed a DB-cert gap)
Wed, 24 Jun 2026

Barry installed colima (Server 29.5.2) — earlier make build "hangs" were just the colima

daemon being wedged, not the build. Ran a non-destructive verification (no DB pave, no branch

switch, sbp-mono left on prod): make build (cached, ~1MB context), in-container venv +

install_all.sh develop (clean), then started the server with GQL_DISABLE_AWS=true. First run

crashed on startup — the CockroachDB DSNs use sslmode=verify-full and libpq wanted

~/.postgresql/root.crt, absent in the container. Fixed by mounting host ~/.postgresql →

/root/.postgresql:ro (commit 4bf1198). After that: "Application startup complete", and a host

POST introspection to localhost:8000 returned HTTP 200 with the real schema; GET / served

GraphiQL. Confirms nested bind mount, per-instance venv volume, ~/.ssh mount, and DB-cert mount

all work. Known remaining: noisy syslog logging errors (no /dev/log socket in the container,

cosmetic/non-fatal) and the MQTT certs for the full AWS path (gql_env's absolute /Users/barry

paths — part of the deferred secrets/config work). Frontend (make run-all) and multi-backend

not yet verified. Pushed to PR #25.

[standalone-dev-env] 2026-06-24: Add optional frontend service to the dev-env containers
Wed, 24 Jun 2026

Added a profile-gated webapp compose service for the sibling sbg-webapp repo

(Vite/Vue 3, Node 18.16.0; dev server on 8090). make run stays backend-only;

make run-all brings up backend + frontend; make setup-webapp npm-installs it

(WEBAPP_SRC defaults to ../sbg-webapp). The browser reaches the backend at

localhost:8000 (VUE_APP_GRAPHQL_HTTP in modules/vue-ui/.env), so no container-to-

container wiring. Removed the legacy setup-webapp.sh/start-webapp/update-webapp —

Barry doesn't use them (they're the Node 10 / local-Postgres / sbg-buildroot era);

he runs the frontend with npm run dev:all from ~/Projects/sbg-webapp. Committed

46607d6, pushed to PR #25. Still unbuilt/unverified (no Docker engine on this machine).

[sbg-webapp] 2026-06-23 17:04: Alert dashboard timeline — deep-link timeframe + timezone alignment (#1545)
Tue, 23 Jun 2026 17:04
[sbg-webapp] 2026-06-23 15:32: Show "Unnamed" for nameless assets across alerts views (#1544)
Tue, 23 Jun 2026 15:32
[sbg-webapp] 2026-06-23 15:15: Address Copilot review on the Queue PRs
Tue, 23 Jun 2026 15:15
[sbg-webapp] 2026-06-23 12:53: Show the journal comment box on asset journals (#1445)
Tue, 23 Jun 2026 12:53
[sbg-webapp] 2026-06-23 12:16: Tstat dashboard heat/cool + fan status (#1500)
Tue, 23 Jun 2026 12:16
[sbg-webapp] 2026-06-23 12:10: Raise inspector menu/dialog above the panel (#1524)
Tue, 23 Jun 2026 12:10
[sbg-webapp] 2026-06-23 12:06: Alert bar length on zoom (#1530)
Tue, 23 Jun 2026 12:06
[sbg-webapp] 2026-06-23 11:59: Mobile — tap unplaced asset opens inspector (#1523)
Tue, 23 Jun 2026 11:59
[sbg-webapp] 2026-06-23 11:57: Hide Delete button for UBX devices (#1512)
Tue, 23 Jun 2026 11:57
[sbg-webapp] 2026-06-23 11:54: Journal shows "Unnamed" for nameless assets (#1510)
Tue, 23 Jun 2026 11:54
[sbg-webapp] 2026-06-23 11:48: Reorder building nav tabs (#1501)
Tue, 23 Jun 2026 11:48
[standalone-dev-env] 2026-06-23: Containerize the gql-server dev environment
Tue, 23 Jun 2026

Stacked feature/dev-env-containerize on the cleanup branch and committed a container-only

setup (commit d78975a). The gql-server now runs in an Ubuntu 22.04 image (python3.10 +

build deps + cockroach-sql client); sbp-mono source is bind-mounted for live editing and the

venv lives in a per-instance named volume. New files: Dockerfile, docker-compose.yml

(parameterized SRC/PORT so multiple backends run at once), Makefile (setup/run/down/shell/test),

.dockerignore, .devcontainer. Modified: csql now calls the cockroach-sql client; setup-graphql.sh

drops the apt/sudo lines and uses python3.10 -m venv. Removed setup.sh/start.sh/start-mac.sh/

setup-crdb.sh/stop.sh (replaced by image+compose+make). NOT yet built/verified: this machine has

the docker CLI but no engine (no Desktop/colima/OrbStack) and no compose plugin — Barry verifies

once an engine is installed (write-now-verify-later, his call).

[standalone-dev-env] 2026-06-23: Rebase dev-env cleanup onto master
Tue, 23 Jun 2026

Rebased Barry's feature/even_more_cleanup onto master (PR #23 / dev-script-runner already merged

there) as feature/dev-env-cleanup — intended as its own cleanup PR. Removes ~109 files of cruft,

strips all platform/Mac branching, drops the pc-*-ec-support packages entirely, and removes

gql-requirements.txt + requirements.txt (deps come from sbp-mono's install_all.sh). Resolved the

setup.sh/setup-graphql.sh conflicts by taking the cleanup version, since the only master changes

to those files were the Mac-support additions we're intentionally dropping. some_cleanup is a

subset and was ignored. requirements3.txt survived — left as an optional extra to remove later.

[sbg-webapp] 2026-06-22 16:13: Fix Expand All browser lockup (reactive loop)
Mon, 22 Jun 2026 16:13
[sbg-webapp] 2026-06-22 15:43: HighCharts series colors + alert-bar color fixes
Mon, 22 Jun 2026 15:43
[sbg-webapp] 2026-06-22 10:15: Alerts Activity tab polish & #1532 follow-ups
Mon, 22 Jun 2026 10:15
[sbg-webapp] 2026-06-18 14:59: alerts Activity — exclude pending + de-dupe active/recent (bugfix)
Thu, 18 Jun 2026 14:59
[sbg-webapp] 2026-06-18 13:38: alerts Activity — hide Recipients column on mobile
Thu, 18 Jun 2026 13:38
[sbg-webapp] 2026-06-18 11:52: alerts Activity — When-column tooltip + sort polish
Thu, 18 Jun 2026 11:52
[sbg-webapp] 2026-06-18 11:25: alerts Configuration — show Dwell/Active Periods only at lg+
Thu, 18 Jun 2026 11:25
[sbg-webapp] 2026-06-18 10:35: alerts Configuration — fix table overflow with fixed layout
Thu, 18 Jun 2026 10:35
[sbg-webapp] 2026-06-18 09:26: alerts — create/edit dialog uses StandardDialog (title + close)
Thu, 18 Jun 2026 09:26
[sbg-webapp] 2026-06-18 09:18: alerts — create/edit in a dialog instead of full-page routes
Thu, 18 Jun 2026 09:18
[sbg-webapp] 2026-06-18 09:05: alerts — default date range to the "last 7 days" preset
Thu, 18 Jun 2026 09:05
[sbg-webapp] 2026-06-17 16:23: alerts — address Copilot review on PR #1471
Wed, 17 Jun 2026 16:23
[sbg-webapp] 2026-06-17 15:25: alerts Activity — sort Active section newest-first
Wed, 17 Jun 2026 15:25
[sbg-webapp] 2026-06-17 15:16: alerts — asset chips open inspector on both tabs
Wed, 17 Jun 2026 15:16
[sbg-webapp] 2026-06-17 15:02: alerts — "Asset removed" label + Vuetify cellProps fix
Wed, 17 Jun 2026 15:02
[sbg-webapp] 2026-06-17 14:31: alerts Configuration — active-period one-line + asset chip new tab
Wed, 17 Jun 2026 14:31
[sbg-webapp] 2026-06-17 14:13: alert history view — drop summary section, reword nav
Wed, 17 Jun 2026 14:13
[sbg-webapp] 2026-06-17 13:52: alerts Configuration tab — CTO polish + on/off toggle
Wed, 17 Jun 2026 13:52
[sbg-webapp] 2026-06-17 13:40: alerts Activity tab — CTO polish pass
Wed, 17 Jun 2026 13:40
[sbg-webapp] 2026-06-16 12:42: fix — linked properties missing from CSV export
Tue, 16 Jun 2026 12:42
[sbg-webapp] 2026-06-15 16:33: fix — keep chart mounted on aggregation change (update in place)
Mon, 15 Jun 2026 16:33
[sbg-webapp] 2026-06-15 16:24: fix — navigator follows MIN/MAX/AVERAGE but never RAW
Mon, 15 Jun 2026 16:24
[sbg-webapp] 2026-06-15 16:20: fix — navigator inherited RAW aggregation (real root cause)
Mon, 15 Jun 2026 16:20
[sbg-webapp] 2026-06-15 15:53: test — extract groupQueryPeriod helper + unit tests
Mon, 15 Jun 2026 15:53
[sbg-webapp] 2026-06-15 15:50: fix — navigator series always uses a 6h (21600s) period
Mon, 15 Jun 2026 15:50
[sbg-webapp] 2026-06-15 14:16: battery PR #1525 — add usePropertyIndicator precedence test (Copilot review)
Mon, 15 Jun 2026 14:16
[sbg-webapp] 2026-06-15 14:10: fix — CSV export crash when numeric/text samples don't align
Mon, 15 Jun 2026 14:10
[sbg-webapp] 2026-06-15 13:11: asset markers — give battery a 24h stale window
Mon, 15 Jun 2026 13:11
[sbg-webapp] 2026-06-11 14:55: alert configs — remove unused alert activity view
Thu, 11 Jun 2026 14:55
[sbg-webapp] 2026-06-11 14:53: alert configs — first action links to dashboard, add action tooltips
Thu, 11 Jun 2026 14:53
[sbg-webapp] 2026-06-11 14:29: alert configs — style assets as chips, recipients with delivery icons
Thu, 11 Jun 2026 14:29
[sbg-webapp] 2026-06-11 14:18: alert configs — per-cell expansion for assets and recipients
Thu, 11 Jun 2026 14:18
[sbg-webapp] 2026-06-11 14:07: recent alerts — use theme primary color for edit pencil
Thu, 11 Jun 2026 14:07
[sbg-webapp] 2026-06-11 13:44: recent alerts — add edit pencil next to alert name
Thu, 11 Jun 2026 13:44
[sbg-webapp] 2026-06-11 13:38: alert definitions — tighten table padding on mobile
Thu, 11 Jun 2026 13:38
[sbg-webapp] 2026-06-11 12:57: recent alerts — tighten table layout on mobile
Thu, 11 Jun 2026 12:57
[sbg-webapp] 2026-06-11 12:36: recent alerts — show timestamps as relative time ago
Thu, 11 Jun 2026 12:36
[sbg-webapp] 2026-06-11 12:25: alerts graph — drop in-tooltip link on hover-capable devices
Thu, 11 Jun 2026 12:25
[sbg-webapp] 2026-06-11 12:22: alerts graph — no-data overlay no longer blocks alert bar clicks
Thu, 11 Jun 2026 12:22
[sbg-webapp] 2026-06-11 12:10: alerts graph — navigate on tap of in-tooltip details link (mobile fix)
Thu, 11 Jun 2026 12:10
[sbg-webapp] 2026-06-11 11:08: fix(styles): disabled flat/elevated buttons render their disabled state
Thu, 11 Jun 2026 11:08
[sbg-webapp] 2026-06-11 10:27: chore(install-wizard): one configuration i18n namespace; mark plans historical
Thu, 11 Jun 2026 10:27
[sbg-webapp] 2026-06-11 10:24: refactor(composables): surface platform traits through use-display
Thu, 11 Jun 2026 10:24
[sbg-webapp] 2026-06-11 10:21: refactor(uploads): one removable file chip list on all platforms
Thu, 11 Jun 2026 10:21
[sbg-webapp] 2026-06-11 10:19: refactor(install-wizard): canonical threshold helpers; tested wiring terminal table
Thu, 11 Jun 2026 10:19
[sbg-webapp] 2026-06-11 10:15: refactor(install-wizard): derive step numbers from visible steps; simplify row API
Thu, 11 Jun 2026 10:15
[sbg-webapp] 2026-06-11 10:13: refactor(layout): single source for navbar heights with --app-navbar-height CSS var
Thu, 11 Jun 2026 10:13
[sbg-webapp] 2026-06-11 10:09: refactor(tstat): centralize zone-sensor candidate rule in tstat/sensors.ts
Thu, 11 Jun 2026 10:09
[sbg-webapp] 2026-06-11 10:08: refactor(assets): single child-link sync path; declarative wizard sensor rows
Thu, 11 Jun 2026 10:08
[sbg-webapp] 2026-06-11 10:00: fix(components): initialize ThresholdDialog property state before onOpen runs
Thu, 11 Jun 2026 10:00
[sbg-webapp] 2026-06-10 16:20: link alert instances on graphs to the alert config dashboard
Wed, 10 Jun 2026 16:20
[sbg-webapp] 2026-06-10 16:20: recent alerts — replace expanded instance rows with inline graph
Wed, 10 Jun 2026 16:20
[standalone-dev-env] 2026-06-10: Implement run-dev-script.sh environment selection
Wed, 10 Jun 2026

Executed the implementation plan via subagent-driven development (3 TDD tasks, each

spec- and quality-reviewed, plus a final holistic review). run-dev-script.sh now takes

-e <dev|test|staging|production>; non-dev environments fetch ubx/database/<env>/dsn

from AWS Secrets Manager via inline boto3 and override DBDSN, aborting with exit 69 on

fetch failure. New test-run-dev-script.sh covers it end to end against real AWS

(12 checks). Commits 82733db, af5619b, 3138675. Fetch-failure test uses a dead

HTTPS_PROXY because gql_env clobbers AWS_ACCESS_KEY_ID.

[standalone-dev-env] 2026-06-10: Fix mac_os check in setup.sh
Wed, 10 Jun 2026

Committed a pre-existing one-line fix Barry had in the working tree: if !mac_os; then

tried to run a command named !mac_os (always false), so setup-crdb.sh never ran.

Now tests the variable: if [ "$mac_os" != true ].

[standalone-dev-env] 2026-06-10: Design spec for run-dev-script.sh environment selection
Wed, 10 Jun 2026

Brainstormed and committed a design spec (docs/superpowers/specs/2026-06-10-dev-script-environments-design.md)

for adding an optional -e <env> flag to run-dev-script.sh. For test/staging/production it

fetches the DB DSN from AWS Secrets Manager (ubx/database/<env>/dsn, same convention as

agentic-framework's environments.yaml) and overrides DBDSN after sourcing gql_env; no flag or

-e dev keeps today's behavior, and gql_env itself is never modified. Fetch failure aborts

(exit 69) rather than falling through to the personal dev DB.

[sbg-webapp] 2026-06-09 19:04: chore(iaq): remove temp sensor configuration step from install wizard
Tue, 09 Jun 2026 19:04
[sbg-webapp] 2026-06-09 15:58: fix(tstat): match installation scroll offset to navbar height per breakpoint
Tue, 09 Jun 2026 15:58
[sbg-webapp] 2026-06-09 15:50: refactor(refrigeration): share fridge-suitable sensor rule with config tab
Tue, 09 Jun 2026 15:50
[sbg-webapp] 2026-06-09 15:43: feat(tstat): scroll to installation section when opened via #installation hash
Tue, 09 Jun 2026 15:43
[sbg-webapp] 2026-06-09 15:43: feat(tstat): link wiring Configure to the config installation section
Tue, 09 Jun 2026 15:43
[sbg-webapp] 2026-06-09 15:43: feat(refrigeration): evaporator icon and fridge-suitable sensor candidates
Tue, 09 Jun 2026 15:43
[sbg-webapp] 2026-06-09 14:24: docs: reflect inline editing in next-steps spec and plan
Tue, 09 Jun 2026 14:24
[sbg-webapp] 2026-06-09 14:24: refactor(install-wizard): derive hasConfigStep from asset.config
Tue, 09 Jun 2026 14:24
[sbg-webapp] 2026-06-09 14:24: fix(iaq): refresh after inline threshold save; localize Low/High
Tue, 09 Jun 2026 14:24
[sbg-webapp] 2026-06-09 14:24: fix(refrigeration): label sensor pickers; revert selection on save failure
Tue, 09 Jun 2026 14:24
[sbg-webapp] 2026-06-09 14:24: fix(tstat): label zone-sensor picker; revert selection on save failure
Tue, 09 Jun 2026 14:24
[sbg-webapp] 2026-06-09 14:24: fix(install-wizard): accessible label on AssetSelector, gate empty row button
Tue, 09 Jun 2026 14:24
[sbg-webapp] 2026-06-09 13:42: fix(install-wizard): make next-step row actionLabel optional
Tue, 09 Jun 2026 13:42
[sbg-webapp] 2026-06-09 13:40: feat(refrigeration): inline sensor selection in wizard, split energy rows
Tue, 09 Jun 2026 13:40
[sbg-webapp] 2026-06-09 13:30: style(tstat): format zone sensor as a config row with inline picker
Tue, 09 Jun 2026 13:30
[sbg-webapp] 2026-06-09 13:23: feat(tstat): replace timezone with inline Zone Sensor selector in wizard
Tue, 09 Jun 2026 13:23
[sbg-webapp] 2026-06-09 13:14: fix(install-wizard): clarify progress counts required steps; mark config optional
Tue, 09 Jun 2026 13:14
[sbg-webapp] 2026-06-09 13:09: style(install-wizard): match configuration card outline to dashboard cards
Tue, 09 Jun 2026 13:09
[sbg-webapp] 2026-06-09 13:06: style(install-wizard): wrap configuration step contents in outlined card
Tue, 09 Jun 2026 13:06
[sbg-webapp] 2026-06-09 13:03: feat(install-wizard): make Configuration an optional numbered step
Tue, 09 Jun 2026 13:03
[sbg-webapp] 2026-06-09 11:37: style(install-wizard): increase top spacing above next-steps section
Tue, 09 Jun 2026 11:37
[sbg-webapp] 2026-06-09 11:35: fix(iaq): open ThresholdDialog on next tick to avoid setup TDZ
Tue, 09 Jun 2026 11:35
[sbg-webapp] 2026-06-09 11:32: style(iaq): drop icon, use Review thresholds action, plain Low/High value
Tue, 09 Jun 2026 11:32
[sbg-webapp] 2026-06-09 11:28: style(iaq): prefix threshold value with "Critical thresholds"
Tue, 09 Jun 2026 11:28
[sbg-webapp] 2026-06-09 11:24: fix(iaq): show next steps on temp/RH sensor; derive rows from config
Tue, 09 Jun 2026 11:24
[sbg-webapp] 2026-06-09 11:15: style(install-wizard): drop bottom borders on next-steps header and rows
Tue, 09 Jun 2026 11:15
[sbg-webapp] 2026-06-09 11:11: feat(refrigeration): install wizard next steps (sensor links)
Tue, 09 Jun 2026 11:11
[sbg-webapp] 2026-06-09 11:10: feat(iaq): install wizard next steps (critical thresholds)
Tue, 09 Jun 2026 11:10
[sbg-webapp] 2026-06-09 11:09: feat(tstat): install wizard next steps (wiring + timezone)
Tue, 09 Jun 2026 11:09
[sbg-webapp] 2026-06-09 11:06: feat(install-wizard): render InstallWizardNextSteps slot + shared strings
Tue, 09 Jun 2026 11:06
[sbg-webapp] 2026-06-09 11:05: feat(install-wizard): shared next-steps section + row components
Tue, 09 Jun 2026 11:05
[sbg-webapp] 2026-06-09 11:04: feat(refrigeration): fridgeSensorRows helper for install wizard next steps
Tue, 09 Jun 2026 11:04
[sbg-webapp] 2026-06-09 11:03: feat(tstat): wiringSummary helper for install wizard next steps
Tue, 09 Jun 2026 11:03
[sbg-webapp] 2026-06-09 11:01: feat(iaq): criticalThresholds helper for install wizard next steps
Tue, 09 Jun 2026 11:01
[sbg-webapp] 2026-06-09 10:56: docs(plan): fix threshold unit resolution and timezone label lookup
Tue, 09 Jun 2026 10:56
[sbg-webapp] 2026-06-09 10:49: docs(plan): fix wiring predicates, threshold conversion, channel display
Tue, 09 Jun 2026 10:49
[sbg-webapp] 2026-06-09 10:43: docs(plan): install wizard next steps implementation plan
Tue, 09 Jun 2026 10:43
[sbg-webapp] 2026-06-09 10:33: docs(spec): tighten next-steps spec per second review
Tue, 09 Jun 2026 10:33
[sbg-webapp] 2026-06-09 10:29: docs(spec): address review of install wizard next steps
Tue, 09 Jun 2026 10:29
[sbg-webapp] 2026-06-09 10:18: docs(spec): install wizard per-device "Next steps" section
Tue, 09 Jun 2026 10:18
[sbg-webapp] 2026-06-08 12:32: Android camera/library choice for asset image upload (#1511, PR #1516)
Mon, 08 Jun 2026 12:32
[iaq-lambda] 2026-06-08: Smartbutton RF test message — hub identity
Mon, 08 Jun 2026

Reworded the smartbutton_lambda RF test Slack/SMS message to identify hubs by asset name and UBX serial number instead of an EUI fragment, so installers can recognize hubs during field surveys. Format: Hub: <Asset Name> (<UBX SN>) = <level> (<rssi> RSSI), degrading gracefully to the original Hub <eui4>: ... line when the hub is unregistered, fields are blank, or any DB lookup fails.

Built via brainstorm → spec → plan → subagent-driven TDD (16 tests, the repo's first pytest suite). New get_hub_info() does a best-effort per-cluster lookup (hubs have no ubx_device_cluster_map rows), positive-only cache, single connection attempt, abort-on-error fallback. Pure format_hub_line() holds the display rules.

Field test surfaced the key bug: the installer-facing UBX SN is ubx_device.ubx_serial_number (asset console "Serial #"), not ubx_asset.serial_number (an EUI copy) — every hub was falling back. Fixed the query, verified against live clusters (hub …b794 → SN 1G1P). Also fixed a pre-existing operator-precedence bug in the low-battery SMS condition (!= -1 & ... < 10 was always False; alert never fired).

Promoted to production (prod checkpointed for rollback). PR #279 open. Branch feature/smartbutton_message_rewording.

[sbg-webapp] 2026-06-04 17:30: PR — nginx asset-fallback companion (server-configurations)
Thu, 04 Jun 2026 17:30
[sbg-webapp] 2026-06-04 17:00: PR — vendor-chunk split + previous-release symlinks (sbg-webapp #1515)
Thu, 04 Jun 2026 17:00

- Vendor-chunk split (vite.config.ts): build.rollupOptions.output.manualChunks splits stable node_modules into 10 vendor chunks (vendor-vue, vendor-vuetify, vendor-apollo, vendor-charts, vendor-maps, vendor-icons, vendor-auth, vendor-rbac, vendor-utils, vendor-misc). ~2.6 MB of JS/CSS now caches across deploys; the central index chunk dropped from 3.3 MB → 964 KB. A/B verified: a one-line app source change rotates ~86 app-chunk hashes but zero vendor-chunk hashes.

- Capistrano deploy:rotate_previous_release_symlinks (lib/capistrano/tasks/asset_slots.rake): post-deploy:cleanup hook that updates previous-release-1..previous-release-3 symlinks in deploy_to to the 3 most recent prior releases (matches keep_releases = 4). Verified on staging: symlinks point at the expected prior timestamps after deploy.

[sbg-webapp] 2026-06-04 16:30: Investigation — cascade is via static imports of central `index` chunk
Thu, 04 Jun 2026 16:30
[sbg-webapp] 2026-06-03 16:00: Build — investigated cascade through central `index` chunk
Wed, 03 Jun 2026 16:00
[sbg-webapp] 2026-06-03 14:36: Main — auto-reload on Vite preload error so stale bundles recover
Wed, 03 Jun 2026 14:36
[sbg-webapp] 2026-06-03 12:13: Apollo — retry HTTP GraphQL requests on transient 5xx
Wed, 03 Jun 2026 12:13
[sbg-webapp] 2026-06-03 09:30: Refrigeration — default fridge dashboard timeframe to 1 week
Wed, 03 Jun 2026 09:30
[sbg-webapp] 2026-06-02 16:01: Refrigeration — fridge report selection model (Copilot review)
Tue, 02 Jun 2026 16:01
[sbg-webapp] 2026-06-02 15:58: Refrigeration — drop O(n²) resolver patterns (Copilot review)
Tue, 02 Jun 2026 15:58
[sbg-webapp] 2026-06-02 15:42: Refrigeration — match dashboard widget muted style on no-sensors alert across surfaces
Tue, 02 Jun 2026 15:42
[sbg-webapp] 2026-06-02 15:31: Refrigeration — drop trailing arrow on no-sensors CTA link
Tue, 02 Jun 2026 15:31
[sbg-webapp] 2026-06-02 15:21: Refrigeration — extract FridgeNoSensorsAlert shared component
Tue, 02 Jun 2026 15:21
[sbg-webapp] 2026-06-02 15:11: Refrigeration — same CTA link on asset-dashboard no-sensors alert
Tue, 02 Jun 2026 15:11
[sbg-webapp] 2026-06-02 15:04: Refrigeration — same CTA link on inspector no-sensors alert
Tue, 02 Jun 2026 15:04
[sbg-webapp] 2026-06-02 14:58: Refrigeration — CTA link on unconfigured fridge alert
Tue, 02 Jun 2026 14:58
[sbg-webapp] 2026-06-02 14:46: Refrigeration — move no-sensors alert into the hero slot
Tue, 02 Jun 2026 14:46
[sbg-webapp] 2026-06-02 14:31: useAsset — pull device properties on childLinks selection
Tue, 02 Jun 2026 14:31
[sbg-webapp] 2026-06-02 14:23: Refrigeration — bump fridge status-dot tooltip font-size
Tue, 02 Jun 2026 14:23
[sbg-webapp] 2026-06-02 14:20: Refrigeration — restore colored two-column tooltip content
Tue, 02 Jun 2026 14:20
[sbg-webapp] 2026-06-02 14:13: Refrigeration — match PropertyValue tooltip style on the status dot
Tue, 02 Jun 2026 14:13
[sbg-webapp] 2026-06-02 14:01: Refrigeration — per-sensor tooltip on the fridge status dot
Tue, 02 Jun 2026 14:01
[sbg-webapp] 2026-06-02 13:38: Refrigeration — redo fridge status dot as online/offline rollup
Tue, 02 Jun 2026 13:38
[sbg-webapp] 2026-06-02 12:51: Refrigeration — code-review followups on compound status dot
Tue, 02 Jun 2026 12:51
[sbg-webapp] 2026-06-02 12:41: Refrigeration — compound asset status dot for fridges
Tue, 02 Jun 2026 12:41
[sbg-webapp] 2026-06-02 09:11: Refrigeration — fridge report cells use AssetsTablePropertyValue
Tue, 02 Jun 2026 09:11
[sbg-webapp] 2026-06-02 09:00: Refrigeration — dedupe snapshot derivation + wire table headers through i18n
Tue, 02 Jun 2026 09:00
[sbg-webapp] 2026-06-02 08:56: Refrigeration — rework Fridges report section as a proper data table
Tue, 02 Jun 2026 08:56
[sbg-webapp] 2026-06-01 20:06: Refrigeration — Fridges section in the sensor data report (initial card layout)
Mon, 01 Jun 2026 20:06
[sbg-webapp] 2026-06-01 19:59: Refrigeration — simplify floorplan popup hero to temp/humidity with power fallback
Mon, 01 Jun 2026 19:59
[sbg-webapp] 2026-06-01 19:47: Refrigeration — fridge hero on the floorplan popup
Mon, 01 Jun 2026 19:47
[sbg-webapp] 2026-06-01 19:40: Refrigeration — fridge asset inspector status panel
Mon, 01 Jun 2026 19:40
[sbg-webapp] 2026-06-01 19:37: Dashboard — surface non-smart assets that register a DashboardWidget
Mon, 01 Jun 2026 19:37
[sbg-webapp] 2026-06-01 18:44: Refrigeration — fridges as cards on the building dashboard
Mon, 01 Jun 2026 18:44
[sbg-webapp] 2026-06-01 18:40: useBuildingAssets — opt-in `includeChildLinks` flag
Mon, 01 Jun 2026 18:40
[sbg-webapp] 2026-06-01 18:33: Refrigeration — useFridgeProperties composable
Mon, 01 Jun 2026 18:33
[sbg-webapp] 2026-06-01 17:56: Refrigeration — design spec + implementation plan for fridges-as-ubx-devices
Mon, 01 Jun 2026 17:56
[sbg-webapp] 2026-06-01 09:23: docs — use placeholder for Auth0 domain in auth-overview (Copilot review)
Mon, 01 Jun 2026 09:23
[sbg-webapp] 2026-06-01 09:22: main — spell out the cacheLocation=localstorage XSS tradeoff inline (Copilot review)
Mon, 01 Jun 2026 09:22
[sbg-webapp] 2026-06-01 09:21: main — preserve query + hash in Auth0 onRedirectCallback fallback (Copilot review)
Mon, 01 Jun 2026 09:21
[sbg-webapp] 2026-06-01 09:21: Apollo — don't strand bounceToLogin's flag if Auth0 SDK isn't ready (Copilot review)
Mon, 01 Jun 2026 09:21

1. loginWithRedirect() returns undefined from the Auth0 SPA SDK when its internal auth0Client isn't initialized yet (init failure, storage blocked, plugin not mounted, etc.). The previous ?.catch() bypassed the rejection handler when the result was undefined, so redirectingToLogin stayed true forever, hanging every subsequent getAuthorizationHeader() caller. Detect the undefined return and reset the flag synchronously.

2. targetPath previously concatenated only pathname + search, dropping window.location.hash. Deep-link routes that rely on the URL fragment lost it across the Auth0 round-trip. Include hash too.

[sbg-webapp] 2026-05-27 16:34: Asset — fold parent-link data into useAsset to remove duplicate queries (Copilot review)
Wed, 27 May 2026 16:34
[sbg-webapp] 2026-05-27 13:14: BuildingFloorplansTab — pick up new ?assetUuid deep-links after mount (Copilot review)
Wed, 27 May 2026 13:14
[sbg-webapp] 2026-05-27 13:01: docs — split the Auth0 expiry table into token vs SSO-session sections
Wed, 27 May 2026 13:01
[sbg-webapp] 2026-05-27 12:48: docs — record concrete tenant SSO session values + user-impact wording
Wed, 27 May 2026 12:48
[sbg-webapp] 2026-05-27 12:13: docs — correct the SSO Session Timeout row in the auth lifetime table
Wed, 27 May 2026 12:13
[sbg-webapp] 2026-05-27 12:09: Apollo — detect auth-recoverable errors by error-shape instead of code allowlist
Wed, 27 May 2026 12:09
[sbg-webapp] 2026-05-27 12:07: Apollo — don't propagate auth errors past bounceToLogin
Wed, 27 May 2026 12:07
[sbg-webapp] 2026-05-27 11:59: Apollo — redirect to login on missing_refresh_token + mfa/access_denied
Wed, 27 May 2026 11:59
[sbg-webapp] 2026-05-27 11:44: docs — explain the app-tokens vs tenant-SSO-session two-layer model
Wed, 27 May 2026 11:44
[sbg-webapp] 2026-05-27 11:37: Apollo — dedupe loginWithRedirect across concurrent auth failures
Wed, 27 May 2026 11:37
[sbg-webapp] 2026-05-27 11:05: Apollo — redirect to login on invalid_grant + interaction_required too
Wed, 27 May 2026 11:05
[sbg-webapp] 2026-05-27 11:01: docs — explain the user-visible effect of the Auth0 lifetime values
Wed, 27 May 2026 11:01
[sbg-webapp] 2026-05-27 10:53: docs — add authentication overview
Wed, 27 May 2026 10:53
[sbg-webapp] 2026-05-26 17:05: Apollo — wire errorLink into the client + handle auth-shaped network errors
Tue, 26 May 2026 17:05
[sbg-webapp] 2026-05-26 17:03: Apollo — bounce to interactive login when getAccessTokenSilently fails
Tue, 26 May 2026 17:03
[sbg-webapp] 2026-05-26 17:03: Auth0 — enable refresh tokens to fix Safari ITP silent-refresh failure
Tue, 26 May 2026 17:03
[sbg-webapp] 2026-05-21 09:41: InstallWizard — promote Mark Completed to a primary green button when ready
Thu, 21 May 2026 09:41
[sbg-webapp] 2026-05-21 09:40: InstallWizard — prompt to save dirty fields before close or mark-complete
Thu, 21 May 2026 09:40
[sbg-webapp] 2026-05-21 09:39: InstallWizard — say "steps" instead of "tasks" in mark-complete confirm
Thu, 21 May 2026 09:39
[sbg-webapp] 2026-05-20 16:36: FloorSelectorCard — clear floor/asset deep-link query when switching floors
Wed, 20 May 2026 16:36
[sbg-webapp] 2026-05-20 16:36: AssetInspector — move parent-asset-links into the header toolbar
Wed, 20 May 2026 16:36
[sbg-webapp] 2026-05-20 16:22: AssetView — Photos tab with carousel in a dashboard-style card
Wed, 20 May 2026 16:22
[sbg-webapp] 2026-05-20 13:46: ParentAssetLinks — floor pin + floorplan deep link with marker highlight
Wed, 20 May 2026 13:46
[sbg-webapp] 2026-05-20 10:17: setAssetInstallComplete — wrap DB.execute in `with DB:` (backend review fix)
Wed, 20 May 2026 10:17
[sbg-webapp] 2026-05-20 10:02: InstallWizard — Mark as incomplete uses the project link color
Wed, 20 May 2026 10:02
[sbg-webapp] 2026-05-20 09:55: InstallWizard — align effectiveInstalled with explicit flag; link is a button (review fixes)
Wed, 20 May 2026 09:55

Copilot code review on PR #1490 flagged:

1. effectiveInstalled was derived from effectiveSteps.value.name (the implicit-old gate) while the new Mark Completed UI keyed off installStatus.installed (the explicit flag). A named-but-unmarked asset would render with a green check icon + no SetUpChip + a Mark Completed button — contradictory.

- Switched effectiveInstalled to (installedOverride ?? installStatus?.installed).

- Added an installedOverride ref that markComplete() / onMarkIncomplete() set right after the mutation so the header icon, chip, and close() dismiss logic react instantly before the parent refetches. Resets on assetUuid change alongside the existing dismissed reset.

- Mark Completed button + Mark as incomplete link both now key off effectiveInstalled so they participate in the same optimistic flip.

2. The <a href="#"> for Mark as incomplete was less accessible than a button (no Space activation, no :disabled semantics). Replaced with a <button> styled to read as an inline link — keeps the visual, gains real button semantics, supports :disabled during in-flight mutation. CSS strips native button chrome and adds a disabled state.

3. Comma splice in the confirm-dialog body flagged but left as-is (UI copy iterated on twice; Barry's call).

[sbg-webapp] 2026-05-20 09:34: Remove low-value setAssetInstallComplete integration test
Wed, 20 May 2026 09:34
[sbg-webapp] 2026-05-20 09:30: setAssetInstallComplete integration test — align expected with non-UBX bypass
Wed, 20 May 2026 09:30
[sbg-webapp] 2026-05-19 17:24: InstallStatus — non-UBX assets always read as installed (backend)
Tue, 19 May 2026 17:24
[sbg-webapp] 2026-05-19 17:09: InstallWizard — confirm body says "this device" not "it"
Tue, 19 May 2026 17:09
[sbg-webapp] 2026-05-19 17:06: InstallWizard — confirm dialog body names the actual concern
Tue, 19 May 2026 17:06
[sbg-webapp] 2026-05-19 17:01: InstallWizard — success snackbar after marking complete
Tue, 19 May 2026 17:01
[sbg-webapp] 2026-05-19 16:50: InstallWizard — skip confirm dialog when all setup steps are done
Tue, 19 May 2026 16:50
[sbg-webapp] 2026-05-19 16:44: InstallWizard — Mark as incomplete renders as a plain link
Tue, 19 May 2026 16:44
[sbg-webapp] 2026-05-19 16:39: InstallWizard — text-link "Mark as incomplete" for already-installed devices
Tue, 19 May 2026 16:39
[sbg-webapp] 2026-05-19 16:34: InstallWizard — hide Mark Completed for already-installed devices
Tue, 19 May 2026 16:34
[sbg-webapp] 2026-05-19 16:30: InstallWizard — confirm-dialog body now reflects actual behaviour
Tue, 19 May 2026 16:30
[sbg-webapp] 2026-05-19 16:22: setAssetInstallComplete mutation variable type fix (frontend)
Tue, 19 May 2026 16:22
[sbg-webapp] 2026-05-19 16:18: InstallWizard — swap button order (Mark Completed first, then Close)
Tue, 19 May 2026 16:18
[sbg-webapp] 2026-05-19 16:10: AssetBase accepts install_complete as a Private field (backend follow-up)
Tue, 19 May 2026 16:10
[sbg-webapp] 2026-05-19 08:53: install_complete column added to create-table schema (backend follow-up)
Tue, 19 May 2026 08:53
[sbg-webapp] 2026-05-18 16:02: InstallWizard — wire Mark Completed to setAssetInstallComplete (frontend)
Mon, 18 May 2026 16:02
[sbg-webapp] 2026-05-18 16:00: InstallWizard — Close + Mark Completed buttons with confirm dialog (frontend)
Mon, 18 May 2026 16:00
[sbg-webapp] 2026-05-18 15:56: setAssetInstallComplete GraphQL mutation wrapper (frontend)
Mon, 18 May 2026 15:56
[sbg-webapp] 2026-05-18 15:53: setAssetInstallComplete mutation + perms (backend)
Mon, 18 May 2026 15:53

- complete: trueinstall_complete=TRUE, installation_date=now() (overwrites — fresh install on re-mark after move/repurpose)

- complete: falseinstall_complete=FALSE, installation_date=NULL (cleared so a future re-mark starts clean)

[sbg-webapp] 2026-05-18 15:42: _compute_install_status reads explicit install_complete flag (backend)
Mon, 18 May 2026 15:42
[sbg-webapp] 2026-05-18 15:30: Asset — add explicit install_complete column + backfill (backend)
Mon, 18 May 2026 15:30
[sbg-webapp] 2026-05-18 15:18: Asset dashboard — side-by-side floorplan preview + photo carousel
Mon, 18 May 2026 15:18
[sbg-webapp] 2026-05-18 10:09: Remove Claude auto PR-review workflow in favor of Copilot
Mon, 18 May 2026 10:09
[sbg-webapp] 2026-05-14 16:57: Deploy workflow — forward GitHub deploy key to server
Thu, 14 May 2026 16:57
[sbg-webapp] 2026-05-14 16:41: Deploy workflow — comment deployed URL on success
Thu, 14 May 2026 16:41
[sbg-webapp] 2026-05-14 16:40: Deploy workflow — pin ed25519 gem to 1.3.0
Thu, 14 May 2026 16:40
[sbg-webapp] 2026-05-14 16:37: Deploy workflow — strip CR from /deploy comment body
Thu, 14 May 2026 16:37
[sbg-webapp] 2026-05-14 16:07: Deploy workflow — install ed25519 + bcrypt_pbkdf gems
Thu, 14 May 2026 16:07
[sbg-webapp] 2026-05-14 15:41: Deploy a PR to dev or staging via `/deploy <env>` comment
Thu, 14 May 2026 15:41
[sbg-webapp] 2026-05-13 11:16: Asset dashboard — floorplan preview card showing the asset's pin
Wed, 13 May 2026 11:16
[sbg-webapp] 2026-05-13 10:53: UBX-TSTAT-EXT1 — display temperature with 0.1° precision
Wed, 13 May 2026 10:53
[sbg-webapp] 2026-05-12 16:37: Floorplan tooltip — fix drag-suppression regression
Tue, 12 May 2026 16:37
[sbg-webapp] 2026-05-12 16:33: Floorplan tooltip — tighter hover, dismiss on leave, hide while dragging
Tue, 12 May 2026 16:33
[sbg-webapp] 2026-05-12 13:48: Breadcrumbs — surface parent assets; relocate header row
Tue, 12 May 2026 13:48
[sbg-webapp] 2026-05-12 13:01: ParentAssetLinks — collapse duplicate parents into one back-link
Tue, 12 May 2026 13:01
[sbg-webapp] 2026-05-12 12:49: ParentAssetLinks — back-link from child asset to its parents
Tue, 12 May 2026 12:49
[sbg-webapp] 2026-05-12 12:15: AssetSelector — sort multi-mode by displayed name; dedupe helper
Tue, 12 May 2026 12:15
[sbg-webapp] 2026-05-12 11:56: AssetSelector — show "Unnamed" for blank-name assets
Tue, 12 May 2026 11:56
[sbg-webapp] 2026-05-11 17:09: FormField — fix mode-change validation false-positives (#1473)
Mon, 11 May 2026 17:09

1. Path rebind, no unmount (Heat↔Cool on a dual setpoint device). Vee-validate's internal pathStateLookup migrates to the new path but formValues[newPath] is left empty. form.validate() then validates against an undefined value and emits "Required field" even though our model has the data and the displayed input has the right value. Fix: a watch(fullName, async () => { await nextTick(); resetField(...); validateField(); }) re-seeds value + initialValue from the model after vee-validate's own nextTick migration, and validateField() triggers a fresh validateWithStateMutation so withLatest dedup suppresses the rules watcher's stale-value result.

2. Path rebind WITH unmount (Cool→Auto on a dual setpoint device). v-if/v-else swaps the single target_temperature form-field out for the two-field [4]/[5] pair. Vee-validate's internal path-migration watcher lives in the FormField's effectScope and is cancelled before it can migrate pathStateLookup. useField's own onBeforeUnmount then looks up the new path, finds nothing (matchesId false), takes an early-return, and never calls removePathState. The leaked state survives in pathStates.value with a stale path Ref that resolves to [3], and every subsequent form.validate() reports "Required field" on a phantom target_temperature[3]. Fix: inject FormContextKey, capture useField's id as fieldId, register our own onBeforeUnmount after useField's, scrub any leaked state whose id === fieldId straight out of getAllPathStates().

[sbg-webapp] 2026-05-11 14:03: Cumulative occupancy dashboard — mount install wizard directly
Mon, 11 May 2026 14:03
[sbg-webapp] 2026-05-11 13:59: Gateway dashboard — convert to DeviceDashboardLayout
Mon, 11 May 2026 13:59
[sbg-webapp] 2026-05-11 13:57: DeviceDashboardLayout — adopt useInstallWizardMount
Mon, 11 May 2026 13:57
[sbg-webapp] 2026-05-11 13:51: Extract useInstallWizardMount composable
Mon, 11 May 2026 13:51
[sbg-webapp] 2026-05-07 20:52: Floorplan pin tooltip polish + a few small bug fixes
Thu, 07 May 2026 20:52

Mostly floorplan-tooltip iteration plus a handful of orthogonal fixes.

[sbg-webapp] 2026-05-07 12:42: Refresh page outside wizard on save without full reload
Thu, 07 May 2026 12:42

Three coupled fixes so dashboards / breadcrumbs / inspector reflect in-wizard edits without manual refresh.

[sbg-webapp] 2026-05-07 10:01: Soften install gate to name-only + drop building step from wizard
Thu, 07 May 2026 10:01
[sbg-webapp] 2026-05-06 13:49: Wizard header polish — orange Set-up chip + progress underline
Wed, 06 May 2026 13:49
[sbg-webapp] 2026-05-06 13:38: Show collapsed install wizard on asset dashboard for unfinished setup
Wed, 06 May 2026 13:38
[sbg-webapp] 2026-05-06 13:00: Render UBX serials in Roboto Mono so the slashed zero matches the printed label
Wed, 06 May 2026 13:00
[sbg-webapp] 2026-05-05 16:54: Setup CTA chip on dashboard widgets + tightened banner copy
Tue, 05 May 2026 16:54
[sbg-webapp] 2026-05-05 15:48: Server-side install status + dashboard banner + wizard simplification
Tue, 05 May 2026 15:48
[sbg-webapp] 2026-05-05 13:57: Show UBX Serial column in tabular reports
Tue, 05 May 2026 13:57
[sbg-webapp] 2026-05-05 11:26: Latch install wizard's initial collapsed state
Tue, 05 May 2026 11:26
[sbg-webapp] 2026-05-05 11:20: Hide marker hover tooltip on floorplan inside install wizard
Tue, 05 May 2026 11:20
[sbg-webapp] 2026-05-05 10:28: Asset install status + collapse install wizard when complete
Tue, 05 May 2026 10:28
[sbg-webapp] 2026-05-05 09:36: Floorplan tooltip stays open and renders below the marker
Tue, 05 May 2026 09:36
[sbg-webapp] 2026-05-04 14:33: Revert asset inspector multi-property layout changes
Mon, 04 May 2026 14:33
[sbg-webapp] 2026-05-04 14:19: Floorplan tooltip shows second primary property next to the first
Mon, 04 May 2026 14:19
[sbg-webapp] 2026-05-04 13:56: Render thermostat humidity in its own column next to temperature
Mon, 04 May 2026 13:56
[sbg-webapp] 2026-05-04 13:51: Inspector multi-property layout; floorplan tooltip below marker
Mon, 04 May 2026 13:51
[sbg-webapp] 2026-05-04 13:33: Switch floorplan tooltip to Leaflet's native LTooltip
Mon, 04 May 2026 13:33
[sbg-webapp] 2026-05-04 13:22: Add hover tooltip on floorplan pins
Mon, 04 May 2026 13:22
[sbg-webapp] 2026-05-04 09:15: Rename KnownAsset.dashboardSection to reportingSection
Mon, 04 May 2026 09:15
[sbg-webapp] 2026-04-30 15:54: Apply category sections + friendly-name labels to thresholds report
Thu, 30 Apr 2026 15:54
[sbg-webapp] 2026-04-30 13:42: Fix sensor-data report render error from merged-config tables
Thu, 30 Apr 2026 13:42
[sbg-webapp] 2026-04-30 13:37: Group sensor-data report by category, then by friendly name
Thu, 30 Apr 2026 13:37
[sbg-webapp] 2026-04-30 12:42: Decouple dashboard category ordering from use-dashboard-config
Thu, 30 Apr 2026 12:42
[sbg-webapp] 2026-04-30 12:18: Move dashboard category assignment onto KNOWN_ASSETS
Thu, 30 Apr 2026 12:18
[sbg-webapp] 2026-04-29 16:30: Surface friendly name + SN in asset header; extend Unnamed fallback further
Wed, 29 Apr 2026 16:30
[sbg-webapp] 2026-04-29 15:54: Apply Unnamed fallback to asset header
Wed, 29 Apr 2026 15:54
[sbg-webapp] 2026-04-29 12:23: Fix asset inspector summary missing for non-UBX known assets
Wed, 29 Apr 2026 12:23
[sbg-webapp] 2026-04-29 12:20: Apply Unnamed fallback to inspector title; wrap dashboard tab tr's in tbody
Wed, 29 Apr 2026 12:20
[sbg-webapp] 2026-04-29 11:51: Style asset inspector primary summary at 16px / rgba(0,0,0,0.78)
Wed, 29 Apr 2026 11:51
[sbg-webapp] 2026-04-29 11:33: Collapse asset inspector details into a single contextual summary line
Wed, 29 Apr 2026 11:33
[sbg-webapp] 2026-04-29 11:24: Centralize Unnamed fallback in SmartAssetName, surface friendly name + SN on chips and pins
Wed, 29 Apr 2026 11:24
[sbg-webapp] 2026-04-29 10:25: Surface serial number and friendly name on building dashboard cards
Wed, 29 Apr 2026 10:25
[sbg-webapp] 2026-04-29 10:00: Add friendlyName to UBX known assets
Wed, 29 Apr 2026 10:00
[sbg-webapp-vue3] 2026-04-27 18:15: Restructure alert dashboard around multi-asset incidents timeline
Mon, 27 Apr 2026 18:15

1. Alert Home (white card): config + recipients (unchanged AlertConfigSummary)

2. Incidents (NEW): Gantt-style Highcharts xrange chart with one row per scope asset; each bar is a firing. Bars include firings on the scope asset itself and on its linked child sensors (resolved via the asset's childLinks GraphQL field). Date range picker (shared with Details) sits above.

3. Details (only when an instance is selected via timeline click or ?ai=): a single PropertyGraph for the associated scope asset's property + the existing AlertInstanceBanner.

[standalone-dev-env-gql-repos-sbp-mono] 2026-04-27 16:51: Bump alert durations to 10 min - 8 hr
Mon, 27 Apr 2026 16:51
[standalone-dev-env-gql-repos-sbp-mono] 2026-04-27 16:47: Constrain ACTIVE/PENDING to recent anchors
Mon, 27 Apr 2026 16:47
[standalone-dev-env-gql-repos-sbp-mono] 2026-04-27 16:39: Shorter, slot-spaced alerts + --clear flag
Mon, 27 Apr 2026 16:39
[standalone-dev-env-gql-repos-sbp-mono] 2026-04-27 11:30: Move alert simulator to its own branch and push
Mon, 27 Apr 2026 11:30
[standalone-dev-env-gql-repos-sbp-mono] 2026-04-27 11:25: Commit alert firing simulator to sbp-mono
Mon, 27 Apr 2026 11:25
[standalone-dev-env-gql-repos-sbp-mono] 2026-04-27 11:23: Build dev-script to simulate alert firings for local UI testing
Mon, 27 Apr 2026 11:23
[standalone-dev-env-gql-repos-sbp-mono] 2026-04-27 11:23: Add generic dev-script launcher to standalone-dev-env
Mon, 27 Apr 2026 11:23
[sbg-webapp-vue3] 2026-04-23 15:10: Alert dashboard — white outer section + dashboard-widget cards
Thu, 23 Apr 2026 15:10
[sbg-webapp-vue3] 2026-04-23 14:20: Lighter instance banner + linkable asset chips
Thu, 23 Apr 2026 14:20
[sbg-webapp-vue3] 2026-04-23 13:50: Redesign Alert Config Dashboard UX
Thu, 23 Apr 2026 13:50

- Condition card: condition property, dwell time, active periods, assets

- Recipients card: each recipient as a row with email/SMS delivery icons (muted when disabled), per-recipient Snooze and work-schedule icon stubs, collective "Snooze all" button in the card header

[sbg-webapp-vue3] 2026-04-23 12:52: Alert Config Dashboard return button
Thu, 23 Apr 2026 12:52
[sbg-webapp-vue3] 2026-04-23 12:39: Fix alert bars for linked-sensor alerts
Thu, 23 Apr 2026 12:39
[sbg-webapp-vue3] 2026-04-23 12:06: Fix dashboard date props disrupting store subscription
Thu, 23 Apr 2026 12:06
[sbg-webapp-vue3] 2026-04-23 12:02: Fix Return button icon regression
Thu, 23 Apr 2026 12:02
[sbg-webapp-vue3] 2026-04-23 11:42: Short alert redirect URLs for notifications
Thu, 23 Apr 2026 11:42
[sbg-webapp] 2026-04-20 19:23: Clean up Vuetify 3 layout bugs on Ops Agents pages
Mon, 20 Apr 2026 19:23

1. Chevrons stacking below the row on the Available Agents and Active Customers lists — the icons were in v-list-item's default slot where Vuetify 3 stacks children vertically. Moved them into #append.

2. Status chip and action buttons vertically stacked on the Configured Agents list. The chip was wrapped in a second v-list-item-subtitle (new line) and the three buttons each took their own row. Put the chip inline with the title and moved the buttons into a .agent-actions flex row below the subtitle (wraps on narrow widths).

3. All list-item link text rendering in brand blue — the global .v-theme--light a:not(...) rule in styles.scss painted every anchor blue, and Vuetify 3's v-list-item with :to renders as <a>, so list-item titles and subtitles inherited the blue. Extended the :not() exclusion to skip .v-list-item and its descendants, matching the rule's original intent (V2 list items weren't anchors).

[sbg-webapp] 2026-04-20 19:05: Fix blank customer list in Ops Agents config
Mon, 20 Apr 2026 19:05
[standalone-dev-env-gql-repos-sbp-mono] 2026-04-16 20:30: Fix inherited_access_map race that returned empty Group.buildings on concurrent requests
Thu, 16 Apr 2026 20:30
[sbg-webapp] 2026-04-16 13:05: Show spinner while install wizard building query loads
Thu, 16 Apr 2026 13:05
[sbg-webapp] 2026-04-16 12:16: Fix floor auto-reselect after clear, rename useAssetBySerial param
Thu, 16 Apr 2026 12:16
[sbg-webapp] 2026-04-16 11:11: Edit mfgSerialNumber in asset form, drop serialNumber from mutations
Thu, 16 Apr 2026 11:11
[sbg-webapp] 2026-04-15 18:15: Scope dashboard widget fit-content rule to hero only
Wed, 15 Apr 2026 18:15
[sbg-webapp] 2026-04-15 13:03: Drop redundant @dblclick on fallback dashboard-widget
Wed, 15 Apr 2026 13:03
[sbg-webapp] 2026-04-15 12:49: Remove debug logging from DashboardWidget card click
Wed, 15 Apr 2026 12:49
[sbg-webapp] 2026-04-15 12:30: Shrink .property-value to content inside dashboard widgets
Wed, 15 Apr 2026 12:30
[sbg-webapp] 2026-04-15 12:22: Drop redundant property-value wrappers (fix hero width)
Wed, 15 Apr 2026 12:22
[sbg-webapp] 2026-04-15 12:19: Move card-click origin check onto PropertyValue class
Wed, 15 Apr 2026 12:19
[sbg-webapp] 2026-04-15 12:15: Extend double-click-to-asset-dashboard to pins, tables, thresholds
Wed, 15 Apr 2026 12:15
[sbg-webapp] 2026-04-15 12:07: Use event.target check to gate card click
Wed, 15 Apr 2026 12:07
[sbg-webapp] 2026-04-15 11:55: Wrap property-value with @click.stop div
Wed, 15 Apr 2026 11:55
[sbg-webapp] 2026-04-15 11:47: Enable dashboard card click on mobile
Wed, 15 Apr 2026 11:47
[sbg-webapp] 2026-04-14 15:36: Install wizard floorplan pointer cursor and install shortcut route
Tue, 14 Apr 2026 15:36
[sbg-webapp] 2026-04-14 15:00: Fix floorplan pin not appearing after placement in install wizard
Tue, 14 Apr 2026 15:00
[sbg-webapp] 2026-04-13 15:18: Double-click dashboard card opens asset dashboard
Mon, 13 Apr 2026 15:18
[sbg-webapp] 2026-04-13 12:35: Configured impeccable design skill for UBX
Mon, 13 Apr 2026 12:35
[sbg-webapp] 2026-04-09 16:32: Install wizard photo delete and lightbox
Thu, 09 Apr 2026 16:32
[sbg-webapp] 2026-04-09 16:26: Install wizard photo lightbox
Thu, 09 Apr 2026 16:26
[sbg-webapp] 2026-04-09 16:10: Install wizard photo loading states
Thu, 09 Apr 2026 16:10
[sbg-webapp] 2026-04-09 16:03: Install wizard floor selector fix
Thu, 09 Apr 2026 16:03
[sbg-webapp] 2026-04-09 16:03: Install wizard floor selector fix
Thu, 09 Apr 2026 16:03
[sbg-webapp] 2026-04-09 15:33: Portless support fixes
Thu, 09 Apr 2026 15:33
[sbg-webapp-vue3] 2026-04-09 14:25: Fix stale Apollo cache in useAccountBuildings
Thu, 09 Apr 2026 14:25
[sbg-webapp-vue3] 2026-04-09 14:20: Install wizard — reorder steps, add reload link
Thu, 09 Apr 2026 14:20

- Multiple: dropdown selector that moves the asset via moveAssetsMutation on selection

- Single: plain text (non-editable)

- Empty: "No buildings loaded." with a reload link — added for testing while the backend race condition is unresolved

[sbg-webapp-vue3] 2026-04-09 14:15: Rebuild portless-support branch
Thu, 09 Apr 2026 14:15
[sbg-webapp] 2026-04-09: Make building dashboard section collapsed state ephemeral
Thu, 09 Apr 2026
[sbg-webapp-vue3] 2026-04-08 16:37: Install wizard — building selector step
Wed, 08 Apr 2026 16:37
[sbg-webapp] 2026-04-08 10:00: Support portless.sh for local development
Wed, 08 Apr 2026 10:00
[sbg-webapp] 2026-04-07 14:03: Install wizard prototype for new device setup
Tue, 07 Apr 2026 14:03
[sbg-webapp-vue3] 2026-04-06: Alert feedback fixes — grouping, graphs, link styling
Mon, 06 Apr 2026
[sbg-webapp-vue3] 2026-04-03: Alert Config Dashboard & Alerts Tab Updates
Fri, 03 Apr 2026
[sbg-webapp-vue3] 2026-04-02: Fix TypeScript warnings in CI
Thu, 02 Apr 2026
[sbg-webapp-vue3] 2026-04-02: Targeted AWS tunnel cleanup in deploy script
Thu, 02 Apr 2026
[sbg-webapp-vue3] 2026-04-02: Fix AssetSelector group header selecting non-asset item
Thu, 02 Apr 2026
[sbg-webapp-vue3] 2026-04-02: Fix Vuetify 3 item.raw and custom-filter in selectors
Thu, 02 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Fix dashboard search hiding search box on no results
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Address PR review comments on building-dashboard-v2
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Exclude inferred schedule_enabled from panel status aggregation
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Position status icon next to panel title
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Skip pending state sync when device lock is expired
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Show failure for stale pending fields on unlocked devices
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Suppress pending spinner when device is not locked
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Validate parsed DateTime for device lock expiration
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Handle null schedule_days in schedule bank conversion
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-04-01: Ignore expired device locks
Wed, 01 Apr 2026
[sbg-webapp-vue3] 2026-03-31: Fix form dirty state not resetting after save (Vue 3 upgrade regression)
Tue, 31 Mar 2026
[sbg-webapp-vue3] 2026-03-31: Dismiss status tooltip on click
Tue, 31 Mar 2026
[sbg-webapp-vue3] 2026-03-31: Restore Vuetify 2 tooltip color and offset
Tue, 31 Mar 2026
[sbg-webapp-vue3] 2026-03-31: Fix validation messages showing raw translation keys (Vue 3 upgrade regression)
Tue, 31 Mar 2026
[sbg-webapp-vue3] 2026-03-30: Fix mobile date range preset list styling
Mon, 30 Mar 2026
[sbg-webapp-vue3] 2026-03-30: Rename Vuetify 2 typography classes to Vuetify 3 equivalents
Mon, 30 Mar 2026
[sbg-webapp-vue3] 2026-03-30: Update occupancy labels to "since last report"
Mon, 30 Mar 2026
[sbg-webapp-vue3] 2026-03-30: Fix tooltip z-index in asset inspector
Mon, 30 Mar 2026
[sbg-webapp-vue3] 2026-03-30: Floorplan asset inspector full viewport height
Mon, 30 Mar 2026
[sbg-webapp-vue3] 2026-03-30: Asset inspector open-in-new icon stays visible on title overflow
Mon, 30 Mar 2026
[sbg-webapp-vue3] 2026-03-30: Fix string switch OFF toggle not sending mutation (Vue 3 upgrade regression)
Mon, 30 Mar 2026
[sbg-webapp-vue3] 2026-03-26 13:30: Fix asset inspector toolbar title and widget click handling
Thu, 26 Mar 2026 13:30
[sbg-webapp-vue3] 2026-03-26 13:00: Update default dashboard categories and sort order
Thu, 26 Mar 2026 13:00
[sbg-webapp-vue3] 2026-03-26 12:30: Dashboard section asset count chip style
Thu, 26 Mar 2026 12:30
[sbg-webapp-vue3] 2026-03-26 12:00: Mobile dashboard widgets — title-only click to open inspector
Thu, 26 Mar 2026 12:00
[sbg-webapp-vue3] 2026-03-26 11:30: Fix mobile fullscreen dialog dismissing on select click
Thu, 26 Mar 2026 11:30
[sbg-webapp-vue3] 2026-03-26 11:10: Fix mobile floorplan toolbar Vue 3 regressions
Thu, 26 Mar 2026 11:10
[sbg-webapp-vue3] 2026-03-25 15:00: Dashboard cleanup
Wed, 25 Mar 2026 15:00
[sbg-webapp-vue3] 2026-03-25 14:45: Equal-size dashboard widget grid
Wed, 25 Mar 2026 14:45
[sbg-webapp-vue3] 2026-03-25 12:30: Fix reorder mode mutation flurry
Wed, 25 Mar 2026 12:30
[sbg-webapp-vue3] 2026-03-25 12:04: Remove alert indicators from dashboard cards
Wed, 25 Mar 2026 12:04
[sbg-webapp-vue3] 2026-03-25 11:59: Add search field to dashboard overview
Wed, 25 Mar 2026 11:59
[sbg-webapp-vue3] 2026-03-25 11:46: Move report strings to locale file
Wed, 25 Mar 2026 11:46
[sbg-webapp-vue3] 2026-03-25 11:35: Move table views from dashboard to standalone report pages
Wed, 25 Mar 2026 11:35
[sbg-webapp-vue3] 2026-03-25 10:03: Dashboard reorder and settings UX improvements
Wed, 25 Mar 2026 10:03
[sbg-webapp-vue3] 2026-03-25: Dashboard card click opens asset inspector
Wed, 25 Mar 2026
[sbg-webapp-vue3] 2026-03-25: Replace inspector dialog with slideout panel
Wed, 25 Mar 2026
[sbg-webapp-vue3] 2026-03-24 18:09: Add asset inspector slideout to dashboard
Tue, 24 Mar 2026 18:09
[sbg-webapp-vue3] 2026-03-24 16:09: Create dashboard widget card system
Tue, 24 Mar 2026 16:09
[sbg-webapp-vue3] 2026-03-24: Fix pre-existing lint errors across 4 files
Tue, 24 Mar 2026
[sbg-webapp-vue3] 2026-03-24: Systematic asset crawl — 36 model types audited
Tue, 24 Mar 2026
[sbg-webapp-vue3] 2026-03-23: Fix suffix text wrapping on tstat config tolerance fields
Mon, 23 Mar 2026
[sbg-webapp-vue3] 2026-03-23: Add missing i18n options for switch_status
Mon, 23 Mar 2026
[sbg-webapp-vue3] 2026-03-23: Fix Apollo subscription cache warning for assetDataChanges
Mon, 23 Mar 2026
[sbg-webapp-vue3] 2026-03-23: Set up Chrome DevTools MCP for browser debugging
Mon, 23 Mar 2026
[sbg-webapp-vue3] 2026-03-23: Fix VHover extraneous loading prop warning on occupancy dashboards
Mon, 23 Mar 2026
[sbg-webapp-vue3] 2026-03-23: Fix reactive component warning on VRF device dashboards
Mon, 23 Mar 2026
[sbg-webapp-vue3] 2026-03-19 15:30: Fix number spinner arrows on asset selector inputs
Thu, 19 Mar 2026 15:30
[sbg-webapp-vue3] 2026-03-19 15:20: Fix undefined 'value' reference in ComparePropertyDialog
Thu, 19 Mar 2026 15:20
[sbg-webapp-vue3] 2026-03-19 15:15: Fix linked property selection count not updating
Thu, 19 Mar 2026 15:15
[sbg-webapp-vue3] 2026-03-19 15:00: Fix showTimestamp prop type error from v-hover null
Thu, 19 Mar 2026 15:00
[sbg-webapp-vue3] 2026-03-19 14:45: Fix building breadcrumb linking to floorplans instead of dashboard
Thu, 19 Mar 2026 14:45
[sbg-webapp-vue3] 2026-03-19 14:30: Fix stale tstat schedule route names and style attribute
Thu, 19 Mar 2026 14:30
[sbg-webapp-vue3] 2026-03-19 14:00: Fix alert edit form showing UUIDs instead of names
Thu, 19 Mar 2026 14:00
[sbg-webapp-vue3] 2026-03-19 13:00: Fix alert copy-to-days checkboxes all selecting at once
Thu, 19 Mar 2026 13:00
[sbg-webapp-vue3] 2026-03-19 12:45: Fix energy report crash — router.currentRoute
Thu, 19 Mar 2026 12:45
[sbg-webapp-vue3] 2026-03-19 12:30: Fix date picker not updating field value
Thu, 19 Mar 2026 12:30
[sbg-webapp-vue3] 2026-03-19 12:15: Fix journal page errors
Thu, 19 Mar 2026 12:15
[sbg-webapp-vue3] 2026-03-19 10:30: Fix floorplan drag-and-drop rendering in Vue 3
Thu, 19 Mar 2026 10:30

Several drag-and-drop issues on the Building Floorplans page after the Vue 3 migration:

[sbg-webapp-vue3] 2026-03-19 10:30: Drag asset off floorplan to remove
Thu, 19 Mar 2026 10:30

Added the ability to remove an asset from a floorplan by dragging its pin off the edge of the floorplan image. When a marker's moveend fires with coordinates outside the [0, sizeY] × [0, sizeX] bounds, a confirmation dialog appears (reusing the existing "Remove from Floor" dialog strings from the asset inspector). On confirm, the asset is unplaced; on cancel, the pin clamps to the nearest floorplan edge via forceCoordsOntoFloorplan.

[sbg-webapp-vue3] 2026-03-19 09:54: Add timestamps to worklog RSS feed
Thu, 19 Mar 2026 09:54

Updated ~/.claude/bin/generate-worklog-rss.py to support optional HH:MM timestamps in worklog headings. Headings can now be ## YYYY-MM-DD HH:MM: title — the time flows through to RSS pubDate and HTML display. Entries without timestamps remain backward compatible (default to midnight).

[sbg-webapp-vue3] 2026-03-19 09:05: Vue 2 port guide for fridge dashboard alerts
Thu, 19 Mar 2026 09:05

Documented the 3 steps needed to backport fridge dashboard alert overlays to the Vue 2 branch, in case we need to ship this feature before the Vue 3 migration lands:

1. Add useBuildingAlerts to use-asset-alerts.ts and call from AssetView.vue (building-level definitions instead of asset-level)

2. Collect all displayed asset UUIDs in PropertyGraph.vue (not just primary asset)

3. Change assetUuidassetUuids in useAlertInstancesForProperties

Also notes what NOT to port (DeviceDashboardLayout refactor, store rename, Vue 3 reactivity fixes).

Doc location: ~/.claude/projects/-Users-barry-Projects-sbg-webapp-vue3/memory/reference_fridge_alerts_vue2_port.md

[sbg-webapp-vue3] 2026-03-18: Resolve alert composable naming collision
Wed, 18 Mar 2026
[sbg-webapp-vue3] 2026-03-18: Fetch building-level alert definitions
Wed, 18 Mar 2026
[sbg-webapp-vue3] 2026-03-18: Testing fridge dashboard alerts on staging
Wed, 18 Mar 2026

Tested multi-asset alert overlays on the fridge dashboard on staging. Initial deploy only had the instance query changes — discovered that alert *definitions* were still only fetched for the primary asset (AssetAlerts query), so linked asset alerts never appeared. Added useBuildingAlerts composable to fetch building-level definitions, redeployed to staging for further testing.

[sbg-webapp-vue3] 2026-03-18: Design doc — LLM-powered chat agent for UBX
Wed, 18 Mar 2026

Built a design document for integrating an LLM-powered chat agent into the platform. Users would ask natural-language questions about their buildings' HVAC systems and get data-driven suggestions.

Key design challenge: LLMs are stateless, so every request requires full context reconstruction — user identity, current building, session history, and specialist agent selection (scheduling, energy, air quality). Solution is a layered context assembly system: platform knowledge → building config → persistent building memory → specialist agent → conversation history, assembled per call and stored in the DB.

Data access runs through existing Strawberry resolvers so auth, tenant isolation, and permissions are inherited.

Phase 1 is read-only — the agent observes and advises but doesn't modify setpoints or schedules. Future phases: autonomous conversations (e.g. triggered by alerts) and tool usage (making changes with user approval).

[sbg-webapp-vue3] 2026-03-16: Fridge dashboard crash resolved + alerts on fridge graphs
Mon, 16 Mar 2026

Resolved the "Maximum recursive updates exceeded" crash that had been blocking the fridge dashboard since 2026-03-12. This was a multi-session, multi-iteration debugging effort — at least 4-5 attempted fixes across previous sessions before landing on the working approach.

Root cause

Vue 3's Object.is() reactivity check treats every computed re-evaluation as a "change" when the computed returns a new object, even if all field values are identical. The PropertyGraph component tree (Series → Group → Graph) uses exposeDataToParent to pass data upward via use-component-tree. Each level's data computed created a fresh object every evaluation, which the parent saw as changed, which triggered its own recomputation, cascading back down — an infinite reactive loop.

The fix (applied at every level of the tree)

FridgeDashboardTab refactored to DeviceDashboardLayout

LineGraph initialLoading bug fix

[sbg-webapp-vue3] 2026-03-16: Multi-asset alerts on property graphs
Mon, 16 Mar 2026
[sbg-webapp-vue3] 2026-03-16: Extract NewRelic alert conditions for self-hosted migration
Mon, 16 Mar 2026

Extracted all 36 alert conditions from the existing NewRelic instance managed by Mission Cloud, in preparation for decommissioning that instance and moving to a self-hosted NewRelic deployment.

[sbg-webapp-vue3] 2026-03-12: Fix v-data-table selection storing undefined values
Thu, 12 Mar 2026
[sbg-webapp-vue3] 2026-03-12: Fix [object Object] in DocumentCopyDialog selected value
Thu, 12 Mar 2026
[sbg-webapp-vue3] 2026-03-12: Fix [object Object] in manufacturer combobox dropdown
Thu, 12 Mar 2026
[sbg-webapp-vue3] 2026-03-12: Fix multi-select chips not rendering
Thu, 12 Mar 2026
[sbg-webapp-vue3] 2026-03-12: Fix duplicate item text in autocomplete dropdowns
Thu, 12 Mar 2026
[sbg-webapp-vue3] 2026-03-12: Fridge dashboard crash — investigation in progress
Thu, 12 Mar 2026

Two Vue 3 rendering errors when navigating to a fridge asset's dashboard tab. First error fixed; second still under investigation.

Fixed: Cannot read properties of null (reading 'emitsOptions')

Under investigation: Maximum recursive updates exceeded in component <PropertyGraphList>

[sbg-webapp-vue3] 2026-03-11: Promote dashboard layout to account default
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: Bundle code-splitting plan
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: Worklog RSS feed via Tailscale
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: Dashboard section drag-to-reorder
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: Dashboard settings dialog
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: Dashboard lazy loading and lint fixes
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: UI preference backend — fetchone fix and branch setup
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: Fix NULL user_uuid in upsert/delete for account defaults
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: Spacer scoping fix for property cards
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: GraphQL permissions for UI preferences
Wed, 11 Mar 2026
[sbg-webapp-vue3] 2026-03-11: UI preference unit tests
Wed, 11 Mar 2026

## Known Issues to Investigate

VBtnToggle slot warning on asset config page

[sbg-webapp-vue3] 2026-03-10: Building Dashboard layout and styling improvements
Tue, 10 Mar 2026

Field sizing fix for Vuetify 3

DashboardOverview styling

AssetPropertyCard layout improvements

Control panel refinements (manual edits by Barry)

Customizable dashboard layout (backend + frontend)

[sbg-webapp-vue3] 2026-03-09: Building Dashboard - live cards, icons, and bugfixes
Mon, 09 Mar 2026

Dashboard cards refactored to use live components

Building navigation defaults to Dashboard

SVG icons for all sensor types

Bugfixes

[sbg-webapp-vue3] 2026-03-04: More Vuetify 3 migration fixes
Wed, 04 Mar 2026

AppNavbar.vue + UserAvatar.vue (Profile menu)

AssetImageCarousel.vue (Lightbox)

DocumentUploadDialog.vue (Document upload)

Data table toolbar fixes (5 files)

AppFooter.vue

SelectField.vue

LightboxCarousel.vue

StandardDialog.vue (Edit Building timezone dropdown)

FormField.vue (Console warnings)

Global styles (styles.scss)

BuildingControlsTab.vue (Controls sidebar)

[sbg-webapp-vue3] 2026-03-03: Visual regression fixes for Vuetify 3 migration
Tue, 03 Mar 2026

UnplacedAssetsCard.vue + AssetChip.vue (Building Floorplans page)

PortfolioMapTab.vue + PortfolioBuildingCard.vue (Home page)

BuildingView.vue + AppLayout.vue (Tab navigation)

FileField.vue + FormField.vue (Floorplan upload dialog)

- Root cause: FormField passes type: undefined as fallthrough attr; Vuetify's _mergeProps overrides type="file" with undefined

- Fix: Added defineOptions({ inheritAttrs: false }) to FileField.vue

- Root cause: Vuetify 3 v-file-input emits single File (not File[]) when multiple is not set. onFilesChanged tried files.length on a File object → undefined → emitted null

- Fix: Handle both File and File[] in onFilesChanged via instanceof File check. Removed unnecessary filesArray array adapter — pass modelValue directly to v-file-input

- Root cause: validateOnMount was passed as a computed() ref to vee-validate's useField(). vee-validate checks if (validateOnMount) which evaluates the ref OBJECT (always truthy), never accessing .value

- Fix: Changed to pass plain boolean instead of computed ref

- Also: Skip validation on initial value sync watcher (setFieldValue(newVal, false) on first call)