# Reports & the Journal
Every run — success, failure, blocked, or nothing-changed — produces two audit records: a human-readable HTML report and a machine-readable JSONL journal. Neither is optional (Rule 2).
## How a report is produced
```mermaid
flowchart LR
J[journal run-start] --> E[light env check] --> R[run pipeline] --> RP[REPORT
atomic write + archive] --> SH[SHOW]
SH --> J2[journal run-end]
```
The `SHOW` rule decides presentation:
| Context | Behavior |
|---|---|
| Interactive run | Opens the report in the browser |
| Background / scheduled run | Windows toast |
| Shutdown quick-push | **Never** opens the report |
## The HTML report
Generated after every run to:
```text
\urgithub\.urgithub\reports\report.html
\urgithub\.urgithub\reports\archive\
```
Older reports are archived and kept per `report.archive_keep_days` (default 90 days). Open it with `python urgithub.py --report` or let it auto-open (`report.auto_open`, default on).
## What a report contains
| Section | Records |
|---|---|
| Header & run summary | Run time · trigger · duration · run ID · outcome |
| 7 stat cards | Pushed · Cloned · Renamed · Initialized · Removed · Failed · Events, each with its own accent color |
| Activity timeline | Icon-chip rows with mono timestamps, repo names, details, and `↗` links to GitHub |
| Per-repository details | Action badge, `before → after` SHAs, A/M/D/R changed-file chips, "Open on GitHub" |
| All repositories | Live re-scan: registry status, **branch**, CLEAN/DIRTY/UNINIT |
| Files & last commit | Per-file "committed at" dates, newest first, `uncommitted` for untracked (up to `report.files_max`, default 500) |
| Security & size | Secret findings, oversized files, warnings — only when findings exist |
| Environment drift | Changes detected in the environment snapshot — only when findings exist |
The report is an **execution record, not only a success page** — failures and blocked operations are reported as clearly as successes.
## First place to look when something is wrong
When synchronization is blocked, open `report.html` and check for:
- divergence
- detected secrets
- invalid repository state
- missing remote
- authorization failure
- repository access failure
- unsupported state
## The JSONL journal
An append-only, machine-readable event log (`database\journal.jsonl`) stored as one JSON object per line:
```json
{"ts":"...","op":"scan","repo":"...","trigger":"startup","success":true,"sha_before":"...","sha_after":"...","blocked":false}
{"ts":"...","op":"push","repo":"...","trigger":"every_hours","success":true,"sha_before":"...","sha_after":"..."}
{"ts":"...","op":"sync","repo":"...","trigger":"file_change","success":false,"blocked":true,"reason":"secrets"}
```
```mermaid
flowchart LR
E1[event] --> E2[event] --> E3[event] --> E4[event]
```
Each event represents one operation or state transition and supports analysis of:
- when the operation occurred
- which repository was involved
- what trigger initiated it
- whether the operation succeeded
- what commit identifiers were involved
- whether the operation was blocked
> **Do not manually edit runtime journal files** unless you understand the consequences — they are append-only audit records.
## Related settings
| Setting | Default | Purpose |
|---|---|---|
| `report.auto_open` | `true` | Open `report.html` in the browser after a run |
| `report.archive` | `true` | Archive old reports |
| `report.archive_keep_days` | `90` | Retention for archived reports |
| `report.show_files` / `files_max` | `true` / `500` | Show file lists, capped at 500 per repo |
Next: [Troubleshooting](troubleshooting.md) — common problems and their fixes.