@descent-vtt/spec-brief 0.7.0 → 0.8.0

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.
package/CHANGELOG.md CHANGED
@@ -11,6 +11,43 @@ release that can turn a run red. This is the family's policy, recorded in
11
11
  releases up to 0.2.7 came before it, and several of their patches changed
12
12
  what a run reports.
13
13
 
14
+ ## 0.8.0
15
+
16
+ An option is refused, exit 2, where taking it would tell someone what is
17
+ not so: `init --strict`, `init --config`, `--color` on a command that
18
+ prints none, and `--config` beside `--no-config`. Each ran as the line
19
+ without it does. An option that asks a command to leave out what it never
20
+ does is still taken. And `FORCE_COLOR=false` turns colour off.
21
+
22
+ ### Changed
23
+
24
+ - **An option is refused where taking it would tell someone what is not
25
+ so.** `init` with `--config`, `--strict` or `--color`, `new` with
26
+ `--strict` or `--color`, and `list --strict` each ran as the line without
27
+ the option does, exit 0: `init --config team.json` wrote
28
+ `.spec-brief.json`, and `init --strict` set nothing up strictly. Each is
29
+ now exit 2 with a line that names the command, the option and what the
30
+ command reads, and writes nothing. An option that asks a command to
31
+ leave out what it never does is still taken, since it asks for what is
32
+ already so: `--no-color` by every command, and `--no-git` and
33
+ `--no-config` by `init` (ADR-0001,
34
+ [An option a command does not read](README.md#an-option-a-command-does-not-read)).
35
+ Upgrading: drop the option from that command's line; `init` writes
36
+ `.spec-brief.json` and no other file, so a configuration kept under
37
+ another name is renamed after it.
38
+ - **`--config` beside `--no-config`, and `--color` beside `--no-color`, are
39
+ refused.** The defaults ran with the file never opened, and colour was
40
+ off whatever `--color` asked, with no word of either; each pair is now
41
+ exit 2 with a line that names both. Upgrading: give one of the two.
42
+
43
+ ### Fixed
44
+
45
+ - **`FORCE_COLOR=false` turns colour off**, as `FORCE_COLOR=0` does, on a
46
+ terminal too. It forced colour on, into a pipe as well, where Node itself
47
+ and `supports-color` read it as off. Any other value that is not empty
48
+ still forces colour on, and `NO_COLOR`, `--color` and `--no-color` win as
49
+ they did.
50
+
14
51
  ## 0.7.0
15
52
 
16
53
  An input that is set and names nothing is refused, exit 2, by a line that
package/README.md CHANGED
@@ -246,16 +246,21 @@ Reopens an archived brief: the banner and the hash come off, the status goes bac
246
246
 
247
247
  ### Every command
248
248
 
249
- | Flag | What it does |
250
- | --- | --- |
251
- | `--root <dir>` | Runs from another directory, which must be there: only `init` makes one that is not. |
252
- | `--config <file>` | Names the configuration. |
253
- | `--no-config` | Uses the defaults. |
254
- | `--format <format>` | `pretty` by default, or `json`; `lint`, `matrix` and `schedule`, which report findings, also write `sarif`, `github` and `gitlab`, and `--help` lists each command's formats. |
255
- | `--strict` | Makes warnings fail the run. |
256
- | `--no-git` | Leaves git out even inside a repository: the tree is read from disk, and `archive` records no commit. |
257
- | `--color`, `--no-color` | Override `NO_COLOR`, `FORCE_COLOR`, `TERM=dumb` and the terminal check. |
258
- | `--help`, `--version` | Do what they say. |
249
+ Every command takes these, except where the last column names it: an option is [refused where taking it would tell someone what is not so](#an-option-a-command-does-not-read).
250
+
251
+ | Flag | What it does | Not for |
252
+ | --- | --- | --- |
253
+ | `--root <dir>` | Runs from another directory, which must be there: only `init` makes one that is not. | |
254
+ | `--config <file>` | Names the configuration. | `init`, which writes `.spec-brief.json` |
255
+ | `--no-config` | Uses the defaults. | |
256
+ | `--format <format>` | `pretty` by default, or `json`; `lint`, `matrix` and `schedule`, which report findings, also write `sarif`, `github` and `gitlab`, and `--help` lists each command's formats. | |
257
+ | `--strict` | Makes warnings fail the run. | `init`, `new` and `list`, which have none |
258
+ | `--no-git` | Leaves git out even inside a repository: the tree is read from disk, and `archive` records no commit. | |
259
+ | `--color` | Colour, whatever the environment and the terminal say. | `init` and `new`, which print none |
260
+ | `--no-color` | No colour, whatever they say. | |
261
+ | `--help`, `--version` | Do what they say, whatever else is on the line. | |
262
+
263
+ Without `--color` or `--no-color`, `NO_COLOR` set to anything turns colour off; otherwise `FORCE_COLOR` turns it on, and `FORCE_COLOR=0` or `FORCE_COLOR=false` off, on a terminal too; otherwise `TERM=dumb` turns it off; otherwise a terminal has colour and a pipe has none. `NO_COLOR` or `FORCE_COLOR` set to nothing is as unset. Only the `pretty` format has colour.
259
264
 
260
265
  **Exit codes:**
261
266
 
@@ -263,7 +268,7 @@ Reopens an archived brief: the banner and the hash come off, the status goes bac
263
268
  | --- | --- |
264
269
  | `0` | Clean. |
265
270
  | `1` | Findings, a collision, or a refused action. |
266
- | `2` | The run could not be trusted, or its answer did not arrive - a bad flag, [an input that names nothing](#an-input-that-names-nothing), a configuration that does not load, a brief that does not exist, a git command that failed, a `SOURCE_DATE_EPOCH` that [cannot be read as a date](#todays-date) where one is to be written, a stdout its reader closed before all of the output was written, as a pipeline into `head` does, each said in one line on stderr, or an error spec-brief did not expect, reported on stderr as `spec-brief: unexpected error:` with its stack. |
271
+ | `2` | The run could not be trusted, or its answer did not arrive - a bad flag, [an input that names nothing](#an-input-that-names-nothing), [an option the command does not read](#an-option-a-command-does-not-read), a configuration that does not load, a brief that does not exist, a git command that failed, a `SOURCE_DATE_EPOCH` that [cannot be read as a date](#todays-date) where one is to be written, a stdout its reader closed before all of the output was written, as a pipeline into `head` does, each said in one line on stderr, or an error spec-brief did not expect, reported on stderr as `spec-brief: unexpected error:` with its stack. |
267
272
 
268
273
  A run over a briefs directory that does not exist exits 2, because a check over nothing looks exactly like a clean one.
269
274
 
@@ -277,6 +282,25 @@ An option, an argument or a path that is given and names nothing is refused: exi
277
282
  - **A `--root` that is no directory.** A file, or a path that does not exist, is refused: the search for a configuration would go on from its parent, and the run would report on, or `new` write into, the tree above. A directory below the configuration's is a place to start from, as the current directory is.
278
283
  - **A configuration that is a directory**, named by `--config` or found under the configuration's name, does not load, and is said so in a line, as one that is not JSON is.
279
284
 
285
+ ### An option a command does not read
286
+
287
+ An option is refused where taking it would tell someone what is not so: exit 2, one line that names the command, the option, what the command does read and what it takes besides, nothing written. `init --strict` would otherwise say the briefs had been set up strictly, and `init --config team.json` that the configuration had been written there.
288
+
289
+ | Command | Refuses | Because it would say |
290
+ | --- | --- | --- |
291
+ | `init` | `--config`, `--strict`, `--color` | That the configuration was written to the file named, where `.spec-brief.json` is; that something was strict, where `init` has no warning to fail on; that colour was printed, where it prints none. |
292
+ | `new` | `--strict`, `--color` | That a warning would have failed it, where it has none; that colour was printed, where it prints none. |
293
+ | `list` | `--strict` | That a warning would have failed it, where it reports no finding. |
294
+
295
+ ```text
296
+ spec-brief: init does not read --strict; it reads --root, --format, --briefs and --archive, and takes --no-config, --no-git and --no-color
297
+ ```
298
+
299
+ - **Two options of which one would go unread** are refused together, for the same reason: `--config <file>` beside `--no-config` says the file was read, where the defaults ran and it was never opened, and `--color` beside `--no-color` that colour was forced on, where it was off. Give one of the two.
300
+ - **An option that asks a command to leave out what it never does is taken**, since it asks for what is already so: `--no-color` by `init` and `new`, which print no colour, `--no-git` by `init`, which asks git nothing, and `--no-config` by `init`, which opens no configuration file. A script that runs every command in a tree without git, or into a log, passes such an option to each of them. `init --no-config` still writes over no configuration: where one is there, it stops as `init` does.
301
+ - **An option a format has nothing to read for is taken**: `--no-color` or `--color` beside `--format json` changes nothing, and a caller that asks for JSON passes `--no-color` beside it.
302
+ - **`--help` and `--version` answer first**: `init --strict --help` prints the help.
303
+
280
304
  ### Today's date
281
305
 
282
306
  `new` writes a date into the front matter and `archive` one into the banner: the one `--date` gives, or today's. Today is the clock's date in UTC, unless `SOURCE_DATE_EPOCH` is set, the variable a pipeline sets to have every run write the same bytes ([its specification](https://reproducible-builds.org/specs/source-date-epoch/)): then it is the date of that time, in UTC.
package/dist/cli.js CHANGED
@@ -72,6 +72,87 @@ const TABLE = {
72
72
  },
73
73
  unarchive: { options: { 'dry-run': { type: 'boolean' } }, formats: ['pretty', 'json'] },
74
74
  };
75
+ /**
76
+ * Whether taking the option would tell someone what is not so. `init
77
+ * --strict` says the briefs were set up strictly, where nothing was strict;
78
+ * `init --config team.json` that the configuration was written there, where
79
+ * `.spec-brief.json` was; `init --color` and `new --color` that colour was
80
+ * printed, where neither prints any; `new --strict` and `list --strict` that
81
+ * a warning would have failed the run, where neither has one. Each ran as
82
+ * the line without the option does, exit 0.
83
+ *
84
+ * A function, not a table beside the commands': a table built when the
85
+ * module loads is static to Stryker, and each of its mutants then runs the
86
+ * whole suite (ADR-0009).
87
+ */
88
+ function untrue(command, option) {
89
+ switch (option) {
90
+ case 'config':
91
+ return command === 'init';
92
+ case 'strict':
93
+ return command === 'init' || command === 'new' || command === 'list';
94
+ case 'color':
95
+ return command === 'init' || command === 'new';
96
+ // Each caller asks only whether the answer is true, so the mutant that
97
+ // leaves this case out, and answers nothing, is equivalent.
98
+ default:
99
+ return false;
100
+ }
101
+ }
102
+ /**
103
+ * Whether the option asks the command to leave out what it never does, and
104
+ * so asks for what is already so: `init` opens no configuration file and
105
+ * asks git nothing, and neither it nor `new` prints colour. Such an option
106
+ * is taken. A script that runs every command in a tree without git, or into
107
+ * a log, passes it to each of them, as spec-harness passes `--no-color`.
108
+ * The command reads nothing of it, so a refusal's line lists it apart from
109
+ * what the command reads, as taken.
110
+ */
111
+ function alreadySo(command, option) {
112
+ switch (option) {
113
+ case 'no-config':
114
+ case 'no-git':
115
+ return command === 'init';
116
+ case 'no-color':
117
+ return command === 'init' || command === 'new';
118
+ // Each caller asks only whether the answer is true, so the mutant that
119
+ // leaves this case out, and answers nothing, is equivalent.
120
+ default:
121
+ return false;
122
+ }
123
+ }
124
+ /** Options by their names on the command line, as a sentence lists them. */
125
+ function listed(names) {
126
+ const options = names.map((name) => `--${name}`);
127
+ return options.length === 1 ? options[0] : `${options.slice(0, -1).join(', ')} and ${options.at(-1)}`;
128
+ }
129
+ /**
130
+ * Why a command line that parsed is still not one to run.
131
+ *
132
+ * An option is refused where taking it would tell someone what is not so,
133
+ * and so are two options of which one would go unread: `--config team.json
134
+ * --no-config` says the file was read, where the defaults ran, and `--color
135
+ * --no-color` that colour was forced on, where it was off. An option that
136
+ * asks a command to leave out what it never does asks for what is already
137
+ * so, and is taken.
138
+ */
139
+ function unread(command, spec, values) {
140
+ // The first such option as the line was typed, which is the order the
141
+ // parser keeps.
142
+ const stray = Object.keys(values).find((option) => untrue(command, option));
143
+ if (stray !== undefined) {
144
+ const shared = Object.keys(GLOBAL).filter((option) => option !== 'help' && option !== 'version' && !untrue(command, option));
145
+ const reads = [...shared.filter((option) => !alreadySo(command, option)), ...Object.keys(spec.options)];
146
+ const takes = shared.filter((option) => alreadySo(command, option));
147
+ return `${command} does not read --${stray}; it reads ${listed(reads)}${takes.length > 0 ? `, and takes ${listed(takes)}` : ''}`;
148
+ }
149
+ if (text(values, 'config') !== undefined && flag(values, 'no-config')) {
150
+ return '--config is given beside --no-config, which has the run read no configuration file; give one of the two';
151
+ }
152
+ if (flag(values, 'color') && flag(values, 'no-color'))
153
+ return '--color is given beside --no-color, which turns colour off; give one of the two';
154
+ return null;
155
+ }
75
156
  /**
76
157
  * The commands by name, and nothing for a command line that names none. A map,
77
158
  * because an object answers to more names than it was given: `constructor` and
@@ -108,14 +189,14 @@ Commands:
108
189
  archive <brief> close a round: check it, stamp it, freeze it, move it
109
190
  unarchive <brief> reopen an archived brief
110
191
 
111
- Options for every command:
192
+ Options for every command, except where a line says otherwise:
112
193
  --root <dir> run from this directory instead of the current one; it must exist, unless init makes it
113
- --config <file> use this configuration file
194
+ --config <file> use this configuration file; not for init, which writes .spec-brief.json
114
195
  --no-config use the defaults, ignoring any configuration file
115
196
  --format <format> the output format, pretty by default; each command's are below
116
- --strict treat warnings as errors
197
+ --strict treat warnings as errors; not for init, new or list, which have none
117
198
  --no-git leave git out; read the files on disk instead
118
- --color, --no-color force colour on or off
199
+ --color, --no-color force colour on or off; --color not for init or new, which print none
119
200
  -h, --help show this help
120
201
  -v, --version show the version
121
202
 
@@ -156,7 +237,11 @@ unarchive:
156
237
  --dry-run print the plan and change nothing
157
238
 
158
239
  An option given an empty value, a list that names nothing and an argument a
159
- command does not take are refused, not read as if they were not there.
240
+ command does not take are refused, not read as if they were not there. So is
241
+ an option where taking it would say what is not so, as init --strict, and so
242
+ are --config beside --no-config and --color beside --no-color, of which one
243
+ would go unread. An option that asks a command to leave out what it never
244
+ does is taken, as init --no-git: it asks for what is already so.
160
245
 
161
246
  Exit codes: 0 clean, 1 findings or refused, 2 the run could not be trusted.
162
247
  `;
@@ -238,9 +323,13 @@ function useColor(values, io) {
238
323
  const env = io.env ?? process.env;
239
324
  if ((env['NO_COLOR'] ?? '') !== '')
240
325
  return false;
326
+ // Off for exactly "0" and exactly "false": Node itself and supports-color
327
+ // read "false" as off, and here it forced colour on. Any other value that
328
+ // is not empty is on, "FALSE" too, which is the one reading the family's
329
+ // tools share (spec-core ADR-0005).
241
330
  const force = env['FORCE_COLOR'];
242
331
  if (force !== undefined && force !== '')
243
- return force !== '0';
332
+ return force !== '0' && force !== 'false';
244
333
  // A terminal that says it is dumb has asked for no escape sequence, and
245
334
  // Node itself counts one colour for it: the family's tools read it alike.
246
335
  if (env['TERM'] === 'dumb')
@@ -469,6 +558,9 @@ export async function main(argv = process.argv.slice(2), io = {}) {
469
558
  return flag(values, 'help') ? EXIT_OK : EXIT_ERROR;
470
559
  }
471
560
  const spec = COMMANDS.get(command);
561
+ const refusal = unread(command, spec, values);
562
+ if (refusal !== null)
563
+ throw new UsageError(refusal);
472
564
  const format = (text(values, 'format') ?? 'pretty');
473
565
  if (!spec.formats.includes(format)) {
474
566
  err(`--format for ${command} is one of ${spec.formats.join(', ')}, not "${format}"`);
package/dist/cli.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The command line: argument parsing, dispatch, output and exit codes.\n *\n * Exit 0: done, nothing found. Exit 1: findings, collisions, or an action\n * refused. Exit 2: the run could not be trusted - a bad flag, a configuration\n * that does not load, a brief that does not exist. A run that checked nothing\n * must never exit as though it found nothing.\n */\n\nimport { readFile, stat } from 'node:fs/promises';\nimport { parseArgs, type ParseArgsConfig } from 'node:util';\n\nimport { TransactionError, ConflictError } from './apply.js';\nimport type { Plan } from './archive.js';\nimport { reported } from './collisions.js';\nimport { CONFIG_FILES, ConfigError, initialConfig } from './config.js';\nimport { BriefEngine, EngineError, today } from './engine.js';\nimport { NodeFileSystem } from './fs.js';\nimport { GitError } from './git.js';\nimport { failing, sortFindings, summarise } from './lint.js';\nimport { normalisePath } from './links.js';\nimport {\n briefJson,\n findingJson,\n FORMATS,\n type Format,\n githubCommands,\n gitlabCodeQuality,\n jsonDocument,\n type ListRow,\n matrixJson,\n planJson,\n prettyFindings,\n prettyList,\n prettyMatrix,\n prettyPlan,\n prettySchedule,\n sarif,\n scheduleJson,\n sectionsJson,\n type Style,\n summaryLine,\n} from './report.js';\nimport type { Finding } from './types.js';\n\nexport const EXIT_OK = 0;\nexport const EXIT_FAILED = 1;\nexport const EXIT_ERROR = 2;\n\nexport class UsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UsageError';\n }\n}\n\nexport interface CliIO {\n readonly stdout?: { write(text: string): unknown; readonly isTTY?: boolean };\n readonly stderr?: { write(text: string): unknown };\n readonly cwd?: string;\n readonly env?: Readonly<Record<string, string | undefined>>;\n}\n\ntype Values = Record<string, string | boolean | undefined>;\n\nconst GLOBAL: NonNullable<ParseArgsConfig['options']> = {\n root: { type: 'string' },\n config: { type: 'string' },\n 'no-config': { type: 'boolean' },\n format: { type: 'string' },\n strict: { type: 'boolean' },\n 'no-git': { type: 'boolean' },\n color: { type: 'boolean' },\n 'no-color': { type: 'boolean' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n};\n\ninterface CommandSpec {\n readonly options: NonNullable<ParseArgsConfig['options']>;\n readonly formats: readonly Format[];\n /**\n * Set on a command that takes no argument: what its refusal of one adds to\n * the usage, which is where the option a person most likely meant is named.\n */\n readonly noArgument?: string;\n}\n\nconst TABLE: Readonly<Record<string, CommandSpec>> = {\n init: {\n options: { briefs: { type: 'string' }, archive: { type: 'string' } },\n formats: ['pretty', 'json'],\n noArgument: '; --root <dir> names the directory it sets up, and --briefs <dir> the one for the briefs',\n },\n new: {\n options: {\n id: { type: 'string' },\n type: { type: 'string' },\n wave: { type: 'string' },\n 'depends-on': { type: 'string' },\n date: { type: 'string' },\n },\n formats: ['pretty', 'json'],\n },\n lint: { options: {}, formats: FORMATS },\n list: { options: { ready: { type: 'boolean' }, archived: { type: 'boolean' } }, formats: ['pretty', 'json'], noArgument: '' },\n matrix: { options: { 'all-waves': { type: 'boolean' } }, formats: FORMATS, noArgument: '' },\n schedule: { options: { write: { type: 'boolean' } }, formats: FORMATS, noArgument: '' },\n archive: {\n options: {\n pr: { type: 'string' },\n commit: { type: 'string' },\n base: { type: 'string' },\n summary: { type: 'string' },\n date: { type: 'string' },\n 'allow-dirty': { type: 'boolean' },\n 'dry-run': { type: 'boolean' },\n },\n formats: ['pretty', 'json'],\n },\n unarchive: { options: { 'dry-run': { type: 'boolean' } }, formats: ['pretty', 'json'] },\n};\n\n/**\n * The commands by name, and nothing for a command line that names none. A map,\n * because an object answers to more names than it was given: `constructor` and\n * `toString` are no commands.\n */\nconst COMMANDS: ReadonlyMap<string | undefined, CommandSpec> = new Map(Object.entries(TABLE));\n\n/**\n * The formats each command writes, read from the table `main` checks a\n * `--format` against, so the help names no format a command refuses: the\n * finding formats are `lint`'s, `matrix`'s and `schedule`'s alone.\n */\nfunction formatsHelp(): string {\n const groups = new Map<string, string[]>();\n for (const [command, spec] of Object.entries(TABLE)) {\n const formats = spec.formats.join(', ');\n groups.set(formats, [...(groups.get(formats) ?? []), command]);\n }\n const rows = [...groups].map(([formats, commands]) => [commands.join(', '), formats] as const);\n const width = Math.max(...rows.map(([commands]) => commands.length));\n return rows.map(([commands, formats]) => ` ${commands.padEnd(width)} ${formats}`).join('\\n');\n}\n\nexport const HELP = `spec-brief - lint, schedule and archive task briefs\n\nUsage:\n spec-brief <command> [options]\n\nCommands:\n init write .spec-brief.json and the brief directories\n new <title> scaffold a brief with the next free id\n lint [brief...] check briefs against the configuration\n list briefs with their status, wave and readiness\n matrix scope collisions between briefs in the same wave\n schedule the waves the live briefs can run in, computed\n archive <brief> close a round: check it, stamp it, freeze it, move it\n unarchive <brief> reopen an archived brief\n\nOptions for every command:\n --root <dir> run from this directory instead of the current one; it must exist, unless init makes it\n --config <file> use this configuration file\n --no-config use the defaults, ignoring any configuration file\n --format <format> the output format, pretty by default; each command's are below\n --strict treat warnings as errors\n --no-git leave git out; read the files on disk instead\n --color, --no-color force colour on or off\n -h, --help show this help\n -v, --version show the version\n\nFormats:\n${formatsHelp()}\n\ninit:\n --briefs <dir> the directory of live briefs; default briefs\n --archive <dir> the directory of archived briefs; default <briefs>/archive\n\nnew:\n --id <id> use this id instead of the next free one\n --type <type> a brief type from the configuration\n --wave <n> the wave it runs in\n --depends-on <ids> comma-separated ids it runs after\n --date <YYYY-MM-DD> the date in its front matter; default SOURCE_DATE_EPOCH's, or today's in UTC\n\nlist:\n --ready only briefs that can run now: dependencies archived, not drafts or deferred\n --archived include archived briefs\n\nmatrix:\n --all-waves compare every live brief, whatever its wave\n\nschedule:\n --write write each proposed wave into its brief's front matter\n\narchive:\n --pr <number> the pull request the round merged in\n --commit <rev> the commit the round landed as\n --base <rev> the branch it started from; the diff runs from the merge base\n --summary <text> what the round did, for the banner\n --date <YYYY-MM-DD> the archival date; default SOURCE_DATE_EPOCH's, or today's in UTC\n --allow-dirty archive although the tree has uncommitted work\n --dry-run print the plan and change nothing\n\nunarchive:\n --dry-run print the plan and change nothing\n\nAn option given an empty value, a list that names nothing and an argument a\ncommand does not take are refused, not read as if they were not there.\n\nExit codes: 0 clean, 1 findings or refused, 2 the run could not be trusted.\n`;\n\ninterface Parsed {\n readonly command: string | undefined;\n readonly values: Values;\n readonly positionals: readonly string[];\n}\n\n/** Global options that take a value, so the value is not mistaken for the command. */\nconst VALUED = new Set(['--root', '--config', '--format']);\n\nfunction commandOf(argv: readonly string[]): string | undefined {\n for (let i = 0; i < argv.length; i += 1) {\n const arg = argv[i] as string;\n if (arg === '--') return argv[i + 1];\n if (VALUED.has(arg)) {\n i += 1;\n continue;\n }\n if (!arg.startsWith('-')) return arg;\n }\n return undefined;\n}\n\nexport function parse(argv: readonly string[]): Parsed {\n const command = commandOf(argv);\n const spec = COMMANDS.get(command);\n if (command !== undefined && spec === undefined) {\n throw new UsageError(`\"${command}\" is not a command; run spec-brief --help`);\n }\n let parsed: { values: Values; positionals: string[] };\n try {\n parsed = parseArgs({\n args: [...argv],\n options: { ...GLOBAL, ...(spec?.options ?? {}) },\n allowPositionals: true,\n strict: true,\n }) as { values: Values; positionals: string[] };\n } catch (error) {\n throw new UsageError((error as Error).message);\n }\n const positionals = parsed.positionals.slice(1);\n // What the parser takes is not yet what names something. An option whose\n // value is empty, as `--root \"$DIR\"` is where the variable is not set, was\n // read as the option left out, and an argument no command asked for was\n // dropped: either way the run answered a question nobody had put, exit 0.\n for (const [name, value] of Object.entries(parsed.values)) {\n if (typeof value === 'string' && value.trim() === '') {\n // Shown as JSON, where a tab or a line break in it can be seen.\n throw new UsageError(`--${name} is ${JSON.stringify(value)}, which is no value; give it one, or leave the option out`);\n }\n }\n if (spec?.noArgument !== undefined && positionals.length > 0) {\n const extra = positionals.map((argument) => `\"${argument}\"`).join(', ');\n throw new UsageError(`${command} takes no argument, not ${extra}: spec-brief ${command}${spec.noArgument}`);\n }\n return { command, values: parsed.values, positionals };\n}\n\n/** The value of an option declared a string, which is all `parseArgs` gives one. */\nfunction text(values: Values, key: string): string | undefined {\n return values[key] as string | undefined;\n}\n\nfunction flag(values: Values, key: string): boolean {\n return values[key] === true;\n}\n\nfunction integer(values: Values, key: string, minimum: number): number | undefined {\n const raw = text(values, key);\n if (raw === undefined) return undefined;\n if (!/^\\d+$/.test(raw) || Number(raw) < minimum) throw new UsageError(`--${key} must be a whole number of at least ${minimum}, not \"${raw}\"`);\n return Number(raw);\n}\n\nasync function version(): Promise<string> {\n const pkg = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8')) as { version: string };\n return pkg.version;\n}\n\ninterface Run {\n /**\n * Today, as the environment the run was given says. Asked only by a command\n * that writes a date and was given none: a `SOURCE_DATE_EPOCH` that cannot\n * be read stops the run that would have written the clock's date for it,\n * and no run whose answer it has no part in.\n */\n readonly today: () => string;\n readonly out: (text: string) => void;\n readonly err: (text: string) => void;\n readonly style: Style;\n readonly format: Format;\n readonly strict: boolean;\n readonly version: string;\n readonly values: Values;\n readonly positionals: readonly string[];\n readonly cwd: string;\n}\n\nfunction useColor(values: Values, io: CliIO): boolean {\n if (flag(values, 'no-color')) return false;\n if (flag(values, 'color')) return true;\n const env = io.env ?? process.env;\n if ((env['NO_COLOR'] ?? '') !== '') return false;\n const force = env['FORCE_COLOR'];\n if (force !== undefined && force !== '') return force !== '0';\n // A terminal that says it is dumb has asked for no escape sequence, and\n // Node itself counts one colour for it: the family's tools read it alike.\n if (env['TERM'] === 'dumb') return false;\n return (io.stdout ?? process.stdout).isTTY === true;\n}\n\nasync function openEngine(run: Run): Promise<BriefEngine> {\n return BriefEngine.open({\n cwd: text(run.values, 'root') ?? run.cwd,\n config: text(run.values, 'config'),\n ...(flag(run.values, 'no-git') ? { git: null } : {}),\n noConfig: flag(run.values, 'no-config'),\n });\n}\n\nfunction emitFindings(run: Run, command: string, findings: readonly Finding[], checked: number, extra: Record<string, unknown> = {}): number {\n const failed = failing(findings, run.strict);\n switch (run.format) {\n case 'json':\n run.out(jsonDocument(command, run.version, { ok: !failed, checked, summary: summarise(findings), findings: findings.map(findingJson), ...extra }));\n break;\n case 'sarif':\n run.out(sarif(findings, run.version));\n break;\n case 'github':\n run.out(githubCommands(findings));\n break;\n case 'gitlab':\n run.out(gitlabCodeQuality(findings));\n break;\n case 'pretty':\n if (findings.length > 0) run.out(`${prettyFindings(findings, run.style)}\\n\\n`);\n run.out(`${findings.length === 0 ? `${checked} brief(s) checked, no findings` : `${summaryLine(findings)} in ${checked} brief(s)`}\\n`);\n break;\n }\n return failed ? EXIT_FAILED : EXIT_OK;\n}\n\nasync function runInit(run: Run): Promise<number> {\n const root = text(run.values, 'root') ?? run.cwd;\n const fs = new NodeFileSystem(root);\n for (const name of CONFIG_FILES) {\n if (await fs.exists(name)) throw new UsageError(`${name} already exists here; edit it instead`);\n }\n // A directory above the root is refused as the configuration refuses one\n // (config.ts), in the same words, before anything is written.\n const inside = (option: string, given: string): string => {\n try {\n return normalisePath(given);\n } catch {\n throw new UsageError(`--${option} must be a directory inside the repository, not \"${given}\"`);\n }\n };\n const briefs = inside('briefs', text(run.values, 'briefs') ?? 'briefs');\n const archive = inside('archive', text(run.values, 'archive') ?? `${briefs}/archive`);\n if (briefs === '' || archive === '' || briefs === archive) throw new UsageError('--briefs and --archive must be two directories');\n const config = `${JSON.stringify(initialConfig(briefs, archive), null, 2)}\\n`;\n await fs.write('.spec-brief.json', config);\n const written = ['.spec-brief.json'];\n for (const dir of [briefs, archive]) {\n const keep = `${dir}/.gitkeep`;\n if ((await fs.list(dir)) === null) {\n await fs.write(keep, '');\n written.push(keep);\n }\n }\n if (run.format === 'json') run.out(jsonDocument('init', run.version, { ok: true, written }));\n else run.out(`${written.map((w) => `wrote ${w}`).join('\\n')}\\nnext: spec-brief new \"<title>\"\\n`);\n return EXIT_OK;\n}\n\nasync function runNew(run: Run): Promise<number> {\n const title = run.positionals.join(' ').trim();\n if (title === '') throw new UsageError('new needs a title: spec-brief new \"<title>\"');\n const listed = text(run.values, 'depends-on');\n const dependsOn = listed?.split(',').map((d) => d.trim());\n // A list that names no brief is not a brief that depends on none: written\n // as given, \",\" scaffolded a brief with no dependency and said nothing.\n if (dependsOn?.every((d) => d === '')) {\n throw new UsageError(`--depends-on is ${JSON.stringify(listed)}, which names no brief; give it ids with commas between them, as in 7,8, or leave the option out`);\n }\n // And a place in it that names none is a brief left out: \"$A,$B\" with one\n // of the two unset scaffolded a brief that depends on the other alone.\n if (dependsOn?.includes('')) {\n throw new UsageError(`--depends-on is ${JSON.stringify(listed)}, which names no brief in one of its places; give it ids with one comma between each two, as in 7,8, and none before or after`);\n }\n const engine = await openEngine(run);\n const created = await engine.create({\n title,\n id: text(run.values, 'id'),\n type: text(run.values, 'type'),\n wave: integer(run.values, 'wave', 0),\n dependsOn,\n date: text(run.values, 'date') ?? run.today(),\n });\n if (run.format === 'json') run.out(jsonDocument('new', run.version, { ok: true, file: created.file }));\n else run.out(`wrote ${created.file}\\n`);\n return EXIT_OK;\n}\n\nasync function runLint(run: Run): Promise<number> {\n const engine = await openEngine(run);\n engine.requireBriefs();\n const findings = await engine.lint(run.positionals);\n const checked = run.positionals.length === 0 ? engine.corpus.briefs.length : run.positionals.length;\n return emitFindings(run, 'lint', findings, checked, { sections: sectionsJson(engine.config) });\n}\n\nasync function runList(run: Run): Promise<number> {\n const engine = await openEngine(run);\n engine.requireBriefs();\n const briefs = flag(run.values, 'archived') ? engine.corpus.briefs : engine.corpus.live;\n const ready = new Set(engine.ready());\n const rows: ListRow[] = briefs\n .map((brief) => ({ brief, ready: ready.has(brief), waitingOn: engine.waitingOn(brief) }))\n .filter((row) => !flag(run.values, 'ready') || row.ready);\n if (run.format === 'json') {\n run.out(\n jsonDocument('list', run.version, {\n ok: true,\n briefs: rows.map((r) => briefJson(r.brief, { ready: r.ready, waitingOn: r.waitingOn })),\n sections: sectionsJson(engine.config),\n }),\n );\n } else {\n run.out(`${prettyList(rows, run.style)}\\n`);\n }\n return EXIT_OK;\n}\n\nasync function runMatrix(run: Run): Promise<number> {\n const engine = await openEngine(run);\n engine.requireBriefs();\n const { report, findings } = await engine.collisions({ all: flag(run.values, 'all-waves') });\n const sorted = sortFindings(findings);\n if (run.format === 'pretty') {\n // Drawn from what the run reports, so a rule that is off marks nothing in the grid.\n run.out(`${prettyMatrix(reported(engine.corpus, report), run.style)}\\n`);\n return failing(sorted, run.strict) ? EXIT_FAILED : EXIT_OK;\n }\n return emitFindings(run, 'matrix', sorted, engine.corpus.live.length, matrixJson(report));\n}\n\n/**\n * The waves, computed. The view shows the moves, their reasons and the\n * cycles; the other findings - briefs that run alone, pairs the search could\n * not decide, a front matter that cannot take a wave - print beneath it.\n */\nasync function runSchedule(run: Run): Promise<number> {\n const engine = await openEngine(run);\n engine.requireBriefs();\n const { schedule: computed, findings } = await engine.schedule();\n let written: string[] | null = null;\n let reported: Finding[] = findings;\n if (flag(run.values, 'write')) {\n const result = await engine.writeWaves(computed);\n written = result.written;\n // Written, the waves hold, and the findings that said they did not are answered.\n reported = [...(written.length > 0 ? findings.filter((f) => f.rule !== 'wave-schedule') : findings), ...result.refused];\n }\n const sorted = sortFindings(reported);\n if (run.format === 'pretty') {\n run.out(`${prettySchedule(computed, written, run.style)}\\n`);\n const rest = sorted.filter((f) => f.rule !== 'wave-schedule' && f.rule !== 'dependency-cycle');\n if (rest.length > 0) run.out(`\\n${prettyFindings(rest, run.style)}\\n`);\n return failing(sorted, run.strict) ? EXIT_FAILED : EXIT_OK;\n }\n return emitFindings(run, 'schedule', sorted, engine.corpus.live.length, { ...scheduleJson(computed), written });\n}\n\nasync function runTransition(run: Run, action: 'archive' | 'unarchive'): Promise<number> {\n const reference = run.positionals[0];\n if (reference === undefined || run.positionals.length > 1) throw new UsageError(`${action} takes one brief: spec-brief ${action} <brief>`);\n const engine = await openEngine(run);\n const dryRun = flag(run.values, 'dry-run');\n const plan: Plan =\n action === 'archive'\n ? await engine.planArchive(reference, {\n pr: integer(run.values, 'pr', 1),\n commit: text(run.values, 'commit'),\n base: text(run.values, 'base'),\n summary: text(run.values, 'summary'),\n date: text(run.values, 'date') ?? run.today(),\n allowDirty: flag(run.values, 'allow-dirty'),\n strict: run.strict,\n noGit: flag(run.values, 'no-git'),\n })\n : engine.planUnarchive(reference, { strict: run.strict });\n const refused = plan.blocking.length > 0;\n if (!refused && !dryRun) await engine.apply(plan);\n if (run.format === 'json') run.out(jsonDocument(action, run.version, { ok: !refused, dryRun, plan: planJson(plan) }));\n else run.out(`${prettyPlan(plan, dryRun, run.style)}\\n`);\n return refused ? EXIT_FAILED : EXIT_OK;\n}\n\nexport async function main(argv: readonly string[] = process.argv.slice(2), io: CliIO = {}): Promise<number> {\n const stdout = io.stdout ?? process.stdout;\n const stderr = io.stderr ?? process.stderr;\n const err = (message: string): void => {\n stderr.write(`spec-brief: ${message}\\n`);\n };\n let parsed: Parsed;\n try {\n parsed = parse(argv);\n } catch (error) {\n err((error as Error).message);\n return EXIT_ERROR;\n }\n const { command, values, positionals } = parsed;\n // From here on, so that what comes before a command is covered as the\n // command is: --version and --help, the package's own manifest, the colour.\n // An error there left main as a rejection, which the launcher ended as\n // Node's uncaught error with exit 1, \"findings\" to a script.\n try {\n if (flag(values, 'version')) {\n stdout.write(`${await version()}\\n`);\n return EXIT_OK;\n }\n if (flag(values, 'help') || command === undefined) {\n stdout.write(HELP);\n // Asked for, the help is the answer; printed because no command was named, it is the error.\n return flag(values, 'help') ? EXIT_OK : EXIT_ERROR;\n }\n const spec = COMMANDS.get(command) as CommandSpec;\n const format = (text(values, 'format') ?? 'pretty') as Format;\n if (!spec.formats.includes(format)) {\n err(`--format for ${command} is one of ${spec.formats.join(', ')}, not \"${format}\"`);\n return EXIT_ERROR;\n }\n // A file, or a name with nothing behind it, had the search for a\n // configuration go on from its parent: the run reported on a tree nobody\n // had named, and `new` wrote into it. A path that cannot be reached is\n // not there to the run either. `init` alone is given a directory that\n // does not exist yet, which it makes.\n const root = text(values, 'root');\n if (root !== undefined) {\n const found = await stat(root).catch(() => null);\n if (found === null ? command !== 'init' : !found.isDirectory()) {\n throw new UsageError(`--root is \"${root}\", which is no directory; give it one, or leave the option out`);\n }\n }\n const run: Run = {\n today: () => today(io.env ?? process.env),\n out: (t) => {\n stdout.write(t);\n },\n err,\n // Read by the pretty format alone: the others have nothing to colour.\n style: { color: useColor(values, io) },\n format,\n strict: flag(values, 'strict'),\n version: await version(),\n values,\n positionals,\n cwd: io.cwd ?? process.cwd(),\n };\n switch (command) {\n case 'init':\n return await runInit(run);\n case 'new':\n return await runNew(run);\n case 'lint':\n return await runLint(run);\n case 'list':\n return await runList(run);\n case 'matrix':\n return await runMatrix(run);\n case 'schedule':\n return await runSchedule(run);\n case 'archive':\n return await runTransition(run, 'archive');\n default:\n return await runTransition(run, 'unarchive');\n }\n } catch (error) {\n // What git refused or could not do is git's message, and no line here.\n const expected = [ConfigError, UsageError, EngineError, ConflictError, TransactionError, GitError];\n if (expected.some((kind) => error instanceof kind)) {\n err((error as Error).message);\n return EXIT_ERROR;\n }\n // A write its reader had closed the pipe for is no defect either: the\n // answer was not delivered, which is still 2, and no stack sends a person\n // looking for a bug. The process's own streams report it as an event,\n // which the launcher answers in the same words; here it is a caller's\n // stream that throws it. It is read by its code: stdout and stderr are the\n // only pipes spec-brief writes to.\n if (!(error instanceof Error)) err(`unexpected error: ${String(error)}`);\n else if ((error as NodeJS.ErrnoException).code === 'EPIPE') err('stdout was closed before all of the output was written');\n else err(`unexpected error: ${error.stack ?? error.message}`);\n return EXIT_ERROR;\n }\n}\n"]}
1
+ {"version":3,"file":"cli.js","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The command line: argument parsing, dispatch, output and exit codes.\n *\n * Exit 0: done, nothing found. Exit 1: findings, collisions, or an action\n * refused. Exit 2: the run could not be trusted - a bad flag, a configuration\n * that does not load, a brief that does not exist. A run that checked nothing\n * must never exit as though it found nothing.\n */\n\nimport { readFile, stat } from 'node:fs/promises';\nimport { parseArgs, type ParseArgsConfig } from 'node:util';\n\nimport { TransactionError, ConflictError } from './apply.js';\nimport type { Plan } from './archive.js';\nimport { reported } from './collisions.js';\nimport { CONFIG_FILES, ConfigError, initialConfig } from './config.js';\nimport { BriefEngine, EngineError, today } from './engine.js';\nimport { NodeFileSystem } from './fs.js';\nimport { GitError } from './git.js';\nimport { failing, sortFindings, summarise } from './lint.js';\nimport { normalisePath } from './links.js';\nimport {\n briefJson,\n findingJson,\n FORMATS,\n type Format,\n githubCommands,\n gitlabCodeQuality,\n jsonDocument,\n type ListRow,\n matrixJson,\n planJson,\n prettyFindings,\n prettyList,\n prettyMatrix,\n prettyPlan,\n prettySchedule,\n sarif,\n scheduleJson,\n sectionsJson,\n type Style,\n summaryLine,\n} from './report.js';\nimport type { Finding } from './types.js';\n\nexport const EXIT_OK = 0;\nexport const EXIT_FAILED = 1;\nexport const EXIT_ERROR = 2;\n\nexport class UsageError extends Error {\n constructor(message: string) {\n super(message);\n this.name = 'UsageError';\n }\n}\n\nexport interface CliIO {\n readonly stdout?: { write(text: string): unknown; readonly isTTY?: boolean };\n readonly stderr?: { write(text: string): unknown };\n readonly cwd?: string;\n readonly env?: Readonly<Record<string, string | undefined>>;\n}\n\ntype Values = Record<string, string | boolean | undefined>;\n\nconst GLOBAL: NonNullable<ParseArgsConfig['options']> = {\n root: { type: 'string' },\n config: { type: 'string' },\n 'no-config': { type: 'boolean' },\n format: { type: 'string' },\n strict: { type: 'boolean' },\n 'no-git': { type: 'boolean' },\n color: { type: 'boolean' },\n 'no-color': { type: 'boolean' },\n help: { type: 'boolean', short: 'h' },\n version: { type: 'boolean', short: 'v' },\n};\n\ninterface CommandSpec {\n readonly options: NonNullable<ParseArgsConfig['options']>;\n readonly formats: readonly Format[];\n /**\n * Set on a command that takes no argument: what its refusal of one adds to\n * the usage, which is where the option a person most likely meant is named.\n */\n readonly noArgument?: string;\n}\n\nconst TABLE: Readonly<Record<string, CommandSpec>> = {\n init: {\n options: { briefs: { type: 'string' }, archive: { type: 'string' } },\n formats: ['pretty', 'json'],\n noArgument: '; --root <dir> names the directory it sets up, and --briefs <dir> the one for the briefs',\n },\n new: {\n options: {\n id: { type: 'string' },\n type: { type: 'string' },\n wave: { type: 'string' },\n 'depends-on': { type: 'string' },\n date: { type: 'string' },\n },\n formats: ['pretty', 'json'],\n },\n lint: { options: {}, formats: FORMATS },\n list: { options: { ready: { type: 'boolean' }, archived: { type: 'boolean' } }, formats: ['pretty', 'json'], noArgument: '' },\n matrix: { options: { 'all-waves': { type: 'boolean' } }, formats: FORMATS, noArgument: '' },\n schedule: { options: { write: { type: 'boolean' } }, formats: FORMATS, noArgument: '' },\n archive: {\n options: {\n pr: { type: 'string' },\n commit: { type: 'string' },\n base: { type: 'string' },\n summary: { type: 'string' },\n date: { type: 'string' },\n 'allow-dirty': { type: 'boolean' },\n 'dry-run': { type: 'boolean' },\n },\n formats: ['pretty', 'json'],\n },\n unarchive: { options: { 'dry-run': { type: 'boolean' } }, formats: ['pretty', 'json'] },\n};\n\n/**\n * Whether taking the option would tell someone what is not so. `init\n * --strict` says the briefs were set up strictly, where nothing was strict;\n * `init --config team.json` that the configuration was written there, where\n * `.spec-brief.json` was; `init --color` and `new --color` that colour was\n * printed, where neither prints any; `new --strict` and `list --strict` that\n * a warning would have failed the run, where neither has one. Each ran as\n * the line without the option does, exit 0.\n *\n * A function, not a table beside the commands': a table built when the\n * module loads is static to Stryker, and each of its mutants then runs the\n * whole suite (ADR-0009).\n */\nfunction untrue(command: string, option: string): boolean {\n switch (option) {\n case 'config':\n return command === 'init';\n case 'strict':\n return command === 'init' || command === 'new' || command === 'list';\n case 'color':\n return command === 'init' || command === 'new';\n // Each caller asks only whether the answer is true, so the mutant that\n // leaves this case out, and answers nothing, is equivalent.\n default:\n return false;\n }\n}\n\n/**\n * Whether the option asks the command to leave out what it never does, and\n * so asks for what is already so: `init` opens no configuration file and\n * asks git nothing, and neither it nor `new` prints colour. Such an option\n * is taken. A script that runs every command in a tree without git, or into\n * a log, passes it to each of them, as spec-harness passes `--no-color`.\n * The command reads nothing of it, so a refusal's line lists it apart from\n * what the command reads, as taken.\n */\nfunction alreadySo(command: string, option: string): boolean {\n switch (option) {\n case 'no-config':\n case 'no-git':\n return command === 'init';\n case 'no-color':\n return command === 'init' || command === 'new';\n // Each caller asks only whether the answer is true, so the mutant that\n // leaves this case out, and answers nothing, is equivalent.\n default:\n return false;\n }\n}\n\n/** Options by their names on the command line, as a sentence lists them. */\nfunction listed(names: readonly string[]): string {\n const options = names.map((name) => `--${name}`);\n return options.length === 1 ? (options[0] as string) : `${options.slice(0, -1).join(', ')} and ${options.at(-1) as string}`;\n}\n\n/**\n * Why a command line that parsed is still not one to run.\n *\n * An option is refused where taking it would tell someone what is not so,\n * and so are two options of which one would go unread: `--config team.json\n * --no-config` says the file was read, where the defaults ran, and `--color\n * --no-color` that colour was forced on, where it was off. An option that\n * asks a command to leave out what it never does asks for what is already\n * so, and is taken.\n */\nfunction unread(command: string, spec: CommandSpec, values: Values): string | null {\n // The first such option as the line was typed, which is the order the\n // parser keeps.\n const stray = Object.keys(values).find((option) => untrue(command, option));\n if (stray !== undefined) {\n const shared = Object.keys(GLOBAL).filter((option) => option !== 'help' && option !== 'version' && !untrue(command, option));\n const reads = [...shared.filter((option) => !alreadySo(command, option)), ...Object.keys(spec.options)];\n const takes = shared.filter((option) => alreadySo(command, option));\n return `${command} does not read --${stray}; it reads ${listed(reads)}${takes.length > 0 ? `, and takes ${listed(takes)}` : ''}`;\n }\n if (text(values, 'config') !== undefined && flag(values, 'no-config')) {\n return '--config is given beside --no-config, which has the run read no configuration file; give one of the two';\n }\n if (flag(values, 'color') && flag(values, 'no-color')) return '--color is given beside --no-color, which turns colour off; give one of the two';\n return null;\n}\n\n/**\n * The commands by name, and nothing for a command line that names none. A map,\n * because an object answers to more names than it was given: `constructor` and\n * `toString` are no commands.\n */\nconst COMMANDS: ReadonlyMap<string | undefined, CommandSpec> = new Map(Object.entries(TABLE));\n\n/**\n * The formats each command writes, read from the table `main` checks a\n * `--format` against, so the help names no format a command refuses: the\n * finding formats are `lint`'s, `matrix`'s and `schedule`'s alone.\n */\nfunction formatsHelp(): string {\n const groups = new Map<string, string[]>();\n for (const [command, spec] of Object.entries(TABLE)) {\n const formats = spec.formats.join(', ');\n groups.set(formats, [...(groups.get(formats) ?? []), command]);\n }\n const rows = [...groups].map(([formats, commands]) => [commands.join(', '), formats] as const);\n const width = Math.max(...rows.map(([commands]) => commands.length));\n return rows.map(([commands, formats]) => ` ${commands.padEnd(width)} ${formats}`).join('\\n');\n}\n\nexport const HELP = `spec-brief - lint, schedule and archive task briefs\n\nUsage:\n spec-brief <command> [options]\n\nCommands:\n init write .spec-brief.json and the brief directories\n new <title> scaffold a brief with the next free id\n lint [brief...] check briefs against the configuration\n list briefs with their status, wave and readiness\n matrix scope collisions between briefs in the same wave\n schedule the waves the live briefs can run in, computed\n archive <brief> close a round: check it, stamp it, freeze it, move it\n unarchive <brief> reopen an archived brief\n\nOptions for every command, except where a line says otherwise:\n --root <dir> run from this directory instead of the current one; it must exist, unless init makes it\n --config <file> use this configuration file; not for init, which writes .spec-brief.json\n --no-config use the defaults, ignoring any configuration file\n --format <format> the output format, pretty by default; each command's are below\n --strict treat warnings as errors; not for init, new or list, which have none\n --no-git leave git out; read the files on disk instead\n --color, --no-color force colour on or off; --color not for init or new, which print none\n -h, --help show this help\n -v, --version show the version\n\nFormats:\n${formatsHelp()}\n\ninit:\n --briefs <dir> the directory of live briefs; default briefs\n --archive <dir> the directory of archived briefs; default <briefs>/archive\n\nnew:\n --id <id> use this id instead of the next free one\n --type <type> a brief type from the configuration\n --wave <n> the wave it runs in\n --depends-on <ids> comma-separated ids it runs after\n --date <YYYY-MM-DD> the date in its front matter; default SOURCE_DATE_EPOCH's, or today's in UTC\n\nlist:\n --ready only briefs that can run now: dependencies archived, not drafts or deferred\n --archived include archived briefs\n\nmatrix:\n --all-waves compare every live brief, whatever its wave\n\nschedule:\n --write write each proposed wave into its brief's front matter\n\narchive:\n --pr <number> the pull request the round merged in\n --commit <rev> the commit the round landed as\n --base <rev> the branch it started from; the diff runs from the merge base\n --summary <text> what the round did, for the banner\n --date <YYYY-MM-DD> the archival date; default SOURCE_DATE_EPOCH's, or today's in UTC\n --allow-dirty archive although the tree has uncommitted work\n --dry-run print the plan and change nothing\n\nunarchive:\n --dry-run print the plan and change nothing\n\nAn option given an empty value, a list that names nothing and an argument a\ncommand does not take are refused, not read as if they were not there. So is\nan option where taking it would say what is not so, as init --strict, and so\nare --config beside --no-config and --color beside --no-color, of which one\nwould go unread. An option that asks a command to leave out what it never\ndoes is taken, as init --no-git: it asks for what is already so.\n\nExit codes: 0 clean, 1 findings or refused, 2 the run could not be trusted.\n`;\n\ninterface Parsed {\n readonly command: string | undefined;\n readonly values: Values;\n readonly positionals: readonly string[];\n}\n\n/** Global options that take a value, so the value is not mistaken for the command. */\nconst VALUED = new Set(['--root', '--config', '--format']);\n\nfunction commandOf(argv: readonly string[]): string | undefined {\n for (let i = 0; i < argv.length; i += 1) {\n const arg = argv[i] as string;\n if (arg === '--') return argv[i + 1];\n if (VALUED.has(arg)) {\n i += 1;\n continue;\n }\n if (!arg.startsWith('-')) return arg;\n }\n return undefined;\n}\n\nexport function parse(argv: readonly string[]): Parsed {\n const command = commandOf(argv);\n const spec = COMMANDS.get(command);\n if (command !== undefined && spec === undefined) {\n throw new UsageError(`\"${command}\" is not a command; run spec-brief --help`);\n }\n let parsed: { values: Values; positionals: string[] };\n try {\n parsed = parseArgs({\n args: [...argv],\n options: { ...GLOBAL, ...(spec?.options ?? {}) },\n allowPositionals: true,\n strict: true,\n }) as { values: Values; positionals: string[] };\n } catch (error) {\n throw new UsageError((error as Error).message);\n }\n const positionals = parsed.positionals.slice(1);\n // What the parser takes is not yet what names something. An option whose\n // value is empty, as `--root \"$DIR\"` is where the variable is not set, was\n // read as the option left out, and an argument no command asked for was\n // dropped: either way the run answered a question nobody had put, exit 0.\n for (const [name, value] of Object.entries(parsed.values)) {\n if (typeof value === 'string' && value.trim() === '') {\n // Shown as JSON, where a tab or a line break in it can be seen.\n throw new UsageError(`--${name} is ${JSON.stringify(value)}, which is no value; give it one, or leave the option out`);\n }\n }\n if (spec?.noArgument !== undefined && positionals.length > 0) {\n const extra = positionals.map((argument) => `\"${argument}\"`).join(', ');\n throw new UsageError(`${command} takes no argument, not ${extra}: spec-brief ${command}${spec.noArgument}`);\n }\n return { command, values: parsed.values, positionals };\n}\n\n/** The value of an option declared a string, which is all `parseArgs` gives one. */\nfunction text(values: Values, key: string): string | undefined {\n return values[key] as string | undefined;\n}\n\nfunction flag(values: Values, key: string): boolean {\n return values[key] === true;\n}\n\nfunction integer(values: Values, key: string, minimum: number): number | undefined {\n const raw = text(values, key);\n if (raw === undefined) return undefined;\n if (!/^\\d+$/.test(raw) || Number(raw) < minimum) throw new UsageError(`--${key} must be a whole number of at least ${minimum}, not \"${raw}\"`);\n return Number(raw);\n}\n\nasync function version(): Promise<string> {\n const pkg = JSON.parse(await readFile(new URL('../package.json', import.meta.url), 'utf8')) as { version: string };\n return pkg.version;\n}\n\ninterface Run {\n /**\n * Today, as the environment the run was given says. Asked only by a command\n * that writes a date and was given none: a `SOURCE_DATE_EPOCH` that cannot\n * be read stops the run that would have written the clock's date for it,\n * and no run whose answer it has no part in.\n */\n readonly today: () => string;\n readonly out: (text: string) => void;\n readonly err: (text: string) => void;\n readonly style: Style;\n readonly format: Format;\n readonly strict: boolean;\n readonly version: string;\n readonly values: Values;\n readonly positionals: readonly string[];\n readonly cwd: string;\n}\n\nfunction useColor(values: Values, io: CliIO): boolean {\n if (flag(values, 'no-color')) return false;\n if (flag(values, 'color')) return true;\n const env = io.env ?? process.env;\n if ((env['NO_COLOR'] ?? '') !== '') return false;\n // Off for exactly \"0\" and exactly \"false\": Node itself and supports-color\n // read \"false\" as off, and here it forced colour on. Any other value that\n // is not empty is on, \"FALSE\" too, which is the one reading the family's\n // tools share (spec-core ADR-0005).\n const force = env['FORCE_COLOR'];\n if (force !== undefined && force !== '') return force !== '0' && force !== 'false';\n // A terminal that says it is dumb has asked for no escape sequence, and\n // Node itself counts one colour for it: the family's tools read it alike.\n if (env['TERM'] === 'dumb') return false;\n return (io.stdout ?? process.stdout).isTTY === true;\n}\n\nasync function openEngine(run: Run): Promise<BriefEngine> {\n return BriefEngine.open({\n cwd: text(run.values, 'root') ?? run.cwd,\n config: text(run.values, 'config'),\n ...(flag(run.values, 'no-git') ? { git: null } : {}),\n noConfig: flag(run.values, 'no-config'),\n });\n}\n\nfunction emitFindings(run: Run, command: string, findings: readonly Finding[], checked: number, extra: Record<string, unknown> = {}): number {\n const failed = failing(findings, run.strict);\n switch (run.format) {\n case 'json':\n run.out(jsonDocument(command, run.version, { ok: !failed, checked, summary: summarise(findings), findings: findings.map(findingJson), ...extra }));\n break;\n case 'sarif':\n run.out(sarif(findings, run.version));\n break;\n case 'github':\n run.out(githubCommands(findings));\n break;\n case 'gitlab':\n run.out(gitlabCodeQuality(findings));\n break;\n case 'pretty':\n if (findings.length > 0) run.out(`${prettyFindings(findings, run.style)}\\n\\n`);\n run.out(`${findings.length === 0 ? `${checked} brief(s) checked, no findings` : `${summaryLine(findings)} in ${checked} brief(s)`}\\n`);\n break;\n }\n return failed ? EXIT_FAILED : EXIT_OK;\n}\n\nasync function runInit(run: Run): Promise<number> {\n const root = text(run.values, 'root') ?? run.cwd;\n const fs = new NodeFileSystem(root);\n for (const name of CONFIG_FILES) {\n if (await fs.exists(name)) throw new UsageError(`${name} already exists here; edit it instead`);\n }\n // A directory above the root is refused as the configuration refuses one\n // (config.ts), in the same words, before anything is written.\n const inside = (option: string, given: string): string => {\n try {\n return normalisePath(given);\n } catch {\n throw new UsageError(`--${option} must be a directory inside the repository, not \"${given}\"`);\n }\n };\n const briefs = inside('briefs', text(run.values, 'briefs') ?? 'briefs');\n const archive = inside('archive', text(run.values, 'archive') ?? `${briefs}/archive`);\n if (briefs === '' || archive === '' || briefs === archive) throw new UsageError('--briefs and --archive must be two directories');\n const config = `${JSON.stringify(initialConfig(briefs, archive), null, 2)}\\n`;\n await fs.write('.spec-brief.json', config);\n const written = ['.spec-brief.json'];\n for (const dir of [briefs, archive]) {\n const keep = `${dir}/.gitkeep`;\n if ((await fs.list(dir)) === null) {\n await fs.write(keep, '');\n written.push(keep);\n }\n }\n if (run.format === 'json') run.out(jsonDocument('init', run.version, { ok: true, written }));\n else run.out(`${written.map((w) => `wrote ${w}`).join('\\n')}\\nnext: spec-brief new \"<title>\"\\n`);\n return EXIT_OK;\n}\n\nasync function runNew(run: Run): Promise<number> {\n const title = run.positionals.join(' ').trim();\n if (title === '') throw new UsageError('new needs a title: spec-brief new \"<title>\"');\n const listed = text(run.values, 'depends-on');\n const dependsOn = listed?.split(',').map((d) => d.trim());\n // A list that names no brief is not a brief that depends on none: written\n // as given, \",\" scaffolded a brief with no dependency and said nothing.\n if (dependsOn?.every((d) => d === '')) {\n throw new UsageError(`--depends-on is ${JSON.stringify(listed)}, which names no brief; give it ids with commas between them, as in 7,8, or leave the option out`);\n }\n // And a place in it that names none is a brief left out: \"$A,$B\" with one\n // of the two unset scaffolded a brief that depends on the other alone.\n if (dependsOn?.includes('')) {\n throw new UsageError(`--depends-on is ${JSON.stringify(listed)}, which names no brief in one of its places; give it ids with one comma between each two, as in 7,8, and none before or after`);\n }\n const engine = await openEngine(run);\n const created = await engine.create({\n title,\n id: text(run.values, 'id'),\n type: text(run.values, 'type'),\n wave: integer(run.values, 'wave', 0),\n dependsOn,\n date: text(run.values, 'date') ?? run.today(),\n });\n if (run.format === 'json') run.out(jsonDocument('new', run.version, { ok: true, file: created.file }));\n else run.out(`wrote ${created.file}\\n`);\n return EXIT_OK;\n}\n\nasync function runLint(run: Run): Promise<number> {\n const engine = await openEngine(run);\n engine.requireBriefs();\n const findings = await engine.lint(run.positionals);\n const checked = run.positionals.length === 0 ? engine.corpus.briefs.length : run.positionals.length;\n return emitFindings(run, 'lint', findings, checked, { sections: sectionsJson(engine.config) });\n}\n\nasync function runList(run: Run): Promise<number> {\n const engine = await openEngine(run);\n engine.requireBriefs();\n const briefs = flag(run.values, 'archived') ? engine.corpus.briefs : engine.corpus.live;\n const ready = new Set(engine.ready());\n const rows: ListRow[] = briefs\n .map((brief) => ({ brief, ready: ready.has(brief), waitingOn: engine.waitingOn(brief) }))\n .filter((row) => !flag(run.values, 'ready') || row.ready);\n if (run.format === 'json') {\n run.out(\n jsonDocument('list', run.version, {\n ok: true,\n briefs: rows.map((r) => briefJson(r.brief, { ready: r.ready, waitingOn: r.waitingOn })),\n sections: sectionsJson(engine.config),\n }),\n );\n } else {\n run.out(`${prettyList(rows, run.style)}\\n`);\n }\n return EXIT_OK;\n}\n\nasync function runMatrix(run: Run): Promise<number> {\n const engine = await openEngine(run);\n engine.requireBriefs();\n const { report, findings } = await engine.collisions({ all: flag(run.values, 'all-waves') });\n const sorted = sortFindings(findings);\n if (run.format === 'pretty') {\n // Drawn from what the run reports, so a rule that is off marks nothing in the grid.\n run.out(`${prettyMatrix(reported(engine.corpus, report), run.style)}\\n`);\n return failing(sorted, run.strict) ? EXIT_FAILED : EXIT_OK;\n }\n return emitFindings(run, 'matrix', sorted, engine.corpus.live.length, matrixJson(report));\n}\n\n/**\n * The waves, computed. The view shows the moves, their reasons and the\n * cycles; the other findings - briefs that run alone, pairs the search could\n * not decide, a front matter that cannot take a wave - print beneath it.\n */\nasync function runSchedule(run: Run): Promise<number> {\n const engine = await openEngine(run);\n engine.requireBriefs();\n const { schedule: computed, findings } = await engine.schedule();\n let written: string[] | null = null;\n let reported: Finding[] = findings;\n if (flag(run.values, 'write')) {\n const result = await engine.writeWaves(computed);\n written = result.written;\n // Written, the waves hold, and the findings that said they did not are answered.\n reported = [...(written.length > 0 ? findings.filter((f) => f.rule !== 'wave-schedule') : findings), ...result.refused];\n }\n const sorted = sortFindings(reported);\n if (run.format === 'pretty') {\n run.out(`${prettySchedule(computed, written, run.style)}\\n`);\n const rest = sorted.filter((f) => f.rule !== 'wave-schedule' && f.rule !== 'dependency-cycle');\n if (rest.length > 0) run.out(`\\n${prettyFindings(rest, run.style)}\\n`);\n return failing(sorted, run.strict) ? EXIT_FAILED : EXIT_OK;\n }\n return emitFindings(run, 'schedule', sorted, engine.corpus.live.length, { ...scheduleJson(computed), written });\n}\n\nasync function runTransition(run: Run, action: 'archive' | 'unarchive'): Promise<number> {\n const reference = run.positionals[0];\n if (reference === undefined || run.positionals.length > 1) throw new UsageError(`${action} takes one brief: spec-brief ${action} <brief>`);\n const engine = await openEngine(run);\n const dryRun = flag(run.values, 'dry-run');\n const plan: Plan =\n action === 'archive'\n ? await engine.planArchive(reference, {\n pr: integer(run.values, 'pr', 1),\n commit: text(run.values, 'commit'),\n base: text(run.values, 'base'),\n summary: text(run.values, 'summary'),\n date: text(run.values, 'date') ?? run.today(),\n allowDirty: flag(run.values, 'allow-dirty'),\n strict: run.strict,\n noGit: flag(run.values, 'no-git'),\n })\n : engine.planUnarchive(reference, { strict: run.strict });\n const refused = plan.blocking.length > 0;\n if (!refused && !dryRun) await engine.apply(plan);\n if (run.format === 'json') run.out(jsonDocument(action, run.version, { ok: !refused, dryRun, plan: planJson(plan) }));\n else run.out(`${prettyPlan(plan, dryRun, run.style)}\\n`);\n return refused ? EXIT_FAILED : EXIT_OK;\n}\n\nexport async function main(argv: readonly string[] = process.argv.slice(2), io: CliIO = {}): Promise<number> {\n const stdout = io.stdout ?? process.stdout;\n const stderr = io.stderr ?? process.stderr;\n const err = (message: string): void => {\n stderr.write(`spec-brief: ${message}\\n`);\n };\n let parsed: Parsed;\n try {\n parsed = parse(argv);\n } catch (error) {\n err((error as Error).message);\n return EXIT_ERROR;\n }\n const { command, values, positionals } = parsed;\n // From here on, so that what comes before a command is covered as the\n // command is: --version and --help, the package's own manifest, the colour.\n // An error there left main as a rejection, which the launcher ended as\n // Node's uncaught error with exit 1, \"findings\" to a script.\n try {\n if (flag(values, 'version')) {\n stdout.write(`${await version()}\\n`);\n return EXIT_OK;\n }\n if (flag(values, 'help') || command === undefined) {\n stdout.write(HELP);\n // Asked for, the help is the answer; printed because no command was named, it is the error.\n return flag(values, 'help') ? EXIT_OK : EXIT_ERROR;\n }\n const spec = COMMANDS.get(command) as CommandSpec;\n const refusal = unread(command, spec, values);\n if (refusal !== null) throw new UsageError(refusal);\n const format = (text(values, 'format') ?? 'pretty') as Format;\n if (!spec.formats.includes(format)) {\n err(`--format for ${command} is one of ${spec.formats.join(', ')}, not \"${format}\"`);\n return EXIT_ERROR;\n }\n // A file, or a name with nothing behind it, had the search for a\n // configuration go on from its parent: the run reported on a tree nobody\n // had named, and `new` wrote into it. A path that cannot be reached is\n // not there to the run either. `init` alone is given a directory that\n // does not exist yet, which it makes.\n const root = text(values, 'root');\n if (root !== undefined) {\n const found = await stat(root).catch(() => null);\n if (found === null ? command !== 'init' : !found.isDirectory()) {\n throw new UsageError(`--root is \"${root}\", which is no directory; give it one, or leave the option out`);\n }\n }\n const run: Run = {\n today: () => today(io.env ?? process.env),\n out: (t) => {\n stdout.write(t);\n },\n err,\n // Read by the pretty format alone: the others have nothing to colour.\n style: { color: useColor(values, io) },\n format,\n strict: flag(values, 'strict'),\n version: await version(),\n values,\n positionals,\n cwd: io.cwd ?? process.cwd(),\n };\n switch (command) {\n case 'init':\n return await runInit(run);\n case 'new':\n return await runNew(run);\n case 'lint':\n return await runLint(run);\n case 'list':\n return await runList(run);\n case 'matrix':\n return await runMatrix(run);\n case 'schedule':\n return await runSchedule(run);\n case 'archive':\n return await runTransition(run, 'archive');\n default:\n return await runTransition(run, 'unarchive');\n }\n } catch (error) {\n // What git refused or could not do is git's message, and no line here.\n const expected = [ConfigError, UsageError, EngineError, ConflictError, TransactionError, GitError];\n if (expected.some((kind) => error instanceof kind)) {\n err((error as Error).message);\n return EXIT_ERROR;\n }\n // A write its reader had closed the pipe for is no defect either: the\n // answer was not delivered, which is still 2, and no stack sends a person\n // looking for a bug. The process's own streams report it as an event,\n // which the launcher answers in the same words; here it is a caller's\n // stream that throws it. It is read by its code: stdout and stderr are the\n // only pipes spec-brief writes to.\n if (!(error instanceof Error)) err(`unexpected error: ${String(error)}`);\n else if ((error as NodeJS.ErrnoException).code === 'EPIPE') err('stdout was closed before all of the output was written');\n else err(`unexpected error: ${error.stack ?? error.message}`);\n return EXIT_ERROR;\n }\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@descent-vtt/spec-brief",
3
- "version": "0.7.0",
3
+ "version": "0.8.0",
4
4
  "description": "Lifecycle management for task briefs: lint the contract, map parallel collisions, and archive a round in one atomic command.",
5
5
  "keywords": [
6
6
  "agents",