chore: absorb the no-nudge seam into the workflow tree

The parent branch dropped structuredNudgeRetries; the two workflow-side test
setups stop passing it, and the RFC's foundation paragraph now describes the
current design (final-ASSEMBLY enforcement logged via request/header, the
post-capture pre-execute deny, the start() schema snapshot, no re-prompt)
instead of the retired agent/request + nudge shape.
This commit is contained in:
Tianyi Cui
2026-07-07 09:26:47 +08:00
parent e63bf54df0
commit 4641f1a851
3 changed files with 3 additions and 3 deletions

View File

@@ -36,7 +36,7 @@ A `workflow` tool mirroring `dsh-tool-subagent`'s synchronous shape: start, awai
### The foundation: structured output on the subagent seam
`agent({schema})` needs `SubagentStartRequest.outputSchema` to actually work; it was vocabulary without an implementation (`outputSchema: false` everywhere). Implemented in `dsh-subagent-inprocess` for both in-process backends: a globally registered `structured_output` capture tool whose per-child schema is enforced by a `prepend: true` `agent/request` listener doing FINAL-REQUEST enforcement (post-processing `await next()` — cooperative mutation would not survive a downstream listener returning a replacement request; the listener also appends the calling instruction to the request's `system` text, since `AgentOptions` carries no per-agent prompt field), a `prepend: true` `agent/turn-continuation` veto after capture (no wasted extra model step, and an earlier-registered force-continue listener cannot short-circuit it), validation-retry in-turn via `ToolArgsError`, and a clean-finish nudge loop (`structuredNudgeRetries`). Lifetime is refcounted by backends (plugin lifetime) AND live runs (start → settle). The seam's `outputSchema` type became the raw JSON-Schema SUBSET (`StructuredOutputSchema` in dsh-tools: single-string `type`, `properties`/`required`/`additionalProperties`, `items`, scalar `enum`/`const`; anything unenforced is rejected loud) — the schema travels verbatim to the model as the forced tool's parameters, so the wire format, not the author DSL, is the right vocabulary.
`agent({schema})` needs `SubagentStartRequest.outputSchema` to actually work; it was vocabulary without an implementation (`outputSchema: false` everywhere). Implemented in `dsh-subagent-inprocess` for both in-process backends: a globally registered `structured_output` capture tool whose per-child schema is enforced by a `prepend: true` `system-prompt/assemble` listener doing FINAL-ASSEMBLY enforcement (post-processing `await next()` — cooperative mutation would not survive a downstream listener returning a replacement assembly; the calling instruction rides as a trailing prompt section, since `AgentOptions` carries no per-agent prompt field, and the loop logs the result as the step's `request/header`, keeping the injection reconstructable), a `prepend: true` `agent/turn-continuation` veto after capture (no wasted extra model step) plus a `tools/pre-execute` deny for calls arriving after the capture (terminal within the step, not only at its end), and validation-retry in-turn via `ToolArgsError`. The schema is `structuredClone`d at `start()` (caller mutation cannot drift enforcement). Deliberately NO re-prompt: a child that finishes cleanly without calling the tool settles `error` to the parent. Lifetime is refcounted by backends (plugin lifetime) AND live runs (start → settle). The seam's `outputSchema` type became the raw JSON-Schema SUBSET (`StructuredOutputSchema` in dsh-tools: single-string `type`, `properties`/`required`/`additionalProperties`, `items`, scalar `enum`/`const`; anything unenforced is rejected loud) — the schema travels verbatim to the model as the forced tool's parameters, so the wire format, not the author DSL, is the right vocabulary.
## Deferred (documented non-goals of this cut)