diff --git a/src/ClaudeDo.Logging/DefaultTaskIdEnricher.cs b/src/ClaudeDo.Logging/DefaultTaskIdEnricher.cs
new file mode 100644
index 0000000..cea4b60
--- /dev/null
+++ b/src/ClaudeDo.Logging/DefaultTaskIdEnricher.cs
@@ -0,0 +1,15 @@
+using Serilog.Core;
+using Serilog.Events;
+
+namespace ClaudeDo.Logging;
+
+/// Ensures every log event carries a TaskId property (defaulting to "-")
+/// so the output template's [{TaskId}] column never renders the raw token.
+public sealed class DefaultTaskIdEnricher : ILogEventEnricher
+{
+ public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
+ {
+ if (!logEvent.Properties.ContainsKey("TaskId"))
+ logEvent.AddPropertyIfAbsent(propertyFactory.CreateProperty("TaskId", "-"));
+ }
+}
diff --git a/src/ClaudeDo.Logging/Placeholder.cs b/src/ClaudeDo.Logging/Placeholder.cs
deleted file mode 100644
index c72b270..0000000
--- a/src/ClaudeDo.Logging/Placeholder.cs
+++ /dev/null
@@ -1,3 +0,0 @@
-namespace ClaudeDo.Logging;
-
-internal static class Placeholder;
diff --git a/tests/ClaudeDo.Worker.Tests/ClaudeDo.Worker.Tests.csproj b/tests/ClaudeDo.Worker.Tests/ClaudeDo.Worker.Tests.csproj
index bfa4f50..c2fb766 100644
--- a/tests/ClaudeDo.Worker.Tests/ClaudeDo.Worker.Tests.csproj
+++ b/tests/ClaudeDo.Worker.Tests/ClaudeDo.Worker.Tests.csproj
@@ -25,6 +25,7 @@
+
diff --git a/tests/ClaudeDo.Worker.Tests/Logging/DefaultTaskIdEnricherTests.cs b/tests/ClaudeDo.Worker.Tests/Logging/DefaultTaskIdEnricherTests.cs
new file mode 100644
index 0000000..d360f1f
--- /dev/null
+++ b/tests/ClaudeDo.Worker.Tests/Logging/DefaultTaskIdEnricherTests.cs
@@ -0,0 +1,49 @@
+using ClaudeDo.Logging;
+using Serilog;
+using Serilog.Context;
+using Serilog.Core;
+using Serilog.Events;
+
+namespace ClaudeDo.Worker.Tests.Logging;
+
+public sealed class DefaultTaskIdEnricherTests
+{
+ private sealed class CollectingSink : ILogEventSink
+ {
+ public List Events { get; } = new();
+ public void Emit(LogEvent logEvent) => Events.Add(logEvent);
+ }
+
+ [Fact]
+ public void AddsDash_WhenNoTaskIdInScope()
+ {
+ var sink = new CollectingSink();
+ using var logger = new LoggerConfiguration()
+ .Enrich.FromLogContext()
+ .Enrich.With(new DefaultTaskIdEnricher())
+ .WriteTo.Sink(sink)
+ .CreateLogger();
+
+ logger.Information("hello");
+
+ var prop = Assert.Single(sink.Events).Properties["TaskId"];
+ Assert.Equal("\"-\"", prop.ToString());
+ }
+
+ [Fact]
+ public void KeepsPushedTaskId_WhenInScope()
+ {
+ var sink = new CollectingSink();
+ using var logger = new LoggerConfiguration()
+ .Enrich.FromLogContext()
+ .Enrich.With(new DefaultTaskIdEnricher())
+ .WriteTo.Sink(sink)
+ .CreateLogger();
+
+ using (LogContext.PushProperty("TaskId", "task-42"))
+ logger.Information("hello");
+
+ var prop = Assert.Single(sink.Events).Properties["TaskId"];
+ Assert.Equal("\"task-42\"", prop.ToString());
+ }
+}