workflow: harden the seam-contract tests ahead of the engine swap

Three engine-agnostic pins, landed BEFORE the worker-thread port so the
port commit demonstrates contract preservation against them:

- tool-workflow: the tool:<toolName> prompt-section registration was
  entirely unasserted — assemble() now pins the section present under
  the CONFIGURED name and gone after fiber dispose (the packages
  AGENTS.md dispose-and-assert-cleanup rule; tool-bash is the template).
- tool-workflow: drop the dead `??` re-defaulting of already-
  schemastery-resolved config (the hidden-fallback shape AGENTS.md
  bans) and the direct-apply test that existed only to cover those
  branches; both engines' `config as ResolvedConfig` is the pattern.
- workflow-vm: workflow/end was asserted only on completed runs — the
  cancelled path and the grace force-settle path now pin the event and
  its stopReason/error/agentsStarted payload (an observer's only death
  signal on those paths).
This commit is contained in:
imccyu
2026-07-09 18:16:51 +08:00
parent 4a15c8a479
commit fbc9eb313c
3 changed files with 24 additions and 14 deletions

View File

@@ -49,6 +49,8 @@ export const Config: z<Config> = z.object({
maxResultChars: z.natural().min(1).default(50_000),
})
type ResolvedConfig = Required<Config>
/**
* The script-authoring contract, embedded in the tool description. This IS the
* model-facing spec: the meta block, the hooks and their exact semantics, and
@@ -120,8 +122,9 @@ function renderResult(run: WorkflowRun, result: WorkflowResult, maxChars: number
}
export function apply(ctx: Context, config: Config): void {
const maxResultChars = config.maxResultChars ?? 50_000
const toolName = config.toolName ?? 'workflow'
// schemastery (the exported Config schema) has already filled the defaulted
// fields; the assertion records that resolution, not a hidden fallback.
const { toolName, maxResultChars } = config as ResolvedConfig
// Usage policy ships with the tool (the master convention: tool guidance
// lives in tool plugins as prompt sections, not in the deployment persona).
ctx.systemPrompt.section({