practice slice 3B — the practice agents: partitioner, generator, grader
src/agent/subagents/practice.ts: createPracticeAgents(deps) with the ExtractionModels mirror (per-stage engine overrides + engineFor + providerKeyMissing + refuseIfStagesUnready, all three roles strong-tier). Generator doctrine = the owner's problem-engineering framework verbatim (minus Sources) + Part III wiring section per the green-lit amendments (FULL SET input with minimal-use doctrine; degradation never in meta-commentary). Partitioner: true-partition doctrine, validate via chainCoverage + exactly-once + unknown-ids, error-back retries through runSubmitAgent's new validate hook (ToolInputError → error tool result). Generator: echo law (chains set === target). Grader: verdict union + nonempty feedback (schema-enforced). renderChains/renderPropositions/ renderParams/renderPreviousProblems. BACKGROUND_MODEL_ROLES extended with the practice trio (settings override symmetry). runSubmitAgent gains the validate seam (null = accept). 16-test faux-engine suite incl. retry paths, refusal gates, neverSubmitted.
This commit is contained in:
@@ -13,7 +13,7 @@
|
||||
import type { Usage } from "@earendil-works/pi-ai";
|
||||
import type { AgentTool } from "@earendil-works/pi-agent-core";
|
||||
import type { TSchema } from "typebox";
|
||||
import { toToolResult } from "../tool-execute.ts";
|
||||
import { toToolResult, ToolInputError } from "../tool-execute.ts";
|
||||
import type { ModelRole } from "../../../config.ts";
|
||||
import type { PiEngine } from "../models.ts";
|
||||
import { runSubagent } from "./pi-run.ts";
|
||||
@@ -42,6 +42,11 @@ export async function runSubmitAgent<T>(opts: {
|
||||
* TypeBox validation — the sanctioned shim point). Identity by
|
||||
* default; extraction wires healStringifiedArrays here. */
|
||||
prepareArguments?: (args: unknown) => unknown;
|
||||
/** Semantic validation at the submit seam: the value is schema-valid
|
||||
* but may violate a PIPELINE law (coverage, echo-equality). Returning
|
||||
* a problem string throws ToolInputError → pi turns it into an error
|
||||
* tool result → the model retries within maxTurns. null = accept. */
|
||||
validate?: (value: T) => string | null;
|
||||
}): Promise<T> {
|
||||
let submitted: T | undefined;
|
||||
const result = await runSubagent(
|
||||
@@ -55,7 +60,10 @@ export async function runSubmitAgent<T>(opts: {
|
||||
prepareArguments: (args) =>
|
||||
(opts.prepareArguments ? opts.prepareArguments(args) : args) as never,
|
||||
execute: async (_toolCallId, input) => {
|
||||
submitted = opts.fill(input);
|
||||
const value = opts.fill(input);
|
||||
const problem = opts.validate?.(value) ?? null;
|
||||
if (problem) throw new ToolInputError(opts.toolName, [problem]);
|
||||
submitted = value;
|
||||
return toToolResult(submitted);
|
||||
},
|
||||
} satisfies AgentTool<any>,
|
||||
|
||||
Reference in New Issue
Block a user