fix(dogfood): batch 5 — the last three audit findings, and a producer that could fabricate its own verdict #360
Workflow file for this run
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
| name: mdBook CI | |
| on: | |
| push: | |
| branches: [main] | |
| paths: | |
| - "book/**" | |
| - ".github/workflows/book.yml" | |
| # FALSIFY-BOOK-CLI-PARITY-001 asserts every `apr` subcommand has a chapter. | |
| # Filtering on book/** alone meant it only ran when the BOOK changed, never | |
| # when the CLI gained a command — so `apr beat-run` shipped in #1995 with no | |
| # chapter and the gate stayed green for months, until an unrelated batch that | |
| # happened to touch book/ woke it. A parity gate must run when EITHER side | |
| # moves; watching only one of them is how it comes to certify nothing. | |
| - "crates/apr-cli/src/commands_enum.rs" | |
| - "crates/apr-cli/src/extended_commands.rs" | |
| - "crates/apr-cli/src/tool_commands.rs" | |
| pull_request: | |
| branches: [main] | |
| paths: | |
| - "book/**" | |
| - ".github/workflows/book.yml" | |
| - "crates/apr-cli/src/commands_enum.rs" | |
| - "crates/apr-cli/src/extended_commands.rs" | |
| - "crates/apr-cli/src/tool_commands.rs" | |
| permissions: | |
| contents: read | |
| pages: write | |
| id-token: write | |
| concurrency: | |
| group: "pages" | |
| cancel-in-progress: false | |
| jobs: | |
| build: | |
| name: Build Book | |
| runs-on: ubuntu-latest | |
| steps: | |
| - uses: actions/checkout@v7 | |
| - name: Install mdBook | |
| run: | | |
| mkdir -p ~/bin | |
| curl -sSL https://github.com/rust-lang/mdBook/releases/download/v0.4.40/mdbook-v0.4.40-x86_64-unknown-linux-gnu.tar.gz | tar -xz -C ~/bin | |
| echo "$HOME/bin" >> $GITHUB_PATH | |
| - name: Build book | |
| run: mdbook build book | |
| # BOOK-CLOSEOUT-001 § Phase 1: shell-script quality (per CLAUDE.md, use bashrs not shellcheck) | |
| - name: bashrs lint book check scripts (FALSIFY-BOOK-SHELL-QUALITY-001) | |
| run: | | |
| cargo install bashrs --locked --quiet | |
| # Lint only check scripts; gen-*-stubs.sh contain markdown heredocs with em-dashes | |
| # that bashrs flags as SC1100, but those are intentional in the generated book output. | |
| bashrs lint scripts/check_book_*.sh 2>&1 | tee /tmp/bashrs.log | |
| ! grep -qE "Summary: [1-9][0-9]* error" /tmp/bashrs.log | |
| # BOOK-CLOSEOUT-001 § Phase 1: zero broken file links | |
| - name: Linkcheck gate (FALSIFY-BOOK-LINKCHECK-001) | |
| run: bash scripts/check_book_linkcheck.sh | |
| # BOOK-CLOSEOUT-001 § Phase 4: every CLI subcommand has a chapter | |
| - name: CLI parity gate (FALSIFY-BOOK-CLI-PARITY-001) | |
| run: | | |
| # apr CLI binary needed for parity check | |
| cargo install --path crates/apr-cli --locked --quiet | |
| bash scripts/check_book_cli_parity.sh | |
| # BOOK-CLOSEOUT-001 § Phase 4: every CLI stub has a runnable example | |
| - name: CLI example-block gate (FALSIFY-BOOK-EXAMPLE-001) | |
| run: bash scripts/check_book_example_block.sh | |
| # BOOK-CLOSEOUT-001 § Phase 3: every aprender-core public module has a chapter | |
| - name: Library parity gate (FALSIFY-BOOK-LIB-PARITY-001) | |
| run: bash scripts/check_book_lib_parity.sh | |
| # BOOK-CLOSEOUT-001 § Phase 3: every lib stub has a runnable rust example | |
| - name: Library example-block gate (FALSIFY-BOOK-LIB-EXAMPLE-001) | |
| run: bash scripts/check_book_lib_example_block.sh | |
| # BOOK-CLOSEOUT-001 § Phase 4: pmat comply gates all book contracts together | |
| # (single check that asserts is_compliant=true; ties the linkcheck + | |
| # parity + example gates into one contract surface) | |
| - name: pmat comply gate (FALSIFY-BOOK-COMPLY-001) | |
| run: | | |
| # Install pmat if not present (most CI runners have it cached) | |
| if ! command -v pmat >/dev/null 2>&1; then | |
| cargo install pmat --locked --quiet || true | |
| fi | |
| # Validate the book-completeness contract via pv. | |
| # | |
| # This line used to call a bare `pv` and exited 127 (command not found) | |
| # the first time the step ever ran: every earlier run died at the parity | |
| # gate above, so nothing reached it. Note the shape of the bug — the step | |
| # guards `pmat` with `command -v` and a comment saying it "tolerates | |
| # absence", then invokes `pv` unguarded one line earlier, in a step whose | |
| # entire purpose is running pv. | |
| # | |
| # `pv` is IN-TREE (crates/aprender-contracts-cli, [[bin]] name = "pv"), so | |
| # build it from the tree instead of depending on an installed copy — that | |
| # is the dogfood rule in CLAUDE.md, and it cannot drift from the contracts | |
| # it is validating. | |
| cargo run --quiet -p aprender-contracts-cli --bin pv -- \ | |
| validate contracts/apr-book-completeness-v1.yaml | |
| # pmat comply check — single binary signal; tolerates absence (pmat may not be available on every runner) | |
| if command -v pmat >/dev/null 2>&1; then | |
| pmat comply check 2>&1 | tail -10 || echo "::warning::pmat comply check returned non-zero (advisory)" | |
| else | |
| echo "::warning::pmat not available — skipping comply gate (advisory)" | |
| fi | |
| - name: Upload artifact | |
| uses: actions/upload-pages-artifact@v5 | |
| with: | |
| path: ./book/book | |
| deploy: | |
| name: Deploy to GitHub Pages | |
| runs-on: ubuntu-latest | |
| needs: build | |
| if: github.event_name == 'push' && github.ref == 'refs/heads/main' | |
| permissions: | |
| pages: write | |
| id-token: write | |
| environment: | |
| name: github-pages | |
| url: ${{ steps.deployment.outputs.page_url }} | |
| steps: | |
| - name: Deploy to GitHub Pages | |
| id: deployment | |
| uses: actions/deploy-pages@v5 |