softschema 0.1.4__tar.gz → 0.2.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {softschema-0.1.4 → softschema-0.2.1}/AGENTS.md +5 -5
- {softschema-0.1.4 → softschema-0.2.1}/PKG-INFO +117 -177
- {softschema-0.1.4 → softschema-0.2.1}/README.md +116 -176
- {softschema-0.1.4 → softschema-0.2.1}/docs/development.md +19 -18
- softschema-0.2.1/docs/e2e-testing.runbook.md +227 -0
- softschema-0.2.1/docs/installation.md +89 -0
- {softschema-0.1.4 → softschema-0.2.1}/docs/publishing.md +54 -38
- {softschema-0.1.4 → softschema-0.2.1}/docs/softschema-guide.md +126 -64
- {softschema-0.1.4 → softschema-0.2.1}/docs/softschema-python-design.md +64 -38
- softschema-0.2.1/docs/softschema-spec.md +437 -0
- {softschema-0.1.4 → softschema-0.2.1}/docs/softschema-typescript-design.md +32 -10
- {softschema-0.1.4 → softschema-0.2.1}/examples/movie_page/README.md +22 -17
- {softschema-0.1.4 → softschema-0.2.1}/examples/movie_page/spirited-away.md +2 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/README.md +3 -3
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/canonicalize.py +3 -3
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/cli.py +53 -14
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/compile.py +5 -5
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/errors.py +2 -2
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/generate.py +30 -18
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/models.py +39 -2
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/schema_view.py +4 -4
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/soft_field.py +4 -4
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/validate.py +69 -18
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_cli.py +5 -20
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_core.py +41 -3
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_generate.py +40 -12
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_movie_page_example.py +26 -18
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_parity.py +3 -3
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_schema_view.py +1 -1
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_soft_field.py +7 -12
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_warning_codes.py +0 -5
- {softschema-0.1.4 → softschema-0.2.1}/packages/typescript/README.md +5 -5
- {softschema-0.1.4 → softschema-0.2.1}/skills/softschema/SKILL.md +10 -6
- {softschema-0.1.4 → softschema-0.2.1}/tests/golden/README.md +3 -3
- softschema-0.1.4/docs/installation.md +0 -74
- softschema-0.1.4/docs/softschema-spec.md +0 -260
- {softschema-0.1.4 → softschema-0.2.1}/.gitignore +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/LICENSE +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/docs/publishing-npm.md +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/examples/__init__.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/examples/movie_page/__init__.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/examples/movie_page/host_integration.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/examples/movie_page/model.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/examples/movie_page/movie-page.schema.yaml +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/examples/parity/__init__.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/examples/parity/model.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/examples/parity/parity.schema.yaml +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/__init__.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/py.typed +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/src/softschema/registry.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_canonicalize.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_doc_topics_resolve.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_enforced_extras.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_errors.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_metadata_rules.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/python/tests/test_skill_mirror_drift.py +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/packages/typescript/LICENSE +0 -0
- {softschema-0.1.4 → softschema-0.2.1}/pyproject.toml +0 -0
|
@@ -4,16 +4,16 @@ This repo teaches and implements the soft schema pattern.
|
|
|
4
4
|
|
|
5
5
|
Start here:
|
|
6
6
|
|
|
7
|
-
- [
|
|
7
|
+
- [softschema Guide](docs/softschema-guide.md): standalone concept and adoption guide
|
|
8
8
|
for humans and agents.
|
|
9
|
-
- [
|
|
10
|
-
- [Movie
|
|
9
|
+
- [softschema Spec](docs/softschema-spec.md): exact language-neutral artifact format.
|
|
10
|
+
- [Movie Page Example](examples/movie_page/README.md): complete Python-backed example.
|
|
11
11
|
|
|
12
12
|
softschema ships two interchangeable implementations with the same CLI and library
|
|
13
13
|
surface: Python/Pydantic (`softschema`, `softschema-py`) and TypeScript/Zod
|
|
14
14
|
(`softschema`, `softschema-ts`). They are held to exact behavioral parity: same flags,
|
|
15
|
-
same canonical JSON Schema
|
|
16
|
-
identical regardless of which you run.
|
|
15
|
+
same canonical compiled JSON Schema, same validation results, so authoring an artifact
|
|
16
|
+
is identical regardless of which you run.
|
|
17
17
|
|
|
18
18
|
For implementer reference (only when changing a package itself):
|
|
19
19
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: softschema
|
|
3
|
-
Version: 0.1
|
|
3
|
+
Version: 0.2.1
|
|
4
4
|
Summary: Soft schema conventions and validation tools for Markdown/YAML artifacts
|
|
5
5
|
Project-URL: Homepage, https://github.com/jlevy/softschema
|
|
6
6
|
Project-URL: Repository, https://github.com/jlevy/softschema
|
|
@@ -28,8 +28,24 @@ Description-Content-Type: text/markdown
|
|
|
28
28
|
|
|
29
29
|
# softschema
|
|
30
30
|
|
|
31
|
+
Soft schemas: gradual, practical validation for Markdown/YAML artifacts that mix prose
|
|
32
|
+
and structured data—built for humans and coding agents.
|
|
33
|
+
|
|
31
34
|
## Quick Start
|
|
32
35
|
|
|
36
|
+
Try it anywhere, with nothing installed but [uv](https://docs.astral.sh/uv/) or Node.
|
|
37
|
+
Print the bundled example artifact and its compiled schema, then validate—the artifact
|
|
38
|
+
is fully self-describing, so no flags are needed:
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
uvx softschema@latest docs example-artifact > spirited-away.md
|
|
42
|
+
uvx softschema@latest docs example-schema > movie-page.schema.yaml
|
|
43
|
+
uvx softschema@latest validate spirited-away.md
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
(Or `npx softschema@latest ...` for the Node implementation; the two are
|
|
47
|
+
interchangeable.)
|
|
48
|
+
|
|
33
49
|
To set up softschema in a repository with an agent, tell the agent:
|
|
34
50
|
|
|
35
51
|
> Run `uvx softschema@latest --help` (for the Python implementation) or
|
|
@@ -47,13 +63,13 @@ flexible document context and machine-readable values.
|
|
|
47
63
|
The idea is quite simple, but I’ve found it non-obvious enough that coding agents do not
|
|
48
64
|
come up with this approach themselves.
|
|
49
65
|
|
|
50
|
-
However if given the information and tools in this repo, soft schemas are unreasonably
|
|
66
|
+
However, if given the information and tools in this repo, soft schemas are unreasonably
|
|
51
67
|
effective. Agents become far better at designing and building complex workflows that mix
|
|
52
68
|
structured and unstructured data, such as document processing, data extraction,
|
|
53
69
|
scientific or financial analyses, and many similar applications.
|
|
54
70
|
|
|
55
71
|
**Soft schemas** are what we call the general practice.
|
|
56
|
-
**
|
|
72
|
+
**softschema** is the name of this repository’s Markdown-and-YAML spec and the matching
|
|
57
73
|
`softschema` CLI that implements it.
|
|
58
74
|
|
|
59
75
|
## How Do Soft Schemas Work?
|
|
@@ -135,60 +151,20 @@ Keeping prose and structured values in one artifact is more convenient and
|
|
|
135
151
|
context-efficient. A reader (human or agent) has only one place to look, and information
|
|
136
152
|
can stay as loose prose until a downstream consumer needs it in more formal schemas.
|
|
137
153
|
|
|
138
|
-
##
|
|
139
|
-
|
|
140
|
-
This repo is simply:
|
|
141
|
-
|
|
142
|
-
- A few documents for use by agents, including a [spec](docs/softschema-spec.md)
|
|
143
|
-
defining soft schema file format conventions for Markdown documents with YAML
|
|
144
|
-
frontmatter.
|
|
145
|
-
|
|
146
|
-
- A small CLI (and library) that handles formatting, compilation, validation, and other
|
|
147
|
-
common workflows on soft schema-style documents.
|
|
148
|
-
|
|
149
|
-
The CLI can be used directly, as a library, or installed as a skill.
|
|
150
|
-
|
|
151
|
-
For the full conceptual reference and adoption playbooks, see the
|
|
152
|
-
[Softschema Guide](docs/softschema-guide.md).
|
|
153
|
-
|
|
154
|
-
## Two Synchronized Implementations
|
|
155
|
-
|
|
156
|
-
softschema ships **two complete, fully supported implementations** with the same CLI and
|
|
157
|
-
library surface:
|
|
158
|
-
|
|
159
|
-
- **Python / Pydantic**: [`softschema`](docs/softschema-python-design.md) on PyPI (run
|
|
160
|
-
as `softschema` or `softschema-py`).
|
|
161
|
-
- **TypeScript / Zod**: [`softschema`](docs/softschema-typescript-design.md) on npm (run
|
|
162
|
-
as `softschema` or `softschema-ts`).
|
|
163
|
-
|
|
164
|
-
The TypeScript package is a **synchronized port** of the Python one, held to **exact
|
|
165
|
-
behavioral parity**: equivalent CLI inputs, outputs, and flags; equivalent library APIs;
|
|
166
|
-
the same canonical JSON Schema sidecar (content-identical, with an equal `schema_sha256`
|
|
167
|
-
fingerprint over its canonical JSON); and the same engine-neutral validation results.
|
|
168
|
-
Only idiomatic surface details differ (snake_case ↔ camelCase, Pydantic ↔ Zod).
|
|
169
|
-
Authoring or validating an artifact is identical regardless of which you run, so a team
|
|
170
|
-
can adopt either runtime, or both, without divergence.
|
|
171
|
-
|
|
172
|
-
The two are **maintained in lockstep**: every behavior change lands in a shared
|
|
173
|
-
golden-test corpus first, then in both packages, and CI fails if their outputs or
|
|
174
|
-
compiled schemas drift.
|
|
175
|
-
They release together under **the same version number** on PyPI and npm.
|
|
176
|
-
See
|
|
177
|
-
[Keeping Python and TypeScript in Parity](docs/development.md#keeping-python-and-typescript-in-parity)
|
|
178
|
-
for the development process and the parity invariants CI enforces, and
|
|
179
|
-
[Publishing](https://github.com/jlevy/softschema/blob/main/docs/publishing.md) for the
|
|
180
|
-
synchronized release.
|
|
181
|
-
|
|
182
|
-
## Example Artifact Shape
|
|
154
|
+
## The Artifact Shape
|
|
183
155
|
|
|
184
156
|
The default shape is Markdown with YAML frontmatter.
|
|
185
|
-
|
|
157
|
+
The `softschema:` block is the self-description quartet: `contract` names the payload
|
|
158
|
+
contract, `schema` points at the compiled JSON Schema (relative to the document),
|
|
159
|
+
`envelope` names the payload key, and `status` sets validation strictness:
|
|
186
160
|
|
|
187
161
|
```markdown
|
|
188
162
|
---
|
|
189
163
|
title: Spirited Away (2001)
|
|
190
164
|
softschema:
|
|
191
165
|
contract: example.movies:MoviePage/v1
|
|
166
|
+
schema: movie-page.schema.yaml
|
|
167
|
+
envelope: movie
|
|
192
168
|
status: enforced
|
|
193
169
|
movie:
|
|
194
170
|
title: Spirited Away
|
|
@@ -197,153 +173,108 @@ movie:
|
|
|
197
173
|
mpaa_rating: PG
|
|
198
174
|
directors:
|
|
199
175
|
- Hayao Miyazaki
|
|
200
|
-
genres:
|
|
201
|
-
- Animation
|
|
202
|
-
- Adventure
|
|
203
|
-
- Family
|
|
204
|
-
synopsis: >
|
|
205
|
-
Ten-year-old Chihiro and her parents stumble into a mysterious abandoned town
|
|
206
|
-
that turns out to be a spirit world. After her parents are transformed into pigs,
|
|
207
|
-
Chihiro must take a job in a magical bathhouse run by the witch Yubaba and find a
|
|
208
|
-
way to break the spell so the family can return home.
|
|
209
|
-
cast:
|
|
210
|
-
- actor: Rumi Hiiragi
|
|
211
|
-
character: Chihiro / Sen
|
|
212
|
-
- actor: Miyu Irino
|
|
213
|
-
character: Haku
|
|
214
|
-
- actor: Mari Natsuki
|
|
215
|
-
character: Yubaba
|
|
176
|
+
genres: [Animation, Adventure, Family]
|
|
216
177
|
ratings:
|
|
217
|
-
rotten_tomatoes:
|
|
218
|
-
critics_percent: 96
|
|
219
|
-
audience_percent: 96
|
|
220
|
-
critic_review_count: 225
|
|
221
178
|
imdb:
|
|
222
179
|
score: 8.6
|
|
223
180
|
total_votes: 850000
|
|
224
181
|
---
|
|
225
182
|
# Spirited Away (2001)
|
|
226
183
|
|
|
227
|
-
*Spirited Away* is Hayao Miyazaki
|
|
184
|
+
*Spirited Away* is Hayao Miyazaki's animated fantasy about ten-year-old Chihiro, who
|
|
228
185
|
slips into a spirit world and takes a job in a bathhouse for the gods to free her
|
|
229
186
|
parents from the witch Yubaba.
|
|
230
187
|
It won the 2003 Academy Award for Best Animated Feature.
|
|
231
|
-
|
|
232
|
-
Rotten Tomatoes shows a 96% Tomatometer from 225 critic reviews and a 96% Popcornmeter
|
|
233
|
-
from the audience; IMDb users give it 8.6 out of 10 across more than 850,000 votes.
|
|
234
|
-
|
|
235
|
-
<!-- The reader-facing body continues with prose and tables; see the full example. -->
|
|
236
188
|
```
|
|
237
189
|
|
|
238
190
|
The YAML payload is authoritative; a consumer reads it.
|
|
239
191
|
The Markdown body overlaps with it but is for human readers: the prose adds context like
|
|
240
|
-
the film’s Academy Award (which no structured field carries), the
|
|
241
|
-
|
|
242
|
-
some YAML fields as tables for the reader’s convenience.
|
|
192
|
+
the film’s Academy Award (which no structured field carries), and the full example’s
|
|
193
|
+
body mirrors some YAML fields as tables for the reader’s convenience.
|
|
243
194
|
|
|
244
|
-
Only the `softschema` block and the
|
|
195
|
+
Only the `softschema` block and the declared envelope key (`movie:` above) are
|
|
245
196
|
softschema’s concern.
|
|
246
|
-
Additional top-level frontmatter keys, such as the `title:` above (or
|
|
247
|
-
`
|
|
248
|
-
|
|
197
|
+
Additional top-level frontmatter keys, such as the `title:` above (or `description:`,
|
|
198
|
+
`tags:`, or any other host-specific metadata), are a separate concern: softschema
|
|
199
|
+
neither forbids nor interprets them, so an artifact can coexist with whatever
|
|
249
200
|
frontmatter conventions a static-site generator, doc indexer, or other tool already
|
|
250
|
-
expects.
|
|
251
|
-
|
|
252
|
-
registered contract) to designate the payload.
|
|
253
|
-
|
|
254
|
-
The example illustrates the structural variety a softschema artifact can carry:
|
|
255
|
-
constrained integers (`release_year`, `runtime_minutes`), an enum (`mpaa_rating`
|
|
256
|
-
restricted to `G`, `PG`, `PG-13`, `R`, `NC-17`, `NR`), lists of strings (`directors`,
|
|
257
|
-
`genres`), a list of structured records (`cast`), and nested objects (`ratings`). The
|
|
258
|
-
full artifact, model, and generated JSON Schema live under
|
|
259
|
-
[examples/movie_page/](examples/movie_page/README.md).
|
|
260
|
-
|
|
261
|
-
## Contract IDs
|
|
262
|
-
|
|
263
|
-
Recommended style:
|
|
264
|
-
|
|
265
|
-
```text
|
|
266
|
-
namespace:UpperCamelCaseName/version
|
|
267
|
-
```
|
|
268
|
-
|
|
269
|
-
Examples:
|
|
270
|
-
|
|
271
|
-
- `example.movies:MoviePage/v1`
|
|
272
|
-
- `example.docs:IncidentReview/v1`
|
|
273
|
-
- `com.acme.docs:IncidentReview/1.0`
|
|
201
|
+
expects. Because the artifact declares `envelope: movie`, validation still needs no
|
|
202
|
+
flags.
|
|
274
203
|
|
|
275
|
-
|
|
204
|
+
Every key after `contract` is optional; a minimal artifact carries `contract` alone and
|
|
205
|
+
binds its schema some other way (a `--schema` flag, or a host registry in library use).
|
|
206
|
+
Contract IDs follow an enforced shape, `[namespace:]Name[/version]`—for example
|
|
207
|
+
`example.movies:MoviePage/v1` or `com.acme.docs:IncidentReview/1.0`—naming a payload
|
|
208
|
+
contract, not a class or import path.
|
|
276
209
|
|
|
277
|
-
##
|
|
210
|
+
## Validate
|
|
278
211
|
|
|
279
|
-
|
|
212
|
+
A self-describing artifact validates with no flags; flags override the document when you
|
|
213
|
+
need to point a run elsewhere:
|
|
280
214
|
|
|
281
215
|
```bash
|
|
282
|
-
|
|
216
|
+
softschema validate doc.md # uses the document's bindings
|
|
217
|
+
softschema validate doc.md --schema candidate.schema.yaml # try a different schema
|
|
218
|
+
softschema validate doc.md --envelope incident # designate the payload key
|
|
283
219
|
```
|
|
284
220
|
|
|
285
|
-
|
|
221
|
+
`validate` reports structural (JSON Schema) and semantic (Pydantic/Zod model) results
|
|
222
|
+
separately as deterministic JSON. Semantic validation loads a model with
|
|
223
|
+
`--model module:Class` (Python) or `--model path:export` (Zod)—note that `--model`
|
|
224
|
+
imports and executes local code, so use it only with trusted models; a compiled schema
|
|
225
|
+
via `--schema` executes nothing and is the safe path for untrusted input.
|
|
286
226
|
|
|
287
|
-
|
|
288
|
-
uv run softschema validate examples/movie_page/spirited-away.md \
|
|
289
|
-
--model examples.movie_page.model:MoviePage \
|
|
290
|
-
--schema examples/movie_page/movie-page.schema.yaml \
|
|
291
|
-
--envelope movie
|
|
292
|
-
```
|
|
227
|
+
## Install
|
|
293
228
|
|
|
294
|
-
|
|
295
|
-
`--envelope movie` designates the payload key, which the example needs because the
|
|
296
|
-
artifact also carries a top-level `title:` that softschema does not interpret.
|
|
297
|
-
When an artifact has exactly one non-`softschema` top-level key, that key is inferred as
|
|
298
|
-
the envelope automatically and `--envelope` is unnecessary.
|
|
299
|
-
`--contract` and `--status` override the corresponding `softschema:` fields.
|
|
229
|
+
Two supported ways to consume softschema; pick by use:
|
|
300
230
|
|
|
301
|
-
|
|
231
|
+
- **Pin it as a dependency** for projects, CI gates, and library use (reproducible,
|
|
232
|
+
fast, offline, and the only way to `import` it):
|
|
302
233
|
|
|
303
|
-
```bash
|
|
304
|
-
uv
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
uv run softschema docs example-artifact
|
|
308
|
-
uv run softschema skill --brief
|
|
309
|
-
```
|
|
234
|
+
```bash
|
|
235
|
+
uv add --dev softschema==0.2.1 # Python
|
|
236
|
+
npm install -D softschema@0.2.1 # Node (or: bun add -d)
|
|
237
|
+
```
|
|
310
238
|
|
|
311
|
-
|
|
312
|
-
human can copy from them, but it does not scaffold or mutate another project.
|
|
239
|
+
- **Zero-install** for one-off checks and agent bootstrap:
|
|
313
240
|
|
|
314
|
-
|
|
241
|
+
```bash
|
|
242
|
+
uvx softschema@latest --help
|
|
243
|
+
npx softschema@latest --help
|
|
244
|
+
```
|
|
315
245
|
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
```
|
|
246
|
+
The rule of thumb: if softschema runs more than once, or in CI, or you import it—pin it.
|
|
247
|
+
For a quick check or an agent bootstrapping with nothing installed, use a zero-install
|
|
248
|
+
runner. See [Installation](docs/installation.md) for details, including the supply-chain
|
|
249
|
+
cool-off that makes `@latest` safe to recommend.
|
|
321
250
|
|
|
322
|
-
##
|
|
251
|
+
## Use as a Library
|
|
323
252
|
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
pinned zero-install runner:
|
|
253
|
+
Both packages expose the same surface (idiomatic per language).
|
|
254
|
+
Register contracts at startup and validate at file boundaries:
|
|
327
255
|
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
256
|
+
```python
|
|
257
|
+
from pathlib import Path
|
|
258
|
+
from softschema import Contract, Contracts, validate_artifact
|
|
259
|
+
|
|
260
|
+
registry = Contracts()
|
|
261
|
+
registry.register(Contract(id="mycorp.docs:IncidentReview/v1", model=IncidentReview,
|
|
262
|
+
envelope_key="incident"))
|
|
263
|
+
result = validate_artifact(Path("incident.md"),
|
|
264
|
+
contract_id="mycorp.docs:IncidentReview/v1",
|
|
265
|
+
registry=registry)
|
|
332
266
|
```
|
|
333
267
|
|
|
334
|
-
|
|
268
|
+
```ts
|
|
269
|
+
import { validateArtifact } from "softschema";
|
|
335
270
|
|
|
336
|
-
|
|
337
|
-
npx softschema@latest docs --list
|
|
338
|
-
npx softschema@latest docs guide
|
|
339
|
-
npx softschema@latest skill --brief
|
|
271
|
+
const result = validateArtifact("incident.md", contract);
|
|
340
272
|
```
|
|
341
273
|
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
See the [
|
|
346
|
-
shape and the full Python ↔ TypeScript API table.
|
|
274
|
+
A host registry’s bindings outrank the document’s own (`softschema.schema`/`envelope`),
|
|
275
|
+
so a document cannot silently redirect a host’s validation; a contract registered
|
|
276
|
+
without a schema path lets self-describing documents bind themselves.
|
|
277
|
+
See the [softschema Guide](docs/softschema-guide.md) for the full playbooks.
|
|
347
278
|
|
|
348
279
|
## Use as an Agent Skill
|
|
349
280
|
|
|
@@ -382,31 +313,40 @@ uvx softschema@latest skill --install
|
|
|
382
313
|
Both mirrors carry a `DO NOT EDIT` marker.
|
|
383
314
|
Re-run `skill --install` to refresh after upgrading the CLI.
|
|
384
315
|
|
|
385
|
-
##
|
|
316
|
+
## Two Synchronized Implementations
|
|
386
317
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
tests/golden/ shared CLI golden corpus, run against both implementations
|
|
395
|
-
```
|
|
318
|
+
softschema ships **two complete, fully supported implementations** with the same CLI and
|
|
319
|
+
library surface:
|
|
320
|
+
|
|
321
|
+
- **Python / Pydantic**: [`softschema`](docs/softschema-python-design.md) on PyPI (run
|
|
322
|
+
as `softschema` or `softschema-py`).
|
|
323
|
+
- **TypeScript / Zod**: [`softschema`](docs/softschema-typescript-design.md) on npm (run
|
|
324
|
+
as `softschema` or `softschema-ts`).
|
|
396
325
|
|
|
397
|
-
The
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
326
|
+
The two are held to **exact behavioral parity**: equivalent CLI inputs, outputs, and
|
|
327
|
+
flags; equivalent library APIs; the same canonical compiled JSON Schema
|
|
328
|
+
(content-identical, with an equal `schema_sha256` fingerprint); and the same
|
|
329
|
+
engine-neutral validation results.
|
|
330
|
+
Every behavior change lands in a shared golden-test corpus first, then in both packages,
|
|
331
|
+
and CI fails if their outputs or compiled schemas drift.
|
|
332
|
+
They release together under the same version number on PyPI and npm.
|
|
401
333
|
|
|
402
|
-
##
|
|
334
|
+
## Further Reading
|
|
335
|
+
|
|
336
|
+
- [softschema Guide](docs/softschema-guide.md): the full mental model and adoption
|
|
337
|
+
playbooks.
|
|
338
|
+
- [softschema Spec](docs/softschema-spec.md): the exact artifact format and validation
|
|
339
|
+
rules.
|
|
340
|
+
- [Movie Page Example](examples/movie_page/README.md): the complete example backing the
|
|
341
|
+
snippets above.
|
|
342
|
+
- [Installation](docs/installation.md): pinned vs zero-install, uv and Node setup.
|
|
403
343
|
|
|
404
|
-
|
|
405
|
-
release workflow, and pointers to the installation and publishing docs.
|
|
344
|
+
## Development and Contributing
|
|
406
345
|
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
346
|
+
Repo setup, common commands, CI checks, the parity process, and the release workflow
|
|
347
|
+
live in [Development](docs/development.md).
|
|
348
|
+
The Python and TypeScript implementations must be kept in exact sync: any behavior
|
|
349
|
+
change goes through the shared golden corpus first and then lands in both packages.
|
|
410
350
|
|
|
411
351
|
<!-- This document follows common-doc-guidelines.md.
|
|
412
352
|
See github.com/jlevy/practical-prose and review guidelines before editing.
|