Generate Requirement Drafts
Generate draft requirements from Simulink models using the richest artifact the environment supports. All outputs are drafts requiring human review and approval before baselining.
When to Use
- Drafting or updating requirements from a Simulink model
- Creating
.slreqx or .yaml requirements artifacts
- Establishing model-to-requirement traceability
When NOT to Use
- Importing requirements from an existing source of truth (ReqIF, DOORS, Word, Excel) — use Requirements Toolbox import APIs directly
- Writing or running tests — use the
testing-simulink-models skill
- Free-form prose notes with no saved artifact
- User explicitly wants a different text format (markdown, Word)
Output Conventions
- Default file names:
<Model>_Requirements.slreqx or <model>_requirements.yaml
- Stable IDs:
REQ_<SYSTEM>_001, REQ_<SYSTEM>_002, … — use one consistent project-wide prefix with sequential integers across all requirements, even when they derive from different subsystems. Do not switch to per-subsystem prefixes or hierarchical decimal numbering (e.g. CB-1.1, TP-1.1).
- Follow repo conventions if
.slreqx or .yaml files already exist
- When updating an existing artifact, preserve existing IDs — append new IDs, never renumber
- Every generated requirement must be marked as draft — use
"draft" in Keywords (slreq) or status: Draft + keywords: [draft] (YAML)
Writing Good Requirements
Requirements must express behavioral intent (WHAT the system shall do), not restate model topology (HOW it is implemented). Put the WHY in Rationale. Use EARS (Easy Approach to Requirements Syntax) patterns:
EARS Patterns
Choose the pattern that best fits the model behavior:
| Pattern |
Template |
When to Use |
| Ubiquitous |
The <system> shall <response>. |
Always-on behavior, invariants |
| Event-driven |
When <trigger>, the <system> shall <response>. |
A momentary trigger causes a one-time response: input events, entering a Stateflow state (the transition itself) |
| State-driven |
While <state>, the <system> shall <response>. |
Behavior that holds continuously while in a Stateflow state or mode — the ongoing response, not the entry transition |
| Unwanted behavior |
If <condition>, then the <system> shall <response>. |
Error handling, safety limits, saturation |
| Optional feature |
Where <feature>, the <system> shall <response>. |
Variant subsystems, configurable features |
| Combined |
While <state>, when <trigger>, the <system> shall <response>. |
State + event combinations |
Examples — Model Concepts to EARS Requirements
| ❌ Bad — restates implementation |
✅ Good — EARS pattern |
| "Saturation block limits output to [0,1]" |
"If throttle command exceeds ThrottleMax (1.0) or falls below ThrottleMin (0.0), then the controller shall clamp the output to the valid range." |
| "BrakeLogic subsystem disengages controller" |
"When brake pedal input exceeds BrakeThreshold (0.0), the controller shall disengage cruise control." |
| "Gain block multiplies by 2.5" |
"While cruise control is active, the controller shall amplify speed error by Kp (2.5) to compute proportional correction." |
| "Stateflow chart transitions to Idle" |
"When the driver presses the off button, the system shall transition to the Idle state." |
| "Defrost state runs the heater at full power" |
"While in the Defrost state, the system shall drive the heater at full power." |
| "Variant subsystem selects Algorithm A" |
"Where the adaptive mode is enabled, the controller shall use the predictive algorithm." |
Rules
- Write requirements using EARS patterns — pick the pattern that matches the model behavior
- Use block/subsystem names (e.g.
Saturation, BrakeLogic) only in Rationale, Description, or provenance notes — never in the requirement Summary. (A workspace parameter rendered as VarName (value) is required in the Summary and is not a block name.)
- When referencing a numeric value, include the workspace variable name and resolved value:
VarName (value). If the model uses a literal with no variable, record the numeric literal directly
- Put the WHY in
Rationale, not in the requirement statement
- One subsystem may support zero, one, or several behavioral requirements — don't force a 1:1 mapping
- For a Stateflow state or mode, separate entering it from being in it: the entry transition is event-driven (
When <trigger>, … shall transition to <state>), but the behavior that holds throughout the mode is state-driven (While <state>, … shall <response>). When asked for a mode's behavior, prefer the While <state> form — do not fold it into a When entry statement
Backend Decision Gate
Choose once at the start, then stay on that path.
| Situation |
Backend |
User explicitly asks for .slreqx, traceability views, or repo already uses .slreqx |
Requirements Toolbox — if probe fails, inform the user that Requirements Toolbox is unavailable; do NOT silently fall back |
User explicitly asks for .yaml, or repo already uses .yaml requirements |
Structured YAML |
| No format specified — probe for Requirements Toolbox |
Requirements Toolbox if probe succeeds |
| No format specified and probe fails |
Structured YAML (silent fallback is OK here since user had no preference) |
Probe (run via evaluate_matlab_code):
hasSlreq = ~isempty(which('slreq.new'));
if hasSlreq, try, slreq.find(Type="Link"); catch, hasSlreq = false; end, end
disp(hasSlreq)
Workflow
- Call
model_overview, model_read, model_query_params, model_resolve_params as MCP tools — never pass their names to evaluate_matlab_code.
- Use
evaluate_matlab_code only for MATLAB code, such as the backend probe and the slreq.* APIs in Path A.
Understand the model — use the model_overview and model_read tools to understand subsystems, interfaces, control logic.
Extract parameters — use the model_query_params / model_resolve_params tools for thresholds, gains, sample times that should appear in requirement text. Record both variable names and resolved values.
Build a capture table (backend-neutral):
| Id |
ParentId |
Summary |
Description |
SourceBlock |
Rationale |
ASIL |
Priority |
Keywords |
Run the backend path (A or B below).
Review using the gate below.
Path A — Requirements Toolbox (.slreqx)
Use when probe succeeds. For full API patterns see references/slreq-patterns.md.
model = "CruiseControl";
load_system(model);
rs = slreq.new(model + "_Requirements");
% Add requirements with hierarchy — note behavioral "shall" statements
req = add(rs, Id="REQ_CC_001", ...
Summary="If throttle command exceeds ThrottleMax (1.0) or falls below ThrottleMin (0.0), then the controller shall clamp the output to the valid range.", ...
Description="Derived from CruiseControl/ThrottleCmd.");
req.Rationale = "Prevents invalid actuator commands that could damage the throttle body.";
req.Keywords = ["draft","auto-generated","control","safety"];
child = add(req, Id="REQ_CC_002", ...
Summary="When brake pedal input exceeds BrakeThreshold (0.0), the controller shall disengage cruise control.", ...
Description="Derived from CruiseControl/BrakeLogic.");
child.Keywords = ["draft","auto-generated","safety","brake"];
% Create traceability links: use block handle from SID (blk_X → X) for robustness
lnk = slreq.createLink(Simulink.ID.getHandle(model + ":5"), req);
slreq.createLink(Simulink.ID.getHandle(model + ":8"), child);
save(rs);
% Save all link sets
linkSets = slreq.find(Type="LinkSet");
for i = 1:numel(linkSets), save(linkSets(i)); end
Link rules:
- Source = model element, destination = requirement → link type is automatically
Implement
- Prefer subsystem-level links; use block-level only when the requirement is block-specific
- Every model-derived requirement must have at least one traceability link
- The model must be loaded (
load_system) before creating links with block paths
Path B — Structured YAML fallback
Use when Requirements Toolbox is unavailable. For schema and field rules see references/yaml-requirements.md.
- Generate a
<model>_requirements.yaml file from the capture table
- Set
status: Draft and include draft in keywords for every requirement
- Self-review: all required fields set,
asil/status/priority use valid values, IDs sequential, derived_from references valid IDs or is null
- Validate:
python -c "import yaml, sys; yaml.safe_load(open(sys.argv[1])); print('OK')" path/to/requirements.yaml
Guardrails
| Always |
Never |
| Mark every generated requirement as DRAFT |
Emit markdown or ad hoc text when .slreqx is available and no text format was requested |
| Write requirements using EARS patterns |
Restate block topology as the requirement summary |
Include parameter name + value: VarName (value) |
Create both .slreqx and .yaml unless user asks for both |
| Link direction: model element → requirement |
Reverse the link direction (requirement → block) |
load_system before creating traceability links |
Over-link every primitive block — prefer subsystem links |
| Use only R2023a+ APIs |
Silently fall back to YAML when user explicitly requested .slreqx |
| Stay consistent with existing repo format |
Renumber existing requirement IDs on regeneration |
Review Gate
Before finishing, verify (both backends):
slreq path only:
YAML path only:
References
references/slreq-patterns.md — Requirements Toolbox API cookbook
references/yaml-requirements.md — Structured YAML schema and field rules
assets/slreq_from_model.m — End-to-end slreq example
assets/requirements.yaml — Structured YAML example
Copyright 2026 The MathWorks, Inc.
1---2name: generate-requirement-drafts3description: Generates draft requirements from Simulink models. Use when drafting or updating requirement artifacts from a model. Prefers Requirements Toolbox (.slreqx) when available; falls back to structured YAML.4license: https://www.mathworks.com/content/dam/mathworks/license/pmrl/lic5---6
7# Generate Requirement Drafts
8
9Generate draft requirements from Simulink models using the richest artifact the environment supports. All outputs are **drafts** requiring human review and approval before baselining.
10
11## When to Use
12- Drafting or updating requirements from a Simulink model
13- Creating `.slreqx` or `.yaml` requirements artifacts
14- Establishing model-to-requirement traceability
15
16## When NOT to Use
17- Importing requirements from an existing source of truth (ReqIF, DOORS, Word, Excel) — use Requirements Toolbox import APIs directly
18- Writing or running tests — use the `testing-simulink-models` skill
19- Free-form prose notes with no saved artifact
20- User explicitly wants a different text format (markdown, Word)
21
22## Output Conventions
23- Default file names: `<Model>_Requirements.slreqx` or `<model>_requirements.yaml`
24- Stable IDs: `REQ_<SYSTEM>_001`, `REQ_<SYSTEM>_002`, … — use **one** consistent project-wide prefix with sequential integers across all requirements, even when they derive from different subsystems. Do not switch to per-subsystem prefixes or hierarchical decimal numbering (e.g. `CB-1.1`, `TP-1.1`).
25- Follow repo conventions if `.slreqx` or `.yaml` files already exist
26- When updating an existing artifact, preserve existing IDs — append new IDs, never renumber
27- Every generated requirement must be marked as draft — use `"draft"` in Keywords (slreq) or `status: Draft` + `keywords: [draft]` (YAML)
28
29## Writing Good Requirements
30
31Requirements must express **behavioral intent** (WHAT the system shall do), not restate model topology (HOW it is implemented). Put the WHY in `Rationale`. Use **EARS (Easy Approach to Requirements Syntax)** patterns:
32
33### EARS Patterns
34
35Choose the pattern that best fits the model behavior:
36
37| Pattern | Template | When to Use |
38|---------|----------|-------------|
39| **Ubiquitous** | The \<system\> shall \<response\>. | Always-on behavior, invariants |
40| **Event-driven** | When \<trigger\>, the \<system\> shall \<response\>. | A momentary trigger causes a one-time response: input events, **entering** a Stateflow state (the transition itself) |
41| **State-driven** | While \<state\>, the \<system\> shall \<response\>. | Behavior that holds continuously **while in** a Stateflow state or mode — the ongoing response, not the entry transition |
42| **Unwanted behavior** | If \<condition\>, then the \<system\> shall \<response\>. | Error handling, safety limits, saturation |
43| **Optional feature** | Where \<feature\>, the \<system\> shall \<response\>. | Variant subsystems, configurable features |
44| **Combined** | While \<state\>, when \<trigger\>, the \<system\> shall \<response\>. | State + event combinations |
45
46### Examples — Model Concepts to EARS Requirements
47
48| ❌ Bad — restates implementation | ✅ Good — EARS pattern |
49|---|---|
50| "Saturation block limits output to [0,1]" | "If throttle command exceeds ThrottleMax (1.0) or falls below ThrottleMin (0.0), then the controller shall clamp the output to the valid range." |
51| "BrakeLogic subsystem disengages controller" | "When brake pedal input exceeds BrakeThreshold (0.0), the controller shall disengage cruise control." |
52| "Gain block multiplies by 2.5" | "While cruise control is active, the controller shall amplify speed error by Kp (2.5) to compute proportional correction." |
53| "Stateflow chart transitions to Idle" | "When the driver presses the off button, the system shall transition to the Idle state." |
54| "Defrost state runs the heater at full power" | "While in the Defrost state, the system shall drive the heater at full power." |
55| "Variant subsystem selects Algorithm A" | "Where the adaptive mode is enabled, the controller shall use the predictive algorithm." |
56
57### Rules
58
59- Write requirements using **EARS patterns** — pick the pattern that matches the model behavior
60- Use block/subsystem names (e.g. `Saturation`, `BrakeLogic`) only in `Rationale`, `Description`, or provenance notes — **never** in the requirement `Summary`. (A workspace *parameter* rendered as `VarName (value)` is required in the Summary and is not a block name.)
61- When referencing a numeric value, include the **workspace variable name and resolved value**: `VarName (value)`. If the model uses a literal with no variable, record the numeric literal directly
62- Put the **WHY** in `Rationale`, not in the requirement statement
63- One subsystem may support zero, one, or several behavioral requirements — don't force a 1:1 mapping
64- For a Stateflow state or mode, separate **entering** it from **being in** it: the entry transition is event-driven (`When <trigger>, … shall transition to <state>`), but the behavior that holds throughout the mode is state-driven (`While <state>, … shall <response>`). When asked for a mode's behavior, prefer the `While <state>` form — do not fold it into a `When` entry statement
65
66## Backend Decision Gate
67
68Choose once at the start, then stay on that path.
69
70| Situation | Backend |
71|-----------|---------|
72| User explicitly asks for `.slreqx`, traceability views, or repo already uses `.slreqx` | **Requirements Toolbox** — if probe fails, **inform the user** that Requirements Toolbox is unavailable; do NOT silently fall back |
73| User explicitly asks for `.yaml`, or repo already uses `.yaml` requirements | **Structured YAML** |
74| No format specified — probe for Requirements Toolbox | **Requirements Toolbox** if probe succeeds |
75| No format specified and probe fails | **Structured YAML** (silent fallback is OK here since user had no preference) |
76
77**Probe** (run via `evaluate_matlab_code`):
78```matlab
79hasSlreq = ~isempty(which('slreq.new'));
80if hasSlreq, try, slreq.find(Type="Link"); catch, hasSlreq = false; end, end
81disp(hasSlreq)
82```
83
84## Workflow
85
86- Call `model_overview`, `model_read`, `model_query_params`, `model_resolve_params` as **MCP tools** — never pass their names to `evaluate_matlab_code`.
87- Use `evaluate_matlab_code` only for MATLAB code, such as the backend probe and the `slreq.*` APIs in Path A.
88
891. **Understand the model** — use the `model_overview` and `model_read` tools to understand subsystems, interfaces, control logic.
902. **Extract parameters** — use the `model_query_params` / `model_resolve_params` tools for thresholds, gains, sample times that should appear in requirement text. Record both variable names and resolved values.
913. **Build a capture table** (backend-neutral):
92
93 | Id | ParentId | Summary | Description | SourceBlock | Rationale | ASIL | Priority | Keywords |
94 |----|----------|---------|-------------|-------------|-----------|------|----------|----------|
95
964. **Run the backend path** (A or B below).
975. **Review** using the gate below.
98
99### Path A — Requirements Toolbox (`.slreqx`)
100
101Use when probe succeeds. For full API patterns see `references/slreq-patterns.md`.
102
103```matlab
104model = "CruiseControl";
105load_system(model);
106rs = slreq.new(model + "_Requirements");
107
108% Add requirements with hierarchy — note behavioral "shall" statements
109req = add(rs, Id="REQ_CC_001", ...
110 Summary="If throttle command exceeds ThrottleMax (1.0) or falls below ThrottleMin (0.0), then the controller shall clamp the output to the valid range.", ...
111 Description="Derived from CruiseControl/ThrottleCmd.");
112req.Rationale = "Prevents invalid actuator commands that could damage the throttle body.";
113req.Keywords = ["draft","auto-generated","control","safety"];
114
115child = add(req, Id="REQ_CC_002", ...
116 Summary="When brake pedal input exceeds BrakeThreshold (0.0), the controller shall disengage cruise control.", ...
117 Description="Derived from CruiseControl/BrakeLogic.");
118child.Keywords = ["draft","auto-generated","safety","brake"];
119
120% Create traceability links: use block handle from SID (blk_X → X) for robustness
121lnk = slreq.createLink(Simulink.ID.getHandle(model + ":5"), req);
122slreq.createLink(Simulink.ID.getHandle(model + ":8"), child);
123
124save(rs);
125% Save all link sets
126linkSets = slreq.find(Type="LinkSet");
127for i = 1:numel(linkSets), save(linkSets(i)); end
128```
129
130**Link rules:**
131- Source = model element, destination = requirement → link type is automatically `Implement`
132- Prefer subsystem-level links; use block-level only when the requirement is block-specific
133- Every model-derived requirement **must** have at least one traceability link
134- The model **must** be loaded (`load_system`) before creating links with block paths
135
136### Path B — Structured YAML fallback
137
138Use when Requirements Toolbox is unavailable. For schema and field rules see `references/yaml-requirements.md`.
139
1401. Generate a `<model>_requirements.yaml` file from the capture table
1412. Set `status: Draft` and include `draft` in `keywords` for every requirement
1423. Self-review: all required fields set, `asil`/`status`/`priority` use valid values, IDs sequential, `derived_from` references valid IDs or is `null`
1434. Validate:
144```bash
145python -c "import yaml, sys; yaml.safe_load(open(sys.argv[1])); print('OK')" path/to/requirements.yaml
146```
147
148## Guardrails
149
150| Always | Never |
151|--------|-------|
152| Mark every generated requirement as **DRAFT** | Emit markdown or ad hoc text when `.slreqx` is available and no text format was requested |
153| Write requirements using EARS patterns | Restate block topology as the requirement summary |
154| Include parameter name + value: `VarName (value)` | Create both `.slreqx` and `.yaml` unless user asks for both |
155| Link direction: model element → requirement | Reverse the link direction (requirement → block) |
156| `load_system` before creating traceability links | Over-link every primitive block — prefer subsystem links |
157| Use only R2023a+ APIs | Silently fall back to YAML when user explicitly requested `.slreqx` |
158| Stay consistent with existing repo format | Renumber existing requirement IDs on regeneration |
159
160## Review Gate
161
162Before finishing, verify (both backends):
163- [ ] Every requirement has `Id`, `Summary`, and `Description`
164- [ ] Every requirement is marked as **DRAFT** (via Keywords or status field)
165- [ ] Summaries use EARS patterns, not block-topology restatements
166- [ ] Numeric values include parameter name + value where a workspace variable exists
167- [ ] IDs are stable and sequential; existing IDs preserved on regeneration
168
169**slreq path only:**
170- [ ] Model-derived requirements have a traceability link to the source model element
171- [ ] Link direction is model element → requirement (not reversed)
172- [ ] Subsystem-level linking preferred over block-level
173- [ ] Requirement set and all link sets are saved
174
175**YAML path only:**
176- [ ] File parses without errors
177- [ ] `asil` and `priority` use valid enum values (or `Unset` when unknown)
178
179## References
180- `references/slreq-patterns.md` — Requirements Toolbox API cookbook
181- `references/yaml-requirements.md` — Structured YAML schema and field rules
182- `assets/slreq_from_model.m` — End-to-end slreq example
183- `assets/requirements.yaml` — Structured YAML example
184
185----
186
187Copyright 2026 The MathWorks, Inc.
188
189----