@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.
Files changed (35) hide show
  1. package/ai/modules/kontract/resources/api-generation-standards.rf.md +83 -0
  2. package/ai/modules/kontract/resources/{configuration.rf.md → authoring/configuration.rf.md} +49 -11
  3. package/ai/modules/kontract/resources/authoring/design-profile/api-styles.rf.md +241 -0
  4. package/ai/modules/kontract/resources/authoring/design-profile/async-styles.rf.md +134 -0
  5. package/ai/modules/kontract/resources/authoring/design-profile/overview.md +64 -0
  6. package/ai/modules/kontract/resources/authoring/design-profile/schema-layout-styles.rf.md +356 -0
  7. package/ai/modules/kontract/resources/authoring/overview.md +56 -0
  8. package/ai/modules/kontract/resources/{schema-reuse.rf.md → authoring/schema-reuse.rf.md} +222 -46
  9. package/ai/modules/kontract/resources/{scope-and-splitting.rf.md → authoring/scope-and-splitting.rf.md} +113 -57
  10. package/ai/modules/kontract/resources/authoring/spec-layout.rf.md +492 -0
  11. package/ai/modules/kontract/resources/authoring/team-members/spec-author.tm.md +77 -0
  12. package/ai/modules/kontract/resources/{workflows/contract-change.wf.md → authoring/workflows/spec-change.wf.md} +21 -15
  13. package/ai/modules/kontract/resources/generated-output.rf.md +19 -14
  14. package/ai/modules/kontract/resources/openapi-sdk-generator-research.rf.md +17 -19
  15. package/ai/modules/kontract/resources/overview.md +115 -82
  16. package/ai/modules/kontract/resources/performance.rf.md +7 -7
  17. package/ai/modules/kontract/sumr.module.yaml +3 -0
  18. package/ai/modules/mission/sumr.module.yaml +6 -0
  19. package/ai/modules/playbook/resources/authoring/content-structure.rf.md +1 -1
  20. package/ai/modules/playbook/resources/authoring/cross-referencing.rf.md +1 -1
  21. package/ai/modules/playbook/resources/authoring/descriptions.rf.md +1 -1
  22. package/ai/modules/playbook/resources/authoring/extraction.rf.md +1 -1
  23. package/ai/modules/playbook/resources/authoring/flows.rf.md +1 -1
  24. package/ai/modules/playbook/resources/authoring/folder-structure.rf.md +1 -1
  25. package/ai/modules/playbook/resources/authoring/frontmatter.rf.md +4 -1
  26. package/ai/modules/playbook/resources/authoring/markdown.rf.md +1 -1
  27. package/ai/modules/playbook/resources/authoring/overview.md +1 -1
  28. package/ai/modules/playbook/resources/team-members/{playbook-technical-writer.tm.md → technical-writer.tm.md} +3 -2
  29. package/ai/modules/playbook/sumr.module.yaml +7 -2
  30. package/index.js +332 -276
  31. package/package.json +1 -1
  32. package/ai/modules/kontract/resources/language-sdk-generator-extension.rf.md +0 -62
  33. package/ai/modules/kontract/resources/openapi-generator-lessons.rf.md +0 -61
  34. package/ai/modules/kontract/resources/spec-layout.rf.md +0 -275
  35. package/ai/modules/kontract/resources/team-members/contract-author.tm.md +0 -60
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sumrco/cli",
3
- "version": "0.3.0",
3
+ "version": "0.3.1",
4
4
  "description": "SUMR public CLI",
5
5
  "type": "module",
6
6
  "repository": {
@@ -1,62 +0,0 @@
1
- ---
2
- category: reference
3
- name: language-sdk-generator-extension
4
- title: Language SDK Generator Extension
5
- description: "How Kontract should add future non-TypeScript SDK generators such as Java or Rust."
6
- label: Language SDK Generator Extension
7
- when: Researching or implementing a new Kontract SDK generator for another language
8
- order: 47
9
- ---
10
-
11
- # Language SDK Generator Extension
12
-
13
- Kontract can add Java, Rust, or other SDK generators, but only as explicit
14
- generator types after research and tests prove the output is useful.
15
-
16
- ## Current support
17
-
18
- Implemented generators:
19
-
20
- - `typescript-nestjs`
21
- - `asyncapi-nats`
22
- - `typescript-fetch`
23
- - `typescript-axios`
24
- - `typescript-angular`
25
- - `typescript-models`
26
-
27
- Java and Rust are not implemented yet. Config such as `type: java` or
28
- `type: rust` must fail until a real generator exists.
29
-
30
- ## Add a new language generator
31
-
32
- Use this sequence:
33
-
34
- 1. Research mature public generators for the target language and record lessons
35
- in `resources/`.
36
- 2. Add the generator type to `src/types/contracts.types.ts`.
37
- 3. Add config parsing and allowed options in `src/lib/sumr-yaml.ts`.
38
- 4. Add dependency warnings in `src/cli/dependency-check.ts` only when generated
39
- output requires runtime packages in the consumer repo.
40
- 5. Add a generator implementation under `src/generators/openapi/<language>/` or
41
- a shared SDK emitter if the language can reuse one.
42
- 6. Wire generation planning in `src/cli/generate-plan.ts`.
43
- 7. Add tests that prove config parsing, output shape, unsafe-schema failures,
44
- and generated file roots.
45
- 8. Update `README.md`, `docs/**`, `resources/**`, and regenerate AI resources
46
- with `bun run sync`.
47
-
48
- ## Test coverage required
49
-
50
- Every generator must have at least:
51
-
52
- - a config parsing test;
53
- - a direct generation test for expected root files;
54
- - an edge-case test for reserved names or language keywords;
55
- - query array serialization coverage for HTTP SDKs;
56
- - enum and `additionalProperties` coverage where the language supports them;
57
- - a rejection test for unsupported schema features such as unsafe polymorphism;
58
- - a catalog coverage test so the documented generator list and implemented list
59
- stay aligned.
60
-
61
- Do not add a generator type first and fill behavior later. Unsupported language
62
- targets should stay rejected until they can generate useful, validated output.
@@ -1,61 +0,0 @@
1
- ---
2
- category: reference
3
- name: openapi-generator-lessons
4
- title: OpenAPI Generator Bug Lessons
5
- description: "Hardening lessons Kontract applies from public OpenAPI Generator NestJS/TypeScript bug reports. Use when reviewing generated output risks, query parameters, inline schemas, and strict TypeScript compatibility."
6
- label: OpenAPI Generator Lessons
7
- when: Reviewing Kontract specs or generator changes for known OpenAPI/NestJS codegen failure modes
8
- order: 45
9
- ---
10
-
11
- # OpenAPI Generator Bug Lessons
12
-
13
- Kontract learns from public OpenAPI/NestJS generator bugs without inheriting their
14
- architecture. These lessons are guardrails for spec authors, reviewers, and AI agents
15
- working on generated contracts.
16
-
17
- ## Core lessons
18
-
19
- - **Preserve query parameter semantics.** Optional query params stay optional, array query
20
- params serialize as repeated keys, and enum query params use generated enum symbols instead
21
- of raw literal imports.
22
- - **Do not let wire names become unsafe local variables.** Parameter names such as `from`,
23
- `class`, and `default` must remain valid wire keys while generated local identifiers are
24
- safe TypeScript names.
25
- - **Prefer component `$ref` schemas over anonymous inline operation models.** Kontract rejects
26
- inline request/response schemas because anonymous model naming commonly causes duplicate
27
- `InlineObject` outputs and unstable imports.
28
- - **Generate maps deliberately.** `additionalProperties` map schemas must preserve named
29
- properties and typed catch-all/index-signature values consistently across Zod, DTOs, models,
30
- and SDK output. Unsupported `oneOf`, `anyOf`, `not`, and discriminators should produce clear
31
- errors instead of partially generated code with missing symbols such as `AnyType` or
32
- `InnerEnum`.
33
- - **Keep NestJS ownership boundaries clean.** Kontract emits contracts, DTOs, models, swagger
34
- metadata, and SDK clients. Application modules, controllers, providers, and DI wiring stay in
35
- the consuming NestJS app.
36
- - **Compile generated code under strict TypeScript assumptions.** Generated output should avoid
37
- dangling imports, deprecated Nest HTTP client imports, stale `basePath` globals, `Map` headers
38
- where records are expected, and framework symbols that were never emitted.
39
- - **Stay Bun-native.** Kontract does not depend on Java, Docker images, downloaded generator
40
- binaries, or template folders at generation time.
41
-
42
- ## Spec authoring rules
43
-
44
- - Put reusable request/response bodies, parameters, enums, and object fragments under
45
- `components` and reference them with `$ref`.
46
- - Encode validation constraints in the OpenAPI schema (`minLength`, `maxLength`, `minimum`,
47
- `maximum`, `pattern`, `format`) so DTO/Zod output can enforce them.
48
- - Use `additionalProperties` when the payload is intentionally map-shaped. Prefer typed map values
49
- over `additionalProperties: true`; Kontract preserves named fields and emits a safe unknown
50
- catch-all when the spec intentionally allows arbitrary values.
51
- - For repeated query values, use `type: array` with scalar `items`; generated SDKs must not
52
- collapse values into comma-separated strings.
53
-
54
- ## Reviewer checklist
55
-
56
- - Generated files include the auto-generated header and are not hand-edited.
57
- - Query DTOs and SDK request types preserve optionality from the spec.
58
- - No generated file contains `any`, `AnyType`, `InlineObject`, `InnerEnum`, `queryParameters`,
59
- deprecated `HttpService`, stale `basePath`, or unsafe `apiKeys` access.
60
- - Operation schemas reference named components instead of inline request/response objects.
61
- - Unsupported schema features fail before any consumer repo is left with partial broken output.
@@ -1,275 +0,0 @@
1
- ---
2
- category: reference
3
- name: spec-layout
4
- title: Spec File Layout
5
- description: "Required folder and file conventions for Kontract OpenAPI/AsyncAPI source specs."
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.openapi.yml ← one OpenAPI doc per service/domain
19
- recipes.asyncapi.yml ← one AsyncAPI doc per service/domain
20
- recipes.schema.yml ← neutral suffix; detected by openapi:/asyncapi:
21
- base.yml ← shared components, referenced via $ref
22
- bookstore/
23
- bookstore.openapi.yml ← root entrypoint
24
- bookstore.asyncapi.yml ← root entrypoint
25
- paths/catalog.yml ← OpenAPI path fragments
26
- messages/events.yml ← AsyncAPI channel/message fragments
27
- models/shared.yml ← protocol-neutral model fragments
28
- ```
29
-
30
- ## Rules
31
-
32
- - OpenAPI specs end in `*.openapi.yml` / `*.openapi.yaml`.
33
- - AsyncAPI specs end in `*.asyncapi.yml` / `*.asyncapi.yaml`.
34
- - Use `*.schema.yml` / `*.schema.yaml` when a domain folder already makes the
35
- protocol obvious less useful than the business surface name. Kontract reads
36
- the file marker and treats `openapi:` as OpenAPI and `asyncapi:` as AsyncAPI.
37
- - Discovery is recursive; `base.yml` is skipped as an entry point.
38
- - Service output paths mirror nested spec paths under the configured source
39
- input directory.
40
- - A root `*.openapi.yml` or `*.asyncapi.yml` may reference plain `.yml`
41
- fragments for paths, messages, parameters, and schemas. Kontract bundles the
42
- root before generation when it finds external `$ref` links.
43
- - OpenAPI and AsyncAPI roots may share neutral model fragments when the shapes
44
- mean the same thing for HTTP and messaging. Keep protocol-specific path,
45
- operation, parameter, channel, and message metadata in separate fragments.
46
- - Nested `*.schema.yml` files are grouped by their first folder. This supports a
47
- DDD layout where the folder is the domain and each file is a subdomain surface:
48
-
49
- ```text
50
- schema/
51
- recipes/
52
- catalog.schema.yml ← OpenAPI
53
- publishing.schema.yml ← AsyncAPI
54
- ```
55
-
56
- Both files generate under `contracts/recipes/`.
57
- - Use nested domain/subdomain paths when one root file would mix independently
58
- owned API surfaces; see the scope and splitting reference for line-count
59
- thresholds and naming rules.
60
- - Use comments only as editor navigation markers. Comments may label groups such
61
- as `Catalog paths` or `Response schemas`, but they must not explain endpoint
62
- behavior or replace `summary` / `description`.
63
- - Share common schemas through `$ref` into `base.yml`. Do **not** duplicate
64
- schemas across specs and do **not** merge by hand-mutating parsed JSON.
65
- - Prefer a `schema/shared/` folder for cross-domain components such as common
66
- parameters, error responses, pagination, scalar constraints, response envelope
67
- fragments, schedules, and reusable config objects.
68
- - The NATS namespace comes from the AsyncAPI `info.title`, not the filename —
69
- set `info.title` deliberately.
70
- - Multi-file specs are bundled automatically (OpenAPI via Redocly core in-process
71
- with CLI fallback, AsyncAPI via `@asyncapi/cli bundle`); keep `$ref` paths
72
- repo-relative.
73
-
74
- ## Split root-entrypoint layout
75
-
76
- Use this layout when one product domain should generate as one contract package,
77
- but the root files are getting too large:
78
-
79
- ```text
80
- schema/
81
- bookstore/
82
- bookstore.openapi.yml
83
- bookstore.asyncapi.yml
84
- components/
85
- parameters.yml
86
- paths/
87
- books.yml
88
- authors.yml
89
- messages/
90
- books.yml
91
- authors.yml
92
- models/
93
- shared.yml
94
- books.yml
95
- authors.yml
96
- ```
97
-
98
- The root files stay small and readable. Fragment files are plain `.yml` because
99
- they are not standalone OpenAPI or AsyncAPI documents.
100
-
101
- If a root file needs many visual section markers to stay readable, split the
102
- internals into domain/subdomain fragments before adding more comments.
103
-
104
- ```yaml
105
- # schema/bookstore/bookstore.openapi.yml
106
- openapi: 3.0.3
107
- info:
108
- title: Bookstore Contracts
109
- version: 1.0.0
110
- paths:
111
- /books:
112
- $ref: ./paths/books.yml#/paths/~1books
113
- components:
114
- schemas:
115
- Book:
116
- $ref: ./models/books.yml#/Book
117
- PaginatedBooks:
118
- $ref: ./models/books.yml#/PaginatedBooks
119
- ```
120
-
121
- ```yaml
122
- # schema/bookstore/paths/books.yml
123
- paths:
124
- /books:
125
- get:
126
- operationId: listBooks
127
- responses:
128
- "200":
129
- description: Paginated book list.
130
- content:
131
- application/json:
132
- schema:
133
- $ref: ../models/books.yml#/PaginatedBooks
134
- ```
135
-
136
- ```yaml
137
- # schema/bookstore/bookstore.asyncapi.yml
138
- asyncapi: 3.0.0
139
- info:
140
- title: Bookstore
141
- version: 1.0.0
142
- channels:
143
- listBooks:
144
- $ref: ./messages/books.yml#/channels/listBooks
145
- listBooksReply:
146
- $ref: ./messages/books.yml#/channels/listBooksReply
147
- operations:
148
- listBooks:
149
- $ref: ./messages/books.yml#/operations/listBooks
150
- components:
151
- messages:
152
- ListBooksQuery:
153
- $ref: ./messages/books.yml#/messages/ListBooksQuery
154
- PaginatedBooksReply:
155
- $ref: ./messages/books.yml#/messages/PaginatedBooksReply
156
- schemas:
157
- ListBooksQuery:
158
- $ref: ./models/books.yml#/ListBooksQuery
159
- PaginatedBooks:
160
- $ref: ./models/books.yml#/PaginatedBooks
161
- ```
162
-
163
- ```yaml
164
- # schema/bookstore/messages/books.yml
165
- channels:
166
- listBooks:
167
- address: qry.bookstore.books.list
168
- messages:
169
- listBooksQuery:
170
- $ref: ./books.yml#/messages/ListBooksQuery
171
- listBooksReply:
172
- address: qry.bookstore.books.list.reply
173
- messages:
174
- paginatedBooksReply:
175
- $ref: ./books.yml#/messages/PaginatedBooksReply
176
- operations:
177
- listBooks:
178
- action: receive
179
- channel:
180
- $ref: "#/channels/listBooks"
181
- messages:
182
- - $ref: "#/channels/listBooks/messages/listBooksQuery"
183
- reply:
184
- channel:
185
- $ref: "#/channels/listBooksReply"
186
- messages:
187
- - $ref: "#/channels/listBooksReply/messages/paginatedBooksReply"
188
- messages:
189
- ListBooksQuery:
190
- payload:
191
- $ref: ../models/books.yml#/ListBooksQuery
192
- PaginatedBooksReply:
193
- payload:
194
- $ref: ../models/books.yml#/PaginatedBooks
195
- ```
196
-
197
- Shared schemas can be referenced by both roots when they carry the same business
198
- meaning:
199
-
200
- ```yaml
201
- # schema/bookstore/models/shared.yml
202
- BookSlug:
203
- type: string
204
- minLength: 1
205
- maxLength: 120
206
- pattern: "^[a-z0-9]+(?:-[a-z0-9]+)*$"
207
- ```
208
-
209
- ```yaml
210
- # schema/bookstore/models/books.yml
211
- Book:
212
- type: object
213
- required: [id, slug, title]
214
- properties:
215
- id:
216
- type: string
217
- format: uuid
218
- slug:
219
- $ref: ./shared.yml#/BookSlug
220
- title:
221
- type: string
222
- minLength: 1
223
- ```
224
-
225
- Do not put graph, routing, or protocol behavior into shared model fragments.
226
- Share only business payload shapes.
227
-
228
- ## OpenAPI authoring rules
229
-
230
- - Put reusable HTTP payloads in `components.schemas`.
231
- - Operation request/response schemas should reference components with `$ref`.
232
- Inline operation schemas are rejected so generated DTO/model names stay stable.
233
- - Use operation `summary` to name the action. Use `description` to explain
234
- outcome, scope, caller context, constraints, or next steps; do not repeat the
235
- summary in sentence form.
236
- - Avoid tag echo. If the API docs already show a tag such as `Playbook` or
237
- `Accounts`, omit that word from the summary unless the operation would become
238
- ambiguous.
239
- - Route public or developer-facing `summary`, `description`, parameter, schema,
240
- and response text through the repo's copywriter/microcopy standard before
241
- validating.
242
- - Prefer explicit object schemas over anonymous nested shapes when a payload is
243
- shared by multiple operations.
244
- - If multiple responses repeat the same envelope fields, extract the envelope
245
- fragment and compose concrete responses with supported object `allOf`.
246
- - If multiple schemas repeat the same regex or scalar validation, extract a
247
- named scalar component and reference it.
248
- - Use stable `operationId` values. They become Swagger metadata constants such
249
- as `SWG_LIST_RECIPES`.
250
- - Unsupported composition features (`oneOf`, `anyOf`, `not`, `discriminator`)
251
- must either be modeled differently or implemented in Kontract before use.
252
-
253
- ## AsyncAPI operation classification
254
-
255
- | AsyncAPI shape | Generated client kind |
256
- |---------------------|-----------------------|
257
- | `receive` + `reply` | Query |
258
- | `receive` | Command |
259
- | `send` | Event |
260
-
261
- Run `sumr kontract validate` after any layout change to confirm specs still
262
- resolve before generating.
263
-
264
- ## AsyncAPI copy rules
265
-
266
- AsyncAPI `title`, `summary`, and `description` fields can appear in generated
267
- docs, SDK docs, and AI answers. Write them with the same copy gate as OpenAPI:
268
-
269
- - `title` names the message or operation.
270
- - `summary` states the job or event in one concise sentence.
271
- - `description` adds context only when the outcome, constraint, or event
272
- semantics need more detail.
273
- - Do not repeat the channel, operation id, schema key, or title in the summary.
274
- - Keep transport terms such as subject, payload, NATS, command, and query only
275
- when the reader needs that exact implementation detail.
@@ -1,60 +0,0 @@
1
- ---
2
- category: team-member
3
- name: contract-author
4
- title: Contract Author
5
- description: "Owns API spec authoring and Kontract regeneration discipline. Use when changing OpenAPI/AsyncAPI 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
- # Contract 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, plus the configuration,
20
- spec-layout, schema-reuse, scope-and-splitting, and generated-output references,
21
- before acting.
22
-
23
- ## Responsibilities
24
-
25
- - Translate API requirements into OpenAPI/AsyncAPI specs under `schema/`.
26
- - After writing or updating any `*.openapi.yml` / `*.asyncapi.yml` file, review
27
- it against Kontract reuse, layout, and generation rules before validating.
28
- - Route changed public or developer-facing summaries, descriptions, parameter
29
- descriptions, response descriptions, message titles, and message summaries
30
- through the repo's copywriter/microcopy standard before generation.
31
- - Keep shared shapes in shared component files and reference them with `$ref`.
32
- - Keep specs domain-aligned and reviewable: use domain/subdomain paths, split
33
- oversized files at documented thresholds, and avoid generic `common` buckets
34
- for unrelated concepts.
35
- - Use comments only as visual editor landmarks. Do not explain endpoint behavior
36
- with comments; use OpenAPI/AsyncAPI descriptions for that.
37
- - Name schemas from domain meaning first, using operation-specific response
38
- names only when the shape belongs to one operation.
39
- - Proactively spot duplicated envelope fields, pagination metadata, error
40
- schemas, path/query params, regex scalar constraints, schedules, and config
41
- objects before generating.
42
- - Prefer supported object `allOf` composition when a concrete response extends
43
- a shared base envelope.
44
- - Run `sumr kontract validate` then `sumr kontract generate` for every change.
45
- - Review the generated diff for correctness and unintended breakage.
46
- - If a generated diff creates many near-identical DTO/model files, pause and
47
- propose a spec-level shared component refactor.
48
- - Keep spec + regenerated output committed together.
49
- - When generated files are missing, check `sumr.yaml` target options and the
50
- installed `SUMR Kontract module` version before changing application code.
51
-
52
- ## Boundaries
53
-
54
- - Never edit files under the generated `contracts/` output.
55
- - Never hand-write Zod schemas, DTOs, NATS subjects, or clients that Kontract owns.
56
- - Do not introduce a second source of truth; the spec is authoritative.
57
- - Do not over-share unrelated concepts only because their current fields look
58
- similar; shared components must have the same product meaning and owner.
59
- - Flag breaking contract changes for human review before commit.
60
- - Scope `--clean` to the intended source/target in consumer repos.