boost-skill-cli 1.2.5__tar.gz → 1.2.7__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.7}/PKG-INFO +1 -1
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/registry.py +44 -4
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_skill_cli.egg-info/SOURCES.txt +5 -0
- boost_skill_cli-1.2.7/docs/roadmap/items/pathlib-exists-is-not-total.md +48 -0
- boost_skill_cli-1.2.7/docs/roadmap/items/two-ci-controls-that-could-not-act.md +50 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap.html +93 -1
- boost_skill_cli-1.2.7/tests/fuzz/corpus/registry/09-nul.txt +0 -0
- boost_skill_cli-1.2.7/tests/fuzz/corpus/registry/10-name-too-long.txt +1 -0
- boost_skill_cli-1.2.7/tests/fuzz/corpus/registry/11-long-owner-repo.txt +1 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_failure_alerting_covers_unattended.py +44 -0
- boost_skill_cli-1.2.7/tests/unit/test_registry_control_chars.py +233 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_workflow_push_has_credentials.py +40 -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.7}/.gitattributes +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.gitignore +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.lycheeignore +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/.vale.ini +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/CLAUDE.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/LICENSE +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/MANIFEST.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/Makefile +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/SECURITY.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/bmad.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/bootstrap.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/browse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/builtin.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/catalogbundle.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/chat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/complete.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/localembed.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/selfupdate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/data/rules/boost-first.mdc +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_langchain/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_langchain/_compat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_langchain/graph.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_langchain/loader.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_langchain/py.typed +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_langchain/retriever.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/codecov.yml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/adapters.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/carousel.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/chat.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/commands.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/demo-index.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/demo.gif +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/demo.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/demo.tape +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/eval-latest.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/eval.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/index.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/langchain.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/bmad-autopilot-one-command-persona-routing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/boost-first-carried-the-losing-trigger.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/boost-first-rule.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/boost-langchain-publishing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/browse-could-not-search-two-words.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/catalogue-entries-carry-no-content-identity.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/completions-install-could-eat-your-rc-file.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/crash-reports-leak-api-keys.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/demo-workflow-cancels-other-prs.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/dependabot-splits-multi-path-action-repos.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/discover-searches-github-not-a-stale-sample.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/dry-run-promised-a-link-nobody-makes.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/efficiency-registries-ponytail-caveman.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/est-items-counts-agent-mirrors-as-items.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/eval-stats-could-never-publish.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/expanded-card-bodies-overflow.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/gemini-agent-frontmatter-sanitizer.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/heal-deleted-links-it-never-made.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/install-path-disambiguation.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/langchain-in-the-wheel.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/langchain-integration-explainer-page.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/langchain-langgraph-langsmith-integration.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/langchain-retriever-metadata-and-k-floor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/lighthouse-scored-a-page-nobody-is-served.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-already-covered-defeater.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-search-hid-which-ranking-ran.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mcp-zero-setup-and-three-kinds.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/one-dead-tap-broke-every-update.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/pep585-604-modernization-sweep.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/python-floor-moves-to-312.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/ragas-unpin-when-upstream-ships.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/rules-install-but-cannot-be-governed.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/scripts-under-the-lint-gate.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/search-never-notices-a-new-tap.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/serve-404-reflected-the-request.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/serve-is-a-searchable-catalogue.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/shards-pipeline-never-produced-a-shard.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/shareable-catalogue-bundle.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/sync-could-not-repair-a-gutted-skill.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/taps-check-out-freight-they-never-index.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/tool-call-eval-tier.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/two-crashes-that-should-have-been-messages.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/unwatched-crons-hid-a-real-fuzz-crash.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/update-advertises-a-flag-it-rejects.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/update-refreshed-rules-without-a-gate.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/roadmap/items/zip-strict-audit.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/docs/superpowers/specs/2026-08-16-catalogue-content-identity-design.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/__init__.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/baseline.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/metrics.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/examples/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/index.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/noxfile.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/pyproject.toml +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/build_demo_index.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/build_scale_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/check_required_checks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/eval_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/measure_registry.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/page_budget.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/publish_eval_json.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/scripts/serve_docs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/setup.cfg +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/sonar-project.properties +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/style/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/style/boost.css +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/style/boost.js +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/style/demo.html +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/conftest.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/eval/golden-natural.jsonl +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/eval/taps-scale.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_catalog.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_chat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_kind_conformance.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/langchain/conftest.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/langchain/test_graph.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/langchain/test_loader.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/langchain/test_retriever.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_action_pin_lockstep.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_bmad_core.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_boost_first_offer.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_bootstrap.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_browse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_builtin.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_catalogbundle.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_chat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_clean_internal_cache.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_compact.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_complete.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_complete_rc_block.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_content_dedupe.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_content_identity.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_crash_redaction.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dedup_trust.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_demo_index.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dense_embed_dedupe.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dense_fix_hint.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dense_shard_real_schema.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dense_shard_unreadable_vectors.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dense_shards.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_embed_local.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_embed_truncated_response.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_entry_key.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_eval_baseline.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_eval_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_eval_grading.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_gemini_agent_sanitize.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_gitutil_lfs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_gitutil_sparse.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_install_permission_error.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_langchain_packaging.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_link_ownership.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_localembed.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_localembed_e2e.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_measure_registry.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_page_budget.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_rag_fusion.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_required_checks.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_scale_corpus.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_selfupdate.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_serve_docs.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_shards_matrix.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_smoke_covers_every_command.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_store_materialize.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_sync_blocked_links.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_sync_repairs_gutted_skill.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_visual_harness_flags.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_workflow_concurrency_groups.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/unit/test_zizmor_ignores_still_anchor.py +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.2.5 → boost_skill_cli-1.2.7}/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.7'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 2, 7)
|
|
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
|
|
@@ -413,6 +414,7 @@ docs/roadmap/items/taps-check-out-freight-they-never-index.md
|
|
|
413
414
|
docs/roadmap/items/the-catalogue-advertised-repos-that-no-longer-exist.md
|
|
414
415
|
docs/roadmap/items/theme-asset-linting-stylelint-eslint.md
|
|
415
416
|
docs/roadmap/items/tool-call-eval-tier.md
|
|
417
|
+
docs/roadmap/items/two-ci-controls-that-could-not-act.md
|
|
416
418
|
docs/roadmap/items/two-crashes-that-should-have-been-messages.md
|
|
417
419
|
docs/roadmap/items/typo-detection-codespell.md
|
|
418
420
|
docs/roadmap/items/typosquat-and-name-confusion-detection.md
|
|
@@ -565,6 +567,9 @@ tests/fuzz/corpus/registry/05-empty.txt
|
|
|
565
567
|
tests/fuzz/corpus/registry/06-space.txt
|
|
566
568
|
tests/fuzz/corpus/registry/07-slash.txt
|
|
567
569
|
tests/fuzz/corpus/registry/08-bare-host.txt
|
|
570
|
+
tests/fuzz/corpus/registry/09-nul.txt
|
|
571
|
+
tests/fuzz/corpus/registry/10-name-too-long.txt
|
|
572
|
+
tests/fuzz/corpus/registry/11-long-owner-repo.txt
|
|
568
573
|
tests/langchain/conftest.py
|
|
569
574
|
tests/langchain/test_graph.py
|
|
570
575
|
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.
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: two-ci-controls-that-could-not-act
|
|
3
|
+
board: code
|
|
4
|
+
section: internals
|
|
5
|
+
status: shipped
|
|
6
|
+
category: CI · Correctness
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: Medium
|
|
9
|
+
wow: 4
|
|
10
|
+
note: one publisher could never publish and one alert could never stand down — both reported success
|
|
11
|
+
order: 119
|
|
12
|
+
owner: fix/ci-controls-that-cannot-act
|
|
13
|
+
pr: 529
|
|
14
|
+
title: a publisher that could not publish, and an alert that could not stand down
|
|
15
|
+
---
|
|
16
|
+
<b>Two controls, the same failure mode: present, running, and structurally unable to do the thing
|
|
17
|
+
they exist for.</b>
|
|
18
|
+
|
|
19
|
+
<b>1. <code>eval-stats</code> pushed to a branch no token can push to.</b> An earlier fix got the
|
|
20
|
+
credentials right — the checkout uses <code>persist-credentials: false</code>, so the push
|
|
21
|
+
needed its own token URL, and it got one. That took the workflow as far as a <em>different</em>
|
|
22
|
+
permanent failure: <code>GH013: Repository rule violations found for refs/heads/main</code>.
|
|
23
|
+
<code>main</code> carries a ruleset with a <code>pull_request</code> rule and an <b>empty bypass
|
|
24
|
+
list</b>, so no token can push to it — not <code>github.token</code>, not a PAT, not any bot.
|
|
25
|
+
The workflow was not misconfigured; it was impossible.
|
|
26
|
+
|
|
27
|
+
<b>The remedy is not a bypass actor.</b> Adding one would open the protection guarding every change
|
|
28
|
+
to main so that a docs payload can skip review. The refreshed metrics now arrive the way
|
|
29
|
+
<code>eval-corpus-refresh.yml</code> already lands its moved pins — as a pull request on one
|
|
30
|
+
long-lived <code>bot/eval-metrics</code> branch that each run updates in place, rather than a new PR
|
|
31
|
+
a week. Reviewable, mergeable, and no weaker than any other change to main. It carries the same
|
|
32
|
+
warning that workflow's PRs do: a <code>GITHUB_TOKEN</code> push never triggers workflows, so the
|
|
33
|
+
check list is empty until someone presses <b>Update branch</b>, and empty looks exactly like
|
|
34
|
+
“not started yet”.
|
|
35
|
+
|
|
36
|
+
<b>2. The failure tracker opened issues and never closed one.</b> Its own closing line said
|
|
37
|
+
“close this once CI is green again” — a manual step nobody had a reason to take. So
|
|
38
|
+
<code>visual</code> stayed open through <b>four consecutive green runs</b>, and an issue list that
|
|
39
|
+
mixes live outages with fixed ones makes every entry in it read as equally suspect. An alert that
|
|
40
|
+
cannot stand down is only half an alert. A success on main now closes the tracker for
|
|
41
|
+
<em>that</em> workflow, keyed on the same per-workflow marker the opener writes — a
|
|
42
|
+
<code>ci</code> success must never close a <code>demo</code> tracker.
|
|
43
|
+
|
|
44
|
+
<b>The second job is what made the permissions wrong.</b> <code>issues: write</code> sat at the
|
|
45
|
+
workflow level, where it reaches every job including any added later; zizmor's excessive-permissions
|
|
46
|
+
audit says so and now fails the build on it. Each job asks for its own.
|
|
47
|
+
|
|
48
|
+
<b>Both halves are pinned statically</b>, and the push guard was verified by reversion: restore the
|
|
49
|
+
old <code>HEAD:main</code> and the test names the exact line. The guard outlives this fix — it
|
|
50
|
+
is parametrised over every workflow that pushes, so the next one cannot rediscover the same wall.
|
|
@@ -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>257</b><span>Loop finds</span></div>
|
|
137
137
|
<!-- /ROADMAP:stats -->
|
|
138
138
|
</div>
|
|
139
139
|
</section>
|
|
@@ -4120,6 +4120,98 @@ 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>
|
|
4168
|
+
|
|
4169
|
+
<article class="cap rcard" id="two-ci-controls-that-could-not-act">
|
|
4170
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">CI · Correctness</span></div>
|
|
4171
|
+
<h3>a publisher that could not publish, and an alert that could not stand down</h3>
|
|
4172
|
+
<details class="cardbody"><summary>Write-up</summary>
|
|
4173
|
+
<p><b>Two controls, the same failure mode: present, running, and structurally unable to do the thing
|
|
4174
|
+
they exist for.</b>
|
|
4175
|
+
|
|
4176
|
+
<b>1. <code>eval-stats</code> pushed to a branch no token can push to.</b> An earlier fix got the
|
|
4177
|
+
credentials right — the checkout uses <code>persist-credentials: false</code>, so the push
|
|
4178
|
+
needed its own token URL, and it got one. That took the workflow as far as a <em>different</em>
|
|
4179
|
+
permanent failure: <code>GH013: Repository rule violations found for refs/heads/main</code>.
|
|
4180
|
+
<code>main</code> carries a ruleset with a <code>pull_request</code> rule and an <b>empty bypass
|
|
4181
|
+
list</b>, so no token can push to it — not <code>github.token</code>, not a PAT, not any bot.
|
|
4182
|
+
The workflow was not misconfigured; it was impossible.
|
|
4183
|
+
|
|
4184
|
+
<b>The remedy is not a bypass actor.</b> Adding one would open the protection guarding every change
|
|
4185
|
+
to main so that a docs payload can skip review. The refreshed metrics now arrive the way
|
|
4186
|
+
<code>eval-corpus-refresh.yml</code> already lands its moved pins — as a pull request on one
|
|
4187
|
+
long-lived <code>bot/eval-metrics</code> branch that each run updates in place, rather than a new PR
|
|
4188
|
+
a week. Reviewable, mergeable, and no weaker than any other change to main. It carries the same
|
|
4189
|
+
warning that workflow's PRs do: a <code>GITHUB_TOKEN</code> push never triggers workflows, so the
|
|
4190
|
+
check list is empty until someone presses <b>Update branch</b>, and empty looks exactly like
|
|
4191
|
+
“not started yet”.
|
|
4192
|
+
|
|
4193
|
+
<b>2. The failure tracker opened issues and never closed one.</b> Its own closing line said
|
|
4194
|
+
“close this once CI is green again” — a manual step nobody had a reason to take. So
|
|
4195
|
+
<code>visual</code> stayed open through <b>four consecutive green runs</b>, and an issue list that
|
|
4196
|
+
mixes live outages with fixed ones makes every entry in it read as equally suspect. An alert that
|
|
4197
|
+
cannot stand down is only half an alert. A success on main now closes the tracker for
|
|
4198
|
+
<em>that</em> workflow, keyed on the same per-workflow marker the opener writes — a
|
|
4199
|
+
<code>ci</code> success must never close a <code>demo</code> tracker.
|
|
4200
|
+
|
|
4201
|
+
<b>The second job is what made the permissions wrong.</b> <code>issues: write</code> sat at the
|
|
4202
|
+
workflow level, where it reaches every job including any added later; zizmor's excessive-permissions
|
|
4203
|
+
audit says so and now fails the build on it. Each job asks for its own.
|
|
4204
|
+
|
|
4205
|
+
<b>Both halves are pinned statically</b>, and the push guard was verified by reversion: restore the
|
|
4206
|
+
old <code>HEAD:main</code> and the test names the exact line. The guard outlives this fix — it
|
|
4207
|
+
is parametrised over every workflow that pushes, so the next one cannot rediscover the same wall.</p></details>
|
|
4208
|
+
<div class="meta">
|
|
4209
|
+
<span class="m">Complexity <b>S</b></span>
|
|
4210
|
+
<span class="m">Impact <b>Medium</b></span>
|
|
4211
|
+
<span class="m">Wow <b class="wow">★★★★</b></span>
|
|
4212
|
+
<span class="m">one publisher could never publish and one alert could never stand down — both reported success</span>
|
|
4213
|
+
</div>
|
|
4214
|
+
</article>
|
|
4123
4215
|
<!-- /ROADMAP:cards -->
|
|
4124
4216
|
|
|
4125
4217
|
</div>
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
8������������������������������������������������������������������������������������������
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
owner/rrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr
|
|
@@ -130,3 +130,47 @@ class TestEveryUnattendedWorkflowIsWatched:
|
|
|
130
130
|
names = {workflow_name(p.read_text(encoding="utf-8"), p.stem)
|
|
131
131
|
for p in WORKFLOWS.glob("*.yml")}
|
|
132
132
|
assert watched() <= names, sorted(watched() - names)
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
class TestTheAlertCanStandDown:
|
|
136
|
+
"""An alert that cannot close is only half an alert.
|
|
137
|
+
|
|
138
|
+
The tracker opened issues, commented on repeats, and never closed one — so
|
|
139
|
+
its own closing line, "close this once CI is green again", was a manual step
|
|
140
|
+
nobody had a reason to take. `visual` stayed open through four consecutive
|
|
141
|
+
green runs, and a list that mixes live outages with fixed ones makes every
|
|
142
|
+
entry in it read as equally suspect.
|
|
143
|
+
"""
|
|
144
|
+
|
|
145
|
+
def test_a_success_on_main_closes_the_tracker(self):
|
|
146
|
+
text = ALERT.read_text(encoding="utf-8")
|
|
147
|
+
assert "conclusion == 'success'" in text, (
|
|
148
|
+
"nothing reacts to a watched workflow going green, so every "
|
|
149
|
+
"tracker this file opens stays open until someone closes it")
|
|
150
|
+
assert "state: 'closed'" in text
|
|
151
|
+
|
|
152
|
+
def test_closing_is_keyed_by_workflow_like_opening(self):
|
|
153
|
+
"""A `ci` success must not close a `demo` tracker.
|
|
154
|
+
|
|
155
|
+
The opener keys its marker on the workflow name for exactly this
|
|
156
|
+
reason; a closer that matched any `ci-failure` issue would undo that.
|
|
157
|
+
"""
|
|
158
|
+
text = ALERT.read_text(encoding="utf-8")
|
|
159
|
+
assert text.count("ci-failure-tracker:${run.name}") >= 2, (
|
|
160
|
+
"the closing half must use the same per-workflow marker the "
|
|
161
|
+
"opening half writes")
|
|
162
|
+
|
|
163
|
+
def test_only_main_can_close_it(self):
|
|
164
|
+
"""`workflow_run` fires for the default branch, but the opener still
|
|
165
|
+
checks — and an asymmetry here would let a non-main success close a
|
|
166
|
+
tracker for a failure that is still live on main."""
|
|
167
|
+
text = ALERT.read_text(encoding="utf-8")
|
|
168
|
+
assert text.count("head_branch == 'main'") >= 2
|
|
169
|
+
|
|
170
|
+
def test_permissions_are_not_granted_workflow_wide(self):
|
|
171
|
+
"""`issues: write` at the top reaches every job, including any added
|
|
172
|
+
later. zizmor's excessive-permissions audit fails the build on it."""
|
|
173
|
+
text = ALERT.read_text(encoding="utf-8")
|
|
174
|
+
assert re.search(r"^permissions:\s*\{\}\s*$", text, re.M), \
|
|
175
|
+
"workflow-level permissions must be empty; each job asks for its own"
|
|
176
|
+
assert text.count("issues: write") >= 2
|
|
@@ -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))
|