Derive Shojiku's definitions.yml and the params-building code from an existing data source — a database schema, ORM models, or an API payload. Use when a Shojiku document must be fed from data that already lives somewhere, before (or alongside) authoring the template.
Install
npx skillscat add kengos/shojiku/shojiku-definitions-author Install via the SkillsCat registry.
Shojiku Definitions Author
Audience: AI agents only. A human gives you access to their schema
(SQL DDL, ORM models, an API response, a CSV header row) and names the
document they want; you produce thedefinitions.ymlthe template
will validate against, aparams.jsonsample, and the code that
builds params from the real source at render time.
You are building the SEAM between an application's data and a Shojiku
template. The engine validates every template binding againstdefinitions.yml and every params payload against the same file — so
the quality of this file decides whether mistakes surface as diagnostics
at author time or as blank spots on paper.
The definitions schema itself (types, formats, constraints) is
normative in
docs/engine/definitions.md; the
engine-access commands and the authoring wire gotchas live in
shojiku-template-author — read
both, restate neither.
The mapping procedure
- Read the source of truth, not a description of it. Ask for the
DDL / model files / a REAL sample payload. Column types, nullability
and enum sets are the facts the definitions must mirror. - Shape the params tree by DOCUMENT ROLE, not by table. A receipt
wantsrecipient.name,amount.total_in_tax,items[]— notorders_join_customers. Nesting mirrors the params JSON exactly;
top-level objects become the Designer's field groups, so group by
what a human filling the form would expect. - Line items are
type: arraywith anitems:object whose keys
are RELATIVE to one row. DeclareminItemsonly when the document
actually requires a row (a blank order form does not). - Give every money/date/count field its semantic pair:
type: number+format: currency,type: string+format: date(bareYYYY-MM-DD) orformat: date-time(FULL
RFC 3339 — an offset-less timestamp is refused),type: integer+format: quantityONLY for a standalone count (it prints the
locale's counter word — a count with its own unit column stays a
plain integer). - The engine does no math. Totals, tax lines, per-rate summaries
are params fields the host computes; declare them, and write the
computation into the params-building code, next to the query. - Enums and constraints go in. A status column with three values
becomesenum:; lengths becomeminLength/maxLengthwhen the
layout depends on them.title:in the READER's language — these
label the Designer's palette. - Blank-form fields get
placeholderat the FIELD level, so one
template serves the blank ↔ filled pair withoutmissing_data. - Write the params builder in the host's language, from the real
schema to the declared tree — a function that takes the row(s) and
returns the params object. The worked production shape (SQLite →
params → PDF inside a Docker image) is
examples/deploy/python/render.py;
mirror its layering: static document facts stay in a committed base
params file, transactional values come from the query.
Prove it against the engine
Supplying BOTH definitions and params turns on params-vs-schema
validation — the params_* diagnostics (required / type / range /
enum / unknown keys) are the proof this mapping is honest:
- Build a sample
params.jsonthrough YOUR builder from real rows. validatewith definitions + template + params (command table in
shojiku-template-author § Engine access).- Fix until clean — a
params_unknown_keymeans the builder emits
something undeclared; aparams_requiredmeans the query can return
less than the document needs (decide:placeholder, a default in
the builder, or a realrequiredfailure). - Render the preview and LOOK at it: a declared-but-wrong mapping
(unit price where the amount should be) validates clean and only the
pixels catch it.
What NOT to do
- Do not invent per-language reflection tooling that generates
definitions from live DB connections automatically — the mapping is a
judgment (roles, grouping, formats), and this skill IS the tool. - Do not put geometry, display formats, or locale wording into
definitions.yml— formatting lives in the template'sdefaults:/styles:, locale data in packs. - Do not lie about shapes to quiet a warning (
type: stringfor a
number, a scalar for a list). The warning is the seam telling the
truth.