mirror of
https://github.com/garrytan/gstack.git
synced 2026-11-03 15:27:56 +01:00
Unmarked Markdown that no test depends on is a docs/no-tests empty lane. A file a test reads, including a fixture, still selects that test through the import graph. Unmapped source and unreferenced test-tree files still fail closed. Co-authored-by: Nick <surlymo@apache.org>
60 lines
2.6 KiB
TypeScript
60 lines
2.6 KiB
TypeScript
/**
|
|
* pregate docs/no-tests — Markdown no test depends on is an empty lane.
|
|
*
|
|
* A repo with no `.gstack/pregate.json` used to fail `lanes` on a tracked
|
|
* `.work` plan, a redproof note, or any other Markdown file (`PREGATE_NO_LANE`).
|
|
* Those files document a change; they are not test subjects. `isDocsEmptyLane`
|
|
* is that class. `lane-selection` consults it only when the import graph
|
|
* mapped nothing (`testsFor`: imports, repo-path literals including `join()`,
|
|
* the bin convention, declarations), so a test that reads the file — a
|
|
* fixture or a doc — still runs. Source code and anything under a test
|
|
* directory never qualify, including when `empty_lanes` globs match them.
|
|
* Unmapped code stays `PREGATE_NO_LANE`.
|
|
*/
|
|
import { SOURCE_EXT } from './import-graph';
|
|
import { matchesAny } from '../ship-policy';
|
|
|
|
const TEST_TREE = /(?:^|\/)(?:test|tests|spec|__tests__)(?:\/|$)/i;
|
|
const MARKDOWN = /\.(?:md|markdown)$/i;
|
|
/** Prose names, with or without `.md` (LICENSE has no extension). */
|
|
const PROSE_NAME = /^(?:README|CHANGELOG|CONTRIBUTING|AGENTS|CLAUDE|ETHOS|LICENSE|LICENCE|COPYING|NOTICE)(?:\.md)?$/i;
|
|
|
|
function isMarkdown(rel: string): boolean {
|
|
return MARKDOWN.test(rel);
|
|
}
|
|
|
|
function isTestTree(rel: string): boolean {
|
|
return TEST_TREE.test(rel);
|
|
}
|
|
|
|
/** Code the empty-lane class must not swallow. Extensionless `bin/` entrypoints count; `bin/README.md` does not. */
|
|
function isSourceCode(rel: string): boolean {
|
|
if (SOURCE_EXT.test(rel)) return true;
|
|
const base = rel.split('/').pop() ?? rel;
|
|
if (rel.startsWith('bin/') && !isMarkdown(rel) && !PROSE_NAME.test(base)) return true;
|
|
return false;
|
|
}
|
|
|
|
function isBuiltinDocsPath(rel: string): boolean {
|
|
const base = rel.split('/').pop() ?? rel;
|
|
if (PROSE_NAME.test(base)) return true;
|
|
// Any Markdown file. Name and directory do not matter: `planet.md` and
|
|
// `prompts/system.md` qualify the same way a `.work` plan does. A test
|
|
// that reads the file is handled by the caller, before this check.
|
|
return isMarkdown(rel);
|
|
}
|
|
|
|
/**
|
|
* True when `rel` is documentation that needs no test lane.
|
|
* `extraGlobs` are the repo's `empty_lanes` (`.gstack/pregate.json` on the
|
|
* base branch). They add paths; they cannot classify source code or a file
|
|
* under a test directory. Callers apply this only after the import graph
|
|
* found no test.
|
|
*/
|
|
export function isDocsEmptyLane(rel: string, extraGlobs: readonly string[] = []): boolean {
|
|
const norm = rel.replace(/\\/g, '/').replace(/^\.\//, '');
|
|
if (!norm || isTestTree(norm) || isSourceCode(norm)) return false;
|
|
if (extraGlobs.length > 0 && matchesAny(extraGlobs, norm)) return true;
|
|
return isBuiltinDocsPath(norm);
|
|
}
|