# v0.71.0 — CI Truthfulness, Test Harness & Documentation Cleanup > **Full details:** [v0.71.0.md-full.md](v0.71.0.md-full.md) ## What's New v0.71.0 is the final release of the Assessment-13-Driven Hardening Arc. It resolves the remaining MEDIUM- and LOW-severity findings that span CI gate accuracy, test harness schema drift, the SQL API catalog generator, Rust code quality, and stale planning documents. After this release, every finding in Assessment 13 is resolved and the project is ready for the v1.0 stable release gate. ### CI-001: Fuzz Smoke Covers All Nine Targets (CI-001) The `fuzz-smoke.yml` workflow previously ran only six of the nine committed fuzz targets, leaving `sql_builder_fuzz`, `merge_sql_fuzz`, and `row_id_fuzz` — all high-value string-generation surfaces — without CI coverage. Fix: the workflow target list is generated dynamically from `fuzz/fuzz_targets/*.rs`. A new CI step runs before the fuzz jobs: `scripts/check_fuzz_targets.py` fails if any `fuzz/fuzz_targets/*.rs` file is not represented in the matrix, preventing future drift. ### CI-002: `just fuzz-all` Exits Non-Zero on Failure (CI-002) The `fuzz-all` justfile recipe used `|| true` after each target, masking crashes and making the command unsuitable as a release gate. Fix: the `|| true` suffix is removed. Target failures are accumulated and reported at the end. A new `fuzz-all-best-effort` recipe preserves the old behaviour for exploratory local runs. ### CI-003: E2E Coverage Workflow Schedule Aligned (CI-003) The coverage workflow claimed E2E coverage ran weekly in comments but the job was gated to `workflow_dispatch` only — so scheduled runs always skipped it. Fix: the E2E coverage job is moved to a `schedule: cron: '0 2 * * 0'` trigger (weekly Sunday 02:00 UTC) in addition to `workflow_dispatch`. The timeout is increased to 90 minutes. The misleading comments are updated. ### CI-004: `docs-lint` Added to `just lint` (CI-004) Contributors running the local `just lint` gate required by AGENTS.md could miss documentation drift because `docs-lint` was a separate recipe not called by `lint`. This allowed breaking doc changes to pass local checks and fail only in CI. Fix: `just lint` now calls `docs-lint` as a final step. The AGENTS.md contributor workflow is updated to reflect this. An alias `just lint-all = lint` is added for consistency with prior documentation. ### DEP-001: Advisory Ignore Expiry/Review Metadata (DEP-001) All five RUSTSEC advisory ignores in `deny.toml` gain structured metadata: `# Owner:`, `# Added:`, `# Review-By:`, `# Upstream:`, and `# Remove-When:` comment fields. A new script `scripts/check_deny_expiry.py` fails if any advisory ignore has a `Review-By` date in the past, providing a lightweight human-review cadence enforced by CI. ### DOC-001 / CODE-001: SQL API Catalog Generator Rewritten (DOC-001, CODE-001) The `scripts/gen_catalogs.py` generator used regexes over Rust source to infer function signatures. Nested generics and multiline `TableIterator` return types were routinely truncated, producing entries like `TableIterator<` in `docs/SQL_API_CATALOG.md`. CI guaranteed the broken output was reproducible, not correct. Fix: the generator is rewritten to consume pgrx's generated SQL output (`target/release/pg_trickle.sql` produced by `cargo pgrx schema`) as its source of truth. SQL `CREATE FUNCTION` statements are parsed with a simple context-free parser to extract name, arguments, and return type. A quality gate is added: `gen_catalogs.py` fails if any extracted return type ends with `<`, contains unbalanced generics, or is empty for a non-void function. ### CODE-002: Tarjan SCC Unwraps Converted to Errors (CODE-002) `tarjan_strongconnect()` contained `unwrap()` calls with `// nosemgrep: rust.panic-in-sql-path` suppression comments. The invariants are valid but panics in SQL-reachable code violate the repo coding convention. Fix: `lowlinks.get_mut(&v).unwrap()` and `stack.pop().unwrap()` are converted to `ok_or(PgTrickleError::InternalError("SCC invariant violated: ..."))`. `debug_assert!` guards keep the invariant visible in debug builds without affecting release code paths. ### TEST-005: Test Harness Catalog Schema Generated from Archive (TEST-005) `tests/common/mod.rs` maintained a hand-written subset of the catalog schema that had drifted from the extension SQL: `initiated_by` was missing `SELF_MONITOR`, and `unit_kind` was missing `cyclic_scc`, `repeatable_read_group`, and `fused_chain`. Fix: a new `scripts/gen_test_schema.py` script extracts the relevant `CREATE TABLE` DDL blocks from `sql/archive/pg_trickle--.sql` and emits a Rust string constant used by `tests/common/mod.rs`. A CI step runs `scripts/gen_test_schema.py --check` which fails when the generated output differs from the committed constant, preventing future drift. ### ARCH-003 / DOC-002: `plans/PLAN.md` Archived (ARCH-003, DOC-002) `plans/PLAN.md` opened with two duplicated "Implementation Status (v0.9.0 Cycle)" blocks, conflicting with the current v0.67+ roadmap. Contributors could not determine which planning document was authoritative. Fix: the historical content is moved to `plans/archive/PLAN_HISTORICAL.md` with a header noting it reflects the v0.9 era. `plans/PLAN.md` is rewritten as a short Architecture & Roadmap Index that links to `ROADMAP.md`, `docs/ARCHITECTURE.md`, the current assessment series, and the ADR catalogue. ### DOC-003: `plans/INDEX.md` Regenerated (DOC-003) `plans/INDEX.md` was maintained by hand and had not been updated since the v0.52 assessment series. It was missing all Overall Assessment files from 9 through 13 and all roadmap-arc planning files added during v0.62–v0.67. Fix: `scripts/gen_plans_index.py` regenerates `plans/INDEX.md` from the actual files under `plans/`. A CI step runs the script in `--check` mode to prevent future drift. The index is sorted by file date and categorised by prefix (`PLAN_OVERALL_ASSESSMENT_*`, `PLAN_DOCUMENTATION_*`, `PLAN_ADR_*`, etc.). ## Breaking Changes None. All changes are internal tooling, documentation, and code quality.