Skip to content

feat(verify): report every fixture case in verify --json - #598

Open
theCodeDrift wants to merge 2 commits into
mainfrom
cli/verify-json-cases
Open

theCodeDrift wants to merge 2 commits into
mainfrom
cli/verify-json-cases

Conversation

@theCodeDrift

Copy link
Copy Markdown
Member

taskless verify --json now reports each rule's fixture cases as structured data, for sg, vale and runtime:

cases: Array<{
  name: string;              // "<bucket>/<case>", e.g. "fail/cast"
  expected: "fail" | "pass";
  ok: boolean;
  message?: string;          // only when ok is false
  files?: Array<{ path: string; content: string }>; // only when ok is false
}>

Until now a failed case was named only inside errors prose (fail fixture did not fire: fail/<name>), which the generator deliberately does not parse, so the dashboard's request timeline reads "Failing case: not provided" on every failed run (taskless/taskless#334, item 1).

How it is built

  • From each runner's own verdict, never from errors. sg and Vale derive it from the CaseOutcomes they already judge; runtime records it in its per-case loop.
  • message and errors cannot drift. describeCaseFailures is split into a per-case describeCaseFailure, and runtime's four failure lines become named functions; both errors and cases[].message are produced by them. Tests assert each failing case's message appears in errors verbatim.
  • errors is unchanged, so the change is additive.

Choices where the issue left room

  • Always present, empty when nothing ran (for validate, a refused runtime run, and a rule that failed before its fixtures ran), matching how findings already behaves. A reader treating it as optional still works.
  • files only on failing cases. The server stores only those, and attaching every passing case's files would grow every report for nothing.
  • Paths are project-relative, the same spelling as findings[].file, so a finding can be matched to the file it was reported against.
  • A file over 64 KiB or containing NUL is left out, not truncated: a truncated fixture misrepresents its case. Reading the files never fails a report.

runRuntimeFixtures gains a leading cwd parameter, used only to name those files; its one caller is updated. The field is declared in the output schema, so it reaches @taskless/cli/schemas too.

Verified

  • Seven new tests through the built CLI: runtime (a pass case that fired, with message and files; a case that never reached the check; empty when the run was refused), sg (a fail case that did not match, with message and files; all cases on a passing rule; empty from validate), and Vale (a pass case that fired). All seven fail against the unchanged source.
  • vale-verify.test.ts asserts the whole verification with toEqual on purpose, so it now spells out cases.
  • pnpm typecheck, pnpm lint, and the full CLI suite (2842 passed, 10 skipped).

Refs #596

Each rule gains cases: [{ name, expected, ok, message?, files? }] for sg, vale and runtime, built from each runner's own per-case verdict. A failing case's message is produced by the same function as its errors line, and errors is unchanged.
@theCodeDrift

Copy link
Copy Markdown
Member Author

@claude /review

@github-actions

github-actions Bot commented Nov 2, 2026 •

Copy link
Copy Markdown
Contributor

Claude finished @theCodeDrift's task in 2m 34s —— View job


Review: verify --json per-case results

Review mode: incremental — read 0 prior review thread(s) before reviewing. .prior-review.json held no reviews, review threads, or top-level comments beyond the trigger itself, so this is the first full review of this PR.

  • Read .prior-review.json
  • Fetch PR diff and metadata
  • Review schema changes (schemas/rule-check.ts)
  • Review fixture/runtime changes (fixtures.ts, run-fixtures.ts)
  • Review verify.ts / vale/verify.ts / inspect.ts changes
  • Review test coverage
  • Post findings

Overall: the design is sound and consistently applied. I traced every return path in verify.ts, inspect.ts, vale/verify.ts, and run-fixtures.ts and every one of them now populates cases (empty or real), matching the "always present, never absent" invariant the PR states for findings. The shared describeCaseFailure/caseResult plumbing genuinely makes errors and cases[].message impossible to drift, and the new tests assert that overlap directly (toContain(cases[].message)), which is the right check. The runtime loop's extra record/continue calls are a faithful refactor of the original if/else if — no behavior change there.

Two things worth a look, posted inline:

  1. [New] fixtures.ts:410 — the "not text" exclusion the changeset and schema text describe is implemented as a NUL-byte check only. readFile(..., "utf8") doesn't throw on invalid UTF-8, it substitutes U+FFFD, so a binary fixture without an embedded NUL byte will be included in cases[].files with corrupted content rather than excluded as the docs claim.
  2. [New] runtime-fixture-runner.test.ts:347 — no test (unit or e2e) exercises the 64 KiB cutoff or the NUL/binary exclusion in readCaseFiles; all fixtures used are small text files.

Nothing else stood out — the cwd threading into runRuntimeFixtures, the schema's .default([])/optional files, and the project-relative path spelling matching findings[].file all check out against the stated design.

Comment thread packages/cli/src/rules/fixtures.ts Resolved
…oth exclusions

readCaseFiles decoded with readFile(..., "utf8"), which substitutes U+FFFD
for invalid bytes, so a binary fixture without a NUL byte reached
cases[].files mangled instead of being left out as documented. Decode
strictly (BOM preserved) and cover the size boundary, NUL, invalid UTF-8
and files-only-on-failure in a unit test.
@theCodeDrift

Copy link
Copy Markdown
Member Author

Re: @github-actions — "Claude finished @theCodeDrift's task in 2m 34s — Review: verify --json per-case results…"
#598 (comment)

Both inline findings are fixed in 40393dc (strict UTF-8 decoding for case files, plus unit tests for the size and not-text exclusions) and their threads resolved.

— AI Coding Agent

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant