src/Runtime/JobManager.php:57 unsets the job entry as soon as it transitions into any JobState::isTerminal() value. src/Internal/Runtime/JobListHandler.php:23 queries JobManager::all() to build the Jobs response and therefore can only ever return jobs that are still in flight. The matchesStatus filter at src/Internal/Runtime/JobListHandler.php:59 happily accepts a request like filter.status: ["completed", "failed", "cancelled"], but the list will always be empty even though the runtime has the historical envelopes in EventLog. Operators cannot reconstruct recent job history through the public API, and created_after / created_before filters lose any value past the moment a job finishes.
The protocol guide at docs/guides/jobs.md and the README quick-start advertise session.list_jobs as the canonical way to enumerate jobs for an operator dashboard. Returning only the currently-running subset is surprising and silently breaks pagination assumptions because the cursor is the last-seen job id, but those ids vanish as soon as the job terminates.
Fix prompt: Keep terminal jobs reachable from the list path for some bounded retention window — either store a separate map of terminal jobs inside JobManager with a configurable retention (e.g., last N or last X minutes), or populate the list response from the EventLog job.accepted/job.completed/job.failed/job.cancelled envelopes. Update tests/Integration/JobLifecycleTest.php (or the matching list test) to assert that a completed job continues to appear in session.list_jobs results within the retention window with the expected status, and that pagination cursors continue to function after a job terminates.
src/Runtime/JobManager.php:57unsets the job entry as soon as it transitions into anyJobState::isTerminal()value.src/Internal/Runtime/JobListHandler.php:23queriesJobManager::all()to build theJobsresponse and therefore can only ever return jobs that are still in flight. ThematchesStatusfilter atsrc/Internal/Runtime/JobListHandler.php:59happily accepts a request likefilter.status: ["completed", "failed", "cancelled"], but the list will always be empty even though the runtime has the historical envelopes inEventLog. Operators cannot reconstruct recent job history through the public API, andcreated_after/created_beforefilters lose any value past the moment a job finishes.The protocol guide at
docs/guides/jobs.mdand the README quick-start advertisesession.list_jobsas the canonical way to enumerate jobs for an operator dashboard. Returning only the currently-running subset is surprising and silently breaks pagination assumptions because the cursor is the last-seen job id, but those ids vanish as soon as the job terminates.Fix prompt: Keep terminal jobs reachable from the list path for some bounded retention window — either store a separate map of terminal jobs inside
JobManagerwith a configurable retention (e.g., last N or last X minutes), or populate the list response from theEventLogjob.accepted/job.completed/job.failed/job.cancelledenvelopes. Updatetests/Integration/JobLifecycleTest.php(or the matching list test) to assert that a completed job continues to appear insession.list_jobsresults within the retention window with the expectedstatus, and that pagination cursors continue to function after a job terminates.