asljs-rq-cli 0.0.0-stage → 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,63 @@
1
+ import { type Folders, Io, type Setting } from 'asljs-rq';
2
+ /**
3
+ * The environment variables `rq` reads.
4
+ */
5
+ export declare const ENVIRONMENT_VARIABLES: readonly ["RQ_AI_COMMAND", "RQ_LOG_LEVEL", "RQ_LOG_FILE", "RQ_LOG_FORMAT"];
6
+ /**
7
+ * The configuration `rq` runs with, as `rq config` prints it.
8
+ */
9
+ export interface Configuration {
10
+ version: string;
11
+ workingDir: string;
12
+ /**
13
+ * The `rq.json` in use; `null` when there is none.
14
+ */
15
+ configFile: string | null;
16
+ requirementsDir: Setting;
17
+ documentsDir: Setting;
18
+ /**
19
+ * The command `rq.json` runs on the markdown files a command wrote; `null`
20
+ * when there is none.
21
+ */
22
+ markdownPostProcessing: string | null;
23
+ /**
24
+ * The agent of instruction steps and `rq coverage` when `--ai` names none:
25
+ * `RQ_AI_COMMAND`, or the first installed of `agents`, detected when a
26
+ * command needs it.
27
+ */
28
+ agent: {
29
+ command: string | null;
30
+ agents: string[];
31
+ };
32
+ log: {
33
+ level: LogSetting;
34
+ file: LogSetting;
35
+ format: LogSetting;
36
+ };
37
+ /**
38
+ * Each variable `rq` reads, and its value; `null` when it is not set.
39
+ */
40
+ environment: Record<string, string | null>;
41
+ }
42
+ /**
43
+ * A log setting and where it comes from: its option, its `RQ_LOG_`
44
+ * variable, or the default.
45
+ */
46
+ export interface LogSetting {
47
+ value: string;
48
+ source: 'option' | 'environment' | 'default';
49
+ }
50
+ /**
51
+ * Prints the configuration: the folders and where they come from, the
52
+ * `rq.json` in use, the agent, the log settings, and the environment
53
+ * variables `rq` reads. `args` is the command line, for the log options.
54
+ */
55
+ export declare function execConfig(io: Io, options: {
56
+ folders: Folders;
57
+ args: readonly string[];
58
+ json?: boolean;
59
+ }): Promise<number>;
60
+ /**
61
+ * The configuration `rq` runs with in the working folder of `io`.
62
+ */
63
+ export declare function readConfiguration(io: Io, folders: Folders, args: readonly string[]): Promise<Configuration>;
package/dist/config.js ADDED
@@ -0,0 +1,78 @@
1
+ import { AI_AGENTS } from 'asljs-agents';
2
+ import { readLoggerOptions } from 'asljs-logging';
3
+ import { findConfig } from 'asljs-mdcli';
4
+ import { CONFIG_FILE } from 'asljs-rq';
5
+ import { createRequire } from 'node:module';
6
+ /**
7
+ * The environment variables `rq` reads.
8
+ */
9
+ export const ENVIRONMENT_VARIABLES = ['RQ_AI_COMMAND',
10
+ 'RQ_LOG_LEVEL',
11
+ 'RQ_LOG_FILE',
12
+ 'RQ_LOG_FORMAT'];
13
+ /**
14
+ * Prints the configuration: the folders and where they come from, the
15
+ * `rq.json` in use, the agent, the log settings, and the environment
16
+ * variables `rq` reads. `args` is the command line, for the log options.
17
+ */
18
+ export async function execConfig(io, options) {
19
+ const configuration = await readConfiguration(io, options.folders, options.args);
20
+ io.stdout.write(options.json
21
+ ? `${JSON.stringify(configuration, null, 2)}\n`
22
+ : describe(configuration));
23
+ return 0;
24
+ }
25
+ /**
26
+ * The configuration `rq` runs with in the working folder of `io`.
27
+ */
28
+ export async function readConfiguration(io, folders, args) {
29
+ const found = await findConfig(io.cwd, CONFIG_FILE);
30
+ const environment = Object.fromEntries(ENVIRONMENT_VARIABLES.map(name => [name,
31
+ io.env[name] || null]));
32
+ const overrides = readLoggerOptions(args);
33
+ const pick = (option, variable, fallback) => option !== undefined
34
+ ? { value: option,
35
+ source: 'option' }
36
+ : environment[variable] !== null
37
+ ? { value: environment[variable],
38
+ source: 'environment' }
39
+ : { value: fallback,
40
+ source: 'default' };
41
+ const file = pick(overrides.file, 'RQ_LOG_FILE', 'stdout');
42
+ return { version: packageVersion(),
43
+ workingDir: io.cwd,
44
+ configFile: folders.configFile,
45
+ requirementsDir: folders.requirementsDir,
46
+ documentsDir: folders.documentsDir,
47
+ markdownPostProcessing: found?.config.markdownPostProcessing?.trim()
48
+ || null,
49
+ agent: { command: environment.RQ_AI_COMMAND,
50
+ agents: [...AI_AGENTS] },
51
+ log: { level: pick(overrides.level, 'RQ_LOG_LEVEL', file.source === 'default'
52
+ ? 'silent'
53
+ : 'information'),
54
+ file,
55
+ format: pick(overrides.format, 'RQ_LOG_FORMAT', 'auto') },
56
+ environment };
57
+ }
58
+ function describe(configuration) {
59
+ const setting = (value) => `${value.value} (${value.source})`;
60
+ const lines = [`version: ${configuration.version}`,
61
+ `workingDir: ${configuration.workingDir}`,
62
+ `configFile: ${configuration.configFile ?? '(none)'}`,
63
+ `requirementsDir: ${setting(configuration.requirementsDir)}`,
64
+ `documentsDir: ${setting(configuration.documentsDir)}`,
65
+ `markdownPostProcessing: ${configuration.markdownPostProcessing ?? '(none)'}`,
66
+ `agent: ${configuration.agent.command === null
67
+ ? `the first installed of ${configuration.agent.agents.join(', ')}, detected when needed`
68
+ : `${configuration.agent.command} (RQ_AI_COMMAND)`}`,
69
+ `logLevel: ${setting(configuration.log.level)}`,
70
+ `logFile: ${setting(configuration.log.file)}`,
71
+ `logFormat: ${setting(configuration.log.format)}`,
72
+ 'environment:',
73
+ ...Object.entries(configuration.environment).map(([name, value]) => ` ${name}=${value ?? ''}`)];
74
+ return `${lines.join('\n')}\n`;
75
+ }
76
+ function packageVersion() {
77
+ return createRequire(import.meta.url)('../package.json').version;
78
+ }
@@ -0,0 +1 @@
1
+ export { createCli, runCli, type CliState } from './cli.js';
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { createCli, runCli } from './cli.js';
@@ -0,0 +1,108 @@
1
+ # Changing the graph
2
+
3
+ Commands that change the structure of the graph, so that no one edits links or
4
+ results by hand. Each prints the files it created, changed or removed.
5
+
6
+ Every command takes `--working-dir <folder>`, `--requirements-dir <folder>` and
7
+ `--documents-dir <folder>`; see [Working folder][WF] and
8
+ [Requirements and documents folders][FD] for how paths, ids and `.md` names are
9
+ resolved. The scope - every `.md` document of the documents folder - is where
10
+ the next free id, the links to rewrite or remove, and another parent of a
11
+ requirement being linked are looked for.
12
+
13
+ ## rq add requirement
14
+
15
+ ```text
16
+ rq add requirement <parent> <name> [--statement <text>] [--path <file>]
17
+ [--working-dir <folder>]
18
+ ```
19
+
20
+ Creates `R<n> <name>.md` in the parent's folder, with `<n>` the highest `R`
21
+ number in the scope plus one, a level 1 heading equal to the file name, and the
22
+ statement. Adds a link to it to the parent's `## Implementation` list.
23
+
24
+ - `<parent>` must be a requirement; `<name>` must not contain `/` or `\`.
25
+ - `--path` gives the new file's path instead; its name must still start with
26
+ `R<n>` (`T<n>` for a test), and its heading is its file name.
27
+ - An existing file is an error.
28
+
29
+ ## rq add test
30
+
31
+ ```text
32
+ rq add test <parent> <name> [--description <text>] [--step <command>]...
33
+ [--path <file>] [--working-dir <folder>]
34
+ ```
35
+
36
+ Like `add requirement`, but creates `tests/T<n> <name>.md` next to the parent,
37
+ with the description and a `## Steps` section holding one `shell` step, `###
38
+ Step <n>`, per `--step`. Write other kinds of steps by editing the text; see
39
+ [Requirements][RM].
40
+
41
+ ## rq link
42
+
43
+ ```text
44
+ rq link <parent> <child> [--working-dir <folder>]
45
+ ```
46
+
47
+ Adds a link to an existing requirement or test to the parent's `##
48
+ Implementation` list. Refused when the parent is a test, when it already links
49
+ to the child, when the child leads back to the parent, or when the child is a
50
+ requirement another requirement of the scope already links to: a requirement has
51
+ one parent, a test may have several.
52
+
53
+ ## rq unlink
54
+
55
+ ```text
56
+ rq unlink <parent> <child> [--working-dir <folder>]
57
+ ```
58
+
59
+ Removes every link from the parent to the child: an `## Implementation` item
60
+ holding one goes with it, a link definition goes with its line, and any other
61
+ link, or reference to a removed definition, is replaced by its text. An error
62
+ when the parent does not link to the child.
63
+
64
+ ## rq remove
65
+
66
+ ```text
67
+ rq remove <file> [--recursive] [--working-dir <folder>]
68
+ ```
69
+
70
+ Deletes a requirement or a test, and removes the links to it from every document
71
+ of the scope, as `unlink` does. A requirement that links to anything is refused
72
+ unless `--recursive` is given; then every document only removed documents link
73
+ to is removed too, down the graph.
74
+
75
+ ## rq move
76
+
77
+ ```text
78
+ rq move <file> <destination> [--working-dir <folder>]
79
+ ```
80
+
81
+ Moves or renames a requirement or a test. `<destination>` is the new path, or an
82
+ existing folder to move it into; an existing file is an error, and so is a name
83
+ of another kind, e.g. an `R` file renamed to `T` or `notes.md`.
84
+
85
+ - Links to it from every document of the scope point at the new path, keeping
86
+ their `#` fragments.
87
+ - Its own relative links, including images, are rewritten for its new folder.
88
+ - When its heading is its old file name, the heading becomes the new file name,
89
+ and so does the text of `## Implementation` links that was the old heading.
90
+
91
+ ## rq log
92
+
93
+ ```text
94
+ rq log <test> --result PASS|FAIL [--note <text>] [--time <time>] [--working-dir <folder>]
95
+ ```
96
+
97
+ Records a result established another way: writes an execution file, `.rq/E<n>
98
+ <test>.md` in the working folder, with the one test, its result and the note, in
99
+ the format [`rq test`][TS] writes. `<test>` is a test file or id, e.g. `T12`.
100
+ `--time` is ISO 8601, now by default; the note is written on one line. The test
101
+ itself is not changed, except that the results are then recalculated and written
102
+ as [`rq test`][TS] does, with `--time` as the `Updated` of the test and of every
103
+ requirement recalculated above it.
104
+
105
+ [TS]: <rq test.md>
106
+ [RM]: ../../rq/docs/Requirements.md
107
+ [FD]: ../../rq/docs/Requirements.md#requirements-and-documents-folders
108
+ [WF]: ../../rq/docs/Requirements.md#working-folder
@@ -0,0 +1,71 @@
1
+ # Querying the graph
2
+
3
+ Commands that print the structure of the graph without changing anything. Paths
4
+ are printed relative to the working folder, with `/` separators.
5
+
6
+ The text output has one line per document: its kind - `requirement`, `test`,
7
+ `other` for an `## Implementation` link to a document that is neither, or
8
+ `missing` for one to no file - its path, and for a requirement or test its
9
+ status, `PASS`, `FAIL` or `NOT RUN`, as its `## Status` records it, then for a
10
+ requirement its coverage, `COMPLETE` or `INCOMPLETE`, when it was checked; see
11
+ [Requirements][RM]. The commands take only requirement and test files.
12
+
13
+ ```text
14
+ requirement requirements/R1 Export.md FAIL
15
+ test requirements/tests/T1 PDF export.md PASS
16
+ ```
17
+
18
+ With `--json` the same documents are printed as an array of `{ path, kind,
19
+ title, result, coverage }`; `result` is `null` for any other document, and
20
+ `coverage` for one that is not a requirement or was never checked.
21
+
22
+ Every command takes `--working-dir <folder>`, `--requirements-dir <folder>` and
23
+ `--documents-dir <folder>`, and a requirement or test as a path, `.md` name or
24
+ id; see [Requirements and documents folders][FD]. The results are read from the
25
+ working folder's `.rq` folder.
26
+
27
+ ## rq list
28
+
29
+ ```text
30
+ rq list [path] [--working-dir <folder>] [--json]
31
+ ```
32
+
33
+ Every document of the graph of a requirement file or folder, the requirements
34
+ folder by default, in breadth-first order from the roots. Structure errors are
35
+ written to standard error.
36
+
37
+ ## rq links
38
+
39
+ ```text
40
+ rq links <requirement> [--working-dir <folder>] [--json]
41
+ ```
42
+
43
+ What a requirement's `## Implementation` list links to.
44
+
45
+ ## rq backlinks
46
+
47
+ ```text
48
+ rq backlinks <file> [--working-dir <folder>] [--json]
49
+ ```
50
+
51
+ The requirements that link to a requirement or a test, looked for in every `.md`
52
+ document of the documents folder. Links in a test are not edges, so a test is
53
+ never a backlink.
54
+
55
+ ## rq tojson
56
+
57
+ ```text
58
+ rq tojson [path] [--working-dir <folder>]
59
+ ```
60
+
61
+ The graph of a requirement file or folder, the requirements folder by default,
62
+ as JSON:
63
+
64
+ - `roots` - the paths of the roots, empty when a folder has none;
65
+ - `errors` - the structure errors;
66
+ - `nodes` - every document, from the roots down, with `path`, `kind`, `title`,
67
+ `body` (the text between the heading and the first section), `links` (the
68
+ paths its `## Implementation` links to), `steps`, `result` and `coverage`.
69
+
70
+ [RM]: ../../rq/docs/Requirements.md
71
+ [FD]: ../../rq/docs/Requirements.md#requirements-and-documents-folders
@@ -0,0 +1,29 @@
1
+ # rq agents
2
+
3
+ Prints instructions for an AI agent that edits the files of a requirements
4
+ folder directly, without `rq`: the formats of requirements, tests, `## Status`
5
+ sections and execution files, and the rules every change keeps, so that the
6
+ requirements stay one valid graph.
7
+
8
+ ```text
9
+ rq agents [--working-dir <folder>] [--requirements-dir <folder>]
10
+ [--documents-dir <folder>]
11
+ ```
12
+
13
+ It takes the folder options of every command, and they are checked as for every
14
+ command, but the instructions do not depend on them.
15
+
16
+ The instructions are made, when the command runs, from [Requirement files][RF],
17
+ the page of the package that is the only description of the formats: its text,
18
+ with every link replaced by its text so that it stands alone. They do not
19
+ mention `rq`; they are about the files, not about the commands.
20
+
21
+ Use it where `rq` is neither installed for the agent nor served to it by
22
+ [rq-mcp][MC], e.g. to give Copilot or Claude the rules in an instructions file:
23
+
24
+ ```bash
25
+ npx rq agents > .github/instructions/requirements.instructions.md
26
+ ```
27
+
28
+ [MC]: ../../rq-mcp/docs/rq-mcp.md
29
+ [RF]: <../../rq/docs/Requirement files.md>
@@ -0,0 +1,32 @@
1
+ # rq check
2
+
3
+ Checks the structure of the graph and of each document without running anything.
4
+ It exits with a non-zero code when it finds a problem.
5
+
6
+ ```text
7
+ rq check [path] [--working-dir <folder>]
8
+ ```
9
+
10
+ `[path]` is a requirement file, a folder, a `.md` name or an id, the
11
+ requirements folder by default; see [Requirements][RM] for the problems it
12
+ reports. `--working-dir`, `--requirements-dir` and `--documents-dir` set the
13
+ folders that paths, names and ids resolve in; see [Working folder][WF] and
14
+ [Requirements and documents folders][FD].
15
+
16
+ ```text
17
+ Error R1 Export.md: the link to R3.md points at no file.
18
+ Error tests/T2 CSV export.md: has a Log section; results are kept in .rq/E<n> files.
19
+ ```
20
+
21
+ Without problems it prints a count:
22
+
23
+ ```text
24
+ OK 2 requirements, 2 tests
25
+ ```
26
+
27
+ Run it after editing documents by hand, and before `rq test`, which runs the
28
+ steps.
29
+
30
+ [RM]: ../../rq/docs/Requirements.md
31
+ [FD]: ../../rq/docs/Requirements.md#requirements-and-documents-folders
32
+ [WF]: ../../rq/docs/Requirements.md#working-folder
@@ -0,0 +1,60 @@
1
+ # rq config
2
+
3
+ Prints the configuration `rq` runs with in the working folder, with the current
4
+ values and where each comes from. It reads and writes nothing else.
5
+
6
+ ```text
7
+ rq config [--json] [--working-dir <folder>] [--requirements-dir <folder>]
8
+ [--documents-dir <folder>]
9
+ ```
10
+
11
+ ```text
12
+ version: 0.1.1
13
+ workingDir: C:\projects\project1
14
+ configFile: C:\projects\project1\rq.json
15
+ requirementsDir: C:\projects\project1\requirements (rq.json)
16
+ documentsDir: C:\projects\project1 (option)
17
+ markdownPostProcessing: npx toolkit flint
18
+ agent: the first installed of claude, copilot, detected when needed
19
+ logLevel: silent (default)
20
+ logFile: stdout (default)
21
+ logFormat: auto (default)
22
+ environment:
23
+ RQ_AI_COMMAND=
24
+ RQ_LOG_LEVEL=
25
+ RQ_LOG_FILE=
26
+ RQ_LOG_FORMAT=
27
+ ```
28
+
29
+ - `version` - the version of `rq`.
30
+ - `workingDir` - the [working folder][WF], whose `.rq` folder holds the results.
31
+ - `configFile` - the `rq.json` in use, the nearest one from the working folder
32
+ up; `(none)` when there is none. See [Configuration][CF].
33
+ - `requirementsDir`, `documentsDir` - the
34
+ [requirements and documents folders][FD], and where each comes from: `option`,
35
+ `rq.json` or `default`.
36
+ - `markdownPostProcessing` - the command of `rq.json`; `(none)` when there is
37
+ none.
38
+ - `agent` - the agent of instruction steps and `rq coverage` when `--ai` names
39
+ none: `RQ_AI_COMMAND`, or the first installed of `claude` and `copilot`. `rq
40
+ config` does not look for an installed agent; that happens when a command
41
+ needs one.
42
+ - `logLevel`, `logFile`, `logFormat` - the log settings, and where each comes
43
+ from: `option` (`--loglevel`, `--logfile`, `--logformat`), `environment`
44
+ (`RQ_LOG_LEVEL`, `RQ_LOG_FILE`, `RQ_LOG_FORMAT`) or `default`. See the
45
+ repository's logging rules.
46
+ - `environment` - each variable `rq` reads, and its value, empty when it is not
47
+ set.
48
+
49
+ ## Options
50
+
51
+ - `--json` - print the same as a JSON object, with `null` for a missing value
52
+ and `{ value, source }` for each folder and log setting.
53
+ - `--working-dir <folder>`, `--requirements-dir <folder>`, `--documents-dir
54
+ <folder>` - as for every command; `rq config` shows what they resolve to. A
55
+ requirements folder outside the documents folder is an error, here as in every
56
+ command.
57
+
58
+ [CF]: ../../rq/docs/Requirements.md#configuration
59
+ [FD]: ../../rq/docs/Requirements.md#requirements-and-documents-folders
60
+ [WF]: ../../rq/docs/Requirements.md#working-folder
@@ -0,0 +1,80 @@
1
+ # rq coverage
2
+
3
+ Asks an AI agent, for each requirement the targets select, whether its
4
+ sub-requirements and its own tests together provide sufficient functional
5
+ coverage, writes the verdict to the `- Coverage:` item of its `## Status`
6
+ section, and the agent's analysis to its `## Coverage` section. It exits with a
7
+ non-zero code when a checked requirement is incomplete or the graph has a
8
+ structure error.
9
+
10
+ ```text
11
+ rq coverage <target>... [--recurse] [--working-dir <folder>]
12
+ [--ai[=<agent>][:<model>]]
13
+ ```
14
+
15
+ The targets are as for [`rq test`][TS]: ids, `.md` names, requirement files or
16
+ folders. A requirement target checks itself, and with `--recurse` every
17
+ requirement below it; a folder checks all its requirements. Tests are skipped.
18
+
19
+ It is independent of `rq test`: it runs no steps and reads no results, and `rq
20
+ test` keeps the coverage it writes. The agent judges coverage only: whether what
21
+ the linked requirements state and what the linked tests check covers each
22
+ statement. It is told to ignore test results and the `## Status` sections, not
23
+ to report on them, and not to recommend running tests.
24
+
25
+ ```text
26
+ COMPLETE requirements/R1 Export.md
27
+ INCOMPLETE requirements/R2 CSV export.md - Nothing covers quoting of commas.
28
+ ```
29
+
30
+ - The `## Coverage` section holds the analysis: when the requirement is
31
+ complete, which requirement or test covers each statement; when it is not,
32
+ each statement nothing covers and what to do - a test to add and what it
33
+ should check, a sub-requirement to add and its statement, or a change to make.
34
+ It explains only what is covered, what is not, and how to improve the
35
+ coverage. The agent is asked to name requirements and tests by their id; a
36
+ link it writes anyway is replaced by its text. Then each id of a requirement
37
+ or test below the requirement in the graph, outside code, becomes a reference
38
+ link to its document, e.g. `[T2][]`, with its definition at the end of the
39
+ section, or none when the document already defines that label for the same
40
+ file. Other ids, e.g. of the requirements a test builds as its fixture, stay
41
+ text. It is rewritten on every check, with its definitions, placed before `##
42
+ Status`; a heading the agent writes is escaped so the section stays one
43
+ section.
44
+
45
+ ```markdown
46
+ ## Coverage
47
+
48
+ Nothing covers "quotes fields that contain commas": [T2][] checks plain values
49
+ only.
50
+
51
+ - Add a test that exports a value with a comma and checks it is quoted, or
52
+ - extend [T2][] with such a value.
53
+
54
+ ## Status
55
+
56
+ - Coverage: INCOMPLETE - Nothing covers quoting of commas.
57
+ ```
58
+
59
+ - A requirement that links to nothing is `INCOMPLETE` without asking, with an
60
+ analysis that says to decompose it or add tests.
61
+ - The agent reads the requirement and what it links to; it is allowed to read
62
+ and search files only, so it runs no command and changes no file. The reason
63
+ it gives for an incomplete verdict becomes the note.
64
+ - The verdict is not invalidated by later edits: run `rq coverage` again after
65
+ changing a requirement or what it links to.
66
+
67
+ ## Options
68
+
69
+ - `--recurse` - also check every requirement below a requirement target.
70
+ - `--working-dir <folder>` - the working folder; see [Working folder][WF].
71
+ - `--requirements-dir <folder>`, `--documents-dir <folder>` - see
72
+ [Requirements and documents folders][FD].
73
+ - `--ai[=<agent>][:<model>]` - the agent, `claude` or `copilot`, and its model,
74
+ both optional; the first of `claude` and `copilot` that is installed by
75
+ default. No agent is an error. `RQ_AI_COMMAND` replaces the agent, as for
76
+ [`rq test`][TS].
77
+
78
+ [FD]: ../../rq/docs/Requirements.md#requirements-and-documents-folders
79
+ [TS]: <rq test.md>
80
+ [WF]: ../../rq/docs/Requirements.md#working-folder
@@ -0,0 +1,124 @@
1
+ # rq test
2
+
3
+ Runs the tests of requirements and tests, records the results in an execution
4
+ file, writes the results that follow to the `## Status` sections as each test
5
+ finishes, and reports the result of each target. It exits with a non-zero code
6
+ when a reported node does not pass or the graph has a structure error.
7
+
8
+ ```text
9
+ rq test <target>... [--recurse] [--working-dir <folder>] [--name <slug>]
10
+ [--ai[=<agent>][:<model>]]
11
+ ```
12
+
13
+ ## Targets
14
+
15
+ Each target is one of:
16
+
17
+ - an id, e.g. `R10` or `T12`, or a `.md` name: the requirement or test the
18
+ requirements folder and its subfolders hold;
19
+ - a requirement or test file, relative to the working folder;
20
+ - a folder, relative to the working folder; see [Requirements][RM] for how its
21
+ roots are found.
22
+
23
+ See [Requirements and documents folders][FD] for how ids and names are matched.
24
+
25
+ ```text
26
+ rq test R10 R56 R100 T12 --recurse
27
+ ```
28
+
29
+ What runs:
30
+
31
+ - a test target runs itself;
32
+ - a requirement target runs the tests it links to directly, and with `--recurse`
33
+ every test below it;
34
+ - a folder target runs every test of its graph.
35
+
36
+ Each test runs once, however many targets reach it.
37
+
38
+ ## Results
39
+
40
+ The run is written to `.rq/E<n> <slug>.md` in the working folder, with `<n>` the
41
+ next free number; see [Requirements][RM] for the format. As each test finishes,
42
+ it is added to that file, its result is written to its `## Status` section, and
43
+ every requirement above it is recalculated and written, all with the time the
44
+ test finished as `Updated`; a failed test fails every requirement above it, and
45
+ each of them names it, with its note and the execution file. After the last
46
+ test, the targets are recalculated too. A run that stops early leaves every test
47
+ that finished recorded. Nothing is written when no test runs.
48
+
49
+ ## Output
50
+
51
+ One line per test, as it finishes, with its note, and for a failed one the
52
+ execution file. Then one line per other reported node: each requirement target,
53
+ and with `--recurse` or for a folder every requirement below it; without
54
+ `--recurse`, also each requirement a target links to, marked `(recorded)`, with
55
+ the result its document records. Then one `Error` line per structure error, the
56
+ path of the execution file, one `Updated` line per document whose `## Status`
57
+ changed, in the order they changed, and one `Removed` line per old execution
58
+ file the [retention][RT] removed.
59
+
60
+ ```text
61
+ PASS requirements/tests/T1 PDF export.md - 1 step
62
+ FAIL requirements/tests/T2 CSV export.md - step 1 exited with code 1: 1 test failed (.rq/E4 requirements.md)
63
+ FAIL requirements/R1 Export.md - 1 of 2 links failed: T2 CSV export: step 1 exited with code 1: 1 test failed (.rq/E4 requirements.md)
64
+ FAIL requirements/R2 CSV export.md - 1 of 1 links failed: T2 CSV export: step 1 exited with code 1: 1 test failed (.rq/E4 requirements.md)
65
+ Error R2 CSV export.md: the link to R3.md points at no file.
66
+ Results .rq/E4 requirements.md
67
+ Updated requirements/tests/T1 PDF export.md
68
+ Updated requirements/R1 Export.md
69
+ Updated requirements/R2 CSV export.md
70
+ Updated requirements/tests/T2 CSV export.md
71
+ ```
72
+
73
+ Without `--recurse`, `rq test R1` runs the tests R1 links to and merges their
74
+ results with the results its sub-requirements record, which it does not
75
+ recalculate; `--recurse` reruns the tests below them too. The results come from
76
+ the documents' `## Status` sections, never from `.rq`.
77
+
78
+ ```text
79
+ PASS requirements/tests/T1 PDF export.md - 1 step
80
+ NOT RUN requirements/R1 Export.md - 1 of 2 links not run
81
+ NOT RUN requirements/R2 CSV export.md (recorded) - 1 of 1 links not run
82
+ ```
83
+
84
+ A requirement is:
85
+
86
+ - `PASS` when every node it links to passes;
87
+ - `FAIL` when one fails, or when it links to nothing, naming each failed test
88
+ below it with its note and execution file;
89
+ - `NOT RUN` otherwise: something below it has no result yet.
90
+
91
+ ## Options
92
+
93
+ - `--recurse` - also run the tests of every requirement below a requirement
94
+ target.
95
+ - `--working-dir <folder>` - the working folder; the current directory by
96
+ default.
97
+ - `--requirements-dir <folder>`, `--documents-dir <folder>` - the requirements
98
+ folder, where ids and names are searched for, and the documents folder; see
99
+ [Requirements and documents folders][FD].
100
+ - `--name <slug>` - the slug of the execution file. By default the targets, a
101
+ path by its file or folder name: `rq test R10 T12` writes `E<n> R10 T12.md`.
102
+ - `--ai[=<agent>][:<model>]` - the AI agent of instruction steps, `claude` or
103
+ `copilot`, and its model, both optional: `--ai`, `--ai=claude:fable`,
104
+ `--ai=copilot`.
105
+
106
+ Instruction steps always use an agent: the one `--ai` names, or the first of
107
+ `claude` and `copilot` that is installed. Such a step may read files and run
108
+ commands, and is told and configured not to edit files; see [Requirements][RM]
109
+ for what that does not prevent. An instruction step without an agent fails.
110
+ Write `--ai=<agent>` with `=` when a target follows it, e.g. `rq test
111
+ --ai=claude R1`, so that the target is not taken for the agent. Coverage is
112
+ checked by [`rq coverage`][CV], not by `rq test`.
113
+
114
+ ## Environment
115
+
116
+ - `RQ_AI_COMMAND` - a command line that replaces the agent. It gets the prompt
117
+ on standard input, and its verdict is the last line of its output that is
118
+ `{"result":"OK"}` or `{"result":"Fail","message":"..."}`.
119
+
120
+ [CV]: <rq coverage.md>
121
+ [RM]: ../../rq/docs/Requirements.md
122
+ [RT]: ../../rq/docs/Requirements.md#results
123
+ [FD]: ../../rq/docs/Requirements.md#requirements-and-documents-folders
124
+ [WF]: ../../rq/docs/Requirements.md#working-folder