Plain Markdown has no notion of a requirement. Almirah adds one — a tiny extension on top of regular Markdown that turns selected paragraphs and table rows into controlled items: uniquely identified, referencable, and traceable units. Everything else in your documents stays ordinary Markdown.
A paragraph becomes controlled when its line starts with an ID in square brackets, followed by the text:
[SRS-001] The software shall measure the heart rate in the range from 30 to 250 bpm.In the rendered HTML this paragraph turns into a row with its own anchor, so any other document can reference it. The ID prefix conventionally matches the document (SRS-… in srs.md), and every ID must be unique across the project.
A controlled item links to a higher-level item with the > notation — an up-link:
[SAD-010] The Measurement module computes the heart rate. >[SRS-001]During processing Almirah resolves every up-link into a hyperlink and automatically generates the down-link in the opposite direction, so the requirement also points at the design items that realize it. The same pairs feed the traceability and coverage matrices — see Traceability and Coverage.
A regular Markdown table becomes a controlled table when its rows carry up-links. This is how test protocol steps reference the requirements they verify:
| Test Step # | Test Step Description | Result | Req. Id |
|---|---|---|---|
| 1 | Some preparation step | | |
| 2 | Verify the heart rate range | pass | >[SRS-001] |The same mechanism powers the “Affected Documents” table of decision records and risk records, where each row states a proposed requirement text and links to the requirement it updates:
| # | Proposed Text | Req-ID |
|---|---|---|
| 1 | The software shall provide full-text search over all records. | >[REQ-030] |If the referenced ID exists, the cell renders as a link; if it does not exist yet (a proposed requirement), it stays visibly unresolved — useful while the requirements work is still pending.
Implementation files (C, C++, Python, Java, Ruby, JavaScript, TypeScript, Go, Rust) link up to specifications with REQ tags inside ordinary comments:
# <REQ> Computes the heart rate from the PPG signal. >[SRS-001] </REQ>
def compute_heart_rate(signal)Almirah collects these into an implementation matrix, so every requirement shows the code that realizes it.
The ID must open its own top-level paragraph line. In particular, a controlled paragraph cannot be:
- [REQ-001] text stays a plain list item, no controlled item is created;> up-link notation of controlled tables.And one warning worth remembering: since any paragraph that starts with a bracketed token is treated as a controlled-item ID, never begin an ordinary paragraph with […] — rephrase so the bracket is not the first character of the line.