feat(tasks): per-task history / audit timeline
Surfaces a task's lifecycle straight from the event log (the source of truth) so
you can see what actually happened to it — claim/submit/complete, notes, links,
git-driven status — rather than only its current state. Useful for debugging a
live agent run, where current state alone doesn't say how it got there.
- TaskHistory.render: pure timeline renderer (split content/lifecycle to stay under
the complexity cap, mirroring DefaultTaskReducer).
- TaskService.history(id): the task's own events, in order; survives soft-delete
(the deletion is part of the trail), empty for an id that never existed.
- GET /tasks/{id}/history (200 text timeline, 404 when the id never existed) and
the `correx task history <id>` CLI command.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -91,6 +91,7 @@ class TaskCommand : CliktCommand(name = "task") {
|
||||
TaskListCommand(),
|
||||
TaskSearchCommand(),
|
||||
TaskShowCommand(),
|
||||
TaskHistoryCommand(),
|
||||
TaskCreateCommand(),
|
||||
TaskClaimCommand(),
|
||||
TaskCompleteCommand(),
|
||||
@@ -160,6 +161,19 @@ class TaskShowCommand : TaskHttpCommand("show") {
|
||||
}
|
||||
}
|
||||
|
||||
class TaskHistoryCommand : TaskHttpCommand("history") {
|
||||
private val id by argument("TASK_ID")
|
||||
|
||||
override fun run() = http { client ->
|
||||
val resp = client.get("${baseUrl()}/tasks/$id/history")
|
||||
if (resp.status == HttpStatusCode.NotFound) {
|
||||
System.err.println("No such task: $id")
|
||||
} else {
|
||||
print(resp.bodyAsText())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TaskCreateCommand : TaskHttpCommand("create") {
|
||||
private val project by option("--project", help = "Project key, e.g. 'auth'").required()
|
||||
private val title by option("--title").required()
|
||||
|
||||
Reference in New Issue
Block a user