Skip to content

Commit fdc950e

Browse files
authored
feat: add JSON Schema for export and status command output (#320)
feat: add JSON Schema for export and status command output (#315) Define the user-facing JSON contract for status and export commands before the core migration. Output schemas use *_output.schema.json naming convention and codegen scripts are updated to exclude them.
1 parent bd4209b commit fdc950e

5 files changed

Lines changed: 926 additions & 2 deletions

File tree

pyproject.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -86,8 +86,8 @@ dependencies = [
8686
]
8787

8888
[tool.hatch.envs.dev.scripts]
89-
codegen = "datamodel-codegen --disable-timestamp --input src/reqstool/resources/schemas/v1/ --input-file-type jsonschema --output src/reqstool/models/generated/ --output-model-type pydantic_v2.BaseModel --use-schema-description --use-field-description --use-annotated --field-constraints --target-python-version 3.13"
90-
codegen-check = "datamodel-codegen --check --disable-timestamp --input src/reqstool/resources/schemas/v1/ --input-file-type jsonschema --output src/reqstool/models/generated/ --output-model-type pydantic_v2.BaseModel --use-schema-description --use-field-description --use-annotated --field-constraints --target-python-version 3.13"
89+
codegen = "bash -c 'base=$(mktemp -d) && tmp=$base/v1 && mkdir \"$tmp\" && cp src/reqstool/resources/schemas/v1/*.schema.json \"$tmp/\" && rm -f \"$tmp\"/*_output.schema.json && datamodel-codegen --disable-timestamp --input \"$tmp/\" --input-file-type jsonschema --output src/reqstool/models/generated/ --output-model-type pydantic_v2.BaseModel --use-schema-description --use-field-description --use-annotated --field-constraints --target-python-version 3.13 && rm -rf \"$base\"'"
90+
codegen-check = "bash -c 'base=$(mktemp -d) && tmp=$base/v1 && mkdir \"$tmp\" && cp src/reqstool/resources/schemas/v1/*.schema.json \"$tmp/\" && rm -f \"$tmp\"/*_output.schema.json && datamodel-codegen --check --disable-timestamp --input \"$tmp/\" --input-file-type jsonschema --output src/reqstool/models/generated/ --output-model-type pydantic_v2.BaseModel --use-schema-description --use-field-description --use-annotated --field-constraints --target-python-version 3.13 && rm -rf \"$base\"'"
9191

9292
[tool.black]
9393
line-length = 120
Lines changed: 364 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,364 @@
1+
{
2+
"$id": "https://raw.githubusercontent.com/reqstool/reqstool-client/main/src/reqstool/resources/schemas/v1/export_output.schema.json",
3+
"$schema": "https://json-schema.org/draft/2020-12/schema",
4+
"title": "Reqstool Export Output",
5+
"description": "Schema for the JSON output of the reqstool export command",
6+
"type": "object",
7+
"additionalProperties": false,
8+
"required": ["metadata", "requirements", "svcs", "mvrs", "annotations", "test_results"],
9+
"properties": {
10+
"metadata": {
11+
"$ref": "#/$defs/metadata"
12+
},
13+
"requirements": {
14+
"type": "object",
15+
"description": "All requirements, keyed by urn:id",
16+
"additionalProperties": false,
17+
"patternProperties": {
18+
"^.+:.+$": {
19+
"$ref": "#/$defs/requirement"
20+
}
21+
}
22+
},
23+
"svcs": {
24+
"type": "object",
25+
"description": "All software verification cases, keyed by urn:id",
26+
"additionalProperties": false,
27+
"patternProperties": {
28+
"^.+:.+$": {
29+
"$ref": "#/$defs/svc"
30+
}
31+
}
32+
},
33+
"mvrs": {
34+
"type": "object",
35+
"description": "All manual verification results, keyed by urn:id",
36+
"additionalProperties": false,
37+
"patternProperties": {
38+
"^.+:.+$": {
39+
"$ref": "#/$defs/mvr"
40+
}
41+
}
42+
},
43+
"annotations": {
44+
"$ref": "#/$defs/annotations"
45+
},
46+
"test_results": {
47+
"type": "object",
48+
"description": "Automated test results, keyed by urn:fully_qualified_name",
49+
"additionalProperties": false,
50+
"patternProperties": {
51+
"^.+:.+$": {
52+
"type": "array",
53+
"items": {
54+
"$ref": "#/$defs/test_result"
55+
}
56+
}
57+
}
58+
}
59+
},
60+
"$defs": {
61+
"metadata": {
62+
"type": "object",
63+
"description": "Metadata about this export output",
64+
"additionalProperties": false,
65+
"required": ["initial_urn", "urn_parsing_order", "import_graph", "filtered"],
66+
"properties": {
67+
"initial_urn": {
68+
"type": "string",
69+
"description": "The URN of the initial dataset that was processed"
70+
},
71+
"urn_parsing_order": {
72+
"type": "array",
73+
"items": {
74+
"type": "string"
75+
},
76+
"description": "Order in which URNs were parsed during processing"
77+
},
78+
"import_graph": {
79+
"type": "object",
80+
"description": "DAG of URN import relationships (parent -> children)",
81+
"additionalProperties": false,
82+
"patternProperties": {
83+
"^.+$": {
84+
"type": "array",
85+
"items": {
86+
"type": "string"
87+
}
88+
}
89+
}
90+
},
91+
"filtered": {
92+
"type": "boolean",
93+
"description": "Whether filters were applied during processing"
94+
}
95+
}
96+
},
97+
"lifecycle": {
98+
"type": "object",
99+
"description": "Lifecycle state of a requirement or SVC",
100+
"additionalProperties": false,
101+
"required": ["state"],
102+
"properties": {
103+
"state": {
104+
"type": "string",
105+
"enum": ["draft", "effective", "deprecated", "obsolete"],
106+
"description": "Current lifecycle state"
107+
},
108+
"reason": {
109+
"type": ["string", "null"],
110+
"description": "Reason for the current state, required if deprecated or obsolete"
111+
}
112+
}
113+
},
114+
"revision": {
115+
"type": "object",
116+
"description": "Semantic version of the requirement or SVC",
117+
"additionalProperties": false,
118+
"required": ["major", "minor", "patch"],
119+
"properties": {
120+
"major": {
121+
"type": "integer",
122+
"minimum": 0
123+
},
124+
"minor": {
125+
"type": "integer",
126+
"minimum": 0
127+
},
128+
"patch": {
129+
"type": "integer",
130+
"minimum": 0
131+
}
132+
}
133+
},
134+
"requirement": {
135+
"type": "object",
136+
"description": "A single requirement",
137+
"additionalProperties": false,
138+
"required": ["urn", "id", "title", "significance", "description", "lifecycle", "implementation_type", "categories", "revision"],
139+
"properties": {
140+
"urn": {
141+
"type": "string",
142+
"description": "URN of the system this requirement belongs to"
143+
},
144+
"id": {
145+
"type": "string",
146+
"description": "Requirement identifier (e.g. REQ_010)"
147+
},
148+
"title": {
149+
"type": "string",
150+
"description": "Human-readable title"
151+
},
152+
"significance": {
153+
"type": "string",
154+
"enum": ["shall", "should", "may"],
155+
"description": "Level of significance (RFC 2119)"
156+
},
157+
"description": {
158+
"type": "string",
159+
"description": "Detailed description of the requirement"
160+
},
161+
"rationale": {
162+
"type": ["string", "null"],
163+
"description": "Rationale for why this requirement exists"
164+
},
165+
"lifecycle": {
166+
"$ref": "#/$defs/lifecycle"
167+
},
168+
"implementation_type": {
169+
"type": "string",
170+
"enum": ["in-code", "N/A"],
171+
"description": "How the requirement is implemented"
172+
},
173+
"categories": {
174+
"type": "array",
175+
"items": {
176+
"type": "string",
177+
"enum": [
178+
"functional-suitability",
179+
"performance-efficiency",
180+
"compatibility",
181+
"interaction-capability",
182+
"reliability",
183+
"security",
184+
"maintainability",
185+
"flexibility",
186+
"safety"
187+
]
188+
},
189+
"description": "Requirement categories"
190+
},
191+
"revision": {
192+
"$ref": "#/$defs/revision"
193+
},
194+
"references": {
195+
"type": "array",
196+
"items": {
197+
"$ref": "#/$defs/reference"
198+
},
199+
"description": "References to related requirements"
200+
}
201+
}
202+
},
203+
"reference": {
204+
"type": "object",
205+
"description": "A reference to related requirements",
206+
"additionalProperties": false,
207+
"required": ["requirement_ids"],
208+
"properties": {
209+
"requirement_ids": {
210+
"type": "array",
211+
"items": {
212+
"type": "string"
213+
},
214+
"description": "List of urn:id references to related requirements"
215+
}
216+
}
217+
},
218+
"svc": {
219+
"type": "object",
220+
"description": "A software verification case",
221+
"additionalProperties": false,
222+
"required": ["urn", "id", "title", "description", "verification", "lifecycle", "revision", "requirement_ids"],
223+
"properties": {
224+
"urn": {
225+
"type": "string",
226+
"description": "URN of the system this SVC belongs to"
227+
},
228+
"id": {
229+
"type": "string",
230+
"description": "SVC identifier (e.g. SVC_010)"
231+
},
232+
"title": {
233+
"type": "string",
234+
"description": "Human-readable title"
235+
},
236+
"description": {
237+
"type": "string",
238+
"description": "Detailed description"
239+
},
240+
"verification": {
241+
"type": "string",
242+
"enum": ["automated-test", "manual-test", "review", "platform", "other"],
243+
"description": "Type of verification"
244+
},
245+
"instructions": {
246+
"type": ["string", "null"],
247+
"description": "Instructions for manual verification"
248+
},
249+
"lifecycle": {
250+
"$ref": "#/$defs/lifecycle"
251+
},
252+
"revision": {
253+
"$ref": "#/$defs/revision"
254+
},
255+
"requirement_ids": {
256+
"type": "array",
257+
"items": {
258+
"type": "string"
259+
},
260+
"description": "List of urn:id references to requirements this SVC verifies"
261+
}
262+
}
263+
},
264+
"mvr": {
265+
"type": "object",
266+
"description": "A manual verification result",
267+
"additionalProperties": false,
268+
"required": ["urn", "id", "passed", "svc_ids"],
269+
"properties": {
270+
"urn": {
271+
"type": "string",
272+
"description": "URN of the system this MVR belongs to"
273+
},
274+
"id": {
275+
"type": "string",
276+
"description": "MVR identifier (e.g. MVR_201)"
277+
},
278+
"passed": {
279+
"type": "boolean",
280+
"description": "Whether the manual verification passed"
281+
},
282+
"comment": {
283+
"type": ["string", "null"],
284+
"description": "Optional comment about the verification result"
285+
},
286+
"svc_ids": {
287+
"type": "array",
288+
"items": {
289+
"type": "string"
290+
},
291+
"description": "List of urn:id references to SVCs this MVR verifies"
292+
}
293+
}
294+
},
295+
"annotations": {
296+
"type": "object",
297+
"description": "Code annotations for implementations and tests",
298+
"additionalProperties": false,
299+
"required": ["implementations", "tests"],
300+
"properties": {
301+
"implementations": {
302+
"type": "object",
303+
"description": "Implementation annotations, keyed by urn:requirement_id",
304+
"additionalProperties": false,
305+
"patternProperties": {
306+
"^.+:.+$": {
307+
"type": "array",
308+
"items": {
309+
"$ref": "#/$defs/annotation"
310+
}
311+
}
312+
}
313+
},
314+
"tests": {
315+
"type": "object",
316+
"description": "Test annotations, keyed by urn:svc_id",
317+
"additionalProperties": false,
318+
"patternProperties": {
319+
"^.+:.+$": {
320+
"type": "array",
321+
"items": {
322+
"$ref": "#/$defs/annotation"
323+
}
324+
}
325+
}
326+
}
327+
}
328+
},
329+
"annotation": {
330+
"type": "object",
331+
"description": "A single code annotation",
332+
"additionalProperties": false,
333+
"required": ["element_kind", "fully_qualified_name"],
334+
"properties": {
335+
"element_kind": {
336+
"type": "string",
337+
"enum": ["FIELD", "METHOD", "CLASS", "ENUM", "INTERFACE", "RECORD"],
338+
"description": "Kind of code element annotated"
339+
},
340+
"fully_qualified_name": {
341+
"type": "string",
342+
"description": "Fully qualified name of the annotated element"
343+
}
344+
}
345+
},
346+
"test_result": {
347+
"type": "object",
348+
"description": "A single automated test result",
349+
"additionalProperties": false,
350+
"required": ["fully_qualified_name", "status"],
351+
"properties": {
352+
"fully_qualified_name": {
353+
"type": "string",
354+
"description": "Fully qualified name of the test"
355+
},
356+
"status": {
357+
"type": "string",
358+
"enum": ["passed", "failed", "skipped", "missing"],
359+
"description": "Test execution status"
360+
}
361+
}
362+
}
363+
}
364+
}

0 commit comments

Comments
 (0)