Skip to content

feat(logging): configurable format (text|jsonl) + unified hub/agent log config (#51)#52

Merged
oorabona merged 1 commit into
mainfrom
feat/harmonize-logging-config
Jun 9, 2026
Merged

feat(logging): configurable format (text|jsonl) + unified hub/agent log config (#51)#52
oorabona merged 1 commit into
mainfrom
feat/harmonize-logging-config

Conversation

@oorabona

@oorabona oorabona commented Jun 8, 2026

Copy link
Copy Markdown
Collaborator

Closes #51.

What & why

Harmonize logging configuration across the hub (TypeScript) and the agent (Rust): one [logging]
contract — consistent level, a configurable format (text | jsonl), consistent semantics — for
easier debugging and log aggregation (one parser for Loki/Vector/ELK, correlatable hub↔agent logs).

The hub already parsed [logging] (level / output / rotation) but had no format; the agent already had
both tracing formatters (json/text) but hardcoded by daemon-vs-foreground and took its level from
RUST_LOG only. This unifies them.

Design — DRY the contract, native implementations

Hub is TS, agent is Rust → no shared runtime, so the DRY is a single documented contract, implemented
twice (no codegen/shared-schema machinery for a few fields).

  • shared/hub: format = "text" | "jsonl" (default jsonl) added to LogConfig + extractLogConfig;
    extractAgentConfig derives the agent's level + format from the same [logging] section, with
    defensive type-guards (a malformed [agent]/[logging] value falls back to defaults instead of
    crashing hub startup).
  • HubLogger: the API-backing log file (hub.jsonl, read by /api/logs) is always JSONL;
    format governs the stderr/console rendering (structured-to-file, pretty-to-console). Enabling
    format=text never blinds the in-app log viewer or file-tailing aggregators.
  • agent (Rust): tracing_subscriber is driven by config-supplied --log-level + --format
    (formatters already existed); config level is honored when RUST_LOG is unset (RUST_LOG still
    overrides). Default jsonl preserved.
  • delivery: the hub passes --log-level/--format to the local daemon (agent-launcher) and to
    remote agents — OS-aware (POSIX single-quote for Unix, cmd.exe %VAR%+double-quote for
    Windows, matching the existing deploy convention) and only to agents the hub deployed this session
    (known-current binary); found/pre-existing remote agents run --stdio only, preserving back-compat.
    server.ts now forwards the parsed agent config into SessionManager (closing an existing gap).
  • Contract documented once in docs/plans/logging-daemon.md + docs/SPEC.md.

Behavior-preserving by default (jsonl).

Verification

  • TS: vitest packages/hub packages/shared → 1663 passed / 2 skipped / 0 failed; biome + tsc clean; no
    new skips.
  • Rust: cargo fmt --check, cargo clippy -p termora-agent -- -D warnings, cargo test -p termora-agent
    (82 tests) → green.
  • Hardened across several orthogonal-gate rounds (codex). The gate caught and we fixed: text format
    blinding the log API; a malformed-TOML hub-startup crash exposed by wiring the agent config; unquoted
    remote exec path; POSIX-only quoting breaking Windows remotes; new args breaking older remote agents.

Gate status (degraded GATE_OK — documented)

Final gate on the head: codex = CLEAN; copilot exogenously unavailable (rate-limited / à sec)
across these runs. Per the gate's set-union semantics a single CLEAN satisfies when the other engine is
exogenously down.

…og config (#51)

Single [logging] contract, two native implementations (DRY the contract, not
the code across the TS hub / Rust agent boundary).

- shared/hub: add format "text"|"jsonl" (default jsonl) to LogConfig +
  extractLogConfig; HubLogger renders JSONL (unchanged default) or a
  human-readable text line. extractAgentConfig derives the agent's level +
  format from the same [logging] section.
- agent (Rust): drive tracing_subscriber from config-supplied --log-level +
  --format (the json/text formatters already existed); config level is honored
  when RUST_LOG is unset (RUST_LOG still overrides). Default jsonl preserved.
- delivery: hub passes --log-level/--format to the local daemon (agent-launcher)
  and the remote agent (ssh-agent exec); server.ts now forwards the parsed agent
  config into SessionManager (closing an existing plumbing gap).
- contract documented once in docs/plans/logging-daemon.md + docs/SPEC.md.

Behavior-preserving by default. Closes #51.
@oorabona oorabona force-pushed the feat/harmonize-logging-config branch from b8d02c5 to b014c0b Compare June 8, 2026 23:58
@oorabona oorabona merged commit 07bef75 into main Jun 9, 2026
8 checks passed
@oorabona oorabona deleted the feat/harmonize-logging-config branch June 9, 2026 07:59
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.

Harmonize hub+agent logging config (configurable format text|jsonl + unified level)

1 participant