Skip to content

chore: optimize metrics framework and codebase readability#140

Open
dev01lay2 wants to merge 33 commits intodevelopfrom
chore/metrics-optimization
Open

chore: optimize metrics framework and codebase readability#140
dev01lay2 wants to merge 33 commits intodevelopfrom
chore/metrics-optimization

Conversation

@dev01lay2
Copy link
Collaborator

What

Addresses 5 metrics issues identified in PR #139's report:

1. SSH Command Failures — improved reporting

Replace misleading ⚠️ expected in Docker with descriptive ℹ️ Docker (no gateway) label.

2. Code Readability — App.tsx refactored

Extract 6 custom hooks from App.tsx (1737 → 686 lines):

  • useInstanceManager — instance CRUD, SSH hosts, discovery
  • useSshConnection — SSH connect/reconnect, passphrase, health
  • useInstancePersistence — persistence scope, instance token
  • useChannelCache — channel data loading/caching
  • useAppLifecycle — update check, analytics, preload, migration
  • useWorkspaceTabs — tab management, instance selection

3. Missing limits — gates added

  • JS initial load (gzip): ≤ 200 KB gate
  • Command P50 latency: ≤ 50ms (50,000µs) gate
  • Command max latency: ≤ 200ms informational

4. Inaccurate measurements — microsecond precision

Switch trace_command, record_timing, and timing macros from milliseconds to microseconds. Fast local commands now show actual timing instead of 0ms.

5. Code Readability coverage — expanded

Track 18 files (up from 2) with per-file targets:

  • doctor_assistant.rs ≤3000, rescue.rs ≤2000, profiles.rs ≤1500, etc.
  • Gate: files >500 lines must not increase (≤28)
  • Gate: files over their individual target = 0

Commits

  1. refactor: Extract App.tsx hooks
  2. fix: Switch to microsecond measurement
  3. feat: Expand metrics limits and readability tracking

Extract 6 custom hooks from App.tsx (1737 → 686 lines):
- useInstanceManager: instance CRUD, SSH hosts, discovery
- useSshConnection: SSH connect/reconnect, passphrase dialog, health self-healing
- useInstancePersistence: persistence scope, instance token, config version
- useChannelCache: channel nodes, Discord guild channels, loading/refresh
- useAppLifecycle: app update, analytics, preload, legacy migration, error handlers
- useWorkspaceTabs: tab management, instance selection, install-ready handler

Also fixes TS type narrowing for resolveInstanceTransport return type.
trace_command and record_timing now use microseconds instead of
milliseconds. This fixes 0ms readings for fast local commands.
PerfSample.elapsed_ms renamed to elapsed_us. CI report updated to
show µs units with proper limits.
- JS initial load: add ≤200KB gate
- Command P50: add ≤50ms gate (measured in µs)
- Command max: add ≤200ms informational limit
- Code Readability: expand from 2 to 18 tracked files with per-file targets
- Files >500 lines: gate at ≤28 (must not increase)
- SSH remote perf: replace 'expected in Docker' with descriptive label
- metrics.md: update baselines and targets to match current codebase
@github-actions
Copy link
Contributor

github-actions bot commented Mar 18, 2026

📊 Test Coverage Report

Metric Base (develop) PR (chore/metrics-optimization) Delta
Lines 74.34% (6134/8251) 74.34% (6134/8251) ⚪ ±0.00%
Functions 68.88% (704/1022) 68.88% (704/1022) ⚪ ±0.00%
Regions 75.86% (10156/13388) 75.86% (10156/13388) ⚪ ±0.00%

Coverage measured by cargo llvm-cov (clawpal-core + clawpal-cli).

@github-actions
Copy link
Contributor

github-actions bot commented Mar 18, 2026

📦 PR Build Artifacts

Platform Download Size
Windows-x64 📥 clawpal-Windows-x64 15.7 MB
Linux-x64 📥 clawpal-Linux-x64 102.9 MB
macOS-ARM64 📥 clawpal-macOS-ARM64 12.3 MB
macOS-x64 📥 clawpal-macOS-x64 12.9 MB

🔨 Built from 6690700 · View workflow run
⚠️ Unsigned development builds — for testing only

@github-actions
Copy link
Contributor

github-actions bot commented Mar 18, 2026

📏 Metrics Gate Report

Status: ✅ All gates passed

Commit Size ❌

Metric Value Limit Status
Commits checked 33
All within limit 30/33 ≤ 500 lines
Largest commit 2852 lines ≤ 500

Bundle Size ✅

Metric Value Limit Status
JS bundle (raw) 918 KB
JS bundle (gzip) 289 KB ≤ 350 KB
JS initial load (gzip) 164 KB ≤ 180 KB

Perf Metrics E2E ✅

Metric Value Limit Status
Tests 10 passed, 0 failed 0 failures
RSS (test process) 3.1 MB ≤ 20 MB
VMS (test process) 269.9 MB ℹ️
Command P50 latency 32 µs ≤ 1000 µs
Command P95 latency 39 µs ≤ 5000 µs
Command max latency 58 µs ≤ 50000 µs

Command Perf (local) ✅

Metric Value Status
Tests 4 passed, 0 failed
Commands measured 5 ℹ️
RSS (test process) 4.4 MB ℹ️
Local command timings
Command P50 (µs) P95 (µs) Max (µs)
local_openclaw_config_exists 1 9 9
list_ssh_hosts 2 10 10
get_app_preferences 16 39 39
read_app_log 71 88 88
read_error_log 6 11 11

Command Perf (remote SSH) ✅

Metric Value Status
SSH transport OK
Command failures 12/15 runs ℹ️ Docker (no gateway)
Remote command timings (via Docker SSH)
Command Median Max
openclaw_status 2173 ms 3149 ms
cat__root_.openclaw_openclaw.json 242 ms 266 ms
openclaw_gateway 2357 ms 2383 ms
openclaw_cron 2192 ms 2197 ms
openclaw_agent 2320 ms 2449 ms

Home Page Render Probes (mock IPC 50ms, cache-first render) ✅

Probe Value Limit Status
status 64 ms ≤ 200 ms
version 64 ms ≤ 200 ms
agents 64 ms ≤ 200 ms
models 64 ms ≤ 300 ms
settled 64 ms ≤ 1000 ms

Code Readability

File Lines Target Status
commands/doctor_assistant.rs 5636 ≤ 3000 ⚠️
commands/rescue.rs 3402 ≤ 2000 ⚠️
commands/profiles.rs 2477 ≤ 1500 ⚠️
cli_runner.rs 1915 ≤ 1200 ⚠️
commands/credentials.rs 1629 ≤ 1000 ⚠️
openclaw_doc_resolver.rs 1362 ≤ 800 ⚠️
commands/ssh.rs 1232 ≤ 700 ⚠️
commands/doctor.rs 1168 ≤ 700 ⚠️
commands/sessions.rs 905 ≤ 500 ⚠️
pages/StartPage.tsx 898 ≤ 500 ⚠️
pages/Settings.tsx 897 ≤ 500 ⚠️
commands/discovery.rs 878 ≤ 500 ⚠️
pages/Home.tsx 875 ≤ 500 ⚠️
install/commands.rs 839 ≤ 500 ⚠️
ssh.rs 826 ≤ 500 ⚠️
lib/use-api.ts 674 ≤ 500 ⚠️
commands/model.rs 645 ≤ 500 ⚠️
bridge_client.rs 645 ≤ 500 ⚠️
components/InstallHub.tsx 619 ≤ 500 ⚠️
agent_fallback.rs 609 ≤ 500 ⚠️
install/runners/docker.rs 525 ≤ 500 ⚠️
commands/types.rs 518 ≤ 500 ⚠️
commands/overview.rs 508 ≤ 500 ⚠️
components/SessionAnalysisPanel.tsx 503 ≤ 500 ⚠️
commands/instance.rs 501 ≤ 500 ⚠️
App.tsx 499 ≤ 500
lib/types.ts 490 ≤ 500
pages/Doctor.tsx 479 ≤ 500
commands/agent.rs 475 ≤ 500
pages/Channels.tsx 460 ≤ 500
commands/backup.rs 459 ≤ 500
lib/api.ts 453 ≤ 500
node_client.rs 452 ≤ 500
commands/discover_local.rs 441 ≤ 500
pages/Cron.tsx 429 ≤ 500
components/__tests__/DoctorRecoveryOverview.test.tsx 429 ≤ 500
commands/config.rs 419 ≤ 500
bug_report/queue.rs 409 ≤ 500
commands/channels.rs 405 ≤ 500
lib/api-read-cache.ts 401 ≤ 500
components/__tests__/InstanceCard.test.tsx 400 ≤ 500
lib/__tests__/guidance.test.ts 399 ≤ 500
components/DoctorRecoveryOverview.tsx 383 ≤ 500
lib/use-cached-query.ts 353 ≤ 500
components/DoctorTempProviderDialog.tsx 349 ≤ 500
hooks/useSshConnection.ts 337 ≤ 500
bug_report/collector.rs 335 ≤ 500
components/InstanceCard.tsx 334 ≤ 500
lib.rs 333 ≤ 500
hooks/useWorkspaceTabs.ts 331 ≤ 500
lib/doctor-report-i18n.ts 328 ≤ 500
recipe.rs 325 ≤ 500
pages/__tests__/overview-loading.test.ts 318 ≤ 500
components/__tests__/SshFormWidget.test.tsx 312 ≤ 500
hooks/useInstancePersistence.ts 308 ≤ 500
doctor.rs 303 ≤ 500
Files > 500 lines 25 trend ↓
Files over target 25 0 ⚠️

📊 Metrics defined in docs/architecture/metrics.md

@github-actions
Copy link
Contributor

github-actions bot commented Mar 18, 2026

📸 UI Screenshots

Commit: 97b1529e2afc1902ef0e56974cf01083821d80ff | Screenshots: Download artifact

Light Mode — Core Pages

Start Page Home Channels
start home channels
Recipes Cron Doctor
recipes cron doctor
Context History Chat Panel
context history chat
Settings (4 scroll positions)
Main Appearance Advanced Bottom
s1 s2 s3 s4
Start Page Sections
Overview Profiles Settings
sp1 sp2 sp3

Dark Mode

Start Home Channels Doctor
d1 d2 d3 d4
Dark mode — more pages
Recipes Cron Settings
d5 d6 d7

Responsive + Dialogs

Home 1024×680 Chat 1024×680 Create Agent
r1 r2 d1

🔧 Harness: Docker + Xvfb + tauri-driver + Selenium | 28 screenshots, 13 flows

…bar footer

Extract three more modules from App.tsx (686 → 500 lines):
- useNavItems.tsx: navigation item definitions with icons
- AppDialogs.tsx: passphrase and SSH edit dialogs
- SidebarFooter.tsx: profile sync status, SSH transfer speed, pending changes bar
The previous threshold of 100µs was set before the ms→µs migration,
causing false positives on CI. Local commands like get_app_preferences
can take 100ms+ due to CI scheduling jitter.
Measured → New Limit (was):
- Command P50: 32µs → ≤1,000µs (was 50,000µs)
- Command P95: 36µs → ≤5,000µs (was 100,000µs)
- Command Max: 40µs → ≤50,000µs (was 200,000µs)
- JS initial load: 166KB → ≤180KB (was 200KB)
- JS bundle gzip: 288KB → ≤350KB (was 512KB)
- RSS: 3.1MB → ≤20MB (was 80MB)
- Home probes: 10ms → ≤200ms (was 500ms)
- Models probe: 107ms → ≤300ms (was 500ms)
- Settled: 10ms → ≤1,000ms (was 5,000ms)
…es mock

1. Readability: auto-scans all .ts/.tsx/.rs files >300 lines, auto-calculates
   targets (60% of current, floor 500), with manual overrides for key files.
   Covers entire codebase instead of 18 hand-picked files.

2. Home Probes: annotated as mock IPC (50ms latency) so the 10ms values
   are understood as render-only timing, not E2E with real API calls.
…→ 959)

- profile-utils.ts: ProfileForm type, credential helpers (emptyForm,
  normalizeOauthProvider, inferCredentialSource, etc.)
- AutocompleteField.tsx: standalone autocomplete input component
… (963 → 901)

Moves duplicate install detection and post-install onboarding guidance
event emission into a dedicated hook with self-contained refs.
The ~10ms probes for status/version/agents/settled correctly measure
cache-first rendering: prewarmRemoteInstanceReadCache populates the
read cache during instance activation (50ms mock IPC), and Home mounts
after the cache is warm. This is the actual user experience — the
cache layer is working as designed.

models (110ms) still goes through IPC because listModelProfiles is not
in the prewarm path.
…→ 876)

Replace 3 repetitive emitDataLoadMetric blocks with a compact loop.
Moves schedule formatting, relative time, job filtering, and cron
expression humanization into src/lib/cron-utils.ts.
Replaces duplicate emptyForm, normalizeOauthProvider, inferCredentialSource,
providerSupportsOptionalApiKey, AutocompleteField with imports from
profile-utils.ts and AutocompleteField.tsx.
Skip the first 2 get_instance_runtime_snapshot / config_snapshot IPC
calls (which are prewarm calls from instance activation). This forces
the Home page poll loop to make fresh IPC calls, measuring actual
fetch + render time instead of cache-hit render time.

Per Chen Yu's feedback: probe values should reflect real IPC latency.
Also skip get_status_extra, get_status_light, list_agents_overview
during the first 2 IPC rounds, so prewarm doesn't populate any cache.
Each run now clears localStorage before goto to prevent persisted cache
from previous runs. Increased cold-start skip from 2 to 4 to handle
all prewarm paths.
Skip=4 caused the poll loop to keep getting null from cache,
preventing settled from firing. Skip=1 blocks just the prewarm
call; the poll loop's 2nd call returns real data.
…863 → 5709)

Moves skip_json5_ws_and_comments, scan_json5_string_end,
scan_json5_value_end, extract_json5_top_level_value into
src/json5_extract.rs. These are pure string parsers with no
doctor-specific dependencies.
Moves 22 SSH-related type definitions to src/lib/ssh-types.ts.
Re-exported from types.ts for backward compatibility — no import
path changes needed in consuming files.
Extract 47 type definitions into 3 domain files:
- ssh-types.ts (22 types, 160 lines)
- rescue-types.ts (15 types, 142 lines)
- install-types.ts (12 types, 82 lines)
- cron-types.ts (10 types, 62 lines)

All re-exported from types.ts for backward compatibility.
… → 5635)

Moves DoctorTempGatewaySessionRecord/Store structs and 5 CRUD
functions into src-tauri/src/doctor_temp_store.rs (80 lines).
Registered in lib.rs, all call sites updated.
…rget)

Moves 9 doctor/diagnosis type definitions to src/lib/doctor-types.ts.
types.ts now passes readability gate (491 ≤ 500).
@dev01lay2 dev01lay2 deployed to development March 18, 2026 20:30 — with GitHub Actions Active
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant