Files
deepseek-harness/docs/rfc/implemented/architecture/2026-06-11-custom-schema-dsl.md
T
Tianyi Cui 605587e79c docs(rfc): classify RFCs by kind via path-encoded subdirectories
Add a second axis to every RFC — its class (feature, bug-fix,
simplification, architecture, process, testing) — encoded in the path
as docs/rfc/{lifecycle}/{class}/file.md. The folder is the label, so
the closed set is enforced by structure rather than a parsed field.

Two new doc-sync gates back it:
- verify-rfc-classification: every RFC sits in a valid class folder and
  the README index lists it under the matching lifecycle→class heading.
- verify-doc-refs: every docs/*.md path cited in a packages|examples TS
  comment resolves — closes a drift class verify-md-links can't see, and
  catches the four comment refs this reorg moved.

The README gains a Classification section explaining the taxonomy and
per-class index sub-sections. A self-referential process RFC records why
the scheme is path-encoded and gated.
2026-06-20 22:29:45 +08:00

1.7 KiB

RFC: Custom typed tool-schema DSL instead of schemastery

Status: implemented (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 ToolDefinitions 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.