- fitCert: replace the flaky CSS `zoom` (Firefox support is recent/inconsistent)
with transform:scale() measured against the widest line (+ right margin and
font-load retries) so the cert always scales to fit the inspector with no
horizontal clip. Validated live on a narrow 5B cert (0.74x) and a wide DSCA45
cert (0.55x) against the real AD2 dataset.
- inspector Web field -> Published (green) / Not published (amber) chips.
- widen default inspector 480 -> 500px.
- tools/preview-proxy.py: serve the prototype AND reverse-proxy /api to the live
AD2 server so the cert iframe is same-origin during preview — styleCert/fitCert
read iframe.contentDocument, which silently no-ops when the iframe is loaded
cross-origin straight from AD2 (why the fit looked broken in earlier previews).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The DSCA33/DSCA45 main spec files lost in the cryptolocker wipe are recoverable:
the original software published correct certs to the Hoffman product API before
the wipe and our null-skipping renderer never overwrote them. Mine per-model
Final-Test templates (names + specs + verbatim accuracy headers) straight from
those originals instead of requesting spec files from Dataforth/John.
- dsca33-45-templates.json: 56 models (DSCA33 34/35, DSCA45 22/23); only
DSCA33-1948 + DSCA45-1746 (24 units) lack an original.
- mine-hoffman-dsca.py: the re-runnable miner.
- DSCA33-45-HOFFMAN-RECOVERY handoff for the AD2 session (incl. the gate:
validate each render vs its Hoffman original before enabling live rendering).
- memories: Hoffman recovery (supersedes the spec-gap "need John" note) and the
AD2 SSH MTU-blackhole root cause/fix; errorlog entries (syncro jq, ssh correction).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Vanilla single-file (no build/CDN) command-center redesign of the testdatadb search
UI: omni-search with serial/model/text routing + auto-select fast path, dense
monospace results table with PASS/FAIL pills + web-published indicator, persistent
split-pane datasheet inspector (iframe to /api/datasheet), left filter rail
(result/date/model/station/log), server pagination, CSV export, URL state, keyboard
nav (/ ↑↓ ↵ Esc), clinical light theme. Hits the existing API; deployed to AD2 as
public/index.redesign.html (preview at :3000/index.redesign.html). Synthesized from
Grok + Gemini concepts (both converged on this command-center design).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Remote SSH/VPN to AD2 keeps flapping; hand the remaining datasheet fixes to the
local AD2 session. Includes the per-subtype approach (DSCA_TEMPLATES from staged
originals — STAGE 1 done, dsca-templates.json on AD2 = 126 models), the render-wiring
+ per-subtype byte-validation gate, Fix 5 (379 backfill via legacy_cert_text), the
discipline (backup/save-state/validate-before-publish), and the derive-dsca-templates
tool. Ref ticket #32441.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
While using the new 3-retry gemini path for live VPN research, two bugs surfaced:
- emit_or_fail checked auth_failed INSIDE the retry loop; a benign mid-run token-refresh line
matched the over-broad auth regex (bare login|credential|authenticat|oauth|401) and aborted the
retries with a false "auth error" - even though `gemini -p` auth tested fine. Moved auth-classify
to AFTER the retries (it only picks the final error message now) and tightened auth_failed to real
signatures (invalid_grant, not authenticated, login with google, token expired, ...).
- Added quota_exhausted() + a QUOTA FALLBACK: the pinned strong model (gemini-3.1-pro-preview) hit
"exhausted your capacity on this model" mid-session; emit_or_fail now retries once on the default
(lighter) model by stripping -m (separate quota). Validated: capped pro run -> fell back -> 2.9KB answer.
CT_THOUGHTS Thought 2 Resolution updated with both. (Search-bot reliability hardening continues.)
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mike's must-fix. Diagnosed from RAW output of failing queries (not guessed):
- grok xsearch = TIMEOUT: grok-4.20-multi-agent web_search runs past budget on multi-part queries
(286s/280s, rc=124, still searching - 183 thoughts, only progress-noise text); buffered json => total loss.
- gemini search = INTERMITTENT empty turn (a clean re-run gave a real 2.6KB answer in 122s); the wrapper
retried only once, so two empties in a row failed spuriously.
Fixes:
- ask-gemini.sh emit_or_fail: retry up to 3x with 3s/6s backoff (was 1).
- ask-grok.sh xsearch: --output-format streaming-json (salvage partials) + AUTO-FALLBACK to
ask-gemini.sh search when grok doesn't finish (rc!=0 or empty). Validated e2e: grok timed out
(rc=124) -> fell back -> gemini returned a real sourced answer (UniFi Teleport invite-link API).
grok's own multi-agent timeout is an xAI-side limitation; the fallback makes xsearch reliable regardless.
Docs: grok SKILL.md xsearch row + CT_THOUGHTS Thought 2 Resolution.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Mike's correction: web search (grok xsearch + gemini search) carries at least as much weight as
live API probing - the searches gave the real leads this session (connector proxy, teleport setting
path); blind endpoint-probing is "highly suspect" (mostly 404s). And the search bots MUST be properly
fixed - both returned empty repeatedly on UniFi research despite the same-day partial grok fix.
- docs/CT_THOUGHTS.md: Thought 2 (HIGH PRIORITY) - web-search reliability must-fix, with the observed
failures + a proper-fix investigation plan (capture failing-query JSON; max-turns/streaming-json/
retry; cross-fallback grok<->gemini; 5/5 acceptance).
- memory feedback_web_search_over_probing: lead with web search/docs; probe only to CONFIRM a
hypothesis, never as primary discovery. Reading our own config is fine; guessing paths is not.
- errorlog correction logged.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Earlier "no usable Teleport API" was wrong (probed /rest/teleport, /stat/teleport, /v1/teleport).
Gemini research + live verification: Teleport config lives at /api/s/<site>/rest/setting/teleport
(GET/PUT, also under /get/setting key 'teleport') - reachable via the connector. Brooklyn confirmed
enabled, subnet 192.168.1.1/24. Invite generate/revoke is reportedly POST /api/s/<site>/cmd/teleport
{"cmd":"generate-invite"|"revoke-invite"} (untested - it creates a live VPN access link; gate as a
write). Invites are WiFiman-app-only. Proxy path is /v1/connector/consoles/{id}/proxy/... (Gemini's
/v1/hosts/{id}/proxy form 404s). Doc updated.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
neighbor-collect.sh: add `--console <name> [--site <short>]` so the AP name/BSSID/IP map can come
from the cloud connector (/v1/connector/.../stat/device) instead of a UOS direct-login -- lets the
disable-analysis collector run against ANY console we have AP-VLAN reach to (the AP SSH harvest of
/proc/ui_neighbor is unchanged and still needs L3 reach). UOS path untouched. Validated against
Cascades via connector: source=CONNECTOR, built 77-mac + 450-bssid map for the 75 online APs.
This completes the hybrid (don't-lose-functionality): connector for airtime everywhere + neighbor-
collect (any source) for the SNR matrix -> NEIGHBOR_JSON -> optimize-radios disables on remote sites.
Documented (references/site-manager-api.md): the neighbor-collect --console flow, and the gateway
VPN/Teleport reach -- connector reaches /rest/networkconf (VPN servers: wireguard-server/openvpn-
server, site-to-site) read+writable in principle (gate writes like gw-control); Teleport has no
usable API (v1/ea/teleport 404, per-console /teleport 403).
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Validated the cloud-connector analysis against a KNOWN entity (Cascades, normally UOS-Mongo).
The connector reaches the self-hosted "UOS Server" host; Cascades is its site `va6iba3v`.
Two fixes from the validation:
- rf-analyze.py: pass macs:[<all uap macs>] to /stat/report/*.ap. The UniFi report endpoint
returns only a small DEFAULT subset otherwise -- Cascades came back as 10 of 77 APs until the
MAC list was supplied. Now profiles all 75 (uaps with 2.4 radios), matching the UOS path.
- model-rank.sh / optimize-radios.sh: --console now accepts --site <name> (internal short name
from /api/self/sites) for multi-site controllers like the UOS Server (Cascades = va6iba3v).
Result lines up with the known UOS-Mongo figures: 75 APs, 2.4GHz util 65-90% / interf 53-78% /
~1 client each, all power-down, 0 disables (roam graph absent via connector -> same coverage-safe
degradation; disables still need NEIGHBOR_JSON). Apples-to-apples confirmed.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Both analyses now accept `--console "<name>"` and run against the UniFi cloud connector
instead of the UOS Mongo server, so RF airtime tuning works on standalone/non-UOS consoles
(e.g. Brooklyn/Skybar). The UOS Mongo path is unchanged.
- New shared analyzer scripts/rf-analyze.py: pulls per-AP/band airtime history via the
connector POST /stat/report/hourly.ap (SAME schema as ace_stat.stat_hourly) + /stat/device
for names/zones, derives cu_interf = cu_total - cu_self_rx - cu_self_tx, and runs the SAME
model-rank ranking and optimize-radios greedy power-down/disable logic (ported faithfully).
- Roam graph (/stat/event) is usually empty on small/stationary sites -> graceful degrade:
model-rank ranks by airtime pressure; optimize-radios returns power-down candidates + 0
disables (coverage-safe). NEIGHBOR_JSON (SNR matrix) still enables disables, as on UOS.
- model-rank.sh / optimize-radios.sh: added the `--console` route (resolves the key from
vault services/unifi-site-manager, execs rf-analyze.py). Validated on Brooklyn/Skybar:
2.4GHz saturated (Yoga AP cu 63%/interf 55%), 5GHz idle (1-5%) - the expected pain-band split.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New backend reaching ANY of the ~36 ACG UniFi consoles remotely via api.ui.com with the
account key (vault services/unifi-site-manager) - no UOS server, no LAN/VPN. Mapped the API
surface empirically (key live), corroborated by grok+gemini web search:
- Tier 1 (Site Manager): fleet/devices/sites/isp commands - inventory, site health (counts,
IPS, ISP/ASN), and WAN/ISP time-series (latency/throughput/downtime).
- Tier 2 (CLOUD CONNECTOR -> console LOCAL Network API = UOS PARITY): the `net` command proxies
/v1/connector/consoles/<id>/proxy/network/api/s/<site>/stat/{device,sta}, returning the SAME
ace_stat depth as the UOS Mongo path - per-radio cu_total airtime/channel/bw/tx_power/num_sta/
satisfaction and per-client rssi/signal/noise/satisfaction/rates. Verified live on Brooklyn/
Skybar (standalone UDM, WAN-firewalled): `net brooklyn radios` + `net brooklyn clients` work.
This achieves parity with (and broader coverage than) the UOS server for non-UOS consoles.
Added references/site-manager-api.md (full catalog + 3 tiers), a Plane 3 note in SKILL.md, and
updated the reference memory. Read-only; POST actions (device restart, client block) exist, not wired.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Radio Show Promotion:
- Add LIVE badge to header phone with subtle pulse animation
- Add radio promo bar under hero (show name, time, call-in number)
- Radio ticker at bottom remains from Phase 3A
3-Step Visual Funnel:
- New funnel-steps section after Trust
- Progression: 1. Build estimate → 2. Talk it through → 3. Month-to-month start
- Interactive number badges with hover lift + color fill
- Mobile responsive (stacks vertically on small screens)
Strengthen Calculator CTAs:
- Pricing teaser: Make 'Build your exact price' primary button (was more-link)
- All 6 service cards: Add inline 'See what this costs →' calculator links
- Guides prospect directly to calculator from any service mention
Increase Vertical Rhythm:
- Section padding: clamp(2.75rem, 5.5vw, 4.25rem) for breathing room
- Service list: +1.5x base margin-bottom after dense grid
- Dispatch grid: +1.5x base margin-bottom after blog cards
All changes deployed to ww9.azcomputerguru.com and verified live.
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>