boost-skill-cli 1.0.449__tar.gz → 1.0.450__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.449 → boost_skill_cli-1.0.450}/.vale/styles/config/vocabularies/boost/accept.txt +4 -2
- {boost_skill_cli-1.0.449/boost_skill_cli.egg-info → boost_skill_cli-1.0.450}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/configuration.py +31 -3
- boost_skill_cli-1.0.450/boost_cli/core/selfupdate.py +268 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450/boost_skill_cli.egg-info}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_skill_cli.egg-info/SOURCES.txt +1 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/DEBUGGING.md +36 -0
- boost_skill_cli-1.0.450/docs/roadmap/items/self-update-claims-up-to-date-without-asking.md +52 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap.html +49 -1
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/conftest.py +4 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_configuration.py +70 -4
- boost_skill_cli-1.0.450/tests/unit/test_selfupdate.py +529 -0
- boost_skill_cli-1.0.449/boost_cli/core/selfupdate.py +0 -137
- boost_skill_cli-1.0.449/tests/unit/test_selfupdate.py +0 -265
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.gitattributes +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.gitignore +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.lycheeignore +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/.vale.ini +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/LICENSE +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/Makefile +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/README.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/bmad.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/bootstrap.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/builtin.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/chat.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/complete.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/localembed.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/data/rules/boost-first.mdc +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_langchain/__init__.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_langchain/_compat.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_langchain/graph.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_langchain/loader.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_langchain/py.typed +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_langchain/retriever.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/codecov.yml +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/carousel.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/chat.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/commands.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/demo-index.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/demo.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/eval-latest.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/index.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/langchain.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/agents-field-records-the-request-not-the-links.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/bmad-autopilot-one-command-persona-routing.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/boost-first-carried-the-losing-trigger.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/boost-first-rule.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/boost-langchain-publishing.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/chat-cites-sources-by-a-number-it-never-prints.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/demo-workflow-cancels-other-prs.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/dependabot-splits-multi-path-action-repos.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/discover-searches-github-not-a-stale-sample.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/dry-run-promised-a-link-nobody-makes.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/efficiency-registries-ponytail-caveman.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/est-items-counts-agent-mirrors-as-items.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/eval-corpus-is-96x-smaller-than-a-real-install.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/eval-stats-could-never-publish.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/expanded-card-bodies-overflow.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/gemini-agent-frontmatter-sanitizer.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/heal-deleted-links-it-never-made.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/install-path-disambiguation.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/langchain-in-the-wheel.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/langchain-integration-explainer-page.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/langchain-langgraph-langsmith-integration.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/langchain-retriever-metadata-and-k-floor.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/lighthouse-scored-a-page-nobody-is-served.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-already-covered-defeater.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-search-hid-which-ranking-ran.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mcp-zero-setup-and-three-kinds.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/one-dead-tap-broke-every-update.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/pep585-604-modernization-sweep.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/python-floor-moves-to-312.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/ragas-unpin-when-upstream-ships.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/rules-install-but-cannot-be-governed.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/scripts-under-the-lint-gate.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/search-never-notices-a-new-tap.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/serve-404-reflected-the-request.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/serve-is-a-searchable-catalogue.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/shards-pipeline-never-produced-a-shard.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/sync-could-not-repair-a-gutted-skill.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/tool-call-eval-tier.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/unwatched-crons-hid-a-real-fuzz-crash.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/update-advertises-a-flag-it-rejects.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/update-refreshed-rules-without-a-gate.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/zip-strict-audit.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/zizmor-ignores-drift-and-make-lint-never-ran-it.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/README.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/__init__.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/baseline.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/metrics.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/examples/README.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/index.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/noxfile.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/build_demo_index.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/build_scale_corpus.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/check_required_checks.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/eval_corpus.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/measure_registry.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/page_budget.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/publish_eval_json.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/scripts/serve_docs.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/setup.cfg +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/sonar-project.properties +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/style/README.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/style/boost.css +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/style/boost.js +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/style/demo.html +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/eval/golden-natural.jsonl +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/eval/taps-scale.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_chat.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_kind_conformance.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/langchain/conftest.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/langchain/test_graph.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/langchain/test_loader.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/langchain/test_retriever.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_action_pin_lockstep.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_bmad_core.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_boost_first_offer.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_bootstrap.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_builtin.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_chat.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_complete.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_content_dedupe.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dedup_trust.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_demo_index.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dense_fix_hint.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dense_shard_real_schema.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dense_shard_unreadable_vectors.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dense_shards.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_embed_local.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_entry_key.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_eval_baseline.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_eval_corpus.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_eval_grading.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_failure_alerting_covers_unattended.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_gemini_agent_sanitize.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_gitutil_lfs.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_langchain_packaging.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_link_ownership.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_localembed.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_localembed_e2e.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_measure_registry.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_page_budget.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_rag_fusion.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_registry_control_chars.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_required_checks.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_scale_corpus.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_serve_docs.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_shards_matrix.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_smoke_covers_every_command.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_sync_repairs_gutted_skill.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_workflow_concurrency_groups.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_workflow_push_has_credentials.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/unit/test_zizmor_ignores_still_anchor.py +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/visual/visual_check.mjs +0 -0
|
@@ -55,6 +55,7 @@ onboards
|
|
|
55
55
|
OpenShift
|
|
56
56
|
overclaiming
|
|
57
57
|
Pinecone
|
|
58
|
+
pipx
|
|
58
59
|
PrestaShop
|
|
59
60
|
Pulumi
|
|
60
61
|
pytest
|
|
@@ -65,12 +66,12 @@ reindex
|
|
|
65
66
|
repo
|
|
66
67
|
repo's
|
|
67
68
|
repos
|
|
68
|
-
rerank
|
|
69
69
|
Rerank
|
|
70
|
+
rerank
|
|
70
71
|
reranking
|
|
71
72
|
ruleset
|
|
72
|
-
rulesets
|
|
73
73
|
Rulesets
|
|
74
|
+
rulesets
|
|
74
75
|
sandboxed
|
|
75
76
|
sandboxing
|
|
76
77
|
Shopify
|
|
@@ -98,6 +99,7 @@ unlinking
|
|
|
98
99
|
unregister
|
|
99
100
|
unstaged
|
|
100
101
|
untap
|
|
102
|
+
uv
|
|
101
103
|
Vaadin
|
|
102
104
|
vendored
|
|
103
105
|
vendoring
|
|
@@ -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.450'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 450)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -1498,12 +1498,40 @@ def _self_update_package(method: str, dry_run: bool) -> int:
|
|
|
1498
1498
|
journal.log("self-update", new or old, previous=old, method=method)
|
|
1499
1499
|
if new and new != old:
|
|
1500
1500
|
out.ok("boost v%s → v%s" % (old, new))
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
else:
|
|
1501
|
+
return 0
|
|
1502
|
+
if not new:
|
|
1504
1503
|
# The upgrade succeeded but we never saw a version — say exactly that
|
|
1505
1504
|
# rather than claim one.
|
|
1506
1505
|
out.ok("upgraded via %s; run `boost --version` to confirm" % method)
|
|
1506
|
+
return 0
|
|
1507
|
+
return _report_no_op(method, new)
|
|
1508
|
+
|
|
1509
|
+
|
|
1510
|
+
def _report_no_op(method: str, here: str) -> int:
|
|
1511
|
+
"""Explain a manager that exited 0 without moving the version.
|
|
1512
|
+
|
|
1513
|
+
"The version did not change" is not "you are on the latest release", and
|
|
1514
|
+
boost used to print the second on evidence for only the first. When the
|
|
1515
|
+
index pip resolved against was stale, that told a user who was a release
|
|
1516
|
+
behind that they were current — so ask PyPI which it is, and let the three
|
|
1517
|
+
possible answers say three different things.
|
|
1518
|
+
"""
|
|
1519
|
+
latest = selfupdate.latest_version()
|
|
1520
|
+
if latest is None:
|
|
1521
|
+
# Offline. Report only what was observed; claiming "up to date" here is
|
|
1522
|
+
# the same unearned claim with a different cause.
|
|
1523
|
+
out.ok("boost is unchanged (v%s); could not reach PyPI to confirm it is "
|
|
1524
|
+
"the latest" % here)
|
|
1525
|
+
return 0
|
|
1526
|
+
if selfupdate.is_behind(here, latest):
|
|
1527
|
+
raise BoostError(
|
|
1528
|
+
"%s exited 0 but boost is still v%s — PyPI has v%s"
|
|
1529
|
+
% (method, here, latest),
|
|
1530
|
+
hint="no newer candidate was offered: either the index it resolved "
|
|
1531
|
+
"against was stale, or this environment's python is too old "
|
|
1532
|
+
"for the new wheel. Pin it with `%s`"
|
|
1533
|
+
% " ".join(selfupdate.force_command(method, latest)))
|
|
1534
|
+
out.ok("already up to date (v%s)" % here)
|
|
1507
1535
|
return 0
|
|
1508
1536
|
|
|
1509
1537
|
|
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
"""How this boost was installed, and the command that upgrades it in place.
|
|
2
|
+
|
|
3
|
+
`boost self-update` assumed a git checkout and told everyone else to abandon
|
|
4
|
+
their install method — but the documented way in is `pipx install
|
|
5
|
+
boost-skill-cli` or `pip install boost-skill-cli`, where the package lives in
|
|
6
|
+
site-packages and there is nothing to `git pull`. This resolves the install
|
|
7
|
+
method from evidence on disk and hands the command layer the exact argv that
|
|
8
|
+
upgrades *this* copy.
|
|
9
|
+
|
|
10
|
+
It also answers the question the command layer used to guess at: **is this copy
|
|
11
|
+
actually current?** "The version did not change" and "you are on the latest
|
|
12
|
+
release" are different propositions, and conflating them let boost tell a user
|
|
13
|
+
who was one release behind that they were up to date. See :func:`latest_version`
|
|
14
|
+
and :func:`is_behind`.
|
|
15
|
+
"""
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
import http.client
|
|
19
|
+
import json
|
|
20
|
+
import os
|
|
21
|
+
import re
|
|
22
|
+
import shutil
|
|
23
|
+
import subprocess
|
|
24
|
+
import sys
|
|
25
|
+
import urllib.error
|
|
26
|
+
import urllib.request
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
from ..errors import BoostError
|
|
30
|
+
from . import gitutil, nethttp, paths
|
|
31
|
+
|
|
32
|
+
DIST = "boost-skill-cli"
|
|
33
|
+
|
|
34
|
+
GIT = "git"
|
|
35
|
+
PIPX = "pipx"
|
|
36
|
+
UV_TOOL = "uv-tool"
|
|
37
|
+
PIP = "pip"
|
|
38
|
+
UNKNOWN = "unknown"
|
|
39
|
+
|
|
40
|
+
PYPI_JSON = "https://pypi.org/pypi/%s/json" % DIST
|
|
41
|
+
|
|
42
|
+
# `boost --version` prints "boost <version>"; anything else means we did not
|
|
43
|
+
# actually observe a version and must not report one.
|
|
44
|
+
_VERSION_LINE = re.compile(r"^boost\s+(\S+)$", re.MULTILINE)
|
|
45
|
+
|
|
46
|
+
# Leading digits of one dotted segment. Enough to read the numeric release
|
|
47
|
+
# prefix out of `1.0.423` and out of a setuptools-scm `1.0.424.dev3+g36b74ba`.
|
|
48
|
+
_LEADING_DIGITS = re.compile(r"\d+")
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
def installed_version() -> str | None:
|
|
52
|
+
"""Version recorded in installed package metadata, or None.
|
|
53
|
+
|
|
54
|
+
None is the useful answer, not a failure: it means no Python package
|
|
55
|
+
manager has a record of this boost, so none of them can upgrade it.
|
|
56
|
+
"""
|
|
57
|
+
try:
|
|
58
|
+
from importlib.metadata import version
|
|
59
|
+
return version(DIST)
|
|
60
|
+
except Exception:
|
|
61
|
+
return None
|
|
62
|
+
|
|
63
|
+
|
|
64
|
+
def detect(root: Path | None = None, prefix: Path | None = None,
|
|
65
|
+
metadata_version=None) -> str:
|
|
66
|
+
"""Resolve how this boost was installed.
|
|
67
|
+
|
|
68
|
+
Order matters. A source checkout wins first — that includes `pip install
|
|
69
|
+
-e .`, where the package metadata exists too but `git pull` is what the
|
|
70
|
+
user means. Then the two managers that own a private venv and leave a
|
|
71
|
+
receipt inside it. Then plain pip, but only if pip actually has a record
|
|
72
|
+
of the distribution: telling someone to `pip install --upgrade` a boost
|
|
73
|
+
that pip never installed sends them chasing a package that isn't there.
|
|
74
|
+
"""
|
|
75
|
+
root = paths.repo_root() if root is None else Path(root)
|
|
76
|
+
if gitutil.is_repo(root):
|
|
77
|
+
return GIT
|
|
78
|
+
prefix = Path(sys.prefix) if prefix is None else Path(prefix)
|
|
79
|
+
if (prefix / "pipx_metadata.json").is_file():
|
|
80
|
+
return PIPX
|
|
81
|
+
if (prefix / "uv-receipt.toml").is_file():
|
|
82
|
+
return UV_TOOL
|
|
83
|
+
# Resolved here, not as a default argument: a default binds the function
|
|
84
|
+
# object once at import, which silently defeats every attempt to swap it —
|
|
85
|
+
# including a test's, which is how a test of the "nothing installed this"
|
|
86
|
+
# branch ended up running a real `pip install` against PyPI.
|
|
87
|
+
lookup = installed_version if metadata_version is None else metadata_version
|
|
88
|
+
return PIP if lookup() else UNKNOWN
|
|
89
|
+
|
|
90
|
+
|
|
91
|
+
def _require(tool: str) -> str:
|
|
92
|
+
"""Absolute path to `tool`, or a BoostError naming what is missing.
|
|
93
|
+
|
|
94
|
+
Falling back to another manager here would upgrade a different copy of
|
|
95
|
+
boost — or none at all — while reporting success.
|
|
96
|
+
"""
|
|
97
|
+
found = shutil.which(tool)
|
|
98
|
+
if not found:
|
|
99
|
+
raise BoostError(
|
|
100
|
+
"boost was installed with %s, but %s is not on PATH" % (tool, tool),
|
|
101
|
+
hint="install %s, or upgrade manually with `%s upgrade %s`"
|
|
102
|
+
% (tool, tool, DIST))
|
|
103
|
+
return found
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
def upgrade_command(method: str) -> list[str]:
|
|
107
|
+
"""The argv that upgrades boost for `method`.
|
|
108
|
+
|
|
109
|
+
Each manager is told to fetch a fresh package index. PyPI serves the simple
|
|
110
|
+
index with ``Cache-Control: max-age=600`` and pip honours it, so two
|
|
111
|
+
self-updates inside ten minutes are answered from pip's HTTP cache — and a
|
|
112
|
+
release published between them is invisible. That is not hypothetical: three
|
|
113
|
+
consecutive `pipx upgrade` runs spanning the 1.0.423 upload all reported
|
|
114
|
+
"Requirement already satisfied ... (1.0.422)" off a cached index fetched
|
|
115
|
+
eight minutes before the wheel existed.
|
|
116
|
+
|
|
117
|
+
The flag differs per manager because the managers differ: pip has no
|
|
118
|
+
index-only refresh, so it gets `--no-cache-dir`, while uv does and gets
|
|
119
|
+
`--refresh` (keeping its wheel cache). Don't collapse them into one shape.
|
|
120
|
+
"""
|
|
121
|
+
if method == PIPX:
|
|
122
|
+
# pipx owns the venv and shells out to its pip; `--pip-args` is how the
|
|
123
|
+
# flag reaches that pip. The `=` form is required — the value itself
|
|
124
|
+
# starts with `--`.
|
|
125
|
+
return [_require("pipx"), "upgrade", DIST, "--pip-args=--no-cache-dir"]
|
|
126
|
+
if method == UV_TOOL:
|
|
127
|
+
return [_require("uv"), "tool", "upgrade", "--refresh", DIST]
|
|
128
|
+
if method == PIP:
|
|
129
|
+
# sys.executable, never a bare `pip`: the pip first on PATH can belong
|
|
130
|
+
# to a different interpreter than the one running boost, and upgrading
|
|
131
|
+
# that one leaves this install exactly where it was while printing
|
|
132
|
+
# every sign of success.
|
|
133
|
+
return [sys.executable, "-m", "pip", "install", "--no-cache-dir",
|
|
134
|
+
"--upgrade", DIST]
|
|
135
|
+
raise BoostError(
|
|
136
|
+
"cannot work out how boost was installed, so it cannot update itself",
|
|
137
|
+
hint="upgrade with your package manager, e.g. `pipx upgrade %s`" % DIST)
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def force_command(method: str, version: str) -> list[str]:
|
|
141
|
+
"""The argv that pins boost to `version`, bypassing the resolver.
|
|
142
|
+
|
|
143
|
+
Offered only when the manager exited 0 without moving the version while
|
|
144
|
+
PyPI has a newer one. A plain `upgrade` is no help there — the resolver has
|
|
145
|
+
already declined — so this names the exact version and forces the install.
|
|
146
|
+
"""
|
|
147
|
+
spec = "%s==%s" % (DIST, version)
|
|
148
|
+
if method == PIPX:
|
|
149
|
+
return [_require("pipx"), "install", "--force", spec]
|
|
150
|
+
if method == UV_TOOL:
|
|
151
|
+
return [_require("uv"), "tool", "install", "--force", spec]
|
|
152
|
+
if method == PIP:
|
|
153
|
+
return [sys.executable, "-m", "pip", "install", "--no-cache-dir",
|
|
154
|
+
"--force-reinstall", spec]
|
|
155
|
+
raise BoostError(
|
|
156
|
+
"cannot work out how boost was installed, so it cannot update itself",
|
|
157
|
+
hint="install the version by hand, e.g. `pipx install --force %s`" % spec)
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def latest_version(timeout: float = 10.0) -> str | None:
|
|
161
|
+
"""Newest version PyPI publishes for boost, or None if we could not ask.
|
|
162
|
+
|
|
163
|
+
None is the load-bearing third answer, as in ``scripts/release_guard.py``:
|
|
164
|
+
it means "PyPI did not tell us", and the caller must not read it as either
|
|
165
|
+
"up to date" or "behind". Every failure — offline, DNS, 503, a maintenance
|
|
166
|
+
HTML page where JSON was expected — degrades to None rather than raising,
|
|
167
|
+
because a version check is never worth failing a self-update over.
|
|
168
|
+
|
|
169
|
+
``BOOST_NO_NET=1`` skips the request entirely, the same contract as
|
|
170
|
+
``BOOST_NO_AI`` / ``BOOST_NO_SEED``: an air-gapped user (or a test) can
|
|
171
|
+
guarantee nothing leaves the machine.
|
|
172
|
+
"""
|
|
173
|
+
if os.environ.get("BOOST_NO_NET"):
|
|
174
|
+
return None
|
|
175
|
+
# S310 is suppressed below: PYPI_JSON is a module constant with an https
|
|
176
|
+
# scheme and no caller-controlled component.
|
|
177
|
+
req = urllib.request.Request( # noqa: S310
|
|
178
|
+
PYPI_JSON, headers={"Accept": "application/json",
|
|
179
|
+
"User-Agent": "boost-self-update"})
|
|
180
|
+
try:
|
|
181
|
+
with nethttp.urlopen(req, timeout=timeout) as resp:
|
|
182
|
+
if not 200 <= getattr(resp, "status", 0) < 300:
|
|
183
|
+
return None
|
|
184
|
+
payload = json.loads(resp.read().decode("utf-8", "replace"))
|
|
185
|
+
# http.client.HTTPException covers the body going wrong after the headers
|
|
186
|
+
# arrived — the response is ~735 KB (every release's file list), so a
|
|
187
|
+
# connection that drops mid-read raises IncompleteRead. Listing it
|
|
188
|
+
# explicitly is load-bearing: on CPython <= 3.13 IncompleteRead was also a
|
|
189
|
+
# ValueError and JSONDecodeError's clause swallowed it, but on 3.14 its
|
|
190
|
+
# only base is HTTPException, and it escaped this function as a traceback.
|
|
191
|
+
except (urllib.error.URLError, OSError, TimeoutError, ValueError,
|
|
192
|
+
http.client.HTTPException):
|
|
193
|
+
return None
|
|
194
|
+
info = payload.get("info") if isinstance(payload, dict) else None
|
|
195
|
+
version = info.get("version") if isinstance(info, dict) else None
|
|
196
|
+
if not isinstance(version, str) or not version.strip():
|
|
197
|
+
return None
|
|
198
|
+
return version.strip()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def _release_key(version: str) -> tuple[int, ...]:
|
|
202
|
+
"""The leading numeric release segments of `version`, as ints.
|
|
203
|
+
|
|
204
|
+
Deliberately not a PEP 440 parser: `packaging` is not a dependency of the
|
|
205
|
+
zero-dependency install, boost ships `1.0.N`, and the only other shape that
|
|
206
|
+
reaches here is a setuptools-scm dev string (`1.0.424.dev3+g36b74ba`).
|
|
207
|
+
Comparing the numeric release prefix answers "is PyPI ahead of me" for
|
|
208
|
+
both. An empty tuple means "not a version we can reason about".
|
|
209
|
+
"""
|
|
210
|
+
head = version.strip().lstrip("v").split("+", 1)[0]
|
|
211
|
+
parts: list[int] = []
|
|
212
|
+
for chunk in head.split("."):
|
|
213
|
+
m = _LEADING_DIGITS.match(chunk)
|
|
214
|
+
if not m:
|
|
215
|
+
break
|
|
216
|
+
parts.append(int(m.group()))
|
|
217
|
+
return tuple(parts)
|
|
218
|
+
|
|
219
|
+
|
|
220
|
+
def is_behind(installed: str | None, latest: str | None) -> bool:
|
|
221
|
+
"""True only when `latest` is visibly a newer release than `installed`.
|
|
222
|
+
|
|
223
|
+
Compares numbers, not text — `"1.0.9" > "1.0.10"` lexicographically, which
|
|
224
|
+
is how a version check ships an upgrade nag that never clears. Every
|
|
225
|
+
uncertain input (either side missing or unparseable) is False: a spurious
|
|
226
|
+
"you are behind" would turn a successful upgrade into an alarm, and no
|
|
227
|
+
version string is worth that.
|
|
228
|
+
"""
|
|
229
|
+
if not installed or not latest:
|
|
230
|
+
return False
|
|
231
|
+
here, there = _release_key(installed), _release_key(latest)
|
|
232
|
+
if not here or not there:
|
|
233
|
+
return False
|
|
234
|
+
return there > here
|
|
235
|
+
|
|
236
|
+
|
|
237
|
+
def run_upgrade(cmd: list[str], timeout: float = 300.0):
|
|
238
|
+
"""Run the upgrade, raising BoostError with the manager's own last words."""
|
|
239
|
+
try:
|
|
240
|
+
proc = subprocess.run(cmd, capture_output=True, text=True,
|
|
241
|
+
timeout=timeout)
|
|
242
|
+
except (OSError, subprocess.SubprocessError) as err:
|
|
243
|
+
raise BoostError("could not run %s" % " ".join(cmd),
|
|
244
|
+
hint=str(err)) from err
|
|
245
|
+
if proc.returncode != 0:
|
|
246
|
+
detail = ((proc.stderr or "") + (proc.stdout or "")).strip().splitlines()
|
|
247
|
+
raise BoostError(
|
|
248
|
+
"upgrade failed (%s exited %d)" % (Path(cmd[0]).name, proc.returncode),
|
|
249
|
+
hint=detail[-1] if detail else "re-run the command by hand to see why")
|
|
250
|
+
return proc
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def observed_version(timeout: float = 30.0) -> str | None:
|
|
254
|
+
"""Ask a freshly-spawned boost what version it is now, or None.
|
|
255
|
+
|
|
256
|
+
This process imported its own version before the upgrade ran, so it cannot
|
|
257
|
+
answer the question. None means "we did not see one" — better to say
|
|
258
|
+
nothing than to report a version we never observed.
|
|
259
|
+
"""
|
|
260
|
+
try:
|
|
261
|
+
proc = subprocess.run([str(paths.launcher()), "--version"],
|
|
262
|
+
capture_output=True, text=True, timeout=timeout)
|
|
263
|
+
except (OSError, subprocess.SubprocessError):
|
|
264
|
+
return None
|
|
265
|
+
if proc.returncode != 0:
|
|
266
|
+
return None
|
|
267
|
+
match = _VERSION_LINE.search(proc.stdout or "")
|
|
268
|
+
return match.group(1) if match else None
|
|
@@ -382,6 +382,7 @@ docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md
|
|
|
382
382
|
docs/roadmap/items/secret-scanning-gitleaks-push-protection.md
|
|
383
383
|
docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md
|
|
384
384
|
docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md
|
|
385
|
+
docs/roadmap/items/self-update-claims-up-to-date-without-asking.md
|
|
385
386
|
docs/roadmap/items/serve-404-reflected-the-request.md
|
|
386
387
|
docs/roadmap/items/serve-is-a-searchable-catalogue.md
|
|
387
388
|
docs/roadmap/items/serve-py-traversal-guards-untested.md
|
|
@@ -166,6 +166,41 @@ reports are present, so a stuck environment points you at its own evidence.
|
|
|
166
166
|
|
|
167
167
|
---
|
|
168
168
|
|
|
169
|
+
## `boost self-update` didn't move
|
|
170
|
+
|
|
171
|
+
`boost self-update` drives whatever installed this copy — `pipx upgrade`,
|
|
172
|
+
`uv tool upgrade`, or `<this python> -m pip install --upgrade`. Use
|
|
173
|
+
`--dry-run` to see the exact command without running it:
|
|
174
|
+
|
|
175
|
+
```bash
|
|
176
|
+
boost self-update --dry-run
|
|
177
|
+
# installed with: pipx
|
|
178
|
+
# would run: /opt/homebrew/bin/pipx upgrade boost-skill-cli --pip-args=--no-cache-dir
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
**Why the no-cache flag is there.** PyPI serves its package index with
|
|
182
|
+
`Cache-Control: max-age=600` and pip honours it, so two upgrades inside ten
|
|
183
|
+
minutes are answered from pip's HTTP cache — and a release published in between
|
|
184
|
+
is invisible. pip then says `Requirement already satisfied` and exits 0. Every
|
|
185
|
+
manager is therefore told to refresh its index (`--refresh` for uv, which has an
|
|
186
|
+
index-only refresh; `--no-cache-dir` for pip and pipx, which don't).
|
|
187
|
+
|
|
188
|
+
**If the version still doesn't move**, boost does not report success. It asks
|
|
189
|
+
PyPI what the newest release is and says which of three things happened:
|
|
190
|
+
|
|
191
|
+
| What you see | What it means |
|
|
192
|
+
|--------------|---------------|
|
|
193
|
+
| `boost v1.0.422 → v1.0.423` | upgraded |
|
|
194
|
+
| `already up to date (v1.0.423)` | PyPI confirms this is the newest release |
|
|
195
|
+
| `boost is unchanged (v…); could not reach PyPI to confirm…` | nothing moved and the check couldn't run — no claim either way |
|
|
196
|
+
| `pipx exited 0 but boost is still v… — PyPI has v…` | the manager declined to upgrade; the hint gives you a pinned, forced install |
|
|
197
|
+
|
|
198
|
+
That last case is usually a stale index or an environment whose Python is too
|
|
199
|
+
old for the new wheel. The hint names the exact command to force it, because a
|
|
200
|
+
plain `upgrade` has already been tried and refused.
|
|
201
|
+
|
|
202
|
+
---
|
|
203
|
+
|
|
169
204
|
## Environment variables
|
|
170
205
|
|
|
171
206
|
Everything that changes boost's runtime behaviour, in one place:
|
|
@@ -179,6 +214,7 @@ Everything that changes boost's runtime behaviour, in one place:
|
|
|
179
214
|
| `BOOST_LOG_FORMAT` | `text` (default) or `json` — one JSON object per log line |
|
|
180
215
|
| `BOOST_NO_LOG` | `=1` → don't write the diagnostic log file |
|
|
181
216
|
| `BOOST_NO_AI` | `=1` → disable all AI calls (offline / deterministic) |
|
|
217
|
+
| `BOOST_NO_NET` | `=1` → skip the PyPI version check in `self-update` (air-gapped) |
|
|
182
218
|
| `BOOST_ASSUME_YES` | `=1` → auto-confirm prompts (also `--yes`/`-y`) |
|
|
183
219
|
| `NO_COLOR` / `CLICOLOR_FORCE` | force color off / on |
|
|
184
220
|
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: self-update-claims-up-to-date-without-asking
|
|
3
|
+
board: code
|
|
4
|
+
section: compat
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Bug
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: High
|
|
9
|
+
wow: 4
|
|
10
|
+
note:
|
|
11
|
+
order: 11
|
|
12
|
+
owner: loop/self-update-freshness
|
|
13
|
+
pr:
|
|
14
|
+
title: <code>self-update</code> said "already up to date" without asking PyPI
|
|
15
|
+
---
|
|
16
|
+
<code>boost self-update</code> inferred "already up to date (vN)" from the fact that
|
|
17
|
+
<code>observed_version()</code> came back unchanged. Those are two different propositions, and the
|
|
18
|
+
gap between them is exactly one stale HTTP cache wide. Observed on the 1.0.422 → 1.0.423 release:
|
|
19
|
+
PyPI serves the simple index with <code>Cache-Control: max-age=600</code> and pip honours it, so a
|
|
20
|
+
<code>pipx upgrade</code> at 13:15 — eight minutes before the 1.0.423 wheel existed — cached an
|
|
21
|
+
index that had never heard of it, and the two retries at 13:22 and 13:23 (the second one
|
|
22
|
+
<em>after</em> the upload) were both answered from that cache. pip's own words each time:
|
|
23
|
+
<code>Requirement already satisfied: boost-skill-cli in ./lib/python3.14/site-packages
|
|
24
|
+
(1.0.422)</code>. pipx exited 0, the version did not move, and boost reported that the user was
|
|
25
|
+
current while they were a release behind — the most expensive kind of wrong answer, because it
|
|
26
|
+
tells you to stop looking.
|
|
27
|
+
|
|
28
|
+
Fixed at both ends. <code>upgrade_command()</code> now tells each manager to refresh its index
|
|
29
|
+
(<code>--pip-args=--no-cache-dir</code> for pipx, <code>--no-cache-dir</code> for pip,
|
|
30
|
+
<code>--refresh</code> for uv — pip has no index-only refresh and uv does, so the flag is
|
|
31
|
+
per-manager rather than one shape), which removes the cause. And <code>selfupdate.latest_version()</code>
|
|
32
|
+
asks PyPI's JSON API what the newest release actually is, so a no-op upgrade now has three
|
|
33
|
+
distinct outcomes instead of one claim: PyPI is ahead → a <code>BoostError</code> naming both
|
|
34
|
+
versions plus <code>force_command()</code>, which pins the exact version and forces the install
|
|
35
|
+
(a plain upgrade is no help — the resolver has already declined); PyPI agrees → "already up to
|
|
36
|
+
date"; PyPI unreachable → "boost is unchanged (vN); could not reach PyPI to confirm it is the
|
|
37
|
+
latest", because an unearned claim with a different cause is the same bug. <code>None</code> is
|
|
38
|
+
the load-bearing third answer throughout, as in <code>scripts/release_guard.py</code>, and
|
|
39
|
+
<code>is_behind()</code> compares release numbers rather than text — <code>"1.0.9" > "1.0.10"</code>
|
|
40
|
+
lexicographically, which is how a version check ships a nag that never clears.
|
|
41
|
+
|
|
42
|
+
Two findings came out of pointing the new code at real PyPI rather than only at fakes. The
|
|
43
|
+
payload is ~735 KB (the JSON API embeds every release's file list), and a body that drops
|
|
44
|
+
mid-read raises <code>http.client.IncompleteRead</code> — which on CPython ≤ 3.13 was also a
|
|
45
|
+
<code>ValueError</code> and was caught by accident, but on 3.14 has <code>HTTPException</code> as
|
|
46
|
+
its only base and escaped as a traceback out of a check that must never fail. It is now caught
|
|
47
|
+
explicitly. The endpoint stays the fatter one on purpose: <code>info.version</code> excludes
|
|
48
|
+
yanked releases, and computing the max over the leaner simple-API version list would offer a
|
|
49
|
+
yanked release as "newer" and hand the user a force command that installs it.
|
|
50
|
+
<code>BOOST_NO_NET=1</code> skips the request entirely, the same contract as
|
|
51
|
+
<code>BOOST_NO_AI</code> / <code>BOOST_NO_SEED</code>, and the test sandbox sets it so no test
|
|
52
|
+
reaches the network as a side effect of checking what a command prints.
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
<div class="stat"><b>16</b><span>Shipped</span></div>
|
|
134
134
|
<div class="stat"><b>1</b><span>Next up</span></div>
|
|
135
135
|
<div class="stat"><b>7</b><span>Planned</span></div>
|
|
136
|
-
<div class="stat"><b>
|
|
136
|
+
<div class="stat"><b>245</b><span>Loop finds</span></div>
|
|
137
137
|
<!-- /ROADMAP:stats -->
|
|
138
138
|
</div>
|
|
139
139
|
</section>
|
|
@@ -9108,6 +9108,54 @@ nothing, neither does boost.</p></details>
|
|
|
9108
9108
|
</div>
|
|
9109
9109
|
</article>
|
|
9110
9110
|
|
|
9111
|
+
<article class="cap rcard" id="self-update-claims-up-to-date-without-asking">
|
|
9112
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug</span></div>
|
|
9113
|
+
<h3><code>self-update</code> said "already up to date" without asking PyPI</h3>
|
|
9114
|
+
<details class="cardbody"><summary>Write-up</summary>
|
|
9115
|
+
<p><code>boost self-update</code> inferred "already up to date (vN)" from the fact that
|
|
9116
|
+
<code>observed_version()</code> came back unchanged. Those are two different propositions, and the
|
|
9117
|
+
gap between them is exactly one stale HTTP cache wide. Observed on the 1.0.422 → 1.0.423 release:
|
|
9118
|
+
PyPI serves the simple index with <code>Cache-Control: max-age=600</code> and pip honours it, so a
|
|
9119
|
+
<code>pipx upgrade</code> at 13:15 — eight minutes before the 1.0.423 wheel existed — cached an
|
|
9120
|
+
index that had never heard of it, and the two retries at 13:22 and 13:23 (the second one
|
|
9121
|
+
<em>after</em> the upload) were both answered from that cache. pip's own words each time:
|
|
9122
|
+
<code>Requirement already satisfied: boost-skill-cli in ./lib/python3.14/site-packages
|
|
9123
|
+
(1.0.422)</code>. pipx exited 0, the version did not move, and boost reported that the user was
|
|
9124
|
+
current while they were a release behind — the most expensive kind of wrong answer, because it
|
|
9125
|
+
tells you to stop looking.
|
|
9126
|
+
|
|
9127
|
+
Fixed at both ends. <code>upgrade_command()</code> now tells each manager to refresh its index
|
|
9128
|
+
(<code>--pip-args=--no-cache-dir</code> for pipx, <code>--no-cache-dir</code> for pip,
|
|
9129
|
+
<code>--refresh</code> for uv — pip has no index-only refresh and uv does, so the flag is
|
|
9130
|
+
per-manager rather than one shape), which removes the cause. And <code>selfupdate.latest_version()</code>
|
|
9131
|
+
asks PyPI's JSON API what the newest release actually is, so a no-op upgrade now has three
|
|
9132
|
+
distinct outcomes instead of one claim: PyPI is ahead → a <code>BoostError</code> naming both
|
|
9133
|
+
versions plus <code>force_command()</code>, which pins the exact version and forces the install
|
|
9134
|
+
(a plain upgrade is no help — the resolver has already declined); PyPI agrees → "already up to
|
|
9135
|
+
date"; PyPI unreachable → "boost is unchanged (vN); could not reach PyPI to confirm it is the
|
|
9136
|
+
latest", because an unearned claim with a different cause is the same bug. <code>None</code> is
|
|
9137
|
+
the load-bearing third answer throughout, as in <code>scripts/release_guard.py</code>, and
|
|
9138
|
+
<code>is_behind()</code> compares release numbers rather than text — <code>"1.0.9" > "1.0.10"</code>
|
|
9139
|
+
lexicographically, which is how a version check ships a nag that never clears.
|
|
9140
|
+
|
|
9141
|
+
Two findings came out of pointing the new code at real PyPI rather than only at fakes. The
|
|
9142
|
+
payload is ~735 KB (the JSON API embeds every release's file list), and a body that drops
|
|
9143
|
+
mid-read raises <code>http.client.IncompleteRead</code> — which on CPython ≤ 3.13 was also a
|
|
9144
|
+
<code>ValueError</code> and was caught by accident, but on 3.14 has <code>HTTPException</code> as
|
|
9145
|
+
its only base and escaped as a traceback out of a check that must never fail. It is now caught
|
|
9146
|
+
explicitly. The endpoint stays the fatter one on purpose: <code>info.version</code> excludes
|
|
9147
|
+
yanked releases, and computing the max over the leaner simple-API version list would offer a
|
|
9148
|
+
yanked release as "newer" and hand the user a force command that installs it.
|
|
9149
|
+
<code>BOOST_NO_NET=1</code> skips the request entirely, the same contract as
|
|
9150
|
+
<code>BOOST_NO_AI</code> / <code>BOOST_NO_SEED</code>, and the test sandbox sets it so no test
|
|
9151
|
+
reaches the network as a side effect of checking what a command prints.</p></details>
|
|
9152
|
+
<div class="meta">
|
|
9153
|
+
<span class="m">Complexity <b>S</b></span>
|
|
9154
|
+
<span class="m hi">Impact <b>High</b></span>
|
|
9155
|
+
<span class="m">Wow <b class="wow">★★★★</b></span>
|
|
9156
|
+
</div>
|
|
9157
|
+
</article>
|
|
9158
|
+
|
|
9111
9159
|
<article class="cap rcard" id="mcp-register-names-server-before-env">
|
|
9112
9160
|
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug · MCP</span></div>
|
|
9113
9161
|
<h3>Order the server name before -e flags in `boost mcp register`</h3>
|
|
@@ -99,6 +99,10 @@ def sandbox(tmp_path, monkeypatch):
|
|
|
99
99
|
# which this fixture also sets, so without this guard every register
|
|
100
100
|
# test would silently write a standing block into its sandbox HOME.
|
|
101
101
|
monkeypatch.setenv("BOOST_NO_RULE", "1")
|
|
102
|
+
# `self-update` asks PyPI which version is newest before it will claim to
|
|
103
|
+
# be up to date. Same contract again: no test reaches the network as a side
|
|
104
|
+
# effect of checking what a command prints.
|
|
105
|
+
monkeypatch.setenv("BOOST_NO_NET", "1")
|
|
102
106
|
monkeypatch.delenv("VOYAGE_API_KEY", raising=False) # no real embed calls
|
|
103
107
|
monkeypatch.delenv("OPENAI_API_KEY", raising=False)
|
|
104
108
|
monkeypatch.delenv("BOOST_NO_EMBED", raising=False)
|
{boost_skill_cli-1.0.449 → boost_skill_cli-1.0.450}/tests/functional/test_cli_configuration.py
RENAMED
|
@@ -1660,7 +1660,8 @@ class TestSelfUpdate:
|
|
|
1660
1660
|
self._pipx_install(monkeypatch, sandbox)
|
|
1661
1661
|
r = boost("self-update", "--dry-run")
|
|
1662
1662
|
assert "installed with: pipx" in r.out
|
|
1663
|
-
assert "would run: /opt/bin/pipx upgrade boost-skill-cli"
|
|
1663
|
+
assert ("would run: /opt/bin/pipx upgrade boost-skill-cli "
|
|
1664
|
+
"--pip-args=--no-cache-dir") in r.out
|
|
1664
1665
|
|
|
1665
1666
|
def test_plain_pip_install_upgrades_with_this_interpreter(
|
|
1666
1667
|
self, boost, sandbox, monkeypatch):
|
|
@@ -1670,8 +1671,8 @@ class TestSelfUpdate:
|
|
|
1670
1671
|
lambda: "1.0.0")
|
|
1671
1672
|
r = boost("self-update", "--dry-run")
|
|
1672
1673
|
assert "installed with: pip" in r.out
|
|
1673
|
-
assert ("would run: %s -m pip install --upgrade
|
|
1674
|
-
% sys.executable) in r.out
|
|
1674
|
+
assert ("would run: %s -m pip install --no-cache-dir --upgrade "
|
|
1675
|
+
"boost-skill-cli" % sys.executable) in r.out
|
|
1675
1676
|
|
|
1676
1677
|
def test_pipx_upgrade_reports_the_new_version(self, boost, sandbox,
|
|
1677
1678
|
monkeypatch):
|
|
@@ -1683,11 +1684,76 @@ class TestSelfUpdate:
|
|
|
1683
1684
|
lambda: "9.9.9")
|
|
1684
1685
|
r = boost("self-update")
|
|
1685
1686
|
from boost_cli import __version__
|
|
1686
|
-
assert ran == [["/opt/bin/pipx", "upgrade", "boost-skill-cli"
|
|
1687
|
+
assert ran == [["/opt/bin/pipx", "upgrade", "boost-skill-cli",
|
|
1688
|
+
"--pip-args=--no-cache-dir"]]
|
|
1687
1689
|
assert ("boost v%s → v9.9.9" % __version__) in r.out
|
|
1688
1690
|
ev = journal.events(action="self-update")[0]
|
|
1689
1691
|
assert ev["subject"] == "9.9.9" and ev["method"] == "pipx"
|
|
1690
1692
|
|
|
1693
|
+
def _no_op_upgrade(self, monkeypatch, sandbox, latest):
|
|
1694
|
+
"""A manager that exits 0 and leaves the version exactly where it was.
|
|
1695
|
+
|
|
1696
|
+
`latest` is what PyPI is made to report — None for "PyPI would not say".
|
|
1697
|
+
"""
|
|
1698
|
+
from boost_cli import __version__
|
|
1699
|
+
self._pipx_install(monkeypatch, sandbox)
|
|
1700
|
+
monkeypatch.setattr("boost_cli.core.selfupdate.run_upgrade",
|
|
1701
|
+
lambda cmd, **kw: None)
|
|
1702
|
+
monkeypatch.setattr("boost_cli.core.selfupdate.observed_version",
|
|
1703
|
+
lambda: __version__)
|
|
1704
|
+
monkeypatch.setattr("boost_cli.core.selfupdate.latest_version",
|
|
1705
|
+
lambda *a, **kw: latest)
|
|
1706
|
+
return __version__
|
|
1707
|
+
|
|
1708
|
+
def test_a_no_op_upgrade_that_leaves_you_behind_is_not_up_to_date(
|
|
1709
|
+
self, boost, sandbox, monkeypatch):
|
|
1710
|
+
# The bug, end to end. pipx exits 0, pip says "Requirement already
|
|
1711
|
+
# satisfied (1.0.422)" because PyPI's simple index was still cached
|
|
1712
|
+
# from before the 1.0.423 upload, the version does not move — and boost
|
|
1713
|
+
# used to print "already up to date (v1.0.422)". It never asked PyPI.
|
|
1714
|
+
here = self._no_op_upgrade(monkeypatch, sandbox, latest="99.0.0")
|
|
1715
|
+
r = boost("self-update", expect=1)
|
|
1716
|
+
assert "already up to date" not in r.out
|
|
1717
|
+
assert ("pipx exited 0 but boost is still v%s — PyPI has v99.0.0"
|
|
1718
|
+
% here) in r.err
|
|
1719
|
+
# The hint has to be actionable: a plain `upgrade` has already been
|
|
1720
|
+
# tried and declined, so it must pin the version and force it.
|
|
1721
|
+
assert "pipx install --force boost-skill-cli==99.0.0" in r.err
|
|
1722
|
+
|
|
1723
|
+
def test_a_no_op_upgrade_at_the_latest_version_is_up_to_date(
|
|
1724
|
+
self, boost, sandbox, monkeypatch):
|
|
1725
|
+
# PyPI agrees this version is the newest, so the claim is earned.
|
|
1726
|
+
from boost_cli import __version__
|
|
1727
|
+
here = self._no_op_upgrade(monkeypatch, sandbox, latest=__version__)
|
|
1728
|
+
r = boost("self-update")
|
|
1729
|
+
assert ("already up to date (v%s)" % here) in r.out
|
|
1730
|
+
|
|
1731
|
+
def test_a_no_op_upgrade_offline_admits_it_could_not_confirm(
|
|
1732
|
+
self, boost, sandbox, monkeypatch):
|
|
1733
|
+
# PyPI unreachable. "Nothing changed" is all boost observed, so that is
|
|
1734
|
+
# all it may claim — asserting "up to date" here is the original bug
|
|
1735
|
+
# with a different cause.
|
|
1736
|
+
here = self._no_op_upgrade(monkeypatch, sandbox, latest=None)
|
|
1737
|
+
r = boost("self-update")
|
|
1738
|
+
assert ("boost is unchanged (v%s)" % here) in r.out
|
|
1739
|
+
assert "could not reach PyPI to confirm" in r.out
|
|
1740
|
+
assert "already up to date" not in r.out
|
|
1741
|
+
|
|
1742
|
+
def test_an_upgrade_that_moved_does_not_ask_pypi(self, boost, sandbox,
|
|
1743
|
+
monkeypatch):
|
|
1744
|
+
# The version moved, so the question is already answered. Asking PyPI
|
|
1745
|
+
# anyway would put a network round-trip on the happy path.
|
|
1746
|
+
self._pipx_install(monkeypatch, sandbox)
|
|
1747
|
+
monkeypatch.setattr("boost_cli.core.selfupdate.run_upgrade",
|
|
1748
|
+
lambda cmd, **kw: None)
|
|
1749
|
+
monkeypatch.setattr("boost_cli.core.selfupdate.observed_version",
|
|
1750
|
+
lambda: "9.9.9")
|
|
1751
|
+
|
|
1752
|
+
def never(*a, **kw):
|
|
1753
|
+
raise AssertionError("a successful upgrade must not query PyPI")
|
|
1754
|
+
monkeypatch.setattr("boost_cli.core.selfupdate.latest_version", never)
|
|
1755
|
+
assert "→ v9.9.9" in boost("self-update").out
|
|
1756
|
+
|
|
1691
1757
|
def test_upgrade_that_reveals_no_version_does_not_claim_one(
|
|
1692
1758
|
self, boost, sandbox, monkeypatch):
|
|
1693
1759
|
self._pipx_install(monkeypatch, sandbox)
|