* feat: harness engineering P0 - linting, testing, architecture docs
Add foundational infrastructure for agent-first development:
- AGENTS.md: agent entry point with progressive disclosure to deeper docs
- ARCHITECTURE.md: 12-section system reference with source-file refs and ownership rule
- Biome 2.4.7 linter with project-tuned rules, CI workflow (lint-code.yml)
- Architectural boundary lint enforcing forward-only dependency direction (lint-boundaries.mjs)
- Unit test CI workflow (test.yml), all 1083 tests passing
- Fixed 9 pre-existing test failures (bootstrap sync, deploy-config headers, globe parity, redis mocks, geometry URL, import.meta.env null safety)
- Fixed 12 architectural boundary violations (types moved to proper layers)
- Added 3 missing cache tier entries in gateway.ts
- Synced cache-keys.ts with bootstrap.js
- Renamed docs/architecture.mdx to "Design Philosophy" with cross-references
- Deprecated legacy docs/Docs_To_Review/ARCHITECTURE.md
- Harness engineering roadmap tracking doc
* fix: address PR review feedback on harness-engineering-p0
- countries-geojson.test.mjs: skip gracefully when CDN unreachable
instead of failing CI on network issues
- country-geometry-overrides.test.mts: relax timing assertion
(250ms -> 2000ms) for constrained CI environments
- lint-boundaries.mjs: implement the documented api/ boundary check
(was documented but missing, causing false green)
* fix(lint): scan api/ .ts files in boundary check
The api/ boundary check only scanned .js/.mjs files, missing the 25
sebuf RPC .ts edge functions. Now scans .ts files with correct rules:
- Legacy .js: fully self-contained (no server/ or src/ imports)
- RPC .ts: may import server/ and src/generated/ (bundled at deploy),
but blocks imports from src/ application code
* fix(lint): detect import() type expressions in boundary lint
- Move AppContext back to app/app-context.ts (aggregate type that
references components/services/utils belongs at the top, not types/)
- Move HappyContentCategory and TechHQ to types/ (simple enums/interfaces)
- Boundary lint now catches import('@/layer') expressions, not just
from '@/layer' imports
- correlation-engine imports of AppContext marked boundary-ignore
(type-only imports of top-level aggregate)
Replace "WorldMonitor" with "World Monitor" in all user-facing display
text across blog posts, docs, layouts, structured data, footer, offline
page, and X-Title headers. Technical identifiers (User-Agent strings,
X-WorldMonitor-Key headers, @WorldMonitorApp handle, function names)
are preserved unchanged. Also adds anchors color to Mintlify docs config
to fix blue link color in dark mode.
Stadia Maps tiles return HTTP 401 without an API key — style.json loads
but actual .pbf tile requests fail, leaving the map black with floating
data points (issue #1031).
Changes:
- Switch fallback to OpenFreeMap (free, no auth, CORS *, dark style)
- Replace overly broad 'style.json' error match with 'cartocdn.com'
- Store style load timeout on instance, clear in destroy()
- Update TODO-131 text to reference OpenFreeMap
CARTO basemap CORS errors weren't triggering the Stadia fallback because
the error message didn't always match 'Failed to fetch' or 'AJAXError'.
Add broader error pattern matching (CORS, NetworkError, style.json) and
a 5-second timeout that switches to fallback if style hasn't loaded.
Also adds TODO-131 for self-hosted Protomaps + CloudFront tiles to
eliminate third-party basemap dependency entirely.
* feat: add WTO trade policy service with 4 RPC endpoints and TradePolicyPanel
Adds a new `trade` RPC domain backed by the WTO API (apiportal.wto.org) for
trade policy intelligence: quantitative restrictions, tariff timeseries,
bilateral trade flows, and SPS/TBT barrier notifications.
New files: 6 protos, generated server/client, 4 server handlers + shared WTO
fetch utility, client service with circuit breakers, TradePolicyPanel (4 tabs),
and full API key infrastructure (Rust keychain, sidecar, runtime config).
Panel registered for FULL and FINANCE variants with data loader integration,
command palette entry, status panel tracking, data freshness monitoring, and
i18n across all 17 locale files.
https://claude.ai/code/session_01HZXyoQp6xK3TX8obDzv6Ye
* chore: update package-lock.json
https://claude.ai/code/session_01HZXyoQp6xK3TX8obDzv6Ye
* fix: move tab click listener to constructor to prevent leak
The delegated click handler was added inside render(), which runs
on every data update (4× per load cycle). Since the listener targets
this.content (a persistent container), each call stacked a duplicate
handler. Moving it to the constructor binds it exactly once.
https://claude.ai/code/session_01HZXyoQp6xK3TX8obDzv6Ye
---------
Co-authored-by: Claude <noreply@anthropic.com>