boost-skill-cli 1.2.5__tar.gz → 1.2.6__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.5 → boost_skill_cli-1.2.6}/PKG-INFO +1 -1
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/registry.py +44 -4
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_skill_cli.egg-info/SOURCES.txt +4 -0
- boost_skill_cli-1.2.6/docs/roadmap/items/pathlib-exists-is-not-total.md +48 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap.html +46 -1
- boost_skill_cli-1.2.6/tests/fuzz/corpus/registry/09-nul.txt +0 -0
- boost_skill_cli-1.2.6/tests/fuzz/corpus/registry/10-name-too-long.txt +1 -0
- boost_skill_cli-1.2.6/tests/fuzz/corpus/registry/11-long-owner-repo.txt +1 -0
- boost_skill_cli-1.2.6/tests/unit/test_registry_control_chars.py +233 -0
- boost_skill_cli-1.2.5/tests/unit/test_registry_control_chars.py +0 -113
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.gitattributes +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.gitignore +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.lycheeignore +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.vale.ini +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/CLAUDE.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/LICENSE +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/MANIFEST.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/Makefile +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/SECURITY.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/bmad.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/bootstrap.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/browse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/builtin.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/catalogbundle.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/chat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/complete.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/localembed.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/selfupdate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/data/rules/boost-first.mdc +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_langchain/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_langchain/_compat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_langchain/graph.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_langchain/loader.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_langchain/py.typed +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_langchain/retriever.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/codecov.yml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/adapters.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/carousel.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/chat.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/commands.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/demo-index.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/demo.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/demo.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/demo.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/eval-latest.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/eval.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/index.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/langchain.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/agents-field-records-the-request-not-the-links.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/bmad-autopilot-one-command-persona-routing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/boost-first-carried-the-losing-trigger.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/boost-first-rule.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/boost-langchain-publishing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/browse-could-not-search-two-words.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/catalogue-entries-carry-no-content-identity.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/chat-cites-sources-by-a-number-it-never-prints.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/completions-install-could-eat-your-rc-file.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/crash-reports-leak-api-keys.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/demo-workflow-cancels-other-prs.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/dependabot-splits-multi-path-action-repos.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/discover-searches-github-not-a-stale-sample.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/dry-run-promised-a-link-nobody-makes.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/efficiency-registries-ponytail-caveman.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/est-items-counts-agent-mirrors-as-items.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/eval-corpus-is-96x-smaller-than-a-real-install.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/eval-stats-could-never-publish.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/expanded-card-bodies-overflow.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/gemini-agent-frontmatter-sanitizer.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/heal-deleted-links-it-never-made.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/install-path-disambiguation.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/langchain-in-the-wheel.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/langchain-integration-explainer-page.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/langchain-langgraph-langsmith-integration.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/langchain-retriever-metadata-and-k-floor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/lighthouse-scored-a-page-nobody-is-served.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-already-covered-defeater.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-search-hid-which-ranking-ran.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mcp-zero-setup-and-three-kinds.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/one-dead-tap-broke-every-update.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/pep585-604-modernization-sweep.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/python-floor-moves-to-312.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/ragas-unpin-when-upstream-ships.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/rules-install-but-cannot-be-governed.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/scripts-under-the-lint-gate.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/search-never-notices-a-new-tap.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/self-update-claims-up-to-date-without-asking.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/serve-404-reflected-the-request.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/serve-is-a-searchable-catalogue.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/shards-pipeline-never-produced-a-shard.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/shareable-catalogue-bundle.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sweep-died-at-launch-not-at-a-page.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sync-could-not-repair-a-gutted-skill.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/sync-reported-success-for-a-link-it-refused.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/taps-check-out-freight-they-never-index.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/the-catalogue-advertised-repos-that-no-longer-exist.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/tool-call-eval-tier.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/two-crashes-that-should-have-been-messages.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/unwatched-crons-hid-a-real-fuzz-crash.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/update-advertises-a-flag-it-rejects.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/update-refreshed-rules-without-a-gate.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/zip-strict-audit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/zizmor-ignores-drift-and-make-lint-never-ran-it.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/docs/superpowers/specs/2026-08-16-catalogue-content-identity-design.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/baseline.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/metrics.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/examples/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/index.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/noxfile.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/pyproject.toml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/build_demo_index.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/build_scale_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/check_required_checks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/eval_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/measure_registry.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/page_budget.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/publish_eval_json.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/scripts/serve_docs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/setup.cfg +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/sonar-project.properties +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/style/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/style/boost.css +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/style/boost.js +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/style/demo.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/conftest.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/eval/golden-natural.jsonl +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/eval/taps-scale.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_catalog.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_chat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_kind_conformance.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/langchain/conftest.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/langchain/test_graph.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/langchain/test_loader.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/langchain/test_retriever.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_action_pin_lockstep.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_bmad_core.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_boost_first_offer.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_bootstrap.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_browse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_builtin.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_catalogbundle.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_chat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_clean_internal_cache.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_compact.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_complete.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_complete_rc_block.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_content_dedupe.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_content_identity.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_crash_redaction.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dedup_trust.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_demo_index.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dense_embed_dedupe.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dense_fix_hint.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dense_shard_real_schema.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dense_shard_unreadable_vectors.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dense_shards.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_embed_local.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_embed_truncated_response.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_entry_key.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_eval_baseline.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_eval_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_eval_grading.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_failure_alerting_covers_unattended.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_gemini_agent_sanitize.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_gitutil_lfs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_gitutil_sparse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_install_permission_error.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_langchain_packaging.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_link_ownership.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_localembed.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_localembed_e2e.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_measure_registry.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_page_budget.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_rag_fusion.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_required_checks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_scale_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_selfupdate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_serve_docs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_shards_matrix.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_smoke_covers_every_command.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_store_materialize.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_sync_blocked_links.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_sync_repairs_gutted_skill.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_visual_harness_flags.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_workflow_concurrency_groups.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_workflow_push_has_credentials.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/unit/test_zizmor_ignores_still_anchor.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/tests/visual/visual_check.mjs +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.2.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 2,
|
|
21
|
+
__version__ = version = '1.2.6'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 2, 6)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -37,6 +37,29 @@ class Tap:
|
|
|
37
37
|
return self.path.is_dir()
|
|
38
38
|
|
|
39
39
|
|
|
40
|
+
# One path component, in BYTES. ext4, APFS and NTFS all stop at 255, and
|
|
41
|
+
# `Tap.safe_name` maps "/" to "__" — so the whole tap name becomes exactly one
|
|
42
|
+
# component under `~/.boost/repos` and this is its ceiling. A GitHub owner/repo
|
|
43
|
+
# maxes out at 140 (39 + 1 + 100), so nothing real comes near it.
|
|
44
|
+
MAX_NAME_BYTES = 255
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
def _looks_like_a_directory(p: Path) -> bool:
|
|
48
|
+
"""True if `p` is an existing directory, False if the OS will not say.
|
|
49
|
+
|
|
50
|
+
`Path.exists()` is not total. pathlib swallows ENOENT, ENOTDIR, EBADF and
|
|
51
|
+
ELOOP — ENAMETOOLONG is *not* in that set, so a long enough component makes
|
|
52
|
+
`os.stat` raise straight out of `parse_spec` as a bare OSError, which is not
|
|
53
|
+
a BoostError and so is never framed by the CLI's error handling. A path the
|
|
54
|
+
OS refuses to look at is not a directory we can tap; that is a "no", not a
|
|
55
|
+
crash.
|
|
56
|
+
"""
|
|
57
|
+
try:
|
|
58
|
+
return p.is_dir()
|
|
59
|
+
except OSError:
|
|
60
|
+
return False
|
|
61
|
+
|
|
62
|
+
|
|
40
63
|
def parse_spec(spec: str):
|
|
41
64
|
"""Resolve a tap spec -> (name, url).
|
|
42
65
|
|
|
@@ -61,18 +84,35 @@ def parse_spec(spec: str):
|
|
|
61
84
|
# own home-dir lookup (USERPROFILE on Windows), which ignores the $HOME
|
|
62
85
|
# override the whole test suite (and BOOST_HOME sandboxing) relies on.
|
|
63
86
|
p = paths.expand(spec)
|
|
64
|
-
if
|
|
65
|
-
return (p.resolve().name, str(p.resolve()))
|
|
87
|
+
if _looks_like_a_directory(p):
|
|
88
|
+
return _checked(p.resolve().name, str(p.resolve()), spec)
|
|
66
89
|
if spec.startswith(("http://", "https://", "git@", "ssh://")):
|
|
67
90
|
tail = spec.split(":")[-1] if spec.startswith("git@") else spec
|
|
68
91
|
parts = [x for x in tail.replace(".git", "").split("/") if x][-2:]
|
|
69
|
-
return ("/".join(parts), spec)
|
|
92
|
+
return _checked("/".join(parts), spec, spec)
|
|
70
93
|
if "/" in spec and " " not in spec:
|
|
71
|
-
return (spec, "https://github.com/%s" % spec)
|
|
94
|
+
return _checked(spec, "https://github.com/%s" % spec, spec)
|
|
72
95
|
raise BoostError("cannot parse tap spec %r" % spec,
|
|
73
96
|
hint="use owner/repo, a git URL, or a local directory")
|
|
74
97
|
|
|
75
98
|
|
|
99
|
+
def _checked(name: str, url: str, spec: str) -> tuple[str, str]:
|
|
100
|
+
"""The derived pair, or a BoostError if the name cannot be a directory.
|
|
101
|
+
|
|
102
|
+
The rule is on the *name*, never on the spec: a deep local path with a short
|
|
103
|
+
basename is a perfectly good tap, and its own length says nothing about the
|
|
104
|
+
component we are about to create. Caught here rather than at clone time,
|
|
105
|
+
where it surfaces as git's own ENAMETOOLONG on a path the user never typed.
|
|
106
|
+
"""
|
|
107
|
+
if len(name.encode("utf-8")) > MAX_NAME_BYTES:
|
|
108
|
+
raise BoostError(
|
|
109
|
+
"tap name is too long (%d bytes, limit %d): %r"
|
|
110
|
+
% (len(name.encode("utf-8")), MAX_NAME_BYTES, spec[:80]),
|
|
111
|
+
hint="the name becomes one directory under ~/.boost/repos, and "
|
|
112
|
+
"no filesystem accepts a longer component")
|
|
113
|
+
return (name, url)
|
|
114
|
+
|
|
115
|
+
|
|
76
116
|
def list_taps() -> list[Tap]:
|
|
77
117
|
"""Configured taps from config.json.
|
|
78
118
|
|
|
@@ -335,6 +335,7 @@ docs/roadmap/items/one-shared-atomic-write-helper.md
|
|
|
335
335
|
docs/roadmap/items/package-metadata-validation-twine-check-friends.md
|
|
336
336
|
docs/roadmap/items/patch-coverage-gate-diff-cover.md
|
|
337
337
|
docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md
|
|
338
|
+
docs/roadmap/items/pathlib-exists-is-not-total.md
|
|
338
339
|
docs/roadmap/items/pep585-604-modernization-sweep.md
|
|
339
340
|
docs/roadmap/items/performance-regression-gate-pytest-benchmark.md
|
|
340
341
|
docs/roadmap/items/pin-the-lint-toolchain.md
|
|
@@ -565,6 +566,9 @@ tests/fuzz/corpus/registry/05-empty.txt
|
|
|
565
566
|
tests/fuzz/corpus/registry/06-space.txt
|
|
566
567
|
tests/fuzz/corpus/registry/07-slash.txt
|
|
567
568
|
tests/fuzz/corpus/registry/08-bare-host.txt
|
|
569
|
+
tests/fuzz/corpus/registry/09-nul.txt
|
|
570
|
+
tests/fuzz/corpus/registry/10-name-too-long.txt
|
|
571
|
+
tests/fuzz/corpus/registry/11-long-owner-repo.txt
|
|
568
572
|
tests/langchain/conftest.py
|
|
569
573
|
tests/langchain/test_graph.py
|
|
570
574
|
tests/langchain/test_loader.py
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: pathlib-exists-is-not-total
|
|
3
|
+
board: code
|
|
4
|
+
section: internals
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Bug
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: Medium
|
|
9
|
+
wow: 4
|
|
10
|
+
note: the weekly fuzzer has now found two crashes in one function, three weeks apart, and been ignored both times
|
|
11
|
+
order: 118
|
|
12
|
+
owner: fix/tap-spec-name-too-long
|
|
13
|
+
pr: 528
|
|
14
|
+
title: <code>Path.exists()</code> looks total, and is not
|
|
15
|
+
---
|
|
16
|
+
<b><code>boost tap <anything long enough></code> died with a raw traceback on Linux.</b>
|
|
17
|
+
<code>parse_spec</code> probes whether the spec names an existing directory, and
|
|
18
|
+
<code>pathlib</code> swallows only <b>ENOENT, ENOTDIR, EBADF and ELOOP</b> —
|
|
19
|
+
<b>ENAMETOOLONG is not in that set</b>. So on any filesystem with a 255-byte component limit, which
|
|
20
|
+
is to say ext4 and therefore every Linux runner and most users, <code>os.stat</code> raises straight
|
|
21
|
+
out through <code>parse_spec</code> as a bare <code>OSError</code>. Not a <code>BoostError</code>,
|
|
22
|
+
so the CLI's error handling never got to frame it.
|
|
23
|
+
|
|
24
|
+
<b>macOS does not reproduce it.</b> That is the whole reason it shipped: the only thing that ever saw
|
|
25
|
+
it was the scheduled Linux fuzz job.
|
|
26
|
+
|
|
27
|
+
<b>Which had been reporting it for three weeks.</b> <code>fuzz.yml</code> runs libFuzzer over
|
|
28
|
+
<code>parse_spec</code> weekly and has now failed <b>four scheduled runs out of four</b>. The first
|
|
29
|
+
three were one bug — an embedded NUL — found on 2026-07-25, 08-01 and 08-08 and fixed
|
|
30
|
+
after the third. The fourth, on 08-15, is this one, minimised to 91 bytes: <code>0x38</code>
|
|
31
|
+
followed by ninety <code>0xff</code>, each un-decodable and so each becoming U+FFFD, which is
|
|
32
|
+
<b>three</b> UTF-8 bytes apiece — <b>271 bytes</b> from an input only 91 characters long.
|
|
33
|
+
|
|
34
|
+
<b>The limit is on bytes, and on the derived name.</b> Measuring characters would have let exactly
|
|
35
|
+
this input through. Measuring the <em>spec</em> would have turned away a legitimate deep local path
|
|
36
|
+
whose basename is short, so the rule applies to the name that is about to become one directory under
|
|
37
|
+
<code>~/.boost/repos</code>, caught at the parse boundary rather than at clone time where it
|
|
38
|
+
resurfaces as git's own ENAMETOOLONG on a path the user never typed.
|
|
39
|
+
|
|
40
|
+
<b>Rejecting is only half of it.</b> A path the OS refuses to <em>look at</em> is a “no”,
|
|
41
|
+
not a crash, so the probe is now total by construction — and pinned by a test on every
|
|
42
|
+
platform, not only the one where it fails, because a test that needs a real over-long path proves
|
|
43
|
+
nothing on the machine most of this is written on.
|
|
44
|
+
|
|
45
|
+
<b>Both reproducers are now seeds.</b> The NUL one was fixed and never added to the corpus, so
|
|
46
|
+
the fuzzer was free to spend runs rediscovering it. <code>tests/fuzz/corpus/registry/</code> carries
|
|
47
|
+
both, which means the no-atheris seed smoke — the path that runs without the fuzzer installed
|
|
48
|
+
— is now a regression test for both.
|
|
@@ -133,7 +133,7 @@
|
|
|
133
133
|
<div class="stat"><b>16</b><span>Shipped</span></div>
|
|
134
134
|
<div class="stat"><b>1</b><span>Next up</span></div>
|
|
135
135
|
<div class="stat"><b>7</b><span>Planned</span></div>
|
|
136
|
-
<div class="stat"><b>
|
|
136
|
+
<div class="stat"><b>256</b><span>Loop finds</span></div>
|
|
137
137
|
<!-- /ROADMAP:stats -->
|
|
138
138
|
</div>
|
|
139
139
|
</section>
|
|
@@ -4120,6 +4120,51 @@ separately for the same reason.</p></details>
|
|
|
4120
4120
|
<span class="m">a scheduled gate had never once passed, and the reason was one deleted upstream in its pinned corpus</span>
|
|
4121
4121
|
</div>
|
|
4122
4122
|
</article>
|
|
4123
|
+
|
|
4124
|
+
<article class="cap rcard" id="pathlib-exists-is-not-total">
|
|
4125
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug</span></div>
|
|
4126
|
+
<h3><code>Path.exists()</code> looks total, and is not</h3>
|
|
4127
|
+
<details class="cardbody"><summary>Write-up</summary>
|
|
4128
|
+
<p><b><code>boost tap <anything long enough></code> died with a raw traceback on Linux.</b>
|
|
4129
|
+
<code>parse_spec</code> probes whether the spec names an existing directory, and
|
|
4130
|
+
<code>pathlib</code> swallows only <b>ENOENT, ENOTDIR, EBADF and ELOOP</b> —
|
|
4131
|
+
<b>ENAMETOOLONG is not in that set</b>. So on any filesystem with a 255-byte component limit, which
|
|
4132
|
+
is to say ext4 and therefore every Linux runner and most users, <code>os.stat</code> raises straight
|
|
4133
|
+
out through <code>parse_spec</code> as a bare <code>OSError</code>. Not a <code>BoostError</code>,
|
|
4134
|
+
so the CLI's error handling never got to frame it.
|
|
4135
|
+
|
|
4136
|
+
<b>macOS does not reproduce it.</b> That is the whole reason it shipped: the only thing that ever saw
|
|
4137
|
+
it was the scheduled Linux fuzz job.
|
|
4138
|
+
|
|
4139
|
+
<b>Which had been reporting it for three weeks.</b> <code>fuzz.yml</code> runs libFuzzer over
|
|
4140
|
+
<code>parse_spec</code> weekly and has now failed <b>four scheduled runs out of four</b>. The first
|
|
4141
|
+
three were one bug — an embedded NUL — found on 2026-07-25, 08-01 and 08-08 and fixed
|
|
4142
|
+
after the third. The fourth, on 08-15, is this one, minimised to 91 bytes: <code>0x38</code>
|
|
4143
|
+
followed by ninety <code>0xff</code>, each un-decodable and so each becoming U+FFFD, which is
|
|
4144
|
+
<b>three</b> UTF-8 bytes apiece — <b>271 bytes</b> from an input only 91 characters long.
|
|
4145
|
+
|
|
4146
|
+
<b>The limit is on bytes, and on the derived name.</b> Measuring characters would have let exactly
|
|
4147
|
+
this input through. Measuring the <em>spec</em> would have turned away a legitimate deep local path
|
|
4148
|
+
whose basename is short, so the rule applies to the name that is about to become one directory under
|
|
4149
|
+
<code>~/.boost/repos</code>, caught at the parse boundary rather than at clone time where it
|
|
4150
|
+
resurfaces as git's own ENAMETOOLONG on a path the user never typed.
|
|
4151
|
+
|
|
4152
|
+
<b>Rejecting is only half of it.</b> A path the OS refuses to <em>look at</em> is a “no”,
|
|
4153
|
+
not a crash, so the probe is now total by construction — and pinned by a test on every
|
|
4154
|
+
platform, not only the one where it fails, because a test that needs a real over-long path proves
|
|
4155
|
+
nothing on the machine most of this is written on.
|
|
4156
|
+
|
|
4157
|
+
<b>Both reproducers are now seeds.</b> The NUL one was fixed and never added to the corpus, so
|
|
4158
|
+
the fuzzer was free to spend runs rediscovering it. <code>tests/fuzz/corpus/registry/</code> carries
|
|
4159
|
+
both, which means the no-atheris seed smoke — the path that runs without the fuzzer installed
|
|
4160
|
+
— is now a regression test for both.</p></details>
|
|
4161
|
+
<div class="meta">
|
|
4162
|
+
<span class="m">Complexity <b>S</b></span>
|
|
4163
|
+
<span class="m">Impact <b>Medium</b></span>
|
|
4164
|
+
<span class="m">Wow <b class="wow">★★★★</b></span>
|
|
4165
|
+
<span class="m">the weekly fuzzer has now found two crashes in one function, three weeks apart, and been ignored both times</span>
|
|
4166
|
+
</div>
|
|
4167
|
+
</article>
|
|
4123
4168
|
<!-- /ROADMAP:cards -->
|
|
4124
4169
|
|
|
4125
4170
|
</div>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
8������������������������������������������������������������������������������������������
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
owner/rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
"""Unit tests: a tap spec carrying control characters is rejected at the door.
|
|
2
|
+
|
|
3
|
+
`parse_spec` used to accept them. Given the ten bytes ``/\\0\\0\\0\\0\\0\\0\\0\\0A`` it
|
|
4
|
+
returned a perfectly well-formed pair::
|
|
5
|
+
|
|
6
|
+
('/\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00A',
|
|
7
|
+
'https://github.com//\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00A')
|
|
8
|
+
|
|
9
|
+
Nothing raised, so the name travelled onward — into ``config.json``, into
|
|
10
|
+
``Tap.safe_name``, and eventually into a filesystem call, where it died as
|
|
11
|
+
``ValueError: lstat: embedded null character in path`` from deep inside
|
|
12
|
+
``posixpath.realpath``. That message names neither the tap nor the command, and
|
|
13
|
+
``ValueError`` is not ``BoostError``, so the CLI's error handling never got to
|
|
14
|
+
frame it.
|
|
15
|
+
|
|
16
|
+
This is how the repo found out: ``fuzz.yml`` runs libFuzzer over ``parse_spec``
|
|
17
|
+
weekly, and it has failed **three scheduled runs out of three** — 2026-07-25,
|
|
18
|
+
08-01 and 08-08 — writing the same reproducer each time. Nobody noticed, because
|
|
19
|
+
``ci-failure-issue.yml`` watches only ``["ci", "demo"]``, so a red cron job is a
|
|
20
|
+
red square on a page nobody opens. The fuzzer had been right for three weeks.
|
|
21
|
+
|
|
22
|
+
A control character can never appear in a GitHub owner/repo, a git URL, or a
|
|
23
|
+
usable directory name, so there is no input this rejects that anyone wanted.
|
|
24
|
+
Rejecting at the parse boundary turns an arbitrary later ``ValueError`` into the
|
|
25
|
+
documented ``BoostError`` rejection path — which the fuzz harness already
|
|
26
|
+
handles, and which the CLI already renders with a hint.
|
|
27
|
+
"""
|
|
28
|
+
from __future__ import annotations
|
|
29
|
+
|
|
30
|
+
import pytest
|
|
31
|
+
|
|
32
|
+
from boost_cli.core import registry
|
|
33
|
+
from boost_cli.errors import BoostError
|
|
34
|
+
|
|
35
|
+
#: The exact ten bytes libFuzzer minimised to, decoded the way the harness does.
|
|
36
|
+
CRASHER = "/\x00\x00\x00\x00\x00\x00\x00\x00A"
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TestControlCharactersAreRejected:
|
|
40
|
+
def test_the_fuzzer_reproducer_raises_boost_error(self):
|
|
41
|
+
with pytest.raises(BoostError):
|
|
42
|
+
registry.parse_spec(CRASHER)
|
|
43
|
+
|
|
44
|
+
def test_a_bare_nul_is_rejected(self):
|
|
45
|
+
with pytest.raises(BoostError):
|
|
46
|
+
registry.parse_spec("owner/re\x00po")
|
|
47
|
+
|
|
48
|
+
@pytest.mark.parametrize("ch", ["\x00", "\x01", "\x07", "\x1b", "\x7f"])
|
|
49
|
+
def test_every_control_character_is_rejected(self, ch):
|
|
50
|
+
# \x1b in particular: an escape sequence in a name is echoed back by
|
|
51
|
+
# every surface that prints a tap list.
|
|
52
|
+
with pytest.raises(BoostError):
|
|
53
|
+
registry.parse_spec("owner/re%spo" % ch)
|
|
54
|
+
|
|
55
|
+
def test_the_error_names_the_problem(self):
|
|
56
|
+
with pytest.raises(BoostError) as caught:
|
|
57
|
+
registry.parse_spec(CRASHER)
|
|
58
|
+
assert "control character" in str(caught.value).lower()
|
|
59
|
+
|
|
60
|
+
def test_a_newline_or_tab_is_rejected_too(self):
|
|
61
|
+
# These survive `.strip()` when they are in the middle, and a newline in
|
|
62
|
+
# a tap name breaks every line-oriented output in the CLI.
|
|
63
|
+
for spec in ("owner/re\npo", "owner/re\tpo"):
|
|
64
|
+
with pytest.raises(BoostError):
|
|
65
|
+
registry.parse_spec(spec)
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
#: The 91 bytes libFuzzer minimised to on 2026-08-15, decoded the way the
|
|
69
|
+
#: harness does: `0x38` then ninety `0xff`, each of which is un-decodable and so
|
|
70
|
+
#: becomes U+FFFD — three UTF-8 bytes apiece, 271 bytes for the name alone.
|
|
71
|
+
TOO_LONG = "8" + "�" * 90
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
class TestAnOverlongSpecIsRejected:
|
|
75
|
+
"""The second thing the fuzzer found, and the same shape as the first.
|
|
76
|
+
|
|
77
|
+
``p.exists()`` looks total and is not. ``pathlib`` swallows only ENOENT,
|
|
78
|
+
ENOTDIR, EBADF and ELOOP; **ENAMETOOLONG is not in that set**, so on a
|
|
79
|
+
filesystem with a 255-byte component limit — ext4, which is to say every
|
|
80
|
+
Linux runner and most users — a long enough spec makes ``os.stat`` raise
|
|
81
|
+
straight through ``parse_spec``. macOS does not reproduce it, which is why
|
|
82
|
+
only the scheduled Linux fuzz job ever saw it.
|
|
83
|
+
|
|
84
|
+
Rejecting is not the whole fix. A *legitimate* long path (a deep directory
|
|
85
|
+
with a short basename) must still parse, so the probe treats "too long for
|
|
86
|
+
this OS" as "not an existing directory" and the length rule applies to the
|
|
87
|
+
derived NAME, which is what becomes a single component under
|
|
88
|
+
``~/.boost/repos``.
|
|
89
|
+
"""
|
|
90
|
+
|
|
91
|
+
def test_the_fuzzer_reproducer_raises_boost_error(self):
|
|
92
|
+
with pytest.raises(BoostError):
|
|
93
|
+
registry.parse_spec(TOO_LONG)
|
|
94
|
+
|
|
95
|
+
def test_an_overlong_owner_repo_is_rejected(self):
|
|
96
|
+
"""Plain ASCII reaches the same limit, it just takes 256 of them."""
|
|
97
|
+
with pytest.raises(BoostError):
|
|
98
|
+
registry.parse_spec("owner/" + "r" * 300)
|
|
99
|
+
|
|
100
|
+
def test_the_error_names_the_problem(self):
|
|
101
|
+
"""Only for a spec that *parses* — the fuzzer's own reproducer carries
|
|
102
|
+
no separator, so it is rejected as unparseable and never reaches the
|
|
103
|
+
length rule. Both paths raise BoostError, which is the invariant; this
|
|
104
|
+
pins the message on the one where length is the actual reason."""
|
|
105
|
+
with pytest.raises(BoostError) as caught:
|
|
106
|
+
registry.parse_spec("owner/" + "r" * 300)
|
|
107
|
+
assert "too long" in str(caught.value).lower()
|
|
108
|
+
|
|
109
|
+
def test_the_limit_is_on_bytes_not_characters(self):
|
|
110
|
+
"""A component limit is a *byte* limit, and non-ASCII costs more.
|
|
111
|
+
|
|
112
|
+
90 characters is nothing; 90 U+FFFD is 270 bytes and does not fit.
|
|
113
|
+
Measuring characters would let exactly the fuzzer's input through.
|
|
114
|
+
"""
|
|
115
|
+
assert len(TOO_LONG) < 255 < len(TOO_LONG.encode("utf-8"))
|
|
116
|
+
with pytest.raises(BoostError):
|
|
117
|
+
registry.parse_spec(TOO_LONG)
|
|
118
|
+
|
|
119
|
+
def test_a_probe_that_cannot_stat_is_not_an_existing_directory(self, tmp_path):
|
|
120
|
+
"""The OS refusing to look is a "no", not a crash.
|
|
121
|
+
|
|
122
|
+
This is the assertion that actually fails on Linux without the fix:
|
|
123
|
+
the spec is a path shape, so it reaches the filesystem probe before any
|
|
124
|
+
length rule could have rejected it.
|
|
125
|
+
"""
|
|
126
|
+
spec = str(tmp_path / ("d" * 400))
|
|
127
|
+
with pytest.raises(BoostError):
|
|
128
|
+
registry.parse_spec(spec)
|
|
129
|
+
|
|
130
|
+
def test_a_stat_that_raises_reads_as_not_a_directory(self):
|
|
131
|
+
"""Pinned on every platform, because it only *fails* on one.
|
|
132
|
+
|
|
133
|
+
macOS returns False where Linux raises ENAMETOOLONG, so a test that
|
|
134
|
+
relies on a real long path proves nothing on the machine most of this
|
|
135
|
+
is written on — and this bug reached production precisely because the
|
|
136
|
+
scheduled Linux job was the only thing that ever saw it.
|
|
137
|
+
"""
|
|
138
|
+
class Raises:
|
|
139
|
+
def is_dir(self):
|
|
140
|
+
raise OSError(36, "File name too long")
|
|
141
|
+
|
|
142
|
+
assert registry._looks_like_a_directory(Raises()) is False
|
|
143
|
+
|
|
144
|
+
def test_a_stat_that_succeeds_is_still_a_directory(self, tmp_path):
|
|
145
|
+
"""The guard must not swallow the answer it exists to return."""
|
|
146
|
+
assert registry._looks_like_a_directory(tmp_path) is True
|
|
147
|
+
assert registry._looks_like_a_directory(tmp_path / "nope") is False
|
|
148
|
+
|
|
149
|
+
def test_the_rejection_carries_a_hint(self):
|
|
150
|
+
"""A BoostError with no hint is the CLI printing a dead end.
|
|
151
|
+
|
|
152
|
+
Every other rejection in `parse_spec` says what to do instead, and this
|
|
153
|
+
one has something specific to say: the name is about to become a
|
|
154
|
+
directory, which is why the limit is what it is.
|
|
155
|
+
"""
|
|
156
|
+
with pytest.raises(BoostError) as caught:
|
|
157
|
+
registry.parse_spec("owner/" + "r" * 300)
|
|
158
|
+
assert caught.value.hint
|
|
159
|
+
assert "~/.boost/repos" in caught.value.hint
|
|
160
|
+
|
|
161
|
+
def test_a_url_whose_derived_name_is_too_long_names_the_spec(self):
|
|
162
|
+
"""The URL branch derives a name too, and the error must be traceable
|
|
163
|
+
back to what the user typed rather than to the name we computed."""
|
|
164
|
+
with pytest.raises(BoostError) as caught:
|
|
165
|
+
registry.parse_spec("https://github.com/owner/" + "r" * 300)
|
|
166
|
+
assert "owner" in str(caught.value)
|
|
167
|
+
|
|
168
|
+
def test_a_long_path_with_a_short_basename_still_parses(self, tmp_path):
|
|
169
|
+
"""The rule is about the derived name, never the spec's own length."""
|
|
170
|
+
deep = tmp_path
|
|
171
|
+
for _ in range(6):
|
|
172
|
+
deep = deep / ("segment-" + "x" * 30)
|
|
173
|
+
deep = deep / "my-tap"
|
|
174
|
+
deep.mkdir(parents=True)
|
|
175
|
+
assert len(str(deep)) > 255
|
|
176
|
+
name, url = registry.parse_spec(str(deep))
|
|
177
|
+
assert name == "my-tap"
|
|
178
|
+
assert url == str(deep.resolve())
|
|
179
|
+
|
|
180
|
+
def test_a_name_at_the_limit_is_still_accepted(self):
|
|
181
|
+
"""Reject one byte over, not one byte under — the boundary is pinned
|
|
182
|
+
because an off-by-one here silently turns away a legal repo name."""
|
|
183
|
+
name = "o" * 100 + "/" + "r" * 154 # 255 bytes exactly
|
|
184
|
+
assert len(name.encode("utf-8")) == 255
|
|
185
|
+
assert registry.parse_spec(name)[0] == name
|
|
186
|
+
|
|
187
|
+
|
|
188
|
+
class TestOrdinarySpecsStillParse:
|
|
189
|
+
"""The rejection must not widen. Each of these is a documented input."""
|
|
190
|
+
|
|
191
|
+
def test_owner_repo(self):
|
|
192
|
+
assert registry.parse_spec("anthropics/skills") == (
|
|
193
|
+
"anthropics/skills", "https://github.com/anthropics/skills")
|
|
194
|
+
|
|
195
|
+
def test_an_https_url(self):
|
|
196
|
+
name, url = registry.parse_spec("https://github.com/acme/skills")
|
|
197
|
+
assert name == "acme/skills" and url.startswith("https://")
|
|
198
|
+
|
|
199
|
+
def test_an_ssh_url(self):
|
|
200
|
+
name, _url = registry.parse_spec("git@github.com:acme/skills.git")
|
|
201
|
+
assert name == "acme/skills"
|
|
202
|
+
|
|
203
|
+
def test_a_local_directory(self, tmp_path):
|
|
204
|
+
target = tmp_path / "my-skills"
|
|
205
|
+
target.mkdir()
|
|
206
|
+
name, url = registry.parse_spec(str(target))
|
|
207
|
+
assert name == "my-skills" and url == str(target.resolve())
|
|
208
|
+
|
|
209
|
+
def test_surrounding_whitespace_is_still_only_stripped(self):
|
|
210
|
+
# Leading/trailing whitespace is trimmed, not rejected — that is a
|
|
211
|
+
# paste artifact, not a hostile name, and it always worked.
|
|
212
|
+
assert registry.parse_spec(" acme/skills ")[0] == "acme/skills"
|
|
213
|
+
|
|
214
|
+
def test_a_unicode_name_is_not_a_control_character(self):
|
|
215
|
+
# Non-ASCII is legal in a path and must not be caught by this net.
|
|
216
|
+
assert registry.parse_spec("acmé/skïlls")[0] == "acmé/skïlls"
|
|
217
|
+
|
|
218
|
+
|
|
219
|
+
class TestTheDerivedPathIsNowAlwaysUsable:
|
|
220
|
+
"""The property the fuzz harness asserts, and could not reach before.
|
|
221
|
+
|
|
222
|
+
Its containment check calls ``os.path.realpath`` on the derived clone
|
|
223
|
+
directory. That is what raised — so the harness could never even evaluate
|
|
224
|
+
the invariant it exists to protect.
|
|
225
|
+
"""
|
|
226
|
+
|
|
227
|
+
def test_realpath_of_the_derived_path_no_longer_raises(self):
|
|
228
|
+
import os
|
|
229
|
+
with pytest.raises(BoostError):
|
|
230
|
+
name, url = registry.parse_spec(CRASHER)
|
|
231
|
+
# Unreachable once parse_spec rejects; kept so this test fails
|
|
232
|
+
# loudly rather than silently if the rejection is ever removed.
|
|
233
|
+
os.path.realpath(str(registry.Tap(name=name, url=url).path))
|
|
@@ -1,113 +0,0 @@
|
|
|
1
|
-
"""Unit tests: a tap spec carrying control characters is rejected at the door.
|
|
2
|
-
|
|
3
|
-
`parse_spec` used to accept them. Given the ten bytes ``/\\0\\0\\0\\0\\0\\0\\0\\0A`` it
|
|
4
|
-
returned a perfectly well-formed pair::
|
|
5
|
-
|
|
6
|
-
('/\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00A',
|
|
7
|
-
'https://github.com//\\x00\\x00\\x00\\x00\\x00\\x00\\x00\\x00A')
|
|
8
|
-
|
|
9
|
-
Nothing raised, so the name travelled onward — into ``config.json``, into
|
|
10
|
-
``Tap.safe_name``, and eventually into a filesystem call, where it died as
|
|
11
|
-
``ValueError: lstat: embedded null character in path`` from deep inside
|
|
12
|
-
``posixpath.realpath``. That message names neither the tap nor the command, and
|
|
13
|
-
``ValueError`` is not ``BoostError``, so the CLI's error handling never got to
|
|
14
|
-
frame it.
|
|
15
|
-
|
|
16
|
-
This is how the repo found out: ``fuzz.yml`` runs libFuzzer over ``parse_spec``
|
|
17
|
-
weekly, and it has failed **three scheduled runs out of three** — 2026-07-25,
|
|
18
|
-
08-01 and 08-08 — writing the same reproducer each time. Nobody noticed, because
|
|
19
|
-
``ci-failure-issue.yml`` watches only ``["ci", "demo"]``, so a red cron job is a
|
|
20
|
-
red square on a page nobody opens. The fuzzer had been right for three weeks.
|
|
21
|
-
|
|
22
|
-
A control character can never appear in a GitHub owner/repo, a git URL, or a
|
|
23
|
-
usable directory name, so there is no input this rejects that anyone wanted.
|
|
24
|
-
Rejecting at the parse boundary turns an arbitrary later ``ValueError`` into the
|
|
25
|
-
documented ``BoostError`` rejection path — which the fuzz harness already
|
|
26
|
-
handles, and which the CLI already renders with a hint.
|
|
27
|
-
"""
|
|
28
|
-
from __future__ import annotations
|
|
29
|
-
|
|
30
|
-
import pytest
|
|
31
|
-
|
|
32
|
-
from boost_cli.core import registry
|
|
33
|
-
from boost_cli.errors import BoostError
|
|
34
|
-
|
|
35
|
-
#: The exact ten bytes libFuzzer minimised to, decoded the way the harness does.
|
|
36
|
-
CRASHER = "/\x00\x00\x00\x00\x00\x00\x00\x00A"
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
class TestControlCharactersAreRejected:
|
|
40
|
-
def test_the_fuzzer_reproducer_raises_boost_error(self):
|
|
41
|
-
with pytest.raises(BoostError):
|
|
42
|
-
registry.parse_spec(CRASHER)
|
|
43
|
-
|
|
44
|
-
def test_a_bare_nul_is_rejected(self):
|
|
45
|
-
with pytest.raises(BoostError):
|
|
46
|
-
registry.parse_spec("owner/re\x00po")
|
|
47
|
-
|
|
48
|
-
@pytest.mark.parametrize("ch", ["\x00", "\x01", "\x07", "\x1b", "\x7f"])
|
|
49
|
-
def test_every_control_character_is_rejected(self, ch):
|
|
50
|
-
# \x1b in particular: an escape sequence in a name is echoed back by
|
|
51
|
-
# every surface that prints a tap list.
|
|
52
|
-
with pytest.raises(BoostError):
|
|
53
|
-
registry.parse_spec("owner/re%spo" % ch)
|
|
54
|
-
|
|
55
|
-
def test_the_error_names_the_problem(self):
|
|
56
|
-
with pytest.raises(BoostError) as caught:
|
|
57
|
-
registry.parse_spec(CRASHER)
|
|
58
|
-
assert "control character" in str(caught.value).lower()
|
|
59
|
-
|
|
60
|
-
def test_a_newline_or_tab_is_rejected_too(self):
|
|
61
|
-
# These survive `.strip()` when they are in the middle, and a newline in
|
|
62
|
-
# a tap name breaks every line-oriented output in the CLI.
|
|
63
|
-
for spec in ("owner/re\npo", "owner/re\tpo"):
|
|
64
|
-
with pytest.raises(BoostError):
|
|
65
|
-
registry.parse_spec(spec)
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
class TestOrdinarySpecsStillParse:
|
|
69
|
-
"""The rejection must not widen. Each of these is a documented input."""
|
|
70
|
-
|
|
71
|
-
def test_owner_repo(self):
|
|
72
|
-
assert registry.parse_spec("anthropics/skills") == (
|
|
73
|
-
"anthropics/skills", "https://github.com/anthropics/skills")
|
|
74
|
-
|
|
75
|
-
def test_an_https_url(self):
|
|
76
|
-
name, url = registry.parse_spec("https://github.com/acme/skills")
|
|
77
|
-
assert name == "acme/skills" and url.startswith("https://")
|
|
78
|
-
|
|
79
|
-
def test_an_ssh_url(self):
|
|
80
|
-
name, _url = registry.parse_spec("git@github.com:acme/skills.git")
|
|
81
|
-
assert name == "acme/skills"
|
|
82
|
-
|
|
83
|
-
def test_a_local_directory(self, tmp_path):
|
|
84
|
-
target = tmp_path / "my-skills"
|
|
85
|
-
target.mkdir()
|
|
86
|
-
name, url = registry.parse_spec(str(target))
|
|
87
|
-
assert name == "my-skills" and url == str(target.resolve())
|
|
88
|
-
|
|
89
|
-
def test_surrounding_whitespace_is_still_only_stripped(self):
|
|
90
|
-
# Leading/trailing whitespace is trimmed, not rejected — that is a
|
|
91
|
-
# paste artifact, not a hostile name, and it always worked.
|
|
92
|
-
assert registry.parse_spec(" acme/skills ")[0] == "acme/skills"
|
|
93
|
-
|
|
94
|
-
def test_a_unicode_name_is_not_a_control_character(self):
|
|
95
|
-
# Non-ASCII is legal in a path and must not be caught by this net.
|
|
96
|
-
assert registry.parse_spec("acmé/skïlls")[0] == "acmé/skïlls"
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
class TestTheDerivedPathIsNowAlwaysUsable:
|
|
100
|
-
"""The property the fuzz harness asserts, and could not reach before.
|
|
101
|
-
|
|
102
|
-
Its containment check calls ``os.path.realpath`` on the derived clone
|
|
103
|
-
directory. That is what raised — so the harness could never even evaluate
|
|
104
|
-
the invariant it exists to protect.
|
|
105
|
-
"""
|
|
106
|
-
|
|
107
|
-
def test_realpath_of_the_derived_path_no_longer_raises(self):
|
|
108
|
-
import os
|
|
109
|
-
with pytest.raises(BoostError):
|
|
110
|
-
name, url = registry.parse_spec(CRASHER)
|
|
111
|
-
# Unreachable once parse_spec rejects; kept so this test fails
|
|
112
|
-
# loudly rather than silently if the rejection is ever removed.
|
|
113
|
-
os.path.realpath(str(registry.Tap(name=name, url=url).path))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boost_skill_cli-1.2.5 → boost_skill_cli-1.2.6}/.vale/styles/config/vocabularies/boost/accept.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|