boost-skill-cli 1.2.48__tar.gz → 1.2.49__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.2.48 → boost_skill_cli-1.2.49}/CLAUDE.md +22 -1
- {boost_skill_cli-1.2.48/boost_skill_cli.egg-info → boost_skill_cli-1.2.49}/PKG-INFO +5 -1
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/README.md +4 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/__init__.py +9 -1
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/quickstart.py +34 -6
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49/boost_skill_cli.egg-info}/PKG-INFO +5 -1
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_skill_cli.egg-info/SOURCES.txt +3 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/commands.html +4 -3
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/semantic-search.md +7 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/pyproject.toml +15 -0
- boost_skill_cli-1.2.49/scripts/shard_plan.py +146 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_quickstart.py +32 -0
- boost_skill_cli-1.2.49/tests/unit/test_shard_plan.py +125 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_shards_matrix.py +33 -7
- boost_skill_cli-1.2.49/tests/unit/test_version_tags.py +104 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.gitattributes +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.gitignore +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.lycheeignore +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.vale/styles/boost/AIWriting.yml +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/.vale.ini +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/DCO +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/GOVERNANCE.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/LICENSE +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/MAINTAINERS.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/MANIFEST.in +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/Makefile +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/SECURITY.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/SUPPORT.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/aihost.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/bmad.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/bootstrap.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/browse.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/builtin.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/catalogbundle.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/chat.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/complete.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/hookhost.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/localembed.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/selfupdate.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/shards.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/data/rules/boost-first.mdc +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_langchain/__init__.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_langchain/_compat.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_langchain/graph.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_langchain/loader.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_langchain/py.typed +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_langchain/retriever.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/codecov.yml +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/adapters.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/bmad.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/carousel.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/chat.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/code-review.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/commit-audit.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/demo-index.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/demo.gif +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/demo.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/demo.tape +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/dependencies.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/eval-latest.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/eval.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/index.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/langchain.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/openssf-badge.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/openssf-playbook.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/BOOST-D27.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/agents-field-records-the-request-not-the-links.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ai-backend-fanout.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/bm25-has-no-stemming.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/bmad-autopilot-one-command-persona-routing.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/bmad-hooks-all-hosts.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/boost-first-carried-the-losing-trigger.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/boost-first-rule.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/boost-langchain-publishing.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/branch-current-gate.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/browse-could-not-search-two-words.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/catalogue-entries-carry-no-content-identity.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/chat-cites-sources-by-a-number-it-never-prints.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/cli-command-audit.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/cli-output-ignored-the-terminal.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/cold-search-reads-the-whole-catalogue.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/completions-install-could-eat-your-rc-file.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/crash-reports-leak-api-keys.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/demo-workflow-cancels-other-prs.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/dense-search-rescans-every-vector.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/dependabot-splits-multi-path-action-repos.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/discover-searches-github-not-a-stale-sample.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/dry-run-promised-a-link-nobody-makes.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/efficiency-registries-ponytail-caveman.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/est-items-counts-agent-mirrors-as-items.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/eval-corpus-is-96x-smaller-than-a-real-install.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/eval-stats-could-never-publish.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/expanded-card-bodies-overflow.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/gemini-agent-frontmatter-sanitizer.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/gemini-duplicate-skill-discovery.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/gemini-hooks-host-aware.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/gemini-mcp-parity.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/gstack-tap-first-then-coexistence.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/heal-deleted-links-it-never-made.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/install-path-disambiguation.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/langchain-in-the-wheel.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/langchain-integration-explainer-page.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/langchain-langgraph-langsmith-integration.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/langchain-retriever-metadata-and-k-floor.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/lighthouse-scored-a-page-nobody-is-served.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/long-hints-overflow-narrow-panes.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/marketing-crm-domain-had-no-category.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-already-covered-defeater.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-search-hid-which-ranking-ran.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mcp-zero-setup-and-three-kinds.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/one-dead-tap-broke-every-update.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/openssf-best-practices-badge.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/openssf-gold-ceiling.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/openssf-playbook.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/openssf-silver.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/osps-baseline-levels.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/pathlib-exists-is-not-total.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/pep585-604-modernization-sweep.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/published-shards-have-no-consumer.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/python-floor-moves-to-312.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ragas-unpin-when-upstream-ships.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/readme-prune-and-search-guide.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/relicence-apache-2.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/reproducible-release-artifacts.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/rules-install-but-cannot-be-governed.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/scripts-under-the-lint-gate.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/search-and-browse-visual-refresh.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/search-never-notices-a-new-tap.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/self-update-claims-up-to-date-without-asking.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/serve-404-reflected-the-request.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/serve-is-a-searchable-catalogue.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/shards-pipeline-never-produced-a-shard.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/shareable-catalogue-bundle.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/smart-rerank-pays-per-novel-query.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sweep-died-at-launch-not-at-a-page.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sync-could-not-repair-a-gutted-skill.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/sync-reported-success-for-a-link-it-refused.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/taps-check-out-freight-they-never-index.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/the-catalogue-advertised-repos-that-no-longer-exist.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/the-scale-corpus-refreshed-the-wrong-rows.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/the-shard-job-that-could-not-finish.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/tool-call-eval-tier.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/two-ci-controls-that-could-not-act.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/two-crashes-that-should-have-been-messages.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/unwatched-crons-hid-a-real-fuzz-crash.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/update-advertises-a-flag-it-rejects.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/update-refreshed-rules-without-a-gate.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/vex-openvex-feed.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/zip-strict-audit.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/zizmor-ignores-drift-and-make-lint-never-ran-it.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/roadmap.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/security-design.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/superpowers/specs/2026-08-16-catalogue-content-identity-design.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/verifying-releases.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/vex/meta.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/vex/openvex.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/vex/statements/gitleaks-secretscan-test-fixtures.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/vex/statements/quality-trust-fingerprint-not-sensitive.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/vex/statements/zizmor-adhoc-packages-lint-runners.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/docs/vex/statements/zizmor-dangerous-triggers-workflow-run.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/README.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/__init__.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/baseline.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/metrics.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/examples/README.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/index.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/noxfile.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/add_spdx_headers.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/build_demo_index.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/build_scale_corpus.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/build_vex.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/check_branch_current.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/check_dco.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/check_reproducible.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/check_required_checks.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/eval_corpus.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/measure_registry.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/normalize_sdist.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/page_budget.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/publish_eval_json.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/publish_shards.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/scripts/serve_docs.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/setup.cfg +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/sonar-project.properties +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/style/README.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/style/boost.css +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/style/boost.js +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/style/demo.html +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/conftest.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/eval/golden-natural.jsonl +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/eval/taps-scale.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_bmad_all_hosts.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_catalog.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_chat.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_hooks_gemini.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_pane_width.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_tap_pins.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_kind_conformance.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/09-nul.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/10-name-too-long.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/corpus/registry/11-long-owner-repo.txt +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/langchain/conftest.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/langchain/test_graph.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/langchain/test_loader.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/langchain/test_retriever.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_action_pin_lockstep.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_aihost.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_bmad_core.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_boost_first_offer.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_bootstrap.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_branch_current.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_browse.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_builtin.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_catalogbundle.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_chat.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_check_dco.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_check_reproducible.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_clean_internal_cache.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_compact.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_complete.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_complete_rc_block.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_content_dedupe.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_content_identity.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_crash_redaction.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dedup_trust.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_demo_index.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_embed_dedupe.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_fix_hint.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_quantized.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_ready_order.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_shard_real_schema.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_shard_unreadable_vectors.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_shards.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dense_status_cheap.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_embed_local.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_embed_truncated_response.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_entry_key.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_eval_baseline.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_eval_corpus.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_eval_grading.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_failure_alerting_covers_unattended.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_gemini_agent_sanitize.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_gitutil_lfs.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_gitutil_sparse.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_hook_settings_hosts.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_hookhost.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_install_permission_error.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_langchain_packaging.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_link_ownership.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_localembed.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_localembed_e2e.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_measure_registry.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_normalize_sdist.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_page_budget.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_rag_fastpath.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_rag_fusion.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_registry_control_chars.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_registry_parallel.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_required_checks.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_rerank_cache.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_scale_corpus.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_selfupdate.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_serve_docs.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_shards.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_smoke_covers_every_command.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_spdx_headers.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_store_materialize.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_sync_blocked_links.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_sync_repairs_gutted_skill.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_tap_pins.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_vex.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_visual_harness_flags.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_workflow_concurrency_groups.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_workflow_push_has_credentials.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/unit/test_zizmor_ignores_still_anchor.py +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.2.48 → boost_skill_cli-1.2.49}/tests/visual/visual_check.mjs +0 -0
|
@@ -185,7 +185,16 @@ line coverage. Target `boost_cli/core` behavior with assertions, not just import
|
|
|
185
185
|
`HOME`/`BOOST_HOME`; tests point them at a tempdir. In zsh, one-line chains
|
|
186
186
|
like `export A=$(...) B=$A/x` leave `B` broken — use separate `export`
|
|
187
187
|
statements.
|
|
188
|
-
- **Versioning is setuptools-scm from git tags.**
|
|
188
|
+
- **Versioning is setuptools-scm from git tags.** **Only `vX.Y.Z` tags count**, and
|
|
189
|
+
two settings say so: `git_describe_command`'s `--match v[0-9]*` decides which
|
|
190
|
+
tag is *found* and `tag_regex` decides how it is *parsed*. Both are load-
|
|
191
|
+
bearing since the repo gained a deliberate non-version tag — `shards-latest`,
|
|
192
|
+
the rolling release hosting the vector shards. At defaults, `git describe`
|
|
193
|
+
returned `shards-latest-1-g82c3e6a`, the build called itself
|
|
194
|
+
`vshards-latest-…`, and `boost self-update` then reported "already up to
|
|
195
|
+
date" against a newer PyPI release, because it compares version tuples and
|
|
196
|
+
that string parses as none. A silent wrong answer in the command whose job is
|
|
197
|
+
to detect being behind. There is no `__version__`
|
|
189
198
|
constant and `boost_cli/_version.py` is generated + gitignored. Don't hardcode
|
|
190
199
|
or assert exact versions; version tests are shape-only (`^boost \S+$`). The
|
|
191
200
|
publish workflow filename must stay `publish.yml` (PyPI Trusted Publisher
|
|
@@ -450,6 +459,18 @@ each agent's skills dir, and updating the lock file.
|
|
|
450
459
|
costs a download instead of an hour of CPU — and says plainly when one does
|
|
451
460
|
not.
|
|
452
461
|
|
|
462
|
+
- **The shard matrix is packed, not sliced, and 256 is a hard ceiling.**
|
|
463
|
+
GitHub runs at most 256 matrix jobs per workflow, so `shards.yml` cannot take
|
|
464
|
+
one job per registry once the scope is the 463-registry catalogue — the run
|
|
465
|
+
fails before a job starts. `scripts/shard_plan.py` bin-packs by the measured
|
|
466
|
+
`est_items` (longest-processing-time-first), which matters because cost is
|
|
467
|
+
uneven: the largest catalogued registry is 880 items against a median of 30,
|
|
468
|
+
so slicing puts several giants in one job while others idle, against a
|
|
469
|
+
6-hour per-job ceiling. Packing is deterministic on purpose — a rerun that
|
|
470
|
+
repacked differently would re-embed registries whose shards were already
|
|
471
|
+
published. A matrix entry is a **space-separated list**, split in Python
|
|
472
|
+
inside the job, never by shell word-splitting.
|
|
473
|
+
|
|
453
474
|
- **A published shard is only importable while three things match, and every
|
|
454
475
|
mismatch is silent if waved through.** `core/shards.py` fetches
|
|
455
476
|
`manifest.json` from a rolling `shards-latest` **prerelease** on this repo —
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boost-skill-cli
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.49
|
|
4
4
|
Summary: boost — Homebrew for AI coding skills
|
|
5
5
|
Author: Jonathan Reyes
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -186,6 +186,10 @@ those vectors. Embedding is ~1.2 s/chunk on CPU — hours for a real corpus —
|
|
|
186
186
|
and importing the same rows takes 0.12 s, so the difference between the two is
|
|
187
187
|
the difference between semantic search being available and being reachable.
|
|
188
188
|
|
|
189
|
+
Want everything? `boost quickstart --catalog` taps all 463 catalogued
|
|
190
|
+
registries — 2 min 10 s now that clones run in parallel — and fetches vectors
|
|
191
|
+
for every one that has a published shard.
|
|
192
|
+
|
|
189
193
|
Already tapped? `boost reindex --fetch-shards` does the download half alone,
|
|
190
194
|
and `boost reindex --dense` embeds locally whatever has no published shard.
|
|
191
195
|
|
|
@@ -144,6 +144,10 @@ those vectors. Embedding is ~1.2 s/chunk on CPU — hours for a real corpus —
|
|
|
144
144
|
and importing the same rows takes 0.12 s, so the difference between the two is
|
|
145
145
|
the difference between semantic search being available and being reachable.
|
|
146
146
|
|
|
147
|
+
Want everything? `boost quickstart --catalog` taps all 463 catalogued
|
|
148
|
+
registries — 2 min 10 s now that clones run in parallel — and fetches vectors
|
|
149
|
+
for every one that has a published shard.
|
|
150
|
+
|
|
147
151
|
Already tapped? `boost reindex --fetch-shards` does the download half alone,
|
|
148
152
|
and `boost reindex --dense` embeds locally whatever has no published shard.
|
|
149
153
|
|
|
@@ -21,8 +21,16 @@ def _detect_version() -> str:
|
|
|
21
21
|
import subprocess
|
|
22
22
|
from pathlib import Path
|
|
23
23
|
root = Path(__file__).resolve().parent.parent
|
|
24
|
+
# `--match v[0-9]*`, exactly as pyproject's git_describe_command:
|
|
25
|
+
# the repo carries a deliberate non-version tag (`shards-latest`, the
|
|
26
|
+
# rolling release hosting the vector shards), and without the match
|
|
27
|
+
# this fallback served `shards-latest-3-g…` as the version — which
|
|
28
|
+
# parses as no version at all, so `self-update` compared nothing and
|
|
29
|
+
# answered "already up to date" while a newer release existed.
|
|
30
|
+
# `--always` still yields a bare SHA when no version tag is reachable.
|
|
24
31
|
proc = subprocess.run(
|
|
25
|
-
["git", "-C", str(root), "describe", "--tags", "--always",
|
|
32
|
+
["git", "-C", str(root), "describe", "--tags", "--always",
|
|
33
|
+
"--dirty", "--match", "v[0-9]*"],
|
|
26
34
|
capture_output=True, text=True, timeout=3)
|
|
27
35
|
described = proc.stdout.strip()
|
|
28
36
|
if proc.returncode == 0 and described:
|
|
@@ -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.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 2,
|
|
21
|
+
__version__ = version = '1.2.49'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 2, 49)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -32,19 +32,43 @@ from ..core import output as out
|
|
|
32
32
|
from ..errors import BoostError
|
|
33
33
|
|
|
34
34
|
|
|
35
|
-
def
|
|
36
|
-
"""
|
|
35
|
+
def _selection(catalog_scope: bool) -> list[dict]:
|
|
36
|
+
"""The registries quickstart will tap: the seven defaults, or all of them.
|
|
37
|
+
|
|
38
|
+
`--catalog` exists because "search everything" is a real ask and the two
|
|
39
|
+
costs that used to make it unreasonable are gone: tapping 463 registries is
|
|
40
|
+
2 min 10 s now that clones run in parallel, and their vectors are a
|
|
41
|
+
download rather than an hour of CPU.
|
|
42
|
+
"""
|
|
43
|
+
if not catalog_scope:
|
|
44
|
+
return [d.copy() for d in config.DEFAULT_TAPS]
|
|
45
|
+
return [{"name": e["name"], "url": e["url"]}
|
|
46
|
+
for e in config.load_registry_catalog()
|
|
47
|
+
if not e.get("list_only") and e.get("name") and e.get("url")]
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
def _tap_defaults(selection: list[dict], pins: dict[str, dict],
|
|
51
|
+
dry_run: bool) -> list[str]:
|
|
52
|
+
"""Tap the selected registries, pinned to a shard's commit when one exists.
|
|
37
53
|
|
|
38
54
|
Returns the tap names that are configured afterwards, tapped here or not.
|
|
39
55
|
Pinning is the whole point: tapping HEAD and then fetching a shard is the
|
|
40
56
|
ordering that produces a commit mismatch on every registry that moved since
|
|
41
57
|
the last shard run.
|
|
42
58
|
"""
|
|
43
|
-
names = [str(d["name"]) for d in
|
|
59
|
+
names = [str(d["name"]) for d in selection]
|
|
44
60
|
commits = {name: str(pins[name].get("commit")) for name in names
|
|
45
61
|
if name in pins}
|
|
46
62
|
if dry_run:
|
|
47
63
|
existing = {t.name for t in registry.list_taps()}
|
|
64
|
+
pending = [n for n in names if n not in existing]
|
|
65
|
+
# Over 463 registries a line each is a wall of text, so past a handful
|
|
66
|
+
# the dry run reports the shape instead of the list.
|
|
67
|
+
if len(pending) > 12:
|
|
68
|
+
out.info("would tap %d registries (%d pinned to a published "
|
|
69
|
+
"shard's commit)"
|
|
70
|
+
% (len(pending), sum(1 for n in pending if n in commits)))
|
|
71
|
+
return names
|
|
48
72
|
for name in names:
|
|
49
73
|
if name in existing:
|
|
50
74
|
out.info(out.role("%s already tapped" % name, "muted"))
|
|
@@ -56,7 +80,7 @@ def _tap_defaults(pins: dict[str, dict], dry_run: bool) -> list[str]:
|
|
|
56
80
|
# for work that takes ~2 s done together, and the first thing a new user
|
|
57
81
|
# sees should not be a progress bar.
|
|
58
82
|
with spin.Spinner("tapping %d registries" % len(names)):
|
|
59
|
-
results = registry.add_many([str(d["url"]) for d in
|
|
83
|
+
results = registry.add_many([str(d["url"]) for d in selection],
|
|
60
84
|
curated=True, pins=commits)
|
|
61
85
|
for res in results:
|
|
62
86
|
name = res["name"]
|
|
@@ -104,10 +128,13 @@ def _report(results: list[dict]) -> None:
|
|
|
104
128
|
|
|
105
129
|
|
|
106
130
|
def cmd_quickstart(argv) -> int:
|
|
107
|
-
"""boost quickstart [--no-vectors] [--dry-run]"""
|
|
131
|
+
"""boost quickstart [--catalog] [--no-vectors] [--dry-run]"""
|
|
108
132
|
p = cliparse.parser(
|
|
109
133
|
prog="boost quickstart",
|
|
110
134
|
description="Tap the starter registries and load prebuilt vectors")
|
|
135
|
+
p.add_argument("--catalog", action="store_true",
|
|
136
|
+
help="tap every catalogued registry, not just the 7 "
|
|
137
|
+
"starters, and fetch vectors for all of them")
|
|
111
138
|
p.add_argument("--no-vectors", action="store_true",
|
|
112
139
|
help="set up taps and keyword search only, skip shards")
|
|
113
140
|
p.add_argument("--dry-run", action="store_true",
|
|
@@ -129,7 +156,8 @@ def cmd_quickstart(argv) -> int:
|
|
|
129
156
|
out.warn("no published shards: %s" % exc.message)
|
|
130
157
|
manifest = None
|
|
131
158
|
|
|
132
|
-
|
|
159
|
+
selection = _selection(args.catalog)
|
|
160
|
+
names = _tap_defaults(selection, pins, args.dry_run)
|
|
133
161
|
if args.dry_run:
|
|
134
162
|
planned = [n for n in names if n in pins] if manifest else []
|
|
135
163
|
out.info("would build the keyword index, then import %d shard(s)"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boost-skill-cli
|
|
3
|
-
Version: 1.2.
|
|
3
|
+
Version: 1.2.49
|
|
4
4
|
Summary: boost — Homebrew for AI coding skills
|
|
5
5
|
Author: Jonathan Reyes
|
|
6
6
|
License-Expression: Apache-2.0
|
|
@@ -186,6 +186,10 @@ those vectors. Embedding is ~1.2 s/chunk on CPU — hours for a real corpus —
|
|
|
186
186
|
and importing the same rows takes 0.12 s, so the difference between the two is
|
|
187
187
|
the difference between semantic search being available and being reachable.
|
|
188
188
|
|
|
189
|
+
Want everything? `boost quickstart --catalog` taps all 463 catalogued
|
|
190
|
+
registries — 2 min 10 s now that clones run in parallel — and fetches vectors
|
|
191
|
+
for every one that has a published shard.
|
|
192
|
+
|
|
189
193
|
Already tapped? `boost reindex --fetch-shards` does the download half alone,
|
|
190
194
|
and `boost reindex --dense` embeds locally whatever has no published shard.
|
|
191
195
|
|
|
@@ -553,6 +553,7 @@ scripts/publish_shards.py
|
|
|
553
553
|
scripts/release_guard.py
|
|
554
554
|
scripts/release_preflight.py
|
|
555
555
|
scripts/serve_docs.py
|
|
556
|
+
scripts/shard_plan.py
|
|
556
557
|
style/README.md
|
|
557
558
|
style/boost.css
|
|
558
559
|
style/boost.js
|
|
@@ -776,6 +777,7 @@ tests/unit/test_secretscan.py
|
|
|
776
777
|
tests/unit/test_selfupdate.py
|
|
777
778
|
tests/unit/test_serve.py
|
|
778
779
|
tests/unit/test_serve_docs.py
|
|
780
|
+
tests/unit/test_shard_plan.py
|
|
779
781
|
tests/unit/test_shards.py
|
|
780
782
|
tests/unit/test_shards_matrix.py
|
|
781
783
|
tests/unit/test_smoke_covers_every_command.py
|
|
@@ -795,6 +797,7 @@ tests/unit/test_typosquat.py
|
|
|
795
797
|
tests/unit/test_updatediff.py
|
|
796
798
|
tests/unit/test_util.py
|
|
797
799
|
tests/unit/test_version.py
|
|
800
|
+
tests/unit/test_version_tags.py
|
|
798
801
|
tests/unit/test_vex.py
|
|
799
802
|
tests/unit/test_visual_harness_flags.py
|
|
800
803
|
tests/unit/test_workflow_concurrency.py
|
|
@@ -180,7 +180,7 @@
|
|
|
180
180
|
</div>
|
|
181
181
|
<div class="group" data-group="cfg">
|
|
182
182
|
<div class="group-h">Config & setup</div>
|
|
183
|
-
<a class="cmd-link" href="#cmd-quickstart" data-search="quickstart tap the starter registries and load prebuilt vectors --no-vectors --dry-run">quickstart</a>
|
|
183
|
+
<a class="cmd-link" href="#cmd-quickstart" data-search="quickstart tap the starter registries and load prebuilt vectors --catalog --no-vectors --dry-run">quickstart</a>
|
|
184
184
|
<a class="cmd-link" href="#cmd-config" data-search="config display or modify boost configuration --json {list,get,set,unset} key value">config</a>
|
|
185
185
|
<a class="cmd-link" href="#cmd-clean" data-search="clean clear stale caches & broken symlinks --dry-run --deep">clean</a>
|
|
186
186
|
<a class="cmd-link" href="#cmd-compact" data-search="compact shrink tap clones to the files boost indexes --dry-run --reclone tap">compact</a>
|
|
@@ -974,12 +974,13 @@
|
|
|
974
974
|
</div>
|
|
975
975
|
</section>
|
|
976
976
|
<h2 class="group-h" id="grp-cfg">Config & setup</h2>
|
|
977
|
-
<section class="cmd" id="cmd-quickstart" data-search="quickstart tap the starter registries and load prebuilt vectors --no-vectors --dry-run">
|
|
977
|
+
<section class="cmd" id="cmd-quickstart" data-search="quickstart tap the starter registries and load prebuilt vectors --catalog --no-vectors --dry-run">
|
|
978
978
|
<h3><span class="cname">quickstart</span><span class="gtag">cfg</span></h3>
|
|
979
979
|
<p class="summary">Tap the starter registries and load prebuilt vectors</p>
|
|
980
|
-
<pre class="syn">boost quickstart [--no-vectors] [--dry-run]</pre>
|
|
980
|
+
<pre class="syn">boost quickstart [--catalog] [--no-vectors] [--dry-run]</pre>
|
|
981
981
|
<div class="args-h">Options</div>
|
|
982
982
|
<div class="args">
|
|
983
|
+
<div class="arg"><code>--catalog</code><span>tap every catalogued registry, not just the 7 starters, and fetch vectors for all of them</span></div>
|
|
983
984
|
<div class="arg"><code>--no-vectors</code><span>set up taps and keyword search only, skip shards</span></div>
|
|
984
985
|
<div class="arg"><code>--dry-run</code><span>print what would happen, change nothing</span></div>
|
|
985
986
|
</div>
|
|
@@ -61,9 +61,16 @@ two commands consume them:
|
|
|
61
61
|
|
|
62
62
|
```bash
|
|
63
63
|
boost quickstart # tap the starter registries + import their vectors
|
|
64
|
+
boost quickstart --catalog # …or all 463 catalogued registries
|
|
64
65
|
boost reindex --fetch-shards # already tapped: import whatever is published
|
|
65
66
|
```
|
|
66
67
|
|
|
68
|
+
The published set is the whole catalogue, refreshed weekly. CI packs the 463
|
|
69
|
+
registries into ~60 matrix jobs rather than one per registry, because GitHub
|
|
70
|
+
caps a matrix at 256 jobs and embedding cost is uneven enough that slicing
|
|
71
|
+
would leave one job carrying several of the largest registries
|
|
72
|
+
(`scripts/shard_plan.py`).
|
|
73
|
+
|
|
67
74
|
Three rules keep a downloaded vector honest, and each of them refuses rather
|
|
68
75
|
than degrades — the failures they prevent are silent ones:
|
|
69
76
|
|
|
@@ -118,6 +118,21 @@ boost = "boost_cli.cli:main"
|
|
|
118
118
|
# are the single source of truth — no constant to bump, no drift. Writes the
|
|
119
119
|
# resolved version to boost_cli/_version.py (git-ignored).
|
|
120
120
|
version_file = "boost_cli/_version.py"
|
|
121
|
+
# ONLY vX.Y.Z tags are versions, and both settings are needed to say so: the
|
|
122
|
+
# describe command decides which tag is *found*, `tag_regex` decides how it is
|
|
123
|
+
# *parsed*. Without them, the rolling `shards-latest` tag that hosts the
|
|
124
|
+
# prebuilt vector shards was picked up as this project's version — a CI
|
|
125
|
+
# checkout resolved `vshards-latest-4-g1c1398c`, which then broke
|
|
126
|
+
# `boost self-update`'s "am I behind PyPI?" comparison, because that compares
|
|
127
|
+
# version tuples and this parses as none.
|
|
128
|
+
#
|
|
129
|
+
# The repository now carries a non-version tag on purpose (a GitHub release
|
|
130
|
+
# needs one), so this is not a hypothetical: any future non-version tag is
|
|
131
|
+
# covered too.
|
|
132
|
+
git_describe_command = [
|
|
133
|
+
"git", "describe", "--dirty", "--tags", "--long", "--match", "v[0-9]*",
|
|
134
|
+
]
|
|
135
|
+
tag_regex = "^v(?P<version>[0-9]+[^+]*)$"
|
|
121
136
|
|
|
122
137
|
[tool.setuptools.packages.find]
|
|
123
138
|
# Two top-level packages, one wheel: boost_cli (the zero-dependency CLI) and
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
# Copyright the boost contributors.
|
|
3
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
4
|
+
"""Pack the registry catalogue into a bounded, balanced Actions matrix.
|
|
5
|
+
|
|
6
|
+
WHY THIS EXISTS. `shards.yml` ran one job per registry, which is fine for the
|
|
7
|
+
20-repo eval corpus and impossible for the 463-registry catalogue: **GitHub
|
|
8
|
+
caps a matrix at 256 jobs per workflow run**, so 463 rows do not start at all.
|
|
9
|
+
Chunking is therefore not an optimisation, it is the difference between the
|
|
10
|
+
workflow running and not.
|
|
11
|
+
|
|
12
|
+
WHY BIN-PACKING RATHER THAN SLICING. Embedding cost is wildly uneven — the
|
|
13
|
+
catalogue's largest registry is 880 measured items against a median of 30 and a
|
|
14
|
+
minimum of 1 — so a naive `chunk(n)` puts several giants in one job and leaves
|
|
15
|
+
others with nothing. The whole run then takes as long as its unluckiest chunk, against
|
|
16
|
+
a hard 6-hour job ceiling. Longest-processing-time-first (sort by cost
|
|
17
|
+
descending, always add to the currently cheapest bin) is the standard greedy
|
|
18
|
+
answer and is within 4/3 of optimal, which is far inside the margin that
|
|
19
|
+
matters here. The practical effect is that the biggest registry ends up
|
|
20
|
+
effectively alone in its bin, which is exactly what you want: it is the run's
|
|
21
|
+
critical path either way.
|
|
22
|
+
|
|
23
|
+
COST PROXY. `est_items` from the bundled catalogue, which is *measured* (see
|
|
24
|
+
`scripts/measure_registry.py`) rather than guessed. It is a proxy for chunk
|
|
25
|
+
count, not chunk count itself — deduplication means a registry that mirrors
|
|
26
|
+
itself is cheaper than its size suggests — but it is the only per-registry
|
|
27
|
+
number available before cloning, and it is right about the ordering, which is
|
|
28
|
+
what the packing needs.
|
|
29
|
+
|
|
30
|
+
shard_plan.py --scope catalog # matrix JSON for GITHUB_OUTPUT
|
|
31
|
+
shard_plan.py --scope catalog --explain # what each job would carry
|
|
32
|
+
"""
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import argparse
|
|
36
|
+
import json
|
|
37
|
+
import sys
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
|
|
40
|
+
sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
|
|
41
|
+
|
|
42
|
+
from boost_cli.core import config
|
|
43
|
+
|
|
44
|
+
#: GitHub's documented ceiling. Not a tunable — a matrix that exceeds it fails
|
|
45
|
+
#: the whole run before a single job starts.
|
|
46
|
+
MAX_MATRIX_JOBS = 256
|
|
47
|
+
|
|
48
|
+
#: Default jobs to plan for. Under the ceiling with room to spare, and enough
|
|
49
|
+
#: parallelism that the run is bounded by its largest registry rather than by
|
|
50
|
+
#: how many bins there are.
|
|
51
|
+
DEFAULT_JOBS = 60
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def catalog_rows(include_lists: bool = False) -> list[dict]:
|
|
55
|
+
"""Every catalogued registry as ``{"name", "cost"}``, biggest first."""
|
|
56
|
+
rows = []
|
|
57
|
+
for entry in config.load_registry_catalog():
|
|
58
|
+
if not include_lists and entry.get("list_only"):
|
|
59
|
+
# An awesome-list repo indexes other repos; there is nothing of its
|
|
60
|
+
# own to embed.
|
|
61
|
+
continue
|
|
62
|
+
name = str(entry.get("name") or "")
|
|
63
|
+
if not name:
|
|
64
|
+
continue
|
|
65
|
+
rows.append({"name": name, "cost": int(entry.get("est_items") or 0)})
|
|
66
|
+
rows.sort(key=lambda r: (-r["cost"], r["name"]))
|
|
67
|
+
return rows
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def pack(rows: list[dict], jobs: int) -> list[list[str]]:
|
|
71
|
+
"""Longest-processing-time-first packing into at most `jobs` bins.
|
|
72
|
+
|
|
73
|
+
Deterministic: rows arrive sorted by (-cost, name), and ties between bins
|
|
74
|
+
are broken by index, so the same catalogue always plans the same matrix.
|
|
75
|
+
That matters for reruns — a rerun that repacked differently would re-embed
|
|
76
|
+
registries whose shards were already published.
|
|
77
|
+
"""
|
|
78
|
+
if jobs < 1:
|
|
79
|
+
raise SystemExit("--jobs must be at least 1")
|
|
80
|
+
bins: list[list[str]] = [[] for _ in range(min(jobs, max(1, len(rows))))]
|
|
81
|
+
loads = [0] * len(bins)
|
|
82
|
+
for row in rows:
|
|
83
|
+
i = loads.index(min(loads))
|
|
84
|
+
bins[i].append(row["name"])
|
|
85
|
+
loads[i] += row["cost"]
|
|
86
|
+
return [b for b in bins if b]
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def plan(scope: str, jobs: int, include_lists: bool = False) -> list[list[str]]:
|
|
90
|
+
"""The matrix for `scope`, as a list of registry-name lists."""
|
|
91
|
+
if scope == "eval":
|
|
92
|
+
# The pinned corpus every other gate measures against: one job per
|
|
93
|
+
# registry, because there are twenty of them and no packing is needed.
|
|
94
|
+
import subprocess
|
|
95
|
+
out = subprocess.run(
|
|
96
|
+
[sys.executable, str(Path(__file__).with_name("eval_corpus.py")),
|
|
97
|
+
"--list-repos"], check=True, capture_output=True, text=True).stdout
|
|
98
|
+
return [[name] for name in out.split()]
|
|
99
|
+
rows = catalog_rows(include_lists=include_lists)
|
|
100
|
+
if not rows:
|
|
101
|
+
raise SystemExit("the bundled registry catalogue is empty")
|
|
102
|
+
return pack(rows, jobs)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def main(argv: list[str] | None = None) -> int:
|
|
106
|
+
p = argparse.ArgumentParser(description=__doc__,
|
|
107
|
+
formatter_class=argparse.RawDescriptionHelpFormatter)
|
|
108
|
+
p.add_argument("--scope", choices=("catalog", "eval"), default="catalog",
|
|
109
|
+
help="which registries to shard (default: %(default)s)")
|
|
110
|
+
p.add_argument("--jobs", type=int, default=DEFAULT_JOBS,
|
|
111
|
+
help="how many matrix jobs to plan for (default: %(default)s)")
|
|
112
|
+
p.add_argument("--include-lists", action="store_true",
|
|
113
|
+
help="also shard awesome-list/index repos")
|
|
114
|
+
p.add_argument("--explain", action="store_true",
|
|
115
|
+
help="print the packing as a table instead of JSON")
|
|
116
|
+
args = p.parse_args(argv)
|
|
117
|
+
|
|
118
|
+
if args.jobs > MAX_MATRIX_JOBS:
|
|
119
|
+
raise SystemExit(
|
|
120
|
+
"--jobs %d exceeds GitHub's %d-job matrix ceiling; the run would "
|
|
121
|
+
"fail before starting" % (args.jobs, MAX_MATRIX_JOBS))
|
|
122
|
+
chunks = plan(args.scope, args.jobs, args.include_lists)
|
|
123
|
+
if len(chunks) > MAX_MATRIX_JOBS:
|
|
124
|
+
raise SystemExit("planned %d jobs, over the %d-job ceiling"
|
|
125
|
+
% (len(chunks), MAX_MATRIX_JOBS))
|
|
126
|
+
if args.explain:
|
|
127
|
+
costs = {r["name"]: r["cost"] for r in catalog_rows(args.include_lists)}
|
|
128
|
+
for i, chunk in enumerate(chunks):
|
|
129
|
+
load = sum(costs.get(n, 0) for n in chunk)
|
|
130
|
+
print("job %2d %5d est. items %2d registries %s"
|
|
131
|
+
% (i, load, len(chunk),
|
|
132
|
+
", ".join(chunk[:3]) + (" …" if len(chunk) > 3 else "")))
|
|
133
|
+
loads = [sum(costs.get(n, 0) for n in c) for c in chunks]
|
|
134
|
+
print("\n%d jobs · %d registries · %d est. items · heaviest %d, "
|
|
135
|
+
"lightest %d" % (len(chunks), sum(len(c) for c in chunks),
|
|
136
|
+
sum(loads), max(loads), min(loads)))
|
|
137
|
+
return 0
|
|
138
|
+
# One matrix entry per job: a space-separated list the workflow splits in
|
|
139
|
+
# Python, never in shell — `shards.yml`'s header records what happened the
|
|
140
|
+
# last time a list was word-split by the runner.
|
|
141
|
+
print(json.dumps([" ".join(chunk) for chunk in chunks]))
|
|
142
|
+
return 0
|
|
143
|
+
|
|
144
|
+
|
|
145
|
+
if __name__ == "__main__":
|
|
146
|
+
raise SystemExit(main())
|
|
@@ -56,6 +56,38 @@ class TestQuickstartDryRun:
|
|
|
56
56
|
assert str(default["name"]) in res.out
|
|
57
57
|
|
|
58
58
|
|
|
59
|
+
class TestQuickstartCatalog:
|
|
60
|
+
"""`--catalog` is the "search everything" entry point."""
|
|
61
|
+
|
|
62
|
+
def test_it_plans_every_catalogued_registry(self, boost):
|
|
63
|
+
from boost_cli.core import config
|
|
64
|
+
catalogued = [e for e in config.load_registry_catalog()
|
|
65
|
+
if not e.get("list_only")]
|
|
66
|
+
res = boost("quickstart", "--catalog", "--dry-run")
|
|
67
|
+
# Past a handful the dry run reports the shape: 463 lines of "would
|
|
68
|
+
# tap" is a wall of text, not a preview.
|
|
69
|
+
assert "would tap %d registries" % len(catalogued) in res.out
|
|
70
|
+
|
|
71
|
+
def test_the_default_scope_is_still_the_seven_starters(self, boost):
|
|
72
|
+
from boost_cli.core import config
|
|
73
|
+
res = boost("quickstart", "--dry-run")
|
|
74
|
+
for default in config.DEFAULT_TAPS:
|
|
75
|
+
assert str(default["name"]) in res.out
|
|
76
|
+
|
|
77
|
+
def test_catalog_scope_excludes_index_repos(self, boost):
|
|
78
|
+
from boost_cli.core import config
|
|
79
|
+
lists = [e for e in config.load_registry_catalog()
|
|
80
|
+
if e.get("list_only")]
|
|
81
|
+
if not lists:
|
|
82
|
+
pytest.skip("no list-only repos in the bundled catalogue")
|
|
83
|
+
res = boost("quickstart", "--catalog", "--dry-run")
|
|
84
|
+
total = len([e for e in config.load_registry_catalog()
|
|
85
|
+
if not e.get("list_only")])
|
|
86
|
+
# An awesome-list repo indexes other repos and ships nothing of its
|
|
87
|
+
# own, so tapping it for vectors buys nothing.
|
|
88
|
+
assert "would tap %d registries" % total in res.out
|
|
89
|
+
|
|
90
|
+
|
|
59
91
|
class TestQuickstartWithoutTheExtra:
|
|
60
92
|
"""The default install: no `rag` extra, so no vectors and no fetch."""
|
|
61
93
|
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# Copyright the boost contributors.
|
|
2
|
+
# SPDX-License-Identifier: Apache-2.0
|
|
3
|
+
"""Packing the catalogue into a matrix GitHub will actually run.
|
|
4
|
+
|
|
5
|
+
Two facts drive every test here. **GitHub caps a matrix at 256 jobs**, so the
|
|
6
|
+
463-registry catalogue cannot be one job per registry — the run fails before a
|
|
7
|
+
single job starts. And embedding cost is wildly uneven: the largest catalogued
|
|
8
|
+
registry measures 880 items against a median of 30, so slicing the list
|
|
9
|
+
into equal chunks puts several giants in one job while others idle, and the run
|
|
10
|
+
takes as long as its unluckiest chunk against a hard 6-hour job ceiling.
|
|
11
|
+
|
|
12
|
+
Longest-processing-time-first fixes the second and the job count fixes the
|
|
13
|
+
first. The packing must also be *deterministic*: a rerun that repacked
|
|
14
|
+
differently would re-embed registries whose shards were already published.
|
|
15
|
+
"""
|
|
16
|
+
import json
|
|
17
|
+
import subprocess
|
|
18
|
+
import sys
|
|
19
|
+
from pathlib import Path
|
|
20
|
+
|
|
21
|
+
import pytest
|
|
22
|
+
|
|
23
|
+
ROOT = Path(__file__).resolve().parents[2]
|
|
24
|
+
sys.path.insert(0, str(ROOT / "scripts"))
|
|
25
|
+
|
|
26
|
+
import shard_plan # noqa: E402
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
def _rows(*costs):
|
|
30
|
+
return [{"name": "o/r%d" % i, "cost": c} for i, c in enumerate(costs)]
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestPack:
|
|
34
|
+
def test_every_registry_lands_in_exactly_one_bin(self):
|
|
35
|
+
rows = _rows(*range(1, 40))
|
|
36
|
+
packed = shard_plan.pack(rows, jobs=7)
|
|
37
|
+
flat = [name for chunk in packed for name in chunk]
|
|
38
|
+
assert sorted(flat) == sorted(r["name"] for r in rows)
|
|
39
|
+
assert len(flat) == len(set(flat))
|
|
40
|
+
|
|
41
|
+
def test_it_never_plans_more_bins_than_asked(self):
|
|
42
|
+
# The ceiling is the whole reason this function exists.
|
|
43
|
+
assert len(shard_plan.pack(_rows(*range(500)), jobs=60)) <= 60
|
|
44
|
+
|
|
45
|
+
def test_fewer_registries_than_bins_does_not_pad_with_empties(self):
|
|
46
|
+
# An empty matrix entry would be a job that taps nothing and then fails
|
|
47
|
+
# its own "produced no shards" assertion.
|
|
48
|
+
packed = shard_plan.pack(_rows(5, 5, 5), jobs=10)
|
|
49
|
+
assert packed == [["o/r0"], ["o/r1"], ["o/r2"]]
|
|
50
|
+
|
|
51
|
+
def test_the_giant_ends_up_effectively_alone(self):
|
|
52
|
+
# It is the run's critical path either way; what matters is that it is
|
|
53
|
+
# not also carrying somebody else's work.
|
|
54
|
+
rows = _rows(1000, 10, 10, 10, 10)
|
|
55
|
+
packed = shard_plan.pack(rows, jobs=3)
|
|
56
|
+
giant = next(c for c in packed if "o/r0" in c)
|
|
57
|
+
assert giant == ["o/r0"]
|
|
58
|
+
|
|
59
|
+
def test_load_is_balanced_far_better_than_slicing(self):
|
|
60
|
+
rows = _rows(*([100] * 3 + [1] * 30))
|
|
61
|
+
costs = {r["name"]: r["cost"] for r in rows}
|
|
62
|
+
loads = [sum(costs[n] for n in c)
|
|
63
|
+
for c in shard_plan.pack(rows, jobs=3)]
|
|
64
|
+
# Sliced by position the three giants land together (300 vs 15); packed
|
|
65
|
+
# they separate.
|
|
66
|
+
assert max(loads) - min(loads) <= 20
|
|
67
|
+
|
|
68
|
+
def test_packing_is_deterministic(self):
|
|
69
|
+
rows = _rows(*range(1, 60))
|
|
70
|
+
assert shard_plan.pack(rows, jobs=8) == shard_plan.pack(rows, jobs=8)
|
|
71
|
+
|
|
72
|
+
def test_zero_jobs_is_refused_rather_than_silently_empty(self):
|
|
73
|
+
with pytest.raises(SystemExit):
|
|
74
|
+
shard_plan.pack(_rows(1, 2), jobs=0)
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
class TestCatalogRows:
|
|
78
|
+
def test_it_reads_the_bundled_catalogue_biggest_first(self):
|
|
79
|
+
rows = shard_plan.catalog_rows()
|
|
80
|
+
assert rows, "the bundled catalogue should not be empty"
|
|
81
|
+
assert [r["cost"] for r in rows] == sorted(
|
|
82
|
+
(r["cost"] for r in rows), reverse=True)
|
|
83
|
+
|
|
84
|
+
def test_list_only_repos_are_excluded_by_default(self):
|
|
85
|
+
# An awesome-list repo indexes other repos; there is nothing of its own
|
|
86
|
+
# to embed, so a job for it would produce no shard and fail.
|
|
87
|
+
from boost_cli.core import config
|
|
88
|
+
lists = {e["name"] for e in config.load_registry_catalog()
|
|
89
|
+
if e.get("list_only")}
|
|
90
|
+
names = {r["name"] for r in shard_plan.catalog_rows()}
|
|
91
|
+
assert not (names & lists)
|
|
92
|
+
if lists:
|
|
93
|
+
assert names < {r["name"] for r
|
|
94
|
+
in shard_plan.catalog_rows(include_lists=True)}
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
class TestCli:
|
|
98
|
+
def _run(self, *args):
|
|
99
|
+
return subprocess.run([sys.executable,
|
|
100
|
+
str(ROOT / "scripts" / "shard_plan.py"), *args],
|
|
101
|
+
capture_output=True, text=True)
|
|
102
|
+
|
|
103
|
+
def test_it_emits_a_json_list_of_space_separated_chunks(self):
|
|
104
|
+
out = self._run("--scope", "catalog", "--jobs", "12").stdout
|
|
105
|
+
matrix = json.loads(out)
|
|
106
|
+
assert len(matrix) == 12
|
|
107
|
+
assert all(isinstance(chunk, str) for chunk in matrix)
|
|
108
|
+
assert all("/" in chunk for chunk in matrix)
|
|
109
|
+
|
|
110
|
+
def test_over_the_ceiling_is_a_hard_error_not_a_truncation(self):
|
|
111
|
+
# Truncating would silently drop registries from the publish.
|
|
112
|
+
res = self._run("--scope", "catalog", "--jobs", "300")
|
|
113
|
+
assert res.returncode != 0
|
|
114
|
+
assert "256" in res.stderr + res.stdout
|
|
115
|
+
|
|
116
|
+
def test_explain_reports_the_shape(self):
|
|
117
|
+
out = self._run("--scope", "catalog", "--jobs", "10", "--explain").stdout
|
|
118
|
+
assert "heaviest" in out and "lightest" in out
|
|
119
|
+
|
|
120
|
+
def test_the_whole_catalogue_fits_the_default_plan(self):
|
|
121
|
+
# The number the workflow actually runs with.
|
|
122
|
+
matrix = json.loads(self._run("--scope", "catalog").stdout)
|
|
123
|
+
assert len(matrix) <= shard_plan.MAX_MATRIX_JOBS
|
|
124
|
+
packed = sum(len(chunk.split()) for chunk in matrix)
|
|
125
|
+
assert packed == len(shard_plan.catalog_rows())
|