feat(jobs): node-local job ownership and capability-gated job__* visibility

Graph LLM nodes now own the jobs they start, on every exit path. A new
node_job_scope on RequestContext records job ids started while a node
runs: the turn-end guardrail nags only about the node's own jobs
(parallel branches no longer see each other's), and the node executor
reaps — cancels and deregisters — anything left registered when the
node exits, including error, timeout, and retry-exhaustion paths.
Cross-node job handoff is no longer possible; a crashed node takes its
in-flight jobs with it.

With inheritance gone, job__* declarations are gated on capability:
the family is only declared when at least one declared tool would pass
job__start's whitelist (shared predicate: is_backgroundable_tool). One
carve-out — while a context still owns registered jobs (job started,
tool disabled mid-session), the lifecycle verbs stay declared so a
running job can never become unreachable; job__start alone disappears.
A graph node with tools: [] now sees no job__* tools at all.

Prompt instructions, tool declarations, and graph.example.yaml updated
to the node-local semantics; +7 tests, 8 visibility pins rewritten.
This commit is contained in:
2026-08-26 13:43:05 -06:00
parent bfb8105682
commit 404a45a311
7 changed files with 311 additions and 45 deletions
+4
View File
@@ -693,6 +693,10 @@ impl Functions {
self.declarations.extend(jobs::job_function_declarations());
}
pub fn append_declaration(&mut self, declaration: FunctionDeclaration) {
self.declarations.push(declaration);
}
pub fn append_teammate_functions(&mut self) {
self.declarations
.extend(supervisor::teammate_function_declarations());