Logging overhaul: per-task log files, daemon.log drill-down

Switch from jobkit-daemon crate to jobkit with daemon feature.
Wire up per-task log files for all daemon-spawned agent tasks.

Changes:
- Use jobkit::daemon:: instead of jobkit_daemon::
- All agent tasks get .log_dir() set to $data_dir/logs/
- Task log path shown in daemon status and TUI
- New CLI: poc-memory agent daemon log --task NAME
  Finds the task's log path from status or daemon.log, tails the file
- LLM backend selection logged to daemon.log via log_event
- Targeted agent job names include the target key for debuggability
- Logging architecture documented in doc/logging.md

Two-level logging, no duplication:
- daemon.log: lifecycle events with task log path for drill-down
- per-task logs: full agent output via ctx.log_line()

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
Kent Overstreet 2026-03-19 11:17:07 -04:00
parent f2c2c02a22
commit 49f72cdac3
7 changed files with 192 additions and 54 deletions

View file

@ -52,7 +52,7 @@ struct DaemonStatus {
}
fn fetch_status() -> Option<DaemonStatus> {
let json = jobkit_daemon::socket::send_rpc(&crate::config::get().data_dir, "")?;
let json = jobkit::daemon::socket::send_rpc(&crate::config::get().data_dir, "")?;
serde_json::from_str(&json).ok()
}
@ -427,11 +427,8 @@ fn render_overview(frame: &mut Frame, app: &App, area: Rect) {
),
Span::raw(format!(" {}", progress)),
]));
if matches!(t.status, TaskStatus::Running) && !t.output_log.is_empty() {
let skip = t.output_log.len().saturating_sub(2);
for line in &t.output_log[skip..] {
lines.push(Line::from(format!("{}", line)).fg(Color::DarkGray));
}
if let Some(ref lp) = t.log_path {
lines.push(Line::from(format!(" │ log: {}", lp)).fg(Color::DarkGray));
}
}
}
@ -685,11 +682,9 @@ fn render_agent_tab(frame: &mut Frame, app: &App, agent_type: &str, area: Rect)
]));
}
// Output log
if !t.output_log.is_empty() {
for log_line in &t.output_log {
lines.push(Line::from(format!("{}", log_line)).fg(Color::DarkGray));
}
// Log file path
if let Some(ref lp) = t.log_path {
lines.push(Line::from(format!(" │ log: {}", lp)).fg(Color::DarkGray));
}
// Error
@ -785,7 +780,7 @@ fn short_name(name: &str) -> String {
}
fn send_rpc(cmd: &str) -> Option<String> {
jobkit_daemon::socket::send_rpc(&crate::config::get().data_dir, cmd)
jobkit::daemon::socket::send_rpc(&crate::config::get().data_dir, cmd)
}
// --- Entry point ---