# ayimmam/echo architecture

> Architecture diagram of the GitHub repository ayimmam/echo, generated by GitDiagram from its file tree, README and a sample of source files (last updated 2026-10-11). It is an AI-made overview: check details against the source.

- Interactive diagram: https://gitdiagram.com/ayimmam/echo
- Repository: https://github.com/ayimmam/echo

## Overview

Echo is an offline Android app for teachers to record classroom audio, review saved-duration reflections, and choose a practice for the coming week. The main path is teacher setup → foreground recording and private storage → reflection and follow-up. The repository also contains a separate synthetic Android demo, indicator/provenance Python library, and read-only synthetic cohort dashboard. README-described capabilities are included where source excerpts do not show their implementation; such relationships are documented rather than inferred from names.

Main entry points: [`edge/android/app/src/main/java/org/ethioware/echo/EchoViewModel.kt`](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/EchoViewModel.kt) (Demo state), [`edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotApp.kt`](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotApp.kt) (Pilot experience), [`edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotViewModel.kt`](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotViewModel.kt) (Pilot state), [`indicators-core/python/dimts_indicators/indicators.py`](https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/indicators.py) (Indicator engine)

## Diagram (Mermaid)

```mermaid
flowchart TD

subgraph group_android["Android pilot app"]
  node_main["App entry<br/>[MainActivity.kt]"]
  node_pilotui["Pilot experience<br/>[PilotApp.kt]"]
  node_pilotvm["Pilot state<br/>[PilotViewModel.kt]"]
  node_recorder["Audio capture"]
  node_pilotdata["Pilot data<br/>[PilotData.kt]"]
  node_privatefiles[("Encrypted files")]
  node_reminder["Weekly reminders<br/>[WeeklyReminder.kt]"]
  node_pilotcontent["Reflection screens"]
  node_strings["Language strings<br/>[AmharicStrings.kt]"]
end

subgraph group_demo["Synthetic demo"]
  node_syntheticactivity["Demo launcher"]
  node_echovm["Demo state<br/>[EchoViewModel.kt]"]
  node_mockdata["Mock content<br/>[MockJson.kt]"]
  node_demostorage[("Demo persistence<br/>[Storage.kt]")]
  node_demoui["Demo screens<br/>[EchoApp.kt]"]
  node_measure["Draft measures<br/>[MockMeasure.kt]"]
end

subgraph group_indicators["Indicator library"]
  node_timeline["Timeline parser<br/>[timeline.py]"]
  node_indicatorengine["Indicator engine<br/>[indicators.py]"]
  node_evidence["Evidence gates<br/>[evidence.py]"]
  node_eligibility["Observation eligibility<br/>[reporting.py]"]
  node_adapter["Record adapter<br/>[adapter.py]"]
end

subgraph group_webdemo["Cohort dashboard"]
  node_aggregator["Cohort aggregation<br/>[aggregation.py]"]
  node_settings["Demo settings<br/>[demo_settings.py]"]
  node_wsgi["Read-only dashboard<br/>[demo_wsgi.py]"]
end

node_teacher(("Teacher"))
node_visitor(("Dashboard visitor"))

node_teacher -->|"opens"| node_main
node_main -->|"launches"| node_pilotui
node_pilotui -->|"uses state"| node_pilotvm
node_pilotvm -->|"starts recording"| node_recorder
node_recorder -.->|"writes chunks"| node_privatefiles
node_pilotvm -.->|"manages"| node_pilotdata
node_pilotui -.->|"shows"| node_pilotcontent
node_pilotui -.->|"localizes with"| node_strings
node_pilotvm -.->|"schedules"| node_reminder
node_teacher -.->|"reviews and reflects"| node_pilotui
node_main -->|"opens demo"| node_syntheticactivity
node_syntheticactivity -->|"creates"| node_echovm
node_syntheticactivity -->|"creates"| node_demostorage
node_echovm -->|"parses"| node_mockdata
node_echovm -.->|"persists"| node_demostorage
node_echovm -->|"uses"| node_measure
node_echovm -->|"renders through"| node_demoui
node_timeline -->|"provides segments"| node_indicatorengine
node_indicatorengine -->|"parses timeline"| node_timeline
node_adapter -->|"uses"| node_indicatorengine
node_adapter -->|"uses"| node_timeline
node_evidence -.->|"gates metrics"| node_indicatorengine
node_eligibility -->|"checks provenance"| node_evidence
node_aggregator -->|"checks metrics"| node_evidence
node_aggregator -->|"filters lessons"| node_eligibility
node_wsgi -->|"aggregates records"| node_aggregator
node_wsgi -->|"loads configuration"| node_settings
node_visitor -.->|"requests dashboard"| node_wsgi

click node_main "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/MainActivity.kt"
click node_pilotui "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotApp.kt"
click node_pilotvm "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotViewModel.kt"
click node_recorder "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/RecordingService.kt"
click node_pilotdata "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotData.kt"
click node_privatefiles "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/AndroidPrivateFiles.kt"
click node_reminder "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/WeeklyReminder.kt"
click node_pilotcontent "https://github.com/ayimmam/echo/tree/claude/main/edge/android/app/src/main/java/org/ethioware/echo/ui/screens"
click node_strings "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/ui/i18n/AmharicStrings.kt"
click node_syntheticactivity "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/SyntheticDemoActivity.kt"
click node_echovm "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/EchoViewModel.kt"
click node_mockdata "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/data/MockJson.kt"
click node_demostorage "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/data/Storage.kt"
click node_demoui "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/EchoApp.kt"
click node_measure "https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/domain/MockMeasure.kt"
click node_timeline "https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/timeline.py"
click node_indicatorengine "https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/indicators.py"
click node_evidence "https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/evidence.py"
click node_eligibility "https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/reporting.py"
click node_adapter "https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/adapter.py"
click node_aggregator "https://github.com/ayimmam/echo/blob/claude/main/server/domain/aggregation.py"
click node_settings "https://github.com/ayimmam/echo/blob/claude/main/server/config/demo_settings.py"
click node_wsgi "https://github.com/ayimmam/echo/blob/claude/main/server/api/demo_wsgi.py"

classDef toneNeutral fill:#f8fafc,stroke:#334155,stroke-width:1.5px,color:#0f172a
classDef toneBlue fill:#dbeafe,stroke:#2563eb,stroke-width:1.5px,color:#172554
classDef toneAmber fill:#fef3c7,stroke:#d97706,stroke-width:1.5px,color:#78350f
classDef toneMint fill:#dcfce7,stroke:#16a34a,stroke-width:1.5px,color:#14532d
classDef toneRose fill:#ffe4e6,stroke:#e11d48,stroke-width:1.5px,color:#881337
classDef toneIndigo fill:#e0e7ff,stroke:#4f46e5,stroke-width:1.5px,color:#312e81
classDef toneTeal fill:#ccfbf1,stroke:#0f766e,stroke-width:1.5px,color:#134e4a
class node_main,node_pilotui,node_pilotvm,node_recorder,node_pilotdata,node_privatefiles,node_reminder,node_pilotcontent,node_strings toneBlue
class node_syntheticactivity,node_echovm,node_mockdata,node_demostorage,node_demoui,node_measure toneAmber
class node_timeline,node_indicatorengine,node_evidence,node_eligibility,node_adapter toneMint
class node_aggregator,node_settings,node_wsgi toneRose
class node_teacher,node_visitor toneIndigo
```

## Components

### Android pilot app

- [App entry](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/MainActivity.kt): `edge/android/app/src/main/java/org/ethioware/echo/MainActivity.kt`
- [Pilot experience](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotApp.kt): `edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotApp.kt`
- [Pilot state](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotViewModel.kt): `edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotViewModel.kt`
- [Audio capture](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/RecordingService.kt): `edge/android/app/src/main/java/org/ethioware/echo/pilot/RecordingService.kt`
- [Pilot data](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotData.kt): `edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotData.kt`
- [Encrypted files](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/AndroidPrivateFiles.kt): `edge/android/app/src/main/java/org/ethioware/echo/pilot/AndroidPrivateFiles.kt`
- [Weekly reminders](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/pilot/WeeklyReminder.kt): `edge/android/app/src/main/java/org/ethioware/echo/pilot/WeeklyReminder.kt`
- [Reflection screens](https://github.com/ayimmam/echo/tree/claude/main/edge/android/app/src/main/java/org/ethioware/echo/ui/screens): `edge/android/app/src/main/java/org/ethioware/echo/ui/screens`
- [Language strings](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/ui/i18n/AmharicStrings.kt): `edge/android/app/src/main/java/org/ethioware/echo/ui/i18n/AmharicStrings.kt`

### Synthetic demo

- [Demo launcher](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/SyntheticDemoActivity.kt): `edge/android/app/src/main/java/org/ethioware/echo/SyntheticDemoActivity.kt`
- [Demo state](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/EchoViewModel.kt): `edge/android/app/src/main/java/org/ethioware/echo/EchoViewModel.kt`
- [Mock content](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/data/MockJson.kt): `edge/android/app/src/main/java/org/ethioware/echo/data/MockJson.kt`
- [Demo persistence](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/data/Storage.kt): `edge/android/app/src/main/java/org/ethioware/echo/data/Storage.kt`
- [Demo screens](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/EchoApp.kt): `edge/android/app/src/main/java/org/ethioware/echo/EchoApp.kt`
- [Draft measures](https://github.com/ayimmam/echo/blob/claude/main/edge/android/app/src/main/java/org/ethioware/echo/domain/MockMeasure.kt): `edge/android/app/src/main/java/org/ethioware/echo/domain/MockMeasure.kt`

### Indicator library

- [Timeline parser](https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/timeline.py): `indicators-core/python/dimts_indicators/timeline.py`
- [Indicator engine](https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/indicators.py): `indicators-core/python/dimts_indicators/indicators.py`
- [Evidence gates](https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/evidence.py): `indicators-core/python/dimts_indicators/evidence.py`
- [Observation eligibility](https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/reporting.py): `indicators-core/python/dimts_indicators/reporting.py`
- [Record adapter](https://github.com/ayimmam/echo/blob/claude/main/indicators-core/python/dimts_indicators/adapter.py): `indicators-core/python/dimts_indicators/adapter.py`

### Cohort dashboard

- [Cohort aggregation](https://github.com/ayimmam/echo/blob/claude/main/server/domain/aggregation.py): `server/domain/aggregation.py`
- [Demo settings](https://github.com/ayimmam/echo/blob/claude/main/server/config/demo_settings.py): `server/config/demo_settings.py`
- [Read-only dashboard](https://github.com/ayimmam/echo/blob/claude/main/server/api/demo_wsgi.py): `server/api/demo_wsgi.py`

### Other components

- **Teacher**
- **Dashboard visitor**

## Connections

- Teacher → App entry: opens (evidence: `README.md`)
- App entry → Pilot experience: launches (evidence: `edge/android/app/src/main/java/org/ethioware/echo/MainActivity.kt`)
- Pilot experience → Pilot state: uses state (evidence: `edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotApp.kt`)
- Pilot state → Audio capture: starts recording (evidence: `edge/android/app/src/main/java/org/ethioware/echo/pilot/PilotViewModel.kt`)
- Audio capture → Encrypted files: writes chunks (evidence: `README.md`)
- Pilot state → Pilot data: manages (evidence: `README.md`)
- Pilot experience → Reflection screens: shows (evidence: `README.md`)
- Pilot experience → Language strings: localizes with (evidence: `README.md`)
- Pilot state → Weekly reminders: schedules (evidence: `README.md`)
- Teacher → Pilot experience: reviews and reflects (evidence: `README.md`)
- App entry → Demo launcher: opens demo (evidence: `edge/android/app/src/main/java/org/ethioware/echo/MainActivity.kt`)
- Demo launcher → Demo state: creates (evidence: `edge/android/app/src/main/java/org/ethioware/echo/SyntheticDemoActivity.kt`)
- Demo launcher → Demo persistence: creates (evidence: `edge/android/app/src/main/java/org/ethioware/echo/SyntheticDemoActivity.kt`)
- Demo state → Mock content: parses (evidence: `edge/android/app/src/main/java/org/ethioware/echo/EchoViewModel.kt`)
- Demo state → Demo persistence: persists (evidence: `README.md`)
- Demo state → Draft measures: uses (evidence: `edge/android/app/src/main/java/org/ethioware/echo/EchoViewModel.kt`)
- Demo state → Demo screens: renders through (evidence: `edge/android/app/src/main/java/org/ethioware/echo/SyntheticDemoActivity.kt`)
- Timeline parser → Indicator engine: provides segments (evidence: `indicators-core/python/dimts_indicators/indicators.py`)
- Indicator engine → Timeline parser: parses timeline (evidence: `indicators-core/python/dimts_indicators/indicators.py`)
- Record adapter → Indicator engine: uses (evidence: `indicators-core/python/dimts_indicators/adapter.py`)
- Record adapter → Timeline parser: uses (evidence: `indicators-core/python/dimts_indicators/adapter.py`)
- Evidence gates → Indicator engine: gates metrics
- Observation eligibility → Evidence gates: checks provenance (evidence: `indicators-core/python/dimts_indicators/reporting.py`)
- Cohort aggregation → Evidence gates: checks metrics (evidence: `server/domain/aggregation.py`)
- Cohort aggregation → Observation eligibility: filters lessons (evidence: `server/domain/aggregation.py`)
- Read-only dashboard → Cohort aggregation: aggregates records (evidence: `server/api/demo_wsgi.py`)
- Read-only dashboard → Demo settings: loads configuration (evidence: `server/api/demo_wsgi.py`)
- Dashboard visitor → Read-only dashboard: requests dashboard (evidence: `README.md`)
