@sumrco/cli 0.3.0 → 0.3.1
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.
- package/ai/modules/kontract/resources/api-generation-standards.rf.md +83 -0
- package/ai/modules/kontract/resources/{configuration.rf.md → authoring/configuration.rf.md} +49 -11
- package/ai/modules/kontract/resources/authoring/design-profile/api-styles.rf.md +241 -0
- package/ai/modules/kontract/resources/authoring/design-profile/async-styles.rf.md +134 -0
- package/ai/modules/kontract/resources/authoring/design-profile/overview.md +64 -0
- package/ai/modules/kontract/resources/authoring/design-profile/schema-layout-styles.rf.md +356 -0
- package/ai/modules/kontract/resources/authoring/overview.md +56 -0
- package/ai/modules/kontract/resources/{schema-reuse.rf.md → authoring/schema-reuse.rf.md} +222 -46
- package/ai/modules/kontract/resources/{scope-and-splitting.rf.md → authoring/scope-and-splitting.rf.md} +113 -57
- package/ai/modules/kontract/resources/authoring/spec-layout.rf.md +492 -0
- package/ai/modules/kontract/resources/authoring/team-members/spec-author.tm.md +77 -0
- package/ai/modules/kontract/resources/{workflows/contract-change.wf.md → authoring/workflows/spec-change.wf.md} +21 -15
- package/ai/modules/kontract/resources/generated-output.rf.md +19 -14
- package/ai/modules/kontract/resources/openapi-sdk-generator-research.rf.md +17 -19
- package/ai/modules/kontract/resources/overview.md +115 -82
- package/ai/modules/kontract/resources/performance.rf.md +7 -7
- package/ai/modules/kontract/sumr.module.yaml +3 -0
- package/ai/modules/mission/sumr.module.yaml +6 -0
- package/ai/modules/playbook/resources/authoring/content-structure.rf.md +1 -1
- package/ai/modules/playbook/resources/authoring/cross-referencing.rf.md +1 -1
- package/ai/modules/playbook/resources/authoring/descriptions.rf.md +1 -1
- package/ai/modules/playbook/resources/authoring/extraction.rf.md +1 -1
- package/ai/modules/playbook/resources/authoring/flows.rf.md +1 -1
- package/ai/modules/playbook/resources/authoring/folder-structure.rf.md +1 -1
- package/ai/modules/playbook/resources/authoring/frontmatter.rf.md +4 -1
- package/ai/modules/playbook/resources/authoring/markdown.rf.md +1 -1
- package/ai/modules/playbook/resources/authoring/overview.md +1 -1
- package/ai/modules/playbook/resources/team-members/{playbook-technical-writer.tm.md → technical-writer.tm.md} +3 -2
- package/ai/modules/playbook/sumr.module.yaml +7 -2
- package/index.js +332 -276
- package/package.json +1 -1
- package/ai/modules/kontract/resources/language-sdk-generator-extension.rf.md +0 -62
- package/ai/modules/kontract/resources/openapi-generator-lessons.rf.md +0 -61
- package/ai/modules/kontract/resources/spec-layout.rf.md +0 -275
- package/ai/modules/kontract/resources/team-members/contract-author.tm.md +0 -60
|
@@ -0,0 +1,492 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: reference
|
|
3
|
+
name: spec-layout
|
|
4
|
+
title: Spec File Layout
|
|
5
|
+
description: "Required folder and file conventions for Kontract API and async schema source files."
|
|
6
|
+
label: Spec Layout
|
|
7
|
+
when: Creating or moving API spec files, adding a shared base spec, or debugging why a spec is not picked up
|
|
8
|
+
order: 10
|
|
9
|
+
---
|
|
10
|
+
|
|
11
|
+
# Spec File Layout
|
|
12
|
+
|
|
13
|
+
Kontract discovers specs by filename convention under the configured schema
|
|
14
|
+
directory (default `schema/`).
|
|
15
|
+
|
|
16
|
+
```text
|
|
17
|
+
schema/
|
|
18
|
+
recipes.api.yml ← one independent API schema doc per service/surface
|
|
19
|
+
recipes.async.yml ← one independent async schema doc per surface, when messaging exists
|
|
20
|
+
shared/
|
|
21
|
+
enums.yml ← repo-level shared enums/scalars promoted after reuse
|
|
22
|
+
errors.yml ← repo-level shared API components promoted after reuse
|
|
23
|
+
pagination.yml ← repo-level shared API components promoted after reuse
|
|
24
|
+
base.yml ← shared components, referenced via $ref
|
|
25
|
+
bookstore/
|
|
26
|
+
bookstore.api.yml ← simple API schema root entrypoint
|
|
27
|
+
bookstore.async.yml ← async schema root entrypoint only when messaging exists
|
|
28
|
+
catalog.api.yml ← optional API schema sub-area grouped under bookstore
|
|
29
|
+
events.async.yml ← optional async schema surface grouped under bookstore
|
|
30
|
+
shared/
|
|
31
|
+
enums.yml ← capability-local components promoted after reuse
|
|
32
|
+
components.yml ← capability-local components promoted after reuse
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
## Rules
|
|
36
|
+
|
|
37
|
+
- API schema specs end in `*.api.yml` / `*.api.yaml`.
|
|
38
|
+
- async schema specs end in `*.async.yml` / `*.async.yaml`.
|
|
39
|
+
- Public source files declare `api: <version>` or `async: <version>`.
|
|
40
|
+
Kontract normalizes those markers to the internal format required by its
|
|
41
|
+
validators and bundlers.
|
|
42
|
+
- Discovery is recursive; `base.yml` is skipped as an entry point.
|
|
43
|
+
- Service output paths mirror nested spec paths under the configured source
|
|
44
|
+
input directory. Moving a root spec is therefore a generated namespace/import
|
|
45
|
+
migration, not only a documentation cleanup.
|
|
46
|
+
- A root `*.api.yml` or `*.async.yml` may reference plain `.yml`
|
|
47
|
+
fragments for paths, messages, parameters, and schemas. Kontract bundles the
|
|
48
|
+
root before generation when it finds external `$ref` links.
|
|
49
|
+
- Do not infer async schema files from an API-only repo. Only produce async schema
|
|
50
|
+
roots, channels, message folders, or NATS examples when the repo has async schema
|
|
51
|
+
sources/targets or the user asks for messaging contracts.
|
|
52
|
+
- Do not split a simple API schema root into `paths/` fragments by default. Start
|
|
53
|
+
with one focused root file and local `components.schemas`; use fragments only
|
|
54
|
+
when the root is too large, mixes independently owned surfaces, or repeats
|
|
55
|
+
component definitions.
|
|
56
|
+
- API schema and async schema roots may share model fragments only when the
|
|
57
|
+
shapes mean the same thing for HTTP and messaging. This is most common for
|
|
58
|
+
enums, scalar value objects, IDs, slugs, and shared payload fields. Keep
|
|
59
|
+
protocol-specific path, operation, parameter, response, channel, and message
|
|
60
|
+
metadata in separate fragments.
|
|
61
|
+
- Nested `*.api.yml` files are grouped by their first folder. This supports a
|
|
62
|
+
product-capability layout where the folder owns the contract package and each
|
|
63
|
+
file is a focused API surface:
|
|
64
|
+
|
|
65
|
+
```text
|
|
66
|
+
schema/
|
|
67
|
+
recipes/
|
|
68
|
+
catalog.api.yml ← API schema
|
|
69
|
+
publishing.async.yml ← async schema
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
Both files generate under `contracts/recipes/`.
|
|
73
|
+
- Use `folder/folder.api.yml` for a simple product capability root that
|
|
74
|
+
should generate under the folder namespace, for example
|
|
75
|
+
`schema/bookstore/bookstore.api.yml` generates under `contracts/bookstore/`.
|
|
76
|
+
- Do not confuse resource-area fragments inside a product-capability folder with
|
|
77
|
+
a repo-wide `by-resource-area` schema layout style. For example,
|
|
78
|
+
`schema/recipes/paths/ingredients.yml` is still a `recipes` capability
|
|
79
|
+
fragment, not a top-level `ingredients` resource-area root. Use
|
|
80
|
+
`design-profile/schema-layout-styles.rf.md` for canonical layout trees
|
|
81
|
+
before recommending file moves.
|
|
82
|
+
- Use nested capability/surface paths when one root file would mix independently
|
|
83
|
+
owned API surfaces; see the scope and splitting reference for line-count
|
|
84
|
+
thresholds and naming rules.
|
|
85
|
+
- Use comments only as editor navigation markers. Use uppercase noun labels such
|
|
86
|
+
as `CATALOG PATHS`, `COMPONENTS`, or `RESPONSE SCHEMAS`; they must
|
|
87
|
+
not explain endpoint behavior or replace `summary` / `description`.
|
|
88
|
+
When a root file has both `paths:` and `components:`, add a short visual
|
|
89
|
+
marker before `components:` too so the components block is easy to find.
|
|
90
|
+
- Keep schemas in the owning root or surface first. Promote a schema to a
|
|
91
|
+
capability-local `shared/` folder only when multiple surfaces in that
|
|
92
|
+
capability reuse the same product concept. Promote it again to
|
|
93
|
+
`schema/shared/` only when multiple capabilities share the same meaning and
|
|
94
|
+
owner.
|
|
95
|
+
- Share promoted schemas through `$ref` into `base.yml`, `schema/shared/`, or a
|
|
96
|
+
capability-local `shared/` folder when the meaning is identical. Do **not**
|
|
97
|
+
duplicate schemas across specs and do **not** merge by hand-mutating parsed
|
|
98
|
+
JSON.
|
|
99
|
+
- Prefer `schema/shared/` only for cross-capability components such as common
|
|
100
|
+
parameters, error responses, pagination, scalar constraints, response envelope
|
|
101
|
+
fragments, schedules, and reusable config objects with stable semantics.
|
|
102
|
+
- The async contract namespace comes from the async schema `info.title`, not the filename —
|
|
103
|
+
set `info.title` deliberately.
|
|
104
|
+
- Multi-file specs are bundled automatically; keep `$ref` paths repo-relative.
|
|
105
|
+
|
|
106
|
+
## Protocol scenarios
|
|
107
|
+
|
|
108
|
+
Choose the protocol scenario first. Then apply the selected
|
|
109
|
+
`schemaLayoutStyle`.
|
|
110
|
+
|
|
111
|
+
| Scenario | Use when | Shareable pieces |
|
|
112
|
+
|---|---|---|
|
|
113
|
+
| API-only | The repo only defines HTTP contracts. | HTTP components, parameters, responses, request/response schemas. |
|
|
114
|
+
| async-only | The repo only defines messaging contracts. | Message payload schemas, message enums, scalar value objects. |
|
|
115
|
+
| API + async | The repo defines both HTTP and messaging contracts. | Neutral components with identical meaning, especially enums, IDs, slugs, scalars, and shared payload objects. |
|
|
116
|
+
|
|
117
|
+
Do not share protocol layers. API schema paths, parameters, request bodies,
|
|
118
|
+
responses, and async schema channels, operations, and messages stay in their own
|
|
119
|
+
files.
|
|
120
|
+
|
|
121
|
+
## API-only layout
|
|
122
|
+
|
|
123
|
+
For a simple API-only repo, prefer one focused root file per product
|
|
124
|
+
capability, API surface, resource area, workflow, or service owner. Do not add
|
|
125
|
+
`*.async.yml`, `messages/`, or channel examples unless messaging is part of
|
|
126
|
+
the actual contract.
|
|
127
|
+
|
|
128
|
+
```text
|
|
129
|
+
schema/
|
|
130
|
+
bookstore/
|
|
131
|
+
bookstore.api.yml # simple API schema root entrypoint
|
|
132
|
+
shared/ # only if multiple bookstore surfaces reuse it
|
|
133
|
+
enums.yml
|
|
134
|
+
orders/
|
|
135
|
+
main.api.yml # api: 3.0.3; grouped under orders/http
|
|
136
|
+
public.api.yml
|
|
137
|
+
lifecycle.api.yml
|
|
138
|
+
shared/ # capability-local promoted components only
|
|
139
|
+
enums.yml
|
|
140
|
+
components.yml
|
|
141
|
+
shared/ # cross-capability promoted components only
|
|
142
|
+
errors.yml
|
|
143
|
+
pagination.yml
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
```yaml
|
|
147
|
+
# schema/bookstore/bookstore.api.yml
|
|
148
|
+
api: 3.0.3
|
|
149
|
+
info:
|
|
150
|
+
title: Bookstore API
|
|
151
|
+
version: 1.0.0
|
|
152
|
+
paths:
|
|
153
|
+
/books:
|
|
154
|
+
get:
|
|
155
|
+
operationId: listBooks
|
|
156
|
+
summary: List books
|
|
157
|
+
responses:
|
|
158
|
+
"200":
|
|
159
|
+
description: Paginated book list.
|
|
160
|
+
content:
|
|
161
|
+
application/json:
|
|
162
|
+
schema:
|
|
163
|
+
$ref: "#/components/schemas/BookPage"
|
|
164
|
+
# ----- COMPONENTS ---------------------------------------------------------
|
|
165
|
+
components:
|
|
166
|
+
securitySchemes:
|
|
167
|
+
bearerAuth:
|
|
168
|
+
$ref: ../shared/security.yml#/securitySchemes/bearerAuth
|
|
169
|
+
schemas:
|
|
170
|
+
Book:
|
|
171
|
+
type: object
|
|
172
|
+
required: [id, title]
|
|
173
|
+
properties:
|
|
174
|
+
id:
|
|
175
|
+
type: string
|
|
176
|
+
format: uuid
|
|
177
|
+
title:
|
|
178
|
+
type: string
|
|
179
|
+
minLength: 1
|
|
180
|
+
BookPage:
|
|
181
|
+
type: object
|
|
182
|
+
required: [items]
|
|
183
|
+
properties:
|
|
184
|
+
items:
|
|
185
|
+
type: array
|
|
186
|
+
items:
|
|
187
|
+
$ref: "#/components/schemas/Book"
|
|
188
|
+
page:
|
|
189
|
+
$ref: ../shared/pagination.yml#/PageInfo
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
Use the `*.api.yml` suffix when one product-capability folder should
|
|
193
|
+
group several API schema surfaces into one generated package:
|
|
194
|
+
|
|
195
|
+
```text
|
|
196
|
+
schema/
|
|
197
|
+
orders/
|
|
198
|
+
main.api.yml # api: 3.0.3; generates under orders/http
|
|
199
|
+
public.api.yml # api: 3.0.3; generates under orders/http
|
|
200
|
+
lifecycle.api.yml # api: 3.0.3; generates under orders/http
|
|
201
|
+
shared/
|
|
202
|
+
enums.yml # promoted only after more than one surface needs it
|
|
203
|
+
components.yml
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
Keep this layout until a real split trigger appears. A simple API schema spec does
|
|
207
|
+
not need a `paths/` directory only because Kontract supports multi-file specs.
|
|
208
|
+
Also do not move every component into `shared/` preemptively. Local components
|
|
209
|
+
are the default; shared files are a promotion step after real reuse appears.
|
|
210
|
+
|
|
211
|
+
## async-only layout
|
|
212
|
+
|
|
213
|
+
For an async-only repo, prefer one focused messaging root per product
|
|
214
|
+
capability, API surface, workflow, service owner, or message family. Do not add
|
|
215
|
+
API schema roots or `paths/` folders unless HTTP contracts are part of the repo.
|
|
216
|
+
|
|
217
|
+
```text
|
|
218
|
+
schema/
|
|
219
|
+
shared/
|
|
220
|
+
message-enums.yml
|
|
221
|
+
bookstore/
|
|
222
|
+
bookstore.async.yml # async schema root entrypoint
|
|
223
|
+
messages/
|
|
224
|
+
book-commands.yml # channels, operations, messages
|
|
225
|
+
book-events.yml
|
|
226
|
+
models/
|
|
227
|
+
books.yml # message payload schemas
|
|
228
|
+
enums.yml # capability-local message enums
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
```yaml
|
|
232
|
+
# schema/bookstore/bookstore.async.yml
|
|
233
|
+
async: 3.0.0
|
|
234
|
+
info:
|
|
235
|
+
title: Bookstore
|
|
236
|
+
version: 1.0.0
|
|
237
|
+
channels:
|
|
238
|
+
reserveBook:
|
|
239
|
+
$ref: ./messages/book-commands.yml#/channels/reserveBook
|
|
240
|
+
operations:
|
|
241
|
+
reserveBook:
|
|
242
|
+
$ref: ./messages/book-commands.yml#/operations/reserveBook
|
|
243
|
+
# ----- COMPONENTS ---------------------------------------------------------
|
|
244
|
+
components:
|
|
245
|
+
messages:
|
|
246
|
+
ReserveBookCommand:
|
|
247
|
+
$ref: ./messages/book-commands.yml#/messages/ReserveBookCommand
|
|
248
|
+
schemas:
|
|
249
|
+
ReserveBookPayload:
|
|
250
|
+
$ref: ./models/books.yml#/ReserveBookPayload
|
|
251
|
+
BookFormat:
|
|
252
|
+
$ref: ./models/enums.yml#/BookFormat
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
## API + async with shared components
|
|
256
|
+
|
|
257
|
+
When a repo has both protocols, keep the roots and protocol-specific layers
|
|
258
|
+
separate. Share only components with identical semantics across both
|
|
259
|
+
protocols. In practice that usually means enums, scalar value objects, IDs,
|
|
260
|
+
slugs, and carefully named payload objects.
|
|
261
|
+
|
|
262
|
+
```text
|
|
263
|
+
schema/
|
|
264
|
+
bookstore/
|
|
265
|
+
bookstore.api.yml # HTTP root
|
|
266
|
+
bookstore.async.yml # messaging root
|
|
267
|
+
paths/
|
|
268
|
+
books.yml # API schema Path Item fragments
|
|
269
|
+
messages/
|
|
270
|
+
books.yml # async schema channels, operations, messages
|
|
271
|
+
models/
|
|
272
|
+
books.yml # payload schemas
|
|
273
|
+
enums.yml # shared enums used by both protocols
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
Do not put API schema paths, parameters, responses, async schema channels, operations,
|
|
277
|
+
or messages into shared model files.
|
|
278
|
+
|
|
279
|
+
## Split root-entrypoint layout
|
|
280
|
+
|
|
281
|
+
Use this layout when one product capability should generate as one contract
|
|
282
|
+
package, but the root files are getting too large:
|
|
283
|
+
|
|
284
|
+
```text
|
|
285
|
+
schema/
|
|
286
|
+
bookstore/
|
|
287
|
+
bookstore.api.yml
|
|
288
|
+
components/
|
|
289
|
+
parameters.yml
|
|
290
|
+
paths/
|
|
291
|
+
books.yml
|
|
292
|
+
authors.yml
|
|
293
|
+
models/
|
|
294
|
+
shared.yml
|
|
295
|
+
books.yml
|
|
296
|
+
authors.yml
|
|
297
|
+
```
|
|
298
|
+
|
|
299
|
+
If the same capability also owns messaging contracts, add the async schema root and
|
|
300
|
+
message fragments explicitly:
|
|
301
|
+
|
|
302
|
+
```text
|
|
303
|
+
schema/
|
|
304
|
+
bookstore/
|
|
305
|
+
bookstore.async.yml
|
|
306
|
+
messages/
|
|
307
|
+
books.yml
|
|
308
|
+
authors.yml
|
|
309
|
+
```
|
|
310
|
+
|
|
311
|
+
The root files stay small and readable. Fragment files are plain `.yml` because
|
|
312
|
+
they are not standalone API schema or async schema documents.
|
|
313
|
+
|
|
314
|
+
If a root file needs many visual section markers to stay readable, split the
|
|
315
|
+
internals into capability/surface fragments before adding more comments.
|
|
316
|
+
For API schema path fragments, prefer one Path Item Object per file so the root can
|
|
317
|
+
reference `./paths/books.yml` directly. Only use JSON Pointer paths such as
|
|
318
|
+
`#/paths/~1books` when a single fragment intentionally contains a full `paths:`
|
|
319
|
+
map with several paths.
|
|
320
|
+
|
|
321
|
+
```yaml
|
|
322
|
+
# schema/bookstore/bookstore.api.yml
|
|
323
|
+
api: 3.0.3
|
|
324
|
+
info:
|
|
325
|
+
title: Bookstore Contracts
|
|
326
|
+
version: 1.0.0
|
|
327
|
+
paths:
|
|
328
|
+
/books:
|
|
329
|
+
$ref: ./paths/books.yml
|
|
330
|
+
# ----- COMPONENTS ---------------------------------------------------------
|
|
331
|
+
components:
|
|
332
|
+
schemas:
|
|
333
|
+
Book:
|
|
334
|
+
$ref: ./models/books.yml#/Book
|
|
335
|
+
PaginatedBooks:
|
|
336
|
+
$ref: ./models/books.yml#/PaginatedBooks
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
```yaml
|
|
340
|
+
# schema/bookstore/paths/books.yml
|
|
341
|
+
get:
|
|
342
|
+
operationId: listBooks
|
|
343
|
+
responses:
|
|
344
|
+
"200":
|
|
345
|
+
description: Paginated book list.
|
|
346
|
+
content:
|
|
347
|
+
application/json:
|
|
348
|
+
schema:
|
|
349
|
+
$ref: ../models/books.yml#/PaginatedBooks
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
```yaml
|
|
353
|
+
# schema/bookstore/bookstore.async.yml
|
|
354
|
+
async: 3.0.0
|
|
355
|
+
info:
|
|
356
|
+
title: Bookstore
|
|
357
|
+
version: 1.0.0
|
|
358
|
+
channels:
|
|
359
|
+
listBooks:
|
|
360
|
+
$ref: ./messages/books.yml#/channels/listBooks
|
|
361
|
+
listBooksReply:
|
|
362
|
+
$ref: ./messages/books.yml#/channels/listBooksReply
|
|
363
|
+
operations:
|
|
364
|
+
listBooks:
|
|
365
|
+
$ref: ./messages/books.yml#/operations/listBooks
|
|
366
|
+
# ----- COMPONENTS ---------------------------------------------------------
|
|
367
|
+
components:
|
|
368
|
+
messages:
|
|
369
|
+
ListBooksQuery:
|
|
370
|
+
$ref: ./messages/books.yml#/messages/ListBooksQuery
|
|
371
|
+
PaginatedBooksReply:
|
|
372
|
+
$ref: ./messages/books.yml#/messages/PaginatedBooksReply
|
|
373
|
+
schemas:
|
|
374
|
+
ListBooksQuery:
|
|
375
|
+
$ref: ./models/books.yml#/ListBooksQuery
|
|
376
|
+
PaginatedBooks:
|
|
377
|
+
$ref: ./models/books.yml#/PaginatedBooks
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
```yaml
|
|
381
|
+
# schema/bookstore/messages/books.yml
|
|
382
|
+
channels:
|
|
383
|
+
listBooks:
|
|
384
|
+
address: qry.bookstore.books.list
|
|
385
|
+
messages:
|
|
386
|
+
listBooksQuery:
|
|
387
|
+
$ref: ./books.yml#/messages/ListBooksQuery
|
|
388
|
+
listBooksReply:
|
|
389
|
+
address: qry.bookstore.books.list.reply
|
|
390
|
+
messages:
|
|
391
|
+
paginatedBooksReply:
|
|
392
|
+
$ref: ./books.yml#/messages/PaginatedBooksReply
|
|
393
|
+
operations:
|
|
394
|
+
listBooks:
|
|
395
|
+
action: receive
|
|
396
|
+
channel:
|
|
397
|
+
$ref: "#/channels/listBooks"
|
|
398
|
+
messages:
|
|
399
|
+
- $ref: "#/channels/listBooks/messages/listBooksQuery"
|
|
400
|
+
reply:
|
|
401
|
+
channel:
|
|
402
|
+
$ref: "#/channels/listBooksReply"
|
|
403
|
+
messages:
|
|
404
|
+
- $ref: "#/channels/listBooksReply/messages/paginatedBooksReply"
|
|
405
|
+
messages:
|
|
406
|
+
ListBooksQuery:
|
|
407
|
+
payload:
|
|
408
|
+
$ref: ../models/books.yml#/ListBooksQuery
|
|
409
|
+
PaginatedBooksReply:
|
|
410
|
+
payload:
|
|
411
|
+
$ref: ../models/books.yml#/PaginatedBooks
|
|
412
|
+
```
|
|
413
|
+
|
|
414
|
+
Shared schemas can be referenced by both roots when they carry the same business
|
|
415
|
+
meaning:
|
|
416
|
+
|
|
417
|
+
```yaml
|
|
418
|
+
# schema/bookstore/models/shared.yml
|
|
419
|
+
BookSlug:
|
|
420
|
+
type: string
|
|
421
|
+
minLength: 1
|
|
422
|
+
maxLength: 120
|
|
423
|
+
pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$"
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
```yaml
|
|
427
|
+
# schema/bookstore/models/books.yml
|
|
428
|
+
Book:
|
|
429
|
+
type: object
|
|
430
|
+
required: [id, slug, title]
|
|
431
|
+
properties:
|
|
432
|
+
id:
|
|
433
|
+
type: string
|
|
434
|
+
format: uuid
|
|
435
|
+
slug:
|
|
436
|
+
$ref: ./shared.yml#/BookSlug
|
|
437
|
+
title:
|
|
438
|
+
type: string
|
|
439
|
+
minLength: 1
|
|
440
|
+
```
|
|
441
|
+
|
|
442
|
+
Do not put graph, routing, or protocol behavior into shared model fragments.
|
|
443
|
+
Share only business payload shapes.
|
|
444
|
+
|
|
445
|
+
## API schema authoring rules
|
|
446
|
+
|
|
447
|
+
- Put reusable HTTP payloads in `components.schemas`.
|
|
448
|
+
- Operation request/response schemas should reference components with `$ref`.
|
|
449
|
+
Inline operation schemas are rejected so generated DTO/model names stay stable.
|
|
450
|
+
- Use operation `summary` to name the action. Use `description` to explain
|
|
451
|
+
outcome, scope, caller context, constraints, or next steps; do not repeat the
|
|
452
|
+
summary in sentence form.
|
|
453
|
+
- Avoid tag echo. If the API docs already show a tag such as `Playbook` or
|
|
454
|
+
`Accounts`, omit that word from the summary unless the operation would become
|
|
455
|
+
ambiguous.
|
|
456
|
+
- Route public or developer-facing `summary`, `description`, parameter, schema,
|
|
457
|
+
and response text through the repo's copywriter standard before validating.
|
|
458
|
+
- Prefer explicit object schemas over anonymous nested shapes when a payload is
|
|
459
|
+
shared by multiple operations.
|
|
460
|
+
- If multiple responses repeat the same envelope fields, extract the envelope
|
|
461
|
+
fragment and compose concrete responses with supported object `allOf`.
|
|
462
|
+
- If multiple schemas repeat the same regex or scalar validation, extract a
|
|
463
|
+
named scalar component and reference it.
|
|
464
|
+
- Use stable `operationId` values. They become Swagger metadata constants such
|
|
465
|
+
as `SWG_LIST_RECIPES`.
|
|
466
|
+
- Unsupported composition features (`oneOf`, `anyOf`, `not`, `discriminator`)
|
|
467
|
+
must either be modeled differently or implemented in Kontract before use.
|
|
468
|
+
|
|
469
|
+
## async schema operation classification
|
|
470
|
+
|
|
471
|
+
| async schema shape | Generated client kind |
|
|
472
|
+
|---------------------|-----------------------|
|
|
473
|
+
| `receive` + `reply` | Query |
|
|
474
|
+
| `receive` | Command |
|
|
475
|
+
| `send` | Event |
|
|
476
|
+
|
|
477
|
+
Run `sumr kontract validate` after any layout change to confirm specs still
|
|
478
|
+
resolve before generating.
|
|
479
|
+
|
|
480
|
+
## async schema copy rules
|
|
481
|
+
|
|
482
|
+
async schema `title`, `summary`, and `description` fields can appear in generated
|
|
483
|
+
docs, SDK docs, and AI answers. Review them with the same copywriter standard as
|
|
484
|
+
API schema:
|
|
485
|
+
|
|
486
|
+
- `title` names the message or operation.
|
|
487
|
+
- `summary` states the job or event in one concise sentence.
|
|
488
|
+
- `description` adds context only when the outcome, constraint, or event
|
|
489
|
+
semantics need more detail.
|
|
490
|
+
- Do not repeat the channel, operation id, schema key, or title in the summary.
|
|
491
|
+
- Keep transport terms such as subject, payload, NATS, command, and query only
|
|
492
|
+
when the reader needs that exact implementation detail.
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
---
|
|
2
|
+
category: team-member
|
|
3
|
+
name: spec-author
|
|
4
|
+
title: Spec Author
|
|
5
|
+
description: "Owns API spec authoring and Kontract regeneration discipline. Use when changing API schema, async schema, or schema specs, validating, regenerating, or reviewing generated contract diffs."
|
|
6
|
+
modelTier: reasoning
|
|
7
|
+
access: write
|
|
8
|
+
channels:
|
|
9
|
+
codex:
|
|
10
|
+
sandbox_mode: workspace-write
|
|
11
|
+
---
|
|
12
|
+
|
|
13
|
+
# Spec Author
|
|
14
|
+
|
|
15
|
+
You own the API contract source of truth for this repo. You change YAML specs
|
|
16
|
+
and let Kontract generate the TypeScript — you never hand-write or hand-patch
|
|
17
|
+
generated contracts.
|
|
18
|
+
|
|
19
|
+
Apply the generated **sumr-kontract-usage** skill, then start from the
|
|
20
|
+
`resources/authoring/` overview. Use its configuration, design-profile axis
|
|
21
|
+
references, spec-layout, schema-reuse, scope-and-splitting, and spec-change
|
|
22
|
+
workflow before editing source specs. Use the generated-output reference before
|
|
23
|
+
consuming or reviewing generated TypeScript.
|
|
24
|
+
|
|
25
|
+
## Responsibilities
|
|
26
|
+
|
|
27
|
+
- Translate API requirements into API schema, async schema, or `*.api.yml`
|
|
28
|
+
specs under `schema/`.
|
|
29
|
+
- After writing or updating any `*.api.yml`, `*.async.yml`, or
|
|
30
|
+
`*.api.yml` file, review it against Kontract reuse, layout, and generation
|
|
31
|
+
rules before validating.
|
|
32
|
+
- Review changed public or developer-facing summaries, descriptions, parameter
|
|
33
|
+
descriptions, response descriptions, message titles, and message summaries
|
|
34
|
+
against the repo's copywriter standard before generation.
|
|
35
|
+
- Read `kontract.guidance.profile` before writing examples so HTTP paths,
|
|
36
|
+
async schema channels, and schema layouts match the selected styles.
|
|
37
|
+
- Inspect the actual specs before writing examples. If the repo only has
|
|
38
|
+
API schema roots, keep guidance API-only and do not invent async schema files,
|
|
39
|
+
channel examples, or `messages/` folders.
|
|
40
|
+
- If the repo only has async schema roots, keep guidance async-only and do not
|
|
41
|
+
invent API schema roots, `paths/`, or HTTP component examples.
|
|
42
|
+
- When both protocols exist, keep API schema and async schema layers separate and share
|
|
43
|
+
only components with identical meaning, especially enums and scalar
|
|
44
|
+
value objects.
|
|
45
|
+
- Use the canonical schema layout trees before proposing schema folders;
|
|
46
|
+
do not confuse resource-area fragments inside a product-capability root with a
|
|
47
|
+
repo-wide `by-resource-area` structure.
|
|
48
|
+
- Keep shared shapes in shared component files and reference them with `$ref`.
|
|
49
|
+
- Keep specs product-aligned and reviewable: use clear capability/surface paths,
|
|
50
|
+
split oversized files at documented thresholds, and avoid generic `common`
|
|
51
|
+
buckets for unrelated concepts.
|
|
52
|
+
- Use comments only as visual editor landmarks. Do not explain endpoint behavior
|
|
53
|
+
with comments; use API/async descriptions for that.
|
|
54
|
+
- Name schemas from product meaning first, using operation-specific response
|
|
55
|
+
names only when the shape belongs to one operation.
|
|
56
|
+
- Proactively spot duplicated envelope fields, pagination metadata, error
|
|
57
|
+
schemas, path/query params, regex scalar constraints, schedules, and config
|
|
58
|
+
objects before generating.
|
|
59
|
+
- Prefer supported object `allOf` composition when a concrete response extends
|
|
60
|
+
a shared base envelope.
|
|
61
|
+
- Run `sumr kontract validate` then `sumr kontract generate` for every change.
|
|
62
|
+
- Review the generated diff for correctness and unintended breakage.
|
|
63
|
+
- If a generated diff creates many near-identical DTO/model files, pause and
|
|
64
|
+
propose a spec-level shared component refactor.
|
|
65
|
+
- Keep spec + regenerated output committed together.
|
|
66
|
+
- When generated files are missing, check `sumr.yaml` target options and the
|
|
67
|
+
installed `SUMR Kontract module` version before changing application code.
|
|
68
|
+
|
|
69
|
+
## Boundaries
|
|
70
|
+
|
|
71
|
+
- Never edit files under the generated `contracts/` output.
|
|
72
|
+
- Never hand-write Zod schemas, DTOs, NATS subjects, or clients that Kontract owns.
|
|
73
|
+
- Do not introduce a second source of truth; the spec is authoritative.
|
|
74
|
+
- Do not over-share unrelated concepts only because their current fields look
|
|
75
|
+
similar; shared components must have the same product meaning and owner.
|
|
76
|
+
- Flag breaking contract changes for human review before commit.
|
|
77
|
+
- Scope `--clean` to the intended source/target in consumer repos.
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
---
|
|
2
2
|
category: workflow
|
|
3
|
-
name:
|
|
4
|
-
title:
|
|
3
|
+
name: spec-change
|
|
4
|
+
title: Spec Change
|
|
5
5
|
description: "Guides an AI agent through safely changing an API spec and regenerating Kontract contracts. Use when an API surface changes and generated contracts must follow."
|
|
6
6
|
modelTier: coding
|
|
7
7
|
access: write
|
|
8
8
|
---
|
|
9
9
|
|
|
10
|
-
#
|
|
10
|
+
# Spec Change
|
|
11
11
|
|
|
12
12
|
Use this workflow whenever an API surface changes (new endpoint, message,
|
|
13
13
|
field, or breaking change) and the generated contracts must follow.
|
|
@@ -15,34 +15,40 @@ field, or breaking change) and the generated contracts must follow.
|
|
|
15
15
|
## Flow
|
|
16
16
|
|
|
17
17
|
```text
|
|
18
|
-
🕐 edit spec -> review spec -> validate -> generate -> review diff -> ⏸ HUMAN APPROVES -> commit
|
|
18
|
+
🕐 read authoring guidance -> edit spec -> review spec -> validate -> generate -> review diff -> ⏸ HUMAN APPROVES -> commit
|
|
19
19
|
```
|
|
20
20
|
|
|
21
21
|
## Steps
|
|
22
22
|
|
|
23
|
-
1. **
|
|
23
|
+
1. **Read the authoring guidance** under `resources/authoring/`. Confirm the
|
|
24
|
+
configured source input, current `kontract.guidance.profile`, selected
|
|
25
|
+
schema layout style, protocol scenario (API-only, async-only, or both
|
|
26
|
+
with shared components), and whether
|
|
27
|
+
the user asked for a guidance-only profile change or an actual schema/output
|
|
28
|
+
namespace migration.
|
|
29
|
+
2. **Edit the spec** under `schema/` (`*.api.yml` / `*.async.yml`).
|
|
24
30
|
Before adding new schemas, scan for existing shared components. Reuse shared
|
|
25
31
|
components via `$ref`; never duplicate schemas.
|
|
26
|
-
|
|
27
|
-
`*.
|
|
32
|
+
3. **Review the written spec** before validation. Check new or changed
|
|
33
|
+
`*.api.yml` / `*.async.yml` files against Kontract best practices:
|
|
28
34
|
stable component names, no inline operation payload schemas, correct `$ref`
|
|
29
|
-
paths, reusable shared components,
|
|
30
|
-
|
|
31
|
-
|
|
35
|
+
paths, selected profile style, reusable shared components, documented size
|
|
36
|
+
thresholds, clear product ownership, and no duplicated product concepts.
|
|
37
|
+
4. **Refactor repeated shapes first**. If the change repeats envelope fields,
|
|
32
38
|
pagination metadata, error bodies, ID/date params, regex scalar constraints,
|
|
33
39
|
schedules, or config objects, extract a shared component and reference it.
|
|
34
|
-
|
|
40
|
+
5. **Validate**: `sumr kontract validate` (scope with `--source` if large).
|
|
35
41
|
Fix every reported error before continuing.
|
|
36
|
-
|
|
42
|
+
6. **Generate**: `sumr kontract generate`. Unchanged specs are skipped.
|
|
37
43
|
Scope large repos with `--source`, `--target`, or `--specific`.
|
|
38
|
-
|
|
44
|
+
7. **Review the diff** of the generated `contracts/` output. Confirm
|
|
39
45
|
`http/models`, `http/enums`, `http/zod`, optional `http/dto`,
|
|
40
46
|
optional `http/swagger.ts`, and NATS `SUBJECTS` match the intended change;
|
|
41
47
|
watch for unintended removals. If the diff introduces many near-identical
|
|
42
48
|
generated files, return to the spec and look for a shared component.
|
|
43
|
-
|
|
49
|
+
8. **Do not edit generated files** to "fix" the diff — change the spec and
|
|
44
50
|
regenerate instead.
|
|
45
|
-
|
|
51
|
+
9. **Commit** the spec change and the regenerated output together so they
|
|
46
52
|
never drift.
|
|
47
53
|
|
|
48
54
|
## Transition rules
|