boost-skill-cli 1.0.396__tar.gz → 1.0.397__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/check_required_checks.py +184 -11
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_required_checks.py +167 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.gitattributes +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.gitignore +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.lycheeignore +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/.vale.ini +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/LICENSE +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/Makefile +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/README.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/chat.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/complete.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/localembed.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/selfupdate.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/codecov.yml +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/carousel.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/chat.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/commands.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/demo-index.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/demo.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/eval-latest.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/index.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/agents-field-records-the-request-not-the-links.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/chat-cites-sources-by-a-number-it-never-prints.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/eval-corpus-is-96x-smaller-than-a-real-install.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/langchain-integration-explainer-page.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/langchain-langgraph-langsmith-integration.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/lighthouse-scored-a-page-nobody-is-served.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/pep585-604-modernization-sweep.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/python-floor-moves-to-312.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/zip-strict-audit.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/docs/roadmap.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/README.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/__init__.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/baseline.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/metrics.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/examples/README.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/index.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/noxfile.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/build_demo_index.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/build_scale_corpus.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/eval_corpus.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/page_budget.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/publish_eval_json.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/scripts/serve_docs.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/setup.cfg +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/sonar-project.properties +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/style/README.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/style/boost.css +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/style/boost.js +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/style/demo.html +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/eval/golden-natural.jsonl +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/eval/taps-scale.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_chat.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_chat.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_complete.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_content_dedupe.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_dedup_trust.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_demo_index.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_dense_fix_hint.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_dense_shards.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_embed_local.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_entry_key.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_eval_baseline.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_eval_corpus.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_eval_grading.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_localembed.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_localembed_e2e.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_page_budget.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_rag_fusion.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_scale_corpus.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_selfupdate.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_serve_docs.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.0.396 → boost_skill_cli-1.0.397}/tests/visual/visual_check.mjs +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 0,
|
|
21
|
+
__version__ = version = '1.0.397'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 397)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -50,6 +50,30 @@ ROOT = Path(__file__).resolve().parent.parent
|
|
|
50
50
|
WORKFLOWS = ROOT / ".github" / "workflows"
|
|
51
51
|
CONFIG = ROOT / ".github" / "required-checks.txt"
|
|
52
52
|
|
|
53
|
+
# `main` is protected TWICE: by a classic branch protection and by a repository
|
|
54
|
+
# ruleset. They are independent objects with independent lists, and applying the
|
|
55
|
+
# file to one leaves the other untouched — which is how the ruleset came to be
|
|
56
|
+
# missing `bdd`, `evals` and `onnx-inference` while this script reported the
|
|
57
|
+
# config clean. It was checking the file against the *workflows*, and emitting a
|
|
58
|
+
# payload for the classic endpoint only; nothing here had ever heard of a
|
|
59
|
+
# ruleset.
|
|
60
|
+
#
|
|
61
|
+
# Which mechanism actually binds is the part that made the gap expensive rather
|
|
62
|
+
# than untidy. The classic protection sets `enforce_admins: false`, so it does
|
|
63
|
+
# not apply to the identity that merges here; the ruleset carries
|
|
64
|
+
# `bypass_actors: []`, so it applies to everyone. The three checks missing from
|
|
65
|
+
# the ruleset were therefore the three that nothing enforced — among them
|
|
66
|
+
# `evals`, the retrieval-quality floor, and `onnx-inference`, whose entry in
|
|
67
|
+
# required-checks.txt says in as many words that the failure it catches is
|
|
68
|
+
# silent.
|
|
69
|
+
GITHUB_API = "https://api.github.com"
|
|
70
|
+
REPO = "jonnyeclectic/boost"
|
|
71
|
+
BRANCH = "main"
|
|
72
|
+
# GitHub Actions' app id. A ruleset records which app must produce each context;
|
|
73
|
+
# leaving it out lets any app satisfy a check by name, which is a weaker gate
|
|
74
|
+
# than the one the file describes.
|
|
75
|
+
ACTIONS_APP_ID = 15368
|
|
76
|
+
|
|
53
77
|
# A job id line: exactly two spaces of indent, directly under `jobs:`.
|
|
54
78
|
_JOB = re.compile(r"^ ([A-Za-z0-9][\w-]*):\s*$")
|
|
55
79
|
# ` name: something` within a job block overrides the displayed check name.
|
|
@@ -238,29 +262,178 @@ def workflows_for(required: str, by_name: Dict[str, List[str]]) -> List[str]:
|
|
|
238
262
|
return ["an unknown workflow"]
|
|
239
263
|
|
|
240
264
|
|
|
265
|
+
def classic_payload(required: List[str]) -> dict:
|
|
266
|
+
"""The `PUT /branches/{branch}/protection` body for this required list."""
|
|
267
|
+
return {
|
|
268
|
+
"required_status_checks": {"strict": True, "contexts": list(required)},
|
|
269
|
+
# Deliberately null: the repo's working model is parallel loop/*
|
|
270
|
+
# branches self-merging, so requiring reviews would deadlock it.
|
|
271
|
+
"required_pull_request_reviews": None,
|
|
272
|
+
"enforce_admins": False,
|
|
273
|
+
"restrictions": None,
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
|
|
277
|
+
def ruleset_rule(required: List[str]) -> dict:
|
|
278
|
+
"""The `required_status_checks` RULE for a repository ruleset.
|
|
279
|
+
|
|
280
|
+
Shaped differently from the classic payload on purpose — this is not a
|
|
281
|
+
stylistic variant of the same thing. A ruleset names each context as an
|
|
282
|
+
object carrying the app that must produce it, and spells `strict` as
|
|
283
|
+
`strict_required_status_checks_policy`. Hand-translating between the two
|
|
284
|
+
forms is exactly the step that got skipped.
|
|
285
|
+
"""
|
|
286
|
+
return {
|
|
287
|
+
"type": "required_status_checks",
|
|
288
|
+
"parameters": {
|
|
289
|
+
"strict_required_status_checks_policy": True,
|
|
290
|
+
"required_status_checks": [
|
|
291
|
+
{"context": c, "integration_id": ACTIONS_APP_ID} for c in required
|
|
292
|
+
],
|
|
293
|
+
},
|
|
294
|
+
}
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
def drift(required: List[str], remote: List[str]) -> Tuple[List[str], List[str]]:
|
|
298
|
+
"""``(missing, extra)`` — how a live mechanism disagrees with the file.
|
|
299
|
+
|
|
300
|
+
Order-insensitive and duplicate-tolerant: GitHub returns contexts in its own
|
|
301
|
+
order, and a list that merely sorts differently is not drift.
|
|
302
|
+
"""
|
|
303
|
+
want, have = set(required), set(remote)
|
|
304
|
+
return sorted(want - have), sorted(have - want)
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
def _api(path: str, token: str) -> object:
|
|
308
|
+
import urllib.request
|
|
309
|
+
req = urllib.request.Request( # noqa: S310 GITHUB_API is a hardcoded https constant
|
|
310
|
+
GITHUB_API + path,
|
|
311
|
+
headers={"Authorization": "Bearer " + token,
|
|
312
|
+
"Accept": "application/vnd.github+json",
|
|
313
|
+
"User-Agent": "boost-check-required-checks"})
|
|
314
|
+
with urllib.request.urlopen(req, timeout=30) as resp: # noqa: S310 same
|
|
315
|
+
return json.load(resp)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
def ruleset_contexts(detail: dict) -> Tuple[bool, List[str]]:
|
|
319
|
+
"""``(has_rule, contexts)`` for one ruleset's required-status-checks rule.
|
|
320
|
+
|
|
321
|
+
``has_rule`` is returned separately from an empty list because the two mean
|
|
322
|
+
opposite things: a ruleset with no such rule requires nothing at all, which
|
|
323
|
+
is a much louder problem than one whose list has drifted.
|
|
324
|
+
"""
|
|
325
|
+
for rule in detail.get("rules", []):
|
|
326
|
+
if rule.get("type") == "required_status_checks":
|
|
327
|
+
params = rule.get("parameters") or {}
|
|
328
|
+
return True, [c.get("context") for c in params.get("required_status_checks", [])]
|
|
329
|
+
return False, []
|
|
330
|
+
|
|
331
|
+
|
|
332
|
+
def verify_remote(required: List[str], token: str) -> List[str]:
|
|
333
|
+
"""Compare BOTH live mechanisms against the file. Returns problems."""
|
|
334
|
+
problems: List[str] = []
|
|
335
|
+
|
|
336
|
+
prot = _api("/repos/%s/branches/%s/protection" % (REPO, BRANCH), token)
|
|
337
|
+
contexts = ((prot or {}).get("required_status_checks") or {}).get("contexts", [])
|
|
338
|
+
missing, extra = drift(required, contexts)
|
|
339
|
+
if missing or extra:
|
|
340
|
+
problems.append(
|
|
341
|
+
"classic branch protection on %r disagrees with %s — missing %s, extra %s "
|
|
342
|
+
"(apply with `--print-api`)"
|
|
343
|
+
% (BRANCH, CONFIG.name, missing or "nothing", extra or "nothing"))
|
|
344
|
+
|
|
345
|
+
rulesets = _api("/repos/%s/rulesets" % REPO, token) or []
|
|
346
|
+
checked = 0
|
|
347
|
+
for summary in rulesets:
|
|
348
|
+
detail = _api("/repos/%s/rulesets/%s" % (REPO, summary["id"]), token)
|
|
349
|
+
includes = ((detail.get("conditions") or {}).get("ref_name") or {}).get("include", [])
|
|
350
|
+
# `~DEFAULT_BRANCH` is GitHub's alias for whatever the default branch is.
|
|
351
|
+
if not ({"refs/heads/" + BRANCH, "~DEFAULT_BRANCH"} & set(includes)):
|
|
352
|
+
continue
|
|
353
|
+
if detail.get("enforcement") != "active":
|
|
354
|
+
continue
|
|
355
|
+
checked += 1
|
|
356
|
+
has_rule, contexts = ruleset_contexts(detail)
|
|
357
|
+
if not has_rule:
|
|
358
|
+
problems.append(
|
|
359
|
+
"active ruleset %r targets %r but has no required_status_checks "
|
|
360
|
+
"rule at all — it gates nothing" % (detail.get("name"), BRANCH))
|
|
361
|
+
continue
|
|
362
|
+
missing, extra = drift(required, contexts)
|
|
363
|
+
if missing or extra:
|
|
364
|
+
problems.append(
|
|
365
|
+
"ruleset %r (id %s) disagrees with %s — missing %s, extra %s "
|
|
366
|
+
"(apply with `--print-ruleset`; send the WHOLE body, a partial "
|
|
367
|
+
"PUT drops the other rules)"
|
|
368
|
+
% (detail.get("name"), detail.get("id"), CONFIG.name,
|
|
369
|
+
missing or "nothing", extra or "nothing"))
|
|
370
|
+
|
|
371
|
+
if not checked:
|
|
372
|
+
# Silence here would read as "the rulesets agree", which is the failure
|
|
373
|
+
# this whole function exists to stop being invisible.
|
|
374
|
+
problems.append(
|
|
375
|
+
"no active ruleset targets %r — if protection moved to rulesets, "
|
|
376
|
+
"this check is now blind; if it did not, one was deleted" % BRANCH)
|
|
377
|
+
return problems
|
|
378
|
+
|
|
379
|
+
|
|
241
380
|
def main(argv: List[str]) -> int:
|
|
242
381
|
ap = argparse.ArgumentParser(description=__doc__)
|
|
243
382
|
ap.add_argument("--print-api", action="store_true",
|
|
244
|
-
help="print the branch-protection
|
|
383
|
+
help="print the CLASSIC branch-protection payload and exit")
|
|
384
|
+
ap.add_argument("--print-ruleset", action="store_true",
|
|
385
|
+
help="print the ruleset required_status_checks rule and exit")
|
|
386
|
+
ap.add_argument("--verify-remote", action="store_true",
|
|
387
|
+
help="compare BOTH live mechanisms against the file "
|
|
388
|
+
"(needs GITHUB_TOKEN; network — not part of `make lint`)")
|
|
245
389
|
args = ap.parse_args(argv)
|
|
246
390
|
|
|
247
391
|
by_name, on_pr, filtered, on_mg = collect()
|
|
248
392
|
required = read_config()
|
|
249
393
|
|
|
250
394
|
if args.print_api:
|
|
251
|
-
payload = {
|
|
252
|
-
"required_status_checks": {"strict": True, "contexts": required},
|
|
253
|
-
# Deliberately null: the repo's working model is parallel loop/*
|
|
254
|
-
# branches self-merging, so requiring reviews would deadlock it.
|
|
255
|
-
"required_pull_request_reviews": None,
|
|
256
|
-
"enforce_admins": False,
|
|
257
|
-
"restrictions": None,
|
|
258
|
-
}
|
|
259
395
|
print("# apply with:")
|
|
260
396
|
print("# curl -X PUT -H \"Authorization: Bearer $GITHUB_TOKEN\" \\")
|
|
261
|
-
print("#
|
|
397
|
+
print("# %s/repos/%s/branches/%s/protection \\" % (GITHUB_API, REPO, BRANCH))
|
|
262
398
|
print("# -d @payload.json")
|
|
263
|
-
print(
|
|
399
|
+
print("# NOTE: this is only HALF of `main`'s protection — see --print-ruleset.")
|
|
400
|
+
print(json.dumps(classic_payload(required), indent=2))
|
|
401
|
+
return 0
|
|
402
|
+
|
|
403
|
+
if args.print_ruleset:
|
|
404
|
+
print("# One rule out of a ruleset body. The ruleset PUT replaces the whole")
|
|
405
|
+
print("# object, so fetch it, swap ONLY this rule, and send it back — a")
|
|
406
|
+
print("# partial body silently drops deletion/non_fast_forward/code_scanning.")
|
|
407
|
+
print("# curl %s/repos/%s/rulesets" % (GITHUB_API, REPO))
|
|
408
|
+
print(json.dumps(ruleset_rule(required), indent=2))
|
|
409
|
+
return 0
|
|
410
|
+
|
|
411
|
+
if args.verify_remote:
|
|
412
|
+
import os
|
|
413
|
+
token = os.environ.get("GITHUB_TOKEN") or os.environ.get("GH_TOKEN")
|
|
414
|
+
if not token:
|
|
415
|
+
# A skip, not a pass: `make lint` never passes this flag, so the
|
|
416
|
+
# offline gate is unaffected, and a caller who asked for the remote
|
|
417
|
+
# check deserves to know it did not happen.
|
|
418
|
+
print("required-checks: --verify-remote skipped (no GITHUB_TOKEN)")
|
|
419
|
+
return 0
|
|
420
|
+
try:
|
|
421
|
+
remote_problems = verify_remote(required, token)
|
|
422
|
+
# A network fault is not drift: exit 2 (could not check) rather than 1
|
|
423
|
+
# (found a problem), so a caller can tell "GitHub was down" from "your
|
|
424
|
+
# protection is wrong" without reading the message.
|
|
425
|
+
except Exception as exc:
|
|
426
|
+
print("required-checks: --verify-remote could not reach GitHub (%s: %s)"
|
|
427
|
+
% (type(exc).__name__, exc), file=sys.stderr)
|
|
428
|
+
return 2
|
|
429
|
+
if remote_problems:
|
|
430
|
+
print("required-checks: %d live-protection problem(s)"
|
|
431
|
+
% len(remote_problems), file=sys.stderr)
|
|
432
|
+
for p in remote_problems:
|
|
433
|
+
print(" - %s" % p, file=sys.stderr)
|
|
434
|
+
return 1
|
|
435
|
+
print("required-checks: live protection matches %s on both mechanisms "
|
|
436
|
+
"(%d checks)." % (CONFIG.name, len(required)))
|
|
264
437
|
return 0
|
|
265
438
|
|
|
266
439
|
problems: List[str] = []
|
|
@@ -352,6 +352,173 @@ class TestPrintApi:
|
|
|
352
352
|
assert payload["required_pull_request_reviews"] is None
|
|
353
353
|
|
|
354
354
|
|
|
355
|
+
class TestRulesetIsTheOtherHalf:
|
|
356
|
+
"""`main` is protected twice, and this gate only ever saw one of them.
|
|
357
|
+
|
|
358
|
+
The classic branch protection and the repository ruleset are independent
|
|
359
|
+
objects with independent lists. Applying `--print-api` updates the classic
|
|
360
|
+
one and leaves the ruleset exactly as it was, which is how the ruleset came
|
|
361
|
+
to be missing `bdd`, `evals` and `onnx-inference` while this script reported
|
|
362
|
+
the config clean — it was comparing the file against the *workflows*, and
|
|
363
|
+
the workflows were fine.
|
|
364
|
+
|
|
365
|
+
The asymmetry is what made that expensive. Classic protection sets
|
|
366
|
+
`enforce_admins: false`, so it does not bind the identity that merges here;
|
|
367
|
+
the ruleset carries `bypass_actors: []`, so it binds everyone. The three
|
|
368
|
+
checks absent from the ruleset were therefore the three nothing enforced.
|
|
369
|
+
"""
|
|
370
|
+
|
|
371
|
+
def _mod(self, tmp_path, monkeypatch):
|
|
372
|
+
workflow(tmp_path, "ci.yml", " lint:\n runs-on: ubuntu-latest\n")
|
|
373
|
+
config(tmp_path, "lint\n")
|
|
374
|
+
return load(monkeypatch, tmp_path)
|
|
375
|
+
|
|
376
|
+
def test_drift_reports_missing_and_extra(self, tmp_path, monkeypatch):
|
|
377
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
378
|
+
missing, extra = m.drift(["a", "b", "c"], ["b", "z"])
|
|
379
|
+
assert missing == ["a", "c"] and extra == ["z"]
|
|
380
|
+
|
|
381
|
+
def test_drift_ignores_order(self, tmp_path, monkeypatch):
|
|
382
|
+
# GitHub returns contexts in its own order; a different sort is not drift.
|
|
383
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
384
|
+
assert m.drift(["a", "b"], ["b", "a"]) == ([], [])
|
|
385
|
+
|
|
386
|
+
def test_the_ruleset_rule_is_not_the_classic_payload(self, tmp_path, monkeypatch):
|
|
387
|
+
# The two API shapes differ in ways a human retyping them gets wrong:
|
|
388
|
+
# a ruleset names each context as an object carrying the producing app,
|
|
389
|
+
# and spells `strict` differently. Pinning it here is what stops the
|
|
390
|
+
# translation step being done from memory.
|
|
391
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
392
|
+
rule = m.ruleset_rule(["lint", "bdd"])
|
|
393
|
+
assert rule["type"] == "required_status_checks"
|
|
394
|
+
p = rule["parameters"]
|
|
395
|
+
assert p["strict_required_status_checks_policy"] is True
|
|
396
|
+
assert p["required_status_checks"] == [
|
|
397
|
+
{"context": "lint", "integration_id": m.ACTIONS_APP_ID},
|
|
398
|
+
{"context": "bdd", "integration_id": m.ACTIONS_APP_ID},
|
|
399
|
+
]
|
|
400
|
+
|
|
401
|
+
def test_ruleset_rule_names_github_actions_as_the_producer(self, tmp_path, monkeypatch):
|
|
402
|
+
# Without integration_id any app could satisfy a check by name, which is
|
|
403
|
+
# a weaker gate than the one required-checks.txt describes.
|
|
404
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
405
|
+
assert m.ACTIONS_APP_ID == 15368
|
|
406
|
+
|
|
407
|
+
def test_a_ruleset_with_no_status_check_rule_is_distinguishable(self, tmp_path, monkeypatch):
|
|
408
|
+
# "requires nothing" and "requires a drifted list" are different faults
|
|
409
|
+
# and get different messages; collapsing them to an empty list hides the
|
|
410
|
+
# louder one.
|
|
411
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
412
|
+
assert m.ruleset_contexts({"rules": [{"type": "deletion"}]}) == (False, [])
|
|
413
|
+
has, ctx = m.ruleset_contexts({"rules": [
|
|
414
|
+
{"type": "required_status_checks",
|
|
415
|
+
"parameters": {"required_status_checks": [{"context": "lint"}]}}]})
|
|
416
|
+
assert has is True and ctx == ["lint"]
|
|
417
|
+
|
|
418
|
+
# ---- verify_remote, driven against a stubbed API ------------------------
|
|
419
|
+
|
|
420
|
+
def _stub(self, m, monkeypatch, *, classic, ruleset_ctx, has_rule=True,
|
|
421
|
+
enforcement="active", includes=("refs/heads/main",)):
|
|
422
|
+
rules = [{"type": "deletion"}]
|
|
423
|
+
if has_rule:
|
|
424
|
+
rules.append({"type": "required_status_checks", "parameters": {
|
|
425
|
+
"required_status_checks": [{"context": c} for c in ruleset_ctx]}})
|
|
426
|
+
detail = {"id": 1, "name": "main", "enforcement": enforcement,
|
|
427
|
+
"conditions": {"ref_name": {"include": list(includes)}},
|
|
428
|
+
"rules": rules}
|
|
429
|
+
|
|
430
|
+
def fake(path, token):
|
|
431
|
+
if path.endswith("/protection"):
|
|
432
|
+
return {"required_status_checks": {"contexts": list(classic)}}
|
|
433
|
+
if path.endswith("/rulesets"):
|
|
434
|
+
return [{"id": 1}]
|
|
435
|
+
return detail
|
|
436
|
+
monkeypatch.setattr(m, "_api", fake)
|
|
437
|
+
|
|
438
|
+
def test_it_catches_the_real_regression(self, tmp_path, monkeypatch):
|
|
439
|
+
# The exact production state: classic correct, ruleset short by three.
|
|
440
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
441
|
+
want = ["lint", "bdd", "evals", "onnx-inference"]
|
|
442
|
+
self._stub(m, monkeypatch, classic=want, ruleset_ctx=["lint"])
|
|
443
|
+
problems = m.verify_remote(want, "t")
|
|
444
|
+
assert len(problems) == 1
|
|
445
|
+
assert "ruleset" in problems[0]
|
|
446
|
+
for name in ("bdd", "evals", "onnx-inference"):
|
|
447
|
+
assert name in problems[0]
|
|
448
|
+
|
|
449
|
+
def test_it_stays_quiet_when_both_agree(self, tmp_path, monkeypatch):
|
|
450
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
451
|
+
want = ["lint", "bdd"]
|
|
452
|
+
self._stub(m, monkeypatch, classic=want, ruleset_ctx=list(reversed(want)))
|
|
453
|
+
assert m.verify_remote(want, "t") == []
|
|
454
|
+
|
|
455
|
+
def test_it_catches_classic_drift_too(self, tmp_path, monkeypatch):
|
|
456
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
457
|
+
want = ["lint", "bdd"]
|
|
458
|
+
self._stub(m, monkeypatch, classic=["lint"], ruleset_ctx=want)
|
|
459
|
+
problems = m.verify_remote(want, "t")
|
|
460
|
+
assert len(problems) == 1 and "classic" in problems[0]
|
|
461
|
+
|
|
462
|
+
def test_a_ruleset_that_gates_nothing_is_loud(self, tmp_path, monkeypatch):
|
|
463
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
464
|
+
want = ["lint"]
|
|
465
|
+
self._stub(m, monkeypatch, classic=want, ruleset_ctx=[], has_rule=False)
|
|
466
|
+
problems = m.verify_remote(want, "t")
|
|
467
|
+
assert any("gates nothing" in p for p in problems)
|
|
468
|
+
|
|
469
|
+
def test_no_active_ruleset_is_reported_rather_than_passing(self, tmp_path, monkeypatch):
|
|
470
|
+
# Silence here would read as "the rulesets agree" — the exact shape of
|
|
471
|
+
# invisibility this whole check exists to remove.
|
|
472
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
473
|
+
want = ["lint"]
|
|
474
|
+
self._stub(m, monkeypatch, classic=want, ruleset_ctx=want,
|
|
475
|
+
enforcement="disabled")
|
|
476
|
+
assert any("no active ruleset" in p for p in m.verify_remote(want, "t"))
|
|
477
|
+
|
|
478
|
+
def test_a_ruleset_for_another_branch_is_not_mistaken_for_main(self, tmp_path, monkeypatch):
|
|
479
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
480
|
+
want = ["lint"]
|
|
481
|
+
self._stub(m, monkeypatch, classic=want, ruleset_ctx=["something-else"],
|
|
482
|
+
includes=("refs/heads/release",))
|
|
483
|
+
problems = m.verify_remote(want, "t")
|
|
484
|
+
# It must not grade main against a release ruleset...
|
|
485
|
+
assert not any("disagrees" in p and "ruleset" in p for p in problems)
|
|
486
|
+
# ...but must still say main has no ruleset covering it.
|
|
487
|
+
assert any("no active ruleset" in p for p in problems)
|
|
488
|
+
|
|
489
|
+
def test_the_default_branch_alias_counts_as_main(self, tmp_path, monkeypatch):
|
|
490
|
+
# GitHub writes `~DEFAULT_BRANCH` rather than a literal ref when the
|
|
491
|
+
# ruleset was created through the UI's default-branch option.
|
|
492
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
493
|
+
want = ["lint"]
|
|
494
|
+
self._stub(m, monkeypatch, classic=want, ruleset_ctx=want,
|
|
495
|
+
includes=("~DEFAULT_BRANCH",))
|
|
496
|
+
assert m.verify_remote(want, "t") == []
|
|
497
|
+
|
|
498
|
+
def test_verify_remote_without_a_token_skips_rather_than_passes(
|
|
499
|
+
self, tmp_path, monkeypatch, capsys):
|
|
500
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
501
|
+
monkeypatch.delenv("GITHUB_TOKEN", raising=False)
|
|
502
|
+
monkeypatch.delenv("GH_TOKEN", raising=False)
|
|
503
|
+
assert m.main(["--verify-remote"]) == 0
|
|
504
|
+
assert "skipped" in capsys.readouterr().out
|
|
505
|
+
|
|
506
|
+
def test_print_ruleset_emits_the_rule(self, tmp_path, monkeypatch, capsys):
|
|
507
|
+
import json
|
|
508
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
509
|
+
assert m.main(["--print-ruleset"]) == 0
|
|
510
|
+
out = capsys.readouterr().out
|
|
511
|
+
rule = json.loads(out[out.index("{"):])
|
|
512
|
+
assert rule["parameters"]["required_status_checks"][0]["context"] == "lint"
|
|
513
|
+
|
|
514
|
+
def test_print_api_now_says_it_is_only_half(self, tmp_path, monkeypatch, capsys):
|
|
515
|
+
# The old output invited exactly the mistake that caused this: it read
|
|
516
|
+
# as though applying it made protection correct.
|
|
517
|
+
m = self._mod(tmp_path, monkeypatch)
|
|
518
|
+
assert m.main(["--print-api"]) == 0
|
|
519
|
+
assert "--print-ruleset" in capsys.readouterr().out
|
|
520
|
+
|
|
521
|
+
|
|
355
522
|
class TestRealRepo:
|
|
356
523
|
def test_the_committed_config_matches_the_real_workflows(self):
|
|
357
524
|
import subprocess
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|