🚧 Early alpha Under active construction. Everything here may change without notice — except the appcast URL. That one's forever.

Aetower

Docs

Aetower Diagnostics And Debug Console Spec

Status

Current state: partial diagnostics, no real debug console.

What exists today:

What is missing:

This document defines the target diagnostics system for Aetower.

Goals

  1. Make Aetower explain itself when attribution, ranking, enrichment, or export look wrong.
  2. Give operators a first-class in-app console instead of forcing terminal-only debugging.
  3. Preserve low overhead. Diagnostics must be bounded, sampled, and tiered.
  4. Make diagnostics stable enough to compare behavior across versions.
  5. Keep the system useful for both local debugging and longitudinal product improvement.

Non-Goals

  1. Turning Aetower into a generic log aggregation system.
  2. Shipping unbounded verbose logs by default.
  3. Capturing raw user-sensitive content unless explicitly allowed.
  4. Building a remote SaaS diagnostics backend in the first phase.

Product Position

Aetower should have three diagnostics layers:

  1. User-facing explanation layer.

This is already partly present through ranking reasons, timeline, history, and recommendations.

  1. Operator diagnostics layer.

This is missing. It should expose internal health, adapter freshness, attribution decisions, exporter state, and runtime errors.

  1. Engineering trace layer.

This is also missing. It should make bugs reproducible with bounded structured events and snapshot-linked context.

Core Principles

  1. Structured first.

Diagnostics events must be typed records, not freeform strings.

  1. Snapshot-linked.

Every important diagnostics event should reference sequence, captured_at_millis, and when possible entity_id, component, adapter, or capability.

  1. Bounded by design.

No infinite buffers. Every queue, log store, and export path needs a cap and a retention window.

  1. Tiered verbosity.

Default should stay lightweight. Deep tracing must be opt-in and time-limited.

  1. Privacy-aware.

Diagnostics should default to metadata, counters, state, and hashes. Raw titles, command lines, URLs, and socket endpoints should be redacted or explicitly marked as sensitive.

Current Gap Summary

Existing surfaces

Missing surfaces

Target Architecture

Introduce a new crate:

Responsibilities:

Dependency direction

Do not invert this. Diagnostics must not pull UI or app concerns into core crates.

Event Model

Every diagnostics event should share a common envelope:


struct DiagnosticsEvent {
    id: String,
    timestamp_millis: u64,
    level: DiagnosticsLevel,
    subsystem: DiagnosticsSubsystem,
    event_type: DiagnosticsEventType,
    sequence: Option<u64>,
    entity_id: Option<String>,
    adapter: Option<String>,
    capability: Option<String>,
    message: String,
    fields: BTreeMap<String, DiagnosticsValue>,
    sensitive: bool,
}

Levels

Subsystems

Event Types

Required Diagnostics Producers

Engine

Emit:

Required fields:

Collector

Emit:

Required fields:

Identity / Attribution

Emit on meaningful changes only:

Required fields:

Friction

Emit when:

Required fields:

Adapters

Each adapter must emit:

Required fields:

Telemetry

Emit:

Required fields:

Diagnostics Storage

In-memory ring buffer

Always on.

Requirements:

Persisted diagnostics store

Opt-in or debug-mode only in phase 1.

Requirements:

Log Redaction Policy

Mark the following sensitive by default:

Diagnostics UI should support:

In-App Diagnostics Console

Add a new top-level app tab:

Primary sections

  1. Overview
  1. Live Event Stream
  1. Subsystem Panels
  1. Query
  1. Export

UX details

Minimum operator cards

Settings Surface

Extend settings with:

Trace mode must auto-expire.

Export Bundle Spec

Support one-click export of:

  1. app version and git revision if available
  2. platform and hardware summary
  3. current snapshot
  4. recent timeline
  5. persisted history summary
  6. recent diagnostics events
  7. capability states
  8. adapter health states
  9. benchmark/profile summary if present

Output formats:

Performance Budget

Diagnostics must not violate Aetower’s low-footprint goals.

Always-on budget

Debug-mode budget

Versioning And Stability

Define a diagnostics schema version:

Rules:

This matters because diagnostics should become comparable across releases.

Rollout Plan

Phase 1

Phase 2

Phase 3

Acceptance Criteria

  1. A user can answer “why is this entity ranked here?” without leaving the app.
  2. A developer can answer “which subsystem failed?” without adding ad hoc prints.
  3. An operator can export a bounded diagnostics bundle after a bad run.
  4. Diagnostics remain bounded and do not materially regress the benchmark budget.
  5. Adapter failures and telemetry failures are visible, queryable, and timestamped.
  6. Attribution and provenance changes become inspectable over time.

Immediate Follow-Up Backlog

  1. Create aetower-diagnostics crate with ring buffer and event schema.
  2. Add diagnostics producer hooks in engine, adapters, telemetry, and persistence.
  3. Expose queryDiagnostics and exportDiagnosticsBundle through FFI.
  4. Add DiagnosticsView.swift with overview, stream, and export actions.
  5. Add a support-bundle JSON schema and golden tests.
  6. Add benchmark assertions for diagnostics-on default mode.

Recommendation

Treat this as a core feature, not a debug extra.

Aetower’s product value is not only collecting observability signals. It is being able to justify, inspect, and improve its own interpretation over time. Without a proper diagnostics layer, every future observability feature will be harder to trust, harder to debug, and harder to evolve cleanly.

Aetower is a free early-alpha download for macOS 14+ (Apple silicon).

Download for macOS