From e6a19c0cb34f29aa6a85346861222de31eb49413 Mon Sep 17 00:00:00 2001 From: "julia.evseeva" Date: Wed, 25 Feb 2026 18:56:48 +0100 Subject: [PATCH 01/43] Get theme updates with the fixed image rendering --- docs/_preview/go.mod | 2 +- docs/_preview/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_preview/go.mod b/docs/_preview/go.mod index ced82e07df..3e6bbced4d 100644 --- a/docs/_preview/go.mod +++ b/docs/_preview/go.mod @@ -3,7 +3,7 @@ module spine.io/validation/docs/preview go 1.25.6 require ( - github.com/SpineEventEngine/site-commons v0.0.0-20260225164144-d5e941ada2ae // indirect + github.com/SpineEventEngine/site-commons v0.0.0-20260225175457-ace8e24c3a0f // indirect github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20400 // indirect github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2 v2.21100.20000 // indirect github.com/twbs/bootstrap v5.3.8+incompatible // indirect diff --git a/docs/_preview/go.sum b/docs/_preview/go.sum index 69c70e17db..555f61d068 100644 --- a/docs/_preview/go.sum +++ b/docs/_preview/go.sum @@ -1,5 +1,5 @@ -github.com/SpineEventEngine/site-commons v0.0.0-20260225164144-d5e941ada2ae h1:pNjNP8lCXbbzArqX42kc2Rbj2LpqU18ltF+skxZ/xO4= -github.com/SpineEventEngine/site-commons v0.0.0-20260225164144-d5e941ada2ae/go.mod h1:tkAl4StIREKmz9r5PiJtuDhvwMMkFXKWcaTyxhIikho= +github.com/SpineEventEngine/site-commons v0.0.0-20260225175457-ace8e24c3a0f h1:b8GVB6Kydf+FYlHQ/05qistXQWA1mFzt6SpG6Pw7mfY= +github.com/SpineEventEngine/site-commons v0.0.0-20260225175457-ace8e24c3a0f/go.mod h1:tkAl4StIREKmz9r5PiJtuDhvwMMkFXKWcaTyxhIikho= github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20400 h1:L6+F22i76xmeWWwrtijAhUbf3BiRLmpO5j34bgl1ggU= github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20400/go.mod h1:uekq1D4ebeXgduLj8VIZy8TgfTjrLdSl6nPtVczso78= github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2 v2.21100.20000 h1:GZxx4Hc+yb0/t3/rau1j8XlAxLE4CyXns2fqQbyqWfs= From 205c92aa3a7dd53670aaafac85ae3797fce3d022 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 19:11:08 +0000 Subject: [PATCH 02/43] Add `writer` skill --- .agents/skills/writer/SKILL.md | 47 +++++++++++++++++++ .agents/skills/writer/agents/openai.yaml | 5 ++ .../writer/assets/templates/doc-page.md | 23 +++++++++ .../writer/assets/templates/kdoc-example.md | 12 +++++ 4 files changed, 87 insertions(+) create mode 100644 .agents/skills/writer/SKILL.md create mode 100644 .agents/skills/writer/agents/openai.yaml create mode 100644 .agents/skills/writer/assets/templates/doc-page.md create mode 100644 .agents/skills/writer/assets/templates/kdoc-example.md diff --git a/.agents/skills/writer/SKILL.md b/.agents/skills/writer/SKILL.md new file mode 100644 index 0000000000..478d25398c --- /dev/null +++ b/.agents/skills/writer/SKILL.md @@ -0,0 +1,47 @@ +--- +name: writer +description: Write, edit, and restructure user-facing and developer-facing documentation for the Spine `validation` repository. Use when asked to create/update docs such as `README.md`, `docs/**`, `CONTRIBUTING.md`, and other Markdown documentation; when drafting tutorials, guides, troubleshooting pages, or migration notes; and when improving inline API documentation (KDoc) and examples. +--- + +# Write documentation (repo-specific) + +## Decide the target and audience + +- Identify the target reader: end user, contributor, maintainer, or tooling/automation. +- Identify the task type: new doc, update, restructure, or documentation audit. +- Identify the acceptance criteria: “what is correct when the reader is done?” + +## Choose where the content should live + +- Prefer updating an existing doc over creating a new one. +- Place content in the most discoverable location: + - `README.md`: project entry point and “what is this?”. + - `docs/`: longer-form docs (follow existing conventions in that tree). + - `CONTRIBUTING.md`: contributor workflows. + - Source KDoc: API usage, examples, and semantics that belong with the code. + +## Follow local documentation conventions + +- Follow `.agents/documentation-guidelines.md` and `.agents/documentation-tasks.md`. +- Use fenced code blocks for commands and examples; format file/dir names as code. +- Avoid widows, runts, orphans, and rivers by reflowing paragraphs when needed. + +## Make docs actionable + +- Prefer steps the reader can execute (commands + expected outcome). +- Prefer concrete examples over abstract descriptions. +- Include prerequisites (versions, OS, environment) when they are easy to miss. +- Use consistent terminology (match code identifiers and existing docs). + +## KDoc-specific guidance + +- For public/internal APIs, include at least one example snippet demonstrating common usage. +- When converting from Javadoc/inline comments to KDoc: + - Remove HTML like `

` and preserve meaning. + - Prefer short paragraphs and blank lines over HTML formatting. + +## Validate changes + +- For code changes, follow `.agents/running-builds.md`. +- For documentation-only changes in Kotlin/Java sources, prefer `./gradlew dokka`. + diff --git a/.agents/skills/writer/agents/openai.yaml b/.agents/skills/writer/agents/openai.yaml new file mode 100644 index 0000000000..44eaa4e241 --- /dev/null +++ b/.agents/skills/writer/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Writer" + short_description: "Write and update user/developer docs" + default_prompt: "Write or revise documentation in this repository (for example: README.md, docs/**, CONTRIBUTING.md, and API documentation/KDoc). Follow local documentation guidelines in .agents/*.md, keep changes concise and actionable, and include concrete examples and commands where appropriate." + diff --git a/.agents/skills/writer/assets/templates/doc-page.md b/.agents/skills/writer/assets/templates/doc-page.md new file mode 100644 index 0000000000..f405b71e15 --- /dev/null +++ b/.agents/skills/writer/assets/templates/doc-page.md @@ -0,0 +1,23 @@ +# Title + +## Goal + +State what the reader will accomplish. + +## Prerequisites + +- List versions/tools the reader needs. + +## Steps + +1. Do the first thing. +2. Do the next thing. + +## Verify + +Show how the reader can confirm success. + +## Troubleshooting + +- Common failure: likely cause → fix. + diff --git a/.agents/skills/writer/assets/templates/kdoc-example.md b/.agents/skills/writer/assets/templates/kdoc-example.md new file mode 100644 index 0000000000..57e32c5ef3 --- /dev/null +++ b/.agents/skills/writer/assets/templates/kdoc-example.md @@ -0,0 +1,12 @@ +```kotlin +/** + * Explain what this API does in one sentence. + * + * ## Example + * ```kotlin + * // Show the typical usage pattern. + * val result = doThing() + * ``` + */ +``` + From 4744fdb4dd26ed3d0eda6aa38df74ed48bcb582d Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 19:18:48 +0000 Subject: [PATCH 03/43] Add `writer` skill --- skills/writer/SKILL.md | 47 +++++++++++++++++++ skills/writer/agents/openai.yaml | 5 ++ skills/writer/assets/templates/doc-page.md | 23 +++++++++ .../writer/assets/templates/kdoc-example.md | 12 +++++ 4 files changed, 87 insertions(+) create mode 100644 skills/writer/SKILL.md create mode 100644 skills/writer/agents/openai.yaml create mode 100644 skills/writer/assets/templates/doc-page.md create mode 100644 skills/writer/assets/templates/kdoc-example.md diff --git a/skills/writer/SKILL.md b/skills/writer/SKILL.md new file mode 100644 index 0000000000..478d25398c --- /dev/null +++ b/skills/writer/SKILL.md @@ -0,0 +1,47 @@ +--- +name: writer +description: Write, edit, and restructure user-facing and developer-facing documentation for the Spine `validation` repository. Use when asked to create/update docs such as `README.md`, `docs/**`, `CONTRIBUTING.md`, and other Markdown documentation; when drafting tutorials, guides, troubleshooting pages, or migration notes; and when improving inline API documentation (KDoc) and examples. +--- + +# Write documentation (repo-specific) + +## Decide the target and audience + +- Identify the target reader: end user, contributor, maintainer, or tooling/automation. +- Identify the task type: new doc, update, restructure, or documentation audit. +- Identify the acceptance criteria: “what is correct when the reader is done?” + +## Choose where the content should live + +- Prefer updating an existing doc over creating a new one. +- Place content in the most discoverable location: + - `README.md`: project entry point and “what is this?”. + - `docs/`: longer-form docs (follow existing conventions in that tree). + - `CONTRIBUTING.md`: contributor workflows. + - Source KDoc: API usage, examples, and semantics that belong with the code. + +## Follow local documentation conventions + +- Follow `.agents/documentation-guidelines.md` and `.agents/documentation-tasks.md`. +- Use fenced code blocks for commands and examples; format file/dir names as code. +- Avoid widows, runts, orphans, and rivers by reflowing paragraphs when needed. + +## Make docs actionable + +- Prefer steps the reader can execute (commands + expected outcome). +- Prefer concrete examples over abstract descriptions. +- Include prerequisites (versions, OS, environment) when they are easy to miss. +- Use consistent terminology (match code identifiers and existing docs). + +## KDoc-specific guidance + +- For public/internal APIs, include at least one example snippet demonstrating common usage. +- When converting from Javadoc/inline comments to KDoc: + - Remove HTML like `

` and preserve meaning. + - Prefer short paragraphs and blank lines over HTML formatting. + +## Validate changes + +- For code changes, follow `.agents/running-builds.md`. +- For documentation-only changes in Kotlin/Java sources, prefer `./gradlew dokka`. + diff --git a/skills/writer/agents/openai.yaml b/skills/writer/agents/openai.yaml new file mode 100644 index 0000000000..44eaa4e241 --- /dev/null +++ b/skills/writer/agents/openai.yaml @@ -0,0 +1,5 @@ +interface: + display_name: "Writer" + short_description: "Write and update user/developer docs" + default_prompt: "Write or revise documentation in this repository (for example: README.md, docs/**, CONTRIBUTING.md, and API documentation/KDoc). Follow local documentation guidelines in .agents/*.md, keep changes concise and actionable, and include concrete examples and commands where appropriate." + diff --git a/skills/writer/assets/templates/doc-page.md b/skills/writer/assets/templates/doc-page.md new file mode 100644 index 0000000000..f405b71e15 --- /dev/null +++ b/skills/writer/assets/templates/doc-page.md @@ -0,0 +1,23 @@ +# Title + +## Goal + +State what the reader will accomplish. + +## Prerequisites + +- List versions/tools the reader needs. + +## Steps + +1. Do the first thing. +2. Do the next thing. + +## Verify + +Show how the reader can confirm success. + +## Troubleshooting + +- Common failure: likely cause → fix. + diff --git a/skills/writer/assets/templates/kdoc-example.md b/skills/writer/assets/templates/kdoc-example.md new file mode 100644 index 0000000000..57e32c5ef3 --- /dev/null +++ b/skills/writer/assets/templates/kdoc-example.md @@ -0,0 +1,12 @@ +```kotlin +/** + * Explain what this API does in one sentence. + * + * ## Example + * ```kotlin + * // Show the typical usage pattern. + * val result = doThing() + * ``` + */ +``` + From e2cb3f1304d3177e7388de0c4ecbf1a156992400 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 19:20:21 +0000 Subject: [PATCH 04/43] Fix code fence in `kdoc-example.md` --- .agents/skills/writer/assets/templates/kdoc-example.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.agents/skills/writer/assets/templates/kdoc-example.md b/.agents/skills/writer/assets/templates/kdoc-example.md index 57e32c5ef3..c798d13c3b 100644 --- a/.agents/skills/writer/assets/templates/kdoc-example.md +++ b/.agents/skills/writer/assets/templates/kdoc-example.md @@ -1,4 +1,4 @@ -```kotlin +````kotlin /** * Explain what this API does in one sentence. * @@ -8,5 +8,5 @@ * val result = doThing() * ``` */ -``` +```` From 32eb6fb7c1695d172e38b1cd8afed538c75c3fc0 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 19:21:04 +0000 Subject: [PATCH 05/43] Bump version -> `2.0.0-SNAPSHOT.399` --- version.gradle.kts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/version.gradle.kts b/version.gradle.kts index 69fe447967..8b272b178d 100644 --- a/version.gradle.kts +++ b/version.gradle.kts @@ -29,4 +29,4 @@ * * For Spine-based dependencies please see [io.spine.dependency.local.Spine]. */ -val validationVersion by extra("2.0.0-SNAPSHOT.398") +val validationVersion by extra("2.0.0-SNAPSHOT.399") From 701d73f9d77500d173ea40118e31c203b2d2c08c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 20:40:50 +0000 Subject: [PATCH 06/43] Remove `time_options.proto` for now Agents pick up the file repeatedly. We will describe time options when we describe custom validation. --- docs/_options/time_options.proto | 106 ------------------------------- 1 file changed, 106 deletions(-) delete mode 100644 docs/_options/time_options.proto diff --git a/docs/_options/time_options.proto b/docs/_options/time_options.proto deleted file mode 100644 index bc73fe15f5..0000000000 --- a/docs/_options/time_options.proto +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2025, TeamDev. All rights reserved. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * https://www.apache.org/licenses/LICENSE-2.0 - * - * Redistribution and use in source and/or binary forms, with or without - * modification, must retain the above copyright notice and the following - * disclaimer. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, - * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT - * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, - * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY - * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE - * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ - -syntax = "proto3"; - -// API Note on Packaging -// --------------------- -// We do not define the package for this file to allow shorter options for user-defined types. -// This allows to write: -// -// [(when).in = FUTURE]; -// -// instead of: -// -// [(spine.time.when).in = FUTURE]; -// - -import "spine/options.proto"; - -option (type_url_prefix) = "type.spine.io"; -option java_package = "io.spine.time.validation"; -option java_outer_classname = "TimeOptionsProto"; -option java_multiple_files = true; - -import "google/protobuf/descriptor.proto"; - -extend google.protobuf.FieldOptions { - - // See `TimeOption`. - TimeOption when = 73819; -} - -// Specifies that the field value is a point in time lying either in the future or in the past. -// -// Applicable to `google.protobuf.Timestamp` and types introduced in the `spine.time` package -// that describe time-related concepts. -// -// Repeated fields are supported. -// -// Example: Using the `(when)` option. -// -// message ScheduleMeeting { -// spine.time.ZonedDateTime start = 1 [(when).in = FUTURE]; -// } -// -message TimeOption { - - // The default error message. - option (default_message) = "The field `${parent.type}.${field.path}`" - " of the type `${field.type}` must be in the `${when.in}`." - " The encountered value: `${field.value}`."; - - // Defines a restriction for the timestamp. - Time in = 1; - - // Deprecated: please use `error_msg` instead. - string msg_format = 2 [deprecated = true]; - - // A user-defined error message. - // - // The specified message may include the following placeholders: - // - // 1. `${field.path}` – the field path. - // 2. `${field.value}` - the field value. - // 3. `${field.type}` – the fully qualified name of the field type. - // 4. `${parent.type}` – the fully qualified name of the validated message. - // 5. `${when.in}` – the specified timestamp restriction. It is either "past" or "future". - // - string error_msg = 3; -} - -// This enumeration defines restriction for date/time values. -enum Time { - - // The default value (if the time option is not set). - TIME_UNDEFINED = 0; - - // The value must be in the past. - PAST = 1; - - // The value must be in the future. - FUTURE = 2; -} From a608f9b2bf33e6319c09fad19f422b05bcb9efa5 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 20:41:27 +0000 Subject: [PATCH 07/43] Add details to the documentation plan --- .../tasks/validation-documentation-plan.md | 60 +++++++++++++++++-- 1 file changed, 56 insertions(+), 4 deletions(-) diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index fb45460d54..1a31f06adb 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -48,14 +48,66 @@ buildable documentation set, without expanding scope unnecessarily. - Add a Concepts landing page and an “options overview” page that explains: where options come from, how they’re applied, and what code gets generated. - Keep this conceptual (no option-by-option details yet). +- Target outcome: a reader can explain that Validation is enforced by generated code + (not by parsing descriptor/options at runtime) and that the Gradle plugin wires the + Validation Compiler into the build to augment `protoc` output. +- Terminology: use “Validation Compiler” consistently (it is a plugin to the Spine Compiler). +- Pages to create/update: + - Concepts landing: `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/02-concepts/_index.md` + - Options overview: `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/02-concepts/options-overview.md` +- Concepts landing page: planned content (conceptual, 1 screen deeper than “Getting started”) + - Open with a 2–3 sentence “mental model”: + - Constraints are declared in `.proto` files using built-in options imported from `spine/options.proto`. + - The Validation Compiler updates Java sources generated by `protoc` so runtime checks happen in code. + - Explain the “build-time vs runtime” boundary: + - Build-time: options are read from descriptors and used to generate/inject checks into message code. + - Runtime: there is no descriptor parsing; validation runs as regular code in `build()` / `validate()`. + - Add a small pipeline diagram (Mermaid) showing: + `.proto` + `spine/options.proto` import → `protoc` (Java) → Validation Compiler (via Gradle plugin) + → generated JVM API (`build()`, `validate()`). + - Define (briefly) what Protobuf custom options are with a one-sentence refresher, + then link to Protobuf docs for details. + - Clarify “what you write” vs “what you get”: + - You write: option annotations on fields/messages. + - You get: runtime enforcement through `build()` throwing `ValidationException` and + `validate()` returning an error object (as introduced in “Getting started”). + - Mention extensibility without diving in: + - Note that custom validation options + codegen are possible; link forward to + `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/08-custom-validation/_index.md`. + - Close with “What’s next” links: + - Options overview page. + - Custom validation (for organization-specific rules). + - Developers guide (architecture/key modules) for internals. +- Options overview page: planned content (concrete examples, but not an option catalog) + - Purpose statement: explain where built-in options come from and how they influence generated code. + - Where options come from (built-ins only): + - Options are defined in `spine/options.proto` (and related Spine option protos). + - Users import the option proto(s) and annotate their own message/field definitions. + - One-sentence refresher on Protobuf options + a link to Protobuf docs about custom options. + - How options are applied at build time: + - The Gradle plugin integrates Validation into the build. + - Validation Compiler uses the compiled descriptors (including option values) to augment `protoc` output. + - What code gets generated (high-level, user-facing): + - `build()` performs validation and throws `ValidationException` on violations. + - `validate()` can be used to obtain a structured validation error without throwing. + - (Avoid helper-class details; keep terminology aligned with “Using the generated code”.) + - What does *not* happen: + - Validation does not parse descriptor option data at runtime to decide what to validate. + - 1–3 tiny illustrative `.proto` snippets (no deep semantics): + - Example: `(required)` on a field. + - Example: `(pattern)` on a string field. + - Example: `(min)/(max)` on a numeric field. + Each snippet should be used only to anchor the “options → generated code” explanation. + - Add “What’s next” links: + - Built-in options reference (future section 4). + - Custom validation (for defining your own options/rules). 4) Built-in options: publish a minimal reference set -- From `/Users/sanders/Projects/Spine/validation/docs/_options/options.proto` and - `/Users/sanders/Projects/Spine/validation/docs/_options/time_options.proto`, - enumerate the built-in options and group them (fields, strings, numbers, collections, message-level, time). +- From `/Users/sanders/Projects/Spine/validation/docs/_options/options.proto`, + enumerate the built-in options and group them (fields, strings, numbers, collections, message-level). - For each documented option: purpose, supported field types, common pitfalls, and a short `.proto` example. - Start with the options already used in docs/examples: `(required)`, `(pattern)`, `(min)/(max)`, - `(distinct)`, `(validate)`, `(when)`. + `(distinct)`, `(validate)`. 5) Runtime API usage (Java + Kotlin) - Document the two primary usage patterns: From a2d9d958968958eecc78cbb13ef5e29d9e63239e Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 20:51:25 +0000 Subject: [PATCH 08/43] Add landing page of the "Concepts" section --- .../docs/validation/02-concepts/_index.md | 99 ++++++++++++++++++- 1 file changed, 98 insertions(+), 1 deletion(-) diff --git a/docs/content/docs/validation/02-concepts/_index.md b/docs/content/docs/validation/02-concepts/_index.md index 86bc83dcb5..bcded79f31 100644 --- a/docs/content/docs/validation/02-concepts/_index.md +++ b/docs/content/docs/validation/02-concepts/_index.md @@ -6,4 +6,101 @@ headline: Documentation # Concepts -_Draft. We will add content later._ +This page introduces the core vocabulary and mechanics of Spine Validation. +It answers two questions: + +- **How do I express validation rules?** +- **How does the runtime report violations?** + +If you are new to the library, start with declaring constraints in `.proto` files and +then come back here for the details. + + +## Vocabulary + +Spine Validation uses a small set of concepts consistently across code generation and runtime: + +- **Constraint** — a validation rule declared in Protobuf using an option (for example, + `(required)`, `(min)`, `(max)`, `(pattern)`, `(distinct)`, `(validate)`, `(set_once)`). +- **Option application** — a concrete place where an option is applied (a field, a message, + a `oneof`, etc.). +- **Violation** — an instance of a constraint being broken. Violations are represented + as `ConstraintViolation`. +- **Validation error** — a collection of violations. Validation results are represented + as `ValidationError`. + + +## Where constraints live + +Constraints are part of the model. +You declare them next to message fields in your `.proto` files by importing +`spine/options.proto`. + +This makes validation rules: + +- versioned together with the data model, +- shared between services that reuse the same Protobuf definitions, +- enforced automatically by generated code. + + +## How validation is executed + +Validation is executed through **generated code** for your messages and builders. +The generated API exposes two main ways to validate data: + +1. **Fail-fast validation on creation.** + If a constraint is violated, `build()` throws `ValidationException`. + +2. **Validation of an existing instance.** + Generated messages implement `ValidatableMessage` and provide `validate()`, which returns + `Optional`. + +See [Using the generated code](../01-getting-started/generated-code.md) for end-to-end examples. + + +## What a violation contains + +Each `ConstraintViolation` points to the invalid value and explains what went wrong: + +- `field_path` — the path to the invalid field (for example, `contacts.email.value`). +- `type_name` — the name of the validated root message type. +- `message` — a templated, machine-friendly error message (`TemplateString`). +- `field_value` — the invalid value packed as `google.protobuf.Any`. + +When you need a human-readable message, format the `TemplateString` from the violation. +See [Using the generated code](../01-getting-started/generated-code.md) for Kotlin and Java +formatting examples. + + +## Nested validation and `(validate)` + +Protobuf messages often contain other messages. +Spine Validation supports validating nested structures and reporting correct field paths. + +When a nested message is validated as part of another message’s validation, a violation: + +- keeps the **root** type in `type_name`, and +- reports the **full path** to the invalid field in `field_path`. + +This allows you to surface errors as “`contacts.email.value` is invalid” while still knowing +which message was validated at the top level. + + +## Custom constraints + +If built-in options are not enough, you can add organization-specific options and generate +code for them. + +See [Custom validation](../08-custom-validation/) for the workflow and a reference example. + + +## What’s next + +- Declare rules in your model: + [Define constraints in `.proto` files](../01-getting-started/first-model.md). +- Learn how runtime validation behaves: + [Using the generated code](../01-getting-started/generated-code.md). +- Extend the library: + [Custom validation](../08-custom-validation/). +- Explore the implementation: + [Architecture](../09-developers-guide/architecture.md). From 13371f0b76668f033af37d40d679f8a345d1f6d3 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 21:01:26 +0000 Subject: [PATCH 09/43] Update `_examples` ref. --- docs/_examples | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/_examples b/docs/_examples index c15b15240a..4d3727541f 160000 --- a/docs/_examples +++ b/docs/_examples @@ -1 +1 @@ -Subproject commit c15b15240a2d784dae161f84d316f9cf435843fc +Subproject commit 4d3727541f0c4f771a6c1a215eef065cd3e74032 From be257f911bc5143c83594984b98c1663d6db3fa1 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 21:08:38 +0000 Subject: [PATCH 10/43] Add "Options overview" page --- .../docs/validation/02-concepts/_index.md | 4 +- .../02-concepts/options-overview.md | 110 ++++++++++++++++++ 2 files changed, 113 insertions(+), 1 deletion(-) create mode 100644 docs/content/docs/validation/02-concepts/options-overview.md diff --git a/docs/content/docs/validation/02-concepts/_index.md b/docs/content/docs/validation/02-concepts/_index.md index bcded79f31..6d1bce7133 100644 --- a/docs/content/docs/validation/02-concepts/_index.md +++ b/docs/content/docs/validation/02-concepts/_index.md @@ -100,7 +100,9 @@ See [Custom validation](../08-custom-validation/) for the workflow and a referen [Define constraints in `.proto` files](../01-getting-started/first-model.md). - Learn how runtime validation behaves: [Using the generated code](../01-getting-started/generated-code.md). -- Extend the library: +- See how options influence generated code: + [Options overview](options-overview.md). +- Add custom validation options: [Custom validation](../08-custom-validation/). - Explore the implementation: [Architecture](../09-developers-guide/architecture.md). diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md new file mode 100644 index 0000000000..a6ce5dce26 --- /dev/null +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -0,0 +1,110 @@ +--- +title: Options overview +description: Where validation options come from and how they influence generated code. +headline: Documentation +--- + +# Options overview + +Spine Validation rules are expressed as **Protobuf options**. +You annotate your `.proto` model with built-in options, and the **Validation Compiler** +turns those option values into runtime checks in the generated JVM code. + +This page explains where the built-in options come from, how they are applied at build time, +and what API you get at runtime. + + +## Where options come from + +The built-in validation options are defined in Spine option protos: + +- `spine/options.proto` — general validation options. +- `spine/time_options.proto` — time-related options. + +To use an option, import the proto that defines it and annotate your fields and messages. + +```protobuf +import "spine/options.proto"; +import "spine/time_options.proto"; +``` + +If you need a refresher on how custom options work in Protobuf, see +[Protobuf custom options](https://protobuf.dev/programming-guides/proto3/#customoptions). + + +## How options are applied (build time) + +Spine Validation is enforced by **generated code**, not by interpreting option values at runtime. + +At build time: + +1. `protoc` compiles your `.proto` files into **descriptors** and generates Java sources. +2. The Spine Validation Gradle plugin wires the **Validation Compiler** into the build. +3. The Validation Compiler reads the compiled descriptors (including your option values) and + augments `protoc` output with validation logic. + +The result is a JVM API that enforces the rules you declared in the model. + + +## What code you get (runtime) + +Generated messages and builders provide a small validation-focused API surface: + +- `build()` performs validation and throws `ValidationException` if a constraint is violated. +- `buildPartial()` builds without validation. +- `validate()` checks an existing instance and returns `Optional`. + +See [Using the generated code](../01-getting-started/generated-code.md) for Java and Kotlin examples. + + +## What does not happen + +At runtime, Spine Validation does **not** parse descriptor option data to decide what to validate. +All checks are already compiled into the generated message/builder code. + + +## Tiny examples: options → generated checks + +These examples are intentionally minimal. +They are only meant to illustrate the “annotate with options → get runtime checks” flow. + +### Required field + +```protobuf +import "spine/options.proto"; + +message UserEmail { + string value = 1 [(required) = true]; +} +``` + +### String pattern + +```protobuf +import "spine/options.proto"; + +message OrderId { + string value = 1 [(pattern).regex = "^[A-Z]{3}-\\d{6}$"]; +} +``` + +### Numeric range + +```protobuf +import "spine/options.proto"; + +message Temperature { + int32 celsius = 1 [ + (min).value = "0", + (max).value = "100" + ]; +} +``` + + +## What’s next + +- Learn how to define organization-specific rules: + [Custom validation](../08-custom-validation/). +- Built-in options reference (planned). + From a00be2e368374609aff9ef0e69dab02a1aec3c69 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 21:43:50 +0000 Subject: [PATCH 11/43] Use Kelvin for the temperature sample --- .../docs/validation/02-concepts/options-overview.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index a6ce5dce26..fe2423ee46 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -16,16 +16,12 @@ and what API you get at runtime. ## Where options come from -The built-in validation options are defined in Spine option protos: - -- `spine/options.proto` — general validation options. -- `spine/time_options.proto` — time-related options. +The built-in validation options are defined in `spine/options.proto`. To use an option, import the proto that defines it and annotate your fields and messages. ```protobuf import "spine/options.proto"; -import "spine/time_options.proto"; ``` If you need a refresher on how custom options work in Protobuf, see @@ -63,7 +59,7 @@ At runtime, Spine Validation does **not** parse descriptor option data to decide All checks are already compiled into the generated message/builder code. -## Tiny examples: options → generated checks +## Tiny examples These examples are intentionally minimal. They are only meant to illustrate the “annotate with options → get runtime checks” flow. @@ -94,9 +90,9 @@ message OrderId { import "spine/options.proto"; message Temperature { - int32 celsius = 1 [ + int32 kelvin = 1 [ (min).value = "0", - (max).value = "100" + (max).value = "10000" ]; } ``` From 22462dc5685c2e615a65edc2a8412c08ac4c9b40 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Wed, 25 Feb 2026 21:44:18 +0000 Subject: [PATCH 12/43] Reorder "What's next" items --- docs/content/docs/validation/02-concepts/options-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index fe2423ee46..5665987103 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -100,7 +100,7 @@ message Temperature { ## What’s next +- Built-in options reference (planned). - Learn how to define organization-specific rules: [Custom validation](../08-custom-validation/). -- Built-in options reference (planned). From 66c498301bc45d8fb3dee5212daa271873578b9d Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 17:49:45 +0000 Subject: [PATCH 13/43] Add details on where `options.proto` come from --- .../content/docs/validation/02-concepts/options-overview.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index 5665987103..cf560bc159 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -8,7 +8,7 @@ headline: Documentation Spine Validation rules are expressed as **Protobuf options**. You annotate your `.proto` model with built-in options, and the **Validation Compiler** -turns those option values into runtime checks in the generated JVM code. +turns those option values into runtime checks in the generated Java code. This page explains where the built-in options come from, how they are applied at build time, and what API you get at runtime. @@ -18,6 +18,10 @@ and what API you get at runtime. The built-in validation options are defined in `spine/options.proto`. +The file comes in the `spine-base.jar` artifact, which is an API dependency +of the Validation runtime library (`spine-validation-java-runtime.jar`) added +to your project by the Validation Gradle plugin. + To use an option, import the proto that defines it and annotate your fields and messages. ```protobuf From 6bd8f9b2b263f1ac1eca6c45093c93db4aadaa3c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 18:01:44 +0000 Subject: [PATCH 14/43] Refer to generated validation as Java API --- .agents/tasks/validation-documentation-plan.md | 2 +- docs/content/docs/validation/02-concepts/options-overview.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index 1a31f06adb..ef7000db82 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -64,7 +64,7 @@ buildable documentation set, without expanding scope unnecessarily. - Runtime: there is no descriptor parsing; validation runs as regular code in `build()` / `validate()`. - Add a small pipeline diagram (Mermaid) showing: `.proto` + `spine/options.proto` import → `protoc` (Java) → Validation Compiler (via Gradle plugin) - → generated JVM API (`build()`, `validate()`). + → generated Java API (`build()`, `validate()`). - Define (briefly) what Protobuf custom options are with a one-sentence refresher, then link to Protobuf docs for details. - Clarify “what you write” vs “what you get”: diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index cf560bc159..601621ebd5 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -43,7 +43,7 @@ At build time: 3. The Validation Compiler reads the compiled descriptors (including your option values) and augments `protoc` output with validation logic. -The result is a JVM API that enforces the rules you declared in the model. +The result is a Java API that enforces the rules you declared in the model. ## What code you get (runtime) From 3418afeb85cda32e750748337ddb5e484fc9ded7 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 18:47:29 +0000 Subject: [PATCH 15/43] Add "Options overview" to side navigation --- docs/data/docs/validation/2-0-0-snapshot/sidenav.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml b/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml index c1058569cb..9c795e1e90 100644 --- a/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml +++ b/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml @@ -31,6 +31,8 @@ children: - page: Concepts file_path: 02-concepts + - page: Options overview + file_path: 02-concepts/options-overview - page: Custom validation file_path: 08-custom-validation - page: Developer’s guide From 8d046d94da4489864c21fe5b953e1817fe981c40 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 18:48:02 +0000 Subject: [PATCH 16/43] Add Mermaid diagram to illustrate compilation process --- .../docs/validation/02-concepts/options-overview.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index 601621ebd5..ff2d9303b7 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -45,6 +45,13 @@ At build time: The result is a Java API that enforces the rules you declared in the model. +```mermaid +flowchart LR + A[".proto
+
spine/options.proto
"] --> B["protoc
(Java)"] + B --> C["Validation Compiler
via Gradle plugin"] + C --> D["Generated Java API + build(), validate()"] +``` ## What code you get (runtime) From ca64a310bcfae9108a5040053c7f104489161cb2 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 19:09:21 +0000 Subject: [PATCH 17/43] Extract `concepts-plan.md` into `archive/` --- .agents/tasks/archive/concepts-plan.md | 57 ++++++++++++++++++ .../tasks/validation-documentation-plan.md | 59 +------------------ 2 files changed, 59 insertions(+), 57 deletions(-) create mode 100644 .agents/tasks/archive/concepts-plan.md diff --git a/.agents/tasks/archive/concepts-plan.md b/.agents/tasks/archive/concepts-plan.md new file mode 100644 index 0000000000..c4a9276856 --- /dev/null +++ b/.agents/tasks/archive/concepts-plan.md @@ -0,0 +1,57 @@ +**Goal**: explain how Validation works (one layer deeper than “getting started”) +- Add a Concepts landing page and an “options overview” page that explains: + where options come from, how they’re applied, and what code gets generated. +- Keep this conceptual (no option-by-option details yet). +- Target outcome: a reader can explain that Validation is enforced by generated code + (not by parsing descriptor/options at runtime) and that the Gradle plugin wires the + Validation Compiler into the build to augment `protoc` output. +- Terminology: use “Validation Compiler” consistently (it is a plugin to the Spine Compiler). +- Pages to create/update: + - Concepts landing: `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/02-concepts/_index.md` + - Options overview: `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/02-concepts/options-overview.md` +- Concepts landing page: planned content (conceptual, 1 screen deeper than “Getting started”) + - Open with a 2–3 sentence “mental model”: + - Constraints are declared in `.proto` files using built-in options imported from `spine/options.proto`. + - The Validation Compiler updates Java sources generated by `protoc` so runtime checks happen in code. + - Explain the “build-time vs runtime” boundary: + - Build-time: options are read from descriptors and used to generate/inject checks into message code. + - Runtime: there is no descriptor parsing; validation runs as regular code in `build()` / `validate()`. + - Add a small pipeline diagram (Mermaid) showing: + `.proto` + `spine/options.proto` import → `protoc` (Java) → Validation Compiler (via Gradle plugin) + → generated Java API (`build()`, `validate()`). + - Define (briefly) what Protobuf custom options are with a one-sentence refresher, + then link to Protobuf docs for details. + - Clarify “what you write” vs “what you get”: + - You write: option annotations on fields/messages. + - You get: runtime enforcement through `build()` throwing `ValidationException` and + `validate()` returning an error object (as introduced in “Getting started”). + - Mention extensibility without diving in: + - Note that custom validation options + codegen are possible; link forward to + `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/08-custom-validation/_index.md`. + - Close with “What’s next” links: + - Options overview page. + - Custom validation (for organization-specific rules). + - Developers guide (architecture/key modules) for internals. +- Options overview page: planned content (concrete examples, but not an option catalog) + - Purpose statement: explain where built-in options come from and how they influence generated code. + - Where options come from (built-ins only): + - Options are defined in `spine/options.proto` (and related Spine option protos). + - Users import the option proto(s) and annotate their own message/field definitions. + - One-sentence refresher on Protobuf options + a link to Protobuf docs about custom options. + - How options are applied at build time: + - The Gradle plugin integrates Validation into the build. + - Validation Compiler uses the compiled descriptors (including option values) to augment `protoc` output. + - What code gets generated (high-level, user-facing): + - `build()` performs validation and throws `ValidationException` on violations. + - `validate()` can be used to obtain a structured validation error without throwing. + - (Avoid helper-class details; keep terminology aligned with “Using the generated code”.) + - What does *not* happen: + - Validation does not parse descriptor option data at runtime to decide what to validate. + - 1–3 tiny illustrative `.proto` snippets (no deep semantics): + - Example: `(required)` on a field. + - Example: `(pattern)` on a string field. + - Example: `(min)/(max)` on a numeric field. + Each snippet should be used only to anchor the “options → generated code” explanation. + - Add “What’s next” links: + - Built-in options reference (future section 4). + - Custom validation (for defining your own options/rules). diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index ef7000db82..9d22610106 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -44,63 +44,8 @@ buildable documentation set, without expanding scope unnecessarily. - Validate that the "Getting started" section covers: importing options, build-time validation, `build()` vs `buildPartial()`, and `validate()`. -3) Concepts: explain how Validation works (one layer deeper than “getting started”) -- Add a Concepts landing page and an “options overview” page that explains: - where options come from, how they’re applied, and what code gets generated. -- Keep this conceptual (no option-by-option details yet). -- Target outcome: a reader can explain that Validation is enforced by generated code - (not by parsing descriptor/options at runtime) and that the Gradle plugin wires the - Validation Compiler into the build to augment `protoc` output. -- Terminology: use “Validation Compiler” consistently (it is a plugin to the Spine Compiler). -- Pages to create/update: - - Concepts landing: `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/02-concepts/_index.md` - - Options overview: `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/02-concepts/options-overview.md` -- Concepts landing page: planned content (conceptual, 1 screen deeper than “Getting started”) - - Open with a 2–3 sentence “mental model”: - - Constraints are declared in `.proto` files using built-in options imported from `spine/options.proto`. - - The Validation Compiler updates Java sources generated by `protoc` so runtime checks happen in code. - - Explain the “build-time vs runtime” boundary: - - Build-time: options are read from descriptors and used to generate/inject checks into message code. - - Runtime: there is no descriptor parsing; validation runs as regular code in `build()` / `validate()`. - - Add a small pipeline diagram (Mermaid) showing: - `.proto` + `spine/options.proto` import → `protoc` (Java) → Validation Compiler (via Gradle plugin) - → generated Java API (`build()`, `validate()`). - - Define (briefly) what Protobuf custom options are with a one-sentence refresher, - then link to Protobuf docs for details. - - Clarify “what you write” vs “what you get”: - - You write: option annotations on fields/messages. - - You get: runtime enforcement through `build()` throwing `ValidationException` and - `validate()` returning an error object (as introduced in “Getting started”). - - Mention extensibility without diving in: - - Note that custom validation options + codegen are possible; link forward to - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/08-custom-validation/_index.md`. - - Close with “What’s next” links: - - Options overview page. - - Custom validation (for organization-specific rules). - - Developers guide (architecture/key modules) for internals. -- Options overview page: planned content (concrete examples, but not an option catalog) - - Purpose statement: explain where built-in options come from and how they influence generated code. - - Where options come from (built-ins only): - - Options are defined in `spine/options.proto` (and related Spine option protos). - - Users import the option proto(s) and annotate their own message/field definitions. - - One-sentence refresher on Protobuf options + a link to Protobuf docs about custom options. - - How options are applied at build time: - - The Gradle plugin integrates Validation into the build. - - Validation Compiler uses the compiled descriptors (including option values) to augment `protoc` output. - - What code gets generated (high-level, user-facing): - - `build()` performs validation and throws `ValidationException` on violations. - - `validate()` can be used to obtain a structured validation error without throwing. - - (Avoid helper-class details; keep terminology aligned with “Using the generated code”.) - - What does *not* happen: - - Validation does not parse descriptor option data at runtime to decide what to validate. - - 1–3 tiny illustrative `.proto` snippets (no deep semantics): - - Example: `(required)` on a field. - - Example: `(pattern)` on a string field. - - Example: `(min)/(max)` on a numeric field. - Each snippet should be used only to anchor the “options → generated code” explanation. - - Add “What’s next” links: - - Built-in options reference (future section 4). - - Custom validation (for defining your own options/rules). +3) [Concepts](archive/concepts-plan.md) +- Status: DONE (2026-02-26). 4) Built-in options: publish a minimal reference set - From `/Users/sanders/Projects/Spine/validation/docs/_options/options.proto`, From b57f2d65af0a9d9af7a74dabd0c0d8a114dcd3e0 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 19:51:06 +0000 Subject: [PATCH 18/43] Add "Working with error messages" plan item --- .../tasks/validation-documentation-plan.md | 24 ++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index 9d22610106..9068d9c94b 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -47,14 +47,32 @@ buildable documentation set, without expanding scope unnecessarily. 3) [Concepts](archive/concepts-plan.md) - Status: DONE (2026-02-26). -4) Built-in options: publish a minimal reference set +4) Working with error messages +- Describe how `TemplateString` works (placeholders + values) and how to convert it to a + human-readable message (formatting). +- Clarify the recommended ways to work with Validation errors in: + - Kotlin: `TemplateString.format()` / `TemplateString.formatUnsafe()`. + - Java: `io.spine.validation.TemplateStrings.format(TemplateString)`. +- Explain the structure of `ValidationError` / `ConstraintViolation`, and what fields developers + should use when: + - displaying messages to end users; + - logging diagnostics (e.g. include `type_name`, `field_path`, and the unformatted template). +- Add troubleshooting notes for common runtime formatting problems (e.g. missing placeholder + values; choosing `formatUnsafe()` when partial substitution is acceptable). +- Source references to anchor the docs: + - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/proto/spine/validation/error_message.proto` + - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/proto/spine/validation/validation_error.proto` + - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/kotlin/io/spine/validation/TemplateStringExts.kt` + - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/kotlin/io/spine/validation/RuntimeErrorPlaceholder.kt` + +5) Built-in options: publish a minimal reference set - From `/Users/sanders/Projects/Spine/validation/docs/_options/options.proto`, enumerate the built-in options and group them (fields, strings, numbers, collections, message-level). - For each documented option: purpose, supported field types, common pitfalls, and a short `.proto` example. - Start with the options already used in docs/examples: `(required)`, `(pattern)`, `(min)/(max)`, `(distinct)`, `(validate)`. -5) Runtime API usage (Java + Kotlin) +6) Runtime API usage (Java + Kotlin) - Document the two primary usage patterns: - fail-fast on `build()` (throws `ValidationException`); - non-throwing `validate()` (returns `Optional`). @@ -65,7 +83,7 @@ buildable documentation set, without expanding scope unnecessarily. `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/java/io/spine/validation/ValidationException.java`, `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/kotlin/io/spine/validation/MessageExtensions.kt`. -6) Verification pass (keep it tight; fix only doc-related issues) +7) Verification pass (keep it tight; fix only doc-related issues) - From `/Users/sanders/Projects/Spine/validation/docs/`, run: - `./gradlew embedCode` - `./gradlew checkSamples` From de5aa3755e90a7d52db8a086cfb4117050d1c9e7 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 20:01:31 +0000 Subject: [PATCH 19/43] Avoid workstation-specific paths --- .agents/tasks/archive/concepts-plan.md | 6 +-- .../tasks/validation-documentation-plan.md | 51 +++++++++---------- 2 files changed, 28 insertions(+), 29 deletions(-) diff --git a/.agents/tasks/archive/concepts-plan.md b/.agents/tasks/archive/concepts-plan.md index c4a9276856..2185a4137c 100644 --- a/.agents/tasks/archive/concepts-plan.md +++ b/.agents/tasks/archive/concepts-plan.md @@ -7,8 +7,8 @@ Validation Compiler into the build to augment `protoc` output. - Terminology: use “Validation Compiler” consistently (it is a plugin to the Spine Compiler). - Pages to create/update: - - Concepts landing: `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/02-concepts/_index.md` - - Options overview: `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/02-concepts/options-overview.md` + - Concepts landing: `docs/content/docs/validation/02-concepts/_index.md` + - Options overview: `docs/content/docs/validation/02-concepts/options-overview.md` - Concepts landing page: planned content (conceptual, 1 screen deeper than “Getting started”) - Open with a 2–3 sentence “mental model”: - Constraints are declared in `.proto` files using built-in options imported from `spine/options.proto`. @@ -27,7 +27,7 @@ `validate()` returning an error object (as introduced in “Getting started”). - Mention extensibility without diving in: - Note that custom validation options + codegen are possible; link forward to - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/08-custom-validation/_index.md`. + `docs/content/docs/validation/08-custom-validation/_index.md`. - Close with “What’s next” links: - Options overview page. - Custom validation (for organization-specific rules). diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index 9068d9c94b..59a01246c9 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -6,12 +6,11 @@ buildable documentation set, without expanding scope unnecessarily. ## Key locations (source of truth) -- Docs content (Hugo): `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/` +- Docs content (Hugo): `docs/content/docs/validation/` - Protobuf options reference (for built-ins): - - `/Users/sanders/Projects/Spine/validation/docs/_options/options.proto` - - `/Users/sanders/Projects/Spine/validation/docs/_options/time_options.proto` -- Example projects for embedded snippets: `/Users/sanders/Projects/Spine/validation/docs/_examples/` -- Docs build notes: `/Users/sanders/Projects/Spine/validation/docs/GRADLE.md` + - `docs/_options/options.proto` +- Example projects for embedded snippets: `docs/_examples/` +- Docs build notes: `docs/GRADLE.md` ## Definition of done (for a “first complete docs cut”) @@ -25,19 +24,19 @@ buildable documentation set, without expanding scope unnecessarily. 1) Information architecture (IA): make Hugo navigation coherent - Status: DONE (2026-02-23). - Added/updated section landing pages: - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/_index.md` - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/09-developers-guide/_index.md` + - `docs/content/docs/validation/_index.md` + - `docs/content/docs/validation/09-developers-guide/_index.md` - Replaced broken `.../index.md` links with directory links where appropriate: - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/00-intro/_index.md` - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/01-getting-started/_index.md` + - `docs/content/docs/validation/00-intro/_index.md` + - `docs/content/docs/validation/01-getting-started/_index.md` - Added “What’s next” navigation to keep a clear reading path: - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/00-intro/target-audience.md` - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/00-intro/philosophy.md` - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/09-developers-guide/architecture.md` - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/09-developers-guide/key-modules.md` - - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/01-getting-started/first-model.md` + - `docs/content/docs/validation/00-intro/target-audience.md` + - `docs/content/docs/validation/00-intro/philosophy.md` + - `docs/content/docs/validation/09-developers-guide/architecture.md` + - `docs/content/docs/validation/09-developers-guide/key-modules.md` + - `docs/content/docs/validation/01-getting-started/first-model.md` - Fixed an obvious broken image reference: - `/Users/sanders/Projects/Spine/validation/docs/content/docs/validation/08-custom-validation/_index.md` + `docs/content/docs/validation/08-custom-validation/_index.md` 2) Complete “Getting started” flow - Status: DONE (2026-02-24). @@ -60,13 +59,13 @@ buildable documentation set, without expanding scope unnecessarily. - Add troubleshooting notes for common runtime formatting problems (e.g. missing placeholder values; choosing `formatUnsafe()` when partial substitution is acceptable). - Source references to anchor the docs: - - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/proto/spine/validation/error_message.proto` - - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/proto/spine/validation/validation_error.proto` - - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/kotlin/io/spine/validation/TemplateStringExts.kt` - - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/kotlin/io/spine/validation/RuntimeErrorPlaceholder.kt` + - `jvm-runtime/src/main/proto/spine/validation/error_message.proto` + - `jvm-runtime/src/main/proto/spine/validation/validation_error.proto` + - `jvm-runtime/src/main/kotlin/io/spine/validation/TemplateStringExts.kt` + - `jvm-runtime/src/main/kotlin/io/spine/validation/RuntimeErrorPlaceholder.kt` 5) Built-in options: publish a minimal reference set -- From `/Users/sanders/Projects/Spine/validation/docs/_options/options.proto`, +- From `docs/_options/options.proto`, enumerate the built-in options and group them (fields, strings, numbers, collections, message-level). - For each documented option: purpose, supported field types, common pitfalls, and a short `.proto` example. - Start with the options already used in docs/examples: `(required)`, `(pattern)`, `(min)/(max)`, @@ -77,14 +76,14 @@ buildable documentation set, without expanding scope unnecessarily. - fail-fast on `build()` (throws `ValidationException`); - non-throwing `validate()` (returns `Optional`). - Link to the runtime entry points used by generated code: - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/java/io/spine/validation/ValidatableMessage.java`, - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/java/io/spine/validation/ValidatingBuilder.java`, - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/java/io/spine/validation/Validate.java`, - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/java/io/spine/validation/ValidationException.java`, - `/Users/sanders/Projects/Spine/validation/jvm-runtime/src/main/kotlin/io/spine/validation/MessageExtensions.kt`. + `jvm-runtime/src/main/java/io/spine/validation/ValidatableMessage.java`, + `jvm-runtime/src/main/java/io/spine/validation/ValidatingBuilder.java`, + `jvm-runtime/src/main/java/io/spine/validation/Validate.java`, + `jvm-runtime/src/main/java/io/spine/validation/ValidationException.java`, + `jvm-runtime/src/main/kotlin/io/spine/validation/MessageExtensions.kt`. 7) Verification pass (keep it tight; fix only doc-related issues) -- From `/Users/sanders/Projects/Spine/validation/docs/`, run: +- From `docs/`, run: - `./gradlew embedCode` - `./gradlew checkSamples` - `./gradlew buildSite` From 291c3a1f9642fe525e09d0081d15637b5974001d Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 20:20:26 +0000 Subject: [PATCH 20/43] Add task for describing working with error messages --- .../tasks/validation-documentation-plan.md | 18 +---------- .agents/tasks/working-with-error-messages.md | 30 +++++++++++++++++++ 2 files changed, 31 insertions(+), 17 deletions(-) create mode 100644 .agents/tasks/working-with-error-messages.md diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index 59a01246c9..ad30f9bf34 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -46,23 +46,7 @@ buildable documentation set, without expanding scope unnecessarily. 3) [Concepts](archive/concepts-plan.md) - Status: DONE (2026-02-26). -4) Working with error messages -- Describe how `TemplateString` works (placeholders + values) and how to convert it to a - human-readable message (formatting). -- Clarify the recommended ways to work with Validation errors in: - - Kotlin: `TemplateString.format()` / `TemplateString.formatUnsafe()`. - - Java: `io.spine.validation.TemplateStrings.format(TemplateString)`. -- Explain the structure of `ValidationError` / `ConstraintViolation`, and what fields developers - should use when: - - displaying messages to end users; - - logging diagnostics (e.g. include `type_name`, `field_path`, and the unformatted template). -- Add troubleshooting notes for common runtime formatting problems (e.g. missing placeholder - values; choosing `formatUnsafe()` when partial substitution is acceptable). -- Source references to anchor the docs: - - `jvm-runtime/src/main/proto/spine/validation/error_message.proto` - - `jvm-runtime/src/main/proto/spine/validation/validation_error.proto` - - `jvm-runtime/src/main/kotlin/io/spine/validation/TemplateStringExts.kt` - - `jvm-runtime/src/main/kotlin/io/spine/validation/RuntimeErrorPlaceholder.kt` +4) [Working with error messages](working-with-error-messages.md) 5) Built-in options: publish a minimal reference set - From `docs/_options/options.proto`, diff --git a/.agents/tasks/working-with-error-messages.md b/.agents/tasks/working-with-error-messages.md new file mode 100644 index 0000000000..0cc557dbc5 --- /dev/null +++ b/.agents/tasks/working-with-error-messages.md @@ -0,0 +1,30 @@ +# Task: Write documentation on working with validation error messages +- Placement of the page: Under the Concepts section after the “Options overview” page. +- Purpose: explain how validation error messages work, how to customize them, and how to use them in code. +- Target outcome: a reader can explain the relationship between validation options and error messages, +- how to define custom messages, and how to format them for end users or diagnostics. +- Terminology: `TemplateString`, `ValidationError`, `ConstraintViolation`, `format()`, `formatUnsafe()` +- Describe that validation options have default error messages and user-defined error messages + (via `(error_msg)` property of an option). +- Give an example of a custom validation error message with placeholders + defined in a proto field option. Use `spine/options.proto` as a reference for + the option definition and the `error_msg` field. +- Explain the noption of placeholders in error messages and how they correspond to + values provided at runtime when a violation occurs. +- Describe how `TemplateString` works (placeholders + values) and how to convert it to a + human-readable message (formatting). +- Clarify the recommended ways to work with Validation errors in: + - Kotlin: `TemplateString.format()` / `TemplateString.formatUnsafe()`. + - Java: `io.spine.validation.TemplateStrings.format(TemplateString)` + - Java: `io.spine.validation.TemplateStrings.formatUnsafe(TemplateString)`. +- Explain the structure of `ValidationError` / `ConstraintViolation`, and what fields developers + should use when: + - displaying messages to end users; + - logging diagnostics (e.g. include `type_name`, `field_path`, and the unformatted template). +- Add troubleshooting notes for common runtime formatting problems (e.g. missing placeholder + values; choosing `formatUnsafe()` when partial substitution is acceptable). +- Source references to anchor the docs: + - `jvm-runtime/src/main/proto/spine/validation/error_message.proto` + - `jvm-runtime/src/main/proto/spine/validation/validation_error.proto` + - `jvm-runtime/src/main/kotlin/io/spine/validation/TemplateStringExts.kt` + - `jvm-runtime/src/main/kotlin/io/spine/validation/RuntimeErrorPlaceholder.kt` From 7513b15abdd98e4b0e400c5868e5fa752cf2012c Mon Sep 17 00:00:00 2001 From: "julia.evseeva" Date: Thu, 26 Feb 2026 21:21:13 +0100 Subject: [PATCH 21/43] Get theme updates with the Mermaid diagram support --- docs/_preview/go.mod | 2 +- docs/_preview/go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/_preview/go.mod b/docs/_preview/go.mod index 3e6bbced4d..3d83edfef3 100644 --- a/docs/_preview/go.mod +++ b/docs/_preview/go.mod @@ -3,7 +3,7 @@ module spine.io/validation/docs/preview go 1.25.6 require ( - github.com/SpineEventEngine/site-commons v0.0.0-20260225175457-ace8e24c3a0f // indirect + github.com/SpineEventEngine/site-commons v0.0.0-20260226201948-3aec673b8046 // indirect github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20400 // indirect github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2 v2.21100.20000 // indirect github.com/twbs/bootstrap v5.3.8+incompatible // indirect diff --git a/docs/_preview/go.sum b/docs/_preview/go.sum index 555f61d068..f70140dc27 100644 --- a/docs/_preview/go.sum +++ b/docs/_preview/go.sum @@ -1,5 +1,5 @@ -github.com/SpineEventEngine/site-commons v0.0.0-20260225175457-ace8e24c3a0f h1:b8GVB6Kydf+FYlHQ/05qistXQWA1mFzt6SpG6Pw7mfY= -github.com/SpineEventEngine/site-commons v0.0.0-20260225175457-ace8e24c3a0f/go.mod h1:tkAl4StIREKmz9r5PiJtuDhvwMMkFXKWcaTyxhIikho= +github.com/SpineEventEngine/site-commons v0.0.0-20260226201948-3aec673b8046 h1:qx3XD7j5i3xhtDu/iRLdqwT16BxHg+9Z7wtXae1VWRU= +github.com/SpineEventEngine/site-commons v0.0.0-20260226201948-3aec673b8046/go.mod h1:tkAl4StIREKmz9r5PiJtuDhvwMMkFXKWcaTyxhIikho= github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20400 h1:L6+F22i76xmeWWwrtijAhUbf3BiRLmpO5j34bgl1ggU= github.com/gohugoio/hugo-mod-bootstrap-scss/v5 v5.20300.20400/go.mod h1:uekq1D4ebeXgduLj8VIZy8TgfTjrLdSl6nPtVczso78= github.com/gohugoio/hugo-mod-jslibs-dist/popperjs/v2 v2.21100.20000 h1:GZxx4Hc+yb0/t3/rau1j8XlAxLE4CyXns2fqQbyqWfs= From 03a058d475a35ae763b8171ab2dc5fd7811a051f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 21:11:32 +0000 Subject: [PATCH 22/43] Add "Working with error messages" section --- .agents/tasks/working-with-error-messages.md | 8 +- .../01-getting-started/adding-to-build.md | 2 +- .../docs/validation/02-concepts/_index.md | 6 +- .../working-with-error-messages.md | 109 ++++++++++++++++++ 4 files changed, 120 insertions(+), 5 deletions(-) create mode 100644 docs/content/docs/validation/02-concepts/working-with-error-messages.md diff --git a/.agents/tasks/working-with-error-messages.md b/.agents/tasks/working-with-error-messages.md index 0cc557dbc5..06ac297228 100644 --- a/.agents/tasks/working-with-error-messages.md +++ b/.agents/tasks/working-with-error-messages.md @@ -5,11 +5,11 @@ - how to define custom messages, and how to format them for end users or diagnostics. - Terminology: `TemplateString`, `ValidationError`, `ConstraintViolation`, `format()`, `formatUnsafe()` - Describe that validation options have default error messages and user-defined error messages - (via `(error_msg)` property of an option). + (via the `error_msg` field of a validation option, such as `(pattern).error_msg`). - Give an example of a custom validation error message with placeholders defined in a proto field option. Use `spine/options.proto` as a reference for the option definition and the `error_msg` field. -- Explain the noption of placeholders in error messages and how they correspond to +- Explain the notion of placeholders in error messages and how they correspond to values provided at runtime when a violation occurs. - Describe how `TemplateString` works (placeholders + values) and how to convert it to a human-readable message (formatting). @@ -28,3 +28,7 @@ - `jvm-runtime/src/main/proto/spine/validation/validation_error.proto` - `jvm-runtime/src/main/kotlin/io/spine/validation/TemplateStringExts.kt` - `jvm-runtime/src/main/kotlin/io/spine/validation/RuntimeErrorPlaceholder.kt` + +## Output + +Implemented as `docs/content/docs/validation/02-concepts/working-with-error-messages.md`. diff --git a/docs/content/docs/validation/01-getting-started/adding-to-build.md b/docs/content/docs/validation/01-getting-started/adding-to-build.md index 74495d484a..8a3026ca63 100644 --- a/docs/content/docs/validation/01-getting-started/adding-to-build.md +++ b/docs/content/docs/validation/01-getting-started/adding-to-build.md @@ -82,7 +82,7 @@ Add the Validation plugin to the build. ```kotlin plugins { module - id("io.spine.validation") version "2.0.0-SNAPSHOT.398" + id("io.spine.validation") version "2.0.0-SNAPSHOT.399" } ``` diff --git a/docs/content/docs/validation/02-concepts/_index.md b/docs/content/docs/validation/02-concepts/_index.md index 6d1bce7133..26b258d446 100644 --- a/docs/content/docs/validation/02-concepts/_index.md +++ b/docs/content/docs/validation/02-concepts/_index.md @@ -68,8 +68,8 @@ Each `ConstraintViolation` points to the invalid value and explains what went wr - `field_value` — the invalid value packed as `google.protobuf.Any`. When you need a human-readable message, format the `TemplateString` from the violation. -See [Using the generated code](../01-getting-started/generated-code.md) for Kotlin and Java -formatting examples. +See [Working with error messages](working-with-error-messages.md) for message formatting, +placeholders, and customization. ## Nested validation and `(validate)` @@ -102,6 +102,8 @@ See [Custom validation](../08-custom-validation/) for the workflow and a referen [Using the generated code](../01-getting-started/generated-code.md). - See how options influence generated code: [Options overview](options-overview.md). +- Customize and format messages: + [Working with error messages](working-with-error-messages.md). - Add custom validation options: [Custom validation](../08-custom-validation/). - Explore the implementation: diff --git a/docs/content/docs/validation/02-concepts/working-with-error-messages.md b/docs/content/docs/validation/02-concepts/working-with-error-messages.md new file mode 100644 index 0000000000..33e1f3d367 --- /dev/null +++ b/docs/content/docs/validation/02-concepts/working-with-error-messages.md @@ -0,0 +1,109 @@ +--- +title: Working with error messages +description: How validation error messages are built, customized, and formatted. +headline: Documentation +--- + +# Working with error messages + +When a message violates validation constraints, Spine Validation reports violations as +`ConstraintViolation` entries inside a `ValidationError`. + +Each violation contains a machine-friendly error message (`TemplateString`) which you can: + +- format for end users, +- log for diagnostics, and +- customize in your `.proto` model. + + +## Where error messages come from + +Every built-in validation option defines a **default** error message. +For example, the `(pattern)` option declares its default message in `spine/options.proto`. + +When you apply an option in a `.proto` file, you can **override** the default message by +setting the option’s `error_msg` field. + +Example: custom message for a regex pattern. + +```protobuf +import "spine/options.proto"; + +message CreateAccount { + string id = 1 [ + (pattern).regex = "^[A-Za-z0-9+]+$", + (pattern).error_msg = "ID must be alphanumerical in `${parent.type}`. Provided: `${field.value}`." + ]; +} +``` + +The placeholders (like `${field.value}`) are substituted at runtime when the violation is created. +Each option documents the placeholders it supports next to its `error_msg` field in `spine/options.proto`. + + +## Placeholders and `TemplateString` + +`ConstraintViolation.message` is a `TemplateString`: + +- `with_placeholders` — a template string that may contain placeholders like `${field.path}`. +- `placeholder_value` — a map from placeholder keys to their runtime values. + +The placeholder keys in the map do **not** include `${}` — for example, `field.path`. + +The map may include extra keys that are not referenced by the template, but every placeholder +used in `with_placeholders` must have a corresponding value (otherwise, the template is invalid). + + +## Formatting messages in code + +To format a `TemplateString`, use: + +- Kotlin: `TemplateString.format()` / `TemplateString.formatUnsafe()` +- Java: `TemplateStrings.format(TemplateString)` / `TemplateStrings.formatUnsafe(TemplateString)` + +`format()` validates that all placeholders have values and throws `IllegalArgumentException` otherwise. +`formatUnsafe()` does not validate and leaves missing placeholders unsubstituted. + +Example (Kotlin): + +```kotlin +val error = message.validate().orElse(null) ?: return +val violation = error.constraintViolationList.first() +val text = violation.message.format() +``` + +Example (Java): + +```java +var error = message.validate(); +if (error.isEmpty()) { + return; +} +var violation = error.get().getConstraintViolation(0); +var text = TemplateStrings.format(violation.getMessage()); +``` + + +## Choosing what to show vs what to log + +For **end-user** output: + +- format and display `ConstraintViolation.message`; +- avoid leaking internal type names unless your product requires them. + +For **diagnostics** and support logs: + +- include `type_name` and `field_path` to pinpoint the location of the violation; +- include the raw template (`message.with_placeholders`) and the placeholder map for debugging. + + +## Troubleshooting formatting issues + +### `IllegalArgumentException` from `format()` + +This means `with_placeholders` references a placeholder that has no entry in `placeholder_value`. + +Recommended actions: + +- treat this as a bug in the option/message definition, and fix the custom `error_msg` in your `.proto`; +- if you can tolerate partial substitution (for example, in logs), use `formatUnsafe()`. From e4880ff16b7bfbda68994916a27d0aa5b463d38a Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 21:14:24 +0000 Subject: [PATCH 23/43] Add "Working with error messages" to sidebar Also: * Improve the file name. --- .agents/tasks/working-with-error-messages.md | 2 +- .../{working-with-error-messages.md => error-messages.md} | 0 docs/data/docs/validation/2-0-0-snapshot/sidenav.yml | 2 ++ 3 files changed, 3 insertions(+), 1 deletion(-) rename docs/content/docs/validation/02-concepts/{working-with-error-messages.md => error-messages.md} (100%) diff --git a/.agents/tasks/working-with-error-messages.md b/.agents/tasks/working-with-error-messages.md index 06ac297228..78921306b9 100644 --- a/.agents/tasks/working-with-error-messages.md +++ b/.agents/tasks/working-with-error-messages.md @@ -31,4 +31,4 @@ ## Output -Implemented as `docs/content/docs/validation/02-concepts/working-with-error-messages.md`. +Implemented as `docs/content/docs/validation/02-concepts/error-messages.md`. diff --git a/docs/content/docs/validation/02-concepts/working-with-error-messages.md b/docs/content/docs/validation/02-concepts/error-messages.md similarity index 100% rename from docs/content/docs/validation/02-concepts/working-with-error-messages.md rename to docs/content/docs/validation/02-concepts/error-messages.md diff --git a/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml b/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml index 9c795e1e90..fe3e414279 100644 --- a/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml +++ b/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml @@ -33,6 +33,8 @@ file_path: 02-concepts - page: Options overview file_path: 02-concepts/options-overview + - page: Working with error messages + file_path: 02-concepts/error-messages - page: Custom validation file_path: 08-custom-validation - page: Developer’s guide From 33ac2de37418509b12220010c43a47d007a9ebaa Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 21:19:20 +0000 Subject: [PATCH 24/43] Add tabs for Kotlin/Java examples --- .../writer/assets/templates/kotlin-java-example.md | 13 +++++++++++++ .../docs/validation/02-concepts/error-messages.md | 9 ++++++--- 2 files changed, 19 insertions(+), 3 deletions(-) create mode 100644 .agents/skills/writer/assets/templates/kotlin-java-example.md diff --git a/.agents/skills/writer/assets/templates/kotlin-java-example.md b/.agents/skills/writer/assets/templates/kotlin-java-example.md new file mode 100644 index 0000000000..5517516f56 --- /dev/null +++ b/.agents/skills/writer/assets/templates/kotlin-java-example.md @@ -0,0 +1,13 @@ +{{< code-tabs langs="Kotlin, Java">}} + +{{< code-tab lang="Kotlin" >}} +```kotlin +``` +{{< /code-tab >}} + +{{< code-tab lang="Java" >}} +```java +``` +{{< /code-tab >}} + +{{< /code-tabs >}} diff --git a/docs/content/docs/validation/02-concepts/error-messages.md b/docs/content/docs/validation/02-concepts/error-messages.md index 33e1f3d367..7cde7dde18 100644 --- a/docs/content/docs/validation/02-concepts/error-messages.md +++ b/docs/content/docs/validation/02-concepts/error-messages.md @@ -64,16 +64,17 @@ To format a `TemplateString`, use: `format()` validates that all placeholders have values and throws `IllegalArgumentException` otherwise. `formatUnsafe()` does not validate and leaves missing placeholders unsubstituted. -Example (Kotlin): +{{< code-tabs langs="Kotlin, Java">}} +{{< code-tab lang="Kotlin" >}} ```kotlin val error = message.validate().orElse(null) ?: return val violation = error.constraintViolationList.first() val text = violation.message.format() ``` +{{< /code-tab >}} -Example (Java): - +{{< code-tab lang="Java" >}} ```java var error = message.validate(); if (error.isEmpty()) { @@ -82,7 +83,9 @@ if (error.isEmpty()) { var violation = error.get().getConstraintViolation(0); var text = TemplateStrings.format(violation.getMessage()); ``` +{{< /code-tab >}} +{{< /code-tabs >}} ## Choosing what to show vs what to log From 5e4b2cf1c033ccea4496e96924c30b689b61c8d1 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 21:42:30 +0000 Subject: [PATCH 25/43] Add example of a default error message --- .../validation/02-concepts/error-messages.md | 35 ++++++++++++++----- 1 file changed, 27 insertions(+), 8 deletions(-) diff --git a/docs/content/docs/validation/02-concepts/error-messages.md b/docs/content/docs/validation/02-concepts/error-messages.md index 7cde7dde18..b6114f2778 100644 --- a/docs/content/docs/validation/02-concepts/error-messages.md +++ b/docs/content/docs/validation/02-concepts/error-messages.md @@ -19,7 +19,21 @@ Each violation contains a machine-friendly error message (`TemplateString`) whic ## Where error messages come from Every built-in validation option defines a **default** error message. -For example, the `(pattern)` option declares its default message in `spine/options.proto`. +These messages come as the value of the `default_message` option declared for each option type. + +For example, the `pattern` option defines the following default message: + +```protobuf +message PatternOption { + + // The default error message. + option (default_message) = "The `${parent.type}.${field.path}` field" + " must match the regular expression `${regex.pattern}` (modifiers: `${regex.modifiers}`)." + " The passed value: `${field.value}`."; + + // ... +} +``` When you apply an option in a `.proto` file, you can **override** the default message by setting the option’s `error_msg` field. @@ -30,16 +44,19 @@ Example: custom message for a regex pattern. import "spine/options.proto"; message CreateAccount { - string id = 1 [ - (pattern).regex = "^[A-Za-z0-9+]+$", - (pattern).error_msg = "ID must be alphanumerical in `${parent.type}`. Provided: `${field.value}`." - ]; + string id = 1 [ + (pattern).regex = "^[A-Za-z0-9+]+$", + (pattern).error_msg = "ID must be alphanumerical in `${parent.type}`. Provided: `${field.value}`." + ]; } ``` The placeholders (like `${field.value}`) are substituted at runtime when the violation is created. -Each option documents the placeholders it supports next to its `error_msg` field in `spine/options.proto`. +{{% note-block class="note" %}} +Each option documents the placeholders it supports next to its `error_msg` field +in `spine/options.proto`. +{{% /note-block %}} ## Placeholders and `TemplateString` @@ -50,9 +67,11 @@ Each option documents the placeholders it supports next to its `error_msg` field The placeholder keys in the map do **not** include `${}` — for example, `field.path`. +{{% note-block class="warning" %}} The map may include extra keys that are not referenced by the template, but every placeholder -used in `with_placeholders` must have a corresponding value (otherwise, the template is invalid). - +used in `with_placeholders` **must** have a corresponding value. +Otherwise, the template is invalid. +{{% /note-block %}} ## Formatting messages in code From b56c66c28c5e45609930c493a0379fb28f8fe6bf Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 21:51:53 +0000 Subject: [PATCH 26/43] Use Mermaid diagram for generated code flow --- docs/content/docs/validation/00-intro/philosophy.md | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/validation/00-intro/philosophy.md b/docs/content/docs/validation/00-intro/philosophy.md index d2827f2104..ccc2291514 100644 --- a/docs/content/docs/validation/00-intro/philosophy.md +++ b/docs/content/docs/validation/00-intro/philosophy.md @@ -123,8 +123,12 @@ front-end models, or JSON schemas. Its focus is entirely on: -``` -Protobuf → generated Java/Kotlin/TypeScript → domain logic +```mermaid +graph LR + A(Protobuf) --> B(Generated code) + B --> C(Domain logic) + subgraph B [Generated Java/Kotlin/TypeScript] + end ``` Everything else (frontend validation, OpenAPI, view models) should build on top From 0b6c2a7e41da473bf4cfb8a6b70867477297ff89 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 21:59:21 +0000 Subject: [PATCH 27/43] Add link to `first-model` --- docs/content/docs/validation/02-concepts/_index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/validation/02-concepts/_index.md b/docs/content/docs/validation/02-concepts/_index.md index 26b258d446..c9d559a3fd 100644 --- a/docs/content/docs/validation/02-concepts/_index.md +++ b/docs/content/docs/validation/02-concepts/_index.md @@ -12,8 +12,8 @@ It answers two questions: - **How do I express validation rules?** - **How does the runtime report violations?** -If you are new to the library, start with declaring constraints in `.proto` files and -then come back here for the details. +If you are new to the library, start with [declaring constraints](../01-getting-started/first-model) +in `.proto` files and then come back here for the details. ## Vocabulary From cf51e6de0869daaff424b94deef556ef6d3d9a89 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 22:03:15 +0000 Subject: [PATCH 28/43] Archive the almost complete task --- .agents/tasks/{ => archive}/working-with-error-messages.md | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename .agents/tasks/{ => archive}/working-with-error-messages.md (100%) diff --git a/.agents/tasks/working-with-error-messages.md b/.agents/tasks/archive/working-with-error-messages.md similarity index 100% rename from .agents/tasks/working-with-error-messages.md rename to .agents/tasks/archive/working-with-error-messages.md From 4be83bbfce4f25f8d23c1fbe49b12c0a1d386f88 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 22:09:28 +0000 Subject: [PATCH 29/43] Remove extra empty lines --- .agents/skills/writer/assets/templates/kdoc-example.md | 1 - 1 file changed, 1 deletion(-) diff --git a/.agents/skills/writer/assets/templates/kdoc-example.md b/.agents/skills/writer/assets/templates/kdoc-example.md index c798d13c3b..fdbd9b6a0d 100644 --- a/.agents/skills/writer/assets/templates/kdoc-example.md +++ b/.agents/skills/writer/assets/templates/kdoc-example.md @@ -9,4 +9,3 @@ * ``` */ ```` - From 6a1db3d00fc8663cdbd1f9b35d284b7295fc29a0 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Thu, 26 Feb 2026 22:11:13 +0000 Subject: [PATCH 30/43] Update dependency reports --- dependencies.md | 60 ++++++++++++++++++++++++------------------------- pom.xml | 2 +- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/dependencies.md b/dependencies.md index bf23d06224..7ce35d6304 100644 --- a/dependencies.md +++ b/dependencies.md @@ -1,6 +1,6 @@ -# Dependencies of `io.spine.tools:validation-context:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-context:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -1139,14 +1139,14 @@ The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:06 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-context-tests:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-context-tests:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -1731,7 +1731,7 @@ This report was generated on **Tue Feb 24 20:44:06 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:02 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). @@ -1752,7 +1752,7 @@ This report was generated on **Mon Feb 23 18:35:33 WET 2026** using -# Dependencies of `io.spine.tools:validation-gradle-plugin:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-gradle-plugin:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -2841,14 +2841,14 @@ This report was generated on **Mon Feb 23 18:35:33 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:06 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-java:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-java:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -3935,14 +3935,14 @@ This report was generated on **Tue Feb 24 20:44:06 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:06 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-java-bundle:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-java-bundle:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.google.auto.service. **Name** : auto-service-annotations. **Version** : 1.1.1. @@ -4005,14 +4005,14 @@ This report was generated on **Tue Feb 24 20:44:06 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:01 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine:validation-jvm-runtime:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine:validation-jvm-runtime:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -4845,14 +4845,14 @@ This report was generated on **Tue Feb 24 20:44:05 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:06 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-ksp:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-ksp:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.google.auto.service. **Name** : auto-service-annotations. **Version** : 1.1.1. @@ -5781,14 +5781,14 @@ This report was generated on **Tue Feb 24 20:44:06 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:06 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-consumer:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-consumer:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -6379,14 +6379,14 @@ This report was generated on **Tue Feb 24 20:44:06 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:01 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-consumer-dependency:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-consumer-dependency:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -6897,14 +6897,14 @@ This report was generated on **Tue Feb 24 20:44:05 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-extensions:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-extensions:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -7588,14 +7588,14 @@ This report was generated on **Tue Feb 24 20:44:05 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-runtime:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-runtime:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -8217,14 +8217,14 @@ This report was generated on **Tue Feb 24 20:44:05 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-validating:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-validating:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -8889,14 +8889,14 @@ This report was generated on **Tue Feb 24 20:44:05 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:06 WET 2026** using +This report was generated on **Thu Feb 26 22:11:03 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-validator:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-validator:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.fasterxml.jackson. **Name** : jackson-bom. **Version** : 2.20.0. @@ -9647,14 +9647,14 @@ This report was generated on **Tue Feb 24 20:44:06 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:02 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-validator-dependency:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-validator-dependency:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -9924,14 +9924,14 @@ This report was generated on **Tue Feb 24 20:44:05 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:02 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). -# Dependencies of `io.spine.tools:validation-vanilla:2.0.0-SNAPSHOT.398` +# Dependencies of `io.spine.tools:validation-vanilla:2.0.0-SNAPSHOT.399` ## Runtime 1. **Group** : com.google.code.findbugs. **Name** : jsr305. **Version** : 3.0.2. @@ -10282,6 +10282,6 @@ This report was generated on **Tue Feb 24 20:44:05 WET 2026** using The dependencies distributed under several licenses, are used according their commercial-use-friendly license. -This report was generated on **Tue Feb 24 20:44:05 WET 2026** using +This report was generated on **Thu Feb 26 22:11:01 WET 2026** using [Gradle-License-Report plugin](https://github.com/jk1/Gradle-License-Report) by Evgeny Naumenko, licensed under [Apache 2.0 License](https://github.com/jk1/Gradle-License-Report/blob/master/LICENSE). \ No newline at end of file diff --git a/pom.xml b/pom.xml index b36592557f..ed86aa7649 100644 --- a/pom.xml +++ b/pom.xml @@ -10,7 +10,7 @@ all modules and does not describe the project structure per-subproject. --> io.spine.tools validation -2.0.0-SNAPSHOT.398 +2.0.0-SNAPSHOT.399 2015 From a4ac738a2c8fc80ffe5e382b38a111032534ea5c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 17:03:16 +0000 Subject: [PATCH 31/43] Improve Mermaid diagram on compilation --- docs/content/docs/validation/02-concepts/options-overview.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index ff2d9303b7..71ddbc29cd 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -47,10 +47,10 @@ The result is a Java API that enforces the rules you declared in the model. ```mermaid flowchart LR - A[".proto
+
spine/options.proto
"] --> B["protoc
(Java)"] + A[".proto
  +
spine/options.proto"] --> B["protoc
(Java)"] B --> C["Validation Compiler
via Gradle plugin"] C --> D["Generated Java API - build(), validate()"] + build(), validate()"] ``` ## What code you get (runtime) From ba2972351d34f953ab2cd716949ae6910e6ce63f Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 17:13:04 +0000 Subject: [PATCH 32/43] Mark "Working with error messages" done --- .agents/tasks/validation-documentation-plan.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index ad30f9bf34..282373302c 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -47,6 +47,7 @@ buildable documentation set, without expanding scope unnecessarily. - Status: DONE (2026-02-26). 4) [Working with error messages](working-with-error-messages.md) +- Status: DONE (2026-02-27). 5) Built-in options: publish a minimal reference set - From `docs/_options/options.proto`, From 2204308df9f2e35a3fa7ad1633e671939b6167cf Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 17:26:29 +0000 Subject: [PATCH 33/43] Update the plan with subtask details --- .agents/tasks/built-in-options-plan.md | 7 +++ .agents/tasks/custom-validation-plan.md | 47 +++++++++++++++ .agents/tasks/developers-guide-plan.md | 51 ++++++++++++++++ .agents/tasks/third-party-messages-plan.md | 60 +++++++++++++++++++ .../tasks/validation-documentation-plan.md | 33 ++++------ 5 files changed, 178 insertions(+), 20 deletions(-) create mode 100644 .agents/tasks/built-in-options-plan.md create mode 100644 .agents/tasks/custom-validation-plan.md create mode 100644 .agents/tasks/developers-guide-plan.md create mode 100644 .agents/tasks/third-party-messages-plan.md diff --git a/.agents/tasks/built-in-options-plan.md b/.agents/tasks/built-in-options-plan.md new file mode 100644 index 0000000000..62c2e2ded4 --- /dev/null +++ b/.agents/tasks/built-in-options-plan.md @@ -0,0 +1,7 @@ +# Task: Publish a minimal reference set on built-in validation options +- Placement: a separate section comping after the "Concepts" section. +- From `docs/_options/options.proto`, + enumerate the built-in options and group them (fields, strings, numbers, collections, message-level). +- For each documented option: purpose, supported field types, common pitfalls, and a short `.proto` example. +- Start with the options already used in docs/examples: `(required)`, `(pattern)`, `(min)/(max)`, + `(distinct)`, `(validate)`. diff --git a/.agents/tasks/custom-validation-plan.md b/.agents/tasks/custom-validation-plan.md new file mode 100644 index 0000000000..831e9c6115 --- /dev/null +++ b/.agents/tasks/custom-validation-plan.md @@ -0,0 +1,47 @@ +# Task: Expand “Custom validation” docs (custom options + codegen) + +## Goal + +Turn the existing “Custom validation” landing page into a complete, end-to-end guide for +implementing organization-specific rules via custom Protobuf options and code generation. + +Target outcome: a reader can define a custom option, register it, implement reaction/view/generator, +and verify it works in a consumer project. + +## Placement + +- Placement of the pages: `docs/content/docs/validation/08-custom-validation/`. +- Keep the current landing page as an overview and add a single practical walkthrough page. + +## Planned content + +- Clarify the extension surface: + - Custom Protobuf option definition (`extend google.protobuf.*Options`). + - Option discovery + validation (reaction). + - Accumulating a model (views, plus policies if needed). + - Generating/injecting Java validation code (generator). +- Make the steps actionable: + - Show file/Gradle locations where each piece belongs in a consumer project. + - Explain registration points: + - `io.spine.option.OptionsProvider` + - `io.spine.tools.validation.java.ValidationOption` (SPI for custom option implementations) +- Provide a minimal “walkthrough” with the existing `(currency)` sample: + - Point to the option declaration, the reaction/view/generator, and the registration. + - Explain the intended contract: what rule is enforced, where the error message comes from. +- Add a short troubleshooting section: + - Option not discovered (missing `OptionsProvider`). + - Generator not invoked (missing `ValidationOption` SPI entry). + - Illegal option application should fail compilation (where to look for error messages). + +## Source references to anchor the docs + +- Existing overview page: + - `docs/content/docs/validation/08-custom-validation/_index.md` +- Full working example: + - `:tests:extensions` module (custom `(currency)` option implementation) + +## Output + +- Update: `docs/content/docs/validation/08-custom-validation/_index.md`. +- Add: `docs/content/docs/validation/08-custom-validation/currency-example.md`. + diff --git a/.agents/tasks/developers-guide-plan.md b/.agents/tasks/developers-guide-plan.md new file mode 100644 index 0000000000..7d584d77e2 --- /dev/null +++ b/.agents/tasks/developers-guide-plan.md @@ -0,0 +1,51 @@ +# Task: Complete Developer’s guide (architecture and key modules) + +## Goal + +Make the “Developer’s guide” pages sufficient for maintainers and contributors: +the reader should understand the compilation pipeline, where each responsibility lives, +and where to start when debugging a doc/codegen/runtime issue. + +## Placement + +- Placement of the pages: `docs/content/docs/validation/09-developers-guide/`. +- Expand the existing pages without adding many new sections (keep it minimal). + +## Planned content + +- Architecture page (`architecture.md`) + - Add a legend / step-by-step explanation for the existing diagram: + - where options are discovered; + - where the validation model is built (policies/views); + - where Java code is generated/injected; + - what artifacts flow between stages (descriptors, generated sources, resources). + - Call out the main extension points and where they plug in: + - custom options (reaction/view/generator + SPI); + - external message validators (`MessageValidator` + `@Validator` + KSP discovery). + - Add “Where to look” links: + - built-in options reference; + - custom validation section; + - key modules page. + +- Key modules page (`key-modules.md`) + - Keep the tables, but add a 1–2 paragraph “debugging map”: + - build-time problems (compiler/plugin) vs runtime problems (generated code / runtime library). + - Add a short list of “common entry points” by scenario: + - option semantics or compilation errors → `:context`, `:java`, `:gradle-plugin`; + - validator discovery problems → `:ksp`, `:java`; + - error message formatting → `:jvm-runtime`. + +## Source references to anchor the docs + +- Existing pages: + - `docs/content/docs/validation/09-developers-guide/architecture.md` + - `docs/content/docs/validation/09-developers-guide/key-modules.md` +- External message validator mechanism (for cross-linking): + - `jvm-runtime/src/main/kotlin/io/spine/validation/MessageValidator.kt` + - `jvm-runtime/src/main/kotlin/io/spine/validation/Validator.kt` + +## Output + +- Update: `docs/content/docs/validation/09-developers-guide/architecture.md`. +- Update: `docs/content/docs/validation/09-developers-guide/key-modules.md`. + diff --git a/.agents/tasks/third-party-messages-plan.md b/.agents/tasks/third-party-messages-plan.md new file mode 100644 index 0000000000..690a7f7ec9 --- /dev/null +++ b/.agents/tasks/third-party-messages-plan.md @@ -0,0 +1,60 @@ +# Task: Document validating third-party (external) messages + +## Goal + +Explain how to enforce validation rules for Protobuf message classes that are **already generated** +by third parties and therefore cannot be updated via `.proto` option annotations + codegen. + +Target outcome: a reader can pick the right strategy depending on whether they control the `.proto` +source, and can implement an external message validator that is automatically applied when +validating local messages. + +## Placement + +- Placement of the page: after “Built-in options”, before “Custom validation”. +- Hugo section (minimal change): add the page under `docs/content/docs/validation/02-concepts/`. + If the site navigation later gains an “Advanced topics” section, the page can move there. + +## Planned content + +- Define “local” vs “external” messages: + - Local: `.proto` sources compiled in the current build; Validation injects checks into generated code. + - External: message classes already compiled (e.g., come from dependencies); codegen cannot be applied. +- What does and does not work: + - You cannot attach Validation options to fields of external messages unless you rebuild their `.proto`. + - External validators are applied **only when an external message is a field inside a local message**. + - External validators are not applied transitively inside other external messages. +- Recommended strategy decision tree: + - If you control `.proto`: prefer built-in options or custom validation options (codegen). + - If you don’t control `.proto`: use `MessageValidator` + `@Validator`. +- How external validation works (high-level): + - Implement `io.spine.validation.MessageValidator`. + - Annotate the implementation with `@io.spine.validation.Validator(M::class)`. + - Ensure a `public` no-args constructor (required by discovery/instantiation). + - Validation invokes the validator for: + - singular fields of type `M`; + - repeated fields of type `M`; + - map values of type `M`. +- Error reporting shape: + - Return `List`. + - Use `FieldViolation` (and other available violation types) to point at a field path and value. + - Mention that the runtime converts `DetectedViolation` into `ConstraintViolation`/`ValidationError`. +- Constraints and guardrails: + - Exactly one validator per external message type (duplicate is an error). + - Validators for local messages are prohibited (use options/codegen instead). +- Example walkthrough (short, copy-pastable): + - Implement `EarphonesValidator` (from `:tests:validator`) and show how it affects a local message + that contains an `Earphones` field. + +## Source references to anchor the docs + +- External validation API and requirements: + - `jvm-runtime/src/main/kotlin/io/spine/validation/MessageValidator.kt` + - `jvm-runtime/src/main/kotlin/io/spine/validation/Validator.kt` +- Example implementation: + - `tests/validator/src/main/kotlin/io/spine/tools/validation/test/EarphonesValidator.kt` + +## Output + +Implemented as `docs/content/docs/validation/02-concepts/third-party-messages.md`. + diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index 282373302c..f6ba2ec28e 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -46,28 +46,21 @@ buildable documentation set, without expanding scope unnecessarily. 3) [Concepts](archive/concepts-plan.md) - Status: DONE (2026-02-26). -4) [Working with error messages](working-with-error-messages.md) +4) [Working with error messages](archive/working-with-error-messages.md) - Status: DONE (2026-02-27). -5) Built-in options: publish a minimal reference set -- From `docs/_options/options.proto`, - enumerate the built-in options and group them (fields, strings, numbers, collections, message-level). -- For each documented option: purpose, supported field types, common pitfalls, and a short `.proto` example. -- Start with the options already used in docs/examples: `(required)`, `(pattern)`, `(min)/(max)`, - `(distinct)`, `(validate)`. - -6) Runtime API usage (Java + Kotlin) -- Document the two primary usage patterns: - - fail-fast on `build()` (throws `ValidationException`); - - non-throwing `validate()` (returns `Optional`). -- Link to the runtime entry points used by generated code: - `jvm-runtime/src/main/java/io/spine/validation/ValidatableMessage.java`, - `jvm-runtime/src/main/java/io/spine/validation/ValidatingBuilder.java`, - `jvm-runtime/src/main/java/io/spine/validation/Validate.java`, - `jvm-runtime/src/main/java/io/spine/validation/ValidationException.java`, - `jvm-runtime/src/main/kotlin/io/spine/validation/MessageExtensions.kt`. - -7) Verification pass (keep it tight; fix only doc-related issues) +5) [Built-in options](built-in-options-plan.md): publish a minimal reference set + +6) [Validating third-party messages](third-party-messages-plan.md) + +7) [Custom validation: defining your own options and codegen](custom-validation-plan.md) + +8) [Developer's guide: architecture and key modules](developers-guide-plan.md) + +## Verification pass + +Keep it tight; fix only doc-related issues. + - From `docs/`, run: - `./gradlew embedCode` - `./gradlew checkSamples` From 1b1c689da766a22f01d2e3f5856f28c1434572f1 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 17:37:32 +0000 Subject: [PATCH 34/43] Add empty drafts for remaining sections --- docs/content/docs/validation/02-concepts/_index.md | 14 ++++++++------ .../validation/02-concepts/options-overview.md | 6 ++---- .../docs/validation/03-built-in-options/_index.md | 13 +++++++++++++ .../validation/04-third-party-messages/_index.md | 13 +++++++++++++ .../docs/validation/08-custom-validation/_index.md | 1 + docs/content/docs/validation/_index.md | 2 ++ .../docs/validation/2-0-0-snapshot/sidenav.yml | 4 ++++ 7 files changed, 43 insertions(+), 10 deletions(-) create mode 100644 docs/content/docs/validation/03-built-in-options/_index.md create mode 100644 docs/content/docs/validation/04-third-party-messages/_index.md diff --git a/docs/content/docs/validation/02-concepts/_index.md b/docs/content/docs/validation/02-concepts/_index.md index c9d559a3fd..0fc0e61291 100644 --- a/docs/content/docs/validation/02-concepts/_index.md +++ b/docs/content/docs/validation/02-concepts/_index.md @@ -102,9 +102,11 @@ See [Custom validation](../08-custom-validation/) for the workflow and a referen [Using the generated code](../01-getting-started/generated-code.md). - See how options influence generated code: [Options overview](options-overview.md). -- Customize and format messages: - [Working with error messages](working-with-error-messages.md). -- Add custom validation options: - [Custom validation](../08-custom-validation/). -- Explore the implementation: - [Architecture](../09-developers-guide/architecture.md). + - Customize and format messages: + [Working with error messages](working-with-error-messages.md). +- [Built-in options](../03-built-in-options/) +- [Validating third-party messages](../04-third-party-messages/) + - Add custom validation options: + [Custom validation](../08-custom-validation/). + - Explore the implementation: + [Architecture](../09-developers-guide/architecture.md). diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index 71ddbc29cd..3109e249d4 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -111,7 +111,5 @@ message Temperature { ## What’s next -- Built-in options reference (planned). -- Learn how to define organization-specific rules: - [Custom validation](../08-custom-validation/). - +- [Built-in options](../03-built-in-options/) +- [Custom validation](../08-custom-validation/) diff --git a/docs/content/docs/validation/03-built-in-options/_index.md b/docs/content/docs/validation/03-built-in-options/_index.md new file mode 100644 index 0000000000..74b937aa86 --- /dev/null +++ b/docs/content/docs/validation/03-built-in-options/_index.md @@ -0,0 +1,13 @@ +--- +title: Built-in options +description: Reference for built-in Spine Validation options. +headline: Documentation +--- + +# Built-in options + +## What’s next + +- [Validating third-party messages](../04-third-party-messages/) +- [Custom validation](../08-custom-validation/) + diff --git a/docs/content/docs/validation/04-third-party-messages/_index.md b/docs/content/docs/validation/04-third-party-messages/_index.md new file mode 100644 index 0000000000..158abcd1eb --- /dev/null +++ b/docs/content/docs/validation/04-third-party-messages/_index.md @@ -0,0 +1,13 @@ +--- +title: Validating third-party messages +description: How to validate message types generated outside your build. +headline: Documentation +--- + +# Validating third-party messages + +## What’s next + +- [Custom validation](../08-custom-validation/) +- [Architecture](../09-developers-guide/architecture.md) + diff --git a/docs/content/docs/validation/08-custom-validation/_index.md b/docs/content/docs/validation/08-custom-validation/_index.md index 91409e9a93..681741c310 100644 --- a/docs/content/docs/validation/08-custom-validation/_index.md +++ b/docs/content/docs/validation/08-custom-validation/_index.md @@ -25,6 +25,7 @@ Below is a workflow diagram for a typical option: ## What’s next +- [Validating third-party messages](../04-third-party-messages/) - Learn where this plugs in: [Architecture](../09-developers-guide/architecture.md). Take a look at the `:tests:extensions` module that contains a full example of diff --git a/docs/content/docs/validation/_index.md b/docs/content/docs/validation/_index.md index 6ac06fcda9..3d075a52b3 100644 --- a/docs/content/docs/validation/_index.md +++ b/docs/content/docs/validation/_index.md @@ -16,5 +16,7 @@ options, and runs those checks automatically when you build messages. ## Deeper topics +- [Built-in options](03-built-in-options/) +- [Validating third-party messages](04-third-party-messages/) - How it works: [Architecture](09-developers-guide/architecture.md) - Extension points: [Custom validation](08-custom-validation/) diff --git a/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml b/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml index fe3e414279..907ffec735 100644 --- a/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml +++ b/docs/data/docs/validation/2-0-0-snapshot/sidenav.yml @@ -35,6 +35,10 @@ file_path: 02-concepts/options-overview - page: Working with error messages file_path: 02-concepts/error-messages + - page: Built-in options + file_path: 03-built-in-options + - page: Validating third-party messages + file_path: 04-third-party-messages - page: Custom validation file_path: 08-custom-validation - page: Developer’s guide From 9cbc80d99dca006f4e4c9088b2791fa1e21c138c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 17:45:05 +0000 Subject: [PATCH 35/43] Improve plan file name --- .../{working-with-error-messages.md => error-messages-plan.md} | 0 .agents/tasks/validation-documentation-plan.md | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename .agents/tasks/archive/{working-with-error-messages.md => error-messages-plan.md} (100%) diff --git a/.agents/tasks/archive/working-with-error-messages.md b/.agents/tasks/archive/error-messages-plan.md similarity index 100% rename from .agents/tasks/archive/working-with-error-messages.md rename to .agents/tasks/archive/error-messages-plan.md diff --git a/.agents/tasks/validation-documentation-plan.md b/.agents/tasks/validation-documentation-plan.md index f6ba2ec28e..8152490abd 100644 --- a/.agents/tasks/validation-documentation-plan.md +++ b/.agents/tasks/validation-documentation-plan.md @@ -46,7 +46,7 @@ buildable documentation set, without expanding scope unnecessarily. 3) [Concepts](archive/concepts-plan.md) - Status: DONE (2026-02-26). -4) [Working with error messages](archive/working-with-error-messages.md) +4) [Working with error messages](archive/error-messages-plan.md) - Status: DONE (2026-02-27). 5) [Built-in options](built-in-options-plan.md): publish a minimal reference set From 9523120d984578c042f2a5965afeb02a6343cc8c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 17:52:24 +0000 Subject: [PATCH 36/43] Add "What's next" block for the error messages page --- .../docs/validation/02-concepts/error-messages.md | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/docs/content/docs/validation/02-concepts/error-messages.md b/docs/content/docs/validation/02-concepts/error-messages.md index b6114f2778..ba00d250bd 100644 --- a/docs/content/docs/validation/02-concepts/error-messages.md +++ b/docs/content/docs/validation/02-concepts/error-messages.md @@ -129,3 +129,14 @@ Recommended actions: - treat this as a bug in the option/message definition, and fix the custom `error_msg` in your `.proto`; - if you can tolerate partial substitution (for example, in logs), use `formatUnsafe()`. + +## What’s next + +- See how constraints are expressed as options and compiled into runtime checks: + [Options overview](options-overview.md). +- Explore the built-in options: + [Built-in options](../03-built-in-options/). +- Learn how to validate message types from third-party libraries: + [Validating third-party messages](../04-third-party-messages/). +- If built-in options are not enough, define your own constraints and messages: + [Custom validation](../08-custom-validation/). From 8346dd0dc91d6ae7e6cf308217dcc71de18ea80c Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 17:55:33 +0000 Subject: [PATCH 37/43] Fix the broken link --- docs/content/docs/validation/02-concepts/_index.md | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/docs/content/docs/validation/02-concepts/_index.md b/docs/content/docs/validation/02-concepts/_index.md index 0fc0e61291..54c4ec69e0 100644 --- a/docs/content/docs/validation/02-concepts/_index.md +++ b/docs/content/docs/validation/02-concepts/_index.md @@ -68,7 +68,7 @@ Each `ConstraintViolation` points to the invalid value and explains what went wr - `field_value` — the invalid value packed as `google.protobuf.Any`. When you need a human-readable message, format the `TemplateString` from the violation. -See [Working with error messages](working-with-error-messages.md) for message formatting, +See [Working with error messages](error-messages.md) for message formatting, placeholders, and customization. @@ -102,11 +102,9 @@ See [Custom validation](../08-custom-validation/) for the workflow and a referen [Using the generated code](../01-getting-started/generated-code.md). - See how options influence generated code: [Options overview](options-overview.md). - - Customize and format messages: - [Working with error messages](working-with-error-messages.md). +- Customize and format messages: + [Working with error messages](error-messages.md). - [Built-in options](../03-built-in-options/) - [Validating third-party messages](../04-third-party-messages/) - - Add custom validation options: - [Custom validation](../08-custom-validation/). - - Explore the implementation: - [Architecture](../09-developers-guide/architecture.md). +- Add custom validation options: + [Custom validation](../08-custom-validation/). From 109e924fa66ed7938b44a5d1169bcfd3ccbec237 Mon Sep 17 00:00:00 2001 From: Alexander Yevsyukov Date: Fri, 27 Feb 2026 20:02:47 +0200 Subject: [PATCH 38/43] Fix typo in a plan document Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- .agents/tasks/built-in-options-plan.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.agents/tasks/built-in-options-plan.md b/.agents/tasks/built-in-options-plan.md index 62c2e2ded4..90df03f04d 100644 --- a/.agents/tasks/built-in-options-plan.md +++ b/.agents/tasks/built-in-options-plan.md @@ -1,5 +1,5 @@ # Task: Publish a minimal reference set on built-in validation options -- Placement: a separate section comping after the "Concepts" section. +- Placement: a separate section coming after the "Concepts" section. - From `docs/_options/options.proto`, enumerate the built-in options and group them (fields, strings, numbers, collections, message-level). - For each documented option: purpose, supported field types, common pitfalls, and a short `.proto` example. From 2d214534bfdf86da9423da8705e5a31feb4c60f9 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 18:09:37 +0000 Subject: [PATCH 39/43] Avoid raw brak in the Mermaid diagram --- docs/content/docs/validation/02-concepts/options-overview.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index 3109e249d4..57e637e1e1 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -49,8 +49,7 @@ The result is a Java API that enforces the rules you declared in the model. flowchart LR A[".proto
  +
spine/options.proto"] --> B["protoc
(Java)"] B --> C["Validation Compiler
via Gradle plugin"] - C --> D["Generated Java API - build(), validate()"] + C --> D["Generated Java API
build(), validate()"] ``` ## What code you get (runtime) From 74d593189868a3b9623e9f66f03c601be92a8552 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 18:16:05 +0000 Subject: [PATCH 40/43] Fix Mermaid diagram structure --- docs/content/docs/validation/00-intro/philosophy.md | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/docs/content/docs/validation/00-intro/philosophy.md b/docs/content/docs/validation/00-intro/philosophy.md index ccc2291514..0da8cbf498 100644 --- a/docs/content/docs/validation/00-intro/philosophy.md +++ b/docs/content/docs/validation/00-intro/philosophy.md @@ -125,10 +125,8 @@ Its focus is entirely on: ```mermaid graph LR - A(Protobuf) --> B(Generated code) + A(Protobuf) --> B(Generated Java/Kotlin/TypeScript) B --> C(Domain logic) - subgraph B [Generated Java/Kotlin/TypeScript] - end ``` Everything else (frontend validation, OpenAPI, view models) should build on top From e1832d308403f69e3e8bb325addd993ac1fcdc17 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 18:19:57 +0000 Subject: [PATCH 41/43] Improve the wording around code generation --- docs/content/docs/validation/02-concepts/options-overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/docs/validation/02-concepts/options-overview.md b/docs/content/docs/validation/02-concepts/options-overview.md index 57e637e1e1..a304cca991 100644 --- a/docs/content/docs/validation/02-concepts/options-overview.md +++ b/docs/content/docs/validation/02-concepts/options-overview.md @@ -66,7 +66,7 @@ See [Using the generated code](../01-getting-started/generated-code.md) for Java ## What does not happen At runtime, Spine Validation does **not** parse descriptor option data to decide what to validate. -All checks are already compiled into the generated message/builder code. +All checks are already translated into the generated message/builder code. ## Tiny examples From c9d8411e9e54d7c2cf8a6e5c979eeafbb32f0f54 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 18:21:02 +0000 Subject: [PATCH 42/43] Remove extra empty lines --- docs/content/docs/validation/03-built-in-options/_index.md | 1 - docs/content/docs/validation/04-third-party-messages/_index.md | 1 - 2 files changed, 2 deletions(-) diff --git a/docs/content/docs/validation/03-built-in-options/_index.md b/docs/content/docs/validation/03-built-in-options/_index.md index 74b937aa86..6e186d9a85 100644 --- a/docs/content/docs/validation/03-built-in-options/_index.md +++ b/docs/content/docs/validation/03-built-in-options/_index.md @@ -10,4 +10,3 @@ headline: Documentation - [Validating third-party messages](../04-third-party-messages/) - [Custom validation](../08-custom-validation/) - diff --git a/docs/content/docs/validation/04-third-party-messages/_index.md b/docs/content/docs/validation/04-third-party-messages/_index.md index 158abcd1eb..18665689ab 100644 --- a/docs/content/docs/validation/04-third-party-messages/_index.md +++ b/docs/content/docs/validation/04-third-party-messages/_index.md @@ -10,4 +10,3 @@ headline: Documentation - [Custom validation](../08-custom-validation/) - [Architecture](../09-developers-guide/architecture.md) - From cc68451a97e772394629a29d9070851c6dc0bb65 Mon Sep 17 00:00:00 2001 From: alexander-yevsyukov Date: Fri, 27 Feb 2026 18:22:06 +0000 Subject: [PATCH 43/43] Remove duplicating skill --- skills/writer/SKILL.md | 47 ------------------- skills/writer/agents/openai.yaml | 5 -- skills/writer/assets/templates/doc-page.md | 23 --------- .../writer/assets/templates/kdoc-example.md | 12 ----- 4 files changed, 87 deletions(-) delete mode 100644 skills/writer/SKILL.md delete mode 100644 skills/writer/agents/openai.yaml delete mode 100644 skills/writer/assets/templates/doc-page.md delete mode 100644 skills/writer/assets/templates/kdoc-example.md diff --git a/skills/writer/SKILL.md b/skills/writer/SKILL.md deleted file mode 100644 index 478d25398c..0000000000 --- a/skills/writer/SKILL.md +++ /dev/null @@ -1,47 +0,0 @@ ---- -name: writer -description: Write, edit, and restructure user-facing and developer-facing documentation for the Spine `validation` repository. Use when asked to create/update docs such as `README.md`, `docs/**`, `CONTRIBUTING.md`, and other Markdown documentation; when drafting tutorials, guides, troubleshooting pages, or migration notes; and when improving inline API documentation (KDoc) and examples. ---- - -# Write documentation (repo-specific) - -## Decide the target and audience - -- Identify the target reader: end user, contributor, maintainer, or tooling/automation. -- Identify the task type: new doc, update, restructure, or documentation audit. -- Identify the acceptance criteria: “what is correct when the reader is done?” - -## Choose where the content should live - -- Prefer updating an existing doc over creating a new one. -- Place content in the most discoverable location: - - `README.md`: project entry point and “what is this?”. - - `docs/`: longer-form docs (follow existing conventions in that tree). - - `CONTRIBUTING.md`: contributor workflows. - - Source KDoc: API usage, examples, and semantics that belong with the code. - -## Follow local documentation conventions - -- Follow `.agents/documentation-guidelines.md` and `.agents/documentation-tasks.md`. -- Use fenced code blocks for commands and examples; format file/dir names as code. -- Avoid widows, runts, orphans, and rivers by reflowing paragraphs when needed. - -## Make docs actionable - -- Prefer steps the reader can execute (commands + expected outcome). -- Prefer concrete examples over abstract descriptions. -- Include prerequisites (versions, OS, environment) when they are easy to miss. -- Use consistent terminology (match code identifiers and existing docs). - -## KDoc-specific guidance - -- For public/internal APIs, include at least one example snippet demonstrating common usage. -- When converting from Javadoc/inline comments to KDoc: - - Remove HTML like `

` and preserve meaning. - - Prefer short paragraphs and blank lines over HTML formatting. - -## Validate changes - -- For code changes, follow `.agents/running-builds.md`. -- For documentation-only changes in Kotlin/Java sources, prefer `./gradlew dokka`. - diff --git a/skills/writer/agents/openai.yaml b/skills/writer/agents/openai.yaml deleted file mode 100644 index 44eaa4e241..0000000000 --- a/skills/writer/agents/openai.yaml +++ /dev/null @@ -1,5 +0,0 @@ -interface: - display_name: "Writer" - short_description: "Write and update user/developer docs" - default_prompt: "Write or revise documentation in this repository (for example: README.md, docs/**, CONTRIBUTING.md, and API documentation/KDoc). Follow local documentation guidelines in .agents/*.md, keep changes concise and actionable, and include concrete examples and commands where appropriate." - diff --git a/skills/writer/assets/templates/doc-page.md b/skills/writer/assets/templates/doc-page.md deleted file mode 100644 index f405b71e15..0000000000 --- a/skills/writer/assets/templates/doc-page.md +++ /dev/null @@ -1,23 +0,0 @@ -# Title - -## Goal - -State what the reader will accomplish. - -## Prerequisites - -- List versions/tools the reader needs. - -## Steps - -1. Do the first thing. -2. Do the next thing. - -## Verify - -Show how the reader can confirm success. - -## Troubleshooting - -- Common failure: likely cause → fix. - diff --git a/skills/writer/assets/templates/kdoc-example.md b/skills/writer/assets/templates/kdoc-example.md deleted file mode 100644 index 57e32c5ef3..0000000000 --- a/skills/writer/assets/templates/kdoc-example.md +++ /dev/null @@ -1,12 +0,0 @@ -```kotlin -/** - * Explain what this API does in one sentence. - * - * ## Example - * ```kotlin - * // Show the typical usage pattern. - * val result = doThing() - * ``` - */ -``` -