From fa3144efdd7bf8c3f034fa0dc7dc32e004c8a3b1 Mon Sep 17 00:00:00 2001 From: Claude Date: Tue, 3 Nov 2026 16:13:04 +0000 Subject: [PATCH] osq: plan 348 rust lints strict Plan change 348: deny unwrap_used, allow_attributes_without_reason, dbg_macro, todo, unimplemented, print_stdout, print_stderr and string_add in the workspace lints, add a rustdoc check to verify-rust.sh, and fix every current hit crate by crate first. Co-Authored-By: Claude Opus 5.5 Claude-Session: https://claude.ai/code/session_0127zo32rmpUfq5NcxHgFJN4 --- .../348-rust-lints-strict/.run/plan.jsonl | 1 + .../changes/348-rust-lints-strict/proposal.md | 99 ++++++++++++++ .../specs/rust-core/spec.md | 123 ++++++++++++++++++ .../changes/348-rust-lints-strict/tasks.md | 36 +++++ .../changes/348-rust-lints-strict/tasks/1.md | 28 ++++ .../changes/348-rust-lints-strict/tasks/10.md | 20 +++ .../changes/348-rust-lints-strict/tasks/11.md | 22 ++++ .../changes/348-rust-lints-strict/tasks/12.md | 19 +++ .../changes/348-rust-lints-strict/tasks/13.md | 18 +++ .../changes/348-rust-lints-strict/tasks/14.md | 19 +++ .../changes/348-rust-lints-strict/tasks/15.md | 19 +++ .../changes/348-rust-lints-strict/tasks/16.md | 18 +++ .../changes/348-rust-lints-strict/tasks/17.md | 22 ++++ .../changes/348-rust-lints-strict/tasks/18.md | 18 +++ .../changes/348-rust-lints-strict/tasks/19.md | 15 +++ .../changes/348-rust-lints-strict/tasks/2.md | 28 ++++ .../changes/348-rust-lints-strict/tasks/20.md | 15 +++ .../changes/348-rust-lints-strict/tasks/21.md | 15 +++ .../changes/348-rust-lints-strict/tasks/22.md | 34 +++++ .../changes/348-rust-lints-strict/tasks/23.md | 35 +++++ .../changes/348-rust-lints-strict/tasks/3.md | 24 ++++ .../changes/348-rust-lints-strict/tasks/4.md | 25 ++++ .../changes/348-rust-lints-strict/tasks/5.md | 20 +++ .../changes/348-rust-lints-strict/tasks/6.md | 18 +++ .../changes/348-rust-lints-strict/tasks/7.md | 20 +++ .../changes/348-rust-lints-strict/tasks/8.md | 18 +++ .../changes/348-rust-lints-strict/tasks/9.md | 18 +++ 27 files changed, 747 insertions(+) create mode 100644 openspec/changes/348-rust-lints-strict/.run/plan.jsonl create mode 100644 openspec/changes/348-rust-lints-strict/proposal.md create mode 100644 openspec/changes/348-rust-lints-strict/specs/rust-core/spec.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/1.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/10.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/11.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/12.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/13.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/14.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/15.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/16.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/17.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/18.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/19.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/2.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/20.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/21.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/22.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/23.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/3.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/4.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/5.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/6.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/7.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/8.md create mode 100644 openspec/changes/348-rust-lints-strict/tasks/9.md diff --git a/openspec/changes/348-rust-lints-strict/.run/plan.jsonl b/openspec/changes/348-rust-lints-strict/.run/plan.jsonl new file mode 100644 index 00000000..191b7035 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/.run/plan.jsonl @@ -0,0 +1 @@ +{"type":"plan_ready","timestamp":"2026-11-03T16:12:44.238Z","data":{"hash":"sha256:51fa09bba539062eea7b1b5017b3cc7f0bf3d9c3b4e8be565499ee07db118180","notices":[{"id":"rules_path","severity":"red","folded":false},{"id":"many_tasks","severity":"amber","folded":false},{"id":"large_scope","severity":"amber","folded":false},{"id":"assumptions","severity":"amber","folded":false},{"id":"tests_modify","severity":"grey","folded":false}]}} diff --git a/openspec/changes/348-rust-lints-strict/proposal.md b/openspec/changes/348-rust-lints-strict/proposal.md new file mode 100644 index 00000000..0057a8b1 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/proposal.md @@ -0,0 +1,99 @@ +--- +title: Rust lints deny unwrap, reasonless allows, debug leftovers and broken doc links, so agents can't slip them past verify +depends_on: [] +verify: sh scripts/verify-rust.sh +check: pnpm verify +features: + reads: [rust-harnesses, rust-storage, rust-vcs, rust-loop, rust-sync, rust-archive, rust-doctor, rust-inbox, rust-lint, rust-report, rust-approve, rust-land, rust-manual, rust-plan, rust-retry, rust-run, rust-show, rust-cli] +--- +## Goal + +osq's Rust lints are already strict: pedantic, denied docs on every item, +forbidden `unsafe` and an 80-line function cap. But an agent can still write +`.unwrap()`, put `#[allow(dead_code)]` on a module with no reason, leave a +`dbg!` or `todo!`, or write a doc link that points nowhere, and verify stays +green. Most of osq's Rust is written by agents, and a rule an agent can break +without the compiler noticing gets broken and then copied. + +This change adds eight clippy restriction lints to `[workspace.lints]` at +deny and a rustdoc step to `scripts/verify-rust.sh`, and fixes every place +that breaks them today, so the workspace stays green under the new table. It +is Tier 1 of the 2026-11-03 lint audit and item 10, `rust-lints-google`, of +the Google Rust guidelines report, narrowed to the lints with few hits. + +Measured on main at 7015dd2f with Rust 1.99.1, the new lints fire at: + +| Lint or check | Crate: hits | +|---|---| +| `unwrap_used`, with `allow-unwrap-in-tests` | harnesses src: 4. Test helpers outside `#[test]` functions: storage 136, vcs 93, inbox 61, archive 27, report 25, doctor 5, loop 4, lint 1 | +| `allow_attributes_without_reason` | run 8, approve 2, plan 2, land 1, lint 1, loop 1, manual 1, report 1, retry 1, sync 1. All `allow(dead_code)` in tests | +| `string_add` | show 7, run 4, harnesses 1, manual 1. All in tests | +| `dbg_macro`, `todo`, `unimplemented`, `print_stdout`, `print_stderr` | none | +| `RUSTDOCFLAGS=-D warnings cargo doc --workspace --no-deps` | core 1, report 2, cli 1 | + +## Verify + +`sh scripts/verify-rust.sh` + +The script runs the format check, clippy with `-D warnings`, and after task 23 the rustdoc check, then every test, then cargo-mutants on the +lines the change touched. Each fix task keeps it green, since the lints turn on +only in task 22 and the rustdoc step only in task 23, after every hit is +fixed. The `check` runs `pnpm verify` at archive and land, +which covers the two new TypeScript tests and the changed verify script test. + +## Non-goals + +- `expect_used`, `indexing_slicing`, `panic` or `clippy::nursery`. `expect` + with a reason is the house style, and the others fire hundreds of times, + mostly in tests. +- Tier 2 of the audit: `mod_module_files`, `as_conversions`, + `rust_2018_idioms`, `unused_qualifications`, `let_underscore_must_use` and + `missing_assert_message`. Each is its own change. +- Tier 3: `max-fn-params-bools`, a Rust file line cap and `cargo-deny`. +- `allow_attributes`, which would force `#[expect]`. A test support module is + compiled into several test binaries, and a binary that uses every item + would fail an `#[expect(dead_code)]` as unfulfilled. +- The TypeScript side: `tsconfig.json` and `biome.json` do not change. +- Rewriting AGENTS.md. The lints now say what it would. + +## Surface + +- Added: `[workspace.lints.clippy]` in `Cargo.toml` denies `unwrap_used`, `allow_attributes_without_reason`, `dbg_macro`, `todo`, `unimplemented`, `print_stdout`, `print_stderr` and `string_add`. +- Added: `allow-unwrap-in-tests = true` in `clippy.toml`. +- Added: `scripts/verify-rust.sh` runs `cargo doc --workspace --no-deps` with `RUSTDOCFLAGS="-D warnings"` between clippy and the tests. + +## Decisions + +- ADR 023: this is an additive amendment. Section 4 says the lint table "includes at least" a set, and task 22 records the new lints and the rustdoc step in a dated amendment. No lint is loosened. +- ADR 022: each fix task stays in one crate. No crate gains a dependency. +- ADR 024: every public function keeps its `Implements:` tag, and verify still runs cargo-mutants on the changed lines. Harnesses' `unwrap` to `expect` lines must stay covered. +- ADR 025: nothing under `openspec/` or `.run/` changes shape. +- ADR 026: the specs kernel and its parity job do not change. Its tests have no hits. +- ADR 027: scheduling does not change. The fix tasks run in a chain so each crate's clippy check sees harnesses already fixed. +- ADR 028: no `Feature` implementation changes. Report's `run` keeps its code and only its doc text changes. +- ADR 029: no config key changes. Lint levels live in `Cargo.toml` and `clippy.toml`, not osq's config. +- ADR 030: no event or reaction changes. + +## Assumptions + +- The audit doc's first count of `unwrap` was 4. That was wrong: `allow-unwrap-in-tests` covers only `#[test]` functions, so 352 `unwrap`s in test helpers also need `expect`. This plan converts them all. +- Clippy lints a workspace crate's library when it builds a crate that depends on it. So only harnesses' `src` hits block other crates, and task 2 comes before every other fix task. +- ADR 023 is amended in place with a dated section, as 207 edited it before, and not superseded. +- `cargo doc --workspace --no-deps` adds under a minute to each verify on this machine. +- Tasks 2 to 21 edit test files and docs that rust-harnesses, rust-storage and 16 other capabilities own, with no delta for them: their behaviour and specs do not change. `osq lint` warns once per such file. Splitting the sweep into one change per capability would clear the warnings at the cost of 18 changes. + +## Human steps + +### Before approval + +None + +### After landing + +None + +## Delta + +- `specs/rust-core/spec.md`: ADDED "Workspace lint table" and "Verify script rustdoc check". MODIFIED "Code ownership" (gains `clippy.toml` and the two new lint tests), "Verify script mutation step" and "Verify script toolchain check" (the rustdoc command joins the cargo command list). + +`clippy.toml` is written by task 1 only; task 22 reads it. No file is shared between tasks. diff --git a/openspec/changes/348-rust-lints-strict/specs/rust-core/spec.md b/openspec/changes/348-rust-lints-strict/specs/rust-core/spec.md new file mode 100644 index 00000000..934286b4 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/specs/rust-core/spec.md @@ -0,0 +1,123 @@ +# Spec Delta: rust-core + +## ADDED Requirements + +### Requirement: Workspace lint table +The root `Cargo.toml`'s `[workspace.lints]` tables SHALL set every lint +level below, so `unwrap`, a bare `#[allow]`, a debug macro, a placeholder, a +print or `+` on strings fails clippy. `clippy.toml` SHALL set the settings +below. `allow-unwrap-in-tests` allows `unwrap` inside `#[test]` functions +only; helpers and `src/` use `expect` with a reason. + +#### Scenario: Workspace lint levels +- **WHEN** the root `Cargo.toml` is read +- **THEN** its `[workspace.lints]` tables set each lint to the level given: + +| Table | Lint | Level | +|---|---|---| +| `[workspace.lints.rust]` | `missing_docs` | `"deny"` | +| `[workspace.lints.rust]` | `unsafe_code` | `"forbid"` | +| `[workspace.lints.clippy]` | `pedantic` | `{ level = "warn", priority = -1 }` | +| `[workspace.lints.clippy]` | `missing_docs_in_private_items` | `"deny"` | +| `[workspace.lints.clippy]` | `too_many_lines` | `"deny"` | +| `[workspace.lints.clippy]` | `unwrap_used` | `"deny"` | +| `[workspace.lints.clippy]` | `allow_attributes_without_reason` | `"deny"` | +| `[workspace.lints.clippy]` | `dbg_macro` | `"deny"` | +| `[workspace.lints.clippy]` | `todo` | `"deny"` | +| `[workspace.lints.clippy]` | `unimplemented` | `"deny"` | +| `[workspace.lints.clippy]` | `print_stdout` | `"deny"` | +| `[workspace.lints.clippy]` | `print_stderr` | `"deny"` | +| `[workspace.lints.clippy]` | `string_add` | `"deny"` | + +#### Scenario: Clippy settings +- **WHEN** `clippy.toml` is read +- **THEN** it sets each key to the value given: + +| Key | Value | +|---|---| +| `too-many-lines-threshold` | `80` | +| `allow-unwrap-in-tests` | `true` | + +### Requirement: Verify script rustdoc check +`scripts/verify-rust.sh` SHALL build the workspace's docs with +`cargo doc --workspace --no-deps` and `RUSTDOCFLAGS` set to `-D warnings`, +after clippy and before the tests, so a broken intra-doc link, a redundant +link target or a public doc that links a private item fails the verify. +Clippy does not run rustdoc, so without this step those docs pass. + +#### Scenario: Verify script denies rustdoc warnings +- **WHEN** `sh scripts/verify-rust.sh` runs with no `OSQ_DIFF` and a `cargo` on `PATH` that prints `cargo 1.99.1 (stub)` for `--version`, records its other arguments, and records the value of `RUSTDOCFLAGS` it was given when its first argument is `doc` +- **THEN** the script exits 0, records `doc --workspace --no-deps` once, as the third command after `--version`, and the recorded `RUSTDOCFLAGS` is `-D warnings` + +## MODIFIED Requirements + +### Requirement: Code ownership + +The rust-core capability SHALL own the `osq-core` crate, the Rust decisions +test, and the Rust workspace's tooling files and their tests. + +#### Scenario: Codebase ownership boundaries +- **WHEN** file ownership is resolved for the `Event` enum, the folds or the change typestate +- **THEN** system maps `crates/core/**` to rust-core + +#### Scenario: Rust decisions test ownership +- **WHEN** file ownership is resolved for `tests/rust-adrs.test.ts` +- **THEN** system maps it to rust-core + +#### Scenario: Rust tooling ownership +- **WHEN** file ownership is resolved for `scripts/verify-rust.sh`, `scripts/mutants-rust.sh`, `.cargo/mutants.toml`, `.github/workflows/rust.yml` and `tests/rust-ci.test.ts` +- **THEN** system maps each to rust-core + +#### Scenario: Verify script test ownership +- **WHEN** file ownership is resolved for `tests/rust-verify-script.test.ts` +- **THEN** system maps it to rust-core + +#### Scenario: Toolchain file ownership +- **WHEN** file ownership is resolved for `rust-toolchain.toml` +- **THEN** system maps it to rust-core + +#### Scenario: Lint settings ownership +- **WHEN** file ownership is resolved for `clippy.toml`, `tests/rust-clippy-settings.test.ts` and `tests/rust-workspace-lints.test.ts` +- **THEN** system maps each to rust-core + +### Requirement: Verify script mutation step +`scripts/verify-rust.sh` SHALL run the format check, clippy, the rustdoc +check and the workspace tests with ignored corpus tests included, then, when +`OSQ_DIFF` is set and not empty, run `sh scripts/mutants-rust.sh "$OSQ_DIFF"` +and exit with its status, so a missed mutant or timeout in the changed lines +fails the verify. When `OSQ_DIFF` is unset or empty, it SHALL print +`mutation check not run: OSQ_DIFF is not set` and exit 0 after the tests. + +#### Scenario: Verify script steps +- **WHEN** `sh scripts/verify-rust.sh` runs with a `cargo` on `PATH` that prints `cargo 1.99.1 (stub)` for `--version`, records its other arguments and exits with the status of its row for `mutants` and 0 otherwise +- **THEN** the script runs the cargo commands and exits as given: + +| `OSQ_DIFF` | `mutants` status | cargo commands in order | Exit | +|---|---|---|---| +| a diff file | 0 | `fmt --all --check`, `clippy --workspace --all-targets -- -D warnings`, `doc --workspace --no-deps`, `test --workspace -- --include-ignored`, then `mutants` with `--in-diff` and the diff file's path | 0 | +| a diff file | 2 | the same five | 2 | +| unset | 0 | `fmt --all --check`, `clippy --workspace --all-targets -- -D warnings`, `doc --workspace --no-deps`, `test --workspace -- --include-ignored` | 0 | +| empty | 0 | the same four | 0 | + +#### Scenario: Verify script names the missing diff +- **WHEN** `sh scripts/verify-rust.sh` runs with that recording `cargo` and no `OSQ_DIFF` +- **THEN** its output holds `mutation check not run: OSQ_DIFF is not set` + +### Requirement: Verify script toolchain check +Before any other cargo command, `scripts/verify-rust.sh` SHALL compare +the version that `cargo --version` prints, its second word, with the +`channel` of `rust-toolchain.toml`. When they differ, it SHALL print +`cargo is on PATH, but rust-toolchain.toml pins ; put rustup's cargo proxy first on PATH` +to standard error and exit 1 without running another cargo command, so a +`cargo` that ignores the toolchain file cannot lint with a different +clippy. + +#### Scenario: Verify script refuses another toolchain +- **WHEN** `sh scripts/verify-rust.sh` runs with no `OSQ_DIFF` and a `cargo` on `PATH` that prints its row's text for `--version`, records its other arguments and exits 0 +- **THEN** the script exits, prints and runs the cargo commands as given: + +| `cargo --version` prints | Exit | Output holds | cargo commands after `--version` | +|---|---|---|---| +| `cargo 1.99.1 (stub)` | 0 | `mutation check not run: OSQ_DIFF is not set` | `fmt --all --check`, `clippy --workspace --all-targets -- -D warnings`, `doc --workspace --no-deps`, `test --workspace -- --include-ignored` | +| `cargo 1.99.0 (stub)` | 1 | `cargo 1.99.0 is on PATH, but rust-toolchain.toml pins 1.99.1; put rustup's cargo proxy first on PATH` | none | +| `cargo 1.97.0 (stub)` | 1 | `cargo 1.97.0 is on PATH, but rust-toolchain.toml pins 1.99.1; put rustup's cargo proxy first on PATH` | none | diff --git a/openspec/changes/348-rust-lints-strict/tasks.md b/openspec/changes/348-rust-lints-strict/tasks.md new file mode 100644 index 00000000..6383cd1f --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks.md @@ -0,0 +1,36 @@ +# Tasks + +## 1. Clippy settings + +- [ ] 1. When clippy checks a #[test] function, unwrap is allowed there and nowhere else + +## 2. Fix every clippy hit, one crate at a time + +- [ ] 2. When the harnesses kernel takes a piped child's stdout or stderr, it says why the pipe is there instead of unwrapping +- [ ] 3. When storage kernel test helpers fail a setup step, they panic with expect and a reason instead of unwrap +- [ ] 4. When vcs kernel test helpers fail a git setup step, they panic with expect and a reason instead of unwrap +- [ ] 5. When loop kernel tests share a support module or fail a setup step, the allow and the panic both say why +- [ ] 6. When sync kernel tests share a support module, its dead_code allow says why +- [ ] 7. When archive feature test helpers fail a setup step, they panic with expect and a reason instead of unwrap +- [ ] 8. When doctor feature test helpers fail a setup step, they panic with expect and a reason instead of unwrap +- [ ] 9. When inbox feature test helpers fail a setup step, they panic with expect and a reason instead of unwrap +- [ ] 10. When lint feature tests share a support module or fail a setup step, the allow and the panic both say why +- [ ] 11. When report feature tests share a support module or fail a setup step, the allow and the panic both say why +- [ ] 12. When approve feature tests share a support module, its dead_code allow says why +- [ ] 13. When land feature tests share a support module, its dead_code allow says why +- [ ] 14. When manual feature tests share a support module, its allow says why and it builds strings with format +- [ ] 15. When plan feature tests include a shared module, its dead_code allow says why +- [ ] 16. When retry feature tests share a support module, its dead_code allow says why +- [ ] 17. When run feature tests share support modules or build prompt text, every allow says why and strings use format +- [ ] 18. When show feature land tests build expected text, they use format instead of adding strings + +## 3. Fix every rustdoc warning + +- [ ] 19. When the report feature's docs build, its public run doc links no private item +- [ ] 20. When core's docs build, the event kind module's link to Event::kind resolves +- [ ] 21. When the CLI app's docs build, its crate doc has no redundant link target + +## 4. Turn the checks on + +- [ ] 22. When clippy checks the workspace, the eight new restriction lints are denied and ADR 023 says why +- [ ] 23. When the Rust workspace is verified, a rustdoc warning fails it diff --git a/openspec/changes/348-rust-lints-strict/tasks/1.md b/openspec/changes/348-rust-lints-strict/tasks/1.md new file mode 100644 index 00000000..2dce479c --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/1.md @@ -0,0 +1,28 @@ +--- +title: When clippy checks a #[test] function, unwrap is allowed there and nowhere else +verify: node --import tsx --import ./tests/git-test-env.ts --test tests/rust-clippy-settings.test.ts +verify_starts: red +scope: + - clippy.toml + - tests/rust-clippy-settings.test.ts +entry: + - clippy.toml + - tests/rust-ci.test.ts +skills: [] +--- +## Acceptance + +- [ ] `clippy.toml` keeps its comment and `too-many-lines-threshold = 80`, and gains `allow-unwrap-in-tests = true` with a one-line comment saying `unwrap` stays allowed inside `#[test]` functions only, and test helpers use `expect`. +- [ ] New `tests/rust-clippy-settings.test.ts` holds `describe('rust-core: Clippy settings', ...)` with one case per table row of that scenario. It reads `clippy.toml` with plain text matching, one `key = value` line per row; add no TOML dependency. +- [ ] `pnpm lint` reports nothing in `tests/rust-clippy-settings.test.ts`. + +## Details + +Follow the shape of `tests/rust-ci.test.ts`, which reads +`rust-toolchain.toml` the same way: `repoRoot` from `import.meta.url`, +`node:test` and `node:assert/strict`. The lint itself turns on in task 22, +so clippy's output does not change in this task. + +## Scenarios + +- rust-core: Clippy settings diff --git a/openspec/changes/348-rust-lints-strict/tasks/10.md b/openspec/changes/348-rust-lints-strict/tasks/10.md new file mode 100644 index 00000000..a739f87f --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/10.md @@ -0,0 +1,20 @@ +--- +title: When lint feature tests share a support module or fail a setup step, the allow and the panic both say why +verify: cargo clippy -p osq-feature-lint --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [9] +tests: + modify: true +scope: + - crates/features/lint/tests/lint_entry_git.rs + - crates/features/lint/tests/support/mod.rs +entry: + - crates/features/lint/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] The `.unwrap()` that clippy's `unwrap_used` reports in `tests/lint_entry_git.rs` becomes `.expect("...")` with a message naming the step. +- [ ] `#![allow(dead_code)]` in `tests/support/mod.rs` becomes `#![allow(dead_code, reason = "...")]`, the reason saying several test binaries include the module and each uses only some of its items. It stays `allow`, not `expect`. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/11.md b/openspec/changes/348-rust-lints-strict/tasks/11.md new file mode 100644 index 00000000..bcc7ab64 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/11.md @@ -0,0 +1,22 @@ +--- +title: When report feature tests share a support module or fail a setup step, the allow and the panic both say why +verify: cargo clippy -p osq-feature-report --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [10] +tests: + modify: true +scope: + - crates/features/report/tests/query_json.rs + - crates/features/report/tests/query_run.rs + - crates/features/report/tests/support/mod.rs + - crates/features/report/tests/summary_support/mod.rs +entry: + - crates/features/report/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] Every `.unwrap()` under `crates/features/report/tests/` that clippy's `unwrap_used` reports, 25 today, becomes `.expect("...")` with a message naming the step. An `unwrap` inside a `#[test]` function may stay. +- [ ] `#![allow(dead_code)]` in `tests/summary_support/mod.rs` becomes `#![allow(dead_code, reason = "...")]`, the reason saying several test binaries include the module and each uses only some of its items. It stays `allow`, not `expect`. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/12.md b/openspec/changes/348-rust-lints-strict/tasks/12.md new file mode 100644 index 00000000..a72c9fe0 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/12.md @@ -0,0 +1,19 @@ +--- +title: When approve feature tests share a support module, its dead_code allow says why +verify: cargo clippy -p osq-feature-approve --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [11] +tests: + modify: true +scope: + - crates/features/approve/tests/support/mod.rs + - crates/features/approve/tests/worktree_support/mod.rs +entry: + - crates/features/approve/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] `#![allow(dead_code)]` in `tests/support/mod.rs` and in `tests/worktree_support/mod.rs` becomes `#![allow(dead_code, reason = "...")]`, the reason saying several test binaries include the module and each uses only some of its items. Each stays `allow`, not `expect`. +- [ ] No other line changes. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/13.md b/openspec/changes/348-rust-lints-strict/tasks/13.md new file mode 100644 index 00000000..0072bb1d --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/13.md @@ -0,0 +1,18 @@ +--- +title: When land feature tests share a support module, its dead_code allow says why +verify: cargo clippy -p osq-feature-land --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [12] +tests: + modify: true +scope: + - crates/features/land/tests/support/mod.rs +entry: + - crates/features/land/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] `#![allow(dead_code)]` in `tests/support/mod.rs` becomes `#![allow(dead_code, reason = "...")]`, the reason saying several test binaries include the module and each uses only some of its items. It stays `allow`, not `expect`. +- [ ] No other line changes. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/14.md b/openspec/changes/348-rust-lints-strict/tasks/14.md new file mode 100644 index 00000000..7a5a53d6 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/14.md @@ -0,0 +1,19 @@ +--- +title: When manual feature tests share a support module, its allow says why and it builds strings with format +verify: cargo clippy -p osq-feature-manual --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [13] +tests: + modify: true +scope: + - crates/features/manual/tests/support/mod.rs +entry: + - crates/features/manual/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] `#![allow(dead_code)]` in `tests/support/mod.rs` becomes `#![allow(dead_code, reason = "...")]`, the reason saying several test binaries include the module and each uses only some of its items. It stays `allow`, not `expect`. +- [ ] The one `String + &str` in the same file becomes `format!` or `push_str` and builds the same string. +- [ ] No test asserts anything different. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/15.md b/openspec/changes/348-rust-lints-strict/tasks/15.md new file mode 100644 index 00000000..8e4937ef --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/15.md @@ -0,0 +1,19 @@ +--- +title: When plan feature tests include a shared module, its dead_code allow says why +verify: cargo clippy -p osq-feature-plan --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [14] +tests: + modify: true +scope: + - crates/features/plan/tests/prompt_disclosures.rs + - crates/features/plan/tests/prompt_history.rs +entry: + - crates/features/plan/tests/prompt_history.rs +skills: [] +--- +## Acceptance + +- [ ] The `#[allow(dead_code)]` in `tests/prompt_disclosures.rs` and in `tests/prompt_history.rs` becomes `#[allow(dead_code, reason = "...")]`, the reason saying this binary uses only some items of the shared module. Each stays `allow`, not `expect`. +- [ ] No other line changes. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/16.md b/openspec/changes/348-rust-lints-strict/tasks/16.md new file mode 100644 index 00000000..d1c3db09 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/16.md @@ -0,0 +1,18 @@ +--- +title: When retry feature tests share a support module, its dead_code allow says why +verify: cargo clippy -p osq-feature-retry --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [15] +tests: + modify: true +scope: + - crates/features/retry/tests/support/mod.rs +entry: + - crates/features/retry/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] `#![allow(dead_code)]` in `tests/support/mod.rs` becomes `#![allow(dead_code, reason = "...")]`, the reason saying several test binaries include the module and each uses only some of its items. It stays `allow`, not `expect`. +- [ ] No other line changes. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/17.md b/openspec/changes/348-rust-lints-strict/tasks/17.md new file mode 100644 index 00000000..f6d8f17e --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/17.md @@ -0,0 +1,22 @@ +--- +title: When run feature tests share support modules or build prompt text, every allow says why and strings use format +verify: cargo clippy -p osq-feature-run --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [16] +tests: + modify: true +scope: + - crates/features/run/tests/executor_prompt.rs + - crates/features/run/tests/run_*.rs + - crates/features/run/tests/support/mod.rs + - crates/features/run/tests/worktree_support/mod.rs +entry: + - crates/features/run/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] Each of the 8 `allow(dead_code)` attributes under `crates/features/run/tests/` without a reason, in `support/mod.rs`, `worktree_support/mod.rs`, `run_outcomes.rs`, `run_pre_spawn.rs`, `run_usage_pause.rs`, `run_verify_output.rs`, `run_worktree.rs` and `run_worktree_dead.rs`, gains `reason = "..."` saying several test binaries include the module and each uses only some of its items. Each stays `allow`, not `expect`. +- [ ] The 4 `String + &str` expressions in `tests/executor_prompt.rs` become `format!` or `push_str` and build the same strings. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/18.md b/openspec/changes/348-rust-lints-strict/tasks/18.md new file mode 100644 index 00000000..2e46b799 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/18.md @@ -0,0 +1,18 @@ +--- +title: When show feature land tests build expected text, they use format instead of adding strings +verify: cargo clippy -p osq-feature-show --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [17] +tests: + modify: true +scope: + - crates/features/show/tests/show_land.rs +entry: + - crates/features/show/tests/show_land.rs +skills: [] +--- +## Acceptance + +- [ ] The 7 `String + &str` expressions in `tests/show_land.rs` become `format!`, `concat!` or `push_str` and build the same strings. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/19.md b/openspec/changes/348-rust-lints-strict/tasks/19.md new file mode 100644 index 00000000..31e61b1c --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/19.md @@ -0,0 +1,15 @@ +--- +title: When the report feature's docs build, its public run doc links no private item +verify: cargo rustdoc -p osq-feature-report -- -D warnings +verify_starts: red +depends_on: [18] +scope: + - crates/features/report/src/feature.rs +entry: + - crates/features/report/src/feature.rs +skills: [] +--- +## Acceptance + +- [ ] The doc comment of `run` in `src/feature.rs` no longer links the private `report::run` and `query::run_query` with intra-doc links. Name them as plain code spans, or say in words what they return. The function's `Implements:` line and its code do not change. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/2.md b/openspec/changes/348-rust-lints-strict/tasks/2.md new file mode 100644 index 00000000..faa0c927 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/2.md @@ -0,0 +1,28 @@ +--- +title: When the harnesses kernel takes a piped child's stdout or stderr, it says why the pipe is there instead of unwrapping +verify: cargo clippy -p osq-kernel-harnesses --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [1] +tests: + modify: true +scope: + - crates/kernel/harnesses/src/process/runner.rs + - crates/kernel/harnesses/src/verify/runner.rs + - crates/kernel/harnesses/tests/process_runner.rs +entry: + - crates/kernel/harnesses/src/process/runner.rs + - crates/kernel/harnesses/src/verify/runner.rs +skills: [] +--- +## Acceptance + +- [ ] In `process/runner.rs` and `verify/runner.rs`, each `child.stdout.take().unwrap()` and `child.stderr.take().unwrap()` becomes `.expect(...)` with a message saying the stream was set to `Stdio::piped()` when the command was built, such as `"stdout is piped when the child is spawned"`. No other line of either function changes. +- [ ] In `tests/process_runner.rs`, the one `String + &str` becomes `format!` or `push_str`, and the test asserts the same thing. +- [ ] The task's `verify` passes: clippy with the three new lints at deny reports nothing for the crate. The change-level verify then runs every test and cargo-mutants on the changed lines. + +## Details + +These are the only `src/` hits of the new lints in the workspace. Clippy +lints this crate's library whenever a crate that depends on it is checked, +so every later fix task waits for this one. Do not add `#[allow]` or +`#[expect]` for any of the three lints. diff --git a/openspec/changes/348-rust-lints-strict/tasks/20.md b/openspec/changes/348-rust-lints-strict/tasks/20.md new file mode 100644 index 00000000..d1bf6fc4 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/20.md @@ -0,0 +1,15 @@ +--- +title: When core's docs build, the event kind module's link to Event::kind resolves +verify: cargo rustdoc -p osq-core -- -D warnings +verify_starts: red +depends_on: [19] +scope: + - crates/core/src/event/kind.rs +entry: + - crates/core/src/event/kind.rs +skills: [] +--- +## Acceptance + +- [ ] The module doc of `src/event/kind.rs` links `Event::kind` with a path rustdoc resolves, as its `Event` link already does through `super::Event`. No code changes. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/21.md b/openspec/changes/348-rust-lints-strict/tasks/21.md new file mode 100644 index 00000000..e6bd8bcc --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/21.md @@ -0,0 +1,15 @@ +--- +title: When the CLI app's docs build, its crate doc has no redundant link target +verify: cargo rustdoc -p osq-cli -- -D warnings +verify_starts: red +depends_on: [20] +scope: + - crates/apps/cli/src/lib.rs +entry: + - crates/apps/cli/src/lib.rs +skills: [] +--- +## Acceptance + +- [ ] The crate doc of `src/lib.rs` writes its `Command` link so rustdoc reports no redundant explicit link target, for example `` [`osq_core::Command`] `` or a reference-style link. The text still names `Command` from `osq_core`, and no code changes. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/22.md b/openspec/changes/348-rust-lints-strict/tasks/22.md new file mode 100644 index 00000000..c52986f3 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/22.md @@ -0,0 +1,34 @@ +--- +title: When clippy checks the workspace, the eight new restriction lints are denied and ADR 023 says why +verify: node --import tsx --import ./tests/git-test-env.ts --test tests/rust-workspace-lints.test.ts +verify_starts: red +depends_on: [21] +scope: + - Cargo.toml + - decisions/023-rust-code-style.md + - tests/rust-workspace-lints.test.ts +entry: + - Cargo.toml + - clippy.toml + - decisions/023-rust-code-style.md +skills: [] +--- +## Acceptance + +- [ ] The root `Cargo.toml`'s `[workspace.lints.clippy]` gains, after `too_many_lines`, `unwrap_used`, `allow_attributes_without_reason`, `dbg_macro`, `todo`, `unimplemented`, `print_stdout`, `print_stderr` and `string_add`, each `"deny"`. The existing entries and the rulebook comment stay, and the comment gains one sentence naming ADR 023's 2026-11-03 amendment. +- [ ] New `tests/rust-workspace-lints.test.ts` holds `describe('rust-core: Workspace lint levels', ...)` with one case per table row of that scenario. It reads `Cargo.toml` with plain text matching inside the named table; add no TOML dependency. +- [ ] `decisions/023-rust-code-style.md` gains a section `## Amendment, 2026-11-03` after `## Rejected`. It lists the eight lints, `allow-unwrap-in-tests` in `clippy.toml`, and the rustdoc step task 23 adds to `scripts/verify-rust.sh`, and says why: agents write most of osq's Rust, and a rule the compiler doesn't check gets broken and copied. It names change 348. +- [ ] The amendment says `allow_attributes` was left out on purpose: a test support module shared by several test binaries would fail an `#[expect(dead_code)]` in a binary that uses every item. +- [ ] ADR 023's frontmatter, rule line and existing sections stay word for word. +- [ ] `pnpm lint` reports nothing in `tests/rust-workspace-lints.test.ts`. +- [ ] `cargo clippy --workspace --all-targets -- -D warnings` reports nothing. The change-level verify runs it after this task. If it reports a hit, the hit is in a file another task owns: write it under `## Blocked`, and do not add an `#[allow]`. + +## Details + +Follow the shape of `tests/rust-ci.test.ts` for reading a repository file. +Tasks 2 to 18 fixed every clippy hit measured on main, so this task should +change no Rust file. + +## Scenarios + +- rust-core: Workspace lint levels diff --git a/openspec/changes/348-rust-lints-strict/tasks/23.md b/openspec/changes/348-rust-lints-strict/tasks/23.md new file mode 100644 index 00000000..b624462a --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/23.md @@ -0,0 +1,35 @@ +--- +title: When the Rust workspace is verified, a rustdoc warning fails it +verify: node --import tsx --import ./tests/git-test-env.ts --test tests/rust-verify-script.test.ts +verify_starts: red +depends_on: [22] +tests: + modify: true +scope: + - scripts/verify-rust.sh + - tests/rust-verify-script.test.ts +entry: + - scripts/verify-rust.sh + - tests/rust-verify-script.test.ts +skills: [] +--- +## Acceptance + +- [ ] `scripts/verify-rust.sh` runs `RUSTDOCFLAGS="-D warnings" cargo doc --workspace --no-deps` after clippy and before the tests. Its header comment names the step in one sentence. The toolchain check and the mutation step do not change. +- [ ] In `tests/rust-verify-script.test.ts`, a `DOC_COMMAND` constant `doc --workspace --no-deps` joins the expected commands: third in "Verify script steps", where the counts become 5 with a diff and 4 without, and in the pinned row of "Verify script refuses another toolchain". +- [ ] `CARGO_STUB` writes `${RUSTDOCFLAGS:-}` to the file a new `CARGO_DOCFLAGS_FILE` env var names when its first argument is `doc`, and records the call as today. A new `describe('rust-core: Verify script denies rustdoc warnings', ...)` checks that scenario's THEN. No other existing case changes. +- [ ] `pnpm lint` reports nothing in `tests/rust-verify-script.test.ts`. +- [ ] `sh scripts/verify-rust.sh` passes on the real workspace, as the change-level verify checks after this task. Tasks 19 to 21 fixed every rustdoc warning measured on main. + +## Details + +Reuse `withStub`, `runVerify` and `recordedCommands`. The script runs +under `set -eu` with plain `sh`; set `RUSTDOCFLAGS` on the `cargo doc` line +only, so clippy and the tests do not see it. + +## Scenarios + +- rust-core: Verify script denies rustdoc warnings +- rust-core: Verify script steps +- rust-core: Verify script names the missing diff +- rust-core: Verify script refuses another toolchain diff --git a/openspec/changes/348-rust-lints-strict/tasks/3.md b/openspec/changes/348-rust-lints-strict/tasks/3.md new file mode 100644 index 00000000..4c319380 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/3.md @@ -0,0 +1,24 @@ +--- +title: When storage kernel test helpers fail a setup step, they panic with expect and a reason instead of unwrap +verify: cargo clippy -p osq-kernel-storage --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [2] +tests: + modify: true +scope: + - crates/kernel/storage/tests/*.rs +entry: + - crates/kernel/storage/tests/read_model.rs +skills: [] +--- +## Acceptance + +- [ ] Every `.unwrap()` under `crates/kernel/storage/tests/` that clippy's `unwrap_used` reports, 136 today, becomes `.expect("...")` with a message naming the step, such as `"write the change's done marker"`. An `unwrap` inside a `#[test]` function, which `allow-unwrap-in-tests` permits, may stay. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. + +## Details + +Most hits are in helpers that build fixture trees. One message per helper +call site is enough; say what was being done, not "should not fail". Do not +add `#[allow]` or `#[expect]` for any of the three lints. diff --git a/openspec/changes/348-rust-lints-strict/tasks/4.md b/openspec/changes/348-rust-lints-strict/tasks/4.md new file mode 100644 index 00000000..46cec34d --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/4.md @@ -0,0 +1,25 @@ +--- +title: When vcs kernel test helpers fail a git setup step, they panic with expect and a reason instead of unwrap +verify: cargo clippy -p osq-kernel-vcs --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [3] +tests: + modify: true +scope: + - crates/kernel/vcs/tests/*.rs + - crates/kernel/vcs/tests/support/mod.rs +entry: + - crates/kernel/vcs/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] Every `.unwrap()` under `crates/kernel/vcs/tests/` that clippy's `unwrap_used` reports, 93 today, becomes `.expect("...")` with a message naming the step, such as `"commit the base tree"`. An `unwrap` inside a `#[test]` function may stay. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. + +## Details + +Most hits are in `branch_and_commit_writes.rs`, `merge_writes.rs` and +`support/mod.rs`. Do not add `#[allow]` or `#[expect]` for any of the three +lints. diff --git a/openspec/changes/348-rust-lints-strict/tasks/5.md b/openspec/changes/348-rust-lints-strict/tasks/5.md new file mode 100644 index 00000000..a82e3efe --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/5.md @@ -0,0 +1,20 @@ +--- +title: When loop kernel tests share a support module or fail a setup step, the allow and the panic both say why +verify: cargo clippy -p osq-kernel-loop --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [4] +tests: + modify: true +scope: + - crates/kernel/loop/tests/active_schedule.rs + - crates/kernel/loop/tests/delivery_support/mod.rs +entry: + - crates/kernel/loop/tests/delivery_support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] The 4 `.unwrap()`s that clippy's `unwrap_used` reports in `tests/active_schedule.rs` become `.expect("...")` with a message naming the step. +- [ ] `#![allow(dead_code)]` in `tests/delivery_support/mod.rs` becomes `#![allow(dead_code, reason = "...")]`, the reason saying several test binaries include the module and each uses only some of its items. It stays `allow`, not `expect`. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/6.md b/openspec/changes/348-rust-lints-strict/tasks/6.md new file mode 100644 index 00000000..f59dcf19 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/6.md @@ -0,0 +1,18 @@ +--- +title: When sync kernel tests share a support module, its dead_code allow says why +verify: cargo clippy -p osq-kernel-sync --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [5] +tests: + modify: true +scope: + - crates/kernel/sync/tests/support/mod.rs +entry: + - crates/kernel/sync/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] `#![allow(dead_code)]` in `tests/support/mod.rs` becomes `#![allow(dead_code, reason = "...")]`, the reason saying several test binaries include the module and each uses only some of its items. It stays `allow`, not `expect`. +- [ ] No other line changes. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/7.md b/openspec/changes/348-rust-lints-strict/tasks/7.md new file mode 100644 index 00000000..23477c07 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/7.md @@ -0,0 +1,20 @@ +--- +title: When archive feature test helpers fail a setup step, they panic with expect and a reason instead of unwrap +verify: cargo clippy -p osq-feature-archive --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [6] +tests: + modify: true +scope: + - crates/features/archive/tests/*.rs + - crates/features/archive/tests/reseal/mod.rs + - crates/features/archive/tests/support/mod.rs +entry: + - crates/features/archive/tests/support/mod.rs +skills: [] +--- +## Acceptance + +- [ ] Every `.unwrap()` under `crates/features/archive/tests/` that clippy's `unwrap_used` reports, 27 today, becomes `.expect("...")` with a message naming the step. An `unwrap` inside a `#[test]` function may stay. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/8.md b/openspec/changes/348-rust-lints-strict/tasks/8.md new file mode 100644 index 00000000..a3b6747f --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/8.md @@ -0,0 +1,18 @@ +--- +title: When doctor feature test helpers fail a setup step, they panic with expect and a reason instead of unwrap +verify: cargo clippy -p osq-feature-doctor --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [7] +tests: + modify: true +scope: + - crates/features/doctor/tests/doctor_changes.rs +entry: + - crates/features/doctor/tests/doctor_changes.rs +skills: [] +--- +## Acceptance + +- [ ] Every `.unwrap()` in `tests/doctor_changes.rs` that clippy's `unwrap_used` reports, 5 today, becomes `.expect("...")` with a message naming the step. An `unwrap` inside a `#[test]` function may stay. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes. diff --git a/openspec/changes/348-rust-lints-strict/tasks/9.md b/openspec/changes/348-rust-lints-strict/tasks/9.md new file mode 100644 index 00000000..48fff1f6 --- /dev/null +++ b/openspec/changes/348-rust-lints-strict/tasks/9.md @@ -0,0 +1,18 @@ +--- +title: When inbox feature test helpers fail a setup step, they panic with expect and a reason instead of unwrap +verify: cargo clippy -p osq-feature-inbox --all-targets -- -D warnings -D clippy::unwrap_used -D clippy::allow_attributes_without_reason -D clippy::string_add +verify_starts: red +depends_on: [8] +tests: + modify: true +scope: + - crates/features/inbox/tests/*.rs +entry: + - crates/features/inbox/tests/inbox_json.rs +skills: [] +--- +## Acceptance + +- [ ] Every `.unwrap()` under `crates/features/inbox/tests/` that clippy's `unwrap_used` reports, 61 today, becomes `.expect("...")` with a message naming the step. An `unwrap` inside a `#[test]` function may stay. +- [ ] No test asserts anything different, and no test is added, removed or renamed. +- [ ] The task's `verify` passes.