feat(checks): add TODOs & stubs check, replace noop template

/pygienium-todos inventories TODO/FIXME/HACK markers and stub bodies via a
deterministic pre-scan plus the todos sub-agent; --fix converts silent
stubs (placeholder returns, empty/pass bodies) into loud failures,
never implementing TODOs or deleting markers. Replaces the noop
reference check; the extensibility suite now registers a synthetic
witness. Adds agents/todos.md and tests/todos.test.ts.
This commit is contained in:
2026-08-09 16:45:29 -04:00
parent 2caeb2f790
commit 288506e84d
6 changed files with 1132 additions and 145 deletions

View File

@@ -1,38 +1,62 @@
/**
* extensibility.test.ts — the registry extensibility claim (task 14).
*
* Proves a NEW check added as a file in `src/checks/` plus one `registerCheck()`
* entry yields a working `/pygienium-<name>` command with ZERO `index.ts`
* command-wiring changes. The witness is `src/checks/noop.ts`: importing it
* self-registers the `noop` check, after which the generic command-binding path
* (`registerPygieniumCommands`, the exact function `index.ts` calls) exposes
* `/pygienium-noop` and `/pygienium-help` lists it.
* Proves a NEW check registered via the public API yields a working
* `/pygienium-<name>` command with ZERO `index.ts` command-wiring changes: an
* in-test `registerCheck()` call makes the generic command-binding path
* (`registerPygieniumCommands`, the exact function `index.ts` calls) expose
* `/pygienium-witness` and `/pygienium-help` lists it. The shipped checks are
* each exercised by their own test files, so this suite only needs a synthetic
* witness.
*/
import { describe, expect, it } from "bun:test";
import "../src/checks/noop.js";
import { getCheck, getAllChecks } from "../src/checks/registry.js";
import { describe, expect, it, afterEach } from "bun:test";
import {
clearChecks,
getCheck,
getAllChecks,
registerCheck,
type CheckDefinition,
} from "../src/checks/registry.js";
import { registerPygieniumCommands } from "../src/commands.js";
import { buildPygieniumHelpLines } from "../src/help.js";
/** A synthetic check registered only for this suite. */
const witnessCheck: CheckDefinition = {
name: "witness",
label: "Witness",
description: "Test-only check proving zero-wiring extensibility.",
agentName: "scanner",
fixAgentName: "fixer",
phaseId: "witness",
buildScanTask: () =>
"# Task: witness scan\nwrite findings.md: witness: 0 issues",
buildFixTask: () => "# Task: witness fix\nwrite changes.md: witness: 0 edits",
gate: () => undefined,
};
describe("registry extensibility (task 14)", () => {
it("the noop check file self-registers (no index.ts edits)", () => {
// Importing checks/noop.ts ran its top-level registerCheck(noopCheck).
expect(getCheck("noop")).toBeDefined();
expect(getAllChecks().some((c) => c.name === "noop")).toBe(true);
afterEach(() => clearChecks());
it("a registered check is visible via getCheck/getAllChecks", () => {
registerCheck(witnessCheck);
expect(getCheck("witness")).toBe(witnessCheck);
expect(getAllChecks().some((c) => c.name === "witness")).toBe(true);
});
it("registerPygieniumCommands exposes /pygienium-noop (zero wiring)", () => {
it("registerPygieniumCommands exposes /pygienium-<name> (zero wiring)", () => {
registerCheck(witnessCheck);
const names: string[] = [];
registerPygieniumCommands((name) => names.push(name));
expect(names).toContain("pygienium-noop");
expect(names).toContain("pygienium-witness");
// And the operator commands are still wired.
expect(names).toContain("pygienium-help");
expect(names).toContain("pygienium-all");
});
it("/pygienium-help lists the noop check", () => {
it("/pygienium-help lists a registered check", () => {
registerCheck(witnessCheck);
const text = buildPygieniumHelpLines().join("\n");
expect(text).toContain("/pygienium-noop");
expect(text).toContain(getCheck("noop")!.description);
expect(text).toContain("/pygienium-witness");
expect(text).toContain(witnessCheck.description);
});
});