Pre-Release Maintenance

July 31, 2026 · View on GitHub

Status

Implemented

Abstract

Requirements for pre-release maintenance. Ensures no regressions, stale docs, dependency rot, or security gaps ship in a release.

When to Run

  • Before every minor or major release
  • Quarterly for patch-only periods
  • After large feature merges

Requirements

Dependencies

  • All direct dependencies at latest versions, including major/breaking upgrades
  • Upgrade procedure for each outdated dependency:
    1. Bump version constraint in Cargo.toml (workspace or crate-level)
    2. Run cargo build — fix any compilation errors from API changes
    3. Run cargo test — fix any test failures
    4. If upgrade requires non-trivial refactoring (>50 lines changed), defer to a tracked GitHub issue instead of blocking the maintenance pass
  • cargo update run after all version bumps to lock latest patch versions
  • No known CVEs in dependency tree
  • License and advisory checks pass (deny.toml)
  • Supply chain audit passes
  • Dependency tree analysis (cargo tree --duplicates, usage grep):
    • No unused/dead dependencies in workspace or crate Cargo.toml files
    • Single-builtin deps behind feature flags (not always-on)
    • No full crates where a sub-crate suffices (e.g. futures-util vs futures)
    • Duplicate transitive versions reviewed — fix or document why unfixable

Security

  • Threat model (Threat Model) covers all current features
  • Public threat model doc (crates/bashkit/docs/threat-model.md) in sync with spec
  • Every new builtin/feature has a corresponding TM-XXX entry
  • DeepSec is updated to the latest published version before scanning:
    • Run cd .deepsec && pnpm update deepsec@latest
    • Run pnpm deepsec scan --project-id bashkit
    • Run pnpm deepsec process --project-id bashkit --agent codex
    • Review pnpm deepsec report --project-id bashkit and create GitHub issues for any deferred findings
  • Security tests exist for every MITIGATED threat
  • Failpoint tests pass
  • Unsafe usage reviewed (cargo geiger)
  • No OWASP-style issues (injection, path traversal, etc.)

Tests

  • All tests pass
  • No test gaps for recently added features
  • builtins-drift workflow green (generated builtins.json in sync)
  • Bash compatibility — no new regressions against real bash
  • Coverage reviewed — no major uncovered paths

Documentation

  • Rust crate docs (lib.rs) match reality: command count, categories, guide list, features, examples
  • Guide docs (crates/bashkit/docs/) up to date: compatibility, threat-model, custom_builtins, logging, python
  • Rustdoc builds clean (no warnings)
  • Python docs (crates/bashkit-python/README.md) match current bindings and exports
  • Python docstrings match behavior
  • README.md feature list matches implemented builtins
  • Public docs (docs/) match current code: CLI flags, security boundaries, feature descriptions, test counts, and examples all reflect reality
  • Relative markdown links resolve as source: just check-doc-links green. The site rewrites link targets by basename (DOC_LINKS in site/astro.config.mjs), so a cross-tree link written as a bare jq.md renders correctly on bashkit.sh while 404-ing for anyone reading the markdown on GitHub — site/scripts/verify-doc-*.mjs check the built routes and cannot see it. Write cross-tree links source-relative (../crates/bashkit/docs/jq.md); the site rewriter accepts that form too. Do not add YAML frontmatter to docs/ or crates/bashkit/docs/ to carry titles or descriptions: page metadata lives in site/src/pages/docs/_meta.ts, and frontmatter in crates/bashkit/docs/ would leak into rustdoc via include_str!
  • Agent surfaces (/llms.txt, /llms-full.txt, Markdown routes) regenerate and pass verify-llms (auto-enforced in CI); refresh the agent-skills tarball/index.json digest if skills/bashkit/ changed (see Documentation Architecture § Agent-facing site surfaces)
  • CONTRIBUTING.md instructions accurate
  • CHANGELOG.md has entries for all changes since last release

Examples

  • All Rust examples compile and run
  • Feature-gated examples work (python, git)
  • Python agent examples run end-to-end
  • Code examples in docs/rustdoc still accurate
  • examples/browser uses exact dependency versions and a committed lockfile: run pnpm install --frozen-lockfile && pnpm start, load the page, and confirm it runs a plain command, a pipe through jq, and a subshell (bash /home/user/demo.sh). The subshell path exercises the wasm child-shell parse that a top-level command does not — the smoke suite in crates/bashkit-wasm/__test__/ covers the same ground headlessly. If the published package lags a fix the example depends on, hold the example until the next bashkit-wasm release, then review and update both the dependency pin and lockfile.

Specs

  • Each spec status reflects reality
  • limitations.md rows still true (lifted limitations removed)
  • No orphaned TODOs in specs that are now resolved
  • New features have spec entries

Coreutils Argument-Surface and Module-Vendor Drift

See Coreutils Argument Port.

  • Review any open chore: sync uutils/coreutils argument surfaces and vendored modules PR produced by the coreutils-args-drift workflow (weekly cron). The PR covers both ported argument surfaces (args mode) and vendored uucore modules (module mode):
    • Args mode review: confirm new flags are wired into the consuming builtin or explicitly rejected (matching the existing tac -b/-r/-s "not yet implemented" pattern — no silent no-ops). Confirm removed/renamed flags don't break downstream scripts; migrate or document.
    • Module mode review: for every entry in crates/bashkit-coreutils-port/vendored.toml, scan the diff for body changes in the vendored sources — this is verbatim copy, so upstream behaviour changes land directly. Validate that vendored.toml substitutions still cover every internal use (the port aborts loudly if not, but check that the rationale of any error actions still reflects intent).
    • Squash-merge as a human (PR's intermediate commits are bot-authored).
    • Confirm the coreutils_differential_tests step in the auto-PR is green — body drift (semantic divergence vs GNU/uutils) surfaces here even when args parity holds.
  • Run just regen-coreutils-args locally if no drift PR exists; commit any diff yourself rather than letting it accumulate. Module-mode regen is driven by the same workflow; trigger workflow_dispatch if you need to refresh vendored modules out-of-band.
  • Bump the pinned uutils revision recorded in the generated file headers if it has fallen >3 months behind upstream main.

Code Quality

  • Formatted (cargo fmt)
  • No clippy warnings
  • No stale TODO/WTF comments that are now resolved
  • No dead code or unused dependencies

Code Simplification

  • Duplicated patterns consolidated into shared helpers where it reduces total code
  • Unnecessary abstractions, indirection, or over-engineering removed
  • Complex nested logic simplified (deep nesting, long match arms)
  • Dead code removed (unused functions, unreachable branches, commented-out code)
  • Names are clear and descriptive (functions, variables, types)
  • No premature generalizations — code serves current needs, not hypothetical future ones

Binding Parity

  • Python and Node bindings expose the same public API surface
  • Feature gaps tracked and resolved before release
  • Parity checklist:
    • Core classes: Bash, BashTool, ExecResult, ScriptedTool, BashError
    • Execution methods: execute, execute_sync, executeOrThrow/execute_or_throw
    • Configuration: username, hostname, max_commands, max_loop_iterations, python, external_functions/external_handler
    • Mount API: files dict, mounts list (read-only default), runtime mount/unmount (see Virtual Filesystem § Binding API Parity)
    • Tool metadata: name, description, help, system_prompt, input_schema, output_schema, version
    • Module functions: getVersion/get_version
    • Framework integrations: LangChain available in both bindings
    • ExecResult fields: stdout, stderr, exit_code, error, success, truncation flags, final_env
  • New features added to one binding must have a tracking issue for the other

Agent Configuration

  • AGENTS.md / CLAUDE.md instructions accurate
  • Spec table in AGENTS.md lists all current specs
  • Build/test commands work
  • Pre-PR checklist covers current tooling

CI Health

  • CI on main is green — the latest CI run on main must pass. Any failure (audit, test, lint, examples) is a blocker that must be fixed before proceeding with the rest of the maintenance pass.
  • Nightly and fuzz workflows green for past week
  • Fuzz targets compile
  • Git-sourced dependencies still resolve

Escalation Policy

Failures persisting >2 consecutive days on any workflow (CI, nightly, fuzz) are blocking:

  1. Open GitHub issue with label ci:nightly
  2. Link failing run(s)
  3. Assign to most recent contributor in failing area
  4. If upstream dep change: pin to known-good rev, open follow-up issue

This section is a hard gate. The maintenance pass MUST NOT be marked complete or merged while any of the above checks are red. If the agent cannot fix a failure, it must open a GitHub issue and report the pass as blocked.

Deferred Items

When a maintenance pass identifies issues too large to fix inline (e.g. multi-file refactors, cross-cutting changes), the pass must:

  1. Create a GitHub issue for each deferred item with clear scope and reproduction steps
  2. Record the issue numbers in the summary below so they are tracked

Deferred items are not failures — they are expected for large-scope improvements. The requirement is that they are tracked, not silently skipped.

Deferred items

Standing transitive limitation:

  • RustCrypto 0.10/0.11 split (was tracked as #1634, now closed). Our directly-declared hashes (md-5/sha1/sha2) are on the 0.11 line, but the dependency tree still pulls in the 0.10 line transitively — aes-gcm 0.10.3 (and its digest 0.10 / sha2 0.10 / aead 0.5 / cipher 0.4 chain) via turso_core, plus the russh / argon2 crypto stack. Resolution remains blocked on those upstreams releasing on the 0.11 line; no in-tree action available.

Previously tracked items resolved: #880 (ArgParser migration), #881 (errexit propagation helper).

Automation

Sections dependencies, tests, examples, code quality, and nightly CI are fully automatable. Security, documentation, specs, simplification, and agent config require human or agent review.

CI health check enforced by just check-nightly (nightly + fuzz) and manual inspection of CI on main (audit, test, lint). Called by just release-check.

Invocation

Use /maintain skill to execute this checklist interactively.

References