@descent-vtt/spec-brief 0.2.6 → 0.3.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.
Files changed (51) hide show
  1. package/CHANGELOG.md +100 -1
  2. package/README.md +162 -29
  3. package/dist/cli.d.ts +1 -1
  4. package/dist/cli.js +61 -43
  5. package/dist/cli.js.map +1 -1
  6. package/dist/collisions.js +13 -8
  7. package/dist/collisions.js.map +1 -1
  8. package/dist/config.js +2 -1
  9. package/dist/config.js.map +1 -1
  10. package/dist/corpus.d.ts +5 -0
  11. package/dist/corpus.js +7 -0
  12. package/dist/corpus.js.map +1 -1
  13. package/dist/glob.d.ts +6 -2
  14. package/dist/glob.js +27 -5
  15. package/dist/glob.js.map +1 -1
  16. package/dist/lint.js +1 -0
  17. package/dist/lint.js.map +1 -1
  18. package/dist/report.d.ts +18 -4
  19. package/dist/report.js +98 -28
  20. package/dist/report.js.map +1 -1
  21. package/dist/rules.d.ts +2 -0
  22. package/dist/rules.js +21 -8
  23. package/dist/rules.js.map +1 -1
  24. package/dist/schedule.js +12 -10
  25. package/dist/schedule.js.map +1 -1
  26. package/dist/schema.d.ts +5 -1
  27. package/dist/schema.js +6 -2
  28. package/dist/schema.js.map +1 -1
  29. package/dist/scope.d.ts +26 -4
  30. package/dist/scope.js +64 -8
  31. package/dist/scope.js.map +1 -1
  32. package/dist/trigger.js +59 -3
  33. package/dist/trigger.js.map +1 -1
  34. package/dist/types.d.ts +9 -0
  35. package/dist/types.js.map +1 -1
  36. package/dist/vendor/spec-core/markdown/frontmatter.d.ts +11 -1
  37. package/dist/vendor/spec-core/markdown/frontmatter.js +20 -3
  38. package/dist/vendor/spec-core/markdown/frontmatter.js.map +1 -1
  39. package/dist/vendor/spec-core/pattern/glob.d.ts +88 -2
  40. package/dist/vendor/spec-core/pattern/glob.js +234 -32
  41. package/dist/vendor/spec-core/pattern/glob.js.map +1 -1
  42. package/dist/vendor/spec-core/pattern/index.d.ts +2 -2
  43. package/dist/vendor/spec-core/pattern/index.js +1 -1
  44. package/dist/vendor/spec-core/pattern/index.js.map +1 -1
  45. package/dist/vendor/spec-core/text/index.d.ts +1 -0
  46. package/dist/vendor/spec-core/text/index.js +1 -0
  47. package/dist/vendor/spec-core/text/index.js.map +1 -1
  48. package/dist/vendor/spec-core/text/width.d.ts +30 -0
  49. package/dist/vendor/spec-core/text/width.js +113 -0
  50. package/dist/vendor/spec-core/text/width.js.map +1 -0
  51. package/package.json +1 -1
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 } 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 { CONFIG_FILES, ConfigError, initialConfig } from './config.js';\nimport { BriefEngine, EngineError, today } from './engine.js';\nimport { NodeFileSystem } from './fs.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\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\n --config <file> use this configuration file\n --no-config use the defaults, ignoring any configuration file\n --format <format> pretty (default), json, sarif, github or gitlab\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\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 today\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 today\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\nExit codes: 0 clean, 1 findings or refused, 2 the run could not be trusted.\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\nconst COMMANDS: Readonly<Record<string, { options: NonNullable<ParseArgsConfig['options']>; formats: readonly Format[] }>> = {\n init: { options: { briefs: { type: 'string' }, archive: { type: 'string' } }, formats: ['pretty', 'json'] },\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'] },\n matrix: { options: { 'all-waves': { type: 'boolean' } }, formats: FORMATS },\n schedule: { options: { write: { type: 'boolean' } }, formats: FORMATS },\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\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 = command === undefined ? undefined : COMMANDS[command];\n if (command !== undefined && spec === undefined) {\n throw new UsageError(`\"${command}\" is not a command; run spec-brief --help`);\n }\n try {\n const { values, positionals } = parseArgs({\n args: [...argv],\n options: { ...GLOBAL, ...(spec?.options ?? {}) },\n allowPositionals: true,\n strict: true,\n });\n return { command, values: values as Values, positionals: positionals.slice(1) };\n } catch (error) {\n throw new UsageError((error as Error).message);\n }\n}\n\nfunction text(values: Values, key: string): string | undefined {\n const value = values[key];\n return typeof value === 'string' ? value : 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 /** Today, as the environment the run was given says. */\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 return (io.stdout ?? process.stdout).isTTY === true;\n}\n\nasync function openEngine(run: Run): Promise<BriefEngine> {\n const root = text(run.values, 'root');\n const config = text(run.values, 'config');\n return BriefEngine.open({\n cwd: root === undefined ? run.cwd : root,\n ...(config === undefined ? {} : { 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 const briefs = normalisePath(text(run.values, 'briefs') ?? 'briefs');\n const archive = normalisePath(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 engine = await openEngine(run);\n const dependsOn = text(run.values, 'depends-on')\n ?.split(',')\n .map((d) => d.trim())\n .filter((d) => d !== '');\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 run.out(`${prettyMatrix(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 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 return command === undefined && !flag(values, 'help') ? EXIT_ERROR : EXIT_OK;\n }\n const spec = COMMANDS[command] as (typeof COMMANDS)[string];\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 const run: Run = {\n today: today(io.env ?? process.env),\n out: (t) => {\n stdout.write(t);\n },\n err,\n style: { color: format === 'pretty' && 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 try {\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 const expected = [ConfigError, UsageError, EngineError, ConflictError, TransactionError];\n if (expected.some((kind) => error instanceof kind)) {\n err((error as Error).message);\n return EXIT_ERROR;\n }\n err(`unexpected error: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`);\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 } 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 { CONFIG_FILES, ConfigError, initialConfig } from './config.js';\nimport { BriefEngine, EngineError, today } from './engine.js';\nimport { NodeFileSystem } from './fs.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\nconst COMMANDS: Readonly<Record<string, { options: NonNullable<ParseArgsConfig['options']>; formats: readonly Format[] }>> = {\n init: { options: { briefs: { type: 'string' }, archive: { type: 'string' } }, formats: ['pretty', 'json'] },\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'] },\n matrix: { options: { 'all-waves': { type: 'boolean' } }, formats: FORMATS },\n schedule: { options: { write: { type: 'boolean' } }, formats: FORMATS },\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 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(COMMANDS)) {\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\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 today\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 today\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\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 = command === undefined ? undefined : COMMANDS[command];\n if (command !== undefined && spec === undefined) {\n throw new UsageError(`\"${command}\" is not a command; run spec-brief --help`);\n }\n try {\n const { values, positionals } = parseArgs({\n args: [...argv],\n options: { ...GLOBAL, ...(spec?.options ?? {}) },\n allowPositionals: true,\n strict: true,\n });\n return { command, values: values as Values, positionals: positionals.slice(1) };\n } catch (error) {\n throw new UsageError((error as Error).message);\n }\n}\n\nfunction text(values: Values, key: string): string | undefined {\n const value = values[key];\n return typeof value === 'string' ? value : 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 /** Today, as the environment the run was given says. */\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 return (io.stdout ?? process.stdout).isTTY === true;\n}\n\nasync function openEngine(run: Run): Promise<BriefEngine> {\n const root = text(run.values, 'root');\n const config = text(run.values, 'config');\n return BriefEngine.open({\n cwd: root === undefined ? run.cwd : root,\n ...(config === undefined ? {} : { 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 const briefs = normalisePath(text(run.values, 'briefs') ?? 'briefs');\n const archive = normalisePath(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 engine = await openEngine(run);\n const dependsOn = text(run.values, 'depends-on')\n ?.split(',')\n .map((d) => d.trim())\n .filter((d) => d !== '');\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 run.out(`${prettyMatrix(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 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 return command === undefined && !flag(values, 'help') ? EXIT_ERROR : EXIT_OK;\n }\n const spec = COMMANDS[command] as (typeof COMMANDS)[string];\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 const run: Run = {\n today: today(io.env ?? process.env),\n out: (t) => {\n stdout.write(t);\n },\n err,\n style: { color: format === 'pretty' && 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 try {\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 const expected = [ConfigError, UsageError, EngineError, ConflictError, TransactionError];\n if (expected.some((kind) => error instanceof kind)) {\n err((error as Error).message);\n return EXIT_ERROR;\n }\n err(`unexpected error: ${error instanceof Error ? (error.stack ?? error.message) : String(error)}`);\n return EXIT_ERROR;\n }\n}\n"]}
@@ -19,9 +19,9 @@ import { lineOfField } from './brief.js';
19
19
  import { waitingOnDeferred } from './corpus.js';
20
20
  import { globBases, readingIn, WITNESS_BUDGET } from './glob.js';
21
21
  import { configuredSeverity } from './lint.js';
22
- import { meet, scopeOf } from './scope.js';
22
+ import { meet, scopeOf, witnessText } from './scope.js';
23
23
  import { inWords } from './text.js';
24
- function matrix(wave, briefs, scopes, budget) {
24
+ function matrix(wave, briefs, scopes, budget, files) {
25
25
  const collisions = [];
26
26
  const undecided = [];
27
27
  const shared = [];
@@ -30,7 +30,7 @@ function matrix(wave, briefs, scopes, budget) {
30
30
  for (let j = i + 1; j < scoped.length; j += 1) {
31
31
  const left = scoped[i];
32
32
  const right = scoped[j];
33
- const meeting = meet(left, right, budget);
33
+ const meeting = meet(left, right, budget, files);
34
34
  if (meeting.overlaps.length > 0) {
35
35
  collisions.push({ a: left.brief, b: right.brief, overlaps: meeting.overlaps });
36
36
  continue;
@@ -49,7 +49,8 @@ function matrix(wave, briefs, scopes, budget) {
49
49
  return { wave, briefs, collisions, undecided, shared, unscoped };
50
50
  }
51
51
  export function collisions(corpus, options = {}) {
52
- const reading = readingIn(options.repoFiles ?? null);
52
+ const files = options.repoFiles ?? null;
53
+ const reading = readingIn(files);
53
54
  const budget = options.budget ?? WITNESS_BUDGET;
54
55
  const deferred = corpus.live.filter((b) => b.status === 'deferred');
55
56
  const waiting = waitingOnDeferred(corpus);
@@ -57,7 +58,7 @@ export function collisions(corpus, options = {}) {
57
58
  const live = corpus.live.filter((b) => b.status !== 'deferred' && !held.has(b));
58
59
  const scopes = new Map(live.map((brief) => [brief, scopeOf(brief, reading)]));
59
60
  if (options.all === true)
60
- return { waves: [matrix(null, live, scopes, budget)], unscheduled: [], deferred, waiting };
61
+ return { waves: [matrix(null, live, scopes, budget, files)], unscheduled: [], deferred, waiting };
61
62
  const byWave = new Map();
62
63
  const unscheduled = [];
63
64
  for (const brief of live) {
@@ -66,7 +67,7 @@ export function collisions(corpus, options = {}) {
66
67
  else
67
68
  byWave.set(brief.wave, [...(byWave.get(brief.wave) ?? []), brief]);
68
69
  }
69
- const waves = [...byWave.keys()].sort((a, b) => a - b).map((wave) => matrix(wave, byWave.get(wave), scopes, budget));
70
+ const waves = [...byWave.keys()].sort((a, b) => a - b).map((wave) => matrix(wave, byWave.get(wave), scopes, budget, files));
70
71
  return { waves, unscheduled, deferred, waiting };
71
72
  }
72
73
  function label(brief) {
@@ -78,9 +79,9 @@ function where(wave) {
78
79
  function collisionMessage(c, wave) {
79
80
  if (c.overlaps.length === 1) {
80
81
  const only = c.overlaps[0];
81
- return `"${only.patterns[1]}" overlaps ${label(c.a)}'s "${only.patterns[0]}" ${where(wave)}; both cover ${only.witness}`;
82
+ return `"${only.patterns[1]}" overlaps ${label(c.a)}'s "${only.patterns[0]}" ${where(wave)}; both cover ${witnessText(only)}`;
82
83
  }
83
- const each = c.overlaps.map((o) => `"${o.patterns[1]}" and ${label(c.a)}'s "${o.patterns[0]}" both cover ${o.witness}`);
84
+ const each = c.overlaps.map((o) => `"${o.patterns[1]}" and ${label(c.a)}'s "${o.patterns[0]}" both cover ${witnessText(o)}`);
84
85
  return `overlaps ${label(c.a)} ${where(wave)} through ${c.overlaps.length} pairs of patterns: ${each.join('; ')}`;
85
86
  }
86
87
  /** A pair whose collision the search could not decide, as one finding on the later brief. */
@@ -94,6 +95,7 @@ export function undecidedFinding(severity, a, b, patterns, wave) {
94
95
  line: lineOfField(b, 'affectedFiles') + 1,
95
96
  brief: b.id ?? undefined,
96
97
  hint: 'narrow one of the patterns, or run the two in different waves',
98
+ subject: label(a),
97
99
  };
98
100
  }
99
101
  /**
@@ -117,6 +119,8 @@ export function collisionFindings(corpus, report) {
117
119
  line: lineOfField(c.b, 'affectedFiles') + 1,
118
120
  brief: c.b.id ?? undefined,
119
121
  hint: `run them in different waves, make one depend on the other, or narrow a scope`,
122
+ // The pair is the problem, whichever patterns meet and whatever file is named.
123
+ subject: label(c.a),
120
124
  });
121
125
  }
122
126
  }
@@ -134,6 +138,7 @@ export function collisionFindings(corpus, report) {
134
138
  line: lineOfField(s.b, 'affectedFiles') + 1,
135
139
  brief: s.b.id ?? undefined,
136
140
  hint: 'check that the two do not depend on one decision in that directory; if they do, order them',
141
+ subject: label(s.a),
137
142
  });
138
143
  }
139
144
  }
@@ -1 +1 @@
1
- {"version":3,"file":"collisions.js","sourceRoot":"","sources":["../src/collisions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The collision matrix: which briefs scheduled to run side by side declare\n * scopes that can name the same file.\n *\n * Scopes are compared as globs, not as strings. `src/auth/**` and\n * `src/**\\/session.ts` share no prefix a string comparison would see and both\n * cover `src/auth/session.ts`; the witness search finds that, and names the\n * file. What a brief protects it will not write, so a file either brief of a\n * pair protects is no collision. A brief that declares no scope cannot be\n * proven apart from anything, so it is reported as unscoped rather than\n * silently counted as safe, and a pair the search could not decide is reported\n * as undecided rather than as either.\n *\n * Two briefs that collide are one defect however many of their patterns\n * meet: they are fixed together, by a wave, a dependency or a narrower scope.\n * So a pair is one collision, carrying every pair of patterns that meets.\n */\n\nimport type { Brief } from './brief.js';\nimport { lineOfField } from './brief.js';\nimport { type Corpus, waitingOnDeferred, type Waiting } from './corpus.js';\nimport { globBases, readingIn, WITNESS_BUDGET } from './glob.js';\nimport { configuredSeverity } from './lint.js';\nimport { meet, type Overlap, type Scope, scopeOf } from './scope.js';\nimport { inWords } from './text.js';\nimport type { Finding, Severity } from './types.js';\n\nexport type { Overlap } from './scope.js';\n\nexport interface Collision {\n readonly a: Brief;\n readonly b: Brief;\n /** Every pair of patterns that meets, `a`'s first; never empty. */\n readonly overlaps: readonly Overlap[];\n}\n\n/** Two briefs no pair of whose patterns is known to meet, and some pair the search could not decide. */\nexport interface UndecidedPair {\n readonly a: Brief;\n readonly b: Brief;\n /** The pairs of patterns, `a`'s first; never empty. */\n readonly patterns: readonly (readonly [string, string])[];\n}\n\nexport interface SharedDirectory {\n readonly a: Brief;\n readonly b: Brief;\n /** The directories both write into, sorted; never empty. */\n readonly directories: readonly string[];\n}\n\nexport interface WaveMatrix {\n /** `null` when every live brief is compared regardless of wave. */\n readonly wave: number | null;\n readonly briefs: readonly Brief[];\n readonly collisions: readonly Collision[];\n readonly undecided: readonly UndecidedPair[];\n readonly shared: readonly SharedDirectory[];\n readonly unscoped: readonly Brief[];\n}\n\nexport interface CollisionReport {\n readonly waves: readonly WaveMatrix[];\n /** Live briefs with no wave, which the matrix does not place. */\n readonly unscheduled: readonly Brief[];\n /** Deferred briefs, which wait for their trigger and run in no wave. */\n readonly deferred: readonly Brief[];\n /**\n * Briefs that depend on a deferred brief, or on one that waits on one. They\n * cannot start before the deferred work, so they run in no wave either, and\n * are compared with nothing - as `schedule` places them nowhere. By id.\n */\n readonly waiting: readonly Waiting[];\n}\n\nexport interface CollisionOptions {\n /** Compare every live brief with every other, whatever its wave. */\n readonly all?: boolean;\n /** The files the tree holds, which say whether a literal path is a file or a directory. */\n readonly repoFiles?: readonly string[] | null;\n /** How many states one witness search may visit before it answers `undecided`. */\n readonly budget?: number;\n}\n\nfunction matrix(wave: number | null, briefs: readonly Brief[], scopes: ReadonlyMap<Brief, Scope>, budget: number): WaveMatrix {\n const collisions: Collision[] = [];\n const undecided: UndecidedPair[] = [];\n const shared: SharedDirectory[] = [];\n const scoped = briefs.map((brief) => scopes.get(brief) as Scope);\n for (let i = 0; i < scoped.length; i += 1) {\n for (let j = i + 1; j < scoped.length; j += 1) {\n const left = scoped[i] as Scope;\n const right = scoped[j] as Scope;\n const meeting = meet(left, right, budget);\n if (meeting.overlaps.length > 0) {\n collisions.push({ a: left.brief, b: right.brief, overlaps: meeting.overlaps });\n continue;\n }\n if (meeting.undecided.length > 0) {\n undecided.push({ a: left.brief, b: right.brief, patterns: meeting.undecided });\n continue;\n }\n const leftDirs = new Set(left.affected.flatMap((s) => globBases(s.glob)).filter((d) => d !== ''));\n const directories = [...new Set(right.affected.flatMap((s) => globBases(s.glob)))].filter((d) => leftDirs.has(d)).sort();\n if (directories.length > 0) shared.push({ a: left.brief, b: right.brief, directories });\n }\n }\n const unscoped = briefs.length > 1 ? scoped.filter((s) => s.affected.length === 0).map((s) => s.brief) : [];\n return { wave, briefs, collisions, undecided, shared, unscoped };\n}\n\nexport function collisions(corpus: Corpus, options: CollisionOptions = {}): CollisionReport {\n const reading = readingIn(options.repoFiles ?? null);\n const budget = options.budget ?? WITNESS_BUDGET;\n const deferred = corpus.live.filter((b) => b.status === 'deferred');\n const waiting = waitingOnDeferred(corpus);\n const held = new Set(waiting.map((w) => w.brief));\n const live = corpus.live.filter((b) => b.status !== 'deferred' && !held.has(b));\n const scopes = new Map(live.map((brief) => [brief, scopeOf(brief, reading)]));\n if (options.all === true) return { waves: [matrix(null, live, scopes, budget)], unscheduled: [], deferred, waiting };\n const byWave = new Map<number, Brief[]>();\n const unscheduled: Brief[] = [];\n for (const brief of live) {\n if (brief.wave === null) unscheduled.push(brief);\n else byWave.set(brief.wave, [...(byWave.get(brief.wave) ?? []), brief]);\n }\n const waves = [...byWave.keys()].sort((a, b) => a - b).map((wave) => matrix(wave, byWave.get(wave) as Brief[], scopes, budget));\n return { waves, unscheduled, deferred, waiting };\n}\n\nfunction label(brief: Brief): string {\n return brief.id ?? brief.name;\n}\n\nfunction where(wave: number | null): string {\n return wave === null ? 'among the live briefs' : `in wave ${wave}`;\n}\n\nfunction collisionMessage(c: Collision, wave: number | null): string {\n if (c.overlaps.length === 1) {\n const only = c.overlaps[0] as Overlap;\n return `\"${only.patterns[1]}\" overlaps ${label(c.a)}'s \"${only.patterns[0]}\" ${where(wave)}; both cover ${only.witness}`;\n }\n const each = c.overlaps.map((o) => `\"${o.patterns[1]}\" and ${label(c.a)}'s \"${o.patterns[0]}\" both cover ${o.witness}`);\n return `overlaps ${label(c.a)} ${where(wave)} through ${c.overlaps.length} pairs of patterns: ${each.join('; ')}`;\n}\n\n/** A pair whose collision the search could not decide, as one finding on the later brief. */\nexport function undecidedFinding(severity: Severity, a: Brief, b: Brief, patterns: readonly (readonly [string, string])[], wave: number | null): Finding {\n const pairs = patterns.map(([x, y]) => `\"${y}\" and ${label(a)}'s \"${x}\"`);\n return {\n rule: 'collision-undecided',\n severity,\n message: `whether it can write a file ${label(a)} writes ${where(wave)} is undecided: the search met its budget for ${inWords(pairs)}`,\n file: b.file,\n line: lineOfField(b, 'affectedFiles') + 1,\n brief: b.id ?? undefined,\n hint: 'narrow one of the patterns, or run the two in different waves',\n };\n}\n\n/**\n * The report as findings. One pair of briefs is one finding, placed on the\n * later brief of the pair, which is usually the one still being written.\n */\nexport function collisionFindings(corpus: Corpus, report: CollisionReport): Finding[] {\n const findings: Finding[] = [];\n const collision = configuredSeverity(corpus, 'collision');\n const undecided = configuredSeverity(corpus, 'collision-undecided');\n const unscoped = configuredSeverity(corpus, 'unscoped');\n const sharedDirectory = configuredSeverity(corpus, 'shared-directory');\n for (const wave of report.waves) {\n if (collision !== null) {\n for (const c of wave.collisions) {\n findings.push({\n rule: 'collision',\n severity: collision,\n message: collisionMessage(c, wave.wave),\n file: c.b.file,\n line: lineOfField(c.b, 'affectedFiles') + 1,\n brief: c.b.id ?? undefined,\n hint: `run them in different waves, make one depend on the other, or narrow a scope`,\n });\n }\n }\n if (undecided !== null) {\n for (const u of wave.undecided) findings.push(undecidedFinding(undecided, u.a, u.b, u.patterns, wave.wave));\n }\n if (sharedDirectory !== null) {\n for (const s of wave.shared) {\n findings.push({\n rule: 'shared-directory',\n severity: sharedDirectory,\n message: `writes into ${inWords(s.directories.map((d) => `${d}/`))}, as ${label(s.a)} does ${where(wave.wave)}`,\n file: s.b.file,\n line: lineOfField(s.b, 'affectedFiles') + 1,\n brief: s.b.id ?? undefined,\n hint: 'check that the two do not depend on one decision in that directory; if they do, order them',\n });\n }\n }\n if (unscoped !== null) {\n for (const brief of wave.unscoped) findings.push(unscopedFinding(unscoped, brief, `the ${wave.briefs.length - 1} other brief(s) ${where(wave.wave)}`));\n }\n }\n return findings;\n}\n\n/** A brief with no scope, which nothing can be proved apart from. */\nexport function unscopedFinding(severity: Severity, brief: Brief, others: string): Finding {\n return {\n rule: 'unscoped',\n severity,\n message: `declares no affectedFiles, so it cannot be checked against ${others}`,\n file: brief.file,\n line: 1,\n brief: brief.id ?? undefined,\n hint: 'list the files or globs this round writes under \"affectedFiles\"',\n };\n}\n"]}
1
+ {"version":3,"file":"collisions.js","sourceRoot":"","sources":["../src/collisions.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * The collision matrix: which briefs scheduled to run side by side declare\n * scopes that can name the same file.\n *\n * Scopes are compared as globs, not as strings. `src/auth/**` and\n * `src/**\\/session.ts` share no prefix a string comparison would see and both\n * cover `src/auth/session.ts`; the witness search finds that, and names the\n * file. What a brief protects it will not write, so a file either brief of a\n * pair protects is no collision. A brief that declares no scope cannot be\n * proven apart from anything, so it is reported as unscoped rather than\n * silently counted as safe, and a pair the search could not decide is reported\n * as undecided rather than as either.\n *\n * Two briefs that collide are one defect however many of their patterns\n * meet: they are fixed together, by a wave, a dependency or a narrower scope.\n * So a pair is one collision, carrying every pair of patterns that meets.\n */\n\nimport type { Brief } from './brief.js';\nimport { lineOfField } from './brief.js';\nimport { type Corpus, waitingOnDeferred, type Waiting } from './corpus.js';\nimport { globBases, readingIn, WITNESS_BUDGET } from './glob.js';\nimport { configuredSeverity } from './lint.js';\nimport { meet, type Overlap, type Scope, scopeOf, witnessText } from './scope.js';\nimport { inWords } from './text.js';\nimport type { Finding, Severity } from './types.js';\n\nexport type { Overlap } from './scope.js';\n\nexport interface Collision {\n readonly a: Brief;\n readonly b: Brief;\n /** Every pair of patterns that meets, `a`'s first; never empty. */\n readonly overlaps: readonly Overlap[];\n}\n\n/** Two briefs no pair of whose patterns is known to meet, and some pair the search could not decide. */\nexport interface UndecidedPair {\n readonly a: Brief;\n readonly b: Brief;\n /** The pairs of patterns, `a`'s first; never empty. */\n readonly patterns: readonly (readonly [string, string])[];\n}\n\nexport interface SharedDirectory {\n readonly a: Brief;\n readonly b: Brief;\n /** The directories both write into, sorted; never empty. */\n readonly directories: readonly string[];\n}\n\nexport interface WaveMatrix {\n /** `null` when every live brief is compared regardless of wave. */\n readonly wave: number | null;\n readonly briefs: readonly Brief[];\n readonly collisions: readonly Collision[];\n readonly undecided: readonly UndecidedPair[];\n readonly shared: readonly SharedDirectory[];\n readonly unscoped: readonly Brief[];\n}\n\nexport interface CollisionReport {\n readonly waves: readonly WaveMatrix[];\n /** Live briefs with no wave, which the matrix does not place. */\n readonly unscheduled: readonly Brief[];\n /** Deferred briefs, which wait for their trigger and run in no wave. */\n readonly deferred: readonly Brief[];\n /**\n * Briefs that depend on a deferred brief, or on one that waits on one. They\n * cannot start before the deferred work, so they run in no wave either, and\n * are compared with nothing - as `schedule` places them nowhere. By id.\n */\n readonly waiting: readonly Waiting[];\n}\n\nexport interface CollisionOptions {\n /** Compare every live brief with every other, whatever its wave. */\n readonly all?: boolean;\n /** The files the tree holds, which say whether a literal path is a file or a directory. */\n readonly repoFiles?: readonly string[] | null;\n /** How many states one witness search may visit before it answers `undecided`. */\n readonly budget?: number;\n}\n\nfunction matrix(wave: number | null, briefs: readonly Brief[], scopes: ReadonlyMap<Brief, Scope>, budget: number, files: readonly string[] | null): WaveMatrix {\n const collisions: Collision[] = [];\n const undecided: UndecidedPair[] = [];\n const shared: SharedDirectory[] = [];\n const scoped = briefs.map((brief) => scopes.get(brief) as Scope);\n for (let i = 0; i < scoped.length; i += 1) {\n for (let j = i + 1; j < scoped.length; j += 1) {\n const left = scoped[i] as Scope;\n const right = scoped[j] as Scope;\n const meeting = meet(left, right, budget, files);\n if (meeting.overlaps.length > 0) {\n collisions.push({ a: left.brief, b: right.brief, overlaps: meeting.overlaps });\n continue;\n }\n if (meeting.undecided.length > 0) {\n undecided.push({ a: left.brief, b: right.brief, patterns: meeting.undecided });\n continue;\n }\n const leftDirs = new Set(left.affected.flatMap((s) => globBases(s.glob)).filter((d) => d !== ''));\n const directories = [...new Set(right.affected.flatMap((s) => globBases(s.glob)))].filter((d) => leftDirs.has(d)).sort();\n if (directories.length > 0) shared.push({ a: left.brief, b: right.brief, directories });\n }\n }\n const unscoped = briefs.length > 1 ? scoped.filter((s) => s.affected.length === 0).map((s) => s.brief) : [];\n return { wave, briefs, collisions, undecided, shared, unscoped };\n}\n\nexport function collisions(corpus: Corpus, options: CollisionOptions = {}): CollisionReport {\n const files = options.repoFiles ?? null;\n const reading = readingIn(files);\n const budget = options.budget ?? WITNESS_BUDGET;\n const deferred = corpus.live.filter((b) => b.status === 'deferred');\n const waiting = waitingOnDeferred(corpus);\n const held = new Set(waiting.map((w) => w.brief));\n const live = corpus.live.filter((b) => b.status !== 'deferred' && !held.has(b));\n const scopes = new Map(live.map((brief) => [brief, scopeOf(brief, reading)]));\n if (options.all === true) return { waves: [matrix(null, live, scopes, budget, files)], unscheduled: [], deferred, waiting };\n const byWave = new Map<number, Brief[]>();\n const unscheduled: Brief[] = [];\n for (const brief of live) {\n if (brief.wave === null) unscheduled.push(brief);\n else byWave.set(brief.wave, [...(byWave.get(brief.wave) ?? []), brief]);\n }\n const waves = [...byWave.keys()].sort((a, b) => a - b).map((wave) => matrix(wave, byWave.get(wave) as Brief[], scopes, budget, files));\n return { waves, unscheduled, deferred, waiting };\n}\n\nfunction label(brief: Brief): string {\n return brief.id ?? brief.name;\n}\n\nfunction where(wave: number | null): string {\n return wave === null ? 'among the live briefs' : `in wave ${wave}`;\n}\n\nfunction collisionMessage(c: Collision, wave: number | null): string {\n if (c.overlaps.length === 1) {\n const only = c.overlaps[0] as Overlap;\n return `\"${only.patterns[1]}\" overlaps ${label(c.a)}'s \"${only.patterns[0]}\" ${where(wave)}; both cover ${witnessText(only)}`;\n }\n const each = c.overlaps.map((o) => `\"${o.patterns[1]}\" and ${label(c.a)}'s \"${o.patterns[0]}\" both cover ${witnessText(o)}`);\n return `overlaps ${label(c.a)} ${where(wave)} through ${c.overlaps.length} pairs of patterns: ${each.join('; ')}`;\n}\n\n/** A pair whose collision the search could not decide, as one finding on the later brief. */\nexport function undecidedFinding(severity: Severity, a: Brief, b: Brief, patterns: readonly (readonly [string, string])[], wave: number | null): Finding {\n const pairs = patterns.map(([x, y]) => `\"${y}\" and ${label(a)}'s \"${x}\"`);\n return {\n rule: 'collision-undecided',\n severity,\n message: `whether it can write a file ${label(a)} writes ${where(wave)} is undecided: the search met its budget for ${inWords(pairs)}`,\n file: b.file,\n line: lineOfField(b, 'affectedFiles') + 1,\n brief: b.id ?? undefined,\n hint: 'narrow one of the patterns, or run the two in different waves',\n subject: label(a),\n };\n}\n\n/**\n * The report as findings. One pair of briefs is one finding, placed on the\n * later brief of the pair, which is usually the one still being written.\n */\nexport function collisionFindings(corpus: Corpus, report: CollisionReport): Finding[] {\n const findings: Finding[] = [];\n const collision = configuredSeverity(corpus, 'collision');\n const undecided = configuredSeverity(corpus, 'collision-undecided');\n const unscoped = configuredSeverity(corpus, 'unscoped');\n const sharedDirectory = configuredSeverity(corpus, 'shared-directory');\n for (const wave of report.waves) {\n if (collision !== null) {\n for (const c of wave.collisions) {\n findings.push({\n rule: 'collision',\n severity: collision,\n message: collisionMessage(c, wave.wave),\n file: c.b.file,\n line: lineOfField(c.b, 'affectedFiles') + 1,\n brief: c.b.id ?? undefined,\n hint: `run them in different waves, make one depend on the other, or narrow a scope`,\n // The pair is the problem, whichever patterns meet and whatever file is named.\n subject: label(c.a),\n });\n }\n }\n if (undecided !== null) {\n for (const u of wave.undecided) findings.push(undecidedFinding(undecided, u.a, u.b, u.patterns, wave.wave));\n }\n if (sharedDirectory !== null) {\n for (const s of wave.shared) {\n findings.push({\n rule: 'shared-directory',\n severity: sharedDirectory,\n message: `writes into ${inWords(s.directories.map((d) => `${d}/`))}, as ${label(s.a)} does ${where(wave.wave)}`,\n file: s.b.file,\n line: lineOfField(s.b, 'affectedFiles') + 1,\n brief: s.b.id ?? undefined,\n hint: 'check that the two do not depend on one decision in that directory; if they do, order them',\n subject: label(s.a),\n });\n }\n }\n if (unscoped !== null) {\n for (const brief of wave.unscoped) findings.push(unscopedFinding(unscoped, brief, `the ${wave.briefs.length - 1} other brief(s) ${where(wave.wave)}`));\n }\n }\n return findings;\n}\n\n/** A brief with no scope, which nothing can be proved apart from. */\nexport function unscopedFinding(severity: Severity, brief: Brief, others: string): Finding {\n return {\n rule: 'unscoped',\n severity,\n message: `declares no affectedFiles, so it cannot be checked against ${others}`,\n file: brief.file,\n line: 1,\n brief: brief.id ?? undefined,\n hint: 'list the files or globs this round writes under \"affectedFiles\"',\n };\n}\n"]}
package/dist/config.js CHANGED
@@ -183,7 +183,8 @@ export const DEFAULT_CONFIG = {
183
183
  refactor: [],
184
184
  chore: [],
185
185
  },
186
- placeholders: ['TBD', 'TBA', 'TODO', 'FIXME', 'XXX', '???', '...', '\u2026'],
186
+ // To be decided, undecided, to be filled in, to be confirmed: Traditional, then Simplified where it differs.
187
+ placeholders: ['TBD', 'TBA', 'TODO', 'FIXME', 'XXX', '???', '...', '\u2026', '待定', '未定', '待補', '待补', '待確認', '待确认'],
187
188
  fields: [],
188
189
  archiving: {
189
190
  tasks: 'all',
@@ -1 +1 @@
1
- {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Configuration: what it may say, what it says when it says nothing, and how a\n * file becomes a `Config`.\n *\n * Every repository that already keeps briefs keeps them its own way - where\n * they live, what the sections are called, which word means \"done\" - so the\n * conventions are data here rather than code. The defaults describe a brief\n * with the four parts every round needs: an intent, a negative scope, what the\n * round is not empowered to touch, and the invariants that prove it is done.\n *\n * A configuration that does not load stops the run. A typo that silently\n * falls back to defaults produces a clean-looking report about the wrong\n * rules, which is worse than no report.\n */\n\nimport { dirname, join } from 'node:path';\n\nimport { parseGlob } from './glob.js';\nimport { normalisePath } from './links.js';\nimport { type Schema, toJsonSchema, validate } from './schema.js';\nimport { inWords, templateHoles } from './text.js';\nimport type { SeveritySetting } from './types.js';\n\nexport interface SectionRule {\n readonly name: string;\n readonly aliases: readonly string[];\n /** Literal text the section must contain, compared exactly. */\n readonly mustContain: readonly string[];\n /** The section must hold at least one task item. */\n readonly checklist: boolean;\n readonly optional: boolean;\n /**\n * What the section must answer. A new brief carries it as a comment under\n * the heading, a finding that the section is missing or unwritten carries it\n * as its hint, and `list` and `lint` report it, so a tool that helps write a\n * brief can ask for each section without knowing its name in advance.\n */\n readonly hint?: string | undefined;\n}\n\nexport interface PluginReference {\n readonly module: string;\n readonly options: unknown;\n}\n\nexport interface Config {\n /** Directory of live briefs, relative to the root. */\n readonly briefs: string;\n /** Directory of archived briefs, relative to the root. */\n readonly archive: string;\n /** Glob a file name must match to be a brief. */\n readonly files: string;\n /** File-name globs that are never briefs, such as an index. */\n readonly exclude: readonly string[];\n /** A template for `new`, relative to the root; `null` builds one from `sections`. */\n readonly template: string | null;\n readonly id: {\n readonly source: 'filename' | 'frontmatter';\n readonly separator: string;\n readonly digits: number;\n };\n readonly status: {\n readonly field: string | null;\n readonly draft: string | null;\n readonly active: string;\n /** The word for work put off until an event its `trigger` names; `null` when a repository has none. */\n readonly deferred: string | null;\n readonly archived: string;\n };\n readonly sections: readonly SectionRule[];\n readonly sectionOrder: boolean;\n readonly types: Readonly<Record<string, readonly SectionRule[]>>;\n readonly placeholders: readonly string[];\n readonly fields: readonly string[];\n readonly archiving: {\n readonly tasks: 'all' | readonly string[];\n readonly dispositions: readonly string[];\n readonly banner: readonly string[];\n readonly rewriteLinks: boolean;\n readonly freeze: boolean;\n readonly base: string | null;\n };\n readonly rules: Readonly<Record<string, SeveritySetting>>;\n readonly plugins: readonly PluginReference[];\n}\n\nexport const CONFIG_FILES: readonly string[] = ['.spec-brief.json', 'spec-brief.json'];\n\n/** The holes a banner line may use. */\nexport const BANNER_PLACEHOLDERS: readonly string[] = [\n 'date',\n 'summary',\n 'pr',\n 'commit',\n 'diffstat',\n 'links',\n 'id',\n 'title',\n 'author',\n];\n\nexport const SCHEMA_URL = 'https://raw.githubusercontent.com/DescentVTT/spec-brief/main/schema.json';\n\n/**\n * The `$schema` `init` writes, the path the README recommends: the schema of\n * the version installed, which is the one that loads the file. `SCHEMA_URL`\n * follows main, and would flag a key the installed version accepts, or pass\n * one it refuses, as soon as the two differ.\n */\nexport const SCHEMA_PATH = './node_modules/@descent-vtt/spec-brief/schema.json';\n\nconst SEVERITY: Schema = { type: 'string', enum: ['off', 'note', 'warning', 'error'] };\nconst STRINGS: Schema = { type: 'array', items: { type: 'string', minLength: 1 } };\n\nconst SECTION: Schema = {\n type: 'anyOf',\n description: 'A section name, or a section with aliases and content rules.',\n options: [\n { type: 'string', minLength: 1 },\n {\n type: 'object',\n required: ['name'],\n properties: {\n name: { type: 'string', minLength: 1, description: 'The heading text, compared without case or punctuation.' },\n aliases: { ...STRINGS, description: 'Other headings that fill this section.' },\n mustContain: { ...STRINGS, description: 'Literal text the section must contain.' },\n checklist: { type: 'boolean', description: 'The section must hold at least one \"- [ ]\" task item.' },\n optional: { type: 'boolean', description: 'Checked when present, not required.' },\n hint: {\n type: 'string',\n minLength: 1,\n description: 'What the section must answer: a comment under the heading in a new brief, and the hint of a finding that it is missing or unwritten.',\n },\n },\n },\n ],\n};\n\nexport const CONFIG_SCHEMA: Schema = {\n type: 'object',\n properties: {\n $schema: { type: 'string' },\n briefs: { type: 'string', minLength: 1, description: 'Directory of live briefs, relative to this file.' },\n archive: { type: 'string', minLength: 1, description: 'Directory of archived briefs, relative to this file.' },\n files: { type: 'string', minLength: 1, description: 'Glob a file name must match to be a brief.' },\n exclude: { ...STRINGS, description: 'File-name globs that are never briefs.' },\n template: { type: 'string', nullable: true, description: 'Template file for \"new\"; null builds one from the sections.' },\n id: {\n type: 'object',\n properties: {\n source: { type: 'string', enum: ['filename', 'frontmatter'], description: 'Where a brief id comes from.' },\n separator: { type: 'string', minLength: 1, description: 'Separates the id from the slug in a file name.' },\n digits: { type: 'integer', minimum: 1, maximum: 12, description: 'Width of an allocated numeric id.' },\n },\n },\n status: {\n type: 'object',\n properties: {\n field: { type: 'string', nullable: true, description: 'Front-matter key holding the status; null uses location only.' },\n draft: { type: 'string', nullable: true, description: 'The word for a brief still being written, or null.' },\n active: { type: 'string', minLength: 1, description: 'The word for a live brief.' },\n deferred: {\n type: 'string',\n nullable: true,\n description: 'The word for a live brief put off until the event its \"trigger\" names, or null. A deferred brief is never ready and runs in no wave.',\n },\n archived: { type: 'string', minLength: 1, description: 'The word for an archived brief.' },\n },\n },\n sections: { type: 'array', items: SECTION, description: 'Sections every live brief carries.' },\n sectionOrder: { type: 'boolean', description: 'Sections must appear in the order listed.' },\n types: {\n type: 'map',\n description: 'Brief types, each with the sections it adds.',\n values: { type: 'object', properties: { sections: { type: 'array', items: SECTION } } },\n },\n placeholders: { ...STRINGS, description: 'Words that mark a section as unwritten.' },\n fields: { ...STRINGS, description: 'Front-matter keys this repository uses beyond the built-in ones.' },\n archiving: {\n type: 'object',\n properties: {\n tasks: {\n type: 'anyOf',\n description: '\"all\", or the sections whose task items must be closed before archiving.',\n options: [{ type: 'string', enum: ['all'] }, STRINGS],\n },\n dispositions: { ...STRINGS, description: 'Text under an open box that closes it without a tick.' },\n banner: {\n type: 'array',\n items: { type: 'string' },\n description: 'Lines of the frozen banner; a line with an empty {placeholder} is left out, and an empty line separates paragraphs.',\n },\n rewriteLinks: { type: 'boolean', description: 'Rewrite relative links so they resolve from the new directory.' },\n freeze: { type: 'boolean', description: 'Record a content hash so later edits are caught.' },\n base: { type: 'string', nullable: true, description: 'Branch the diff is measured from, such as \"main\".' },\n },\n },\n rules: { type: 'map', values: SEVERITY, description: 'Severity per rule id.' },\n plugins: {\n type: 'array',\n description: 'Modules that contribute rules.',\n items: {\n type: 'anyOf',\n options: [\n { type: 'string', minLength: 1 },\n {\n type: 'object',\n required: ['module'],\n properties: { module: { type: 'string', minLength: 1 }, options: { type: 'any' } },\n },\n ],\n },\n },\n },\n};\n\nfunction section(name: string, extra: Partial<Omit<SectionRule, 'name'>> = {}): SectionRule {\n return { name, aliases: [], mustContain: [], checklist: false, optional: false, ...extra };\n}\n\nexport const DEFAULT_CONFIG: Config = {\n briefs: 'briefs',\n archive: 'briefs/archive',\n files: '[0-9]*.md',\n exclude: [],\n template: null,\n id: { source: 'filename', separator: '_', digits: 3 },\n status: { field: 'status', draft: 'draft', active: 'active', deferred: 'deferred', archived: 'archived' },\n sections: [\n section('Intent', {\n aliases: [\"Commander's Intent\", 'Mission', 'Objective'],\n hint: 'The state of the tree when this round is done, and why it matters. One paragraph.',\n }),\n section('Negative Scope', {\n aliases: ['Out of Scope', 'Non-Goals', 'Not in Scope', 'What this round is NOT', 'What this brief does NOT do'],\n hint: 'What this round must not do, even where it would look helpful.',\n }),\n section('Not Empowered', {\n aliases: ['Non-Empowerment', 'Non-Empowerment List'],\n optional: true,\n hint: 'Files, interfaces and decisions this round may not change.',\n }),\n section('Invariants', {\n aliases: ['Invariant Checklist', 'Definition of Done'],\n checklist: true,\n hint: 'Checks that must hold before the round is called done, each one a task item.',\n }),\n ],\n sectionOrder: false,\n types: {\n feature: [section('Acceptance Criteria', { checklist: true, hint: 'What a reviewer checks to accept the result, each one a task item.' })],\n defect: [\n section('The Defect, Measured', {\n aliases: ['Reproduction'],\n hint: 'How to reproduce the defect, and the measurement that shows it.',\n }),\n ],\n refactor: [],\n chore: [],\n },\n placeholders: ['TBD', 'TBA', 'TODO', 'FIXME', 'XXX', '???', '...', '\\u2026'],\n fields: [],\n archiving: {\n tasks: 'all',\n dispositions: ['**Delegated', '**Accepted debt', '**Rejected'],\n banner: [\n '**Archived {date}.**',\n '{summary}',\n 'Merged in pull request {pr}.',\n 'Recorded at commit `{commit}`: {diffstat}.',\n '{links}',\n 'The body below describes the tree before execution and is not maintained.',\n ],\n rewriteLinks: true,\n freeze: true,\n base: null,\n },\n rules: {},\n plugins: [],\n};\n\ntype Raw = Record<string, unknown>;\n\nfunction sectionFrom(raw: unknown): SectionRule {\n if (typeof raw === 'string') return section(raw);\n const r = raw as Raw;\n return section(r['name'] as string, {\n aliases: (r['aliases'] as string[] | undefined) ?? [],\n mustContain: (r['mustContain'] as string[] | undefined) ?? [],\n checklist: (r['checklist'] as boolean | undefined) ?? false,\n optional: (r['optional'] as boolean | undefined) ?? false,\n hint: r['hint'] as string | undefined,\n });\n}\n\nfunction pluginFrom(raw: unknown): PluginReference {\n if (typeof raw === 'string') return { module: raw, options: undefined };\n const r = raw as Raw;\n return { module: r['module'] as string, options: r['options'] };\n}\n\nexport class ConfigError extends Error {\n readonly problems: readonly string[];\n\n constructor(file: string, problems: readonly string[]) {\n super(`${file}: ${problems.join('; ')}`);\n this.name = 'ConfigError';\n this.problems = problems;\n }\n}\n\n/**\n * Builds a configuration from parsed JSON. Objects merge one level deep over\n * the defaults; lists and `types` replace them, because a repository that\n * names its own sections means those sections and not the defaults as well.\n */\nexport function resolveConfig(raw: unknown, file = 'configuration'): Config {\n const problems = validate(CONFIG_SCHEMA, raw);\n if (problems.length > 0) throw new ConfigError(file, problems);\n const r = raw as Raw;\n const d = DEFAULT_CONFIG;\n const merged = <T extends object>(key: string, base: T): T => ({ ...base, ...((r[key] as Partial<T>) ?? {}) });\n const archiving = merged('archiving', d.archiving);\n const config: Config = {\n briefs: (r['briefs'] as string | undefined) ?? d.briefs,\n archive: (r['archive'] as string | undefined) ?? (r['briefs'] === undefined ? d.archive : `${r['briefs'] as string}/archive`),\n files: (r['files'] as string | undefined) ?? d.files,\n exclude: (r['exclude'] as string[] | undefined) ?? d.exclude,\n template: r['template'] === undefined ? d.template : (r['template'] as string | null),\n id: merged('id', d.id),\n status: merged('status', d.status),\n sections: r['sections'] === undefined ? d.sections : (r['sections'] as unknown[]).map(sectionFrom),\n sectionOrder: (r['sectionOrder'] as boolean | undefined) ?? d.sectionOrder,\n types:\n r['types'] === undefined\n ? d.types\n : Object.fromEntries(\n Object.entries(r['types'] as Record<string, Raw>).map(([name, type]) => [\n name,\n ((type['sections'] as unknown[] | undefined) ?? []).map(sectionFrom),\n ]),\n ),\n placeholders: (r['placeholders'] as string[] | undefined) ?? d.placeholders,\n fields: (r['fields'] as string[] | undefined) ?? d.fields,\n archiving,\n rules: { ...d.rules, ...((r['rules'] as Record<string, SeveritySetting> | undefined) ?? {}) },\n plugins: ((r['plugins'] as unknown[] | undefined) ?? []).map(pluginFrom),\n };\n const semantic = checkConfig(config);\n if (semantic.length > 0) throw new ConfigError(file, semantic);\n return config;\n}\n\n/** The status words a repository uses, in lifecycle order. */\nexport function statusWords(config: Config): string[] {\n const { draft, active, deferred, archived } = config.status;\n return [draft, active, deferred, archived].filter((w) => w !== null);\n}\n\n/** What the schema cannot say: relationships between values. */\nfunction checkConfig(config: Config): string[] {\n const problems: string[] = [];\n const inside = (key: string, path: string): string | null => {\n try {\n return normalisePath(path);\n } catch {\n problems.push(`\"${key}\" must be a directory inside the repository, not \"${path}\"`);\n return null;\n }\n };\n const briefs = inside('briefs', config.briefs);\n const archive = inside('archive', config.archive);\n if (briefs !== null && briefs === archive) problems.push('\"briefs\" and \"archive\" must be different directories');\n // Named by the statuses that share a word: a 0.1 configuration that spelt\n // another status \"deferred\" meets the default for the new one here.\n const sharing = new Map<string, { word: string; keys: string[] }>();\n for (const key of ['draft', 'active', 'deferred', 'archived'] as const) {\n const word = config.status[key];\n if (word === null) continue;\n const group = sharing.get(word.toLowerCase()) ?? { word, keys: [] };\n group.keys.push(key);\n sharing.set(word.toLowerCase(), group);\n }\n for (const { word, keys } of sharing.values()) {\n if (keys.length < 2) continue;\n const orNull = keys.includes('deferred') ? ', or set \"status.deferred\" to null where no work is deferred' : '';\n problems.push(`the status words must differ: \"${word}\" is the word for ${inWords(keys)}; give ${keys.length === 2 ? 'one of them' : 'all but one'} another word${orNull}`);\n }\n // A pattern that does not parse would match nothing, and a run over no briefs reads as clean.\n for (const [key, pattern] of [['files', config.files], ...config.exclude.map((e) => ['exclude', e] as const)] as const) {\n const parsed = parseGlob(pattern);\n if (!parsed.ok) problems.push(`\"${key}\" pattern \"${pattern}\": ${parsed.error}`);\n }\n // An unknown hole is never filled, and a line with an unfilled hole is left\n // out: a misspelt placeholder would silently drop its whole line.\n for (const line of config.archiving.banner) {\n for (const hole of templateHoles(line)) {\n if (!BANNER_PLACEHOLDERS.includes(hole)) {\n problems.push(`\"archiving.banner\" uses {${hole}}; the placeholders are ${BANNER_PLACEHOLDERS.map((p) => `{${p}}`).join(', ')}`);\n }\n }\n }\n return problems;\n}\n\n/** Parses the text of a configuration file. */\nexport function parseConfig(text: string, file: string): Config {\n let raw: unknown;\n try {\n raw = JSON.parse(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);\n } catch (error) {\n throw new ConfigError(file, [`is not valid JSON (${(error as Error).message})`]);\n }\n return resolveConfig(raw, file);\n}\n\n/**\n * The configuration file for a directory: the nearest one at or above it.\n * `exists` is injected so discovery needs no filesystem of its own.\n */\nexport async function locateConfig(\n start: string,\n exists: (path: string) => Promise<boolean>,\n): Promise<string | undefined> {\n let directory = start;\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 found: string[] = [];\n for (const name of CONFIG_FILES) {\n const candidate = join(directory, name);\n if (await exists(candidate)) found.push(candidate);\n }\n if (found.length > 1) {\n throw new ConfigError(directory, [`holds both ${CONFIG_FILES.join(' and ')}; keep one`]);\n }\n if (found[0] !== undefined) return found[0];\n const parent = dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n /* v8 ignore next -- no path is 256 directories deep; the bound exists so the loop ends by construction. */\n return undefined;\n}\n\n/** The JSON Schema published as `schema.json`. */\nexport function configJsonSchema(): Record<string, unknown> {\n return {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n $id: SCHEMA_URL,\n title: 'spec-brief configuration',\n ...toJsonSchema(CONFIG_SCHEMA),\n };\n}\n\n/** The configuration `init` writes: every default spelled out, so it can be edited rather than looked up. */\nexport function initialConfig(briefs: string, archive: string): Record<string, unknown> {\n const d = DEFAULT_CONFIG;\n const sectionJson = (s: SectionRule): unknown => {\n const out: Record<string, unknown> = { name: s.name };\n if (s.aliases.length > 0) out['aliases'] = s.aliases;\n if (s.mustContain.length > 0) out['mustContain'] = s.mustContain;\n if (s.checklist) out['checklist'] = true;\n if (s.optional) out['optional'] = true;\n if (s.hint !== undefined) out['hint'] = s.hint;\n return Object.keys(out).length === 1 ? s.name : out;\n };\n return {\n $schema: SCHEMA_PATH,\n briefs,\n archive,\n files: d.files,\n id: d.id,\n status: d.status,\n sections: d.sections.map(sectionJson),\n types: Object.fromEntries(Object.entries(d.types).map(([k, v]) => [k, { sections: v.map(sectionJson) }])),\n archiving: {\n tasks: d.archiving.tasks,\n dispositions: d.archiving.dispositions,\n banner: d.archiving.banner,\n base: d.archiving.base,\n },\n };\n}\n"]}
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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","sourcesContent":["/**\n * Configuration: what it may say, what it says when it says nothing, and how a\n * file becomes a `Config`.\n *\n * Every repository that already keeps briefs keeps them its own way - where\n * they live, what the sections are called, which word means \"done\" - so the\n * conventions are data here rather than code. The defaults describe a brief\n * with the four parts every round needs: an intent, a negative scope, what the\n * round is not empowered to touch, and the invariants that prove it is done.\n *\n * A configuration that does not load stops the run. A typo that silently\n * falls back to defaults produces a clean-looking report about the wrong\n * rules, which is worse than no report.\n */\n\nimport { dirname, join } from 'node:path';\n\nimport { parseGlob } from './glob.js';\nimport { normalisePath } from './links.js';\nimport { type Schema, toJsonSchema, validate } from './schema.js';\nimport { inWords, templateHoles } from './text.js';\nimport type { SeveritySetting } from './types.js';\n\nexport interface SectionRule {\n readonly name: string;\n readonly aliases: readonly string[];\n /** Literal text the section must contain, compared exactly. */\n readonly mustContain: readonly string[];\n /** The section must hold at least one task item. */\n readonly checklist: boolean;\n readonly optional: boolean;\n /**\n * What the section must answer. A new brief carries it as a comment under\n * the heading, a finding that the section is missing or unwritten carries it\n * as its hint, and `list` and `lint` report it, so a tool that helps write a\n * brief can ask for each section without knowing its name in advance.\n */\n readonly hint?: string | undefined;\n}\n\nexport interface PluginReference {\n readonly module: string;\n readonly options: unknown;\n}\n\nexport interface Config {\n /** Directory of live briefs, relative to the root. */\n readonly briefs: string;\n /** Directory of archived briefs, relative to the root. */\n readonly archive: string;\n /** Glob a file name must match to be a brief. */\n readonly files: string;\n /** File-name globs that are never briefs, such as an index. */\n readonly exclude: readonly string[];\n /** A template for `new`, relative to the root; `null` builds one from `sections`. */\n readonly template: string | null;\n readonly id: {\n readonly source: 'filename' | 'frontmatter';\n readonly separator: string;\n readonly digits: number;\n };\n readonly status: {\n readonly field: string | null;\n readonly draft: string | null;\n readonly active: string;\n /** The word for work put off until an event its `trigger` names; `null` when a repository has none. */\n readonly deferred: string | null;\n readonly archived: string;\n };\n readonly sections: readonly SectionRule[];\n readonly sectionOrder: boolean;\n readonly types: Readonly<Record<string, readonly SectionRule[]>>;\n readonly placeholders: readonly string[];\n readonly fields: readonly string[];\n readonly archiving: {\n readonly tasks: 'all' | readonly string[];\n readonly dispositions: readonly string[];\n readonly banner: readonly string[];\n readonly rewriteLinks: boolean;\n readonly freeze: boolean;\n readonly base: string | null;\n };\n readonly rules: Readonly<Record<string, SeveritySetting>>;\n readonly plugins: readonly PluginReference[];\n}\n\nexport const CONFIG_FILES: readonly string[] = ['.spec-brief.json', 'spec-brief.json'];\n\n/** The holes a banner line may use. */\nexport const BANNER_PLACEHOLDERS: readonly string[] = [\n 'date',\n 'summary',\n 'pr',\n 'commit',\n 'diffstat',\n 'links',\n 'id',\n 'title',\n 'author',\n];\n\nexport const SCHEMA_URL = 'https://raw.githubusercontent.com/DescentVTT/spec-brief/main/schema.json';\n\n/**\n * The `$schema` `init` writes, the path the README recommends: the schema of\n * the version installed, which is the one that loads the file. `SCHEMA_URL`\n * follows main, and would flag a key the installed version accepts, or pass\n * one it refuses, as soon as the two differ.\n */\nexport const SCHEMA_PATH = './node_modules/@descent-vtt/spec-brief/schema.json';\n\nconst SEVERITY: Schema = { type: 'string', enum: ['off', 'note', 'warning', 'error'] };\nconst STRINGS: Schema = { type: 'array', items: { type: 'string', minLength: 1 } };\n\nconst SECTION: Schema = {\n type: 'anyOf',\n description: 'A section name, or a section with aliases and content rules.',\n options: [\n { type: 'string', minLength: 1 },\n {\n type: 'object',\n required: ['name'],\n properties: {\n name: { type: 'string', minLength: 1, description: 'The heading text, compared without case or punctuation.' },\n aliases: { ...STRINGS, description: 'Other headings that fill this section.' },\n mustContain: { ...STRINGS, description: 'Literal text the section must contain.' },\n checklist: { type: 'boolean', description: 'The section must hold at least one \"- [ ]\" task item.' },\n optional: { type: 'boolean', description: 'Checked when present, not required.' },\n hint: {\n type: 'string',\n minLength: 1,\n description: 'What the section must answer: a comment under the heading in a new brief, and the hint of a finding that it is missing or unwritten.',\n },\n },\n },\n ],\n};\n\nexport const CONFIG_SCHEMA: Schema = {\n type: 'object',\n properties: {\n $schema: { type: 'string' },\n briefs: { type: 'string', minLength: 1, description: 'Directory of live briefs, relative to this file.' },\n archive: { type: 'string', minLength: 1, description: 'Directory of archived briefs, relative to this file.' },\n files: { type: 'string', minLength: 1, description: 'Glob a file name must match to be a brief.' },\n exclude: { ...STRINGS, description: 'File-name globs that are never briefs.' },\n template: { type: 'string', nullable: true, description: 'Template file for \"new\"; null builds one from the sections.' },\n id: {\n type: 'object',\n properties: {\n source: { type: 'string', enum: ['filename', 'frontmatter'], description: 'Where a brief id comes from.' },\n separator: { type: 'string', minLength: 1, description: 'Separates the id from the slug in a file name.' },\n digits: { type: 'integer', minimum: 1, maximum: 12, description: 'Width of an allocated numeric id.' },\n },\n },\n status: {\n type: 'object',\n properties: {\n field: { type: 'string', nullable: true, description: 'Front-matter key holding the status; null uses location only.' },\n draft: { type: 'string', nullable: true, description: 'The word for a brief still being written, or null.' },\n active: { type: 'string', minLength: 1, description: 'The word for a live brief.' },\n deferred: {\n type: 'string',\n nullable: true,\n description: 'The word for a live brief put off until the event its \"trigger\" names, or null. A deferred brief is never ready and runs in no wave.',\n },\n archived: { type: 'string', minLength: 1, description: 'The word for an archived brief.' },\n },\n },\n sections: { type: 'array', items: SECTION, description: 'Sections every live brief carries.' },\n sectionOrder: { type: 'boolean', description: 'Sections must appear in the order listed.' },\n types: {\n type: 'map',\n description: 'Brief types, each with the sections it adds.',\n values: { type: 'object', properties: { sections: { type: 'array', items: SECTION } } },\n },\n placeholders: { ...STRINGS, description: 'Words that mark a section as unwritten.' },\n fields: { ...STRINGS, description: 'Front-matter keys this repository uses beyond the built-in ones.' },\n archiving: {\n type: 'object',\n properties: {\n tasks: {\n type: 'anyOf',\n description: '\"all\", or the sections whose task items must be closed before archiving.',\n options: [{ type: 'string', enum: ['all'] }, STRINGS],\n },\n dispositions: { ...STRINGS, description: 'Text under an open box that closes it without a tick.' },\n banner: {\n type: 'array',\n items: { type: 'string' },\n description: 'Lines of the frozen banner; a line with an empty {placeholder} is left out, and an empty line separates paragraphs.',\n },\n rewriteLinks: { type: 'boolean', description: 'Rewrite relative links so they resolve from the new directory.' },\n freeze: { type: 'boolean', description: 'Record a content hash so later edits are caught.' },\n base: { type: 'string', nullable: true, description: 'Branch the diff is measured from, such as \"main\".' },\n },\n },\n rules: { type: 'map', values: SEVERITY, description: 'Severity per rule id.' },\n plugins: {\n type: 'array',\n description: 'Modules that contribute rules.',\n items: {\n type: 'anyOf',\n options: [\n { type: 'string', minLength: 1 },\n {\n type: 'object',\n required: ['module'],\n properties: { module: { type: 'string', minLength: 1 }, options: { type: 'any' } },\n },\n ],\n },\n },\n },\n};\n\nfunction section(name: string, extra: Partial<Omit<SectionRule, 'name'>> = {}): SectionRule {\n return { name, aliases: [], mustContain: [], checklist: false, optional: false, ...extra };\n}\n\nexport const DEFAULT_CONFIG: Config = {\n briefs: 'briefs',\n archive: 'briefs/archive',\n files: '[0-9]*.md',\n exclude: [],\n template: null,\n id: { source: 'filename', separator: '_', digits: 3 },\n status: { field: 'status', draft: 'draft', active: 'active', deferred: 'deferred', archived: 'archived' },\n sections: [\n section('Intent', {\n aliases: [\"Commander's Intent\", 'Mission', 'Objective'],\n hint: 'The state of the tree when this round is done, and why it matters. One paragraph.',\n }),\n section('Negative Scope', {\n aliases: ['Out of Scope', 'Non-Goals', 'Not in Scope', 'What this round is NOT', 'What this brief does NOT do'],\n hint: 'What this round must not do, even where it would look helpful.',\n }),\n section('Not Empowered', {\n aliases: ['Non-Empowerment', 'Non-Empowerment List'],\n optional: true,\n hint: 'Files, interfaces and decisions this round may not change.',\n }),\n section('Invariants', {\n aliases: ['Invariant Checklist', 'Definition of Done'],\n checklist: true,\n hint: 'Checks that must hold before the round is called done, each one a task item.',\n }),\n ],\n sectionOrder: false,\n types: {\n feature: [section('Acceptance Criteria', { checklist: true, hint: 'What a reviewer checks to accept the result, each one a task item.' })],\n defect: [\n section('The Defect, Measured', {\n aliases: ['Reproduction'],\n hint: 'How to reproduce the defect, and the measurement that shows it.',\n }),\n ],\n refactor: [],\n chore: [],\n },\n // To be decided, undecided, to be filled in, to be confirmed: Traditional, then Simplified where it differs.\n placeholders: ['TBD', 'TBA', 'TODO', 'FIXME', 'XXX', '???', '...', '\\u2026', '待定', '未定', '待補', '待补', '待確認', '待确认'],\n fields: [],\n archiving: {\n tasks: 'all',\n dispositions: ['**Delegated', '**Accepted debt', '**Rejected'],\n banner: [\n '**Archived {date}.**',\n '{summary}',\n 'Merged in pull request {pr}.',\n 'Recorded at commit `{commit}`: {diffstat}.',\n '{links}',\n 'The body below describes the tree before execution and is not maintained.',\n ],\n rewriteLinks: true,\n freeze: true,\n base: null,\n },\n rules: {},\n plugins: [],\n};\n\ntype Raw = Record<string, unknown>;\n\nfunction sectionFrom(raw: unknown): SectionRule {\n if (typeof raw === 'string') return section(raw);\n const r = raw as Raw;\n return section(r['name'] as string, {\n aliases: (r['aliases'] as string[] | undefined) ?? [],\n mustContain: (r['mustContain'] as string[] | undefined) ?? [],\n checklist: (r['checklist'] as boolean | undefined) ?? false,\n optional: (r['optional'] as boolean | undefined) ?? false,\n hint: r['hint'] as string | undefined,\n });\n}\n\nfunction pluginFrom(raw: unknown): PluginReference {\n if (typeof raw === 'string') return { module: raw, options: undefined };\n const r = raw as Raw;\n return { module: r['module'] as string, options: r['options'] };\n}\n\nexport class ConfigError extends Error {\n readonly problems: readonly string[];\n\n constructor(file: string, problems: readonly string[]) {\n super(`${file}: ${problems.join('; ')}`);\n this.name = 'ConfigError';\n this.problems = problems;\n }\n}\n\n/**\n * Builds a configuration from parsed JSON. Objects merge one level deep over\n * the defaults; lists and `types` replace them, because a repository that\n * names its own sections means those sections and not the defaults as well.\n */\nexport function resolveConfig(raw: unknown, file = 'configuration'): Config {\n const problems = validate(CONFIG_SCHEMA, raw);\n if (problems.length > 0) throw new ConfigError(file, problems);\n const r = raw as Raw;\n const d = DEFAULT_CONFIG;\n const merged = <T extends object>(key: string, base: T): T => ({ ...base, ...((r[key] as Partial<T>) ?? {}) });\n const archiving = merged('archiving', d.archiving);\n const config: Config = {\n briefs: (r['briefs'] as string | undefined) ?? d.briefs,\n archive: (r['archive'] as string | undefined) ?? (r['briefs'] === undefined ? d.archive : `${r['briefs'] as string}/archive`),\n files: (r['files'] as string | undefined) ?? d.files,\n exclude: (r['exclude'] as string[] | undefined) ?? d.exclude,\n template: r['template'] === undefined ? d.template : (r['template'] as string | null),\n id: merged('id', d.id),\n status: merged('status', d.status),\n sections: r['sections'] === undefined ? d.sections : (r['sections'] as unknown[]).map(sectionFrom),\n sectionOrder: (r['sectionOrder'] as boolean | undefined) ?? d.sectionOrder,\n types:\n r['types'] === undefined\n ? d.types\n : Object.fromEntries(\n Object.entries(r['types'] as Record<string, Raw>).map(([name, type]) => [\n name,\n ((type['sections'] as unknown[] | undefined) ?? []).map(sectionFrom),\n ]),\n ),\n placeholders: (r['placeholders'] as string[] | undefined) ?? d.placeholders,\n fields: (r['fields'] as string[] | undefined) ?? d.fields,\n archiving,\n rules: { ...d.rules, ...((r['rules'] as Record<string, SeveritySetting> | undefined) ?? {}) },\n plugins: ((r['plugins'] as unknown[] | undefined) ?? []).map(pluginFrom),\n };\n const semantic = checkConfig(config);\n if (semantic.length > 0) throw new ConfigError(file, semantic);\n return config;\n}\n\n/** The status words a repository uses, in lifecycle order. */\nexport function statusWords(config: Config): string[] {\n const { draft, active, deferred, archived } = config.status;\n return [draft, active, deferred, archived].filter((w) => w !== null);\n}\n\n/** What the schema cannot say: relationships between values. */\nfunction checkConfig(config: Config): string[] {\n const problems: string[] = [];\n const inside = (key: string, path: string): string | null => {\n try {\n return normalisePath(path);\n } catch {\n problems.push(`\"${key}\" must be a directory inside the repository, not \"${path}\"`);\n return null;\n }\n };\n const briefs = inside('briefs', config.briefs);\n const archive = inside('archive', config.archive);\n if (briefs !== null && briefs === archive) problems.push('\"briefs\" and \"archive\" must be different directories');\n // Named by the statuses that share a word: a 0.1 configuration that spelt\n // another status \"deferred\" meets the default for the new one here.\n const sharing = new Map<string, { word: string; keys: string[] }>();\n for (const key of ['draft', 'active', 'deferred', 'archived'] as const) {\n const word = config.status[key];\n if (word === null) continue;\n const group = sharing.get(word.toLowerCase()) ?? { word, keys: [] };\n group.keys.push(key);\n sharing.set(word.toLowerCase(), group);\n }\n for (const { word, keys } of sharing.values()) {\n if (keys.length < 2) continue;\n const orNull = keys.includes('deferred') ? ', or set \"status.deferred\" to null where no work is deferred' : '';\n problems.push(`the status words must differ: \"${word}\" is the word for ${inWords(keys)}; give ${keys.length === 2 ? 'one of them' : 'all but one'} another word${orNull}`);\n }\n // A pattern that does not parse would match nothing, and a run over no briefs reads as clean.\n for (const [key, pattern] of [['files', config.files], ...config.exclude.map((e) => ['exclude', e] as const)] as const) {\n const parsed = parseGlob(pattern);\n if (!parsed.ok) problems.push(`\"${key}\" pattern \"${pattern}\": ${parsed.error}`);\n }\n // An unknown hole is never filled, and a line with an unfilled hole is left\n // out: a misspelt placeholder would silently drop its whole line.\n for (const line of config.archiving.banner) {\n for (const hole of templateHoles(line)) {\n if (!BANNER_PLACEHOLDERS.includes(hole)) {\n problems.push(`\"archiving.banner\" uses {${hole}}; the placeholders are ${BANNER_PLACEHOLDERS.map((p) => `{${p}}`).join(', ')}`);\n }\n }\n }\n return problems;\n}\n\n/** Parses the text of a configuration file. */\nexport function parseConfig(text: string, file: string): Config {\n let raw: unknown;\n try {\n raw = JSON.parse(text.charCodeAt(0) === 0xfeff ? text.slice(1) : text);\n } catch (error) {\n throw new ConfigError(file, [`is not valid JSON (${(error as Error).message})`]);\n }\n return resolveConfig(raw, file);\n}\n\n/**\n * The configuration file for a directory: the nearest one at or above it.\n * `exists` is injected so discovery needs no filesystem of its own.\n */\nexport async function locateConfig(\n start: string,\n exists: (path: string) => Promise<boolean>,\n): Promise<string | undefined> {\n let directory = start;\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 found: string[] = [];\n for (const name of CONFIG_FILES) {\n const candidate = join(directory, name);\n if (await exists(candidate)) found.push(candidate);\n }\n if (found.length > 1) {\n throw new ConfigError(directory, [`holds both ${CONFIG_FILES.join(' and ')}; keep one`]);\n }\n if (found[0] !== undefined) return found[0];\n const parent = dirname(directory);\n if (parent === directory) return undefined;\n directory = parent;\n }\n /* v8 ignore next -- no path is 256 directories deep; the bound exists so the loop ends by construction. */\n return undefined;\n}\n\n/** The JSON Schema published as `schema.json`. */\nexport function configJsonSchema(): Record<string, unknown> {\n return {\n $schema: 'https://json-schema.org/draft/2020-12/schema',\n $id: SCHEMA_URL,\n title: 'spec-brief configuration',\n ...toJsonSchema(CONFIG_SCHEMA),\n };\n}\n\n/** The configuration `init` writes: every default spelled out, so it can be edited rather than looked up. */\nexport function initialConfig(briefs: string, archive: string): Record<string, unknown> {\n const d = DEFAULT_CONFIG;\n const sectionJson = (s: SectionRule): unknown => {\n const out: Record<string, unknown> = { name: s.name };\n if (s.aliases.length > 0) out['aliases'] = s.aliases;\n if (s.mustContain.length > 0) out['mustContain'] = s.mustContain;\n if (s.checklist) out['checklist'] = true;\n if (s.optional) out['optional'] = true;\n if (s.hint !== undefined) out['hint'] = s.hint;\n return Object.keys(out).length === 1 ? s.name : out;\n };\n return {\n $schema: SCHEMA_PATH,\n briefs,\n archive,\n files: d.files,\n id: d.id,\n status: d.status,\n sections: d.sections.map(sectionJson),\n types: Object.fromEntries(Object.entries(d.types).map(([k, v]) => [k, { sections: v.map(sectionJson) }])),\n archiving: {\n tasks: d.archiving.tasks,\n dispositions: d.archiving.dispositions,\n banner: d.archiving.banner,\n base: d.archiving.base,\n },\n };\n}\n"]}
package/dist/corpus.d.ts CHANGED
@@ -59,3 +59,8 @@ export declare function waitingOnDeferred(corpus: Corpus): Waiting[];
59
59
  * component is reported once, starting from its first brief by path.
60
60
  */
61
61
  export declare function dependencyCycles(corpus: Corpus): Brief[][];
62
+ /**
63
+ * A cycle as a finding's subject: the briefs on it, each once, in order. `lint`
64
+ * and `schedule` word a cycle differently and report it as one problem.
65
+ */
66
+ export declare function cycleSubject(cycle: readonly Brief[]): string;
package/dist/corpus.js CHANGED
@@ -176,6 +176,13 @@ export function dependencyCycles(corpus) {
176
176
  return cyclePath(start, members, edges);
177
177
  });
178
178
  }
179
+ /**
180
+ * A cycle as a finding's subject: the briefs on it, each once, in order. `lint`
181
+ * and `schedule` word a cycle differently and report it as one problem.
182
+ */
183
+ export function cycleSubject(cycle) {
184
+ return [...new Set(cycle.map((b) => b.id ?? b.name))].sort().join(', ');
185
+ }
179
186
  /** A path from `start` back to itself inside one component, found breadth-first. */
180
187
  function cyclePath(start, members, edges) {
181
188
  const previous = new Map();