Skip to content

Commit e621a9f

Browse files
theCodeDriftclaude
andcommitted
test(cli): exempt the two ci.txt lines where a literal invocation is correct
The source guard and the `ci.txt` prose it flags were written on separate branches and were each correct in isolation. Combined, the guard fires on two lines that are deliberately literal: - the enumeration of what `%(PACKAGE_MANAGER_DLX)s` expands to, where naming the four complete invocations IS the documentation — substituting the variable would define the placeholder in terms of itself - `pnpm taskless check`, where `taskless` is the binary pnpm resolves from the wired repo's own `node_modules/.bin`. It is a foreign binary, not this CLI's invocation, and `%(TASKLESS_CLI)s` would render it as `pnpm npx @taskless/cli check` Both are prose *about* invocations rather than an instruction to run one, which is the distinction the regex cannot draw on its own. They are exempted by content match with the reason recorded, not by line number, so an edit above them cannot move the exemption onto a different line. An allowlist nobody rechecks is how a guard quietly stops guarding, so a second test fails when an entry no longer matches a line the regex would otherwise flag. Verified by breaking an entry and watching it fail rather than by assuming it passes. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01Cyga14bww8rmazH2XrF8ms
1 parent 0e86f11 commit e621a9f

1 file changed

Lines changed: 52 additions & 1 deletion

File tree

‎packages/cli/test/recipe-cross-references.test.ts‎

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,36 @@ const HARDCODED_INVOCATION = new RegExp(
7777
String.raw`)\b)`
7878
);
7979

80+
/**
81+
* The two places a literal invocation is CORRECT, and why. Both are prose
82+
* *about* invocations rather than an instruction to run one, which is the
83+
* distinction the regex cannot draw on its own.
84+
*
85+
* Kept as content matches rather than line numbers so an edit above them does
86+
* not silently move the exemption onto a different line. If the prose changes
87+
* enough that a snippet stops matching, the staleness test below fails — which
88+
* is the intended outcome: a reworded exception deserves to be re-justified,
89+
* not silently carried forward.
90+
*/
91+
const ALLOWED_HARDCODED: { file: string; snippet: string; why: string }[] = [
92+
{
93+
file: "ci.txt",
94+
snippet: "`npx @taskless/cli`, `pnpm dlx @taskless/cli`,",
95+
why: "Enumerates what %(PACKAGE_MANAGER_DLX)s expands to. Naming the four complete invocations IS the documentation; substituting the variable here would define the placeholder in terms of itself.",
96+
},
97+
{
98+
file: "ci.txt",
99+
snippet: "`pnpm taskless check`",
100+
why: "That `taskless` is the binary pnpm resolves from the WIRED REPO's node_modules/.bin when @taskless/cli is their dev dependency — a foreign binary, not this CLI's invocation. %(TASKLESS_CLI)s would render `pnpm npx @taskless/cli check`.",
101+
},
102+
];
103+
104+
function isAllowed(file: string, line: string): boolean {
105+
return ALLOWED_HARDCODED.some(
106+
(entry) => entry.file === file && line.includes(entry.snippet)
107+
);
108+
}
109+
80110
async function recipeFiles(): Promise<string[]> {
81111
const entries = await readdir(recipeDirectory);
82112
return entries.filter((entry) => entry.endsWith(".txt")).toSorted();
@@ -180,7 +210,7 @@ describe("recipes defer the CLI invocation to the renderer", () => {
180210
for (const file of await recipeFiles()) {
181211
const source = await readFile(join(recipeDirectory, file), "utf8");
182212
for (const [index, line] of source.split("\n").entries()) {
183-
if (HARDCODED_INVOCATION.test(line)) {
213+
if (HARDCODED_INVOCATION.test(line) && !isAllowed(file, line)) {
184214
offenders.push(`${file}:${String(index + 1)}: ${line.trim()}`);
185215
}
186216
}
@@ -191,6 +221,27 @@ describe("recipes defer the CLI invocation to the renderer", () => {
191221
expect(offenders).toEqual([]);
192222
});
193223

224+
// An allowlist nobody rechecks is how a guard quietly stops guarding. Each
225+
// entry must still match a line the regex would otherwise flag: if the prose
226+
// was reworded, or the exception removed, the entry is dead and the reason
227+
// attached to it no longer describes anything.
228+
it("carries no stale entry in the hardcoded-invocation allowlist", async () => {
229+
const stale: string[] = [];
230+
for (const entry of ALLOWED_HARDCODED) {
231+
const source = await readFile(join(recipeDirectory, entry.file), "utf8");
232+
const stillNeeded = source
233+
.split("\n")
234+
.some(
235+
(line) =>
236+
line.includes(entry.snippet) && HARDCODED_INVOCATION.test(line)
237+
);
238+
if (!stillNeeded) {
239+
stale.push(`${entry.file}: "${entry.snippet}" no longer matches`);
240+
}
241+
}
242+
expect(stale).toEqual([]);
243+
});
244+
194245
it("renders a real invocation into every recipe that names the CLI", async () => {
195246
const rendered = await renderedRecipes();
196247
// Same build-target reasoning as CLI_NAMES: a prod build with no detected

0 commit comments

Comments
 (0)