boost-skill-cli 1.0.451__tar.gz → 1.0.452__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/pkg.py +15 -2
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/quality.py +14 -2
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/embed.py +9 -1
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/logs.py +38 -1
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/store.py +45 -6
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_skill_cli.egg-info/SOURCES.txt +7 -0
- boost_skill_cli-1.0.452/docs/roadmap/items/crash-reports-leak-api-keys.md +33 -0
- boost_skill_cli-1.0.452/docs/roadmap/items/sync-reported-success-for-a-link-it-refused.md +32 -0
- boost_skill_cli-1.0.452/docs/roadmap/items/two-crashes-that-should-have-been-messages.md +34 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap.html +88 -1
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_pkg.py +3 -2
- boost_skill_cli-1.0.452/tests/unit/test_crash_redaction.py +58 -0
- boost_skill_cli-1.0.452/tests/unit/test_embed_truncated_response.py +68 -0
- boost_skill_cli-1.0.452/tests/unit/test_install_permission_error.py +56 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_store.py +1 -1
- boost_skill_cli-1.0.452/tests/unit/test_sync_blocked_links.py +128 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.gitattributes +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.gitignore +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.lycheeignore +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/.vale.ini +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/LICENSE +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/Makefile +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/README.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/bmad.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/bootstrap.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/builtin.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/catalogbundle.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/chat.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/complete.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/localembed.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/selfupdate.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/data/rules/boost-first.mdc +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_langchain/__init__.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_langchain/_compat.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_langchain/graph.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_langchain/loader.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_langchain/py.typed +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_langchain/retriever.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/codecov.yml +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/carousel.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/chat.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/commands.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/demo-index.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/demo.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/eval-latest.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/index.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/langchain.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/agents-field-records-the-request-not-the-links.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/bmad-autopilot-one-command-persona-routing.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/boost-first-carried-the-losing-trigger.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/boost-first-rule.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/boost-langchain-publishing.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/chat-cites-sources-by-a-number-it-never-prints.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/demo-workflow-cancels-other-prs.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/dependabot-splits-multi-path-action-repos.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/discover-searches-github-not-a-stale-sample.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/dry-run-promised-a-link-nobody-makes.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/efficiency-registries-ponytail-caveman.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/est-items-counts-agent-mirrors-as-items.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/eval-corpus-is-96x-smaller-than-a-real-install.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/eval-stats-could-never-publish.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/expanded-card-bodies-overflow.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/gemini-agent-frontmatter-sanitizer.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/heal-deleted-links-it-never-made.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/install-path-disambiguation.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/langchain-in-the-wheel.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/langchain-integration-explainer-page.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/langchain-langgraph-langsmith-integration.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/langchain-retriever-metadata-and-k-floor.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/lighthouse-scored-a-page-nobody-is-served.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-already-covered-defeater.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-search-hid-which-ranking-ran.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mcp-zero-setup-and-three-kinds.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/one-dead-tap-broke-every-update.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/pep585-604-modernization-sweep.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/python-floor-moves-to-312.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/ragas-unpin-when-upstream-ships.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/rules-install-but-cannot-be-governed.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/scripts-under-the-lint-gate.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/search-never-notices-a-new-tap.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/self-update-claims-up-to-date-without-asking.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/serve-404-reflected-the-request.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/serve-is-a-searchable-catalogue.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/shards-pipeline-never-produced-a-shard.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/shareable-catalogue-bundle.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/sync-could-not-repair-a-gutted-skill.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/tool-call-eval-tier.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/unwatched-crons-hid-a-real-fuzz-crash.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/update-advertises-a-flag-it-rejects.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/update-refreshed-rules-without-a-gate.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/zip-strict-audit.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/zizmor-ignores-drift-and-make-lint-never-ran-it.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/README.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/__init__.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/baseline.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/metrics.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/examples/README.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/index.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/noxfile.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/build_demo_index.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/build_scale_corpus.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/check_required_checks.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/eval_corpus.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/measure_registry.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/page_budget.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/publish_eval_json.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/scripts/serve_docs.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/setup.cfg +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/sonar-project.properties +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/style/README.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/style/boost.css +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/style/boost.js +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/style/demo.html +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/eval/golden-natural.jsonl +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/eval/taps-scale.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_catalog.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_chat.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_kind_conformance.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/langchain/conftest.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/langchain/test_graph.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/langchain/test_loader.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/langchain/test_retriever.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_action_pin_lockstep.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_bmad_core.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_boost_first_offer.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_bootstrap.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_builtin.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_catalogbundle.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_chat.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_complete.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_content_dedupe.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dedup_trust.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_demo_index.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dense_fix_hint.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dense_shard_real_schema.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dense_shard_unreadable_vectors.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dense_shards.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_embed_local.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_entry_key.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_eval_baseline.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_eval_corpus.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_eval_grading.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_failure_alerting_covers_unattended.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_gemini_agent_sanitize.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_gitutil_lfs.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_langchain_packaging.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_link_ownership.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_localembed.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_localembed_e2e.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_measure_registry.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_page_budget.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_publish_golden_dataset.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_rag_fusion.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_registry_control_chars.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_required_checks.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_scale_corpus.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_selfupdate.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_serve_docs.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_shards_matrix.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_smoke_covers_every_command.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_sync_repairs_gutted_skill.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_workflow_concurrency_groups.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_workflow_push_has_credentials.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/unit/test_zizmor_ignores_still_anchor.py +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.0.451 → boost_skill_cli-1.0.452}/tests/visual/visual_check.mjs +0 -0
|
@@ -18,7 +18,7 @@ version_tuple: tuple[int | str, ...]
|
|
|
18
18
|
commit_id: str | None
|
|
19
19
|
__commit_id__: str | None
|
|
20
20
|
|
|
21
|
-
__version__ = version = '1.0.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 0,
|
|
21
|
+
__version__ = version = '1.0.452'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 452)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -568,6 +568,7 @@ def cmd_uninstall(argv: list[str]) -> int:
|
|
|
568
568
|
_PLAN_LABELS = [
|
|
569
569
|
("missing_store", "missing from store"),
|
|
570
570
|
("missing_links", "missing agent links"),
|
|
571
|
+
("blocked_links", "agent links blocked by a foreign file"),
|
|
571
572
|
("stale_links", "stale links"),
|
|
572
573
|
("orphaned_store", "orphaned store dirs"),
|
|
573
574
|
("missing_materializations", "missing rule/workflow files"),
|
|
@@ -651,9 +652,11 @@ def cmd_sync(argv: list[str]) -> int:
|
|
|
651
652
|
journal.log("prune", name)
|
|
652
653
|
pruned.append(name)
|
|
653
654
|
left = [n for n in orphans if n not in pruned]
|
|
655
|
+
blocked = plan["blocked_links"]
|
|
654
656
|
if args.json:
|
|
655
657
|
print(json.dumps({"actions": actions, "pruned": pruned,
|
|
656
|
-
"orphaned_store": left, "out_of_scope_links": oos
|
|
658
|
+
"orphaned_store": left, "out_of_scope_links": oos,
|
|
659
|
+
"blocked_links": blocked}))
|
|
657
660
|
return 0
|
|
658
661
|
for a in actions:
|
|
659
662
|
out.ok(a)
|
|
@@ -668,7 +671,17 @@ def cmd_sync(argv: list[str]) -> int:
|
|
|
668
671
|
"`boost install <skill> --force` naming every `--agent`"
|
|
669
672
|
% (_plural(len(oos), "link"),
|
|
670
673
|
", ".join("%s → %s" % (n, a) for n, a in oos)))
|
|
671
|
-
|
|
674
|
+
# Before this, a blocked link produced no action and no warning, so the
|
|
675
|
+
# branch below reported "everything in sync" for a repair that had just
|
|
676
|
+
# been refused — and `boost doctor` went on prescribing this command.
|
|
677
|
+
if blocked:
|
|
678
|
+
out.warn("%s could not be created: %s. boost will not delete a file it "
|
|
679
|
+
"does not own — move or delete the path, then re-run `boost "
|
|
680
|
+
"sync`"
|
|
681
|
+
% (_plural(len(blocked), "agent link"),
|
|
682
|
+
", ".join("%s → %s (%s in the way)"
|
|
683
|
+
% (n, a, _tilde(Path(p))) for n, a, p in blocked)))
|
|
684
|
+
if not actions and not pruned and not left and not oos and not blocked:
|
|
672
685
|
out.ok("everything in sync")
|
|
673
686
|
return 0
|
|
674
687
|
|
|
@@ -427,9 +427,21 @@ def cmd_doctor(argv):
|
|
|
427
427
|
if adir is None:
|
|
428
428
|
continue
|
|
429
429
|
link = adir / name
|
|
430
|
-
|
|
430
|
+
# Two different failures wore one message. `boost sync` creates a
|
|
431
|
+
# link where nothing is in the way and replaces a boost-owned one
|
|
432
|
+
# that dangles — but it will not delete a real file or directory
|
|
433
|
+
# another installer put there, so prescribing it for that case sent
|
|
434
|
+
# the reader in a circle: sync answers "everything in sync", doctor
|
|
435
|
+
# repeats itself. Name the thing in the way instead.
|
|
436
|
+
if link.is_symlink() and link.exists():
|
|
437
|
+
continue
|
|
438
|
+
if not link.is_symlink() and link.exists():
|
|
439
|
+
bad("skill %s not linked for %s — %s exists and is not a boost "
|
|
440
|
+
"link; move or delete it, then run `boost sync`"
|
|
441
|
+
% (name, agent, paths.tilde(link)))
|
|
442
|
+
else:
|
|
431
443
|
bad("skill %s not linked for %s — run `boost sync`" % (name, agent))
|
|
432
|
-
|
|
444
|
+
skill_issues += 1
|
|
433
445
|
# The other direction. `agents` records what is linked and `only_agents`
|
|
434
446
|
# what was asked for, so a link the declaration excludes is pure lock
|
|
435
447
|
# arithmetic here — no second walk of the agent dirs. Doctor has to say
|
|
@@ -33,6 +33,7 @@ index.
|
|
|
33
33
|
from __future__ import annotations
|
|
34
34
|
|
|
35
35
|
import contextlib
|
|
36
|
+
import http.client
|
|
36
37
|
import json
|
|
37
38
|
import os
|
|
38
39
|
import urllib.error
|
|
@@ -253,7 +254,14 @@ def _post(url: str, key: str, payload: dict, timeout: int) -> dict | None:
|
|
|
253
254
|
try:
|
|
254
255
|
with nethttp.urlopen(req, timeout=timeout) as resp:
|
|
255
256
|
return json.loads(resp.read())
|
|
256
|
-
|
|
257
|
+
# http.client.HTTPException is the gap this list used to have. A connection
|
|
258
|
+
# cut mid-body raises IncompleteRead, which subclasses HTTPException and
|
|
259
|
+
# *neither* OSError nor ValueError — so it went straight through and out of
|
|
260
|
+
# `boost search` as a traceback, for a network hiccup whose right answer is
|
|
261
|
+
# to fall back to BM25. (RemoteDisconnected was already covered only by
|
|
262
|
+
# accident: it also subclasses ConnectionResetError.)
|
|
263
|
+
except (urllib.error.URLError, OSError, ValueError,
|
|
264
|
+
http.client.HTTPException):
|
|
257
265
|
return None
|
|
258
266
|
|
|
259
267
|
|
|
@@ -47,6 +47,7 @@ import logging
|
|
|
47
47
|
import logging.handlers
|
|
48
48
|
import os
|
|
49
49
|
import platform
|
|
50
|
+
import re
|
|
50
51
|
import sys
|
|
51
52
|
import time
|
|
52
53
|
import traceback
|
|
@@ -262,10 +263,46 @@ def _boost_version() -> str:
|
|
|
262
263
|
return "unknown"
|
|
263
264
|
|
|
264
265
|
|
|
266
|
+
#: Variable names whose value is a credential by definition. Matched on the
|
|
267
|
+
#: trailing word so ``BOOST_ANTHROPIC_API_KEY``, ``BOOST_GITHUB_TOKEN`` and
|
|
268
|
+
#: ``BOOST_TAP_PASSWORD`` are all caught without enumerating providers.
|
|
269
|
+
_SECRET_NAME = re.compile(
|
|
270
|
+
r"(?:KEY|TOKEN|SECRET|PASSWORD|PASSWD|CREDENTIALS?|AUTH)$", re.IGNORECASE)
|
|
271
|
+
|
|
272
|
+
#: Value prefixes that are unmistakably a credential whatever the variable is
|
|
273
|
+
#: called. A name denylist alone always trails the next provider someone adds,
|
|
274
|
+
#: and the leak this guards against cost nothing to introduce: boost documents
|
|
275
|
+
#: ``BOOST_ANTHROPIC_API_KEY``, so the variable most likely to be *set* was also
|
|
276
|
+
#: the one most likely to be secret.
|
|
277
|
+
_SECRET_VALUE = re.compile(
|
|
278
|
+
r"^(?:sk-|pk-|rk-|voy-|pa-|ghp_|gho_|ghu_|ghs_|ghr_|github_pat_"
|
|
279
|
+
r"|xox[abprs]-|AKIA[0-9A-Z]{16}|AIza[0-9A-Za-z_-]{35})")
|
|
280
|
+
|
|
281
|
+
REDACTED = "<REDACTED>"
|
|
282
|
+
|
|
283
|
+
|
|
284
|
+
def _redact(name: str, value: str) -> str:
|
|
285
|
+
"""The value to print for ``name``, with credentials withheld.
|
|
286
|
+
|
|
287
|
+
Redacts rather than drops. A missing line reads as "unset", which sends
|
|
288
|
+
whoever is reading the crash report down the wrong path — the fact that a
|
|
289
|
+
key *was* configured is exactly what they need to know.
|
|
290
|
+
"""
|
|
291
|
+
if _SECRET_NAME.search(name) or _SECRET_VALUE.match(value):
|
|
292
|
+
return REDACTED
|
|
293
|
+
# Belt and braces for the shape a credential takes even when it carries no
|
|
294
|
+
# recognised prefix: one long opaque run with no separators. Excluding
|
|
295
|
+
# anything path-like keeps ordinary debug values (dirs, URLs) readable.
|
|
296
|
+
if (len(value) >= 40 and not set(value) & set(" \t/\\")
|
|
297
|
+
and re.fullmatch(r"[A-Za-z0-9_.+=-]+", value)):
|
|
298
|
+
return REDACTED
|
|
299
|
+
return value
|
|
300
|
+
|
|
301
|
+
|
|
265
302
|
def _env_snapshot() -> list[str]:
|
|
266
303
|
keys = sorted(k for k in os.environ
|
|
267
304
|
if k.startswith("BOOST_") or k in ("NO_COLOR", "CLICOLOR_FORCE"))
|
|
268
|
-
return ["%s=%s" % (k, os.environ[k]) for k in keys]
|
|
305
|
+
return ["%s=%s" % (k, _redact(k, os.environ[k])) for k in keys]
|
|
269
306
|
|
|
270
307
|
|
|
271
308
|
def write_crash_report(exc: BaseException, argv: list[str]) -> Path | None:
|
|
@@ -251,9 +251,29 @@ def _copy_skill(src: Path, dest: Path) -> None:
|
|
|
251
251
|
fast renames, and a failed swap rolls back to the original.
|
|
252
252
|
"""
|
|
253
253
|
dest = Path(dest)
|
|
254
|
-
dest
|
|
255
|
-
|
|
256
|
-
|
|
254
|
+
# Staging needs to *write* next to dest, and a store that cannot be written
|
|
255
|
+
# is an ordinary, fixable condition — a sandboxed shell, a synced folder, a
|
|
256
|
+
# store owned by another user. It used to escape as a raw PermissionError
|
|
257
|
+
# from tempfile.mkdtemp, so boost answered `boost install <skill>` with a
|
|
258
|
+
# stack trace ending in a temp path nobody recognises, and filed a crash
|
|
259
|
+
# report for it. Name the directory instead: that is the whole diagnosis.
|
|
260
|
+
try:
|
|
261
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
262
|
+
staged = Path(tempfile.mkdtemp(dir=str(dest.parent),
|
|
263
|
+
prefix="." + dest.name + ".tmp"))
|
|
264
|
+
except PermissionError as exc:
|
|
265
|
+
raise BoostError(
|
|
266
|
+
"cannot write to the skill store at %s" % dest.parent,
|
|
267
|
+
hint="check that you own the directory and it is writable "
|
|
268
|
+
"(`ls -ld %s`); a sandboxed shell is the usual cause"
|
|
269
|
+
% dest.parent) from exc
|
|
270
|
+
except OSError as exc:
|
|
271
|
+
# Not a permissions problem — disk full, read-only mount, name too
|
|
272
|
+
# long. Say which, rather than describing every one of them as denied.
|
|
273
|
+
raise BoostError(
|
|
274
|
+
"cannot stage a copy in %s: %s"
|
|
275
|
+
% (dest.parent, exc.strerror or exc),
|
|
276
|
+
hint="free space or fix the mount, then re-run") from exc
|
|
257
277
|
backup = None
|
|
258
278
|
try:
|
|
259
279
|
shutil.copytree(
|
|
@@ -1257,15 +1277,27 @@ def sync_plan() -> dict[str, list]:
|
|
|
1257
1277
|
|
|
1258
1278
|
Returns {missing_store, missing_links, stale_links, orphaned_store}
|
|
1259
1279
|
missing_store: lock entries whose store dir is gone
|
|
1260
|
-
missing_links: (skill, agent) pairs that should be linked but aren't
|
|
1280
|
+
missing_links: (skill, agent) pairs that should be linked but aren't,
|
|
1281
|
+
and that sync *can* create
|
|
1282
|
+
blocked_links: (skill, agent, path) where something that is not a boost
|
|
1283
|
+
symlink occupies the link path — sync will not clobber it
|
|
1261
1284
|
stale_links: paths in agent dirs that are broken/unmanaged symlinks
|
|
1262
1285
|
orphaned_store: store dirs not present in the lock file
|
|
1263
1286
|
out_of_scope_links: (skill, agent) pairs linked outside a declared
|
|
1264
1287
|
``--agent`` narrowing — reported, never auto-removed
|
|
1288
|
+
|
|
1289
|
+
``blocked_links`` exists because lumping it into ``missing_links`` made
|
|
1290
|
+
``boost sync`` promise a repair it could never perform. ``link_agents``
|
|
1291
|
+
refuses to delete a real file or directory it does not own (right), records
|
|
1292
|
+
it in ``.conflicts`` — and ``sync_apply`` dropped that on the floor, so the
|
|
1293
|
+
command printed "everything in sync" while ``boost doctor`` went on
|
|
1294
|
+
reporting the same skill unlinked and prescribing ``boost sync``. Seen for
|
|
1295
|
+
real where another installer had written ``~/.claude/skills/hyperframes``
|
|
1296
|
+
as a directory: a closed loop with no exit.
|
|
1265
1297
|
"""
|
|
1266
1298
|
lock = lockfile.installed()
|
|
1267
1299
|
plan: dict[str, list] = {"missing_store": [], "missing_links": [],
|
|
1268
|
-
"stale_links": [], "orphaned_store": [],
|
|
1300
|
+
"blocked_links": [], "stale_links": [], "orphaned_store": [],
|
|
1269
1301
|
"missing_materializations": [], "out_of_scope_links": []}
|
|
1270
1302
|
for name, entry in lock.items():
|
|
1271
1303
|
sdir = skill_store_dir(name)
|
|
@@ -1298,7 +1330,14 @@ def sync_plan() -> dict[str, list]:
|
|
|
1298
1330
|
in_scope = scoped_agents(entry, linking)
|
|
1299
1331
|
for agent, adir in in_scope.items():
|
|
1300
1332
|
link = adir / name
|
|
1301
|
-
|
|
1333
|
+
# A symlink is boost's to replace even when it dangles; anything
|
|
1334
|
+
# else that exists is someone else's file and stays put.
|
|
1335
|
+
if link.is_symlink():
|
|
1336
|
+
if not link.exists():
|
|
1337
|
+
plan["missing_links"].append((name, agent))
|
|
1338
|
+
elif link.exists():
|
|
1339
|
+
plan["blocked_links"].append((name, agent, str(link)))
|
|
1340
|
+
else:
|
|
1302
1341
|
plan["missing_links"].append((name, agent))
|
|
1303
1342
|
# The other direction, which nothing checked: a link that exists in an
|
|
1304
1343
|
# agent the declaration excludes. The loop above is narrowed to the
|
|
@@ -219,6 +219,7 @@ docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md
|
|
|
219
219
|
docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md
|
|
220
220
|
docs/roadmap/items/crash-listing-branch-untested.md
|
|
221
221
|
docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md
|
|
222
|
+
docs/roadmap/items/crash-reports-leak-api-keys.md
|
|
222
223
|
docs/roadmap/items/demo-cannot-open-its-own-pr.md
|
|
223
224
|
docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md
|
|
224
225
|
docs/roadmap/items/demo-workflow-cancels-other-prs.md
|
|
@@ -401,9 +402,11 @@ docs/roadmap/items/surface-every-docs-page-from-the-guide.md
|
|
|
401
402
|
docs/roadmap/items/sync-could-not-repair-a-gutted-skill.md
|
|
402
403
|
docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md
|
|
403
404
|
docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md
|
|
405
|
+
docs/roadmap/items/sync-reported-success-for-a-link-it-refused.md
|
|
404
406
|
docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md
|
|
405
407
|
docs/roadmap/items/theme-asset-linting-stylelint-eslint.md
|
|
406
408
|
docs/roadmap/items/tool-call-eval-tier.md
|
|
409
|
+
docs/roadmap/items/two-crashes-that-should-have-been-messages.md
|
|
407
410
|
docs/roadmap/items/typo-detection-codespell.md
|
|
408
411
|
docs/roadmap/items/typosquat-and-name-confusion-detection.md
|
|
409
412
|
docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md
|
|
@@ -584,6 +587,7 @@ tests/unit/test_community_health_files.py
|
|
|
584
587
|
tests/unit/test_complete.py
|
|
585
588
|
tests/unit/test_config.py
|
|
586
589
|
tests/unit/test_content_dedupe.py
|
|
590
|
+
tests/unit/test_crash_redaction.py
|
|
587
591
|
tests/unit/test_dedup_trust.py
|
|
588
592
|
tests/unit/test_demo_index.py
|
|
589
593
|
tests/unit/test_dense.py
|
|
@@ -599,6 +603,7 @@ tests/unit/test_docsite_chrome.py
|
|
|
599
603
|
tests/unit/test_ed25519.py
|
|
600
604
|
tests/unit/test_embed.py
|
|
601
605
|
tests/unit/test_embed_local.py
|
|
606
|
+
tests/unit/test_embed_truncated_response.py
|
|
602
607
|
tests/unit/test_entry_key.py
|
|
603
608
|
tests/unit/test_errors_and_cli_table.py
|
|
604
609
|
tests/unit/test_eval_baseline.py
|
|
@@ -619,6 +624,7 @@ tests/unit/test_gitutil_lfs.py
|
|
|
619
624
|
tests/unit/test_imperative.py
|
|
620
625
|
tests/unit/test_import_budget.py
|
|
621
626
|
tests/unit/test_injectscan.py
|
|
627
|
+
tests/unit/test_install_permission_error.py
|
|
622
628
|
tests/unit/test_installscan.py
|
|
623
629
|
tests/unit/test_integrity.py
|
|
624
630
|
tests/unit/test_journal.py
|
|
@@ -678,6 +684,7 @@ tests/unit/test_spin.py
|
|
|
678
684
|
tests/unit/test_stackprobe.py
|
|
679
685
|
tests/unit/test_staleness.py
|
|
680
686
|
tests/unit/test_store.py
|
|
687
|
+
tests/unit/test_sync_blocked_links.py
|
|
681
688
|
tests/unit/test_sync_repairs_gutted_skill.py
|
|
682
689
|
tests/unit/test_token_parity.py
|
|
683
690
|
tests/unit/test_toolchain_lock.py
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: crash-reports-leak-api-keys
|
|
3
|
+
board: code
|
|
4
|
+
section: trust
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Bug
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: High
|
|
9
|
+
wow: 5
|
|
10
|
+
note:
|
|
11
|
+
order: 3
|
|
12
|
+
owner: fix/audit-findings
|
|
13
|
+
pr:
|
|
14
|
+
title: Crash reports carried API keys in cleartext
|
|
15
|
+
---
|
|
16
|
+
A crash report is the one file boost actively invites a user to paste into a bug report — its
|
|
17
|
+
docstring says so: "a user can attach one file to a bug report instead of reproducing by hand."
|
|
18
|
+
<code>_env_snapshot()</code> built that file by printing every <code>BOOST_*</code> variable
|
|
19
|
+
verbatim. Since boost documents <code>BOOST_ANTHROPIC_API_KEY</code> as the way to supply a key,
|
|
20
|
+
the variable most likely to be <em>set</em> was also the one most likely to be secret.
|
|
21
|
+
|
|
22
|
+
Found on a real machine, not in review: three reports under <code>~/.boost/logs/</code>, each
|
|
23
|
+
carrying a live <code>sk-ant-api03-…</code> key, written by two ordinary
|
|
24
|
+
<code>boost install</code> failures and one <code>boost search</code>. Nothing had to go wrong
|
|
25
|
+
beyond the crash itself — the leak was the reporting path working as designed.
|
|
26
|
+
|
|
27
|
+
Values are now withheld two ways, because either alone rots. A name ending in
|
|
28
|
+
<code>KEY</code>/<code>TOKEN</code>/<code>SECRET</code>/<code>PASSWORD</code>/<code>AUTH</code> is
|
|
29
|
+
redacted, which covers every provider without enumerating them; and a value carrying a known
|
|
30
|
+
credential prefix (<code>sk-</code>, <code>ghp_</code>, <code>xox…</code>, <code>AKIA…</code>) is
|
|
31
|
+
redacted whatever it is called, because a name denylist always trails the next provider someone
|
|
32
|
+
adds. Redacted, never dropped: a missing line reads as "unset", and the fact that a key
|
|
33
|
+
<em>was</em> configured is exactly what the reader needs.
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: sync-reported-success-for-a-link-it-refused
|
|
3
|
+
board: code
|
|
4
|
+
section: compat
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Bug
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: High
|
|
9
|
+
wow: 4
|
|
10
|
+
note:
|
|
11
|
+
order: 12
|
|
12
|
+
owner: fix/audit-findings
|
|
13
|
+
pr:
|
|
14
|
+
title: <code>sync</code> reported success for a link it had just refused
|
|
15
|
+
---
|
|
16
|
+
Observed on a real machine as a closed loop with no exit: <code>boost sync</code> answers
|
|
17
|
+
"✓ everything in sync" · <code>boost doctor</code> answers "! skill hyperframes not linked
|
|
18
|
+
for claude-code — run <code>boost sync</code>" · repeat forever.
|
|
19
|
+
|
|
20
|
+
Another installer had written <code>~/.claude/skills/hyperframes</code> as a real directory.
|
|
21
|
+
<code>link_agents</code> correctly refuses to delete a path boost does not own and records it in
|
|
22
|
+
<code>.conflicts</code> — but <code>sync_apply</code> dropped that value on the floor, appended no
|
|
23
|
+
action, and the command layer read "no actions" as "nothing to do". Doctor, meanwhile, tested only
|
|
24
|
+
<code>is_symlink()</code> and prescribed the command that had just declined to help.
|
|
25
|
+
|
|
26
|
+
<code>sync_plan</code> now separates the two cases it had been conflating: a
|
|
27
|
+
<code>missing_link</code> is one sync can create (nothing in the way, or a dangling symlink boost
|
|
28
|
+
owns and may replace), and a <code>blocked_link</code> is a path occupied by a file boost will not
|
|
29
|
+
touch. <code>sync</code> warns and names the path; <code>doctor</code> says why sync did nothing
|
|
30
|
+
and gives the step that unblocks it. store.py's own comment already named this anti-pattern — "sync
|
|
31
|
+
would answer 'everything in sync', change nothing, and send the reader back to the same error" —
|
|
32
|
+
one function above the code that was doing it.
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
---
|
|
2
|
+
id: two-crashes-that-should-have-been-messages
|
|
3
|
+
board: code
|
|
4
|
+
section: compat
|
|
5
|
+
status: shipped
|
|
6
|
+
category: Bug
|
|
7
|
+
complexity: S
|
|
8
|
+
impact: Medium
|
|
9
|
+
wow: 3
|
|
10
|
+
note:
|
|
11
|
+
order: 13
|
|
12
|
+
owner: fix/audit-findings
|
|
13
|
+
pr:
|
|
14
|
+
title: Two crashes that should have been messages
|
|
15
|
+
---
|
|
16
|
+
Both were found by reading the crash reports on a real machine rather than by review, and both are
|
|
17
|
+
the same shape: an expected, fixable condition escaping as a traceback.
|
|
18
|
+
|
|
19
|
+
<strong>An unwritable store.</strong> <code>store._copy_skill</code> stages its copy with
|
|
20
|
+
<code>tempfile.mkdtemp</code> next to the destination. Where <code>~/.agents/skills</code> could not
|
|
21
|
+
be written — a sandboxed shell is the usual cause — the raw <code>PermissionError</code> escaped, so
|
|
22
|
+
<code>boost install <skill></code> answered with a stack trace ending in a temp path nobody
|
|
23
|
+
recognises, and filed a crash report for a permissions problem. It now names the directory, which
|
|
24
|
+
is the whole diagnosis. A non-permissions <code>OSError</code> (disk full, read-only mount) is
|
|
25
|
+
reported as itself rather than described as denied.
|
|
26
|
+
|
|
27
|
+
<strong>A truncated embedding response.</strong> <code>embed._post</code> guarded with
|
|
28
|
+
<code>except (URLError, OSError, ValueError)</code>. <code>http.client.IncompleteRead</code> — what
|
|
29
|
+
a connection cut mid-body raises — subclasses <code>HTTPException</code> and <em>none</em> of those
|
|
30
|
+
three, so it went straight through <code>resp.read()</code> and out of <code>boost search</code>.
|
|
31
|
+
Seen as <code>IncompleteRead(6629 bytes read, 6200 more expected)</code> on
|
|
32
|
+
<code>boost search mempalace</code>. The right answer to a network hiccup is to return None and let
|
|
33
|
+
retrieval fall back to BM25, which is what it now does. <code>RemoteDisconnected</code> had been
|
|
34
|
+
covered only by accident — it also subclasses <code>ConnectionResetError</code>.
|
|
@@ -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>249</b><span>Loop finds</span></div>
|
|
137
137
|
<!-- /ROADMAP:stats -->
|
|
138
138
|
</div>
|
|
139
139
|
</section>
|
|
@@ -9218,6 +9218,64 @@ reaches the network as a side effect of checking what a command prints.</p></det
|
|
|
9218
9218
|
</div>
|
|
9219
9219
|
</article>
|
|
9220
9220
|
|
|
9221
|
+
<article class="cap rcard" id="sync-reported-success-for-a-link-it-refused">
|
|
9222
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug</span></div>
|
|
9223
|
+
<h3><code>sync</code> reported success for a link it had just refused</h3>
|
|
9224
|
+
<details class="cardbody"><summary>Write-up</summary>
|
|
9225
|
+
<p>Observed on a real machine as a closed loop with no exit: <code>boost sync</code> answers
|
|
9226
|
+
"✓ everything in sync" · <code>boost doctor</code> answers "! skill hyperframes not linked
|
|
9227
|
+
for claude-code — run <code>boost sync</code>" · repeat forever.
|
|
9228
|
+
|
|
9229
|
+
Another installer had written <code>~/.claude/skills/hyperframes</code> as a real directory.
|
|
9230
|
+
<code>link_agents</code> correctly refuses to delete a path boost does not own and records it in
|
|
9231
|
+
<code>.conflicts</code> — but <code>sync_apply</code> dropped that value on the floor, appended no
|
|
9232
|
+
action, and the command layer read "no actions" as "nothing to do". Doctor, meanwhile, tested only
|
|
9233
|
+
<code>is_symlink()</code> and prescribed the command that had just declined to help.
|
|
9234
|
+
|
|
9235
|
+
<code>sync_plan</code> now separates the two cases it had been conflating: a
|
|
9236
|
+
<code>missing_link</code> is one sync can create (nothing in the way, or a dangling symlink boost
|
|
9237
|
+
owns and may replace), and a <code>blocked_link</code> is a path occupied by a file boost will not
|
|
9238
|
+
touch. <code>sync</code> warns and names the path; <code>doctor</code> says why sync did nothing
|
|
9239
|
+
and gives the step that unblocks it. store.py's own comment already named this anti-pattern — "sync
|
|
9240
|
+
would answer 'everything in sync', change nothing, and send the reader back to the same error" —
|
|
9241
|
+
one function above the code that was doing it.</p></details>
|
|
9242
|
+
<div class="meta">
|
|
9243
|
+
<span class="m">Complexity <b>S</b></span>
|
|
9244
|
+
<span class="m hi">Impact <b>High</b></span>
|
|
9245
|
+
<span class="m">Wow <b class="wow">★★★★</b></span>
|
|
9246
|
+
</div>
|
|
9247
|
+
</article>
|
|
9248
|
+
|
|
9249
|
+
<article class="cap rcard" id="two-crashes-that-should-have-been-messages">
|
|
9250
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug</span></div>
|
|
9251
|
+
<h3>Two crashes that should have been messages</h3>
|
|
9252
|
+
<details class="cardbody"><summary>Write-up</summary>
|
|
9253
|
+
<p>Both were found by reading the crash reports on a real machine rather than by review, and both are
|
|
9254
|
+
the same shape: an expected, fixable condition escaping as a traceback.
|
|
9255
|
+
|
|
9256
|
+
<strong>An unwritable store.</strong> <code>store._copy_skill</code> stages its copy with
|
|
9257
|
+
<code>tempfile.mkdtemp</code> next to the destination. Where <code>~/.agents/skills</code> could not
|
|
9258
|
+
be written — a sandboxed shell is the usual cause — the raw <code>PermissionError</code> escaped, so
|
|
9259
|
+
<code>boost install <skill></code> answered with a stack trace ending in a temp path nobody
|
|
9260
|
+
recognises, and filed a crash report for a permissions problem. It now names the directory, which
|
|
9261
|
+
is the whole diagnosis. A non-permissions <code>OSError</code> (disk full, read-only mount) is
|
|
9262
|
+
reported as itself rather than described as denied.
|
|
9263
|
+
|
|
9264
|
+
<strong>A truncated embedding response.</strong> <code>embed._post</code> guarded with
|
|
9265
|
+
<code>except (URLError, OSError, ValueError)</code>. <code>http.client.IncompleteRead</code> — what
|
|
9266
|
+
a connection cut mid-body raises — subclasses <code>HTTPException</code> and <em>none</em> of those
|
|
9267
|
+
three, so it went straight through <code>resp.read()</code> and out of <code>boost search</code>.
|
|
9268
|
+
Seen as <code>IncompleteRead(6629 bytes read, 6200 more expected)</code> on
|
|
9269
|
+
<code>boost search mempalace</code>. The right answer to a network hiccup is to return None and let
|
|
9270
|
+
retrieval fall back to BM25, which is what it now does. <code>RemoteDisconnected</code> had been
|
|
9271
|
+
covered only by accident — it also subclasses <code>ConnectionResetError</code>.</p></details>
|
|
9272
|
+
<div class="meta">
|
|
9273
|
+
<span class="m">Complexity <b>S</b></span>
|
|
9274
|
+
<span class="m">Impact <b>Medium</b></span>
|
|
9275
|
+
<span class="m">Wow <b class="wow">★★★</b></span>
|
|
9276
|
+
</div>
|
|
9277
|
+
</article>
|
|
9278
|
+
|
|
9221
9279
|
<article class="cap rcard" id="mcp-register-names-server-before-env">
|
|
9222
9280
|
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug · MCP</span></div>
|
|
9223
9281
|
<h3>Order the server name before -e flags in `boost mcp register`</h3>
|
|
@@ -9656,6 +9714,35 @@ the command layer never was.</p></details>
|
|
|
9656
9714
|
</div>
|
|
9657
9715
|
</article>
|
|
9658
9716
|
|
|
9717
|
+
<article class="cap rcard" id="crash-reports-leak-api-keys">
|
|
9718
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug</span></div>
|
|
9719
|
+
<h3>Crash reports carried API keys in cleartext</h3>
|
|
9720
|
+
<details class="cardbody"><summary>Write-up</summary>
|
|
9721
|
+
<p>A crash report is the one file boost actively invites a user to paste into a bug report — its
|
|
9722
|
+
docstring says so: "a user can attach one file to a bug report instead of reproducing by hand."
|
|
9723
|
+
<code>_env_snapshot()</code> built that file by printing every <code>BOOST_*</code> variable
|
|
9724
|
+
verbatim. Since boost documents <code>BOOST_ANTHROPIC_API_KEY</code> as the way to supply a key,
|
|
9725
|
+
the variable most likely to be <em>set</em> was also the one most likely to be secret.
|
|
9726
|
+
|
|
9727
|
+
Found on a real machine, not in review: three reports under <code>~/.boost/logs/</code>, each
|
|
9728
|
+
carrying a live <code>sk-ant-api03-…</code> key, written by two ordinary
|
|
9729
|
+
<code>boost install</code> failures and one <code>boost search</code>. Nothing had to go wrong
|
|
9730
|
+
beyond the crash itself — the leak was the reporting path working as designed.
|
|
9731
|
+
|
|
9732
|
+
Values are now withheld two ways, because either alone rots. A name ending in
|
|
9733
|
+
<code>KEY</code>/<code>TOKEN</code>/<code>SECRET</code>/<code>PASSWORD</code>/<code>AUTH</code> is
|
|
9734
|
+
redacted, which covers every provider without enumerating them; and a value carrying a known
|
|
9735
|
+
credential prefix (<code>sk-</code>, <code>ghp_</code>, <code>xox…</code>, <code>AKIA…</code>) is
|
|
9736
|
+
redacted whatever it is called, because a name denylist always trails the next provider someone
|
|
9737
|
+
adds. Redacted, never dropped: a missing line reads as "unset", and the fact that a key
|
|
9738
|
+
<em>was</em> configured is exactly what the reader needs.</p></details>
|
|
9739
|
+
<div class="meta">
|
|
9740
|
+
<span class="m">Complexity <b>S</b></span>
|
|
9741
|
+
<span class="m hi">Impact <b>High</b></span>
|
|
9742
|
+
<span class="m">Wow <b class="wow">★★★★★</b></span>
|
|
9743
|
+
</div>
|
|
9744
|
+
</article>
|
|
9745
|
+
|
|
9659
9746
|
<article class="cap rcard" id="tap-signing-and-provenance-sigstore-minisign">
|
|
9660
9747
|
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Security · Provenance</span></div>
|
|
9661
9748
|
<h3>Tap signing & provenance — Sigstore / minisign</h3>
|
|
@@ -1184,12 +1184,13 @@ class TestSyncJson:
|
|
|
1184
1184
|
assert "everything in sync" in r.out
|
|
1185
1185
|
plan = json.loads(boost("sync", "--diff", "--json").out)
|
|
1186
1186
|
assert plan == {"missing_store": [], "missing_links": [],
|
|
1187
|
-
"
|
|
1187
|
+
"blocked_links": [], "stale_links": [],
|
|
1188
|
+
"orphaned_store": [],
|
|
1188
1189
|
"missing_materializations": [], "out_of_scope_links": [],
|
|
1189
1190
|
"project": {"missing": [], "orphaned": []}}
|
|
1190
1191
|
data = json.loads(boost("sync", "--json").out)
|
|
1191
1192
|
assert data == {"actions": [], "pruned": [], "orphaned_store": [],
|
|
1192
|
-
"out_of_scope_links": []}
|
|
1193
|
+
"out_of_scope_links": [], "blocked_links": []}
|
|
1193
1194
|
|
|
1194
1195
|
def test_a_narrowing_reinstall_is_reported_and_pruned_only_on_request(
|
|
1195
1196
|
self, boost, installed):
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
"""A crash report is the one file users are invited to paste into a bug report.
|
|
2
|
+
|
|
3
|
+
`_env_snapshot` captured every ``BOOST_*`` variable verbatim, and boost's own
|
|
4
|
+
documented way to supply a key is ``BOOST_ANTHROPIC_API_KEY`` — so the variable
|
|
5
|
+
most likely to be set was also the one most likely to be secret. Three reports
|
|
6
|
+
on a real machine carried a live ``sk-ant-api03-...`` key in cleartext.
|
|
7
|
+
"""
|
|
8
|
+
from __future__ import annotations
|
|
9
|
+
|
|
10
|
+
import pytest
|
|
11
|
+
|
|
12
|
+
from boost_cli.core import logs
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class TestEnvSnapshotRedaction:
|
|
16
|
+
SECRET = "sk-ant-api03-" + "x" * 80
|
|
17
|
+
|
|
18
|
+
@pytest.mark.parametrize("var", [
|
|
19
|
+
"BOOST_ANTHROPIC_API_KEY",
|
|
20
|
+
"BOOST_OPENAI_API_KEY",
|
|
21
|
+
"BOOST_VOYAGE_API_KEY",
|
|
22
|
+
"BOOST_GITHUB_TOKEN",
|
|
23
|
+
"BOOST_REGISTRY_SECRET",
|
|
24
|
+
"BOOST_TAP_PASSWORD",
|
|
25
|
+
])
|
|
26
|
+
def test_secret_value_never_appears(self, var, monkeypatch):
|
|
27
|
+
monkeypatch.setenv(var, self.SECRET)
|
|
28
|
+
body = "\n".join(logs._env_snapshot())
|
|
29
|
+
assert self.SECRET not in body
|
|
30
|
+
assert var in body, "the variable is still worth reporting — only its value is not"
|
|
31
|
+
|
|
32
|
+
def test_redaction_is_marked_not_silently_dropped(self, monkeypatch):
|
|
33
|
+
monkeypatch.setenv("BOOST_ANTHROPIC_API_KEY", self.SECRET)
|
|
34
|
+
line = next(x for x in logs._env_snapshot() if x.startswith("BOOST_ANTHROPIC_API_KEY"))
|
|
35
|
+
# A dropped line reads as "unset", which sends a bug reporter down the
|
|
36
|
+
# wrong path. Say the value was withheld.
|
|
37
|
+
assert "REDACTED" in line
|
|
38
|
+
|
|
39
|
+
def test_non_secret_values_survive(self, monkeypatch):
|
|
40
|
+
monkeypatch.setenv("BOOST_ASSUME_YES", "1")
|
|
41
|
+
monkeypatch.setenv("BOOST_NO_AI", "1")
|
|
42
|
+
body = "\n".join(logs._env_snapshot())
|
|
43
|
+
assert "BOOST_ASSUME_YES=1" in body
|
|
44
|
+
assert "BOOST_NO_AI=1" in body
|
|
45
|
+
|
|
46
|
+
def test_crash_report_on_disk_carries_no_secret(self, monkeypatch, sandbox):
|
|
47
|
+
monkeypatch.setenv("BOOST_ANTHROPIC_API_KEY", self.SECRET)
|
|
48
|
+
report = logs.write_crash_report(RuntimeError("boom"), ["install", "x"])
|
|
49
|
+
assert report is not None
|
|
50
|
+
assert self.SECRET not in report.read_text(encoding="utf-8")
|
|
51
|
+
|
|
52
|
+
def test_a_secret_by_value_shape_is_caught_whatever_its_name(self, monkeypatch):
|
|
53
|
+
# Name-matching alone is a denylist and will always trail the next
|
|
54
|
+
# variable someone adds. A value that is unmistakably a key is redacted
|
|
55
|
+
# on its shape too.
|
|
56
|
+
monkeypatch.setenv("BOOST_SOMETHING_HARMLESS_SOUNDING", self.SECRET)
|
|
57
|
+
body = "\n".join(logs._env_snapshot())
|
|
58
|
+
assert self.SECRET not in body
|