@dogfood-lab/schemas 1.2.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.
@@ -0,0 +1,414 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/dogfood-lab/testing-os/packages/schemas/src/json/dogfood-finding.schema.json",
4
+ "title": "Dogfood Finding",
5
+ "description": "A reviewed, evidence-backed lesson extracted from one or more dogfood runs. The fourth contract alongside record, scenario, and policy. Findings are the smallest durable unit of reusable learning in dogfood-labs.",
6
+ "type": "object",
7
+ "required": [
8
+ "schema_version",
9
+ "finding_id",
10
+ "title",
11
+ "status",
12
+ "repo",
13
+ "product_surface",
14
+ "journey_stage",
15
+ "issue_kind",
16
+ "root_cause_kind",
17
+ "remediation_kind",
18
+ "transfer_scope",
19
+ "summary",
20
+ "source_record_ids",
21
+ "evidence"
22
+ ],
23
+ "additionalProperties": false,
24
+ "properties": {
25
+
26
+ "schema_version": {
27
+ "type": "string",
28
+ "pattern": "^\\d+\\.\\d+\\.\\d+$",
29
+ "description": "Semver of the finding schema."
30
+ },
31
+
32
+ "finding_id": {
33
+ "type": "string",
34
+ "pattern": "^dfind-[a-z0-9][a-z0-9-]*$",
35
+ "minLength": 7,
36
+ "description": "Unique, stable, human-readable slug. Format: dfind-<repo-short>-<lesson-slug>."
37
+ },
38
+
39
+ "title": {
40
+ "type": "string",
41
+ "minLength": 10,
42
+ "maxLength": 200,
43
+ "description": "Short descriptive sentence of the lesson."
44
+ },
45
+
46
+ "status": {
47
+ "type": "string",
48
+ "enum": ["candidate", "reviewed", "accepted", "rejected"],
49
+ "description": "Lifecycle status. Phase 1 does not enforce transition logic — only validates allowed values."
50
+ },
51
+
52
+ "repo": {
53
+ "type": "string",
54
+ "pattern": "^[a-zA-Z0-9_.-]+/[a-zA-Z0-9_.-]+$",
55
+ "description": "Full org/repo where the finding originated."
56
+ },
57
+
58
+ "product_surface": {
59
+ "type": "string",
60
+ "enum": ["cli", "desktop", "web", "api", "mcp-server", "npm-package", "plugin", "library"],
61
+ "description": "Product surface where the lesson was observed. Same enum as record/scenario/policy."
62
+ },
63
+
64
+ "execution_mode": {
65
+ "type": "string",
66
+ "enum": ["bot", "human", "mixed"],
67
+ "description": "Execution mode of the source dogfood run(s)."
68
+ },
69
+
70
+ "journey_stage": {
71
+ "type": "string",
72
+ "enum": [
73
+ "install",
74
+ "setup",
75
+ "first_run",
76
+ "core_loop",
77
+ "export",
78
+ "publish",
79
+ "recovery",
80
+ "integration",
81
+ "verification",
82
+ "rollout"
83
+ ],
84
+ "description": "Where in the product experience the lesson was observed."
85
+ },
86
+
87
+ "issue_kind": {
88
+ "type": "string",
89
+ "enum": [
90
+ "entrypoint_truth",
91
+ "interface_assumption",
92
+ "docs_drift",
93
+ "schema_mismatch",
94
+ "build_output_mismatch",
95
+ "flag_contract_mismatch",
96
+ "evidence_insufficiency",
97
+ "evidence_overconstraint",
98
+ "policy_mismatch",
99
+ "freshness_miscalibration",
100
+ "read_after_write_timing",
101
+ "provenance_gap",
102
+ "execution_mode_mismatch",
103
+ "surface_misclassification",
104
+ "ux_discoverability",
105
+ "verification_gap",
106
+ "dispatch_format",
107
+ "concurrency_conflict",
108
+ "process_lifecycle"
109
+ ],
110
+ "description": "What visibly went wrong."
111
+ },
112
+
113
+ "root_cause_kind": {
114
+ "type": "string",
115
+ "enum": [
116
+ "contract_drift",
117
+ "docs_code_drift",
118
+ "surface_misclassification",
119
+ "missing_precondition",
120
+ "policy_overconstraint",
121
+ "policy_underconstraint",
122
+ "build_config_error",
123
+ "interface_assumption_error",
124
+ "timing_race",
125
+ "tooling_gap",
126
+ "human_process_gap",
127
+ "schema_alignment_failure",
128
+ "dispatch_encoding_error",
129
+ "process_model_mismatch"
130
+ ],
131
+ "description": "Why it actually happened."
132
+ },
133
+
134
+ "remediation_kind": {
135
+ "type": "string",
136
+ "enum": [
137
+ "docs_change",
138
+ "scenario_change",
139
+ "policy_calibration",
140
+ "schema_fix",
141
+ "build_config_fix",
142
+ "entrypoint_fix",
143
+ "verification_fix",
144
+ "classification_fix",
145
+ "retry_logic",
146
+ "evidence_requirement_change",
147
+ "workflow_change",
148
+ "dispatch_fix",
149
+ "process_fix"
150
+ ],
151
+ "description": "What kind of fix resolved it."
152
+ },
153
+
154
+ "transfer_scope": {
155
+ "type": "string",
156
+ "enum": [
157
+ "repo_local",
158
+ "surface_local",
159
+ "surface_archetype",
160
+ "execution_mode",
161
+ "org_wide"
162
+ ],
163
+ "description": "How far the lesson should travel."
164
+ },
165
+
166
+ "summary": {
167
+ "type": "string",
168
+ "minLength": 20,
169
+ "maxLength": 1000,
170
+ "description": "1-3 sentence factual description of the lesson. Must read like a precise incident lesson, not a vague insight."
171
+ },
172
+
173
+ "doctrine_statement": {
174
+ "type": "string",
175
+ "maxLength": 500,
176
+ "description": "Portable rule derived from this finding. Optional in Phase 1 but included to avoid schema migration later."
177
+ },
178
+
179
+ "notes": {
180
+ "type": "string",
181
+ "maxLength": 2000,
182
+ "description": "Human nuance, context, or caveats."
183
+ },
184
+
185
+ "source_record_ids": {
186
+ "type": "array",
187
+ "minItems": 1,
188
+ "items": {
189
+ "type": "string",
190
+ "minLength": 1
191
+ },
192
+ "description": "Run IDs of the dogfood records that produced this finding. At least one required."
193
+ },
194
+
195
+ "scenario_ids": {
196
+ "type": "array",
197
+ "items": {
198
+ "type": "string",
199
+ "pattern": "^[a-z0-9][a-z0-9-]*$"
200
+ },
201
+ "description": "Scenario IDs relevant to this finding."
202
+ },
203
+
204
+ "evidence": {
205
+ "type": "array",
206
+ "minItems": 1,
207
+ "description": "Structured evidence binding. A finding with no evidence is invalid.",
208
+ "items": {
209
+ "type": "object",
210
+ "required": ["evidence_kind"],
211
+ "additionalProperties": false,
212
+ "properties": {
213
+ "evidence_kind": {
214
+ "type": "string",
215
+ "enum": [
216
+ "record",
217
+ "scenario_result",
218
+ "ci_check",
219
+ "policy",
220
+ "artifact",
221
+ "doc",
222
+ "rejection"
223
+ ],
224
+ "description": "Type of evidence supporting this finding."
225
+ },
226
+ "record_id": {
227
+ "type": "string",
228
+ "description": "Run ID of the source record."
229
+ },
230
+ "scenario_id": {
231
+ "type": "string",
232
+ "description": "Scenario ID if evidence is from a scenario result."
233
+ },
234
+ "artifact_ref": {
235
+ "type": "string",
236
+ "description": "Path or URL to an artifact."
237
+ },
238
+ "policy_ref": {
239
+ "type": "string",
240
+ "description": "Path to the policy file."
241
+ },
242
+ "doc_ref": {
243
+ "type": "string",
244
+ "description": "Path to a documentation file."
245
+ },
246
+ "note": {
247
+ "type": "string",
248
+ "maxLength": 500,
249
+ "description": "Explanation of what this evidence proves."
250
+ }
251
+ }
252
+ }
253
+ },
254
+
255
+ "fix_refs": {
256
+ "type": "array",
257
+ "description": "Links to concrete repair actions taken.",
258
+ "items": {
259
+ "type": "object",
260
+ "required": ["ref_kind", "ref"],
261
+ "additionalProperties": false,
262
+ "properties": {
263
+ "ref_kind": {
264
+ "type": "string",
265
+ "enum": ["commit", "pr", "doc", "policy_change", "scenario_change", "workflow_change"],
266
+ "description": "Type of fix reference."
267
+ },
268
+ "ref": {
269
+ "type": "string",
270
+ "description": "Commit SHA, PR URL, file path, etc."
271
+ },
272
+ "note": {
273
+ "type": "string",
274
+ "maxLength": 500,
275
+ "description": "What the fix did."
276
+ }
277
+ }
278
+ }
279
+ },
280
+
281
+ "created_at": {
282
+ "type": "string",
283
+ "format": "date-time",
284
+ "description": "When this finding was first authored."
285
+ },
286
+
287
+ "updated_at": {
288
+ "type": "string",
289
+ "format": "date-time",
290
+ "description": "When this finding was last modified."
291
+ },
292
+
293
+ "derived": {
294
+ "type": "object",
295
+ "description": "Derivation metadata. Present when the finding was machine-generated by the derivation engine.",
296
+ "required": ["method", "rule_id", "derived_at", "rationale"],
297
+ "additionalProperties": false,
298
+ "properties": {
299
+ "method": {
300
+ "type": "string",
301
+ "enum": ["deterministic_rule"],
302
+ "description": "How this candidate was produced."
303
+ },
304
+ "rule_id": {
305
+ "type": "string",
306
+ "pattern": "^rule-[a-z0-9][a-z0-9-]*$",
307
+ "description": "ID of the derivation rule that emitted this finding."
308
+ },
309
+ "derived_at": {
310
+ "type": "string",
311
+ "format": "date-time",
312
+ "description": "When the derivation engine produced this candidate."
313
+ },
314
+ "rationale": {
315
+ "type": "string",
316
+ "minLength": 10,
317
+ "maxLength": 1000,
318
+ "description": "Machine-generated explanation of why this candidate was emitted."
319
+ }
320
+ }
321
+ },
322
+
323
+ "review": {
324
+ "type": "object",
325
+ "description": "Review metadata. Current state of the most recent review action. The full audit trail lives in the review event log.",
326
+ "additionalProperties": false,
327
+ "properties": {
328
+ "reviewed_by": {
329
+ "type": "string",
330
+ "minLength": 1,
331
+ "description": "Actor who performed the review action."
332
+ },
333
+ "reviewed_at": {
334
+ "type": "string",
335
+ "format": "date-time",
336
+ "description": "When the review action occurred."
337
+ },
338
+ "decision_reason": {
339
+ "type": "string",
340
+ "maxLength": 1000,
341
+ "description": "Why this decision was made."
342
+ },
343
+ "review_notes": {
344
+ "type": "string",
345
+ "maxLength": 2000,
346
+ "description": "Additional review context."
347
+ },
348
+ "last_action": {
349
+ "type": "string",
350
+ "enum": ["review", "accept", "reject", "edit", "merge", "reopen", "invalidate", "supersede"],
351
+ "description": "The most recent review action taken."
352
+ },
353
+ "reject_reason": {
354
+ "type": "string",
355
+ "enum": [
356
+ "insufficient_evidence",
357
+ "duplicate",
358
+ "classification_error",
359
+ "not_portable",
360
+ "noise",
361
+ "source_truth_changed",
362
+ "merged_into_canonical"
363
+ ],
364
+ "description": "Structured reject reason. Required when status is rejected."
365
+ }
366
+ }
367
+ },
368
+
369
+ "lineage": {
370
+ "type": "object",
371
+ "description": "Merge and supersession lineage. Tracks which findings were merged into this one, or which finding superseded this one.",
372
+ "additionalProperties": false,
373
+ "properties": {
374
+ "merged_from": {
375
+ "type": "array",
376
+ "items": { "type": "string", "minLength": 1 },
377
+ "description": "Finding IDs that were merged into this canonical finding."
378
+ },
379
+ "superseded_by": {
380
+ "type": "string",
381
+ "description": "Finding ID that supersedes this one. Set when this finding is replaced by a stronger canonical version."
382
+ }
383
+ }
384
+ },
385
+
386
+ "invalidation": {
387
+ "type": "object",
388
+ "description": "Invalidation metadata. Present when an accepted finding is no longer trustworthy.",
389
+ "required": ["is_invalidated", "invalidated_at", "reason"],
390
+ "additionalProperties": false,
391
+ "properties": {
392
+ "is_invalidated": {
393
+ "type": "boolean",
394
+ "description": "True when this finding has been invalidated."
395
+ },
396
+ "invalidated_at": {
397
+ "type": "string",
398
+ "format": "date-time",
399
+ "description": "When the finding was invalidated."
400
+ },
401
+ "invalidated_by": {
402
+ "type": "string",
403
+ "description": "Review event ID that triggered the invalidation."
404
+ },
405
+ "reason": {
406
+ "type": "string",
407
+ "minLength": 5,
408
+ "maxLength": 1000,
409
+ "description": "Why this finding is no longer trustworthy."
410
+ }
411
+ }
412
+ }
413
+ }
414
+ }
@@ -0,0 +1,124 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/dogfood-lab/testing-os/packages/schemas/src/json/dogfood-pattern.schema.json",
4
+ "title": "Dogfood Pattern",
5
+ "description": "A repeated lesson class backed by multiple accepted findings. Patterns represent recurrence, not individual incidents. Only accepted, non-invalidated findings may support a pattern.",
6
+ "type": "object",
7
+ "required": [
8
+ "schema_version",
9
+ "pattern_id",
10
+ "title",
11
+ "status",
12
+ "pattern_kind",
13
+ "summary",
14
+ "source_finding_ids",
15
+ "support",
16
+ "dimensions",
17
+ "transfer_scope"
18
+ ],
19
+ "additionalProperties": false,
20
+ "properties": {
21
+ "schema_version": {
22
+ "type": "string",
23
+ "pattern": "^\\d+\\.\\d+\\.\\d+$"
24
+ },
25
+ "pattern_id": {
26
+ "type": "string",
27
+ "pattern": "^dpat-[a-z0-9][a-z0-9-]*$",
28
+ "minLength": 6
29
+ },
30
+ "title": {
31
+ "type": "string",
32
+ "minLength": 10,
33
+ "maxLength": 200
34
+ },
35
+ "status": {
36
+ "type": "string",
37
+ "enum": ["candidate", "accepted", "rejected", "invalidated"]
38
+ },
39
+ "pattern_kind": {
40
+ "type": "string",
41
+ "enum": [
42
+ "recurring_failure",
43
+ "recurring_success",
44
+ "calibration_signal",
45
+ "coverage_gap",
46
+ "verification_seam",
47
+ "evidence_calibration"
48
+ ]
49
+ },
50
+ "summary": {
51
+ "type": "string",
52
+ "minLength": 20,
53
+ "maxLength": 1000
54
+ },
55
+ "source_finding_ids": {
56
+ "type": "array",
57
+ "minItems": 2,
58
+ "items": { "type": "string", "minLength": 1 },
59
+ "description": "Finding IDs that support this pattern. Minimum 2."
60
+ },
61
+ "support": {
62
+ "type": "object",
63
+ "required": ["finding_count", "repo_count"],
64
+ "additionalProperties": false,
65
+ "properties": {
66
+ "finding_count": { "type": "integer", "minimum": 2 },
67
+ "repo_count": { "type": "integer", "minimum": 1 },
68
+ "surface_count": { "type": "integer", "minimum": 1 },
69
+ "execution_modes": {
70
+ "type": "array",
71
+ "items": { "type": "string", "enum": ["bot", "human", "mixed"] }
72
+ }
73
+ }
74
+ },
75
+ "dimensions": {
76
+ "type": "object",
77
+ "required": ["issue_kinds"],
78
+ "additionalProperties": false,
79
+ "properties": {
80
+ "product_surfaces": {
81
+ "type": "array",
82
+ "items": { "type": "string", "enum": ["cli", "desktop", "web", "api", "mcp-server", "npm-package", "plugin", "library"] }
83
+ },
84
+ "issue_kinds": {
85
+ "type": "array",
86
+ "minItems": 1,
87
+ "items": { "type": "string" }
88
+ },
89
+ "root_cause_kinds": {
90
+ "type": "array",
91
+ "items": { "type": "string" }
92
+ },
93
+ "remediation_kinds": {
94
+ "type": "array",
95
+ "items": { "type": "string" }
96
+ }
97
+ }
98
+ },
99
+ "transfer_scope": {
100
+ "type": "string",
101
+ "enum": ["repo_local", "surface_local", "surface_archetype", "execution_mode", "org_wide"]
102
+ },
103
+ "pattern_strength": {
104
+ "type": "string",
105
+ "enum": ["emerging", "strong", "portfolio_stable"]
106
+ },
107
+ "lineage_note": {
108
+ "type": "string",
109
+ "maxLength": 1000
110
+ },
111
+ "review": {
112
+ "type": "object",
113
+ "additionalProperties": false,
114
+ "properties": {
115
+ "reviewed_by": { "type": "string" },
116
+ "reviewed_at": { "type": "string", "format": "date-time" },
117
+ "decision_reason": { "type": "string", "maxLength": 1000 },
118
+ "last_action": { "type": "string", "enum": ["accept", "reject", "edit", "invalidate"] }
119
+ }
120
+ },
121
+ "created_at": { "type": "string", "format": "date-time" },
122
+ "updated_at": { "type": "string", "format": "date-time" }
123
+ }
124
+ }
@@ -0,0 +1,107 @@
1
+ {
2
+ "$schema": "https://json-schema.org/draft/2020-12/schema",
3
+ "$id": "https://github.com/dogfood-lab/testing-os/packages/schemas/src/json/dogfood-recommendation.schema.json",
4
+ "title": "Dogfood Recommendation",
5
+ "description": "Actionable guidance for future repos, surfaces, or execution modes. Derived from accepted patterns. Narrower and more operational than doctrine.",
6
+ "type": "object",
7
+ "required": [
8
+ "schema_version",
9
+ "recommendation_id",
10
+ "title",
11
+ "status",
12
+ "recommendation_kind",
13
+ "summary",
14
+ "applies_to",
15
+ "based_on_pattern_ids",
16
+ "action"
17
+ ],
18
+ "additionalProperties": false,
19
+ "properties": {
20
+ "schema_version": {
21
+ "type": "string",
22
+ "pattern": "^\\d+\\.\\d+\\.\\d+$"
23
+ },
24
+ "recommendation_id": {
25
+ "type": "string",
26
+ "pattern": "^drec-[a-z0-9][a-z0-9-]*$",
27
+ "minLength": 6
28
+ },
29
+ "title": {
30
+ "type": "string",
31
+ "minLength": 10,
32
+ "maxLength": 200
33
+ },
34
+ "status": {
35
+ "type": "string",
36
+ "enum": ["candidate", "accepted", "rejected"]
37
+ },
38
+ "recommendation_kind": {
39
+ "type": "string",
40
+ "enum": [
41
+ "starter_scenario",
42
+ "starter_check",
43
+ "policy_seed",
44
+ "evidence_expectation",
45
+ "review_prompt",
46
+ "verification_rule"
47
+ ]
48
+ },
49
+ "summary": {
50
+ "type": "string",
51
+ "minLength": 20,
52
+ "maxLength": 1000
53
+ },
54
+ "applies_to": {
55
+ "type": "object",
56
+ "additionalProperties": false,
57
+ "properties": {
58
+ "product_surfaces": {
59
+ "type": "array",
60
+ "items": { "type": "string", "enum": ["cli", "desktop", "web", "api", "mcp-server", "npm-package", "plugin", "library"] }
61
+ },
62
+ "execution_modes": {
63
+ "type": "array",
64
+ "items": { "type": "string", "enum": ["bot", "human", "mixed"] }
65
+ },
66
+ "transfer_scope": {
67
+ "type": "string",
68
+ "enum": ["repo_local", "surface_local", "surface_archetype", "execution_mode", "org_wide"]
69
+ }
70
+ }
71
+ },
72
+ "based_on_pattern_ids": {
73
+ "type": "array",
74
+ "minItems": 1,
75
+ "items": { "type": "string", "minLength": 1 }
76
+ },
77
+ "action": {
78
+ "type": "object",
79
+ "required": ["type", "details"],
80
+ "additionalProperties": false,
81
+ "properties": {
82
+ "type": {
83
+ "type": "string",
84
+ "enum": ["add_check", "add_scenario", "set_policy", "set_evidence", "add_review_step", "set_verification"]
85
+ },
86
+ "target": { "type": "string", "maxLength": 100 },
87
+ "details": { "type": "string", "minLength": 5, "maxLength": 1000 }
88
+ }
89
+ },
90
+ "confidence": {
91
+ "type": "string",
92
+ "enum": ["emerging", "strong", "proven"]
93
+ },
94
+ "review": {
95
+ "type": "object",
96
+ "additionalProperties": false,
97
+ "properties": {
98
+ "reviewed_by": { "type": "string" },
99
+ "reviewed_at": { "type": "string", "format": "date-time" },
100
+ "decision_reason": { "type": "string", "maxLength": 1000 },
101
+ "last_action": { "type": "string", "enum": ["accept", "reject", "edit"] }
102
+ }
103
+ },
104
+ "created_at": { "type": "string", "format": "date-time" },
105
+ "updated_at": { "type": "string", "format": "date-time" }
106
+ }
107
+ }