# Didactyl Integration Plan: Unified `nostr_core_lib` Logging into One File

## Goal

Route `nostr_core_lib` logs through didactyl logging so there is one authoritative file for errors, using existing didactyl logging in [`debug.c`](../src/debug.c:1) plus the new callback API in [`nostr_log.h`](../nostr_core_lib/nostr_core/nostr_log.h:1).

## Current State

- Didactyl writes logs to path from `DIDACTYL_LOG_FILE` or default `debug.log` in [`debug_open_log_file`](../src/debug.c:10).
- Didactyl log emission is centralized in [`debug_log`](../src/debug.c:31).
- Relay pool setup occurs in [`nostr_handler_init`](../src/nostr_handler.c:1519).
- `nostr_core_lib` now exposes callback logging API in [`nostr_log.h`](../nostr_core_lib/nostr_core/nostr_log.h:1).

## Desired End State

- `nostr_core_lib` logs are forwarded into didactyl logger via callback registration.
- One file path configured by `DIDACTYL_LOG_FILE` receives didactyl plus nostr_core_lib errors.
- Log lines preserve source component tags such as `nostr:websocket` and `nostr:nip013`.

## Architecture

```mermaid
flowchart TD
    A[nostr_core_lib emits callback log] --> B[didactyl bridge callback in nostr_handler.c]
    B --> C[map nostr level to didactyl level]
    C --> D[debug_log in debug.c]
    D --> E[DIDACTYL_LOG_FILE single destination]
```

## Implementation Steps

1. Add bridge function in [`nostr_handler.c`](../src/nostr_handler.c:1519)
   - Create static callback `nostr_core_log_bridge level component message user_data`.
   - Prefix forwarded lines with `nostr:` namespace.

2. Map levels from `nostr_core_lib` to didactyl
   - `NOSTR_LOG_LEVEL_ERROR` to `DEBUG_LEVEL_ERROR`
   - `NOSTR_LOG_LEVEL_WARN` to `DEBUG_LEVEL_WARN`
   - `NOSTR_LOG_LEVEL_INFO` to `DEBUG_LEVEL_INFO`
   - `NOSTR_LOG_LEVEL_DEBUG` to `DEBUG_LEVEL_DEBUG`
   - `NOSTR_LOG_LEVEL_TRACE` to `DEBUG_LEVEL_TRACE`

3. Register callback during startup in [`nostr_handler_init`](../src/nostr_handler.c:1519)
   - Before relay setup, call `nostr_set_log_callback`.
   - Set threshold with `nostr_set_log_level` aligned to current didactyl debug level.

4. Enforce single-file policy
   - Set `DIDACTYL_LOG_FILE` to desired final log path.
   - Keep didactyl as only file owner via [`debug_open_log_file`](../src/debug.c:10).

5. Ensure error visibility
   - Keep bridge forwarding at least error and warn levels even when app runs at lower verbosity.
   - Optionally pin library threshold to `WARN` or `ERROR` for production profiles.

## Validation Plan

1. Start didactyl with explicit file path
   - Example environment: `DIDACTYL_LOG_FILE=didactyl.log`.

2. Trigger nostr websocket activity
   - Confirm `nostr:websocket` entries appear in same file.

3. Trigger nip013 path
   - Confirm `nostr:nip013` entries appear in same file.

4. Trigger normal didactyl LLM call
   - Confirm `[didactyl] llm request` still lands in same file.

5. Verify there is no second active file for nostr core logs.

## Rollout Notes

- Implement bridge first, then verify in development run.
- If log volume is too high, reduce callback threshold by setting `nostr_set_log_level`.
- Keep one destination file operationally stable by configuring and documenting `DIDACTYL_LOG_FILE`.

## Files to Change in Code Mode

- [`src/nostr_handler.c`](../src/nostr_handler.c)
- Optional docs update in [`README.md`](../README.md)
- Optional operational note in [`docs/TOOLS.md`](../docs/TOOLS.md)
