feat: add suggest command to bootstrap assertions files#63
Merged
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
Adds a new bioassert suggest <file> workflow to bootstrap assertion files by inspecting the current file and emitting a starter set of heuristically chosen assertions (with inline # comments) that should round-trip through bioassert run. This fits alongside the existing evaluation pipeline by reusing existing property functions, but in the “inverse” direction (derive assertions from observed state).
Changes:
- Introduces a new
src/suggest/module (Suggestion model, provider registry, per-family providers, orchestrator + renderer). - Wires a new
suggestCLI subcommand with output-path resolution and--forceoverwrite behavior. - Updates the parser grammar to accept trailing inline comments, and adds unit/integration tests + docs/spec updates.
Reviewed changes
Copilot reviewed 30 out of 30 changed files in this pull request and generated 1 comment.
Show a summary per file
| File | Description |
|---|---|
| tests/suggest_subcommand_test.rs | New integration tests for the suggest subcommand (snapshots, --force, and run round-trip). |
| tests/snapshots/suggest_subcommand_test__suggest_unknown_extension.snap | Snapshot of suggest output for an unknown-extension fixture. |
| tests/snapshots/suggest_subcommand_test__suggest_tsv.snap | Snapshot of suggest output for TSV fixture. |
| tests/snapshots/suggest_subcommand_test__suggest_fasta.snap | Snapshot of suggest output for FASTA fixture. |
| tests/snapshots/suggest_subcommand_test__suggest_bam.snap | Snapshot of suggest output for BAM fixture. |
| src/suggest/suggestion.rs | Defines Suggestion, rendering, resource quoting, and the +/-50% band() helper. |
| src/suggest/providers/mod.rs | Declares providers and adds helper to normalize file extensions. |
| src/suggest/providers/file.rs | File-level provider for universal suggestions like file.exists and file.size. |
| src/suggest/providers/fasta.rs | FASTA provider using existing FASTA property functions to suggest counts/bands. |
| src/suggest/providers/delimited.rs | Delimited provider (csv/tsv/psv) suggesting column count and row-count band. |
| src/suggest/providers/bam.rs | BAM provider suggesting header-derived expectations. |
| src/suggest/provider.rs | Provider trait + ordered registry mirroring executor dispatch precedence. |
| src/suggest/orchestrator.rs | Orchestrates providers, collects warnings, and renders grouped output. |
| src/suggest/mod.rs | New module entry point and re-exports for suggest. |
| src/report.rs | Adds resolve_output_file() to compute default suggest output path. |
| src/main.rs | Adds suggest handling path (pre-pipeline), output writing, warnings, exit codes. |
| src/lib.rs | Exposes the new suggest module from the library crate. |
| src/file/size/mod.rs | Exposes size functions internally so suggest can reuse them. |
| src/file/mod.rs | Adjusts visibility so file-family function modules can be reused by suggest. |
| src/file/exists/mod.rs | Exposes exists functions internally for reuse by suggest. |
| src/engine/parser.rs | Adds parser tests ensuring trailing inline comments are ignored. |
| src/engine/assertions.pest | Updates grammar to allow optional trailing # ... inline comments. |
| src/delimited/mod.rs | Adjusts visibility so delimited-family function modules can be reused by suggest. |
| src/delimited/line_count/mod.rs | Exposes line_count functions internally for reuse by suggest. |
| src/delimited/functions.rs | Adds prefix_for_extension() to map extensions to delimited metric prefixes. |
| src/delimited/column_count/mod.rs | Exposes column_count functions internally for reuse by suggest. |
| src/cli.rs | Adds the new suggest subcommand and arguments (--output, --force). |
| specs/suggest.md | Updates/renames the design spec from generate→suggest and aligns details with implementation. |
| README.md | Documents the new suggest command and inline comment semantics. |
| CLAUDE.md | Updates architecture/docs notes to include the new suggest layer and inline comments. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+34
to
+38
| if get_file_size(path).is_ok() { | ||
| suggestions.push(Suggestion::new( | ||
| resource.as_ref(), | ||
| "file.size", | ||
| "gt", |
`bioassert suggest <file>` is the inverse of evaluation: it inspects a file and writes a starting set of suggested assertions to `<file>.assertions.txt` (or `--output FILE`) for the author to review and tighten. The proposals are heuristic guesses from the file's current state, not verified expectations, hence "suggest". - New `src/suggest/` module: `Suggestion` (one output line + `band` helper), the `SuggestionProvider` trait and ordered `providers()` registry, the `suggest()` orchestrator returning a `SuggestResult`, and one provider per resource family (file, delimited, bam, fasta) reusing each family's existing property functions. No executor or dispatch code changes. - Defaults: every file gets `file.exists eq true` and `file.size gt 0B`; schema-like counts are pinned with `eq` (delimited columns, fasta records, bam @sq); run-to-run quantities get a +/- 50% `gte`/`lte` band (delimited rows, fasta total length). - Grammar: assertions now accept an optional trailing inline `# comment` (discarded), so annotated `suggest` output round-trips through `run`. A `#` inside a quoted resource/value is not a comment. - CLI: new `suggest` subcommand; output path derives `<file>.assertions.txt` and is not overwritten without `--force`. Exit 0 on success, 2 on a fatal error; provider warnings go to stderr and keep exit 0. - Tests: unit tests per provider + orchestrator + suggestion rendering; integration snapshots for tsv/bam/fasta/unknown plus a round-trip test that proves every suggested assertion holds against its source file. - Docs: CLAUDE.md module entry and Suggest command section, README usage section, and the design spec at specs/suggest.md. Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>
9f9026c to
33ed36b
Compare
Merged
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What
Adds
bioassert suggest <file>, the inverse of evaluation: it inspects a file and writes a starting set of suggested assertions to<file>.assertions.txt(or--output FILE) for the author to review and tighten.Implements the design in
specs/suggest.md. The proposals are heuristic guesses from the file's current state, not verified expectations — hence the command namesuggestrather thangenerate.How
src/suggest/module (purely additive; no executor or dispatch code changes):suggestion.rs— theSuggestionoutput-line type, itsrender, and thebandhelper for the +/- 50% bounds.provider.rs— theSuggestionProvidertrait and the orderedproviders()registry, mirroring the executor dispatch order (file → delimited → bam → fasta).orchestrator.rs—suggest()returning aSuggestResult { suggestions, rendered, warnings }.providers/{file,delimited,bam,fasta}.rs— one provider per family, each reusing that family's existing property functions (exists/get_file_size,column_count/line_count,read_header+counts,read_records+counts).file.exists eq trueandfile.size gt 0B; schema-like counts are pinned witheq(delimited columns, fasta records, bam@SQ); run-to-run quantities get agte/lte+/- 50% band (delimited rows, fasta total length). Family selection is by extension via a newprefix_for_extensionhelper.suggestsubcommand (src/cli.rs); output path derives<file>.assertions.txt(resolve_output_fileinsrc/report.rs) and is not overwritten without--force. Exit0on success,2on a fatal error; provider warnings go to stderr and keep the exit0.Notable deviation from the spec
The spec's documented output format uses inline
# comments, and the spec also requires the generated file torunwith exit 0 — but the grammar'sassertionrule ended in~ EOIwith no comment support, so inline-commented output would not parse. To make the documented output valid input (and the round-trip pass), the grammar now accepts an optional trailing# comment(discarded). A#inside a quoted resource/value is consumed by the quoted token first, so it is not treated as a comment.Testing
cargo test— 334 passing, 0 failing. New unit tests per provider, the orchestrator, and suggestion rendering; new parser tests for inline comments (incl. no regressions on the existing trailing-token rejection tests).tests/suggest_subcommand_test.rs: insta snapshots for tsv/bam/fasta/unknown-extension, the--forceoverwrite behaviour, and a round-trip test thatsuggests a fixture thenruns the output and asserts exit 0 — proving every suggested assertion holds against its source file.cargo clippy --all-targetsclean;cargo fmt --checkclean.Docs
CLAUDE.md(module entry + Suggest command section + new-family provider step + inline-comment note),README.md(Commands table, inline-comment note, "Suggesting a starting set" section), and the design spec atspecs/suggest.md.🤖 Generated with Claude Code