Hard line breaks mid-paragraph make docs harder to edit and diff — a one-word change reflows and re-diffs the whole paragraph. Reflow all tracked non-vendor Markdown (plus vendor/AGENTS.md) so each prose paragraph is a single line; soft-wrapping is the editor's job. Fenced code, tables, and list structure are preserved (wrapped list items fold to one line per bullet). Documents the convention in AGENTS.md.
2.2 KiB
2.2 KiB
RFC 005: Runtime validation at the model boundary, error taxonomy, dev-mode invariants
Status: proposed
Problem
Three gaps where compile-time guarantees stop:
- Tool args are model-generated JSON —
defineTool'sInferArgs<S>claim is only as true as the model's output. Today a malformed call reachesexecuteuntyped-in-practice. - Tool errors flatten to a text block; name/code/stack are lost, so future sandbox/retry plugins can't distinguish ENOENT from EACCES, and the model gets less actionable feedback than it could.
- Loop ordering invariants (seq monotonicity, step/turn event nesting, turn-number continuity) are asserted only where tests look.
Proposal
- Schema validation in defineTool: before
execute, validate parsed args against the SchemaSpec (the converter already encodes the structure — a small interpreter walks it: presence of required keys, primitive type checks, enum membership, recursion into objects/arrays). On mismatch, return anisErrorToolExecutionResult describing the violation — the model can self-correct. Raw-registered tools (MCP) keep validating their own input. - Structured error taxonomy: per-package error classes extending a common
HarnessError(name,code,causechaining).ToolExecutionResultgains optionalerror: { name, code }alongside the model-facing text. The loop'serrorDataconsumes it; sessionerrorevents carry the code. This also properly fixes the non-Error-throw message degradation found in review. - Dev-mode invariants: a
dsh-invariantsdebug plugin (everything is a plugin — it's just listeners) asserting, when enabled: session seq strictly increases;step/startprecedes its chunks;turn/start/turn/endpair and nest; tool/call has a matching tool/result; status transitions are legal. Enabled in tests and the demo; off in production. Doubles as executable documentation of the event contract.
Plan
2 first (taxonomy is a dependency of 1's error shape), then 1, then 3. Property tests (RFC 001) then close the loop: generated args ↔ validator ↔ InferArgs agreement.
Risks
Validator/InferArgs drift — covered by the RFC 001 composition property. Validation cost per call is negligible next to a model call.