Files
deepseek-harness/docs/adr/0005-custom-schema-dsl-over-schemastery.md
Tianyi Cui 9b8fccc6f9 Backfill architecture decision records
Seven ADRs capturing the why behind decisions already made: vendoring
Cordis as source with a guarded manifest; the microkernel event
taxonomy with one swappable concrete loop; event-sourced sessions
with derived history and the append-before-emit ordering contract;
the provider-neutral content-block vocabulary (and why not
OpenAI/Anthropic shapes); the custom tool-schema DSL over schemastery;
tool schemas living in the prompt assembly; and mechanical quality
gates over prose guidelines (the agents-write-the-code rationale).
2026-06-11 15:24:14 +08:00

36 lines
1.6 KiB
Markdown

# ADR 0005: Custom typed tool-schema DSL instead of schemastery
Status: accepted (2026-06-11)
## Context
Tool parameters must reach the model as standard JSON Schema (the wire
format), and tool authors deserve typed `execute(args)` without casts. The
repo already vendors schemastery (used for plugin Config), so reusing it was
the obvious candidate. The user also explicitly preferred per-property
`required: true` booleans over JSON Schema's separate `required` array.
## Decision
A small custom DSL in dsh-tools: `SchemaSpec` (per-property specs with
`required: true` booleans), type-level `InferArgs<S>` mapping a spec to the
argument type (required keys non-optional, others genuinely optional via `?`),
a runtime `schemaSpecToJsonSchema()` converter, and `defineTool()` tying them
together. Raw JSON-Schema `ToolDefinition`s remain accepted by
`ToolRegistry.register()` — that's how MCP-sourced tools arrive.
Schemastery was evaluated and rejected for this use: it targets validation /
transformation against StandardSchema, not JSON Schema *generation*, so it
would add indirection without producing the wire format cleanly.
## Consequences
- First-party tool authors get zero-cast typed args; the type gymnastics cost
stays inside the core package (sanctioned by the AGENTS.md type-safety
policy).
- The DSL is deliberately small (string/number/boolean/object/array, enum,
default, nested properties/items). Gaps vs full JSON Schema (unions,
formats, constraints) are accepted until real tools demand them.
- The InferArgs mapping is regression-tested at the type level (expectTypeOf)
after an early optionality bug shipped and was caught by review.