engsys 1.0.0

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 (173) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +202 -0
  3. package/core/agents/aaron.md +152 -0
  4. package/core/agents/bert.md +115 -0
  5. package/core/agents/isabelle.md +136 -0
  6. package/core/agents/jody.md +150 -0
  7. package/core/agents/leith.md +111 -0
  8. package/core/agents/marcelo.md +282 -0
  9. package/core/agents/melvin.md +101 -0
  10. package/core/agents/nyx.md +152 -0
  11. package/core/agents/otto.md +168 -0
  12. package/core/agents/patricia.md +283 -0
  13. package/core/commands/design-audit-local.md +155 -0
  14. package/core/commands/design-audit.md +235 -0
  15. package/core/commands/design-critique.md +96 -0
  16. package/core/commands/file-issue.md +22 -0
  17. package/core/commands/generate-project.md +45 -0
  18. package/core/commands/implement-issue.md +37 -0
  19. package/core/commands/implement-project.md +40 -0
  20. package/core/commands/naturalize.md +61 -0
  21. package/core/commands/pre-push.md +29 -0
  22. package/core/commands/prep-review-collect.md +130 -0
  23. package/core/commands/prep-review-finalize.md +121 -0
  24. package/core/commands/prep-review-publish.md +113 -0
  25. package/core/commands/prep-review.md +65 -0
  26. package/core/commands/project-closeout.md +25 -0
  27. package/core/skills/agentic-eval/SKILL.md +195 -0
  28. package/core/skills/chrome-devtools/SKILL.md +97 -0
  29. package/core/skills/code-review/SKILL.md +26 -0
  30. package/core/skills/gh-cli/SKILL.md +2202 -0
  31. package/core/skills/git-commit/SKILL.md +124 -0
  32. package/core/skills/git-workflow-agents/SKILL.md +462 -0
  33. package/core/skills/git-workflow-agents/reference.md +220 -0
  34. package/core/skills/github-actions/SKILL.md +190 -0
  35. package/core/skills/github-issues/SKILL.md +154 -0
  36. package/core/skills/llm-structured-outputs/SKILL.md +323 -0
  37. package/core/skills/llm-structured-outputs/references/provider-details.md +392 -0
  38. package/core/skills/pre-push/SKILL.md +115 -0
  39. package/core/skills/refactor/SKILL.md +645 -0
  40. package/core/skills/web-design-reviewer/SKILL.md +371 -0
  41. package/core/skills/webapp-testing/SKILL.md +127 -0
  42. package/core/skills/webapp-testing/test-helper.js +56 -0
  43. package/core/templates/CLAUDE.md.tmpl +98 -0
  44. package/core/templates/adr-template.md +67 -0
  45. package/core/templates/gh-issue-templates/bug.md +39 -0
  46. package/core/templates/gh-issue-templates/content.md +42 -0
  47. package/core/templates/gh-issue-templates/enhancement.md +36 -0
  48. package/core/templates/gh-issue-templates/feature.md +39 -0
  49. package/core/templates/gh-issue-templates/infrastructure.md +41 -0
  50. package/core/templates/post-edit-reminders.sh.tmpl +19 -0
  51. package/core/templates/settings.json.tmpl +90 -0
  52. package/core/templates/settings.local.json.tmpl +3 -0
  53. package/core/workflows/agent-implementation-workflow.md +346 -0
  54. package/core/workflows/generate-project.md +258 -0
  55. package/core/workflows/implement-project-workflow.md +190 -0
  56. package/core/workflows/issue-tracking.md +89 -0
  57. package/core/workflows/project-closeout-ceremony.md +77 -0
  58. package/core/workflows/review-workflow.md +266 -0
  59. package/engsys.config.example.yaml +46 -0
  60. package/install +202 -0
  61. package/lessons-library/README.md +80 -0
  62. package/lessons-library/async-callbacks-verify-liveness.md +15 -0
  63. package/lessons-library/change-isnt-done-until-every-surface-updated.md +15 -0
  64. package/lessons-library/claim-then-act-for-irreversible-ops.md +16 -0
  65. package/lessons-library/co-commit-entangled-work.md +15 -0
  66. package/lessons-library/dependabot-triage-playbook.md +17 -0
  67. package/lessons-library/deploy-by-digest-and-verify-the-running-revision.md +15 -0
  68. package/lessons-library/enforce-your-guarantee-at-your-boundary.md +16 -0
  69. package/lessons-library/gate-changes-on-measurement-not-vibes.md +15 -0
  70. package/lessons-library/iac-first-no-console-changes.md +15 -0
  71. package/lessons-library/independent-objective-review-gate.md +15 -0
  72. package/lessons-library/keep-an-immutable-source-of-truth.md +15 -0
  73. package/lessons-library/long-agent-runs-checkpoint-not-poll.md +15 -0
  74. package/lessons-library/model-identity-with-stable-ids-and-provenance.md +15 -0
  75. package/lessons-library/operator-choices-are-first-class.md +15 -0
  76. package/lessons-library/prefer-tool-enforced-structured-output.md +15 -0
  77. package/lessons-library/prove-causation-before-acting.md +15 -0
  78. package/lessons-library/re-read-state-before-acting.md +14 -0
  79. package/lessons-library/read-layer-tolerates-unbackfilled-rows.md +15 -0
  80. package/lessons-library/shell-safety-pipefail-and-validate-before-teardown.md +14 -0
  81. package/lessons-library/shift-correctness-left-and-distrust-false-greens.md +15 -0
  82. package/lessons-library/stray-control-bytes-hide-changes.md +14 -0
  83. package/lessons-library/tests-can-assert-the-bug.md +15 -0
  84. package/lessons-library/verify-ground-truth-not-reports.md +15 -0
  85. package/lessons-library/worktrees-need-bootstrap-from-origin-main.md +15 -0
  86. package/lib/commands.js +356 -0
  87. package/lib/generate-team-avatars.mjs +251 -0
  88. package/lib/manifest.js +155 -0
  89. package/lib/render.js +135 -0
  90. package/lib/selftest.js +90 -0
  91. package/lib/util.js +89 -0
  92. package/lib/yaml.js +156 -0
  93. package/optional-agents/gary.md +86 -0
  94. package/optional-agents/jos.md +136 -0
  95. package/optional-agents/sandy.md +101 -0
  96. package/optional-agents/steve.md +161 -0
  97. package/package.json +43 -0
  98. package/stacks/cloud/aws/claude.fragment.md +17 -0
  99. package/stacks/cloud/aws/settings.fragment.json +39 -0
  100. package/stacks/cloud/aws/skills/aws-deployment-preflight/SKILL.md +165 -0
  101. package/stacks/cloud/aws/skills/cloud-architecture-aws/SKILL.md +265 -0
  102. package/stacks/cloud/azure/claude.fragment.md +17 -0
  103. package/stacks/cloud/azure/settings.fragment.json +45 -0
  104. package/stacks/cloud/azure/skills/azure-deployment-preflight/SKILL.md +175 -0
  105. package/stacks/cloud/azure/skills/cloud-architecture-azure/SKILL.md +211 -0
  106. package/stacks/cloud/cloudflare/claude.fragment.md +21 -0
  107. package/stacks/cloud/cloudflare/settings.fragment.json +31 -0
  108. package/stacks/cloud/cloudflare/skills/cloud-architecture-cloudflare/SKILL.md +294 -0
  109. package/stacks/cloud/cloudflare/skills/cloudflare-deployment-preflight/SKILL.md +175 -0
  110. package/stacks/cloud/gcp/claude.fragment.md +17 -0
  111. package/stacks/cloud/gcp/settings.fragment.json +40 -0
  112. package/stacks/cloud/gcp/skills/cloud-architecture-gcp/SKILL.md +208 -0
  113. package/stacks/cloud/gcp/skills/gcp-deployment-preflight/SKILL.md +137 -0
  114. package/stacks/db/mongo/skills/mongo-conventions/SKILL.md +96 -0
  115. package/stacks/db/prisma/claude.fragment.md +49 -0
  116. package/stacks/db/prisma/skills/docker-database-package-copy/SKILL.md +44 -0
  117. package/stacks/db/prisma/skills/prisma-conventions/SKILL.md +37 -0
  118. package/stacks/domain/mobile-growth/skills/apple-ads/SKILL.md +184 -0
  119. package/stacks/domain/mobile-growth/skills/apple-ads/references/benchmark-notes.md +47 -0
  120. package/stacks/domain/mobile-growth/skills/apple-ads/references/official-links.md +53 -0
  121. package/stacks/domain/mobile-growth/skills/google-play-growth/SKILL.md +197 -0
  122. package/stacks/domain/mobile-growth/skills/google-play-growth/references/benchmark-notes.md +47 -0
  123. package/stacks/domain/mobile-growth/skills/google-play-growth/references/official-links.md +45 -0
  124. package/stacks/iac/bicep/claude.fragment.md +14 -0
  125. package/stacks/iac/bicep/settings.fragment.json +20 -0
  126. package/stacks/iac/bicep/skills/iac-bicep/SKILL.md +113 -0
  127. package/stacks/iac/cdk/claude.fragment.md +14 -0
  128. package/stacks/iac/cdk/settings.fragment.json +23 -0
  129. package/stacks/iac/cdk/skills/iac-cdk/SKILL.md +104 -0
  130. package/stacks/iac/terraform/claude.fragment.md +13 -0
  131. package/stacks/iac/terraform/settings.fragment.json +25 -0
  132. package/stacks/iac/terraform/skills/iac-terraform/SKILL.md +93 -0
  133. package/stacks/iac/terraform/skills/terraform-conventions/SKILL.md +87 -0
  134. package/stacks/lang/kotlin/skills/android-testing/SKILL.md +263 -0
  135. package/stacks/lang/kotlin/skills/jetpack-compose/SKILL.md +264 -0
  136. package/stacks/lang/kotlin/skills/kotlin-coroutines/SKILL.md +329 -0
  137. package/stacks/lang/python/skills/python-conventions/SKILL.md +61 -0
  138. package/stacks/lang/shell/skills/shell-scripting/SKILL.md +110 -0
  139. package/stacks/lang/swift/skills/swift-concurrency/SKILL.md +423 -0
  140. package/stacks/lang/swift/skills/swift-concurrency/references/approachable-concurrency.md +80 -0
  141. package/stacks/lang/swift/skills/swift-concurrency/references/concurrency-patterns.md +233 -0
  142. package/stacks/lang/swift/skills/swift-concurrency/references/swiftui-concurrency.md +187 -0
  143. package/stacks/lang/swift/skills/swift-concurrency/references/synchronization-primitives.md +341 -0
  144. package/stacks/lang/swift/skills/swift-testing/SKILL.md +497 -0
  145. package/stacks/lang/swift/skills/swift-testing/references/testing-advanced.md +106 -0
  146. package/stacks/lang/swift/skills/swift-testing/references/testing-patterns.md +504 -0
  147. package/stacks/lang/swift/skills/swiftdata/SKILL.md +334 -0
  148. package/stacks/lang/swift/skills/swiftdata/references/core-data-coexistence.md +504 -0
  149. package/stacks/lang/swift/skills/swiftdata/references/swiftdata-advanced.md +975 -0
  150. package/stacks/lang/swift/skills/swiftdata/references/swiftdata-queries.md +675 -0
  151. package/stacks/lang/swift/skills/swiftui-patterns/SKILL.md +371 -0
  152. package/stacks/lang/swift/skills/swiftui-patterns/references/architecture-patterns.md +486 -0
  153. package/stacks/lang/swift/skills/swiftui-patterns/references/deprecated-migration.md +1097 -0
  154. package/stacks/lang/swift/skills/swiftui-patterns/references/design-polish.md +780 -0
  155. package/stacks/lang/swift/skills/swiftui-patterns/references/platform-and-sharing.md +696 -0
  156. package/stacks/lang/typescript/skills/typescript-conventions/SKILL.md +91 -0
  157. package/stacks/platform/android/claude.fragment.md +40 -0
  158. package/stacks/platform/android/hooks/pre-push-gradle.sh +70 -0
  159. package/stacks/platform/android/settings.fragment.json +13 -0
  160. package/stacks/platform/android/skills/android-build-conventions/SKILL.md +247 -0
  161. package/stacks/platform/ios/claude.fragment.md +24 -0
  162. package/stacks/platform/ios/hooks/pre-push-xcodebuild.sh +82 -0
  163. package/stacks/platform/ios/settings.fragment.json +21 -0
  164. package/stacks/platform/ios/skills/xcodebuildmcp-simulator-logs/SKILL.md +76 -0
  165. package/stacks/platform/web/skills/frontend-testing/SKILL.md +246 -0
  166. package/stacks/platform/web/skills/react-conventions/SKILL.md +261 -0
  167. package/stacks/platform/web/skills/web-platform-conventions/SKILL.md +55 -0
  168. package/stacks/tooling/issue-tracker-github/claude.fragment.md +10 -0
  169. package/stacks/tooling/issue-tracker-github/settings.fragment.json +24 -0
  170. package/stacks/tooling/issue-tracker-github/skills/issue-tracker-github/SKILL.md +278 -0
  171. package/stacks/tooling/issue-tracker-linear/claude.fragment.md +17 -0
  172. package/stacks/tooling/issue-tracker-linear/settings.fragment.json +9 -0
  173. package/stacks/tooling/issue-tracker-linear/skills/issue-tracker-linear/SKILL.md +183 -0
@@ -0,0 +1,323 @@
1
+ ---
2
+ name: llm-structured-outputs
3
+ description: "Cross-provider reference for LLM structured outputs with Claude 4.6, GPT-5.3, Gemini 3.1 Pro, and Grok 4. Use when implementing json_schema constrained decoding, writing Zod schemas for LLM APIs, building multi-provider abstractions, or debugging schema compliance failures."
4
+ ---
5
+
6
+ # LLM Structured Outputs
7
+
8
+ Cross-provider reference for schema-constrained JSON decoding with all major frontier LLM APIs. Last updated: February 23, 2026.
9
+
10
+ ## When to Use This Skill
11
+
12
+ - Implementing structured LLM outputs with any major provider
13
+ - Choosing the right API field for `json_schema` per vendor
14
+ - Writing Zod schemas and converting them to JSON Schema for API requests
15
+ - Building provider-agnostic LLM abstraction layers
16
+ - Debugging parse failures or schema non-compliance
17
+ - Migrating off `zod-to-json-schema` (deprecated Nov 2025)
18
+ - Handling edge cases: truncation, refusals, cache invalidation
19
+
20
+ ---
21
+
22
+ ## Core Concept
23
+
24
+ All four providers support **constrained decoding**: you send a JSON Schema and the model is constrained at the token level to produce compliant JSON. This is mathematical, not probabilistic.
25
+
26
+ | Provider | API Field | Type Value |
27
+ | --------------------------------- | ------------------------------------- | ------------------- |
28
+ | Anthropic Claude 4.6 | `output_config.format` | `"json_schema"` |
29
+ | OpenAI GPT-5.3 (Responses API) | `text.format` | `"json_schema"` |
30
+ | OpenAI GPT-5.3 (Chat Completions) | `response_format` | `"json_schema"` |
31
+ | Gemini 3.1 Pro | `generationConfig.responseJsonSchema` | N/A (schema object) |
32
+ | xAI Grok 4 | `response_format` | `"json_schema"` |
33
+
34
+ ---
35
+
36
+ ## Per-Vendor API Patterns
37
+
38
+ ### Anthropic Claude 4.6 (GA — no beta header needed)
39
+
40
+ ```typescript
41
+ const response = await anthropic.messages.create({
42
+ model: "claude-opus-4-6", // or 'claude-sonnet-4-6'
43
+ max_tokens: 4096,
44
+ messages: [{ role: "user", content: prompt }],
45
+ output_config: {
46
+ format: {
47
+ type: "json_schema",
48
+ schema: jsonSchema,
49
+ },
50
+ },
51
+ });
52
+ const parsed = JSON.parse(response.content[0].text);
53
+ ```
54
+
55
+ Key facts:
56
+
57
+ - GA since Feb 4, 2026 — **no** `anthropic-beta` header required
58
+ - `output_config.format` replaces deprecated `output_format`
59
+ - Assistant prefilling (`role: "assistant"` in messages) removed — returns 400
60
+ - Optional fields via `"type": ["string", "null"]` unions
61
+ - **NOT supported:** `anyOf`, `oneOf`, `allOf`, `pattern`, min/max constraints, recursive schemas
62
+
63
+ ### OpenAI GPT-5.3
64
+
65
+ **Responses API** (recommended):
66
+
67
+ ```typescript
68
+ const response = await openai.responses.create({
69
+ model: "gpt-5.3",
70
+ input: prompt,
71
+ text: {
72
+ format: {
73
+ type: "json_schema",
74
+ json_schema: { name: "result", strict: true, schema: jsonSchema },
75
+ },
76
+ },
77
+ });
78
+ ```
79
+
80
+ **Chat Completions API** (legacy):
81
+
82
+ ```typescript
83
+ const response = await openai.chat.completions.create({
84
+ model: "gpt-5.3",
85
+ messages: [{ role: "user", content: prompt }],
86
+ response_format: {
87
+ type: "json_schema",
88
+ json_schema: { name: "result", strict: true, schema: jsonSchema },
89
+ },
90
+ });
91
+ ```
92
+
93
+ > **Warning:** `gpt-5.3-chat-latest` does **not** support `json_schema`. Use `gpt-5.3` or `gpt-5.3-pro`.
94
+
95
+ - **Supported:** `anyOf`, `pattern`, `minimum`/`maximum`, `enum`
96
+ - **NOT supported:** `oneOf`, `allOf`, recursive schemas
97
+ - `additionalProperties: false` and all fields `required` (or `null`-unioned) are mandatory
98
+
99
+ ### Gemini 3.1 Pro
100
+
101
+ ```typescript
102
+ import { GoogleGenAI } from "@google/genai";
103
+ const ai = new GoogleGenAI({ apiKey: GEMINI_API_KEY });
104
+
105
+ const response = await ai.models.generateContent({
106
+ model: "gemini-3.1-pro-preview",
107
+ contents: prompt,
108
+ config: {
109
+ responseMimeType: "application/json",
110
+ responseJsonSchema: jsonSchema,
111
+ },
112
+ });
113
+ const parsed = JSON.parse(response.text);
114
+ ```
115
+
116
+ - **Broadest schema support** of all four providers
117
+ - Supports `anyOf`, `$ref` (recursive), `prefixItems`, `minimum`/`maximum`, `pattern`
118
+ - **NOT supported:** `allOf`, `oneOf`, `not`, `if`/`then`/`else`
119
+ - Enum-only mode: `responseMimeType: 'text/x.enum'`
120
+ - Always strict (implicit constrained decoding)
121
+
122
+ ### xAI Grok 4
123
+
124
+ ```typescript
125
+ import OpenAI from "openai";
126
+ const client = new OpenAI({
127
+ apiKey: process.env.XAI_API_KEY,
128
+ baseURL: "https://api.x.ai/v1",
129
+ });
130
+
131
+ const response = await client.chat.completions.create({
132
+ model: "grok-4-1-fast-reasoning", // recommended for production
133
+ messages: [{ role: "user", content: prompt }],
134
+ response_format: {
135
+ type: "json_schema",
136
+ json_schema: { name: "result", strict: true, schema: jsonSchema },
137
+ },
138
+ });
139
+ const parsed = JSON.parse(response.choices[0].message.content);
140
+ ```
141
+
142
+ - OpenAI SDK works directly (same API shape)
143
+ - **NOT supported / unreliable:** min/max constraints, `pattern`, `allOf` — validate downstream
144
+ - Prefer `grok-4-1-fast-reasoning` over `grok-4-0709` (known strict mode empty-response bug)
145
+
146
+ ---
147
+
148
+ ## Cross-Provider Feature Matrix
149
+
150
+ | Feature | Claude 4.6 | GPT-5.3 | Gemini 3.1 Pro | Grok 4 |
151
+ | ----------------------------- | :-----------: | :------: | :------------: | :-----------: |
152
+ | `anyOf` | ❌ | ✅ | ✅ | ⚠️ unreliable |
153
+ | `$ref` (recursive) | internal only | limited | ✅ | ❌ |
154
+ | `pattern` | ❌ | ✅ | ✅ | ❌ |
155
+ | min/max constraints | ❌ | ✅ | ✅ | ❌ |
156
+ | `additionalProperties: false` | required | required | supported | supported |
157
+ | Constrained decoding status | GA | GA | GA | GA |
158
+
159
+ ---
160
+
161
+ ## Safe Cross-Provider Schema Subset
162
+
163
+ Use this when schemas must work across **all four** providers:
164
+
165
+ ```typescript
166
+ {
167
+ type: 'object',
168
+ properties: {
169
+ name: { type: 'string' },
170
+ count: { type: 'integer' },
171
+ score: { type: 'number' },
172
+ active: { type: 'boolean' },
173
+ status: { type: 'string', enum: ['pending', 'done', 'failed'] },
174
+ tags: { type: 'array', items: { type: 'string' } },
175
+ nested: {
176
+ type: 'object',
177
+ properties: { value: { type: 'string' } },
178
+ required: ['value'],
179
+ additionalProperties: false
180
+ }
181
+ },
182
+ required: ['name', 'count', 'score', 'active', 'status', 'tags', 'nested'],
183
+ additionalProperties: false
184
+ }
185
+ ```
186
+
187
+ **Avoid in cross-provider schemas:** `anyOf`, `oneOf`, `allOf`, `$ref`, `pattern`, min/max, `prefixItems`, `const`, `not`.
188
+
189
+ ---
190
+
191
+ ## Zod 4 Integration (Native JSON Schema)
192
+
193
+ `zod-to-json-schema` is **deprecated as of November 2025**. Use Zod 4's built-in `z.toJSONSchema()`:
194
+
195
+ ```typescript
196
+ import { z } from "zod";
197
+
198
+ const MySchema = z
199
+ .object({
200
+ title: z.string(),
201
+ score: z.number(),
202
+ tags: z.array(z.string()),
203
+ status: z.enum(["active", "archived"]),
204
+ })
205
+ .strict();
206
+
207
+ // Native Zod 4 — no external dependency
208
+ const jsonSchema = z.toJSONSchema(MySchema);
209
+
210
+ // Optional: target specific draft
211
+ z.toJSONSchema(MySchema, { target: "draft-07" });
212
+ ```
213
+
214
+ ### Zod SDK Helpers
215
+
216
+ ```typescript
217
+ // OpenAI Responses API
218
+ import { zodTextFormat } from "openai/helpers/zod";
219
+ text: {
220
+ format: zodTextFormat(MySchema, "result");
221
+ }
222
+
223
+ // OpenAI Chat Completions / Grok
224
+ import { zodResponseFormat } from "openai/helpers/zod";
225
+ response_format: zodResponseFormat(MySchema, "result");
226
+
227
+ // Anthropic SDK parse helper
228
+ const response = await anthropic.messages.parse({
229
+ model: "claude-sonnet-4-6",
230
+ max_tokens: 4096,
231
+ messages: [{ role: "user", content: prompt }],
232
+ output_format: MySchema, // SDK converts automatically
233
+ });
234
+ const result = response.parsed_output;
235
+ ```
236
+
237
+ ---
238
+
239
+ ## Multi-Provider Abstraction Pattern
240
+
241
+ ```typescript
242
+ import { z } from "zod";
243
+
244
+ const MySchema = z
245
+ .object({
246
+ /* fields */
247
+ })
248
+ .strict();
249
+ const jsonSchema = z.toJSONSchema(MySchema);
250
+
251
+ // Anthropic
252
+ const anthropicBody = {
253
+ output_config: { format: { type: "json_schema", schema: jsonSchema } },
254
+ };
255
+
256
+ // OpenAI (Responses API)
257
+ const openaiBody = {
258
+ text: {
259
+ format: {
260
+ type: "json_schema",
261
+ json_schema: { name: "result", strict: true, schema: jsonSchema },
262
+ },
263
+ },
264
+ };
265
+
266
+ // OpenAI (Chat Completions) / Grok
267
+ const openaiChatBody = {
268
+ response_format: {
269
+ type: "json_schema",
270
+ json_schema: { name: "result", strict: true, schema: jsonSchema },
271
+ },
272
+ };
273
+
274
+ // Gemini
275
+ const geminiConfig = {
276
+ responseMimeType: "application/json",
277
+ responseJsonSchema: jsonSchema,
278
+ };
279
+
280
+ // Always validate output regardless of provider
281
+ function parseAndValidate<T>(raw: string, schema: z.ZodType<T>): T {
282
+ const json = JSON.parse(raw);
283
+ return schema.parse(json); // throws ZodError on mismatch
284
+ }
285
+ ```
286
+
287
+ ---
288
+
289
+ ## Edge Cases & Troubleshooting
290
+
291
+ | Issue | Cause | Fix |
292
+ | ------------------------------- | ------------------------------------------------------- | -------------------------------------------- |
293
+ | Anthropic returns 400 | Assistant prefilling used | Remove `role: "assistant"` from messages |
294
+ | Anthropic ignores schema | Using `output_format` instead of `output_config.format` | Update parameter name |
295
+ | GPT-5.3 rejects `json_schema` | Using `gpt-5.3-chat-latest` | Switch to `gpt-5.3` or `gpt-5.3-pro` |
296
+ | Grok returns empty response | `grok-4-0709` + complex `strict: true` schema | Switch to `grok-4-1-fast-reasoning` |
297
+ | JSON incomplete / truncated | `stop_reason: "max_tokens"` | Increase `max_tokens` or simplify prompt |
298
+ | Refusal / no output | Safety system triggered | Check `stop_reason`, add context or rephrase |
299
+ | Prompt cache miss | `output_config.format` changed | Keep schema constant across turns |
300
+ | Zod import error `toJSONSchema` | Zod v3 still installed | Upgrade to Zod 4 (`zod@^4`) |
301
+
302
+ ---
303
+
304
+ ## Best Practices
305
+
306
+ 1. **Always use constrained decoding** — never rely on prompt-only JSON formatting
307
+ 2. **Define schemas in Zod, derive JSON Schema** via `z.toJSONSchema()` — single source of truth
308
+ 3. **Always validate outputs** through `schema.parse()` even with constrained decoding
309
+ 4. **Handle truncation**: check `stop_reason === "max_tokens"` before parsing
310
+ 5. **Keep schemas flat and explicit** for cross-provider reliability
311
+ 6. **Use `additionalProperties: false`** and list all fields in `required` on every object
312
+ 7. **Implement a retry/repair loop**: on `ZodError`, retry with the invalid JSON + error message as context
313
+
314
+ ---
315
+
316
+ ## References
317
+
318
+ - [Full provider details](./references/provider-details.md) — per-vendor model IDs, limits, schema subsets, and docs
319
+ - [Anthropic Structured Outputs](https://platform.claude.com/docs/en/build-with-claude/structured-outputs)
320
+ - [OpenAI Structured Outputs](https://developers.openai.com/api/docs/guides/structured-outputs/)
321
+ - [Gemini Structured Output](https://ai.google.dev/gemini-api/docs/structured-output)
322
+ - [Grok Structured Outputs](https://docs.x.ai/docs/guides/structured-outputs)
323
+ - [Zod 4 JSON Schema](https://zod.dev/json-schema)