# rqtk **Requirements that live in your repository, proven by tests.** rqtk keeps requirements, stakeholder needs and verification evidence as TOML files next to your code. A requirement change is a commit, a baseline is a git tag, and history is `git log`. There is no separate tool or database, and no export step between your requirements and your version control. ``` .rqtk/ config.toml ← project policy: categories, states, lint rules requirements/SYS/SYS-0001.toml needs/NEED-0001.toml stakeholders/STK-0001.toml evidence.toml ← which tests passed, against which version of each requirement ``` ## Why Most requirements tools are separate systems: documents, spreadsheets or SaaS platforms, disconnected from source control. Engineers end up maintaining two ledgers, and the two drift apart. rqtk treats requirements as source code, and it holds them to the same standard as code: - **Checked like code.** `rqtk lint` rejects typos, unknown references, cycles and vague statements, with the file and line of every finding. - **Proven, not claimed.** A requirement counts as *verified* only when the tests linked to it passed against its current wording. Reword the requirement and it becomes *Suspect* until those tests pass again. Nobody can mark a requirement done by editing a file. - **Operable by agents.** Every command prints JSON with `--json`, exits with documented codes, and never prompts. Agent skills plug rqtk into a coding agent's normal workflow. ## Where to go next - [Install rqtk](getting-started/installation.md), then follow the [quick start](getting-started/quick-start.md). - Read how [verification from test evidence](guides/verification.md) works: it is the core idea. - Using Claude Code, Codex, Cursor or another coding agent? See [Coding agents](guides/agents.md). --- # Installation ## Prebuilt binaries On macOS and Linux: ```bash curl -LsSf https://rqtk.dev/install.sh | sh ``` On Windows (PowerShell): ```powershell powershell -ExecutionPolicy Bypass -c "irm https://rqtk.dev/install.ps1 | iex" ``` Both scripts download the right binary for your platform from the [latest GitHub release](https://github.com/wdoppenberg/rqtk/releases/latest) and verify its checksum. You can also download an archive from the release page yourself. ## With pip or uv ```bash pip install rqtk # or: uv tool install rqtk ``` The Python package contains the full command line and the `@rqtk.verifies` decorator for linking pytest tests. Wheels are available for Linux, macOS and Windows on Python 3.9 and later. ## With Cargo ```bash cargo install rqtk --locked ``` This needs Rust 1.88 or later. ## Linking tests Linking tests to requirements needs nothing extra for most languages: a `// rqtk: verifies VA-…` comment above a test is enough. Two languages have a checked annotation: - **Rust:** add `rqtk = { version = "1", default-features = false, features = ["macros"] }` to `[dev-dependencies]` and annotate tests with `#[rqtk::verifies("VA-…")]`. An unknown activity ID is a compile error. (The standalone `rqtk-macros` crate works too.) - **Python:** `pip install rqtk` and decorate tests with `@rqtk.verifies("VA-…")`. An unknown activity ID fails test collection. See [Verifying with tests](../guides/verification.md). ## Check the installation ```bash rqtk --version ``` --- # Quick start This walks through the whole loop: set up a repository, write a requirement, prove it with a test, and watch it go Suspect when it changes. ## 1. Initialise In a git repository: ```bash rqtk init ``` This creates `.rqtk/config.toml` with a starter policy, named after your project. Add `--agents` to also install the [agent skills](../guides/agents.md), `--hook` for a pre-commit hook that lints before every commit, and `--example` for an example stakeholder and need. Everything except history (`impact`, `diff`, `log`, `baseline`) works outside a git repository too. ## 2. Add a requirement ```bash rqtk add --category SYS --type Functional \ --title "Fast boot" \ --statement "The system shall boot in under 5 seconds." \ --rationale "Operators restart the unit during a pass." \ --criteria "Boot completes in under 5 s on reference hardware." \ --activity "Boot time test" ``` rqtk assigns the next free ID (here `REQ-SYS-0001`) and writes `.rqtk/requirements/SYS/REQ-SYS-0001.toml`, with a verification activity `VA-SYS-0001-01`: ```toml [verification] method = "Test" level = "Unit" phase = "Development" success_criteria = "Boot completes in under 5 s on reference hardware." [[verification.activities]] id = "VA-SYS-0001-01" name = "Boot time test" ``` `--parent` and `--satisfies` link it to the requirement it derives from and the need it serves; `rqtk add-activity` adds more activities later. Then check it: ```bash rqtk lint ``` ## 3. Link a test Put the activity ID above the test that proves it: ```rust // rqtk: verifies VA-SYS-0001-01 #[test] fn boots_in_under_five_seconds() { // … } ``` `rqtk scan` lists every link it finds, and the test each one is attached to. ## 4. Record the results Run your tests with JUnit output, then hand the report to rqtk: ```bash cargo nextest run # writes target/nextest/default/junit.xml rqtk verify --results target/nextest/default/junit.xml rqtk coverage ``` The requirement is now **Verified**, and `.rqtk/evidence.toml` records which test passed, at which commit, against which version of the requirement. Commit it with the code. ## 5. Change the requirement Tighten the statement to "under 3 seconds" and run `rqtk coverage` again. The requirement is now **Suspect**: its tests passed for the old wording, and nothing has proven the new one. Rerunning the same test doesn't settle it: it passed for 5 seconds and says nothing about 3. Update the test for the new limit, run it, and `rqtk verify` again. (If a test already checks the new wording, record that with `rqtk review REQ-SYS-0001 --note "…"`.) `rqtk coverage --strict` exits 1 until every requirement is Verified, so it works as a CI gate. --- # Writing requirements rqtk tracks three kinds of item, each a TOML file named after its ID: | Item | Lives in | Says | |---|---|---| | **Stakeholder** | `.rqtk/stakeholders/` | who cares about the system | | **Need** | `.rqtk/needs/` | what a stakeholder needs, and why | | **Requirement** | `.rqtk/requirements//` | what the system shall do, and how that is verified | Requirements *satisfy* needs, *decompose* into child requirements through `trace.parents`, and are proven by *verification activities*. Every link is by ID, and `rqtk lint` checks that every link resolves. ## Creating items ```bash rqtk add-stakeholder --name "Operator" --role "Runs the ground station" rqtk add-need --title "Fast recovery" \ --statement "Operators need the unit back within seconds after a restart." \ --stakeholders STK-0001 rqtk add --category SYS --type Functional --title "Fast boot" \ --statement "The system shall boot in under 5 seconds." \ --rationale "Operators restart the unit during a pass." \ --satisfies NEED-0001 \ --criteria "Boot completes in under 5 s on reference hardware." \ --activity "Boot time test" ``` rqtk assigns the next free ID in each case. Pass `--dry-run` to see the file without writing it, and `--json` to get the assigned ID in machine-readable form. `rqtk add` also takes `--parent` (repeatable) for the requirement it decomposes, `--priority`, and `--method`, `--level` and `--phase` for how it is verified. A category listed in `validation.require_parent_for_categories` needs `--parent`. Each `--activity` gets an ID derived from the requirement's: `REQ-SYS-0001` gets `VA-SYS-0001-01`, `VA-SYS-0001-02`, and so on. Tests cite these IDs. Add an activity to an existing requirement with: ```bash rqtk add-activity REQ-SYS-0001 --name "Cold boot test" ``` ## Anatomy of a requirement ```toml id = "REQ-SYS-0001" title = "Fast boot" category = "SYS" type = "Functional" state = "Approved" priority = "High" statement = "The system shall boot in under 5 seconds." rationale = "Operators restart the unit during a pass." [trace] satisfies = ["NEED-0001"] # parents, derived_from, refines, depends_on, conflicts_with, related: all by ID [verification] method = "Test" level = "System" phase = "Development" success_criteria = "Boot completes in under 5 s on reference hardware." [[verification.activities]] id = "VA-SYS-0001-01" name = "Boot time test" ``` The full list of fields is on the [File formats](../reference/file-formats.md) page, and `rqtk schema requirement` prints the JSON Schema. Unknown fields are errors, so a typo is reported instead of silently ignored. ## Good statements `rqtk lint` enforces the basics, and the project configuration can tighten them: - **One sentence, with the shall keyword** (RQ010). Split compound requirements. - **Measurable.** A test must be able to decide pass or fail. Forbid vague words such as "fast" or "user-friendly" with `validation.forbidden_keywords` (RQ011). - **Justified.** A `rationale` says why the requirement exists (RQ007). - **Traced.** Set `trace.parents` to the requirement it decomposes, and `trace.satisfies` to the need it serves. With `forbid_orphans`, every requirement must trace back to a root category (RQ018). ## Finding your way around ```bash rqtk search boot -i # substring search across requirements, needs and stakeholders rqtk trace REQ-SYS-0001 # parents and children rqtk context REQ-SYS-0001 # everything about one item: links, tests, status, findings rqtk graph > trace.dot # the whole graph, for Graphviz ``` ## Configuration `.rqtk/config.toml` decides the vocabulary: categories and their hierarchy, requirement types, lifecycle states, priorities, verification methods, and which lint rules apply. See [Configuration](../reference/configuration.md). To add a category, add a table for it: ```toml [categories.SW] name = "Software" level = 2 ``` Requirement IDs are checked against `--` for the configured categories (RQ001). Set `identification.id_pattern` only if your IDs follow another scheme; then new categories must be added to it too. --- # Verifying with tests A requirement is **verified** only by recorded test results, never by editing a file. rqtk records which tests passed against which version of each requirement. When the requirement changes afterwards, that evidence turns **Suspect** until the tests run again. ## The loop 1. **Link a test** to a verification activity. 2. **Run the tests** with JUnit XML output. 3. **Record the results** with `rqtk verify`. 4. **Check** with `rqtk coverage --strict`, and commit `.rqtk/evidence.toml` with the code. ## Linking tests Put the activity ID directly above the test. Only blank lines, comments, other tags and attributes (`#[test]`, `@Test`, `@pytest.mark.parametrize(…)`, `[Fact]`) may sit in between; the first other line must be the test. | Language | Annotation | Checked when | |---|---|---| | Rust | `#[rqtk::verifies("VA-…")]` (the `rqtk` crate with `default-features = false, features = ["macros"]`) | compile time | | Python | `@rqtk.verifies("VA-…")` | test collection | | Anything | `// rqtk: verifies VA-…` (or `#`, `--`, `/* */`) | `rqtk lint` | rqtk recognises these test declarations: | Language | Tests | |---|---| | Rust | `fn name` | | Python | `def test_x`, `async def test_x`, methods of test classes | | Go | `func TestX`, including methods `func (s *S) TestX` | | JavaScript, TypeScript | `it`, `test` and `describe` (a whole group), with `.only`, `.skip`, `.concurrent`, `.each(…)`; `function name` | | Java, C#, C, C++ | methods and functions (`void name()`, `public async Task Name()`), GoogleTest `TEST`, `TEST_F`, `TEST_P`, Catch2 and doctest `TEST_CASE` | | Kotlin, Swift, Ruby, Zig, Elixir | `fun`, `func`, `def`, `test "name"`, RSpec `it "…" do` | `rqtk scan` shows what each link is attached to. A tag with no test declaration below it can never match a result; `rqtk lint` reports it as an error (RQ030). A test can verify several activities, and an activity can have several tests; it passes only when all of them pass. `rqtk lint` also reports links to unknown activities (RQ028). ### One case of a table-driven test Tag the case's row, and name the case: ```go func TestIntact(t *testing.T) { cases := []struct{ name string; flip bool }{ // rqtk: verifies VA-SYS-0003-01 case "flipped byte is corrupt" {"flipped byte is corrupt", true}, // rqtk: verifies VA-SYS-0003-02 case "intact file passes" {"intact file passes", false}, } // … } ``` The link belongs to the enclosing test and matches the runner's result for that case: Go's `TestIntact/flipped_byte_is_corrupt`, or pytest's `test_x[case]`. In Python and Rust, pass `case` to the annotation instead: `@rqtk.verifies("VA-…", case="neg")`. The same works for rows of a JS/TS `it.each([...])` table, where the case is any part of the rendered title (`case "1+1"` for `"adds 1+1"`), and for GoogleTest value-parameterised tests, where the case is the parameter's value: tag the `TEST_P` with `// rqtk: verifies VA-… case "7"`. ### Display names JUnit's `@DisplayName("…")` and `@ParameterizedTest(name = "…")`, and xUnit's `DisplayName = "…"`, change the name some runners report (Gradle does; Maven Surefire reports the method name). rqtk reads them from the annotations above the test and matches either name. A parameterised JUnit test without a `name` is reported by Gradle as `[1] …` with no trace of the method, so give it a `name`. ### Choosing what is scanned In `.rqtk/config.toml`: ```toml [scan] paths = ["."] # default; .gitignore is honoured exclude = ["tests/fixtures/**"] # gitignore-style globs ``` ## Running tests with JUnit output rqtk reads [JUnit XML](../reference/json-and-exit-codes.md#why-junit-xml), which nearly every test runner can write: | Ecosystem | Command | |---|---| | Rust (nextest) | `cargo nextest run`, with `[profile.default.junit] path = "junit.xml"` in `.config/nextest.toml`; the report lands in `target/nextest/default/` | | Rust (stable libtest) | `RUSTC_BOOTSTRAP=1 cargo test --tests -- -Z unstable-options --format junit > junit.xml` | | Python | `pytest --junitxml=junit.xml` | | Go | `go test -v ./... 2>&1 \| go-junit-report > junit.xml` (`go install github.com/jstemmer/go-junit-report/v2@latest`), or `gotestsum --junitfile junit.xml` | | JS/TS | `vitest run --reporter=junit --outputFile=junit.xml`, `bun test --reporter=junit --reporter-outfile=junit.xml`, or jest with `jest-junit` | | JVM | Maven Surefire and Gradle write JUnit XML by default (`target/surefire-reports/*.xml`, `build/test-results/test/*.xml`) | | C/C++ | `ctest --output-junit junit.xml` (CMake 3.21+), or GoogleTest's `--gtest_output=xml:junit.xml` | `--results` takes several files, so one per package or module works too. ### How results are matched A result matches a link by test name (or display name), together with the suite for GoogleTest and the case for a case link. When several tests share a name, rqtk narrows by the source file the runner reports (Bun, vitest, GoogleTest) or by what the link's path says about the result's class or module. If a linked test still matches several distinct tests, `rqtk verify` records nothing for it and says which tests it matched; rename one. Disabled and skipped tests leave an activity incomplete. ## Recording results ```bash rqtk verify --results junit.xml ``` rqtk matches each test case to the functions linked to each activity and records one entry per activity in `.rqtk/evidence.toml`: the outcome, the tests, the commit, and the **content hash of the requirement at that moment**. - An activity passes only when every linked test ran and passed; a skipped test leaves it incomplete. - A run that covers only some tests, such as the Python suite without the Rust one, leaves other activities' evidence untouched. `verify` counts the linked tests it found no result for, so a runner naming tests differently doesn't go unnoticed. - Evidence names each test as `::`, so the same test gets the same entry whichever runner reported it. - `verify` exits 1 if a linked test failed, if a linked test matched several tests, or if the results matched no linked test at all (usually the wrong file, or tags rqtk can't attach). - `verify --check` writes nothing and exits 1 if the committed evidence doesn't match this run. Use it in CI. ## Coverage states `rqtk coverage` puts every requirement in one state: | State | Meaning | What to do | |---|---|---| | **Verified** | Every activity passed: linked tests against the current wording, or a manual status of Passed/Waived | nothing | | **Suspect** | Evidence no longer settles it; see [Suspect](#suspect) | depends on the reason | | **Failed** | A linked test failed, or a manual status is Failed | fix the code, or with the stakeholder, the requirement | | **In Progress** | Some activities passed or started | finish the rest | | **Planned** | Activities defined, nothing run yet | link and run tests | | **Gap** | No activities, or no success criteria | define them | `rqtk coverage --strict` exits 1 unless every requirement is Verified and every need is satisfied. For requirements written ahead of their implementation, `--allow planned` (and `--allow in-progress`) accepts those states too. ## Suspect A requirement becomes Suspect when evidence recorded for it no longer settles it. `rqtk coverage` and `rqtk context` say why: | Reason | What happened | What settles it | |---|---|---| | changed since its tests passed | its content hash changed after its tests passed | run the tests, `rqtk verify` | | passed again with unchanged tests | it changed, and the same tests that passed for the old wording passed again | change the tests for the new wording and run them, or `rqtk review` | | upstream changed | a parent requirement, or a need it or its ancestors satisfy, changed after it was verified | check it still fits, then `rqtk review` | The **content hash** covers what the requirement demands and how it is verified: the statement, its structural links (parents, depends_on, derived_from, refines, satisfies), its parameters, and the verification method, level and phase. Editing the title, keywords, priority or notes changes nothing. This is deliberate. A reworded requirement may no longer be what the tests check, so rqtk refuses to carry the old verdict over, and rerunning a test that was never updated proves nothing new. `rqtk impact ` lists every activity to re-run after a change. [Change control](change-control.md#review-debt) covers `rqtk review`. ## Activities no test can check Inspections, analyses and demonstrations keep a hand-written status: ```toml [[verification.activities]] id = "VA-SYS-002-01" name = "Thermal analysis" status = "Passed" executed_at = 2026-03-14 evidence = ["reports/thermal-2026-03.pdf"] ``` As soon as a test is linked to an activity, its `status` is ignored, and `rqtk lint` warns until you remove it (RQ029). --- # Baselines and change control Requirement changes that slip through without review are harder to catch than code changes: there is no compiler to notice a modified shall statement. rqtk leans on git for the record and adds what git can't tell you. ## Baselines A baseline is an annotated git tag, `rqtk/`: ```bash rqtk baseline 1.0.0 --dry-run # show what would be stamped and tagged rqtk baseline 1.0.0 ``` It writes `approval.baselined_at` and `approval.baselined_by` into every requirement (leaving the rest of each file untouched), commits that, and tags the commit. ## What changed ```bash rqtk diff 0.9.0 1.0.0 # between baselines, branches, tags or SHAs rqtk impact main # between a revision and your working tree rqtk log SYS-0001 # git history of one requirement ``` `diff` classifies each modified requirement as **semantic** (its content hash changed: statement, links, parameters or verification) or **cosmetic** (anything else). `impact` goes further. For a branch or pull request it lists: - requirements and needs added, removed or changed; - requirements **downstream** of a semantic change, which may need their own review; - every verification activity to **re-run**, because its requirement changed or a file containing one of its tests changed, with the tests to run. Activities whose evidence already covers the change are listed separately. ## Review debt Two kinds of change leave a requirement **Suspect** until someone deals with them, however often the tests run: - **Its tests didn't change with it.** The requirement was reworded and the same tests that passed for the old wording passed again. They may still prove it, or they may test the old behaviour; rqtk can't tell which. - **Something upstream changed.** A parent requirement, or a need it or its ancestors satisfy, changed after it was verified. The child may no longer fit. Each is settled one way: - update the tests for the new wording and run them, then `rqtk verify`; - or confirm the requirement still holds, and record that: ```bash rqtk review REQ-SW-0004 --note "Threshold follows the parent; tests check the configured value." ``` The review lands in `.rqtk/evidence.toml` with the date, the commit and the note, and shows in `rqtk report`. It lasts until the requirement or anything upstream changes again. A review doesn't stand in for running a changed requirement's tests: that Suspect reason stays until they pass. ## Review and sign-off Two platform features make the git log an auditable change record: **CODEOWNERS** routes changes to the right reviewer: ``` .rqtk/requirements/SYS/ @systems-lead .rqtk/requirements/SW/ @software-lead ``` **Signed commits**, enforced by branch protection, tie every change to a verified identity. The `[approval]` table in each requirement is a readable summary for anyone looking at the TOML. The authoritative record is the git log: who signed the commit, and who approved the pull request. ```toml [approval] baselined_at = 2026-11-01 baselined_by = "systems-lead" approved_by = ["systems-lead", "chief-engineer"] ecr_ids = ["ECR-0042"] ``` ## Pre-commit hook ```bash rqtk install-hook # or, in a new repository: rqtk init --hook ``` This adds a managed block to `.git/hooks/pre-commit` that runs `rqtk rehash` (refresh any stored content hashes) and `rqtk lint` before each commit. Existing hook content is kept. New files carry no `content_hash`; rqtk computes it when it needs it. Stamp every file with `rqtk rehash --all` if you want the hash visible in the TOML; lint rule RQ021 then reports when it goes stale. --- # Coding agents rqtk is built to be driven by coding agents as well as people: nothing prompts, every command prints JSON with `--json`, and exit codes are fixed. Four agent skills bring it into an agent's normal workflow. ## Skills ```bash rqtk skills install # or, in a new repository: rqtk init --agents ``` | Skill | Invoked by | What it does | |---|---|---| | `rqtk-requirements` | agent or you | Reading and writing `.rqtk/`: find the governing requirement, read its briefing, author items that lint clean. | | `rqtk-verification` | agent or you | The proof loop: link a test, run it, `rqtk verify`; done when `rqtk lint` and `rqtk coverage --strict` exit 0. | | `/to-requirements` | you | Turn a spec or discussion into needs and requirements with verification activities; you approve the draft before anything is written. | | `/requirements-review` | you | Review a diff against the requirements it touches: facts from `rqtk impact`, then a verdict per requirement, and the `rqtk review` commands that would settle what is still Suspect. | The skills follow the open [Agent Skills](https://agentskills.io) format, so they work with any agent that supports it: | Agents | Read skills from | What rqtk installs | |---|---|---| | Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Amp, Cline, Zed, Warp, … | `.agents/skills/` | the skill files | | Claude Code | `.claude/skills/` | a link per skill into `.agents/skills/` | `rqtk skills install --for claude` or `--for universal` installs for one family only; `--copy` writes copies instead of links; `--dir` installs anywhere else. The skills are compiled into the binary, so they always describe the rqtk you have. Reinstall after upgrading: untouched skills are updated, and skills you edited are kept. rqtk also adds a short block to `AGENTS.md` (and to `CLAUDE.md`, unless it already imports `@AGENTS.md`) telling agents where requirements live and when work is done. It never creates those files unless you name one with `--instructions`. ## Where the skills fit The skills are small and slot into an existing flow rather than imposing one. They were designed alongside [mattpocock/skills](https://github.com/mattpocock/skills): ``` grill → /to-spec → /to-requirements → /to-tickets → /implement → /code-review + /requirements-review ``` - `/to-requirements` turns the spec into requirements with activity IDs. - Tickets cite those IDs in their acceptance criteria. - The implementer's tests cite the activity IDs, and `rqtk verify` records them. - `/requirements-review` checks the result on the requirements axis, next to the usual code review. ## Commands agents use most ```bash rqtk context REQ-SYS-0001 --json # the briefing: statement, links, tests, status, findings rqtk impact main --json # what a change touches, what to re-verify, and with which tests rqtk lint --json # findings with code, severity and file:line rqtk explain RQ010 # what a rule checks and how to fix it rqtk schema requirement # the JSON Schema of a file kind rqtk add … --parent … --criteria … --activity … # a complete requirement in one command ``` Exit codes and the JSON contract are described under [JSON output and exit codes](../reference/json-and-exit-codes.md). ## Machine-readable docs These docs are also available in plain Markdown for agents: [`/llms.txt`](/llms.txt) indexes every page, and [`/llms-full.txt`](/llms-full.txt) contains them all in one file. --- # Continuous integration Three commands make a complete requirements gate: ```bash rqtk lint # every file valid, every link resolves rqtk verify --check --results junit.xml # committed evidence matches this test run rqtk coverage --strict # every requirement Verified ``` Each exits 1 when it finds a problem, so any CI system can use them directly. If you write requirements ahead of their implementation, `rqtk coverage --strict --allow planned` lets those through while still failing on anything Suspect, Failed or half-done. ## GitHub Actions ```yaml name: Requirements on: [push, pull_request] jobs: requirements: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - uses: dtolnay/rust-toolchain@stable - uses: taiki-e/install-action@v2 with: tool: cargo-nextest - name: Install rqtk run: curl -LsSf https://rqtk.dev/install.sh | sh - name: Test run: cargo nextest run --profile ci # writes target/nextest/ci/junit.xml - run: rqtk lint - run: rqtk verify --check --results target/nextest/ci/junit.xml - run: rqtk coverage --strict ``` Configure the `ci` nextest profile to write JUnit in `.config/nextest.toml`: ```toml [profile.ci.junit] path = "junit.xml" ``` ## Why `verify --check` Evidence is committed, so it is reviewed like code. `verify --check` makes sure it is honest: it fails when the committed `.rqtk/evidence.toml` doesn't match what this CI run observed. For example, someone may have changed a requirement without re-running its tests, or a test may now fail. To fix it, run the tests and `rqtk verify` locally, then commit the updated evidence. Editing a test that still passes doesn't count as a mismatch. Reviews recorded with `rqtk review` live in the same file, so they reach the main branch through the same pull request review as the change they settle. ## Pull request review `rqtk impact origin/main --json` lists the requirements a pull request changes, the requirements downstream of them, and the activities to re-verify. It is a good input for a review bot, or for the `/requirements-review` [agent skill](agents.md). --- # Commands Every command accepts `--json` (one JSON document on stdout) and `--repo-root `. The same text is available from `rqtk --help`. ```text Requirements Toolkit Usage: rqtk [OPTIONS] Commands: init Scaffold a new requirement set in the current repo add Add a new requirement with the next free ID in its category add-activity Add a verification activity to an existing requirement add-stakeholder Add a new stakeholder definition add-need Add a new stakeholder need lint Check every file against the schema, the config and the `verifies` links in source context Everything relevant to one requirement, need or stakeholder: links, tests, status, evidence and lint findings. Designed as the briefing for working on an item impact What changed since a git revision, and which requirements and activities it affects trace Show the parent/child traceability chain of a requirement coverage Report need satisfaction and verification status (verified / suspect / failed / …) graph Print the traceability graph of stakeholders, needs and requirements baseline Stamp all requirements and create a git tag baseline for HEAD export Export requirements to a file in the given format diff Show requirements that changed between two git revisions or baselines scan List `verifies` links between source code and verification activities verify Record test results as verification evidence in `.rqtk/evidence.toml` review Confirm a requirement still holds after something it depends on changed search Search requirements, needs and stakeholders by substring open Open a requirement file in $EDITOR log Show the git commit history for a single requirement install-hook Install a git pre-commit hook that runs `rqtk rehash` and `rqtk lint` rehash Refresh stored content hashes that no longer match their requirement or need report Generate a Markdown requirements report schema Print the JSON Schema of a file kind, or list the kinds explain Explain a lint rule and how to fix it, or list all rules skills Agent skills for working with rqtk in coding agents (Claude Code, Codex, …) help Print this message or the help of the given subcommand(s) Options: --repo-root Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help -V, --version Print version Exit codes: 0 success, nothing to report 1 findings: lint errors, failed or suspect verification, stale evidence 2 usage error: bad arguments or unsupported option 3 error: configuration, I/O or git failure ``` ## `rqtk init` ```text Scaffold a new requirement set in the current repo Usage: rqtk init [OPTIONS] Options: --repo-root Repository root (the directory containing `.rqtk/`) [default: .] --requirements-dir --force Overwrite an existing `.rqtk/config.toml` --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON --agents Also install the agent skills (see `rqtk skills install`) --example Also create an example stakeholder and need --hook Also install the git pre-commit hook (see `rqtk install-hook`) --dry-run Report the files that would be created without writing them -h, --help Print help ``` ## `rqtk add` ```text Add a new requirement with the next free ID in its category Usage: rqtk add [OPTIONS] --category --type --title --statement <STATEMENT> Options: --category <CATEGORY> Category key from `.rqtk/config.toml`, e.g. SYS --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON --type <REQ_TYPE> Requirement type from `types.allowed` --title <TITLE> --statement <STATEMENT> A single normative sentence, e.g. "The system shall …" --rationale <RATIONALE> --parent <PARENTS> Parent requirement ID (repeatable, or comma-separated) --satisfies <SATISFIES> ID of a need this requirement satisfies (repeatable, or comma-separated) --priority <PRIORITY> Priority from `priority.levels` [default: Medium, or the middle level] --method <METHOD> Verification method from `verification.methods` [default: the first] --level <LEVEL> Verification level from `verification.levels` [default: the first] --phase <PHASE> Verification phase from `verification.phases` [default: the first] --criteria <CRITERIA> Success criteria: what a passing verification shows --activity <ACTIVITIES> Add a verification activity with this name (repeatable). IDs are generated as VA-<CATEGORY>-<NUMBER>-<NN> --dry-run Print the file that would be created without writing it -h, --help Print help ``` ## `rqtk add-activity` ```text Add a verification activity to an existing requirement Usage: rqtk add-activity [OPTIONS] --name <NAME> <REQUIREMENT> Arguments: <REQUIREMENT> Requirement ID Options: --name <NAME> What the activity checks --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --id <ID> Defaults to the next free VA-<CATEGORY>-<NUMBER>-<NN> --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON --dry-run Print the activity that would be added without writing it -h, --help Print help ``` ## `rqtk add-stakeholder` ```text Add a new stakeholder definition Usage: rqtk add-stakeholder [OPTIONS] --name <NAME> Options: --id <ID> Defaults to the next free STK-NNN --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON --name <NAME> --role <ROLE> --organization <ORGANIZATION> --dry-run Print the file that would be created without writing it -h, --help Print help ``` ## `rqtk add-need` ```text Add a new stakeholder need Usage: rqtk add-need [OPTIONS] --title <TITLE> --statement <STATEMENT> Options: --id <ID> Defaults to the next free NEED-NNNN --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON --title <TITLE> --statement <STATEMENT> --stakeholders <STAKEHOLDERS> Stakeholder IDs associated with this need (comma-separated) --rationale <RATIONALE> Why the stakeholders need it --dry-run Print the file that would be created without writing it -h, --help Print help ``` ## `rqtk lint` ```text Check every file against the schema, the config and the `verifies` links in source Usage: rqtk lint [OPTIONS] Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk context` ```text Everything relevant to one requirement, need or stakeholder: links, tests, status, evidence and lint findings. Designed as the briefing for working on an item Usage: rqtk context [OPTIONS] <ID> Arguments: <ID> Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk impact` ```text What changed since a git revision, and which requirements and activities it affects Usage: rqtk impact [OPTIONS] <BASE> Arguments: <BASE> Branch, tag, SHA, `HEAD~N` or baseline name to compare the working tree against Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk trace` ```text Show the parent/child traceability chain of a requirement Usage: rqtk trace [OPTIONS] <ID> Arguments: <ID> Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk coverage` ```text Report need satisfaction and verification status (verified / suspect / failed / …) Usage: rqtk coverage [OPTIONS] Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --strict Exit 1 unless every requirement is Verified and every need is satisfied --allow <ALLOW> With --strict, also accept requirements in this state (repeatable), e.g. for requirements written ahead of their implementation Possible values: - planned: Activities defined, nothing run yet - in-progress: Some activities done, not all --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -s, --short Print only the one-line summary -h, --help Print help (see a summary with '-h') ``` ## `rqtk graph` ```text Print the traceability graph of stakeholders, needs and requirements Usage: rqtk graph [OPTIONS] Options: --format <FORMAT> Possible values: - dot: Graphviz DOT [default: dot] --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help (see a summary with '-h') ``` ## `rqtk baseline` ```text Stamp all requirements and create a git tag baseline for HEAD Usage: rqtk baseline [OPTIONS] <VERSION> Arguments: <VERSION> Options: --dry-run Report what would be stamped and tagged without changing anything --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk export` ```text Export requirements to a file in the given format Usage: rqtk export [OPTIONS] --format <FORMAT> Options: --format <FORMAT> [possible values: csv, json, markdown] --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON --output <OUTPUT> -h, --help Print help ``` ## `rqtk diff` ```text Show requirements that changed between two git revisions or baselines Usage: rqtk diff [OPTIONS] <FROM> <TO> Arguments: <FROM> <TO> Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk scan` ```text List `verifies` links between source code and verification activities Usage: rqtk scan [OPTIONS] Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk verify` ```text Record test results as verification evidence in `.rqtk/evidence.toml`. Reads JUnit XML (cargo-nextest, pytest --junitxml, go-junit-report, jest-junit, …), matches test cases to `verifies` links and records each activity's outcome against the requirement's current content hash. Usage: rqtk verify [OPTIONS] --results <RESULTS>... Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --results <RESULTS>... JUnit XML result files --check Do not write; exit 1 if the evidence file is out of date --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON --dry-run Report what would be recorded without writing -h, --help Print help (see a summary with '-h') ``` ## `rqtk review` ```text Confirm a requirement still holds after something it depends on changed. Settles a Suspect requirement whose tests passed again unchanged after it was reworded, or whose ancestor or need changed. Recorded in `.rqtk/evidence.toml`. Usage: rqtk review [OPTIONS] <ID> Arguments: <ID> Requirement ID Options: --note <NOTE> Why the requirement still holds, kept with the review --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --dry-run Report what would be recorded without writing --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help (see a summary with '-h') ``` ## `rqtk search` ```text Search requirements, needs and stakeholders by substring Usage: rqtk search [OPTIONS] <PATTERN> Arguments: <PATTERN> Pattern to search for Options: -i, --ignore-case Case-insensitive matching --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] -f, --field <FIELD> Restrict search to specific fields: id, title, statement, rationale, notes, keywords --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk open` ```text Open a requirement file in $EDITOR Usage: rqtk open [OPTIONS] <ID> Arguments: <ID> Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk log` ```text Show the git commit history for a single requirement Usage: rqtk log [OPTIONS] <ID> Arguments: <ID> Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk install-hook` ```text Install a git pre-commit hook that runs `rqtk rehash` and `rqtk lint` Usage: rqtk install-hook [OPTIONS] Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk rehash` ```text Refresh stored content hashes that no longer match their requirement or need. Only files that carry a `content_hash` are touched; `--all` also stamps the rest. Usage: rqtk rehash [OPTIONS] Options: --all Also write a hash into files that have none --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --dry-run Report stale hashes without writing --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help (see a summary with '-h') ``` ## `rqtk report` ```text Generate a Markdown requirements report Usage: rqtk report [OPTIONS] Options: -o, --output <OUTPUT> Write to this file instead of stdout --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk schema` ```text Print the JSON Schema of a file kind, or list the kinds Usage: rqtk schema [OPTIONS] [KIND] Arguments: [KIND] config, requirement, need, stakeholder or evidence Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk explain` ```text Explain a lint rule and how to fix it, or list all rules Usage: rqtk explain [OPTIONS] [CODE] Arguments: [CODE] Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ## `rqtk skills` ```text Agent skills for working with rqtk in coding agents (Claude Code, Codex, …) Usage: rqtk skills [OPTIONS] <COMMAND> Commands: list List the bundled skills and who can invoke them install Write the skills into the repo and point AGENTS.md / CLAUDE.md at them help Print this message or the help of the given subcommand(s) Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ### `rqtk skills list` ```text List the bundled skills and who can invoke them Usage: rqtk skills list [OPTIONS] Options: --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON -h, --help Print help ``` ### `rqtk skills install` ```text Write the skills into the repo and point AGENTS.md / CLAUDE.md at them. By default the skills go into `.agents/skills` (read by Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Amp and most other agents), and `.claude/skills` links to them for Claude Code. Skills you have edited are kept unless --force is given. The rqtk block goes into AGENTS.md and/or CLAUDE.md where they exist; no file is created unless named with --instructions. Usage: rqtk skills install [OPTIONS] Options: --for <TARGETS> Agents to install for Possible values: - universal: `.agents/skills`: the shared location read by Codex, Cursor, GitHub Copilot, Gemini CLI, OpenCode, Amp, Cline, Zed, Warp and others - claude: `.claude/skills`: Claude Code [default: universal claude] --repo-root <REPO_ROOT> Repository root (the directory containing `.rqtk/`) [default: .] --dir <DIR> Install a single copy into this directory instead (overrides --for) --json Print one JSON document to stdout instead of text. Errors go to stderr as JSON --copy Copy the skills into .claude/skills instead of linking to .agents/skills --instructions <INSTRUCTIONS> Instructions file (AGENTS.md or CLAUDE.md) to add the rqtk block to; created if missing. Repeat for several --force Replace skills that were edited locally --dry-run Report what would be written without writing -h, --help Print help (see a summary with '-h') ``` --- <!-- https://rqtk.dev/docs/reference/configuration.md --> <!-- Generated by site/build.py from the rqtk binary; do not edit. --> # Configuration `.rqtk/config.toml` sets the project's vocabulary and policy. `rqtk init` writes a starting point; `rqtk schema config` prints the JSON Schema. ## Fields | Field | Type | Required | Description | |---|---|---|---| | `categories` | table of [`Category`](#category) | yes | | | `criticality` | [`CriticalityPolicy`](#criticalitypolicy) | yes | | | `identification` | [`IdentificationScheme`](#identificationscheme) | yes | | | `lifecycle` | [`LifecyclePolicy`](#lifecyclepolicy) | yes | | | `priority` | [`PriorityPolicy`](#prioritypolicy) | yes | | | `project` | [`ProjectMeta`](#projectmeta) | yes | | | `repository` | [`RepositoryLayout`](#repositorylayout) | | | | `scan` | [`ScanConfig`](#scanconfig) | | | | `schema_version` | integer | yes | File format version; must equal the version supported by this build of rqtk. | | `standards` | list of [`Standard`](#standard) | | | | `types` | [`TypePolicy`](#typepolicy) | yes | | | `validation` | [`ValidationRules`](#validationrules) | yes | | | `verification` | [`VerificationPolicy`](#verificationpolicy) | yes | | ### Category | Field | Type | Required | Description | |---|---|---|---| | `description` | string (optional) | | | | `is_root` | boolean | | Marks this category as a traceability root. At least one category should set this to `true` for orphan detection to work. | | `level` | integer | yes | | | `name` | string | yes | | ### CriticalityPolicy | Field | Type | Required | Description | |---|---|---|---| | `levels` | list of string | yes | | ### IdentificationScheme | Field | Type | Required | Description | |---|---|---|---| | `id_pattern` | string (optional) | | Regular expression every requirement ID must match (RQ001). When omitted, it is derived from `prefix`, `id_separator`, the category keys and `zero_padding`, so a new category needs no pattern change. | | `id_separator` | string | | | | `prefix` | string | | | | `zero_padding` | integer | | | ### LifecyclePolicy | Field | Type | Required | Description | |---|---|---|---| | `default_state` | string | yes | | | `states` | list of string | yes | | ### PriorityPolicy | Field | Type | Required | Description | |---|---|---|---| | `levels` | list of string | yes | | ### ProjectMeta | Field | Type | Required | Description | |---|---|---|---| | `classification` | string (optional) | | | | `created` | string (optional) | | | | `description` | string (optional) | | | | `mission_phase` | string (optional) | | | | `name` | string | yes | | | `organization` | [`ProjectOrganization`](#projectorganization) (optional) | | | | `risk_posture` | string (optional) | | | | `short_name` | string (optional) | | | | `updated` | string (optional) | | | | `version` | string | yes | | ### RepositoryLayout | Field | Type | Required | Description | |---|---|---|---| | `needs_dir` | string | | | | `required_dirs` | list of string | | | | `required_files` | list of string | | | | `requirements_dir` | string | | | | `stakeholders_dir` | string | | | ### ScanConfig Where `rqtk scan` looks for `verifies` annotations in source code. | Field | Type | Required | Description | |---|---|---|---| | `exclude` | list of string | | Glob patterns (gitignore syntax) to skip, e.g. `"tests/fixtures/**"`. | | `extensions` | list of string | | File extensions to read. | | `paths` | list of string | | Directories to scan, relative to the repository root. `.gitignore` is honoured. | ### Standard | Field | Type | Required | Description | |---|---|---|---| | `id` | string | yes | | | `revision` | string (optional) | | | | `title` | string | yes | | ### TypePolicy | Field | Type | Required | Description | |---|---|---|---| | `allowed` | list of string | yes | | ### ValidationRules | Field | Type | Required | Description | |---|---|---|---| | `allow_tbd` | boolean | yes | | | `allow_tbr` | boolean | yes | | | `forbid_circular_traces` | boolean | yes | | | `forbid_orphans` | boolean | yes | | | `forbidden_keywords` | list of string | | | | `require_parent_for_categories` | list of string | | Category keys whose requirements must have at least one parent (RQ012). `require_parent_for_levels` is accepted as an older name. | | `require_rationale` | boolean | yes | | | `require_verification_method` | boolean | yes | | | `shall_keywords` | list of string | | | ### VerificationPolicy | Field | Type | Required | Description | |---|---|---|---| | `levels` | list of string | yes | | | `methods` | list of string | yes | | | `phases` | list of string | yes | | ### ProjectOrganization | Field | Type | Required | Description | |---|---|---|---| | `center` | string (optional) | | | | `cognizant_authority` | string (optional) | | | | `program` | string (optional) | | | | `responsible_engineer` | string (optional) | | | --- <!-- https://rqtk.dev/docs/reference/file-formats.md --> <!-- Generated by site/build.py from the rqtk binary; do not edit. --> # File formats Every file under `.rqtk/` is TOML and is checked against these fields; unknown fields are errors. Dates may be native TOML dates (`2026-03-14`) or strings. `rqtk schema <kind>` prints the JSON Schema of each. ## Requirement One requirement file. Scalars sit at the top level; related groups are tables. | Field | Type | Required | Description | |---|---|---|---| | `allocation` | [`Allocation`](#allocation) (optional) | | | | `approval` | [`Approval`](#approval) (optional) | | | | `assumptions` | list of string | | | | `category` | string | yes | | | `content_hash` | string (optional) | | Fingerprint of the semantic fields, see [`Requirement::compute_content_hash`]. Maintained by `rqtk rehash`; checked by lint rule RQ021. | | `criticality` | string (optional) | | | | `custom` | object | | | | `id` | [`RequirementId`](#requirementid) | yes | | | `keywords` | list of string | | | | `maturity` | string (optional) | | | | `notes` | string (optional) | | | | `parameters` | list of [`Parameter`](#parameter) | | | | `priority` | string | yes | | | `rationale` | string (optional) | | | | `risk` | [`Risk`](#risk) (optional) | | | | `state` | string | yes | | | `statement` | string | yes | The normative statement, e.g. "The system shall …". | | `tbd` | boolean | | | | `tbr` | boolean | | | | `title` | string | yes | | | `trace` | [`Traceability`](#traceability) | | | | `type` | string | yes | | | `validation` | [`ValidationSpec`](#validationspec) (optional) | | | | `verification` | [`Verification`](#verification) | yes | | ### Allocation | Field | Type | Required | Description | |---|---|---|---| | `components` | list of string | | | | `software_modules` | list of string | | | | `source_files` | list of string | | | | `subsystems` | list of string | | | ### Approval | Field | Type | Required | Description | |---|---|---|---| | `approved_by` | list of string | | | | `baselined_at` | string (optional) | | | | `baselined_by` | string (optional) | | | | `ecr_ids` | list of string | | | ### Parameter | Field | Type | Required | Description | |---|---|---|---| | `name` | string | yes | | | `operator` | string | yes | | | `tolerance` | number (optional) | | | | `unit` | string (optional) | | | | `value` | any | yes | | ### RequirementId Identifier of a requirement, e.g. `FOBC-SYS-0001`. Type: string ### Risk | Field | Type | Required | Description | |---|---|---|---| | `fmea_ref` | string (optional) | | | | `hazards` | list of string | | | | `mitigations` | list of string | | | | `safety_critical` | boolean | | | | `security_sensitive` | boolean | | | ### Traceability | Field | Type | Required | Description | |---|---|---|---| | `conflicts_with` | list of [`RequirementId`](#requirementid) | | | | `depends_on` | list of [`RequirementId`](#requirementid) | | | | `derived_from` | list of [`RequirementId`](#requirementid) | | | | `external` | list of [`ExternalTrace`](#externaltrace) | | | | `parents` | list of [`RequirementId`](#requirementid) | | | | `refines` | list of [`RequirementId`](#requirementid) | | | | `related` | list of [`RequirementId`](#requirementid) | | | | `satisfies` | list of [`NeedId`](#needid) | | | ### ValidationSpec | Field | Type | Required | Description | |---|---|---|---| | `acceptance_criteria` | string (optional) | | | | `method` | string (optional) | | | | `stakeholder` | [`StakeholderId`](#stakeholderid) (optional) | | | | `status` | string (optional) | | | ### Verification | Field | Type | Required | Description | |---|---|---|---| | `activities` | list of [`VerificationActivity`](#verificationactivity) | | | | `level` | string | yes | | | `method` | string | yes | | | `owner` | string (optional) | | | | `phase` | string | yes | | | `success_criteria` | string (optional) | | | ### ExternalTrace | Field | Type | Required | Description | |---|---|---|---| | `ref` | string | yes | | | `type` | string | yes | | ### NeedId Identifier of a stakeholder need, e.g. `NEED-0001`. Type: string ### StakeholderId Identifier of a stakeholder, e.g. `STK-001`. Type: string ### VerificationActivity | Field | Type | Required | Description | |---|---|---|---| | `evidence` | list of string | | | | `executed_at` | string (optional) | | | | `expected_result` | string (optional) | | | | `id` | string | yes | | | `name` | string | yes | | | `procedure` | string (optional) | | | | `status` | string (optional) | | | ## Need | Field | Type | Required | Description | |---|---|---|---| | `acceptance` | [`Acceptance`](#acceptance) (optional) | | | | `content_hash` | string (optional) | | | | `id` | [`NeedId`](#needid) | yes | | | `keywords` | list of string | | | | `priority` | string (optional) | | | | `rationale` | string (optional) | | | | `stakeholders` | list of [`StakeholderId`](#stakeholderid) | | | | `state` | string | yes | | | `statement` | string | yes | | | `title` | string | yes | | ### Acceptance | Field | Type | Required | Description | |---|---|---|---| | `criteria` | string (optional) | | | | `validated_at` | string (optional) | | | | `validated_by` | string (optional) | | | ### NeedId Identifier of a stakeholder need, e.g. `NEED-0001`. Type: string ### StakeholderId Identifier of a stakeholder, e.g. `STK-001`. Type: string ## Stakeholder | Field | Type | Required | Description | |---|---|---|---| | `authority` | [`StakeholderAuthority`](#stakeholderauthority) | | | | `concerns` | [`StakeholderConcerns`](#stakeholderconcerns) | | | | `id` | [`StakeholderId`](#stakeholderid) | yes | | | `name` | string | yes | | | `organization` | string (optional) | | | | `role` | string (optional) | | | ### StakeholderAuthority | Field | Type | Required | Description | |---|---|---|---| | `approval_scope` | string (optional) | | | | `sign_off_required` | boolean | | | ### StakeholderConcerns | Field | Type | Required | Description | |---|---|---|---| | `primary` | list of string | | | | `secondary` | list of string | | | ### StakeholderId Identifier of a stakeholder, e.g. `STK-001`. Type: string ## Evidence (`.rqtk/evidence.toml`) | Field | Type | Required | Description | |---|---|---|---| | `activity` | list of [`ActivityEvidence`](#activityevidence) | | | | `review` | list of [`Review`](#review) | | | | `schema_version` | integer | yes | | | `written_by` | string (optional) | | Version of rqtk that last wrote the file. | ### ActivityEvidence The latest recorded result for one verification activity. Unknown fields are ignored so that files written by a later rqtk still load. | Field | Type | Required | Description | |---|---|---|---| | `commit` | string (optional) | | Commit checked out when the evidence was recorded. | | `id` | string | yes | Verification activity ID. | | `outcome` | [`Outcome`](#outcome) | yes | | | `requirement` | [`RequirementId`](#requirementid) | yes | Requirement that owned the activity when the evidence was recorded. | | `requirement_hash` | string | yes | The requirement's content hash when the evidence was recorded. If the requirement's current hash differs, the evidence is stale and the activity is Suspect. | | `tests` | list of string | yes | Test cases that produced the outcome, as `path::name`: the linked test's source file and the name the runner gave the case. | | `tests_hash` | string (optional) | | Hash of the linked tests' source when they last ran. | | `unchanged_tests` | boolean | | The requirement was re-verified after it changed, by the same tests that passed for its earlier wording. It stays Suspect until someone runs `rqtk review`. | | `upstream` | table of string | | Content hashes of the requirement's ancestors and of the needs they satisfy, when this version of the requirement was first verified. A later change to any of them makes the requirement Suspect until it is reviewed. | ### Review A person's or agent's confirmation that a requirement still holds after something it depends on changed, recorded with `rqtk review`. | Field | Type | Required | Description | |---|---|---|---| | `commit` | string (optional) | | Commit checked out when the review was recorded. | | `date` | string | yes | Date of the review, `YYYY-MM-DD`. | | `note` | string (optional) | | | | `requirement` | [`RequirementId`](#requirementid) | yes | | | `requirement_hash` | string | yes | The requirement's content hash when it was reviewed; a later change voids the review. | | `upstream` | table of string | | Content hashes of its ancestors and their needs when it was reviewed. | ### Outcome Type: `passed` \| `failed` ### RequirementId Identifier of a requirement, e.g. `FOBC-SYS-0001`. Type: string --- <!-- https://rqtk.dev/docs/reference/lint-rules.md --> <!-- Generated by site/build.py from the rqtk binary; do not edit. --> # Lint rules `rqtk lint` reports these findings. Codes are stable: a code keeps its meaning and is never reused. `rqtk explain <code>` prints the same information. | Code | Severity | Checks | How to fix | |---|---|---|---| | <span id="rq001">RQ001</span> | error | requirement ID does not match the ID pattern | Rename the ID (and file) to `<prefix>-<CATEGORY>-<NUMBER>`, as `rqtk add` does, or set `identification.id_pattern` in .rqtk/config.toml to accept it. | | <span id="rq002">RQ002</span> | error | unknown category | Use a key from `[categories]` in .rqtk/config.toml, or add the category there. | | <span id="rq003">RQ003</span> | error | unknown requirement type | Use a value from `types.allowed`, or add the type there. | | <span id="rq004">RQ004</span> | error | invalid lifecycle state | Use a value from `lifecycle.states`. | | <span id="rq005">RQ005</span> | error | invalid priority | Use a value from `priority.levels`. | | <span id="rq006">RQ006</span> | error | invalid criticality | Use a value from `criticality.levels`, or remove `criticality`. | | <span id="rq007">RQ007</span> | error | rationale is required but missing | Add `rationale = "…"` explaining why the requirement exists. | | <span id="rq008">RQ008</span> | error | verification method is required but missing | Set `verification.method` to a value from `verification.methods`. | | <span id="rq009">RQ009</span> | error | invalid verification method | Use a value from `verification.methods`. | | <span id="rq010">RQ010</span> | error | statement is not exactly one sentence with a shall keyword | Rewrite `statement` as one sentence using a keyword from `validation.shall_keywords`; split compound requirements. | | <span id="rq011">RQ011</span> | error | statement uses a forbidden keyword | Replace the vague word with a measurable criterion. | | <span id="rq012">RQ012</span> | error | category requires at least one parent | Add the requirement it decomposes to `trace.parents`. | | <span id="rq013">RQ013</span> | error | TBD is not allowed by project policy | Resolve the open item and set `tbd = false`. | | <span id="rq014">RQ014</span> | error | TBR is not allowed by project policy | Resolve the open item and set `tbr = false`. | | <span id="rq015">RQ015</span> | error | unknown parent reference | Correct the ID in `trace.parents` or create the parent requirement. | | <span id="rq016">RQ016</span> | error | unknown depends_on reference | Correct the ID in `trace.depends_on`. | | <span id="rq017">RQ017</span> | error | requirement is part of a traceability cycle | Remove one of the parents/depends_on/derived_from/refines links named in the message. | | <span id="rq018">RQ018</span> | warning | orphan requirement has no path to a root category | Add a `trace.parents` chain that reaches a category with `is_root = true`. | | <span id="rq019">RQ019</span> | error | repository is missing a required directory | Create the directory, or remove it from `repository.required_dirs`. | | <span id="rq020">RQ020</span> | error | repository is missing a required file | Create the file, or remove it from `repository.required_files`. | | <span id="rq021">RQ021</span> | warning | content hash is stale | Run `rqtk rehash`. | | <span id="rq022">RQ022</span> | error | `trace.satisfies` references an unknown need | Correct the need ID or create it with `rqtk add-need`. | | <span id="rq023">RQ023</span> | error | reference to an unknown stakeholder | Correct the stakeholder ID or create it with `rqtk add-stakeholder`. | | <span id="rq024">RQ024</span> | error | invalid verification level | Use a value from `verification.levels`. | | <span id="rq025">RQ025</span> | error | invalid verification phase | Use a value from `verification.phases`. | | <span id="rq026">RQ026</span> | error | unknown derived_from / refines / conflicts_with / related reference | Correct the ID in the named `trace` field. | | <span id="rq027">RQ027</span> | error | verification activity ID is defined more than once | Give each `[[verification.activities]]` entry a unique `id`. | | <span id="rq028">RQ028</span> | error | `verifies` annotation names an unknown verification activity | Correct the activity ID in the annotation, or add the activity to a requirement. | | <span id="rq029">RQ029</span> | warning | hand-written status on an activity whose status comes from tests | Remove `status` (and `executed_at`) from the activity; run tests and `rqtk verify` instead. | | <span id="rq030">RQ030</span> | error | `verifies` annotation is not followed by a test rqtk recognises | Place the annotation directly above the test, with only comments and attributes in between. For one case of a table-driven test, tag its row: `// rqtk: verifies VA-… case "name"`. `rqtk scan` shows what each annotation is attached to. | | <span id="rq031">RQ031</span> | warning | an activity's evidence file does not exist | Correct the path (relative to the repository root), add the file, or link to it with a URL. | | <span id="rq100">RQ100</span> | error | file could not be read or parsed (syntax error, unknown or missing field) | Fix the TOML at the reported line; `rqtk schema <kind>` lists the allowed fields. | | <span id="rq101">RQ101</span> | error | ID is defined in more than one file | Give one of the items a new ID and rename its file to match. | | <span id="rq102">RQ102</span> | error | file name does not match the ID it contains | Rename the file to `<ID>.toml`. | --- <!-- https://rqtk.dev/docs/reference/json-and-exit-codes.md --> # JSON output and exit codes ## `--json` Every command accepts `--json` and prints exactly one JSON document on stdout. - Paths are relative to the repository root. - Diagnostics carry `code`, `severity`, `message`, `subject` (the item they concern) and `location` (`path`, `line`, `column`). - Errors go to **stderr** as `{"error": {"kind": "usage" | "error", "message": "…"}}`, and stdout stays empty. - Commands whose output is a document in another format (`report`, `graph`, `open`) reject `--json` with a usage error. Within 1.x, JSON output only **gains** fields. No field is removed, renamed or given a different type; a test in the rqtk repository enforces this against a recorded snapshot of every command's output. Parse leniently and ignore fields you don't know. ## Exit codes | Code | Meaning | |---|---| | 0 | Success, nothing to report. | | 1 | Findings: lint errors, any requirement not Verified under `coverage --strict`, failed or ambiguous tests in `verify` or results that match no linked test, stale evidence under `verify --check`, link errors in `scan`. | | 2 | Usage error: bad arguments, an unknown category, type, rule or schema kind, or `--json` on a command that doesn't support it. | | 3 | Error: missing or invalid configuration, I/O or git failure. | ## Dry runs Every command that writes files accepts `--dry-run`: `init`, `add`, `add-activity`, `add-need`, `add-stakeholder`, `rehash`, `baseline`, `verify`, `review` and `skills install`. A dry run reports exactly what would be written and changes nothing. ## Why JUnit XML `rqtk verify` needs one thing from a test run: which tests ran, and whether they passed, failed or were skipped. JUnit XML is the one results format that almost every test runner writes (nextest, pytest, go-junit-report, jest-junit, vitest, Maven, Gradle, .NET) and every CI system reads. Many projects already produce it for their CI's test reports. Reading it keeps rqtk out of your test loop: rqtk records evidence and doesn't care how you run tests. The trade-off is that JUnit XML isn't strictly standardised, and not every runner says which source file a test lives in. rqtk therefore matches test cases to linked tests by name, narrowed by the file and line the runner reports (Bun, vitest, GoogleTest) or by the classname or module its path implies. A name that still matches several distinct tests is reported as ambiguous rather than guessed. --- <!-- https://rqtk.dev/docs/reference/stability.md --> # Stability From 1.0, the `rqtk` command line follows [semantic versioning](https://semver.org). Within 1.x, the following change only in backwards-compatible ways: | Surface | Promise within 1.x | |---|---| | File format (`schema_version = 1`) | Files valid today stay valid. New optional fields may be added. A breaking change gets a new `schema_version`. | | Commands and flags | None removed or renamed. | | `--json` output | Fields are only added, never removed, renamed or retyped. | | Exit codes | 0, 1, 2 and 3 keep their meaning. | | Lint rule codes | A code keeps its meaning and is never reused. New rules may be added, so lint can find new problems after an upgrade. | | Content hash | Tagged with its version (`v1:`); a different algorithm gets a new tag. | **Not covered:** human-readable text output, and the Rust library crates (`rqtk-core`, `rqtk-export`, `rqtk-report`, `rqtk-macros`), which stay at 0.x and may change between minor versions, along with their re-exports from the `rqtk` crate (`rqtk::core`, `rqtk::export`, `rqtk::macros`). The `#[rqtk::verifies("…")]` attribute itself is covered. --- <!-- https://rqtk.dev/docs/changelog.md --> # Changelog All notable changes to the `rqtk` command line. The format follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); the project follows [semantic versioning](https://semver.org) as described under *Stability* in the README. ## [1.2.0] — 2026-09-24 Field trials on six stacks (Python, Rust, TypeScript on Bun, Go, Java on Maven, C++ with GoogleTest) found cases where rqtk reported a requirement verified when it wasn't. This release fixes them; some checks are stricter as a result. ### Upgrade notes - **`coverage --strict` requires every requirement to be Verified.** It used to pass Planned and In Progress requirements. Add `--allow planned` (and `--allow in-progress`) to accept requirements written ahead of their implementation. - **RQ030 is an error:** a `verifies` tag with no test declaration below it can never be verified. Only comments and attributes may sit between a tag and its test now. - **`verify` exits 1** when the results match no linked test, or a linked test matches several distinct tests. - **Suspect lasts longer.** A requirement stays Suspect after it changes, even when the same unchanged tests pass again, and after a parent requirement or need changes; see *Review debt* below. Run your tests and `rqtk verify` once after upgrading and commit `.rqtk/evidence.toml`, so the evidence records test source hashes and upstream hashes. - **Evidence written by 1.2 can't be read by 1.1** (it has new fields). Upgrade everyone who runs `rqtk verify` together. From 1.2 on, unknown fields in the evidence file are ignored. - **Rust:** `#[requirements_docs]` moved to the `requirements-docs` feature; `features = ["macros"]` now brings only `#[verifies]`. ### Fixed: verdicts - Test declarations in Java, Kotlin, C#, C and C++ (including GoogleTest `TEST`/`TEST_F`/ `TEST_P` and Catch2 `TEST_CASE`) are recognised; before, nothing in those languages could be verified. - A tag binds only to the test directly below it. It used to bind to the next test it recognised within 12 lines, so `it.each(…)` gave its activity to an unrelated test. - JS/TS `.only`, `.skip`, `.concurrent`, `.each(…)` and `describe` groups; Go methods; Python `async def`; Kotlin backtick names. - Results are matched by the file and line the runner reports where available, then by what the link's path says about the classname. A name that still matches several distinct tests is reported as ambiguous instead of all of them deciding the outcome. - CTest and GoogleTest disabled tests (`status="disabled"`, `status="notrun"`) count as skipped, not passed. - `verify` no longer says "Evidence is up to date" when nothing matched. ### Added - **Review debt.** Evidence records a hash of each activity's test source and of everything upstream of the requirement. A requirement re-verified by unchanged tests after it changed, or whose parent or need changed, is Suspect until its tests change or someone records `rqtk review <ID> [--note …]`. `coverage`, `context` and `report` say why a requirement is Suspect (`suspect_reasons` in JSON). - **Table-driven and parameterised tests:** `// rqtk: verifies VA-… case "name"` on a table row, or `verifies("VA-…", case = "…")`, links one case: Go subtests, pytest parameters, rows of `it.each([...])`, and GoogleTest parameter values. - JUnit `@DisplayName` / `@ParameterizedTest(name = …)` and xUnit `DisplayName` are read from the annotations, so tests match under Gradle, which reports display names. - Evidence names tests as `<source file>::<name>`, the same whichever runner reported them (Bun and vitest, CTest and GoogleTest). - `verify` counts linked tests that got no result, and warns when it records evidence with no commit to record it against. - `init --hook` installs the pre-commit hook. - The report header shows uncommitted requirement changes and the latest baseline. - **`rqtk add` writes complete requirements:** `--parent`, `--satisfies`, `--criteria`, `--activity` (IDs `VA-<CATEGORY>-<NUMBER>-<NN>`), `--priority`, `--method`, `--level`, `--phase`. It refuses a category that requires a parent when none is given. - `rqtk add-activity <ID> --name …`, and `add-need --rationale`. - `coverage --strict --allow planned|in-progress`. - `rqtk report` opens with what needs attention, shows the tests and commit (or date and files) behind every activity, and adds a stakeholders table and a need → requirement → activity → evidence matrix. - `impact` names the tests to run for each activity and separates activities whose evidence already covers the change (`tests`, `done`). - Lint rule RQ031: an activity's evidence file doesn't exist. - `activity_states` in verification JSON: activity states as objects. - `init` names the project after `Cargo.toml`, `pyproject.toml`, `package.json` or `go.mod`, and warns outside a git repository. ### Changed - `init` creates the example stakeholder and need only with `--example`. - New requirements get priority Medium (or the middle configured level), not the first level. - New requirement and need files carry no `content_hash`, so editing them leaves no stale-hash warning. `rehash` refreshes stored hashes only; `rehash --all` stamps every file. - `validation.require_parent_for_categories` is the documented name of the parent rule; `require_parent_for_levels` still works. - `identification.id_pattern` is optional: without it, IDs are checked against `<prefix>-<CATEGORY>-<NUMBER>` for the configured categories, so adding a category is one table. `init` no longer writes it. - Everything except history (`impact`, `diff`, `log`, `baseline`) works outside a git repository; `lint` used to fail there. - New stakeholder and need IDs follow `zero_padding` (`STK-0001`), or the width a project's existing IDs already use. - Requirements in top-level categories default to verification level System. - `trace` says when a requirement is top-level or a leaf instead of printing empty lists, and shows titles. - `rqtk = { default-features = false, features = ["macros"] }` builds 16 crates instead of about 270: the macros look activities up with a TOML parser, and the `rqtk` crate's dependencies hang off its `lib`, `cli` and `macros` features. - `scan` shows what each link is attached to and counts links not attached to a test. ### Fixed: other - A closed stdout (`rqtk … | head`) ends the command quietly instead of panicking. - The workspace builds on macOS with a plain `cargo build` (the Python extension links). - `skills install` says "Added" when it adds its block to an existing AGENTS.md. ## [1.1.0] — 2026-09-23 ### Added - `pip install rqtk` (or `uv tool install rqtk`): the Python package on PyPI now contains the full `rqtk` command line as well as the `@rqtk.verifies` decorator. One abi3 wheel per platform (Linux glibc and musl, macOS, Windows) covers Python 3.9 and later. ### Fixed - Building the whole workspace on Windows no longer fails: the Python extension's library is now `_rqtk` (imported as `rqtk._rqtk`) instead of `rqtk`, which collided with the `rqtk` binary's `rqtk.exe`/`rqtk.pdb`. ## [1.0.0] — 2026-09-23 First stable release: from here on the command line, file format, `--json` output, exit codes and lint rule codes follow the *Stability* promise in the README. The code is the same as 0.1.0; the list below is everything that changed on the way from the first internal drafts, where breaking changes were still allowed. ### Verification from test evidence - `rqtk scan` finds `verifies` links in source: Rust `#[verifies("…")]`, Python `@verifies("…")`, and a `// rqtk: verifies …` comment tag for any language. - `rqtk verify --results junit.xml` records test outcomes per activity in `.rqtk/evidence.toml`, against the requirement's content hash. `--check` fails when the committed evidence is out of date. - Coverage adds **Suspect** (tests passed for an earlier version of the requirement) and **Failed**. The hand-written `status` of a test-linked activity is ignored (lint RQ029). - `#[verifies]` rebuilds the annotated test when its requirement file changes. - Rust projects need just one crate: `rqtk` with its `macros` feature provides `#[rqtk::verifies("…")]` (also as `rqtk::macros`), without pulling in the CLI's dependencies. ### For coding agents - Global `--json` on every command; fixed exit codes (0 ok, 1 findings, 2 usage, 3 error); `--dry-run` on every command that writes; no interactive prompts. - `rqtk context <ID>` (briefing for one item), `rqtk impact <rev>` (what a change touches and what to re-verify), `rqtk schema <kind>`, `rqtk explain <code>`. - Agent skills (`rqtk-requirements`, `rqtk-verification`, `/to-requirements`, `/requirements-review`), installed with `rqtk skills install` or `rqtk init --agents` into `.agents/skills` with links for Claude Code; also available as a Claude Code plugin. ### Distribution - Prebuilt binaries for macOS, Linux and Windows with shell and PowerShell installers (`curl -LsSf https://rqtk.dev/install.sh | sh`), built by cargo-dist on each release tag. - Documentation at [rqtk.dev](https://rqtk.dev), with `llms.txt` and a Markdown copy of every page for agents. ### File format (schema_version 1) - Flat files: `statement = "…"` and status fields at the top level, links in `[trace]`. - Unknown fields are errors; every broken file is reported in one run with its line (RQ100–RQ102); duplicate IDs and file-name mismatches are caught. - Native TOML dates are accepted. - `rehash` and `baseline` preserve comments and layout. - Content hashes are versioned (`v1:`) and no longer collide across field boundaries. ### Lint - New rules RQ024–RQ030; `RQ017` names every requirement in a cycle and ignores symmetric links; `RQ011` checks all statements with whole-word matching; STK001 became RQ023. ### Removed - C++ bindings (`rqtk-cpp`, `codegen-cpp-verifies`), GraphML output, the Typst/PDF report (`rqtk report` now writes Markdown), interactive prompts, and the unused `[change_control]` and `[export]` configuration sections. ## [0.1.0] — 2026-09-23 Pre-release of the same code as 1.0.0, published to exercise the release pipeline: GitHub Release with installers, crates.io, and rqtk.dev. The library crates (`rqtk-core`, `rqtk-export`, `rqtk-report`, `rqtk-macros`) remain at 0.1.0.