boost-skill-cli 1.0.308__tar.gz → 1.0.309__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.308 → boost_skill_cli-1.0.309}/PKG-INFO +3 -1
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/quality.py +6 -1
- boost_skill_cli-1.0.309/boost_cli/core/embed.py +270 -0
- boost_skill_cli-1.0.309/boost_cli/core/localembed.py +245 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_skill_cli.egg-info/PKG-INFO +3 -1
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_skill_cli.egg-info/SOURCES.txt +4 -1
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_skill_cli.egg-info/requires.txt +2 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +9 -0
- boost_skill_cli-1.0.308/docs/roadmap/items/keyless-item.md → boost_skill_cli-1.0.309/docs/roadmap/items/keyless-semantic-search-for-everyone.md +52 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap.html +61 -2
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/pyproject.toml +23 -1
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_embed.py +7 -2
- boost_skill_cli-1.0.309/tests/unit/test_embed_local.py +264 -0
- boost_skill_cli-1.0.309/tests/unit/test_localembed.py +491 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_roadmap_fresh.py +21 -0
- boost_skill_cli-1.0.308/boost_cli/core/embed.py +0 -135
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.gitattributes +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.gitignore +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.gitleaks.toml +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.htmlvalidate.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.lighthouserc.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.lycheeignore +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.markdownlint-cli2.jsonc +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.pre-commit-config.yaml +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.stylelintrc.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.vale/styles/boost/Terminology.yml +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/.vale.ini +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/CODE_OF_CONDUCT.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/LICENSE +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/Makefile +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/README.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/_common.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/run.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/safety.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/capabilities.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/ed25519.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/faithfulness.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/installscan.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/integrity.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/mcpdecl.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/mcphost.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/minisign.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/projectlock.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/provenance.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/resolve.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/scopes.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/selfupdate.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/trustaudit.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/codecov.yml +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/architecture/README.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/architecture/c4-components-core.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/architecture/c4-containers.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/architecture/c4-context.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/architecture/c4-dynamic-install.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/gifs/distill.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/gifs/doctor.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/gifs/explain.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/gifs/hooks.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/gifs/install.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/gifs/pulse.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/gifs/search.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/gifs/tap.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/tapes/distill.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/tapes/doctor.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/tapes/explain.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/tapes/hooks.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/tapes/install.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/tapes/pulse.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/tapes/search.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel/tapes/tap.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/carousel.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/commands.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/index.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/command-carousel-page.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/github-community-health-files.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/license-compliance-scanning.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-aware-skills.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/required-checks-config-drift.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/eslint.config.mjs +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/README.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/__init__.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/baseline.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/faithfulness.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/golden_set.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/make_corpus.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/make_golden.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/metrics.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/evals/run_evals.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/examples/README.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/index.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/noxfile.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/coverage-tools.in +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/coverage-tools.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/lint-tools.in +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/lint-tools.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/mutation-tools.in +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/mutation-tools.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/platform-pins.lock +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/release-tools.in +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/release-tools.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/test-tools.in +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/requirements/test-tools.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/a11y_check.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/build_command_reference.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/check_anchors.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/check_licenses.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/check_required_checks.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/eval_gate.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/import_budget.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/lock_toolchain.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/mutation_shards.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/mutation_weights.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/perf_gate.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/release_guard.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/scripts/release_preflight.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/setup.cfg +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/sonar-project.properties +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/style/README.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/style/boost.css +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/style/boost.js +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/style/demo.html +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_capabilities_policy.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_integrity_enforce.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_run.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_tap_signing.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/functional/test_workspace_scope.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/README.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/registry/02-https.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/registry/06-space.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/fuzz_frontmatter.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/fuzz/fuzz_registry.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_a11y_check.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_adapters_multi.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_adapters_runner.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_capabilities.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_check_anchors.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_check_licenses.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_codeql_analysis_key.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_command_reference_fresh.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_community_health_files.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_dense_status.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_dependabot_config.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_docsite_chrome.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_ed25519.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_eval_faithfulness.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_eval_gate.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_eval_metrics.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_eval_stats_summary.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_faithfulness.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_fuzz_targets.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_gitleaks_config.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_import_budget.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_installscan.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_integrity.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_marketing_counts.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_mcp_install_scan.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_mcpdecl.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_mcphost.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_minisign.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_mutation_shards.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_mutation_subfile_shards.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_mutmut_source_paths.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_perf_gate.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_platform_pins.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_post_deploy_smoke.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_project_mcp_sidecar.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_projectlock.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_provenance.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_registry_categories.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_release_guard.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_release_preflight.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_required_checks.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_resolve.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_scopes.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_selfupdate.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_toolchain_lock.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_trustaudit.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_workflow_concurrency.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_workflow_timeouts.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/unit/test_workflows.py +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/visual/a11y_check.mjs +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/visual/console_check.mjs +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/visual/package-lock.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/visual/package.json +0 -0
- {boost_skill_cli-1.0.308 → boost_skill_cli-1.0.309}/tests/visual/visual_check.mjs +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boost-skill-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.309
|
|
4
4
|
Summary: boost — Homebrew for AI coding skills
|
|
5
5
|
Author: Jonathan Reyes
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -702,6 +702,8 @@ Description-Content-Type: text/markdown
|
|
|
702
702
|
License-File: LICENSE
|
|
703
703
|
Provides-Extra: rag
|
|
704
704
|
Requires-Dist: sqlite-vec>=0.1.6; extra == "rag"
|
|
705
|
+
Requires-Dist: onnxruntime>=1.17; extra == "rag"
|
|
706
|
+
Requires-Dist: tokenizers>=0.15; extra == "rag"
|
|
705
707
|
Provides-Extra: eval
|
|
706
708
|
Requires-Dist: ranx>=0.3.20; extra == "eval"
|
|
707
709
|
Requires-Dist: ragas<0.3,>=0.2; extra == "eval"
|
|
@@ -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.309'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 309)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -412,7 +412,12 @@ def cmd_doctor(argv):
|
|
|
412
412
|
# first missing link is ever reported, so these never chain.
|
|
413
413
|
_DENSE_FIX = {
|
|
414
414
|
"no-backend": "install the extra: `pip install 'boost-skill-cli[rag]'`",
|
|
415
|
-
|
|
415
|
+
# Names the keyless remedy first: since the [rag] extra carries a local
|
|
416
|
+
# embedding model, an API key is the quality ceiling, not the entry fee.
|
|
417
|
+
# This reason now means "no key AND no local backend", which in practice is
|
|
418
|
+
# a partial install or BOOST_NO_EMBED.
|
|
419
|
+
"no-key": ("reinstall the extra: `pip install 'boost-skill-cli[rag]'` "
|
|
420
|
+
"(or set VOYAGE_API_KEY / OPENAI_API_KEY for a larger model)"),
|
|
416
421
|
"no-store": "build it: `boost reindex --dense`",
|
|
417
422
|
"version-changed": "rebuild it: `boost reindex --dense --force`",
|
|
418
423
|
"provider-changed": "rebuild it: `boost reindex --dense --force`",
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
"""Optional dense-embedding bridge for RAG Phase 2.
|
|
2
|
+
|
|
3
|
+
Strategy mirrors ``core.ai``: prefer Voyage AI when ``VOYAGE_API_KEY`` is set,
|
|
4
|
+
else OpenAI when ``OPENAI_API_KEY`` is set, else a **local** ONNX model when the
|
|
5
|
+
``[rag]`` extra is installed, else return ``None`` so every caller degrades to
|
|
6
|
+
the always-on BM25 engine. The API embeddings come over ``urllib`` — pure
|
|
7
|
+
stdlib, no client library. Anthropic exposes no embeddings endpoint, hence
|
|
8
|
+
Voyage (its recommended partner) and OpenAI.
|
|
9
|
+
|
|
10
|
+
Why a local provider exists
|
|
11
|
+
---------------------------
|
|
12
|
+
Without one, dense search needed an account and a key, so in practice every
|
|
13
|
+
keyless user got BM25 — and BM25 answers "my app is slow" with bioinformatics
|
|
14
|
+
packages, because nothing in that query shares vocabulary with the docs. The
|
|
15
|
+
vector *store* was never the gated part: vectors already live on the user's own
|
|
16
|
+
machine in sqlite-vec, keyed on each tap's commit. The only API-bound step is
|
|
17
|
+
turning text into vectors.
|
|
18
|
+
|
|
19
|
+
That also rules out the obvious shortcut of shipping a prebuilt index instead:
|
|
20
|
+
answering a query means embedding *the query*, so a downloaded index is useless
|
|
21
|
+
without something local to embed with. A local model is the prerequisite, not
|
|
22
|
+
an alternative.
|
|
23
|
+
|
|
24
|
+
The chain order is load-bearing. Local is tried **last**, so a user who has
|
|
25
|
+
configured Voyage keeps voyage-4 rather than being silently downgraded to a
|
|
26
|
+
384-dim local model. And because ``dense.py`` rebuilds whenever ``model`` or
|
|
27
|
+
``dim`` changes, switching providers can never mix two embedding spaces in one
|
|
28
|
+
index.
|
|
29
|
+
|
|
30
|
+
``BOOST_NO_EMBED=1`` is a hard kill-switch for all three, matching
|
|
31
|
+
``BOOST_NO_AI``.
|
|
32
|
+
"""
|
|
33
|
+
from __future__ import annotations
|
|
34
|
+
|
|
35
|
+
import contextlib
|
|
36
|
+
import json
|
|
37
|
+
import os
|
|
38
|
+
import urllib.error
|
|
39
|
+
import urllib.request
|
|
40
|
+
from typing import Any, List, Optional
|
|
41
|
+
|
|
42
|
+
from . import nethttp
|
|
43
|
+
|
|
44
|
+
VOYAGE_URL = "https://api.voyageai.com/v1/embeddings"
|
|
45
|
+
OPENAI_URL = "https://api.openai.com/v1/embeddings"
|
|
46
|
+
|
|
47
|
+
# model -> output dimension. Stored in the vector index so a provider/model
|
|
48
|
+
# switch is detected and forces a clean rebuild instead of mixing spaces.
|
|
49
|
+
# voyage-4 over voyage-3: same 1024-d default and same $/token, but the
|
|
50
|
+
# voyage-4 generation carries a 200M-token complimentary allowance where
|
|
51
|
+
# voyage-3 has none — so a full index build of a large corpus is free.
|
|
52
|
+
VOYAGE_MODEL = "voyage-4"
|
|
53
|
+
OPENAI_MODEL = "text-embedding-3-small"
|
|
54
|
+
|
|
55
|
+
# The keyless path. Small on purpose: skill docs are short and keyword-dense, so
|
|
56
|
+
# a 384-dim model closes most of the gap to a paid API and runs on CPU. Named
|
|
57
|
+
# with its full hub id because that is what ends up recorded in the index
|
|
58
|
+
# metadata — a bare "bge-small-en-v1.5" would collide with any other vendor's
|
|
59
|
+
# rebuild of it, and a rebuild produces different vectors. See core.localembed
|
|
60
|
+
# for the pinned revision and the (133 MB, not 30 MB) download it implies.
|
|
61
|
+
LOCAL_MODEL = "BAAI/bge-small-en-v1.5"
|
|
62
|
+
LOCAL_DIM = 384
|
|
63
|
+
|
|
64
|
+
_DIMS = {VOYAGE_MODEL: 1024, OPENAI_MODEL: 1536, LOCAL_MODEL: LOCAL_DIM}
|
|
65
|
+
|
|
66
|
+
# Cached backend class and model instance. Loading an ONNX model is expensive
|
|
67
|
+
# enough that doing it per query would make the local path unusable, and the
|
|
68
|
+
# import itself is retried-on-miss rather than repeated: `provider()` runs on
|
|
69
|
+
# effectively every retrieval call.
|
|
70
|
+
_BACKEND_MISSING = object()
|
|
71
|
+
# Deliberately untyped: the backend is core.localembed, imported lazily, so
|
|
72
|
+
# naming its type here would defeat the point of the lazy import.
|
|
73
|
+
_backend_cache: Any = None
|
|
74
|
+
_model_instance: Any = None
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def enabled() -> bool:
|
|
78
|
+
"""True unless the ``BOOST_NO_EMBED`` kill-switch is set."""
|
|
79
|
+
return not os.environ.get("BOOST_NO_EMBED")
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
def _load_backend():
|
|
83
|
+
"""The local embedding class, or None when the ``[rag]`` extra is absent.
|
|
84
|
+
|
|
85
|
+
``localembed`` keeps its own imports lazy for the import budget; this is the
|
|
86
|
+
seam the tests stub, so the unit suite passes with the extra uninstalled.
|
|
87
|
+
"""
|
|
88
|
+
from . import localembed
|
|
89
|
+
return localembed if localembed.available() else None
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
def _backend() -> Any:
|
|
93
|
+
"""``_load_backend`` memoised, including the negative result."""
|
|
94
|
+
global _backend_cache
|
|
95
|
+
if _backend_cache is None:
|
|
96
|
+
_backend_cache = _load_backend() or _BACKEND_MISSING
|
|
97
|
+
return None if _backend_cache is _BACKEND_MISSING else _backend_cache
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+
def reset_local_cache() -> None:
|
|
101
|
+
"""Drop the cached backend and model. For tests, and for a provider switch."""
|
|
102
|
+
global _backend_cache, _model_instance
|
|
103
|
+
_backend_cache = None
|
|
104
|
+
_model_instance = None
|
|
105
|
+
# Nothing to reset when the extra is absent.
|
|
106
|
+
with contextlib.suppress(Exception):
|
|
107
|
+
from . import localembed
|
|
108
|
+
localembed.reset()
|
|
109
|
+
|
|
110
|
+
|
|
111
|
+
def local_available() -> bool:
|
|
112
|
+
"""True when the local embedding backend can be imported."""
|
|
113
|
+
return _backend() is not None
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
def provider() -> Optional[str]:
|
|
117
|
+
"""The active provider, preferring a configured key, or None when nothing works.
|
|
118
|
+
|
|
119
|
+
Order matters: local comes **last** so configuring Voyage keeps voyage-4.
|
|
120
|
+
A fallback that preempted a paid key would silently downgrade every existing
|
|
121
|
+
keyed install to a smaller model.
|
|
122
|
+
"""
|
|
123
|
+
if not enabled():
|
|
124
|
+
return None
|
|
125
|
+
if os.environ.get("VOYAGE_API_KEY"):
|
|
126
|
+
return "voyage"
|
|
127
|
+
if os.environ.get("OPENAI_API_KEY"):
|
|
128
|
+
return "openai"
|
|
129
|
+
if local_available():
|
|
130
|
+
return "local"
|
|
131
|
+
return None
|
|
132
|
+
|
|
133
|
+
|
|
134
|
+
def available() -> bool:
|
|
135
|
+
"""True when embeddings are enabled and a provider key is present."""
|
|
136
|
+
return provider() is not None
|
|
137
|
+
|
|
138
|
+
|
|
139
|
+
def model() -> Optional[str]:
|
|
140
|
+
"""The active provider's model name, or None when unconfigured."""
|
|
141
|
+
p = provider()
|
|
142
|
+
if p == "voyage":
|
|
143
|
+
return VOYAGE_MODEL
|
|
144
|
+
if p == "openai":
|
|
145
|
+
return OPENAI_MODEL
|
|
146
|
+
if p == "local":
|
|
147
|
+
return LOCAL_MODEL
|
|
148
|
+
return None
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def dimension() -> Optional[int]:
|
|
152
|
+
"""Output vector dimension of the active model, or None when
|
|
153
|
+
|
|
154
|
+
unconfigured. Stored in the index so a model switch forces a rebuild.
|
|
155
|
+
"""
|
|
156
|
+
m = model()
|
|
157
|
+
return _DIMS.get(m) if m is not None else None
|
|
158
|
+
|
|
159
|
+
|
|
160
|
+
def fallback_note() -> str:
|
|
161
|
+
"""The one-line hint shown when dense search degrades to BM25.
|
|
162
|
+
|
|
163
|
+
No longer asks for a key: with a local model in the ``[rag]`` extra the
|
|
164
|
+
extra alone is enough, and telling a user they need an API account when
|
|
165
|
+
they do not is worse than saying nothing.
|
|
166
|
+
"""
|
|
167
|
+
if not enabled():
|
|
168
|
+
return "dense search is off (BOOST_NO_EMBED) — using the BM25 engine"
|
|
169
|
+
return ("dense search needs the `[rag]` extra — `pip install "
|
|
170
|
+
"boost-skill-cli[rag]`; using the BM25 full-content engine")
|
|
171
|
+
|
|
172
|
+
|
|
173
|
+
def embed(texts: List[str], input_type: Optional[str] = None,
|
|
174
|
+
timeout: int = 60) -> Optional[List[List[float]]]:
|
|
175
|
+
"""Embed a batch of texts.
|
|
176
|
+
|
|
177
|
+
Returns one vector per input, ``[]`` for an empty batch, or ``None`` when no
|
|
178
|
+
provider is configured or the call fails (so callers degrade cleanly).
|
|
179
|
+
``input_type`` ("query"/"document") is honored by Voyage and ignored by
|
|
180
|
+
OpenAI.
|
|
181
|
+
"""
|
|
182
|
+
p = provider()
|
|
183
|
+
if p is None:
|
|
184
|
+
return None
|
|
185
|
+
if not texts:
|
|
186
|
+
return []
|
|
187
|
+
if p == "local":
|
|
188
|
+
return _embed_local(texts)
|
|
189
|
+
if p == "voyage":
|
|
190
|
+
body = {"input": texts.copy(), "model": VOYAGE_MODEL}
|
|
191
|
+
if input_type:
|
|
192
|
+
body["input_type"] = input_type
|
|
193
|
+
return _vectors(_post(VOYAGE_URL, os.environ["VOYAGE_API_KEY"],
|
|
194
|
+
body, timeout), len(texts))
|
|
195
|
+
body = {"input": texts.copy(), "model": OPENAI_MODEL}
|
|
196
|
+
return _vectors(_post(OPENAI_URL, os.environ["OPENAI_API_KEY"],
|
|
197
|
+
body, timeout), len(texts))
|
|
198
|
+
|
|
199
|
+
|
|
200
|
+
def _local_model():
|
|
201
|
+
"""The loaded local model, or None if it cannot be built.
|
|
202
|
+
|
|
203
|
+
First use downloads the pinned weights and caches them under
|
|
204
|
+
``~/.boost/cache/models``, so this can fail on a machine with no network.
|
|
205
|
+
That is a degrade, not an error: the caller floors to BM25 exactly as it
|
|
206
|
+
does when no key is set.
|
|
207
|
+
"""
|
|
208
|
+
return _backend()
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
def _embed_local(texts: List[str]) -> Optional[List[List[float]]]:
|
|
212
|
+
"""Embed locally. None on any failure, so the caller degrades to BM25.
|
|
213
|
+
|
|
214
|
+
Validated as strictly as the API path: a short batch would misalign vectors
|
|
215
|
+
against their chunks — every hit past the gap pointing at the wrong skill —
|
|
216
|
+
and a wrong-width row would either error inside sqlite-vec or quietly
|
|
217
|
+
corrupt the space, so both are rejected rather than stored.
|
|
218
|
+
"""
|
|
219
|
+
backend = _local_model()
|
|
220
|
+
if backend is None:
|
|
221
|
+
return None
|
|
222
|
+
try:
|
|
223
|
+
rows = backend.encode(texts.copy())
|
|
224
|
+
except Exception: # inference failure degrades, never raises
|
|
225
|
+
return None
|
|
226
|
+
if rows is None or len(rows) != len(texts):
|
|
227
|
+
return None
|
|
228
|
+
out: List[List[float]] = []
|
|
229
|
+
for row in rows:
|
|
230
|
+
try:
|
|
231
|
+
vec = [float(x) for x in row]
|
|
232
|
+
except (TypeError, ValueError):
|
|
233
|
+
return None
|
|
234
|
+
if len(vec) != LOCAL_DIM:
|
|
235
|
+
return None
|
|
236
|
+
out.append(vec)
|
|
237
|
+
return out
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _post(url: str, key: str, payload: dict, timeout: int) -> Optional[dict]:
|
|
241
|
+
data = json.dumps(payload).encode("utf-8")
|
|
242
|
+
req = urllib.request.Request(url, data=data, headers={ # noqa: S310 url is a hardcoded VOYAGE_URL/OPENAI_URL constant
|
|
243
|
+
"Authorization": "Bearer %s" % key,
|
|
244
|
+
"Content-Type": "application/json",
|
|
245
|
+
})
|
|
246
|
+
try:
|
|
247
|
+
with nethttp.urlopen(req, timeout=timeout) as resp:
|
|
248
|
+
return json.loads(resp.read())
|
|
249
|
+
except (urllib.error.URLError, OSError, ValueError):
|
|
250
|
+
return None
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
def _vectors(obj: Optional[dict], n: int) -> Optional[List[List[float]]]:
|
|
254
|
+
"""Pull ``data[].embedding`` out of an OpenAI-shaped response.
|
|
255
|
+
|
|
256
|
+
Both Voyage and OpenAI return ``{"data": [{"embedding": [...]}, ...]}``.
|
|
257
|
+
Returns None unless exactly ``n`` numeric vectors come back.
|
|
258
|
+
"""
|
|
259
|
+
if not isinstance(obj, dict):
|
|
260
|
+
return None
|
|
261
|
+
data = obj.get("data")
|
|
262
|
+
if not isinstance(data, list) or len(data) != n:
|
|
263
|
+
return None
|
|
264
|
+
out: List[List[float]] = []
|
|
265
|
+
for item in data:
|
|
266
|
+
vec = item.get("embedding") if isinstance(item, dict) else None
|
|
267
|
+
if not isinstance(vec, list) or not vec:
|
|
268
|
+
return None
|
|
269
|
+
out.append([float(x) for x in vec])
|
|
270
|
+
return out
|
|
@@ -0,0 +1,245 @@
|
|
|
1
|
+
"""The keyless local embedding backend: ONNX Runtime over a pinned BGE model.
|
|
2
|
+
|
|
3
|
+
``core.embed`` owns the provider chain; this owns the one thing that chain was
|
|
4
|
+
missing — a way to turn text into vectors with no API key. It is reached only
|
|
5
|
+
through ``embed.provider() == "local"`` and, like every other optional path in
|
|
6
|
+
this codebase, returns ``None`` rather than raising so the caller floors to
|
|
7
|
+
BM25.
|
|
8
|
+
|
|
9
|
+
Why the model is fetched rather than vendored
|
|
10
|
+
---------------------------------------------
|
|
11
|
+
The weights are 133 MB — far too large to ship in a wheel for a CLI whose whole
|
|
12
|
+
runtime is stdlib. So they are downloaded once, on first use, and cached under
|
|
13
|
+
``~/.boost/cache/models``. That download is the one part of boost that reaches
|
|
14
|
+
for something big at runtime, so it is pinned the same way the toolchain lock
|
|
15
|
+
is: a fixed repository *revision*, an expected byte length, and a **sha256 that
|
|
16
|
+
is verified before the file is used**. A mismatch deletes the download and
|
|
17
|
+
degrades rather than loading whatever arrived.
|
|
18
|
+
|
|
19
|
+
(For the record, because the number circulates: the "~30 MB" figure often
|
|
20
|
+
quoted for bge-small is the *quantized* rebuild third parties publish, not
|
|
21
|
+
BAAI's own export. This uses the authoritative one — a signed-supply-chain
|
|
22
|
+
repo has no business pulling model weights from a re-uploader to save a
|
|
23
|
+
one-time download. Quantization is a later optimisation, and it changes the
|
|
24
|
+
vectors, so it would need its own eval.)
|
|
25
|
+
|
|
26
|
+
Pooling
|
|
27
|
+
-------
|
|
28
|
+
BGE is a CLS-pooled model: the sentence embedding is the first token's hidden
|
|
29
|
+
state, L2-normalised — *not* a mean over tokens. Using mean pooling here would
|
|
30
|
+
still produce 384 plausible-looking floats and quietly worse retrieval, which
|
|
31
|
+
is the kind of bug an eval catches and a unit test does not, so the choice is
|
|
32
|
+
stated here and asserted against a known-good pair in the tests.
|
|
33
|
+
"""
|
|
34
|
+
from __future__ import annotations
|
|
35
|
+
|
|
36
|
+
import hashlib
|
|
37
|
+
import shutil
|
|
38
|
+
from pathlib import Path
|
|
39
|
+
from typing import List, Optional
|
|
40
|
+
|
|
41
|
+
from . import paths
|
|
42
|
+
|
|
43
|
+
# Pinned to a revision, not a branch: `main` moving would silently change every
|
|
44
|
+
# vector in every user's index, and the index only rebuilds when the *model
|
|
45
|
+
# name* changes — which it would not.
|
|
46
|
+
MODEL_REPO = "BAAI/bge-small-en-v1.5"
|
|
47
|
+
MODEL_REV = "5c38ec7c405ec4b44b94cc5a9bb96e735b38267a"
|
|
48
|
+
_BASE = "https://huggingface.co/%s/resolve/%s/" % (MODEL_REPO, MODEL_REV)
|
|
49
|
+
|
|
50
|
+
# path -> (bytes, sha256). Verified after download and again on every load, so
|
|
51
|
+
# a truncated or tampered cache cannot be used.
|
|
52
|
+
FILES = {
|
|
53
|
+
"onnx/model.onnx": (
|
|
54
|
+
133093490,
|
|
55
|
+
"828e1496d7fabb79cfa4dcd84fa38625c0d3d21da474a00f08db0f559940cf35"),
|
|
56
|
+
"tokenizer.json": (
|
|
57
|
+
711396,
|
|
58
|
+
"d241a60d5e8f04cc1b2b3e9ef7a4921b27bf526d9f6050ab90f9267a1f9e5c66"),
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
# BGE caps at 512 tokens; longer input is truncated rather than rejected, which
|
|
62
|
+
# matches how the chunker already feeds this.
|
|
63
|
+
MAX_TOKENS = 512
|
|
64
|
+
|
|
65
|
+
_session = None
|
|
66
|
+
_tokenizer = None
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
def _deps():
|
|
70
|
+
"""(onnxruntime, tokenizers) or (None, None) when the extra is absent.
|
|
71
|
+
|
|
72
|
+
Imported inside the function: ``scripts/import_budget.py`` gates CLI
|
|
73
|
+
startup, and an ONNX runtime at module import would charge `boost --help`
|
|
74
|
+
for a feature it never uses.
|
|
75
|
+
"""
|
|
76
|
+
try:
|
|
77
|
+
import onnxruntime
|
|
78
|
+
import tokenizers
|
|
79
|
+
except Exception: # any import failure means "no backend"
|
|
80
|
+
return None, None
|
|
81
|
+
return onnxruntime, tokenizers
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def available() -> bool:
|
|
85
|
+
"""True when the runtime and tokenizer libraries are importable."""
|
|
86
|
+
return _deps()[0] is not None
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def model_dir() -> Path:
|
|
90
|
+
"""Where the pinned weights are cached, keyed by revision."""
|
|
91
|
+
return paths.cache_dir() / "models" / MODEL_REV
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _verified(path: Path, size: int, digest: str) -> bool:
|
|
95
|
+
"""True when `path` matches the pinned length and hash.
|
|
96
|
+
|
|
97
|
+
Length first because it is free and rules out the common case (a truncated
|
|
98
|
+
download) without reading 133 MB.
|
|
99
|
+
"""
|
|
100
|
+
try:
|
|
101
|
+
if path.stat().st_size != size:
|
|
102
|
+
return False
|
|
103
|
+
h = hashlib.sha256()
|
|
104
|
+
with path.open("rb") as fh:
|
|
105
|
+
for block in iter(lambda: fh.read(1 << 20), b""):
|
|
106
|
+
h.update(block)
|
|
107
|
+
return h.hexdigest() == digest
|
|
108
|
+
except OSError:
|
|
109
|
+
return False
|
|
110
|
+
|
|
111
|
+
|
|
112
|
+
def _fetch(rel: str, dest: Path, size: int, digest: str) -> bool:
|
|
113
|
+
"""Download one pinned file. False on any failure, leaving nothing behind.
|
|
114
|
+
|
|
115
|
+
Downloads to a temporary name and only renames after the hash matches, so
|
|
116
|
+
an interrupted fetch can never be mistaken for a complete one on the next
|
|
117
|
+
run.
|
|
118
|
+
"""
|
|
119
|
+
from . import nethttp
|
|
120
|
+
tmp = dest.with_suffix(dest.suffix + ".part")
|
|
121
|
+
try:
|
|
122
|
+
dest.parent.mkdir(parents=True, exist_ok=True)
|
|
123
|
+
with nethttp.urlopen(_BASE + rel, timeout=600) as resp, \
|
|
124
|
+
tmp.open("wb") as out:
|
|
125
|
+
shutil.copyfileobj(resp, out, 1 << 20)
|
|
126
|
+
except Exception: # network/disk failure degrades to BM25
|
|
127
|
+
tmp.unlink(missing_ok=True)
|
|
128
|
+
return False
|
|
129
|
+
if not _verified(tmp, size, digest):
|
|
130
|
+
tmp.unlink(missing_ok=True)
|
|
131
|
+
return False
|
|
132
|
+
try:
|
|
133
|
+
tmp.replace(dest)
|
|
134
|
+
except OSError:
|
|
135
|
+
tmp.unlink(missing_ok=True)
|
|
136
|
+
return False
|
|
137
|
+
return True
|
|
138
|
+
|
|
139
|
+
|
|
140
|
+
def ensure_model() -> Optional[Path]:
|
|
141
|
+
"""The verified model directory, downloading it once if needed, or None."""
|
|
142
|
+
root = model_dir()
|
|
143
|
+
for rel, (size, digest) in FILES.items():
|
|
144
|
+
dest = root / rel
|
|
145
|
+
if _verified(dest, size, digest):
|
|
146
|
+
continue
|
|
147
|
+
if not _fetch(rel, dest, size, digest):
|
|
148
|
+
return None
|
|
149
|
+
return root
|
|
150
|
+
|
|
151
|
+
|
|
152
|
+
def _load():
|
|
153
|
+
"""Build and cache the session and tokenizer. False when unavailable."""
|
|
154
|
+
global _session, _tokenizer
|
|
155
|
+
if _session is not None and _tokenizer is not None:
|
|
156
|
+
return True
|
|
157
|
+
onnxruntime, tokenizers = _deps()
|
|
158
|
+
# Both, not just the first: they are returned as a pair and a partial
|
|
159
|
+
# install (onnxruntime present, tokenizers missing) would otherwise reach
|
|
160
|
+
# `tokenizers.Tokenizer` on a None.
|
|
161
|
+
if onnxruntime is None or tokenizers is None:
|
|
162
|
+
return False
|
|
163
|
+
root = ensure_model()
|
|
164
|
+
if root is None:
|
|
165
|
+
return False
|
|
166
|
+
try:
|
|
167
|
+
opts = onnxruntime.SessionOptions()
|
|
168
|
+
# A CLI embedding a handful of chunks gains nothing from spawning a
|
|
169
|
+
# thread per core, and an unbounded pool inside a `boost search` is a
|
|
170
|
+
# surprise on a shared machine.
|
|
171
|
+
opts.intra_op_num_threads = 1
|
|
172
|
+
opts.inter_op_num_threads = 1
|
|
173
|
+
session = onnxruntime.InferenceSession(
|
|
174
|
+
str(root / "onnx/model.onnx"), opts,
|
|
175
|
+
providers=["CPUExecutionProvider"])
|
|
176
|
+
tok = tokenizers.Tokenizer.from_file(str(root / "tokenizer.json"))
|
|
177
|
+
tok.enable_truncation(max_length=MAX_TOKENS)
|
|
178
|
+
tok.enable_padding()
|
|
179
|
+
except Exception: # a broken model degrades, never raises
|
|
180
|
+
return False
|
|
181
|
+
_session, _tokenizer = session, tok
|
|
182
|
+
return True
|
|
183
|
+
|
|
184
|
+
|
|
185
|
+
def reset() -> None:
|
|
186
|
+
"""Drop the cached session and tokenizer. For tests."""
|
|
187
|
+
global _session, _tokenizer
|
|
188
|
+
_session = None
|
|
189
|
+
_tokenizer = None
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
def encode(texts: List[str]) -> Optional[List[List[float]]]:
|
|
193
|
+
"""Embed `texts`, or None on any failure.
|
|
194
|
+
|
|
195
|
+
CLS pooling plus L2 normalisation, which is what BGE was trained for.
|
|
196
|
+
"""
|
|
197
|
+
if not texts:
|
|
198
|
+
return []
|
|
199
|
+
if not _load():
|
|
200
|
+
return None
|
|
201
|
+
session, tok = _session, _tokenizer
|
|
202
|
+
if session is None or tok is None: # unreachable after _load(); for type narrowing
|
|
203
|
+
return None
|
|
204
|
+
try:
|
|
205
|
+
encoded = tok.encode_batch(texts.copy())
|
|
206
|
+
feed = {}
|
|
207
|
+
wanted = {i.name for i in session.get_inputs()}
|
|
208
|
+
cols = {
|
|
209
|
+
"input_ids": [e.ids for e in encoded],
|
|
210
|
+
"attention_mask": [e.attention_mask for e in encoded],
|
|
211
|
+
"token_type_ids": [e.type_ids for e in encoded],
|
|
212
|
+
}
|
|
213
|
+
for name, col in cols.items():
|
|
214
|
+
if name in wanted:
|
|
215
|
+
feed[name] = _as_i64(col)
|
|
216
|
+
return cls_pool(session.run(None, feed)[0])
|
|
217
|
+
except Exception: # inference failure degrades to BM25
|
|
218
|
+
return None
|
|
219
|
+
|
|
220
|
+
|
|
221
|
+
def cls_pool(out) -> List[List[float]]:
|
|
222
|
+
"""Last hidden state -> one L2-normalised CLS vector per row.
|
|
223
|
+
|
|
224
|
+
Kept pure and separate from :func:`encode` so the part that decides *what a
|
|
225
|
+
sentence embedding is* can be tested without an ONNX runtime — it is the
|
|
226
|
+
step most likely to be silently wrong, since taking the mean instead of the
|
|
227
|
+
first token still yields plausible-looking vectors of the right width.
|
|
228
|
+
|
|
229
|
+
``out`` is (batch, tokens, hidden); ``row[0]`` is the [CLS] token.
|
|
230
|
+
"""
|
|
231
|
+
return [_normalise([float(x) for x in row[0]]) for row in out]
|
|
232
|
+
|
|
233
|
+
|
|
234
|
+
def _as_i64(rows):
|
|
235
|
+
"""Token id matrix as the int64 array onnxruntime expects."""
|
|
236
|
+
import numpy
|
|
237
|
+
return numpy.array(rows, dtype=numpy.int64)
|
|
238
|
+
|
|
239
|
+
|
|
240
|
+
def _normalise(vec: List[float]) -> List[float]:
|
|
241
|
+
"""L2-normalise, leaving an all-zero vector alone rather than dividing by 0."""
|
|
242
|
+
norm = sum(x * x for x in vec) ** 0.5
|
|
243
|
+
if not norm:
|
|
244
|
+
return vec
|
|
245
|
+
return [x / norm for x in vec]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boost-skill-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.309
|
|
4
4
|
Summary: boost — Homebrew for AI coding skills
|
|
5
5
|
Author: Jonathan Reyes
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -702,6 +702,8 @@ Description-Content-Type: text/markdown
|
|
|
702
702
|
License-File: LICENSE
|
|
703
703
|
Provides-Extra: rag
|
|
704
704
|
Requires-Dist: sqlite-vec>=0.1.6; extra == "rag"
|
|
705
|
+
Requires-Dist: onnxruntime>=1.17; extra == "rag"
|
|
706
|
+
Requires-Dist: tokenizers>=0.15; extra == "rag"
|
|
705
707
|
Provides-Extra: eval
|
|
706
708
|
Requires-Dist: ranx>=0.3.20; extra == "eval"
|
|
707
709
|
Requires-Dist: ragas<0.3,>=0.2; extra == "eval"
|
|
@@ -66,6 +66,7 @@ boost_cli/core/injectscan.py
|
|
|
66
66
|
boost_cli/core/installscan.py
|
|
67
67
|
boost_cli/core/integrity.py
|
|
68
68
|
boost_cli/core/journal.py
|
|
69
|
+
boost_cli/core/localembed.py
|
|
69
70
|
boost_cli/core/lockfile.py
|
|
70
71
|
boost_cli/core/logs.py
|
|
71
72
|
boost_cli/core/mcp.py
|
|
@@ -228,7 +229,7 @@ docs/roadmap/items/internal-architecture-diagrams.md
|
|
|
228
229
|
docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md
|
|
229
230
|
docs/roadmap/items/journal-rotation-race-and-handle-leak.md
|
|
230
231
|
docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md
|
|
231
|
-
docs/roadmap/items/keyless-
|
|
232
|
+
docs/roadmap/items/keyless-semantic-search-for-everyone.md
|
|
232
233
|
docs/roadmap/items/layering-guard-import-linter.md
|
|
233
234
|
docs/roadmap/items/license-compliance-scanning.md
|
|
234
235
|
docs/roadmap/items/lighthouse-ci-on-the-pages-site.md
|
|
@@ -488,6 +489,7 @@ tests/unit/test_docs_pages_linked.py
|
|
|
488
489
|
tests/unit/test_docsite_chrome.py
|
|
489
490
|
tests/unit/test_ed25519.py
|
|
490
491
|
tests/unit/test_embed.py
|
|
492
|
+
tests/unit/test_embed_local.py
|
|
491
493
|
tests/unit/test_errors_and_cli_table.py
|
|
492
494
|
tests/unit/test_eval_faithfulness.py
|
|
493
495
|
tests/unit/test_eval_gate.py
|
|
@@ -504,6 +506,7 @@ tests/unit/test_injectscan.py
|
|
|
504
506
|
tests/unit/test_installscan.py
|
|
505
507
|
tests/unit/test_integrity.py
|
|
506
508
|
tests/unit/test_journal.py
|
|
509
|
+
tests/unit/test_localembed.py
|
|
507
510
|
tests/unit/test_lockfile.py
|
|
508
511
|
tests/unit/test_logs.py
|
|
509
512
|
tests/unit/test_marketing_counts.py
|
|
@@ -56,3 +56,12 @@ cannot go in the default wheel — the shipped runtime is 0.79 MB and every merg
|
|
|
56
56
|
to main cuts a release, so +17.4 MB × ~24 releases/day exhausts PyPI's 10 GB
|
|
57
57
|
project quota in under a month; it needs a separate, rarely-released data
|
|
58
58
|
package behind an extra.
|
|
59
|
+
<b>Related, and partly overtaken:</b> [[keyless-semantic-search-for-everyone]] shipped a keyless
|
|
60
|
+
path using a <i>transformer</i> (BGE via ONNX Runtime, in the <code>[rag]</code> extra) while this
|
|
61
|
+
item was open. That does not settle the question this card asks — a static lookup table is
|
|
62
|
+
still far cheaper, and this card's discipline about not shipping a retrieval claim before the eval
|
|
63
|
+
still stands. What it does change is the baseline: "keyless" is no longer the differentiator, so the
|
|
64
|
+
case for a static model now rests on <b>cost</b> (~1 ms and no runtime dependency, against a
|
|
65
|
+
measured 233 ms cold and 34 MB of wheels) rather than on availability. Status left alone
|
|
66
|
+
deliberately — this is another loop's item to own.
|
|
67
|
+
|