@descent-vtt/spec-brief 0.1.0 → 0.2.1
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 +301 -0
- package/README.md +92 -22
- package/dist/archive.d.ts +52 -2
- package/dist/archive.js +205 -37
- package/dist/archive.js.map +1 -1
- package/dist/brief.d.ts +2 -0
- package/dist/brief.js +5 -1
- package/dist/brief.js.map +1 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +48 -14
- package/dist/cli.js.map +1 -1
- package/dist/collisions.d.ts +43 -12
- package/dist/collisions.js +90 -58
- package/dist/collisions.js.map +1 -1
- package/dist/config.d.ts +18 -0
- package/dist/config.js +66 -11
- package/dist/config.js.map +1 -1
- package/dist/corpus.d.ts +21 -1
- package/dist/corpus.js +51 -2
- package/dist/corpus.js.map +1 -1
- package/dist/engine.d.ts +33 -3
- package/dist/engine.js +112 -9
- package/dist/engine.js.map +1 -1
- package/dist/frontmatter.d.ts +18 -61
- package/dist/frontmatter.js +31 -300
- package/dist/frontmatter.js.map +1 -1
- package/dist/glob.d.ts +77 -54
- package/dist/glob.js +104 -433
- package/dist/glob.js.map +1 -1
- package/dist/index.d.ts +10 -8
- package/dist/index.js +8 -6
- package/dist/index.js.map +1 -1
- package/dist/links.d.ts +1 -1
- package/dist/links.js +3 -4
- package/dist/links.js.map +1 -1
- package/dist/lint.d.ts +33 -2
- package/dist/lint.js +9 -2
- package/dist/lint.js.map +1 -1
- package/dist/markdown.d.ts +27 -23
- package/dist/markdown.js +66 -235
- package/dist/markdown.js.map +1 -1
- package/dist/plugins.d.ts +14 -0
- package/dist/plugins.js +142 -6
- package/dist/plugins.js.map +1 -1
- package/dist/report.d.ts +40 -3
- package/dist/report.js +227 -11
- package/dist/report.js.map +1 -1
- package/dist/rules.d.ts +22 -4
- package/dist/rules.js +175 -45
- package/dist/rules.js.map +1 -1
- package/dist/scaffold.d.ts +1 -1
- package/dist/scaffold.js +10 -9
- package/dist/scaffold.js.map +1 -1
- package/dist/schedule.d.ts +133 -0
- package/dist/schedule.js +265 -0
- package/dist/schedule.js.map +1 -0
- package/dist/scope.d.ts +52 -0
- package/dist/scope.js +56 -0
- package/dist/scope.js.map +1 -0
- package/dist/text.d.ts +13 -0
- package/dist/text.js +23 -0
- package/dist/text.js.map +1 -1
- package/dist/trigger.d.ts +17 -0
- package/dist/trigger.js +49 -0
- package/dist/trigger.js.map +1 -0
- package/dist/types.d.ts +14 -5
- package/dist/types.js.map +1 -1
- package/dist/vendor/spec-core/markdown/frontmatter.d.ts +103 -0
- package/dist/vendor/spec-core/markdown/frontmatter.js +459 -0
- package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -0
- package/dist/vendor/spec-core/markdown/headings.d.ts +45 -0
- package/dist/vendor/spec-core/markdown/headings.js +199 -0
- package/dist/vendor/spec-core/markdown/headings.js.map +1 -0
- package/dist/vendor/spec-core/markdown/index.d.ts +5 -0
- package/dist/vendor/spec-core/markdown/index.js +4 -0
- package/dist/vendor/spec-core/markdown/index.js.map +1 -0
- package/dist/vendor/spec-core/markdown/layout.d.ts +39 -0
- package/dist/vendor/spec-core/markdown/layout.js +28 -0
- package/dist/vendor/spec-core/markdown/layout.js.map +1 -0
- package/dist/vendor/spec-core/markdown/links.d.ts +25 -0
- package/dist/vendor/spec-core/markdown/links.js +394 -0
- package/dist/vendor/spec-core/markdown/links.js.map +1 -0
- package/dist/vendor/spec-core/markdown/lists.d.ts +22 -0
- package/dist/vendor/spec-core/markdown/lists.js +127 -0
- package/dist/vendor/spec-core/markdown/lists.js.map +1 -0
- package/dist/vendor/spec-core/markdown/scan.d.ts +36 -0
- package/dist/vendor/spec-core/markdown/scan.js +463 -0
- package/dist/vendor/spec-core/markdown/scan.js.map +1 -0
- package/dist/vendor/spec-core/markdown/syntax.d.ts +75 -0
- package/dist/vendor/spec-core/markdown/syntax.js +181 -0
- package/dist/vendor/spec-core/markdown/syntax.js.map +1 -0
- package/dist/vendor/spec-core/markdown/tables.d.ts +18 -0
- package/dist/vendor/spec-core/markdown/tables.js +86 -0
- package/dist/vendor/spec-core/markdown/tables.js.map +1 -0
- package/dist/vendor/spec-core/markdown/types.d.ts +290 -0
- package/dist/vendor/spec-core/markdown/types.js +9 -0
- package/dist/vendor/spec-core/markdown/types.js.map +1 -0
- package/dist/vendor/spec-core/path/index.d.ts +1 -0
- package/dist/vendor/spec-core/path/index.js +2 -0
- package/dist/vendor/spec-core/path/index.js.map +1 -0
- package/dist/vendor/spec-core/path/posix.d.ts +83 -0
- package/dist/vendor/spec-core/path/posix.js +150 -0
- package/dist/vendor/spec-core/path/posix.js.map +1 -0
- package/dist/vendor/spec-core/pattern/automaton.d.ts +129 -0
- package/dist/vendor/spec-core/pattern/automaton.js +340 -0
- package/dist/vendor/spec-core/pattern/automaton.js.map +1 -0
- package/dist/vendor/spec-core/pattern/charset.d.ts +58 -0
- package/dist/vendor/spec-core/pattern/charset.js +116 -0
- package/dist/vendor/spec-core/pattern/charset.js.map +1 -0
- package/dist/vendor/spec-core/pattern/glob.d.ts +121 -0
- package/dist/vendor/spec-core/pattern/glob.js +481 -0
- package/dist/vendor/spec-core/pattern/glob.js.map +1 -0
- package/dist/vendor/spec-core/pattern/index.d.ts +6 -0
- package/dist/vendor/spec-core/pattern/index.js +4 -0
- package/dist/vendor/spec-core/pattern/index.js.map +1 -0
- package/dist/vendor/spec-core/pattern/regex.d.ts +67 -0
- package/dist/vendor/spec-core/pattern/regex.js +813 -0
- package/dist/vendor/spec-core/pattern/regex.js.map +1 -0
- package/dist/vendor/spec-core/text/index.d.ts +2 -0
- package/dist/vendor/spec-core/text/index.js +2 -0
- package/dist/vendor/spec-core/text/index.js.map +1 -0
- package/dist/vendor/spec-core/text/lines.d.ts +72 -0
- package/dist/vendor/spec-core/text/lines.js +156 -0
- package/dist/vendor/spec-core/text/lines.js.map +1 -0
- package/package.json +4 -3
- package/schema.json +17 -0
- package/src/vendor/spec-core/LICENSE +21 -0
- package/src/vendor/spec-core/README.md +8 -0
package/dist/plugins.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Loading rule plugins named by the configuration.\n *\n * spec-brief does not know how another tool signs a departure, records a\n * reproducer or measures a blast radius, and should not: the tool that\n * defines a format is the one that can check it. A plugin is a module whose\n * default export is a plugin object, or a function of the configured options\n * that returns one. Loading one runs its code, exactly as loading an ESLint\n * configuration does; the configuration belongs to the repository, and so\n * does that trust.\n */\n\nimport { createRequire } from 'node:module';\nimport { isAbsolute, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport type { PluginReference } from './config.js';\nimport { ConfigError } from './config.js';\nimport type { Plugin } from './lint.js';\nimport type { Rule } from './rules.js';\n\nconst SEVERITIES = new Set(['off', 'note', 'warning', 'error']);\n\nfunction specifierUrl(specifier: string, root: string): string {\n if (specifier.startsWith('.') || isAbsolute(specifier)) return pathToFileURL(resolve(root, specifier)).href;\n const require = createRequire(join(root, 'package.json'));\n return pathToFileURL(require.resolve(specifier)).href;\n}\n\nfunction isRule(value: unknown): value is Rule {\n if (typeof value !== 'object' || value === null) return false;\n const rule = value as Record<string, unknown>;\n return (\n typeof rule['id'] === 'string' &&\n /^[a-z0-9][a-z0-9-]*$/.test(rule['id']) &&\n typeof rule['description'] === 'string' &&\n typeof rule['severity'] === 'string' &&\n SEVERITIES.has(rule['severity']) &&\n typeof rule['check'] === 'function'\n );\n}\n\n/** Checks the shape a module exported, since nothing typed it on the way in. */\nexport function asPlugin(value: unknown, module: string, options: unknown): Plugin {\n const problems: string[] = [];\n if (typeof value !== 'object' || value === null) {\n throw new ConfigError(module, ['does not export a plugin: expected an object with \"name\" and \"rules\"']);\n }\n const candidate = value as Record<string, unknown>;\n const name = candidate['name'];\n const rules = candidate['rules'];\n if (typeof name !== 'string' || !/^[a-z0-9@][a-z0-9@/._-]*$/i.test(name)) problems.push('\"name\" must be a plain identifier');\n if (!Array.isArray(rules)) problems.push('\"rules\" must be a list');\n else {\n rules.forEach((rule, i) => {\n if (!isRule(rule)) problems.push(`rules[${i}] needs a lower-case \"id\", a \"description\", a \"severity\" and a \"check\" function`);\n });\n }\n if (problems.length > 0) throw new ConfigError(module, problems);\n return { name: name as string, rules: rules as Rule[], options };\n}\n\nexport async function loadPlugins(references: readonly PluginReference[], root: string): Promise<Plugin[]> {\n const plugins: Plugin[] = [];\n for (const reference of references) {\n let loaded: Record<string, unknown>;\n try {\n loaded = (await import(specifierUrl(reference.module, root))) as Record<string, unknown>;\n } catch (error) {\n throw new ConfigError(reference.module, [`could not be loaded: ${(error as Error).message}`]);\n }\n const exported = loaded['default'] ?? loaded['plugin'];\n const value = typeof exported === 'function' ? await (exported as (o: unknown) => unknown)(reference.options) : exported;\n plugins.push(asPlugin(value, reference.module, reference.options));\n }\n const names = plugins.map((p) => p.name);\n const repeated = names.filter((n, i) => names.indexOf(n) !== i);\n if (repeated.length > 0) throw new ConfigError('plugins', [`two plugins are named \"${repeated[0] as string}\"`]);\n return plugins;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"plugins.js","sourceRoot":"","sources":["../src/plugins.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Loading rule plugins named by the configuration.\n *\n * spec-brief does not know how another tool signs a departure, records a\n * reproducer or measures a blast radius, and should not: the tool that\n * defines a format is the one that can check it. A plugin is a module whose\n * default export is a plugin object, or a function of the configured options\n * that returns one. Loading one runs its code, exactly as loading an ESLint\n * configuration does; the configuration belongs to the repository, and so\n * does that trust.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport { createRequire } from 'node:module';\nimport { dirname, isAbsolute, join, resolve } from 'node:path';\nimport { pathToFileURL } from 'node:url';\n\nimport type { Waiver } from './archive.js';\nimport type { PluginReference } from './config.js';\nimport { ConfigError } from './config.js';\nimport type { Plugin } from './lint.js';\nimport type { Rule } from './rules.js';\n\nconst SEVERITIES = new Set(['off', 'note', 'warning', 'error']);\n\n/** The conditions Node matches in \"exports\" when it imports a module. */\nconst IMPORT_CONDITIONS = new Set(['node', 'import', 'module-sync', 'default']);\n\n/**\n * A target of \"exports\": a path inside the package, `null` where the package\n * refuses the subpath, `undefined` where no condition matched and a fallback\n * may still. A target that is not a \"./\" path, or that climbs out of the\n * package or into another, is refused, as Node refuses it: its segments are\n * split on a backslash too, since `join` reads one as a separator on Windows,\n * where \"pkg/..\\..\\outside\" would otherwise climb out of node_modules.\n */\nfunction exportTarget(value: unknown, match: string | null): string | null | undefined {\n if (typeof value === 'string') {\n if (!value.startsWith('./')) return null;\n const path = match === null ? value : value.replaceAll('*', match);\n const parts = path.slice(2).split(/[\\\\/]/);\n return parts.some((part) => part === '..' || part === '.' || part.toLowerCase() === 'node_modules') ? null : path;\n }\n if (Array.isArray(value)) {\n for (const item of value) {\n const path = exportTarget(item, match);\n if (typeof path === 'string') return path;\n }\n return null;\n }\n if (typeof value === 'object' && value !== null) {\n for (const [condition, item] of Object.entries(value)) {\n if (!IMPORT_CONDITIONS.has(condition)) continue;\n const path = exportTarget(item, match);\n if (path !== undefined) return path;\n }\n return undefined;\n }\n return null;\n}\n\n/**\n * The file a package's \"exports\" gives a subpath (`.` or `./x`) under the\n * conditions of an import, or `null` when it gives none: Node's\n * PACKAGE_EXPORTS_RESOLVE. An exact key wins; then the \"*\" pattern with the\n * longest prefix, and of those the longest key.\n */\nexport function exportsTarget(exports: unknown, subpath: string): string | null {\n const keys = typeof exports === 'object' && exports !== null && !Array.isArray(exports) ? Object.keys(exports) : [];\n const dotted = keys.filter((key) => key.startsWith('.'));\n if (dotted.length === 0) return subpath === '.' ? (exportTarget(exports, null) ?? null) : null;\n // Subpaths beside conditions is a package Node refuses to read.\n if (dotted.length !== keys.length) return null;\n const map = exports as Record<string, unknown>;\n if (!subpath.includes('*') && Object.hasOwn(map, subpath)) return exportTarget(map[subpath], null) ?? null;\n let best: { readonly key: string; readonly prefix: number; readonly match: string } | undefined;\n for (const key of dotted) {\n const star = key.indexOf('*');\n if (star < 0 || key.includes('*', star + 1)) continue;\n const suffix = key.slice(star + 1);\n if (subpath.length < key.length || !subpath.startsWith(key.slice(0, star)) || !subpath.endsWith(suffix)) continue;\n if (best === undefined || star > best.prefix || (star === best.prefix && key.length > best.key.length)) {\n best = { key, prefix: star, match: subpath.slice(star, subpath.length - suffix.length) };\n }\n }\n return best === undefined ? null : (exportTarget(map[best.key], best.match) ?? null);\n}\n\n/** A package.json, `undefined` when there is none to read. */\nasync function manifest(path: string): Promise<Record<string, unknown> | undefined> {\n try {\n return JSON.parse(await readFile(path, 'utf8')) as Record<string, unknown>;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === 'ENOENT' || (error as NodeJS.ErrnoException).code === 'ENOTDIR') return undefined;\n throw error;\n }\n}\n\n/**\n * The file a package specifier names, found from the root the way an import\n * there would find it. `require.resolve` reads \"exports\" under the require\n * conditions, so a package that exports only for \"import\" - an ESM-only\n * plugin - could not be found; Node's `import.meta.resolve` resolves only\n * from the module calling it, not from the root. So the nearest\n * node_modules/<name> is found here and its \"exports\" read under the import\n * conditions; a package with no \"exports\" resolves as it always has.\n */\nasync function resolvePackage(specifier: string, root: string): Promise<string> {\n const slash = specifier.indexOf('/', specifier.startsWith('@') ? specifier.indexOf('/') + 1 : 0);\n const name = slash < 0 ? specifier : specifier.slice(0, slash);\n const subpath = slash < 0 ? '.' : `.${specifier.slice(slash)}`;\n let directory = root;\n // Bounded by the depth of the path: each pass moves one directory up.\n for (let depth = 0; depth < 256; depth += 1) {\n const packageDirectory = join(directory, 'node_modules', name);\n const found = await manifest(join(packageDirectory, 'package.json'));\n if (found !== undefined) {\n if (found['exports'] === undefined || found['exports'] === null) break;\n const target = exportsTarget(found['exports'], subpath);\n if (target === null) throw new Error(`${name} exports no \"${subpath}\" for import`);\n return join(packageDirectory, target);\n }\n const parent = dirname(directory);\n if (parent === directory) break;\n directory = parent;\n }\n return createRequire(join(root, 'package.json')).resolve(specifier);\n}\n\nasync function specifierUrl(specifier: string, root: string): Promise<string> {\n if (specifier.startsWith('.') || isAbsolute(specifier)) return pathToFileURL(resolve(root, specifier)).href;\n return pathToFileURL(await resolvePackage(specifier, root)).href;\n}\n\nfunction isRule(value: unknown): value is Rule {\n if (typeof value !== 'object' || value === null) return false;\n const rule = value as Record<string, unknown>;\n return (\n typeof rule['id'] === 'string' &&\n /^[a-z0-9][a-z0-9-]*$/.test(rule['id']) &&\n typeof rule['description'] === 'string' &&\n typeof rule['severity'] === 'string' &&\n SEVERITIES.has(rule['severity']) &&\n typeof rule['check'] === 'function'\n );\n}\n\n/** Checks the shape a module exported, since nothing typed it on the way in. */\nexport function asPlugin(value: unknown, module: string, options: unknown): Plugin {\n const problems: string[] = [];\n if (typeof value !== 'object' || value === null) {\n throw new ConfigError(module, ['does not export a plugin: expected an object with \"name\" and \"rules\"']);\n }\n const candidate = value as Record<string, unknown>;\n const name = candidate['name'];\n const rules = candidate['rules'];\n const waive = candidate['waive'];\n if (typeof name !== 'string' || !/^[a-z0-9@][a-z0-9@/._-]*$/i.test(name)) problems.push('\"name\" must be a plain identifier');\n if (!Array.isArray(rules)) problems.push('\"rules\" must be a list');\n else {\n rules.forEach((rule, i) => {\n if (!isRule(rule)) problems.push(`rules[${i}] needs a lower-case \"id\", a \"description\", a \"severity\" and a \"check\" function`);\n });\n }\n if (waive !== undefined && typeof waive !== 'function') problems.push('\"waive\" must be a function');\n if (problems.length > 0) throw new ConfigError(module, problems);\n const plugin: Plugin = { name: name as string, rules: rules as Rule[], options };\n return waive === undefined ? plugin : { ...plugin, waive: waive as NonNullable<Plugin['waive']> };\n}\n\n/**\n * Checks what a `waive` hook returned: a list of `{ rule, path, reason }`,\n * each a string. A hook that returns nothing waives nothing: a function that\n * found no ruling and fell off its end has answered, not failed.\n */\nexport function asWaivers(value: unknown, plugin: string): Waiver[] {\n const isWaiver = (item: unknown): item is Waiver => {\n if (typeof item !== 'object' || item === null) return false;\n const w = item as Record<string, unknown>;\n return typeof w['rule'] === 'string' && typeof w['path'] === 'string' && typeof w['reason'] === 'string';\n };\n if (value === undefined) return [];\n if (!Array.isArray(value) || !value.every(isWaiver)) {\n throw new ConfigError(`plugin \"${plugin}\"`, ['\"waive\" must return a list of { rule, path, reason }, each a string']);\n }\n return value.map((w) => ({ rule: w.rule, path: w.path, reason: w.reason }));\n}\n\nexport async function loadPlugins(references: readonly PluginReference[], root: string): Promise<Plugin[]> {\n const plugins: Plugin[] = [];\n for (const reference of references) {\n let loaded: Record<string, unknown>;\n try {\n loaded = (await import(await specifierUrl(reference.module, root))) as Record<string, unknown>;\n } catch (error) {\n throw new ConfigError(reference.module, [`could not be loaded: ${(error as Error).message}`]);\n }\n const exported = loaded['default'] ?? loaded['plugin'];\n const value = typeof exported === 'function' ? await (exported as (o: unknown) => unknown)(reference.options) : exported;\n plugins.push(asPlugin(value, reference.module, reference.options));\n }\n const names = plugins.map((p) => p.name);\n const repeated = names.filter((n, i) => names.indexOf(n) !== i);\n if (repeated.length > 0) throw new ConfigError('plugins', [`two plugins are named \"${repeated[0] as string}\"`]);\n return plugins;\n}\n"]}
|
package/dist/report.d.ts
CHANGED
|
@@ -5,15 +5,26 @@
|
|
|
5
5
|
* `json` is a document with a version, for orchestrators. `sarif` is SARIF
|
|
6
6
|
* 2.1.0, for code-scanning upload. `github` is workflow commands, which put a
|
|
7
7
|
* finding on the line of the pull request with no upload and no permission.
|
|
8
|
+
* `gitlab` is a Code Quality report, the artifact a GitLab merge request reads,
|
|
9
|
+
* so the family is not GitHub's alone.
|
|
8
10
|
*/
|
|
9
11
|
import type { Plan } from './archive.js';
|
|
10
12
|
import type { Brief } from './brief.js';
|
|
13
|
+
import type { Config } from './config.js';
|
|
11
14
|
import type { CollisionReport } from './collisions.js';
|
|
15
|
+
import { type Schedule } from './schedule.js';
|
|
12
16
|
import type { Finding } from './types.js';
|
|
13
|
-
export type Format = 'pretty' | 'json' | 'sarif' | 'github';
|
|
17
|
+
export type Format = 'pretty' | 'json' | 'sarif' | 'github' | 'gitlab';
|
|
14
18
|
export declare const FORMATS: readonly Format[];
|
|
15
|
-
/**
|
|
16
|
-
|
|
19
|
+
/**
|
|
20
|
+
* The version of the JSON documents this tool prints, every command's alike.
|
|
21
|
+
* Bumped when a field changes meaning. 2: a collision in `matrix` is a pair of
|
|
22
|
+
* briefs, with every pair of patterns that meets and a witness that is always
|
|
23
|
+
* a file; a shared-directory entry lists its directories; and deferred briefs,
|
|
24
|
+
* and the briefs waiting on them, leave `waves[].briefs` for `deferred` and
|
|
25
|
+
* `waiting`.
|
|
26
|
+
*/
|
|
27
|
+
export declare const JSON_SCHEMA_VERSION = 2;
|
|
17
28
|
export interface Style {
|
|
18
29
|
readonly color: boolean;
|
|
19
30
|
}
|
|
@@ -24,8 +35,24 @@ export declare function prettyFindings(findings: readonly Finding[], style: Styl
|
|
|
24
35
|
export declare function jsonDocument(command: string, version: string, body: Record<string, unknown>): string;
|
|
25
36
|
export declare function findingJson(f: Finding): Record<string, unknown>;
|
|
26
37
|
export declare function sarif(findings: readonly Finding[], version: string): string;
|
|
38
|
+
/**
|
|
39
|
+
* GitLab Code Quality: a JSON array of issues, which a merge request shows
|
|
40
|
+
* beside the lines they are on. The fingerprint is how GitLab tells a new
|
|
41
|
+
* issue from one it has seen, so it hashes the rule, the file and the message
|
|
42
|
+
* and not the line: a finding that moves down a page is the same finding. Two
|
|
43
|
+
* findings with the same three - a section duplicated twice - are told apart
|
|
44
|
+
* by their order.
|
|
45
|
+
*/
|
|
46
|
+
export declare function gitlabCodeQuality(findings: readonly Finding[]): string;
|
|
27
47
|
export declare function githubCommands(findings: readonly Finding[]): string;
|
|
28
48
|
export declare function briefJson(brief: Brief, extra?: Record<string, unknown>): Record<string, unknown>;
|
|
49
|
+
/**
|
|
50
|
+
* The sections the configuration asks for, each with what it must answer:
|
|
51
|
+
* those every live brief carries, with `type` null, then those each type adds.
|
|
52
|
+
* A tool that helps write a brief asks for these rather than for names it
|
|
53
|
+
* knows in advance.
|
|
54
|
+
*/
|
|
55
|
+
export declare function sectionsJson(config: Config): Record<string, unknown>[];
|
|
29
56
|
export interface ListRow {
|
|
30
57
|
readonly brief: Brief;
|
|
31
58
|
readonly ready: boolean;
|
|
@@ -33,6 +60,16 @@ export interface ListRow {
|
|
|
33
60
|
}
|
|
34
61
|
export declare function prettyList(rows: readonly ListRow[], style: Style): string;
|
|
35
62
|
export declare function prettyMatrix(report: CollisionReport, style: Style): string;
|
|
63
|
+
/** The matrix as JSON: briefs by id, and a collision per pair of briefs. */
|
|
64
|
+
export declare function matrixJson(report: CollisionReport): Record<string, unknown>;
|
|
65
|
+
/**
|
|
66
|
+
* The schedule for a person: each wave with its briefs, and under a brief whose
|
|
67
|
+
* wave would change, why it goes where it goes. `written` is `null` when
|
|
68
|
+
* nothing was asked to be written.
|
|
69
|
+
*/
|
|
70
|
+
export declare function prettySchedule(s: Schedule, written: readonly string[] | null, style: Style): string;
|
|
71
|
+
/** The schedule as JSON: a row per placed brief with its declared and proposed wave and why. */
|
|
72
|
+
export declare function scheduleJson(s: Schedule): Record<string, unknown>;
|
|
36
73
|
export declare function prettyPlan(plan: Plan, dryRun: boolean, style: Style): string;
|
|
37
74
|
export declare function planJson(plan: Plan): Record<string, unknown>;
|
|
38
75
|
export {};
|
package/dist/report.js
CHANGED
|
@@ -5,12 +5,24 @@
|
|
|
5
5
|
* `json` is a document with a version, for orchestrators. `sarif` is SARIF
|
|
6
6
|
* 2.1.0, for code-scanning upload. `github` is workflow commands, which put a
|
|
7
7
|
* finding on the line of the pull request with no upload and no permission.
|
|
8
|
+
* `gitlab` is a Code Quality report, the artifact a GitLab merge request reads,
|
|
9
|
+
* so the family is not GitHub's alone.
|
|
8
10
|
*/
|
|
11
|
+
import { createHash } from 'node:crypto';
|
|
9
12
|
import { summarise } from './lint.js';
|
|
10
|
-
import { COLLISION_RULES, RULES } from './rules.js';
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
export const
|
|
13
|
+
import { ARCHIVE_RULES, COLLISION_RULES, RULES } from './rules.js';
|
|
14
|
+
import { breachReasons, holds, moves, reasons } from './schedule.js';
|
|
15
|
+
import { inWords } from './text.js';
|
|
16
|
+
export const FORMATS = ['pretty', 'json', 'sarif', 'github', 'gitlab'];
|
|
17
|
+
/**
|
|
18
|
+
* The version of the JSON documents this tool prints, every command's alike.
|
|
19
|
+
* Bumped when a field changes meaning. 2: a collision in `matrix` is a pair of
|
|
20
|
+
* briefs, with every pair of patterns that meets and a witness that is always
|
|
21
|
+
* a file; a shared-directory entry lists its directories; and deferred briefs,
|
|
22
|
+
* and the briefs waiting on them, leave `waves[].briefs` for `deferred` and
|
|
23
|
+
* `waiting`.
|
|
24
|
+
*/
|
|
25
|
+
export const JSON_SCHEMA_VERSION = 2;
|
|
14
26
|
const CODES = {
|
|
15
27
|
red: [31, 39],
|
|
16
28
|
yellow: [33, 39],
|
|
@@ -58,11 +70,15 @@ export function findingJson(f) {
|
|
|
58
70
|
out['brief'] = f.brief;
|
|
59
71
|
if (f.hint !== undefined)
|
|
60
72
|
out['hint'] = f.hint;
|
|
73
|
+
if (f.path !== undefined)
|
|
74
|
+
out['path'] = f.path;
|
|
75
|
+
if (f.paths !== undefined)
|
|
76
|
+
out['paths'] = f.paths;
|
|
61
77
|
return out;
|
|
62
78
|
}
|
|
63
79
|
const SARIF_LEVEL = { error: 'error', warning: 'warning', note: 'note' };
|
|
64
80
|
export function sarif(findings, version) {
|
|
65
|
-
const described = new Map([...RULES, ...COLLISION_RULES].map((r) => [r.id, r]));
|
|
81
|
+
const described = new Map([...RULES, ...COLLISION_RULES, ...ARCHIVE_RULES].map((r) => [r.id, r]));
|
|
66
82
|
const ids = [...new Set(findings.map((f) => f.rule))].sort();
|
|
67
83
|
const document = {
|
|
68
84
|
$schema: 'https://json.schemastore.org/sarif-2.1.0.json',
|
|
@@ -104,6 +120,36 @@ export function sarif(findings, version) {
|
|
|
104
120
|
};
|
|
105
121
|
return `${JSON.stringify(document, null, 2)}\n`;
|
|
106
122
|
}
|
|
123
|
+
/**
|
|
124
|
+
* GitLab's Code Quality severities. An error fails the run but is not a
|
|
125
|
+
* security hole or a crash, which is what `critical` and `blocker` say in
|
|
126
|
+
* GitLab's own reports, so the scale tops out at `major`.
|
|
127
|
+
*/
|
|
128
|
+
const GITLAB_SEVERITY = { error: 'major', warning: 'minor', note: 'info' };
|
|
129
|
+
/**
|
|
130
|
+
* GitLab Code Quality: a JSON array of issues, which a merge request shows
|
|
131
|
+
* beside the lines they are on. The fingerprint is how GitLab tells a new
|
|
132
|
+
* issue from one it has seen, so it hashes the rule, the file and the message
|
|
133
|
+
* and not the line: a finding that moves down a page is the same finding. Two
|
|
134
|
+
* findings with the same three - a section duplicated twice - are told apart
|
|
135
|
+
* by their order.
|
|
136
|
+
*/
|
|
137
|
+
export function gitlabCodeQuality(findings) {
|
|
138
|
+
const seen = new Map();
|
|
139
|
+
const issues = findings.map((f) => {
|
|
140
|
+
const key = `${f.rule}\u0000${f.file}\u0000${f.message}`;
|
|
141
|
+
const repeat = seen.get(key) ?? 0;
|
|
142
|
+
seen.set(key, repeat + 1);
|
|
143
|
+
return {
|
|
144
|
+
description: f.hint === undefined ? f.message : `${f.message}. ${f.hint}`,
|
|
145
|
+
check_name: f.rule,
|
|
146
|
+
fingerprint: createHash('sha256').update(repeat === 0 ? key : `${key}\u0000${repeat}`).digest('hex'),
|
|
147
|
+
severity: GITLAB_SEVERITY[f.severity],
|
|
148
|
+
location: { path: f.file, lines: { begin: f.line } },
|
|
149
|
+
};
|
|
150
|
+
});
|
|
151
|
+
return `${JSON.stringify(issues, null, 2)}\n`;
|
|
152
|
+
}
|
|
107
153
|
function escapeData(text) {
|
|
108
154
|
return text.replace(/%/g, '%25').replace(/\r/g, '%0D').replace(/\n/g, '%0A');
|
|
109
155
|
}
|
|
@@ -132,10 +178,32 @@ export function briefJson(brief, extra = {}) {
|
|
|
132
178
|
dependsOn: brief.dependsOn,
|
|
133
179
|
affectedFiles: brief.affectedFiles,
|
|
134
180
|
protectedFiles: brief.protectedFiles,
|
|
181
|
+
trigger: brief.trigger,
|
|
135
182
|
tasks: { total: brief.tasks.length, checked: brief.tasks.filter((t) => t.checked).length },
|
|
136
183
|
...extra,
|
|
137
184
|
};
|
|
138
185
|
}
|
|
186
|
+
/**
|
|
187
|
+
* The sections the configuration asks for, each with what it must answer:
|
|
188
|
+
* those every live brief carries, with `type` null, then those each type adds.
|
|
189
|
+
* A tool that helps write a brief asks for these rather than for names it
|
|
190
|
+
* knows in advance.
|
|
191
|
+
*/
|
|
192
|
+
export function sectionsJson(config) {
|
|
193
|
+
const describe = (rule, type) => ({
|
|
194
|
+
name: rule.name,
|
|
195
|
+
type,
|
|
196
|
+
aliases: rule.aliases,
|
|
197
|
+
optional: rule.optional,
|
|
198
|
+
checklist: rule.checklist,
|
|
199
|
+
mustContain: rule.mustContain,
|
|
200
|
+
hint: rule.hint ?? null,
|
|
201
|
+
});
|
|
202
|
+
return [
|
|
203
|
+
...config.sections.map((rule) => describe(rule, null)),
|
|
204
|
+
...Object.entries(config.types).flatMap(([type, rules]) => rules.map((rule) => describe(rule, type))),
|
|
205
|
+
];
|
|
206
|
+
}
|
|
139
207
|
/** Columns padded to their widest cell; every row has the header's length. */
|
|
140
208
|
function table(header, rows) {
|
|
141
209
|
const all = [header, ...rows];
|
|
@@ -166,22 +234,40 @@ export function prettyMatrix(report, style) {
|
|
|
166
234
|
out.push(paint(style, 'bold', `${title} \u00b7 ${plural(wave.briefs.length, 'brief')}`));
|
|
167
235
|
const names = wave.briefs.map(label);
|
|
168
236
|
const width = Math.max(3, ...names.map((n) => n.length));
|
|
169
|
-
const
|
|
170
|
-
const
|
|
237
|
+
const pairs = (list) => new Set(list.flatMap((p) => [`${label(p.a)}\u0000${label(p.b)}`, `${label(p.b)}\u0000${label(p.a)}`]));
|
|
238
|
+
const hits = pairs(wave.collisions);
|
|
239
|
+
const unknown = pairs(wave.undecided);
|
|
240
|
+
const near = pairs(wave.shared);
|
|
171
241
|
out.push(` ${''.padEnd(width)} ${names.map((n) => n.padStart(width)).join(' ')}`);
|
|
172
242
|
for (const row of names) {
|
|
173
243
|
const cells = names.map((col) => {
|
|
174
244
|
const key = `${row}\u0000${col}`;
|
|
175
|
-
const mark = row === col
|
|
245
|
+
const mark = row === col
|
|
246
|
+
? '\u00b7'
|
|
247
|
+
: hits.has(key)
|
|
248
|
+
? paint(style, 'red', 'X')
|
|
249
|
+
: unknown.has(key)
|
|
250
|
+
? paint(style, 'yellow', '?')
|
|
251
|
+
: near.has(key)
|
|
252
|
+
? paint(style, 'yellow', '~')
|
|
253
|
+
: '\u00b7';
|
|
176
254
|
return `${' '.repeat(width - 1)}${mark}`;
|
|
177
255
|
});
|
|
178
256
|
out.push(` ${row.padEnd(width)} ${cells.join(' ')}`);
|
|
179
257
|
}
|
|
258
|
+
// One mark per pair of briefs; each further pair of patterns on a line beneath it.
|
|
180
259
|
for (const c of wave.collisions) {
|
|
181
|
-
|
|
260
|
+
c.overlaps.forEach((o, i) => {
|
|
261
|
+
out.push(` ${i === 0 ? paint(style, 'red', 'X') : ' '} ${label(c.a)} "${o.patterns[0]}" and ${label(c.b)} "${o.patterns[1]}" both cover ${o.witness}`);
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
for (const u of wave.undecided) {
|
|
265
|
+
u.patterns.forEach(([x, y], i) => {
|
|
266
|
+
out.push(` ${i === 0 ? paint(style, 'yellow', '?') : ' '} ${label(u.a)} "${x}" and ${label(u.b)} "${y}": undecided within the search's budget`);
|
|
267
|
+
});
|
|
182
268
|
}
|
|
183
269
|
for (const s of wave.shared) {
|
|
184
|
-
out.push(` ${paint(style, 'yellow', '~')} ${label(s.a)} and ${label(s.b)} both write into ${s.
|
|
270
|
+
out.push(` ${paint(style, 'yellow', '~')} ${label(s.a)} and ${label(s.b)} both write into ${inWords(s.directories.map((d) => `${d}/`))}`);
|
|
185
271
|
}
|
|
186
272
|
for (const b of wave.unscoped) {
|
|
187
273
|
out.push(` ${paint(style, 'cyan', '?')} ${label(b)} declares no affectedFiles and cannot be checked`);
|
|
@@ -191,10 +277,140 @@ export function prettyMatrix(report, style) {
|
|
|
191
277
|
if (report.unscheduled.length > 0) {
|
|
192
278
|
out.push(paint(style, 'dim', `no wave: ${report.unscheduled.map(label).join(', ')}`));
|
|
193
279
|
}
|
|
194
|
-
|
|
280
|
+
for (const w of report.waiting) {
|
|
281
|
+
const why = w.waitsOn.status === 'deferred' ? 'which is deferred' : 'which waits on deferred work';
|
|
282
|
+
out.push(`${paint(style, 'dim', 'waits:')} ${label(w.brief)} on ${label(w.waitsOn)}, ${why}`);
|
|
283
|
+
}
|
|
284
|
+
if (report.deferred.length > 0) {
|
|
285
|
+
out.push(paint(style, 'dim', `deferred: ${report.deferred.map(label).join(', ')}`));
|
|
286
|
+
}
|
|
287
|
+
if (report.waves.length === 0 && report.unscheduled.length === 0 && report.deferred.length === 0)
|
|
195
288
|
out.push('no live briefs');
|
|
196
289
|
return out.join('\n').trimEnd();
|
|
197
290
|
}
|
|
291
|
+
/** The matrix as JSON: briefs by id, and a collision per pair of briefs. */
|
|
292
|
+
export function matrixJson(report) {
|
|
293
|
+
return {
|
|
294
|
+
waves: report.waves.map((w) => ({
|
|
295
|
+
wave: w.wave,
|
|
296
|
+
briefs: w.briefs.map((b) => b.id),
|
|
297
|
+
collisions: w.collisions.map((c) => ({
|
|
298
|
+
a: c.a.id,
|
|
299
|
+
b: c.b.id,
|
|
300
|
+
overlaps: c.overlaps.map((o) => ({ patterns: o.patterns, witness: o.witness })),
|
|
301
|
+
})),
|
|
302
|
+
undecided: w.undecided.map((u) => ({ a: u.a.id, b: u.b.id, patterns: u.patterns })),
|
|
303
|
+
sharedDirectories: w.shared.map((s) => ({ a: s.a.id, b: s.b.id, directories: s.directories })),
|
|
304
|
+
unscoped: w.unscoped.map((b) => b.id),
|
|
305
|
+
})),
|
|
306
|
+
unscheduled: report.unscheduled.map((b) => b.id),
|
|
307
|
+
deferred: report.deferred.map((b) => b.id),
|
|
308
|
+
waiting: report.waiting.map((w) => ({ id: w.brief.id, file: w.brief.file, waitsOn: w.waitsOn.id })),
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* The waves a schedule uses, in order. They appear in order too: a brief goes
|
|
313
|
+
* into a wave only when it is the first or the one before it is occupied.
|
|
314
|
+
*/
|
|
315
|
+
function wavesOf(s) {
|
|
316
|
+
return [...new Set(s.placements.map((p) => p.proposed))];
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* The schedule for a person: each wave with its briefs, and under a brief whose
|
|
320
|
+
* wave would change, why it goes where it goes. `written` is `null` when
|
|
321
|
+
* nothing was asked to be written.
|
|
322
|
+
*/
|
|
323
|
+
export function prettySchedule(s, written, style) {
|
|
324
|
+
const label = (b) => b.id ?? b.name;
|
|
325
|
+
const out = [];
|
|
326
|
+
const width = Math.max(3, ...s.placements.map((p) => label(p.brief).length));
|
|
327
|
+
const titleOf = (b) => b.title ?? b.name;
|
|
328
|
+
const titles = Math.max(0, ...s.placements.map((p) => titleOf(p.brief).length));
|
|
329
|
+
const waves = wavesOf(s);
|
|
330
|
+
for (const wave of waves) {
|
|
331
|
+
const here = s.placements.filter((p) => p.proposed === wave);
|
|
332
|
+
out.push(paint(style, 'bold', `wave ${wave} · ${plural(here.length, 'brief')}`));
|
|
333
|
+
for (const p of here) {
|
|
334
|
+
const title = titleOf(p.brief);
|
|
335
|
+
if (p.proposed === p.declared) {
|
|
336
|
+
out.push(` ${label(p.brief).padEnd(width)} ${title}`);
|
|
337
|
+
continue;
|
|
338
|
+
}
|
|
339
|
+
const from = p.declared === null ? 'no wave' : `wave ${p.declared}`;
|
|
340
|
+
out.push(` ${label(p.brief).padEnd(width)} ${title.padEnd(titles)} ${paint(style, 'yellow', `moves from ${from}`)}`);
|
|
341
|
+
// Why the declared wave holds or does not comes first: it decides whether the move is asked for.
|
|
342
|
+
const verdict = p.declared === null ? [] : holds(p) ? [`wave ${p.declared} also holds`] : [`wave ${p.declared} does not hold: ${breachReasons(p).join('; ')}`];
|
|
343
|
+
for (const reason of [...verdict, ...reasons(p)])
|
|
344
|
+
out.push(` ${' '.repeat(width)} ${paint(style, 'dim', reason)}`);
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
if (waves.length > 0)
|
|
348
|
+
out.push('');
|
|
349
|
+
for (const cycle of s.cycles)
|
|
350
|
+
out.push(`${paint(style, 'red', 'cycle:')} ${cycle.map(label).join(' -> ')}`);
|
|
351
|
+
for (const u of s.unplaced) {
|
|
352
|
+
const why = u.because === 'deferred' ? 'which is deferred' : u.because === 'cycle' ? 'which is in a cycle' : 'which is not placed';
|
|
353
|
+
out.push(`${paint(style, 'dim', 'waits:')} ${label(u.brief)} on ${label(u.waitsOn)}, ${why}`);
|
|
354
|
+
}
|
|
355
|
+
if (s.deferred.length > 0)
|
|
356
|
+
out.push(paint(style, 'dim', `deferred: ${s.deferred.map(label).join(', ')}`));
|
|
357
|
+
const moving = moves(s).length;
|
|
358
|
+
if (written !== null && written.length > 0) {
|
|
359
|
+
out.push(`wrote the wave of ${plural(written.length, 'brief')}: ${written.join(', ')}`);
|
|
360
|
+
}
|
|
361
|
+
else if (written !== null && moving > 0) {
|
|
362
|
+
out.push(paint(style, 'red', s.cycles.length > 0 ? 'nothing was written: the dependencies form a cycle' : 'nothing was written: a front matter cannot be edited'));
|
|
363
|
+
}
|
|
364
|
+
else if (moving > 0 && moves(s).every(holds)) {
|
|
365
|
+
out.push(`${plural(moving, 'brief')} could move, and the declared waves hold; "spec-brief schedule --write" writes the computed ones`);
|
|
366
|
+
}
|
|
367
|
+
else if (moving > 0) {
|
|
368
|
+
out.push(`${plural(moving, 'brief')} would move; "spec-brief schedule --write" writes the waves`);
|
|
369
|
+
}
|
|
370
|
+
else if (s.placements.length > 0) {
|
|
371
|
+
out.push('the declared waves hold');
|
|
372
|
+
}
|
|
373
|
+
else if (s.cycles.length === 0 && s.deferred.length === 0) {
|
|
374
|
+
// A brief is unplaced only behind a cycle or a deferral, so this is a corpus with no live brief.
|
|
375
|
+
out.push('no live briefs');
|
|
376
|
+
}
|
|
377
|
+
return out.join('\n');
|
|
378
|
+
}
|
|
379
|
+
/** The schedule as JSON: a row per placed brief with its declared and proposed wave and why. */
|
|
380
|
+
export function scheduleJson(s) {
|
|
381
|
+
const breach = (b) => b.reason === 'collision'
|
|
382
|
+
? { reason: b.reason, brief: b.brief.id, overlaps: b.overlaps.map((o) => ({ patterns: o.patterns, witness: o.witness })) }
|
|
383
|
+
: { reason: b.reason, brief: b.brief.id, wave: b.wave };
|
|
384
|
+
const passed = (p) => {
|
|
385
|
+
const base = { wave: p.wave, reason: p.reason, brief: p.brief.id };
|
|
386
|
+
if (p.reason === 'collision')
|
|
387
|
+
return { ...base, overlaps: p.overlaps.map((o) => ({ patterns: o.patterns, witness: o.witness })) };
|
|
388
|
+
if (p.reason === 'undecided')
|
|
389
|
+
return { ...base, patterns: p.patterns };
|
|
390
|
+
return base;
|
|
391
|
+
};
|
|
392
|
+
const waves = wavesOf(s);
|
|
393
|
+
return {
|
|
394
|
+
first: s.first,
|
|
395
|
+
waves: waves.map((wave) => ({ wave, briefs: s.placements.filter((p) => p.proposed === wave).map((p) => p.brief.id) })),
|
|
396
|
+
briefs: s.placements.map((p) => ({
|
|
397
|
+
id: p.brief.id,
|
|
398
|
+
file: p.brief.file,
|
|
399
|
+
declared: p.declared,
|
|
400
|
+
proposed: p.proposed,
|
|
401
|
+
moves: p.proposed !== p.declared,
|
|
402
|
+
holds: holds(p),
|
|
403
|
+
breaches: p.breaches.map(breach),
|
|
404
|
+
after: p.after === null ? null : { brief: p.after.brief.id, wave: p.after.wave },
|
|
405
|
+
passed: p.passed.map(passed),
|
|
406
|
+
unscoped: p.unscoped,
|
|
407
|
+
reasons: reasons(p),
|
|
408
|
+
})),
|
|
409
|
+
unplaced: s.unplaced.map((u) => ({ id: u.brief.id, file: u.brief.file, waitsOn: u.waitsOn.id, because: u.because })),
|
|
410
|
+
cycles: s.cycles.map((cycle) => cycle.map((b) => b.id)),
|
|
411
|
+
deferred: s.deferred.map((b) => b.id),
|
|
412
|
+
};
|
|
413
|
+
}
|
|
198
414
|
export function prettyPlan(plan, dryRun, style) {
|
|
199
415
|
const out = [];
|
|
200
416
|
const verb = plan.action === 'archive' ? 'archive' : 'unarchive';
|
package/dist/report.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Rendering: findings, lists, the collision matrix and plans, for a person at\n * a terminal or for the machine reading the job.\n *\n * `json` is a document with a version, for orchestrators. `sarif` is SARIF\n * 2.1.0, for code-scanning upload. `github` is workflow commands, which put a\n * finding on the line of the pull request with no upload and no permission.\n */\n\nimport type { Plan } from './archive.js';\nimport type { Brief } from './brief.js';\nimport type { CollisionReport } from './collisions.js';\nimport { summarise } from './lint.js';\nimport { COLLISION_RULES, RULES } from './rules.js';\nimport type { Finding, Severity } from './types.js';\n\nexport type Format = 'pretty' | 'json' | 'sarif' | 'github';\n\nexport const FORMATS: readonly Format[] = ['pretty', 'json', 'sarif', 'github'];\n\n/** The version of the JSON documents this tool prints. Bumped when a field changes meaning. */\nexport const JSON_SCHEMA_VERSION = 1;\n\nexport interface Style {\n readonly color: boolean;\n}\n\nconst CODES: Readonly<Record<string, readonly [number, number]>> = {\n red: [31, 39],\n yellow: [33, 39],\n cyan: [36, 39],\n green: [32, 39],\n dim: [2, 22],\n bold: [1, 22],\n};\n\nexport function paint(style: Style, color: keyof typeof CODES, text: string): string {\n const code = CODES[color];\n return style.color && code !== undefined ? `\\u001b[${code[0]}m${text}\\u001b[${code[1]}m` : text;\n}\n\nconst SEVERITY_COLOR: Readonly<Record<Severity, keyof typeof CODES>> = { error: 'red', warning: 'yellow', note: 'cyan' };\n\nfunction plural(count: number, word: string): string {\n return `${count} ${word}${count === 1 ? '' : 's'}`;\n}\n\nexport function summaryLine(findings: readonly Finding[]): string {\n const s = summarise(findings);\n return `${plural(s.errors, 'error')}, ${plural(s.warnings, 'warning')}, ${plural(s.notes, 'note')}`;\n}\n\nexport function prettyFindings(findings: readonly Finding[], style: Style): string {\n const out: string[] = [];\n let file: string | undefined;\n const width = Math.max(1, ...findings.map((f) => String(f.line).length));\n for (const f of findings) {\n if (f.file !== file) {\n if (file !== undefined) out.push('');\n out.push(paint(style, 'bold', f.file));\n file = f.file;\n }\n const severity = paint(style, SEVERITY_COLOR[f.severity], f.severity.padEnd(7));\n out.push(` ${String(f.line).padStart(width)} ${severity} ${f.message} ${paint(style, 'dim', f.rule)}`);\n if (f.hint !== undefined) out.push(` ${' '.repeat(width)} ${paint(style, 'dim', f.hint)}`);\n }\n return out.join('\\n');\n}\n\nexport function jsonDocument(command: string, version: string, body: Record<string, unknown>): string {\n return `${JSON.stringify({ tool: 'spec-brief', version, schemaVersion: JSON_SCHEMA_VERSION, command, ...body }, null, 2)}\\n`;\n}\n\nexport function findingJson(f: Finding): Record<string, unknown> {\n const out: Record<string, unknown> = { rule: f.rule, severity: f.severity, file: f.file, line: f.line, message: f.message };\n if (f.brief !== undefined) out['brief'] = f.brief;\n if (f.hint !== undefined) out['hint'] = f.hint;\n return out;\n}\n\nconst SARIF_LEVEL: Readonly<Record<Severity, string>> = { error: 'error', warning: 'warning', note: 'note' };\n\nexport function sarif(findings: readonly Finding[], version: string): string {\n const described = new Map([...RULES, ...COLLISION_RULES].map((r) => [r.id, r]));\n const ids = [...new Set(findings.map((f) => f.rule))].sort();\n const document = {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: 'spec-brief',\n version,\n informationUri: 'https://github.com/DescentVTT/spec-brief',\n rules: ids.map((id) => {\n const rule = described.get(id);\n return {\n id,\n shortDescription: { text: rule?.description ?? id },\n ...(rule !== undefined && rule.severity !== 'off'\n ? { defaultConfiguration: { level: SARIF_LEVEL[rule.severity] } }\n : {}),\n };\n }),\n },\n },\n results: findings.map((f) => ({\n ruleId: f.rule,\n level: SARIF_LEVEL[f.severity],\n message: { text: f.hint === undefined ? f.message : `${f.message}. ${f.hint}` },\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri: f.file, uriBaseId: '%SRCROOT%' },\n region: { startLine: f.line },\n },\n },\n ],\n })),\n },\n ],\n };\n return `${JSON.stringify(document, null, 2)}\\n`;\n}\n\nfunction escapeData(text: string): string {\n return text.replace(/%/g, '%25').replace(/\\r/g, '%0D').replace(/\\n/g, '%0A');\n}\n\nfunction escapeProperty(text: string): string {\n return escapeData(text).replace(/:/g, '%3A').replace(/,/g, '%2C');\n}\n\nconst GITHUB_COMMAND: Readonly<Record<Severity, string>> = { error: 'error', warning: 'warning', note: 'notice' };\n\nexport function githubCommands(findings: readonly Finding[]): string {\n return findings\n .map((f) => {\n const message = f.hint === undefined ? f.message : `${f.message}. ${f.hint}`;\n const properties = `file=${escapeProperty(f.file)},line=${f.line},title=${escapeProperty(`spec-brief ${f.rule}`)}`;\n return `::${GITHUB_COMMAND[f.severity]} ${properties}::${escapeData(message)}\\n`;\n })\n .join('');\n}\n\nexport function briefJson(brief: Brief, extra: Record<string, unknown> = {}): Record<string, unknown> {\n return {\n id: brief.id,\n file: brief.file,\n title: brief.title,\n phase: brief.phase,\n status: brief.status,\n type: brief.type,\n wave: brief.wave,\n dependsOn: brief.dependsOn,\n affectedFiles: brief.affectedFiles,\n protectedFiles: brief.protectedFiles,\n tasks: { total: brief.tasks.length, checked: brief.tasks.filter((t) => t.checked).length },\n ...extra,\n };\n}\n\n/** Columns padded to their widest cell; every row has the header's length. */\nfunction table(header: readonly string[], rows: readonly (readonly string[])[]): string[] {\n const all = [header, ...rows];\n const widths = header.map((_, c) => Math.max(...all.map((r) => (r[c] as string).length)));\n return all.map((r) =>\n r\n .map((cell, c) => (c === r.length - 1 ? cell : cell.padEnd(widths[c] as number)))\n .join(' ')\n .trimEnd(),\n );\n}\n\nexport interface ListRow {\n readonly brief: Brief;\n readonly ready: boolean;\n readonly waitingOn: readonly string[];\n}\n\nexport function prettyList(rows: readonly ListRow[], style: Style): string {\n if (rows.length === 0) return 'no briefs';\n const lines = table(\n ['ID', 'STATUS', 'WAVE', 'TASKS', 'READY', 'TITLE'],\n rows.map(({ brief, ready, waitingOn }) => [\n brief.id ?? '?',\n brief.status ?? brief.statusWord ?? '?',\n brief.wave === null ? '-' : String(brief.wave),\n `${brief.tasks.filter((t) => t.checked).length}/${brief.tasks.length}`,\n brief.phase === 'archived' ? '-' : ready ? 'yes' : waitingOn.length > 0 ? `after ${waitingOn.join(', ')}` : 'no',\n brief.title ?? brief.name,\n ]),\n );\n return [paint(style, 'dim', lines[0] as string), ...lines.slice(1)].join('\\n');\n}\n\nexport function prettyMatrix(report: CollisionReport, style: Style): string {\n const out: string[] = [];\n const label = (b: Brief): string => b.id ?? b.name;\n for (const wave of report.waves) {\n const title = wave.wave === null ? 'all live briefs' : `wave ${wave.wave}`;\n out.push(paint(style, 'bold', `${title} \\u00b7 ${plural(wave.briefs.length, 'brief')}`));\n const names = wave.briefs.map(label);\n const width = Math.max(3, ...names.map((n) => n.length));\n const hits = new Set(wave.collisions.flatMap((c) => [`${label(c.a)}\\u0000${label(c.b)}`, `${label(c.b)}\\u0000${label(c.a)}`]));\n const near = new Set(wave.shared.flatMap((s) => [`${label(s.a)}\\u0000${label(s.b)}`, `${label(s.b)}\\u0000${label(s.a)}`]));\n out.push(` ${''.padEnd(width)} ${names.map((n) => n.padStart(width)).join(' ')}`);\n for (const row of names) {\n const cells = names.map((col) => {\n const key = `${row}\\u0000${col}`;\n const mark = row === col ? '\\u00b7' : hits.has(key) ? paint(style, 'red', 'X') : near.has(key) ? paint(style, 'yellow', '~') : '\\u00b7';\n return `${' '.repeat(width - 1)}${mark}`;\n });\n out.push(` ${row.padEnd(width)} ${cells.join(' ')}`);\n }\n for (const c of wave.collisions) {\n out.push(` ${paint(style, 'red', 'X')} ${label(c.a)} \"${c.patterns[0]}\" and ${label(c.b)} \"${c.patterns[1]}\" both cover ${c.witness}`);\n }\n for (const s of wave.shared) {\n out.push(` ${paint(style, 'yellow', '~')} ${label(s.a)} and ${label(s.b)} both write into ${s.directory}/`);\n }\n for (const b of wave.unscoped) {\n out.push(` ${paint(style, 'cyan', '?')} ${label(b)} declares no affectedFiles and cannot be checked`);\n }\n out.push('');\n }\n if (report.unscheduled.length > 0) {\n out.push(paint(style, 'dim', `no wave: ${report.unscheduled.map(label).join(', ')}`));\n }\n if (report.waves.length === 0 && report.unscheduled.length === 0) out.push('no live briefs');\n return out.join('\\n').trimEnd();\n}\n\nexport function prettyPlan(plan: Plan, dryRun: boolean, style: Style): string {\n const out: string[] = [];\n const verb = plan.action === 'archive' ? 'archive' : 'unarchive';\n if (plan.done) return `${plan.brief.file} is already ${plan.action === 'archive' ? 'archived' : 'live'}; nothing to do`;\n if (plan.blocking.length > 0) {\n out.push(paint(style, 'red', `cannot ${verb} ${plan.brief.file}:`), prettyFindings(plan.blocking, style));\n if (plan.warnings.length > 0) out.push('', prettyFindings(plan.warnings, style));\n return out.join('\\n');\n }\n out.push(`${dryRun ? 'would move' : 'moved'} ${plan.from} -> ${plan.to}`);\n if (plan.linksRewritten > 0) out.push(` ${plural(plan.linksRewritten, 'relative link')} rewritten`);\n for (const file of plan.inboundRewritten) out.push(` ${file}: links to it rewritten`);\n for (const f of plan.inboundFrozen) out.push(` ${f.file}:${f.line}: links to the old path, and is frozen, so it was left as it is`);\n if (plan.changes.length > 0) out.push(` the round changed ${plural(plan.changes.length, 'file')}`);\n if (plan.warnings.length > 0) out.push('', prettyFindings(plan.warnings, style));\n if (dryRun && plan.banner.length > 0) out.push('', paint(style, 'dim', 'banner:'), ...plan.banner.map((l) => ` ${l}`));\n if (!dryRun) out.push('', paint(style, 'dim', 'nothing was committed; review the change and commit it with the round'));\n return out.join('\\n');\n}\n\nexport function planJson(plan: Plan): Record<string, unknown> {\n return {\n action: plan.action,\n brief: plan.brief.id,\n from: plan.from,\n to: plan.to,\n done: plan.done,\n refused: plan.blocking.length > 0,\n blocking: plan.blocking.map(findingJson),\n warnings: plan.warnings.map(findingJson),\n linksRewritten: plan.linksRewritten,\n inboundRewritten: plan.inboundRewritten,\n inboundFrozen: plan.inboundFrozen,\n operations: plan.ops.map((op) => ({ kind: op.kind, path: op.path })),\n banner: plan.banner,\n changes: plan.changes,\n };\n}\n"]}
|
|
1
|
+
{"version":3,"file":"report.js","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Rendering: findings, lists, the collision matrix and plans, for a person at\n * a terminal or for the machine reading the job.\n *\n * `json` is a document with a version, for orchestrators. `sarif` is SARIF\n * 2.1.0, for code-scanning upload. `github` is workflow commands, which put a\n * finding on the line of the pull request with no upload and no permission.\n * `gitlab` is a Code Quality report, the artifact a GitLab merge request reads,\n * so the family is not GitHub's alone.\n */\n\nimport { createHash } from 'node:crypto';\n\nimport type { Plan } from './archive.js';\nimport type { Brief } from './brief.js';\nimport type { Config, SectionRule } from './config.js';\nimport type { CollisionReport } from './collisions.js';\nimport { summarise } from './lint.js';\nimport { ARCHIVE_RULES, COLLISION_RULES, RULES } from './rules.js';\nimport { type Breach, breachReasons, holds, moves, type Passed, reasons, type Schedule } from './schedule.js';\nimport { inWords } from './text.js';\nimport type { Finding, Severity } from './types.js';\n\nexport type Format = 'pretty' | 'json' | 'sarif' | 'github' | 'gitlab';\n\nexport const FORMATS: readonly Format[] = ['pretty', 'json', 'sarif', 'github', 'gitlab'];\n\n/**\n * The version of the JSON documents this tool prints, every command's alike.\n * Bumped when a field changes meaning. 2: a collision in `matrix` is a pair of\n * briefs, with every pair of patterns that meets and a witness that is always\n * a file; a shared-directory entry lists its directories; and deferred briefs,\n * and the briefs waiting on them, leave `waves[].briefs` for `deferred` and\n * `waiting`.\n */\nexport const JSON_SCHEMA_VERSION = 2;\n\nexport interface Style {\n readonly color: boolean;\n}\n\nconst CODES: Readonly<Record<string, readonly [number, number]>> = {\n red: [31, 39],\n yellow: [33, 39],\n cyan: [36, 39],\n green: [32, 39],\n dim: [2, 22],\n bold: [1, 22],\n};\n\nexport function paint(style: Style, color: keyof typeof CODES, text: string): string {\n const code = CODES[color];\n return style.color && code !== undefined ? `\\u001b[${code[0]}m${text}\\u001b[${code[1]}m` : text;\n}\n\nconst SEVERITY_COLOR: Readonly<Record<Severity, keyof typeof CODES>> = { error: 'red', warning: 'yellow', note: 'cyan' };\n\nfunction plural(count: number, word: string): string {\n return `${count} ${word}${count === 1 ? '' : 's'}`;\n}\n\nexport function summaryLine(findings: readonly Finding[]): string {\n const s = summarise(findings);\n return `${plural(s.errors, 'error')}, ${plural(s.warnings, 'warning')}, ${plural(s.notes, 'note')}`;\n}\n\nexport function prettyFindings(findings: readonly Finding[], style: Style): string {\n const out: string[] = [];\n let file: string | undefined;\n const width = Math.max(1, ...findings.map((f) => String(f.line).length));\n for (const f of findings) {\n if (f.file !== file) {\n if (file !== undefined) out.push('');\n out.push(paint(style, 'bold', f.file));\n file = f.file;\n }\n const severity = paint(style, SEVERITY_COLOR[f.severity], f.severity.padEnd(7));\n out.push(` ${String(f.line).padStart(width)} ${severity} ${f.message} ${paint(style, 'dim', f.rule)}`);\n if (f.hint !== undefined) out.push(` ${' '.repeat(width)} ${paint(style, 'dim', f.hint)}`);\n }\n return out.join('\\n');\n}\n\nexport function jsonDocument(command: string, version: string, body: Record<string, unknown>): string {\n return `${JSON.stringify({ tool: 'spec-brief', version, schemaVersion: JSON_SCHEMA_VERSION, command, ...body }, null, 2)}\\n`;\n}\n\nexport function findingJson(f: Finding): Record<string, unknown> {\n const out: Record<string, unknown> = { rule: f.rule, severity: f.severity, file: f.file, line: f.line, message: f.message };\n if (f.brief !== undefined) out['brief'] = f.brief;\n if (f.hint !== undefined) out['hint'] = f.hint;\n if (f.path !== undefined) out['path'] = f.path;\n if (f.paths !== undefined) out['paths'] = f.paths;\n return out;\n}\n\nconst SARIF_LEVEL: Readonly<Record<Severity, string>> = { error: 'error', warning: 'warning', note: 'note' };\n\nexport function sarif(findings: readonly Finding[], version: string): string {\n const described = new Map([...RULES, ...COLLISION_RULES, ...ARCHIVE_RULES].map((r) => [r.id, r]));\n const ids = [...new Set(findings.map((f) => f.rule))].sort();\n const document = {\n $schema: 'https://json.schemastore.org/sarif-2.1.0.json',\n version: '2.1.0',\n runs: [\n {\n tool: {\n driver: {\n name: 'spec-brief',\n version,\n informationUri: 'https://github.com/DescentVTT/spec-brief',\n rules: ids.map((id) => {\n const rule = described.get(id);\n return {\n id,\n shortDescription: { text: rule?.description ?? id },\n ...(rule !== undefined && rule.severity !== 'off'\n ? { defaultConfiguration: { level: SARIF_LEVEL[rule.severity] } }\n : {}),\n };\n }),\n },\n },\n results: findings.map((f) => ({\n ruleId: f.rule,\n level: SARIF_LEVEL[f.severity],\n message: { text: f.hint === undefined ? f.message : `${f.message}. ${f.hint}` },\n locations: [\n {\n physicalLocation: {\n artifactLocation: { uri: f.file, uriBaseId: '%SRCROOT%' },\n region: { startLine: f.line },\n },\n },\n ],\n })),\n },\n ],\n };\n return `${JSON.stringify(document, null, 2)}\\n`;\n}\n\n/**\n * GitLab's Code Quality severities. An error fails the run but is not a\n * security hole or a crash, which is what `critical` and `blocker` say in\n * GitLab's own reports, so the scale tops out at `major`.\n */\nconst GITLAB_SEVERITY: Readonly<Record<Severity, string>> = { error: 'major', warning: 'minor', note: 'info' };\n\n/**\n * GitLab Code Quality: a JSON array of issues, which a merge request shows\n * beside the lines they are on. The fingerprint is how GitLab tells a new\n * issue from one it has seen, so it hashes the rule, the file and the message\n * and not the line: a finding that moves down a page is the same finding. Two\n * findings with the same three - a section duplicated twice - are told apart\n * by their order.\n */\nexport function gitlabCodeQuality(findings: readonly Finding[]): string {\n const seen = new Map<string, number>();\n const issues = findings.map((f) => {\n const key = `${f.rule}\\u0000${f.file}\\u0000${f.message}`;\n const repeat = seen.get(key) ?? 0;\n seen.set(key, repeat + 1);\n return {\n description: f.hint === undefined ? f.message : `${f.message}. ${f.hint}`,\n check_name: f.rule,\n fingerprint: createHash('sha256').update(repeat === 0 ? key : `${key}\\u0000${repeat}`).digest('hex'),\n severity: GITLAB_SEVERITY[f.severity],\n location: { path: f.file, lines: { begin: f.line } },\n };\n });\n return `${JSON.stringify(issues, null, 2)}\\n`;\n}\n\nfunction escapeData(text: string): string {\n return text.replace(/%/g, '%25').replace(/\\r/g, '%0D').replace(/\\n/g, '%0A');\n}\n\nfunction escapeProperty(text: string): string {\n return escapeData(text).replace(/:/g, '%3A').replace(/,/g, '%2C');\n}\n\nconst GITHUB_COMMAND: Readonly<Record<Severity, string>> = { error: 'error', warning: 'warning', note: 'notice' };\n\nexport function githubCommands(findings: readonly Finding[]): string {\n return findings\n .map((f) => {\n const message = f.hint === undefined ? f.message : `${f.message}. ${f.hint}`;\n const properties = `file=${escapeProperty(f.file)},line=${f.line},title=${escapeProperty(`spec-brief ${f.rule}`)}`;\n return `::${GITHUB_COMMAND[f.severity]} ${properties}::${escapeData(message)}\\n`;\n })\n .join('');\n}\n\nexport function briefJson(brief: Brief, extra: Record<string, unknown> = {}): Record<string, unknown> {\n return {\n id: brief.id,\n file: brief.file,\n title: brief.title,\n phase: brief.phase,\n status: brief.status,\n type: brief.type,\n wave: brief.wave,\n dependsOn: brief.dependsOn,\n affectedFiles: brief.affectedFiles,\n protectedFiles: brief.protectedFiles,\n trigger: brief.trigger,\n tasks: { total: brief.tasks.length, checked: brief.tasks.filter((t) => t.checked).length },\n ...extra,\n };\n}\n\n/**\n * The sections the configuration asks for, each with what it must answer:\n * those every live brief carries, with `type` null, then those each type adds.\n * A tool that helps write a brief asks for these rather than for names it\n * knows in advance.\n */\nexport function sectionsJson(config: Config): Record<string, unknown>[] {\n const describe = (rule: SectionRule, type: string | null): Record<string, unknown> => ({\n name: rule.name,\n type,\n aliases: rule.aliases,\n optional: rule.optional,\n checklist: rule.checklist,\n mustContain: rule.mustContain,\n hint: rule.hint ?? null,\n });\n return [\n ...config.sections.map((rule) => describe(rule, null)),\n ...Object.entries(config.types).flatMap(([type, rules]) => rules.map((rule) => describe(rule, type))),\n ];\n}\n\n/** Columns padded to their widest cell; every row has the header's length. */\nfunction table(header: readonly string[], rows: readonly (readonly string[])[]): string[] {\n const all = [header, ...rows];\n const widths = header.map((_, c) => Math.max(...all.map((r) => (r[c] as string).length)));\n return all.map((r) =>\n r\n .map((cell, c) => (c === r.length - 1 ? cell : cell.padEnd(widths[c] as number)))\n .join(' ')\n .trimEnd(),\n );\n}\n\nexport interface ListRow {\n readonly brief: Brief;\n readonly ready: boolean;\n readonly waitingOn: readonly string[];\n}\n\nexport function prettyList(rows: readonly ListRow[], style: Style): string {\n if (rows.length === 0) return 'no briefs';\n const lines = table(\n ['ID', 'STATUS', 'WAVE', 'TASKS', 'READY', 'TITLE'],\n rows.map(({ brief, ready, waitingOn }) => [\n brief.id ?? '?',\n brief.status ?? brief.statusWord ?? '?',\n brief.wave === null ? '-' : String(brief.wave),\n `${brief.tasks.filter((t) => t.checked).length}/${brief.tasks.length}`,\n brief.phase === 'archived' ? '-' : ready ? 'yes' : waitingOn.length > 0 ? `after ${waitingOn.join(', ')}` : 'no',\n brief.title ?? brief.name,\n ]),\n );\n return [paint(style, 'dim', lines[0] as string), ...lines.slice(1)].join('\\n');\n}\n\nexport function prettyMatrix(report: CollisionReport, style: Style): string {\n const out: string[] = [];\n const label = (b: Brief): string => b.id ?? b.name;\n for (const wave of report.waves) {\n const title = wave.wave === null ? 'all live briefs' : `wave ${wave.wave}`;\n out.push(paint(style, 'bold', `${title} \\u00b7 ${plural(wave.briefs.length, 'brief')}`));\n const names = wave.briefs.map(label);\n const width = Math.max(3, ...names.map((n) => n.length));\n const pairs = (list: readonly { readonly a: Brief; readonly b: Brief }[]): Set<string> =>\n new Set(list.flatMap((p) => [`${label(p.a)}\\u0000${label(p.b)}`, `${label(p.b)}\\u0000${label(p.a)}`]));\n const hits = pairs(wave.collisions);\n const unknown = pairs(wave.undecided);\n const near = pairs(wave.shared);\n out.push(` ${''.padEnd(width)} ${names.map((n) => n.padStart(width)).join(' ')}`);\n for (const row of names) {\n const cells = names.map((col) => {\n const key = `${row}\\u0000${col}`;\n const mark =\n row === col\n ? '\\u00b7'\n : hits.has(key)\n ? paint(style, 'red', 'X')\n : unknown.has(key)\n ? paint(style, 'yellow', '?')\n : near.has(key)\n ? paint(style, 'yellow', '~')\n : '\\u00b7';\n return `${' '.repeat(width - 1)}${mark}`;\n });\n out.push(` ${row.padEnd(width)} ${cells.join(' ')}`);\n }\n // One mark per pair of briefs; each further pair of patterns on a line beneath it.\n for (const c of wave.collisions) {\n c.overlaps.forEach((o, i) => {\n out.push(` ${i === 0 ? paint(style, 'red', 'X') : ' '} ${label(c.a)} \"${o.patterns[0]}\" and ${label(c.b)} \"${o.patterns[1]}\" both cover ${o.witness}`);\n });\n }\n for (const u of wave.undecided) {\n u.patterns.forEach(([x, y], i) => {\n out.push(` ${i === 0 ? paint(style, 'yellow', '?') : ' '} ${label(u.a)} \"${x}\" and ${label(u.b)} \"${y}\": undecided within the search's budget`);\n });\n }\n for (const s of wave.shared) {\n out.push(` ${paint(style, 'yellow', '~')} ${label(s.a)} and ${label(s.b)} both write into ${inWords(s.directories.map((d) => `${d}/`))}`);\n }\n for (const b of wave.unscoped) {\n out.push(` ${paint(style, 'cyan', '?')} ${label(b)} declares no affectedFiles and cannot be checked`);\n }\n out.push('');\n }\n if (report.unscheduled.length > 0) {\n out.push(paint(style, 'dim', `no wave: ${report.unscheduled.map(label).join(', ')}`));\n }\n for (const w of report.waiting) {\n const why = w.waitsOn.status === 'deferred' ? 'which is deferred' : 'which waits on deferred work';\n out.push(`${paint(style, 'dim', 'waits:')} ${label(w.brief)} on ${label(w.waitsOn)}, ${why}`);\n }\n if (report.deferred.length > 0) {\n out.push(paint(style, 'dim', `deferred: ${report.deferred.map(label).join(', ')}`));\n }\n if (report.waves.length === 0 && report.unscheduled.length === 0 && report.deferred.length === 0) out.push('no live briefs');\n return out.join('\\n').trimEnd();\n}\n\n/** The matrix as JSON: briefs by id, and a collision per pair of briefs. */\nexport function matrixJson(report: CollisionReport): Record<string, unknown> {\n return {\n waves: report.waves.map((w) => ({\n wave: w.wave,\n briefs: w.briefs.map((b) => b.id),\n collisions: w.collisions.map((c) => ({\n a: c.a.id,\n b: c.b.id,\n overlaps: c.overlaps.map((o) => ({ patterns: o.patterns, witness: o.witness })),\n })),\n undecided: w.undecided.map((u) => ({ a: u.a.id, b: u.b.id, patterns: u.patterns })),\n sharedDirectories: w.shared.map((s) => ({ a: s.a.id, b: s.b.id, directories: s.directories })),\n unscoped: w.unscoped.map((b) => b.id),\n })),\n unscheduled: report.unscheduled.map((b) => b.id),\n deferred: report.deferred.map((b) => b.id),\n waiting: report.waiting.map((w) => ({ id: w.brief.id, file: w.brief.file, waitsOn: w.waitsOn.id })),\n };\n}\n\n/**\n * The waves a schedule uses, in order. They appear in order too: a brief goes\n * into a wave only when it is the first or the one before it is occupied.\n */\nfunction wavesOf(s: Schedule): number[] {\n return [...new Set(s.placements.map((p) => p.proposed))];\n}\n\n/**\n * The schedule for a person: each wave with its briefs, and under a brief whose\n * wave would change, why it goes where it goes. `written` is `null` when\n * nothing was asked to be written.\n */\nexport function prettySchedule(s: Schedule, written: readonly string[] | null, style: Style): string {\n const label = (b: Brief): string => b.id ?? b.name;\n const out: string[] = [];\n const width = Math.max(3, ...s.placements.map((p) => label(p.brief).length));\n const titleOf = (b: Brief): string => b.title ?? b.name;\n const titles = Math.max(0, ...s.placements.map((p) => titleOf(p.brief).length));\n const waves = wavesOf(s);\n for (const wave of waves) {\n const here = s.placements.filter((p) => p.proposed === wave);\n out.push(paint(style, 'bold', `wave ${wave} · ${plural(here.length, 'brief')}`));\n for (const p of here) {\n const title = titleOf(p.brief);\n if (p.proposed === p.declared) {\n out.push(` ${label(p.brief).padEnd(width)} ${title}`);\n continue;\n }\n const from = p.declared === null ? 'no wave' : `wave ${p.declared}`;\n out.push(` ${label(p.brief).padEnd(width)} ${title.padEnd(titles)} ${paint(style, 'yellow', `moves from ${from}`)}`);\n // Why the declared wave holds or does not comes first: it decides whether the move is asked for.\n const verdict = p.declared === null ? [] : holds(p) ? [`wave ${p.declared} also holds`] : [`wave ${p.declared} does not hold: ${breachReasons(p).join('; ')}`];\n for (const reason of [...verdict, ...reasons(p)]) out.push(` ${' '.repeat(width)} ${paint(style, 'dim', reason)}`);\n }\n }\n if (waves.length > 0) out.push('');\n for (const cycle of s.cycles) out.push(`${paint(style, 'red', 'cycle:')} ${cycle.map(label).join(' -> ')}`);\n for (const u of s.unplaced) {\n const why = u.because === 'deferred' ? 'which is deferred' : u.because === 'cycle' ? 'which is in a cycle' : 'which is not placed';\n out.push(`${paint(style, 'dim', 'waits:')} ${label(u.brief)} on ${label(u.waitsOn)}, ${why}`);\n }\n if (s.deferred.length > 0) out.push(paint(style, 'dim', `deferred: ${s.deferred.map(label).join(', ')}`));\n const moving = moves(s).length;\n if (written !== null && written.length > 0) {\n out.push(`wrote the wave of ${plural(written.length, 'brief')}: ${written.join(', ')}`);\n } else if (written !== null && moving > 0) {\n out.push(paint(style, 'red', s.cycles.length > 0 ? 'nothing was written: the dependencies form a cycle' : 'nothing was written: a front matter cannot be edited'));\n } else if (moving > 0 && moves(s).every(holds)) {\n out.push(`${plural(moving, 'brief')} could move, and the declared waves hold; \"spec-brief schedule --write\" writes the computed ones`);\n } else if (moving > 0) {\n out.push(`${plural(moving, 'brief')} would move; \"spec-brief schedule --write\" writes the waves`);\n } else if (s.placements.length > 0) {\n out.push('the declared waves hold');\n } else if (s.cycles.length === 0 && s.deferred.length === 0) {\n // A brief is unplaced only behind a cycle or a deferral, so this is a corpus with no live brief.\n out.push('no live briefs');\n }\n return out.join('\\n');\n}\n\n/** The schedule as JSON: a row per placed brief with its declared and proposed wave and why. */\nexport function scheduleJson(s: Schedule): Record<string, unknown> {\n const breach = (b: Breach): Record<string, unknown> =>\n b.reason === 'collision'\n ? { reason: b.reason, brief: b.brief.id, overlaps: b.overlaps.map((o) => ({ patterns: o.patterns, witness: o.witness })) }\n : { reason: b.reason, brief: b.brief.id, wave: b.wave };\n const passed = (p: Passed): Record<string, unknown> => {\n const base = { wave: p.wave, reason: p.reason, brief: p.brief.id };\n if (p.reason === 'collision') return { ...base, overlaps: p.overlaps.map((o) => ({ patterns: o.patterns, witness: o.witness })) };\n if (p.reason === 'undecided') return { ...base, patterns: p.patterns };\n return base;\n };\n const waves = wavesOf(s);\n return {\n first: s.first,\n waves: waves.map((wave) => ({ wave, briefs: s.placements.filter((p) => p.proposed === wave).map((p) => p.brief.id) })),\n briefs: s.placements.map((p) => ({\n id: p.brief.id,\n file: p.brief.file,\n declared: p.declared,\n proposed: p.proposed,\n moves: p.proposed !== p.declared,\n holds: holds(p),\n breaches: p.breaches.map(breach),\n after: p.after === null ? null : { brief: p.after.brief.id, wave: p.after.wave },\n passed: p.passed.map(passed),\n unscoped: p.unscoped,\n reasons: reasons(p),\n })),\n unplaced: s.unplaced.map((u) => ({ id: u.brief.id, file: u.brief.file, waitsOn: u.waitsOn.id, because: u.because })),\n cycles: s.cycles.map((cycle) => cycle.map((b) => b.id)),\n deferred: s.deferred.map((b) => b.id),\n };\n}\n\nexport function prettyPlan(plan: Plan, dryRun: boolean, style: Style): string {\n const out: string[] = [];\n const verb = plan.action === 'archive' ? 'archive' : 'unarchive';\n if (plan.done) return `${plan.brief.file} is already ${plan.action === 'archive' ? 'archived' : 'live'}; nothing to do`;\n if (plan.blocking.length > 0) {\n out.push(paint(style, 'red', `cannot ${verb} ${plan.brief.file}:`), prettyFindings(plan.blocking, style));\n if (plan.warnings.length > 0) out.push('', prettyFindings(plan.warnings, style));\n return out.join('\\n');\n }\n out.push(`${dryRun ? 'would move' : 'moved'} ${plan.from} -> ${plan.to}`);\n if (plan.linksRewritten > 0) out.push(` ${plural(plan.linksRewritten, 'relative link')} rewritten`);\n for (const file of plan.inboundRewritten) out.push(` ${file}: links to it rewritten`);\n for (const f of plan.inboundFrozen) out.push(` ${f.file}:${f.line}: links to the old path, and is frozen, so it was left as it is`);\n if (plan.changes.length > 0) out.push(` the round changed ${plural(plan.changes.length, 'file')}`);\n if (plan.warnings.length > 0) out.push('', prettyFindings(plan.warnings, style));\n if (dryRun && plan.banner.length > 0) out.push('', paint(style, 'dim', 'banner:'), ...plan.banner.map((l) => ` ${l}`));\n if (!dryRun) out.push('', paint(style, 'dim', 'nothing was committed; review the change and commit it with the round'));\n return out.join('\\n');\n}\n\nexport function planJson(plan: Plan): Record<string, unknown> {\n return {\n action: plan.action,\n brief: plan.brief.id,\n from: plan.from,\n to: plan.to,\n done: plan.done,\n refused: plan.blocking.length > 0,\n blocking: plan.blocking.map(findingJson),\n warnings: plan.warnings.map(findingJson),\n linksRewritten: plan.linksRewritten,\n inboundRewritten: plan.inboundRewritten,\n inboundFrozen: plan.inboundFrozen,\n operations: plan.ops.map((op) => ({ kind: op.kind, path: op.path })),\n banner: plan.banner,\n changes: plan.changes,\n };\n}\n"]}
|