# v0.71.0 Full Details — CI Truthfulness, Test Harness & Documentation Cleanup > **Summary:** [v0.71.0.md](v0.71.0.md) > **Assessment source:** [plans/PLAN_OVERALL_ASSESSMENT_13.md](../plans/PLAN_OVERALL_ASSESSMENT_13.md) --- ## Motivation This is the closeout release for the Assessment-13 hardening arc. The items here are low-risk, high-leverage hygiene changes: correct the gates developers and CI use to detect problems, generate artefacts rather than maintain them by hand, and remove historical confusion from the planning hierarchy. The principle is: every CI check must mean something, every generator must produce correct output, and every planning document must be authoritative or clearly labelled as historical. --- ## Detailed Implementation ### CI-001: Dynamic Fuzz Target Matrix **Files changed:** - `.github/workflows/fuzz-smoke.yml` — replace hard-coded matrix with `$(ls fuzz/fuzz_targets/*.rs | xargs -I{} basename {} .rs)` in a matrix `include` step generated by a `prepare-matrix` job - `scripts/check_fuzz_targets.py` — new script; reads `fuzz/fuzz_targets/*.rs` and fails if any file is missing from the workflow target list - `.github/workflows/fuzz-smoke.yml` — add `check-fuzz-targets` step before the fuzz matrix that runs `scripts/check_fuzz_targets.py` - `justfile` — `fuzz-smoke` recipe updated to match **Acceptance criteria:** 1. `fuzz-smoke.yml` runs all nine targets in CI. 2. Adding a new `fuzz/fuzz_targets/new_target.rs` without updating the workflow fails CI. --- ### CI-002: `just fuzz-all` Failure Propagation **Files changed:** - `justfile` — `fuzz-all` recipe: remove `|| true`; introduce `FAILED_TARGETS` accumulator variable; print summary; `exit 1` if non-empty - `justfile` — new `fuzz-all-best-effort` recipe that restores old behaviour --- ### CI-003: E2E Coverage Schedule **Files changed:** - `.github/workflows/coverage.yml` — add `schedule: [{cron: '0 2 * * 0'}]` trigger; gate E2E job on `github.event_name == 'workflow_dispatch' || github.event_name == 'schedule'`; increase timeout to 90 minutes; update comments --- ### CI-004: `docs-lint` in `just lint` **Files changed:** - `justfile` — `lint` recipe: append `docs-lint` as a final dependency - `AGENTS.md` — note that `just lint` now includes doc drift checking - `CONTRIBUTING.md` — update local workflow section --- ### DEP-001: Advisory Expiry Metadata **Files changed:** - `deny.toml` — add structured comment block for all five RUSTSEC ignores: ``` # Owner: # Added: 2026-05-21 # Review-By: 2026-08-21 # Upstream: https://github.com/... # Remove-When: upstream fixed and dependency upgraded ``` - `scripts/check_deny_expiry.py` — new script; parses `deny.toml`; finds all `# Review-By:` lines; fails if any date is in the past - `.github/workflows/dependency-policy.yml` — add step that runs `check_deny_expiry.py` --- ### DOC-001 / CODE-001: Generator Rewrite **Files changed:** - `scripts/gen_catalogs.py` — rewrite `extract_sql_functions()` to: 1. Run `cargo pgrx schema --pg-config $(pg_config)` (or read cached output) 2. Parse resulting `CREATE FUNCTION` statements with a lightweight context-free parser tracking parenthesis depth 3. Extract `(schema, name, arg_list, return_type)` tuples - `scripts/gen_catalogs.py` — add `validate_catalog(rows)`: fail on return type ending with `<`, empty non-void return, unbalanced `<>` - `docs/SQL_API_CATALOG.md` — regenerated (committed output) - `.github/workflows/docs-drift.yml` — the existing reproducibility check continues to work; the quality gate is an additional step **Acceptance criteria:** 1. All 121 functions in the generated catalog have complete, parseable return types. 2. `gen_catalogs.py --check` fails on the old `docs/SQL_API_CATALOG.md` (regression test). --- ### CODE-002: Tarjan SCC Error Propagation **Files changed:** - `src/dag.rs` — `tarjan_strongconnect()`: replace two `unwrap()` calls with `ok_or_else(|| PgTrickleError::InternalError(...))`; propagate `Result` up to `tarjan_scc()` and callers - `src/dag.rs` — add `debug_assert!(lowlinks.contains_key(&v), "SCC invariant")` above each converted call - Remove `// nosemgrep` comments now that the runtime path is non-panicking --- ### TEST-005: Generated Test Harness Schema **Files changed:** - `scripts/gen_test_schema.py` — new script; reads `sql/archive/pg_trickle--.sql`; extracts DDL for tables referenced in `tests/common/mod.rs` by name; emits a Rust `const TEST_SCHEMA_SQL: &str` to stdout - `tests/common/mod.rs` — replace hand-written DDL constants with `include!(concat!(env!("CARGO_MANIFEST_DIR"), "/tests/generated/schema.rs"))` - `build.rs` — add build step that runs `gen_test_schema.py` and writes `tests/generated/schema.rs`; fails the build if the script returns non-zero - `.github/workflows/ci.yml` — add `check-test-schema` step that runs `gen_test_schema.py --check` against the committed generated file --- ### ARCH-003 / DOC-002: PLAN.md Archival **Files changed:** - `plans/PLAN.md` — replaced with short Architecture & Roadmap Index - `plans/archive/PLAN_HISTORICAL.md` — historical content (moved verbatim) - `plans/archive/` directory created if not present --- ### DOC-003: INDEX.md Generation **Files changed:** - `scripts/gen_plans_index.py` — new script; scans `plans/**/*.md`; categorises by prefix; sorts by mtime; emits `plans/INDEX.md` - `plans/INDEX.md` — regenerated - `.github/workflows/docs-drift.yml` — add step that runs `gen_plans_index.py --check` --- ## Upgrade Notes No schema changes in v0.71.0. The upgrade migration is a version bump only. Build tooling note: `build.rs` now generates `tests/generated/schema.rs` during `cargo build`. This file is `.gitignore`d in the test directory; `cargo build` must run before `cargo test` in fresh checkouts. The CI matrix already runs `cargo test` which triggers `build.rs`, so no CI changes are required.