boost-skill-cli 1.0.148__tar.gz → 1.0.150__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.148 → boost_skill_cli-1.0.150}/Makefile +19 -1
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/PKG-INFO +5 -1
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/discovery.py +170 -42
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_skill_cli.egg-info/PKG-INFO +5 -1
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_skill_cli.egg-info/SOURCES.txt +18 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_skill_cli.egg-info/requires.txt +6 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/pyproject.toml +10 -0
- boost_skill_cli-1.0.150/scripts/bench_cli.sh +27 -0
- boost_skill_cli-1.0.150/tests/bdd/features/adapt.feature +46 -0
- boost_skill_cli-1.0.150/tests/bdd/features/browse.feature +26 -0
- boost_skill_cli-1.0.150/tests/bdd/features/count.feature +24 -0
- boost_skill_cli-1.0.150/tests/bdd/features/discover.feature +39 -0
- boost_skill_cli-1.0.150/tests/bdd/features/doctor.feature +30 -0
- boost_skill_cli-1.0.150/tests/bdd/features/environment.py +66 -0
- boost_skill_cli-1.0.150/tests/bdd/features/explain.feature +25 -0
- boost_skill_cli-1.0.150/tests/bdd/features/index.feature +25 -0
- boost_skill_cli-1.0.150/tests/bdd/features/install.feature +43 -0
- boost_skill_cli-1.0.150/tests/bdd/features/list.feature +42 -0
- boost_skill_cli-1.0.150/tests/bdd/features/mcp.feature +31 -0
- boost_skill_cli-1.0.150/tests/bdd/features/search.feature +37 -0
- boost_skill_cli-1.0.150/tests/bdd/features/steps/cli_steps.py +104 -0
- boost_skill_cli-1.0.150/tests/bdd/features/steps/discovery_steps.py +77 -0
- boost_skill_cli-1.0.150/tests/bdd/features/steps/mcp_steps.py +48 -0
- boost_skill_cli-1.0.150/tests/bdd/features/steps/quality_steps.py +12 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_discovery.py +142 -44
- boost_skill_cli-1.0.150/tests/perf/test_benchmarks.py +59 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/.gitattributes +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/.gitignore +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/LICENSE +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/README.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/index.html +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/docs/roadmap.html +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/examples/README.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/index.html +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/setup.cfg +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/style/README.md +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/style/boost.css +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/style/boost.js +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/style/demo.html +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.148 → boost_skill_cli-1.0.150}/tests/unit/test_workflows.py +0 -0
|
@@ -10,7 +10,7 @@ PYTEST := $(VENV)/bin/pytest
|
|
|
10
10
|
# pinned taps out of the developer's real ~/.boost.
|
|
11
11
|
EVAL_HOME := $(CURDIR)/.eval-home
|
|
12
12
|
|
|
13
|
-
.PHONY: venv test unit functional smoke coverage mutation lint check demo clean-test eval eval-ai eval-rec eval-stats eval-explain audit dist-check
|
|
13
|
+
.PHONY: venv test unit functional smoke coverage mutation lint check demo clean-test eval eval-ai eval-rec eval-stats eval-explain audit dist-check bdd bench bench-cli
|
|
14
14
|
|
|
15
15
|
venv:
|
|
16
16
|
python3 -m venv $(VENV)
|
|
@@ -96,6 +96,24 @@ eval-explain:
|
|
|
96
96
|
PYTHON=$(PY) BOOST_HOME=$(EVAL_HOME) bash scripts/ensure_eval_corpus.sh
|
|
97
97
|
BOOST_HOME=$(EVAL_HOME) $(PY) scripts/eval_explain.py --fail-under 0.80
|
|
98
98
|
|
|
99
|
+
# Opt-in Gherkin/BDD suite (tests/bdd) — additive to tests/functional, not a
|
|
100
|
+
# replacement. Needs the [bdd] extra (`pip install -e '.[bdd]'`); not part of
|
|
101
|
+
# `make check`.
|
|
102
|
+
bdd:
|
|
103
|
+
$(VENV)/bin/behave tests/bdd/features
|
|
104
|
+
|
|
105
|
+
# Opt-in micro-benchmarks (tests/perf) for perf-sensitive core paths. Needs
|
|
106
|
+
# the [perf] extra (`pip install -e '.[perf]'`); not part of `make check` — a
|
|
107
|
+
# timing regression is informational, not a merge gate.
|
|
108
|
+
bench:
|
|
109
|
+
$(PYTEST) tests/perf --benchmark-only -q
|
|
110
|
+
|
|
111
|
+
# Opt-in wall-clock benchmark of the real `boost` binary via hyperfine. Not
|
|
112
|
+
# part of `make check`; degrades cleanly (prints a skip message, exits 0) when
|
|
113
|
+
# hyperfine isn't installed (`brew install hyperfine`).
|
|
114
|
+
bench-cli:
|
|
115
|
+
@command -v hyperfine >/dev/null 2>&1 && bash scripts/bench_cli.sh || echo "hyperfine not on PATH — install via 'brew install hyperfine', skipping"
|
|
116
|
+
|
|
99
117
|
# regenerate generated artifacts from their source (registries + roadmap boards)
|
|
100
118
|
generate:
|
|
101
119
|
$(PY) scripts/build_registries.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boost-skill-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.150
|
|
4
4
|
Summary: boost — Homebrew for AI coding skills
|
|
5
5
|
Author: Jonathan Reyes
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -708,6 +708,10 @@ Requires-Dist: ragas<0.3,>=0.2; extra == "eval"
|
|
|
708
708
|
Requires-Dist: langchain-core<0.4; extra == "eval"
|
|
709
709
|
Requires-Dist: langchain-community<0.4; extra == "eval"
|
|
710
710
|
Requires-Dist: langchain-openai<1; extra == "eval"
|
|
711
|
+
Provides-Extra: bdd
|
|
712
|
+
Requires-Dist: behave>=1.2.6; extra == "bdd"
|
|
713
|
+
Provides-Extra: perf
|
|
714
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == "perf"
|
|
711
715
|
Dynamic: license-file
|
|
712
716
|
|
|
713
717
|
# boost — a package manager for AI coding skills
|
|
@@ -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.150'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 150)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -11,12 +11,14 @@ import re
|
|
|
11
11
|
import shutil
|
|
12
12
|
import subprocess
|
|
13
13
|
import sys
|
|
14
|
+
import threading
|
|
14
15
|
import time
|
|
15
16
|
import urllib.parse
|
|
16
17
|
from pathlib import Path
|
|
17
18
|
|
|
18
19
|
from .. import cliparse, spin
|
|
19
|
-
from ..core import agents, ai, catalog, dense, embed, gitutil,
|
|
20
|
+
from ..core import (agents, ai, catalog, config, dense, embed, gitutil,
|
|
21
|
+
journal, lockfile, paths, rag, registry, store, util)
|
|
20
22
|
from ..core import output as out
|
|
21
23
|
from ..core.stackprobe import detect_stack # re-exported: shared with Quality
|
|
22
24
|
from ..errors import BoostError
|
|
@@ -451,6 +453,77 @@ def _browse_plain(entries, why: str):
|
|
|
451
453
|
return 0
|
|
452
454
|
|
|
453
455
|
|
|
456
|
+
def _tap_categories() -> dict:
|
|
457
|
+
"""tap name ('owner/repo') -> curated category, from the bundled registry
|
|
458
|
+
catalog (data/registries.json) — the only place "category" lives; catalog
|
|
459
|
+
entries themselves carry no category, only their tap does."""
|
|
460
|
+
return {e["name"]: e["category"] for e in config.load_registry_catalog()
|
|
461
|
+
if e.get("category")}
|
|
462
|
+
|
|
463
|
+
|
|
464
|
+
_KIND_BADGE_KEYS = {"skill": "badge_skill", "rule": "badge_rule",
|
|
465
|
+
"workflow": "badge_workflow"}
|
|
466
|
+
|
|
467
|
+
|
|
468
|
+
def _kind_theme_key(kind: str) -> str:
|
|
469
|
+
return _KIND_BADGE_KEYS.get(kind, "badge_skill")
|
|
470
|
+
|
|
471
|
+
|
|
472
|
+
def _row_badges(e: dict, categories: dict):
|
|
473
|
+
"""Ordered (text, theme-key) badges for a browse row: kind, version, tap,
|
|
474
|
+
and — when the tap is one of the curated registries — its category.
|
|
475
|
+
Most-important-first, so a narrow terminal drops from the tail without
|
|
476
|
+
losing the essentials (kind and version survive; category goes first)."""
|
|
477
|
+
badges = [("[%s]" % e.get("kind", "skill"),
|
|
478
|
+
_kind_theme_key(e.get("kind", "skill"))),
|
|
479
|
+
("v" + e["version"], "version"),
|
|
480
|
+
("[%s]" % e["tap"], "tap")]
|
|
481
|
+
category = categories.get(e["tap"])
|
|
482
|
+
if category:
|
|
483
|
+
badges.append(("[%s]" % category, "badge_category"))
|
|
484
|
+
return badges
|
|
485
|
+
|
|
486
|
+
|
|
487
|
+
def _desc_key(e: dict):
|
|
488
|
+
return (e.get("tap", ""), e["name"])
|
|
489
|
+
|
|
490
|
+
|
|
491
|
+
def _entry_source_path(e: dict):
|
|
492
|
+
"""On-disk path of the file backing a catalog entry, or None when its tap
|
|
493
|
+
isn't cloned/known — used to fall back to a `boost explain`-style summary
|
|
494
|
+
for entries whose frontmatter has no description."""
|
|
495
|
+
try:
|
|
496
|
+
tap = registry.get(e["tap"])
|
|
497
|
+
except BoostError:
|
|
498
|
+
return None
|
|
499
|
+
path = tap.path / e.get("skill_md", "")
|
|
500
|
+
return path if path.is_file() else None
|
|
501
|
+
|
|
502
|
+
|
|
503
|
+
def _lazy_description(e: dict) -> str:
|
|
504
|
+
"""A one-line fallback description for an entry with no frontmatter
|
|
505
|
+
description — the `boost explain` idea, sized for a picker row. Meant to
|
|
506
|
+
run off the UI thread since it may shell out to `claude`/the Anthropic API."""
|
|
507
|
+
path = _entry_source_path(e)
|
|
508
|
+
text = ""
|
|
509
|
+
if path is not None:
|
|
510
|
+
try:
|
|
511
|
+
text = path.read_text(encoding="utf-8", errors="replace")
|
|
512
|
+
except OSError:
|
|
513
|
+
text = ""
|
|
514
|
+
if text and ai.available():
|
|
515
|
+
reply = ai.ask(
|
|
516
|
+
"In ONE short plain sentence (max 18 words, no markdown), describe "
|
|
517
|
+
"what this %s named %r does, based on its file:\n\n%s"
|
|
518
|
+
% (e.get("kind", "skill"), e["name"], text[:4000]),
|
|
519
|
+
system="You summarize AI coding skills, rules, and workflows in "
|
|
520
|
+
"one plain sentence for a picker UI.",
|
|
521
|
+
max_tokens=60)
|
|
522
|
+
if reply:
|
|
523
|
+
return reply.strip().splitlines()[0][:200]
|
|
524
|
+
return "no description available"
|
|
525
|
+
|
|
526
|
+
|
|
454
527
|
# --- Aurora palette for the curses browser -----------------------------------
|
|
455
528
|
# The full-screen browser paints itself in the same Aurora tokens as the rest
|
|
456
529
|
# of the CLI. curses can't reuse the ANSI escapes from core.output, so these
|
|
@@ -561,7 +634,10 @@ def _aurora_theme(curses):
|
|
|
561
634
|
"scroll": curses.A_DIM, "detail_name": curses.A_BOLD,
|
|
562
635
|
"detail_meta": curses.A_DIM, "detail_tag": curses.A_NORMAL,
|
|
563
636
|
"dot_r": curses.A_NORMAL, "dot_y": curses.A_NORMAL,
|
|
564
|
-
"dot_g": curses.A_NORMAL
|
|
637
|
+
"dot_g": curses.A_NORMAL, "check": curses.A_BOLD,
|
|
638
|
+
"badge_skill": curses.A_NORMAL, "badge_rule": curses.A_NORMAL,
|
|
639
|
+
"badge_workflow": curses.A_NORMAL, "badge_category": curses.A_NORMAL,
|
|
640
|
+
"desc": curses.A_DIM}
|
|
565
641
|
if not hasattr(curses, "start_color"):
|
|
566
642
|
return t
|
|
567
643
|
try:
|
|
@@ -581,19 +657,49 @@ def _aurora_theme(curses):
|
|
|
581
657
|
"tap": P("violet"), "rule": [P("cyan"), P("violet"), P("pink")],
|
|
582
658
|
"scroll": P("cyan"), "detail_name": P("cyan", True),
|
|
583
659
|
"detail_tag": P("pink"), "dot_r": P("red"), "dot_y": P("yellow"),
|
|
584
|
-
"dot_g": P("green")
|
|
660
|
+
"dot_g": P("green"), "check": P("green", True),
|
|
661
|
+
"badge_skill": P("cyan"), "badge_rule": P("violet"),
|
|
662
|
+
"badge_workflow": P("pink"), "badge_category": P("yellow")})
|
|
585
663
|
return t
|
|
586
664
|
|
|
587
665
|
|
|
666
|
+
_NAME_X = 4 # column the name (and everything under it) starts at
|
|
667
|
+
|
|
668
|
+
|
|
588
669
|
def _browse_tui(curses, entries):
|
|
589
|
-
"""Run the curses UI. Returns the
|
|
590
|
-
|
|
670
|
+
"""Run the curses UI. Returns the list of entries picked for install
|
|
671
|
+
(one or more, via multi-select), or None if the user quit without picking.
|
|
672
|
+
"""
|
|
673
|
+
state = {"picks": None}
|
|
674
|
+
categories = _tap_categories()
|
|
675
|
+
desc_cache: dict = {}
|
|
676
|
+
loading: set = set()
|
|
677
|
+
|
|
678
|
+
def describe(e):
|
|
679
|
+
"""Description text for a row, kicking off a background lazy-load
|
|
680
|
+
(the `boost explain` fallback) the first time an entry with no
|
|
681
|
+
frontmatter description is shown — never blocks the draw loop."""
|
|
682
|
+
if e.get("description"):
|
|
683
|
+
return e["description"]
|
|
684
|
+
key = _desc_key(e)
|
|
685
|
+
if key in desc_cache:
|
|
686
|
+
return desc_cache[key]
|
|
687
|
+
if key not in loading:
|
|
688
|
+
loading.add(key)
|
|
689
|
+
|
|
690
|
+
def worker(entry=e, cache_key=key):
|
|
691
|
+
desc_cache[cache_key] = _lazy_description(entry)
|
|
692
|
+
loading.discard(cache_key)
|
|
693
|
+
|
|
694
|
+
threading.Thread(target=worker, daemon=True).start()
|
|
695
|
+
return "loading description…"
|
|
591
696
|
|
|
592
697
|
def ui(scr):
|
|
593
698
|
try:
|
|
594
699
|
curses.curs_set(0)
|
|
595
700
|
except curses.error:
|
|
596
701
|
pass
|
|
702
|
+
scr.timeout(80) # short poll so a finished lazy-load redraws promptly
|
|
597
703
|
th = _aurora_theme(curses)
|
|
598
704
|
|
|
599
705
|
def put(y, x, s, attr=0): # clip-safe cell writer
|
|
@@ -604,6 +710,7 @@ def _browse_tui(curses, entries):
|
|
|
604
710
|
pass
|
|
605
711
|
|
|
606
712
|
filt, sel, detail = "", 0, False
|
|
713
|
+
selected: set = set()
|
|
607
714
|
while True:
|
|
608
715
|
q = filt.lower()
|
|
609
716
|
matches = [e for e in entries
|
|
@@ -627,35 +734,46 @@ def _browse_tui(curses, entries):
|
|
|
627
734
|
put(1, 0, "❯", th["prompt"])
|
|
628
735
|
put(1, 2, filt, th["query"])
|
|
629
736
|
put(1, 2 + len(filt), "▏", th["prompt"])
|
|
630
|
-
|
|
737
|
+
sel_txt = "%d selected · " % len(selected) if selected else ""
|
|
738
|
+
count = "%s%d/%d" % (sel_txt, len(matches), len(entries))
|
|
631
739
|
put(1, max(2 + len(filt) + 2, _w - 1 - len(count)), count,
|
|
632
740
|
th["count"])
|
|
633
|
-
put(2, 0, "↑↓ move ↵ detail i install q quit",
|
|
741
|
+
put(2, 0, "↑↓ move space select ↵ detail i install q quit",
|
|
634
742
|
th["help"])
|
|
635
|
-
|
|
743
|
+
# each result is a two-row card: name/badges, then description
|
|
744
|
+
avail = max(0, _h - 3 - pane)
|
|
745
|
+
rows = max(1, avail // 2)
|
|
636
746
|
top = max(0, sel - rows + 1)
|
|
637
747
|
view = matches[top:top + rows]
|
|
638
748
|
namew = min(max((len(e["name"]) for e in view), default=4),
|
|
639
|
-
max(
|
|
749
|
+
max(8, _w - _NAME_X - 30))
|
|
640
750
|
bar = _scrollbar(len(matches), rows, top)
|
|
641
751
|
for i, e in enumerate(view):
|
|
642
|
-
y = 3 + i
|
|
752
|
+
y = 3 + i * 2
|
|
643
753
|
chosen = top + i == sel
|
|
754
|
+
checked = _desc_key(e) in selected
|
|
644
755
|
put(y, 0, "▎" if chosen else " ", th["sel_bar"])
|
|
645
|
-
put(y, 1, "
|
|
756
|
+
put(y, 1, "✓" if checked else " ", th["check"])
|
|
757
|
+
put(y, 2, "★" if e.get("curated") else " ", th["star"])
|
|
646
758
|
nm = out.truncate(e["name"], namew)
|
|
647
|
-
put(y,
|
|
759
|
+
put(y, _NAME_X, nm.ljust(namew),
|
|
648
760
|
th["sel_name"] if chosen else th["name"])
|
|
649
761
|
for pos in _match_positions(q, nm.lower()):
|
|
650
|
-
put(y,
|
|
651
|
-
|
|
652
|
-
|
|
653
|
-
|
|
762
|
+
put(y, _NAME_X + pos, nm[pos], th["match"])
|
|
763
|
+
bx = _NAME_X + namew + 2
|
|
764
|
+
for text, tkey in _row_badges(e, categories):
|
|
765
|
+
if bx + len(text) > _w - 2:
|
|
766
|
+
break
|
|
767
|
+
put(y, bx, text, th[tkey])
|
|
768
|
+
bx += len(text) + 1
|
|
769
|
+
put(y + 1, _NAME_X, out.truncate(describe(e), _w - 1 - _NAME_X),
|
|
770
|
+
th["desc"])
|
|
654
771
|
if bar:
|
|
655
772
|
bstart, blen = bar
|
|
656
|
-
|
|
657
|
-
|
|
658
|
-
|
|
773
|
+
thumb = bstart <= i < bstart + blen
|
|
774
|
+
ch = "█" if thumb else "│"
|
|
775
|
+
put(y, _w - 2, ch, th["scroll"])
|
|
776
|
+
put(y + 1, _w - 2, ch, th["scroll"])
|
|
659
777
|
if pane and matches:
|
|
660
778
|
e = matches[sel]
|
|
661
779
|
y0 = _h - pane
|
|
@@ -666,7 +784,7 @@ def _browse_tui(curses, entries):
|
|
|
666
784
|
(e.get("meta", {}).get("tags") or []))
|
|
667
785
|
put(y0 + 1, 1, "%s v%s" % (e["name"], e["version"]),
|
|
668
786
|
th["detail_name"])
|
|
669
|
-
put(y0 + 2, 1, out.truncate(e
|
|
787
|
+
put(y0 + 2, 1, out.truncate(describe(e), _w - 3),
|
|
670
788
|
th["name"])
|
|
671
789
|
put(y0 + 3, 1, "tap %s dir %s" % (e["tap"], e["rel_dir"]),
|
|
672
790
|
th["detail_meta"])
|
|
@@ -675,12 +793,21 @@ def _browse_tui(curses, entries):
|
|
|
675
793
|
except curses.error:
|
|
676
794
|
pass # terminal too small mid-draw; retry on next key
|
|
677
795
|
key = scr.getch()
|
|
796
|
+
if key == -1: # poll tick, no key
|
|
797
|
+
continue
|
|
678
798
|
if key in (ord("q"), 27): # q / ESC
|
|
679
799
|
return
|
|
680
800
|
if key == ord("i") and matches:
|
|
681
|
-
state["
|
|
801
|
+
state["picks"] = ([e for e in entries if _desc_key(e) in selected]
|
|
802
|
+
if selected else [matches[sel]])
|
|
682
803
|
return
|
|
683
|
-
if key ==
|
|
804
|
+
if key == ord(" ") and matches:
|
|
805
|
+
k = _desc_key(matches[sel])
|
|
806
|
+
if k in selected:
|
|
807
|
+
selected.discard(k)
|
|
808
|
+
else:
|
|
809
|
+
selected.add(k)
|
|
810
|
+
elif key == curses.KEY_UP:
|
|
684
811
|
sel = max(0, sel - 1)
|
|
685
812
|
elif key == curses.KEY_DOWN:
|
|
686
813
|
sel = min(sel + 1, max(0, len(matches) - 1))
|
|
@@ -688,11 +815,11 @@ def _browse_tui(curses, entries):
|
|
|
688
815
|
detail = not detail
|
|
689
816
|
elif key in (curses.KEY_BACKSPACE, 127, 8):
|
|
690
817
|
filt = filt[:-1]
|
|
691
|
-
elif
|
|
818
|
+
elif 33 <= key <= 126: # printable, not space
|
|
692
819
|
filt += chr(key)
|
|
693
820
|
|
|
694
821
|
curses.wrapper(ui) # wrapper guards drawing with try/finally endwin()
|
|
695
|
-
return state["
|
|
822
|
+
return state["picks"]
|
|
696
823
|
|
|
697
824
|
|
|
698
825
|
def cmd_browse(argv):
|
|
@@ -712,25 +839,26 @@ def cmd_browse(argv):
|
|
|
712
839
|
except ImportError:
|
|
713
840
|
return _browse_plain(entries, "curses is unavailable on this Python")
|
|
714
841
|
picked = _browse_tui(curses, entries)
|
|
715
|
-
if picked
|
|
842
|
+
if not picked:
|
|
716
843
|
return 0
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
|
|
723
|
-
|
|
724
|
-
|
|
725
|
-
|
|
726
|
-
|
|
727
|
-
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
844
|
+
for entry in picked:
|
|
845
|
+
try:
|
|
846
|
+
res = store.install(entry)
|
|
847
|
+
except BoostError as e:
|
|
848
|
+
# browse lists every catalog kind (skills, rules, workflows), but
|
|
849
|
+
# only skills install; a rule/workflow pick — or an already-
|
|
850
|
+
# installed/pinned skill — must not abort the rest of the batch.
|
|
851
|
+
out.warn(e.message)
|
|
852
|
+
if e.hint:
|
|
853
|
+
out.info(out.c(e.hint, out.DIM))
|
|
854
|
+
continue
|
|
855
|
+
out.ok("installed %s v%s → %s"
|
|
856
|
+
% (entry["name"], entry["version"], _tilde(res.dest)))
|
|
857
|
+
if res.linked:
|
|
858
|
+
out.info("linked into: "
|
|
859
|
+
+ ", ".join(agents.display_name(a) for a in res.linked))
|
|
860
|
+
for conflict in res.conflicts:
|
|
861
|
+
out.warn("conflict: %s exists and is not a symlink" % _tilde(conflict))
|
|
734
862
|
return 0
|
|
735
863
|
|
|
736
864
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: boost-skill-cli
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.150
|
|
4
4
|
Summary: boost — Homebrew for AI coding skills
|
|
5
5
|
Author: Jonathan Reyes
|
|
6
6
|
License: GNU GENERAL PUBLIC LICENSE
|
|
@@ -708,6 +708,10 @@ Requires-Dist: ragas<0.3,>=0.2; extra == "eval"
|
|
|
708
708
|
Requires-Dist: langchain-core<0.4; extra == "eval"
|
|
709
709
|
Requires-Dist: langchain-community<0.4; extra == "eval"
|
|
710
710
|
Requires-Dist: langchain-openai<1; extra == "eval"
|
|
711
|
+
Provides-Extra: bdd
|
|
712
|
+
Requires-Dist: behave>=1.2.6; extra == "bdd"
|
|
713
|
+
Provides-Extra: perf
|
|
714
|
+
Requires-Dist: pytest-benchmark>=4.0; extra == "perf"
|
|
711
715
|
Dynamic: license-file
|
|
712
716
|
|
|
713
717
|
# boost — a package manager for AI coding skills
|
|
@@ -217,6 +217,7 @@ docs/roadmap/items/workspace-scope-install.md
|
|
|
217
217
|
examples/README.md
|
|
218
218
|
examples/adapt-demo.sh
|
|
219
219
|
examples/boost-run-prototype.sh
|
|
220
|
+
scripts/bench_cli.sh
|
|
220
221
|
scripts/build_registries.py
|
|
221
222
|
scripts/build_roadmap.py
|
|
222
223
|
scripts/ensure_eval_corpus.sh
|
|
@@ -231,6 +232,22 @@ style/demo.html
|
|
|
231
232
|
tests/conftest.py
|
|
232
233
|
tests/make_fixture.py
|
|
233
234
|
tests/smoke.sh
|
|
235
|
+
tests/bdd/features/adapt.feature
|
|
236
|
+
tests/bdd/features/browse.feature
|
|
237
|
+
tests/bdd/features/count.feature
|
|
238
|
+
tests/bdd/features/discover.feature
|
|
239
|
+
tests/bdd/features/doctor.feature
|
|
240
|
+
tests/bdd/features/environment.py
|
|
241
|
+
tests/bdd/features/explain.feature
|
|
242
|
+
tests/bdd/features/index.feature
|
|
243
|
+
tests/bdd/features/install.feature
|
|
244
|
+
tests/bdd/features/list.feature
|
|
245
|
+
tests/bdd/features/mcp.feature
|
|
246
|
+
tests/bdd/features/search.feature
|
|
247
|
+
tests/bdd/features/steps/cli_steps.py
|
|
248
|
+
tests/bdd/features/steps/discovery_steps.py
|
|
249
|
+
tests/bdd/features/steps/mcp_steps.py
|
|
250
|
+
tests/bdd/features/steps/quality_steps.py
|
|
234
251
|
tests/eval/baseline.json
|
|
235
252
|
tests/eval/explain.jsonl
|
|
236
253
|
tests/eval/golden.jsonl
|
|
@@ -249,6 +266,7 @@ tests/functional/test_cli_taps.py
|
|
|
249
266
|
tests/functional/test_cli_team.py
|
|
250
267
|
tests/functional/test_everyday_loop.py
|
|
251
268
|
tests/functional/test_property_parsers.py
|
|
269
|
+
tests/perf/test_benchmarks.py
|
|
252
270
|
tests/unit/test_adapters.py
|
|
253
271
|
tests/unit/test_agents.py
|
|
254
272
|
tests/unit/test_ai.py
|
|
@@ -55,6 +55,16 @@ eval = [
|
|
|
55
55
|
"langchain-community<0.4",
|
|
56
56
|
"langchain-openai<1",
|
|
57
57
|
]
|
|
58
|
+
# Opt-in Gherkin/BDD functional suite (tests/bdd) — reusable Given/When/Then
|
|
59
|
+
# scenarios over the same in-process CLI entrypoint tests/functional drives.
|
|
60
|
+
# Additive to, not a replacement for, the pytest functional suite; not part of
|
|
61
|
+
# `make check`. `pip install -e '.[bdd]'`.
|
|
62
|
+
bdd = ["behave>=1.2.6"]
|
|
63
|
+
# Opt-in micro-benchmarks (tests/perf, `make bench`) for perf-sensitive core
|
|
64
|
+
# paths (BM25 indexing/search, catalog scan). Not part of `make check` — a
|
|
65
|
+
# timing regression shouldn't block a merge the way a correctness gate does.
|
|
66
|
+
# `pip install -e '.[perf]'`.
|
|
67
|
+
perf = ["pytest-benchmark>=4.0"]
|
|
58
68
|
|
|
59
69
|
[project.scripts]
|
|
60
70
|
boost = "boost_cli.cli:main"
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
#!/usr/bin/env bash
|
|
2
|
+
# Wall-clock benchmark of the real `boost` binary via hyperfine — the actual
|
|
3
|
+
# fork+exec CLI, not the in-process pytest-benchmark suite (tests/perf).
|
|
4
|
+
# Opt-in (`make bench-cli`); not part of `make check`. Degrades cleanly if
|
|
5
|
+
# hyperfine isn't installed.
|
|
6
|
+
set -uo pipefail
|
|
7
|
+
|
|
8
|
+
if ! command -v hyperfine >/dev/null 2>&1; then
|
|
9
|
+
echo "hyperfine not installed — install via 'brew install hyperfine', skipping"
|
|
10
|
+
exit 0
|
|
11
|
+
fi
|
|
12
|
+
|
|
13
|
+
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
|
14
|
+
SB="$(mktemp -d "${TMPDIR:-/tmp}/boost-bench-XXXXXX")"
|
|
15
|
+
trap 'rm -rf "$SB"' EXIT
|
|
16
|
+
export HOME="$SB" BOOST_NO_AI=1 BOOST_ASSUME_YES=1 NO_COLOR=1
|
|
17
|
+
|
|
18
|
+
FIX="$(python3 "$ROOT/tests/make_fixture.py" "$SB/fixture-tap")"
|
|
19
|
+
"$ROOT/boost" tap "$FIX" >/dev/null
|
|
20
|
+
"$ROOT/boost" install brainstorming >/dev/null
|
|
21
|
+
|
|
22
|
+
echo "== hyperfine: $(command -v hyperfine) over $ROOT/boost (sandbox: $SB)"
|
|
23
|
+
hyperfine --warmup 3 \
|
|
24
|
+
"$ROOT/boost --help" \
|
|
25
|
+
"$ROOT/boost list" \
|
|
26
|
+
"$ROOT/boost search brainstorming" \
|
|
27
|
+
"$ROOT/boost count"
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
Feature: boost adapt
|
|
2
|
+
Render a skill as another agent framework's native source (CrewAI, Agents SDK).
|
|
3
|
+
|
|
4
|
+
Background:
|
|
5
|
+
Given a fresh boost environment
|
|
6
|
+
And the fixture tap is added
|
|
7
|
+
|
|
8
|
+
Scenario: adapting an installed skill to CrewAI
|
|
9
|
+
Given the "brainstorming" skill is installed
|
|
10
|
+
When I run "boost adapt brainstorming --to crewai"
|
|
11
|
+
Then the exit code should be 0
|
|
12
|
+
And the output should contain "from crewai import Agent"
|
|
13
|
+
And the output should contain "brainstorming = Agent("
|
|
14
|
+
|
|
15
|
+
Scenario: adapting an installed skill to the Agents SDK
|
|
16
|
+
Given the "brainstorming" skill is installed
|
|
17
|
+
When I run "boost adapt brainstorming --to agents-sdk"
|
|
18
|
+
Then the exit code should be 0
|
|
19
|
+
And the output should contain "from agents import Agent"
|
|
20
|
+
And the output should match "name=\"brainstorming\""
|
|
21
|
+
|
|
22
|
+
Scenario: adapting a tapped-but-not-installed skill still resolves
|
|
23
|
+
When I run "boost adapt brainstorming --to crewai"
|
|
24
|
+
Then the exit code should be 0
|
|
25
|
+
And the output should contain "brainstorming = Agent("
|
|
26
|
+
|
|
27
|
+
Scenario: --model none opts out of pinning an LLM
|
|
28
|
+
Given the "brainstorming" skill is installed
|
|
29
|
+
When I run "boost adapt brainstorming --to crewai --model none"
|
|
30
|
+
Then the exit code should be 0
|
|
31
|
+
And the output should not contain "llm="
|
|
32
|
+
|
|
33
|
+
Scenario: an unknown framework is rejected
|
|
34
|
+
Given the "brainstorming" skill is installed
|
|
35
|
+
When I run "boost adapt brainstorming --to langchain"
|
|
36
|
+
Then the exit code should be 1
|
|
37
|
+
And the output should contain "unknown framework"
|
|
38
|
+
|
|
39
|
+
Scenario: --to is required
|
|
40
|
+
Given the "brainstorming" skill is installed
|
|
41
|
+
When I run "boost adapt brainstorming"
|
|
42
|
+
Then the exit code should be 2
|
|
43
|
+
|
|
44
|
+
Scenario: adapting an unknown skill fails
|
|
45
|
+
When I run "boost adapt does-not-exist --to crewai"
|
|
46
|
+
Then the exit code should be 1
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
Feature: boost browse
|
|
2
|
+
Interactive full-screen TUI with fuzzy search. There is no TTY in these
|
|
3
|
+
scenarios, so `browse` takes its documented non-interactive escape hatch
|
|
4
|
+
and prints the full catalog instead of launching curses.
|
|
5
|
+
|
|
6
|
+
Background:
|
|
7
|
+
Given a fresh boost environment
|
|
8
|
+
|
|
9
|
+
Scenario: no skills available to browse
|
|
10
|
+
When I run "boost browse"
|
|
11
|
+
Then the exit code should be 1
|
|
12
|
+
And the output should contain "no skills available to browse"
|
|
13
|
+
|
|
14
|
+
Scenario: without a TTY, prints the full catalog instead of the TUI
|
|
15
|
+
Given the fixture tap is added
|
|
16
|
+
When I run "boost browse"
|
|
17
|
+
Then the exit code should be 0
|
|
18
|
+
And the output should contain "interactive mode needs a TTY — showing the full catalog"
|
|
19
|
+
And the output should contain "brainstorming"
|
|
20
|
+
And the output should contain "commit-messages"
|
|
21
|
+
And the output should contain "5 skills · install with `boost install <name>`"
|
|
22
|
+
|
|
23
|
+
Scenario: --help documents the command without touching the catalog
|
|
24
|
+
When I run "boost browse --help"
|
|
25
|
+
Then the exit code should be 0
|
|
26
|
+
And the output should contain "Interactive full-screen TUI with fuzzy search"
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
Feature: boost count
|
|
2
|
+
A one-line inventory summary: installed / available / taps / discovery index.
|
|
3
|
+
|
|
4
|
+
Background:
|
|
5
|
+
Given a fresh boost environment
|
|
6
|
+
|
|
7
|
+
Scenario: an empty environment
|
|
8
|
+
When I run "boost count"
|
|
9
|
+
Then the exit code should be 0
|
|
10
|
+
And the output should contain "installed 0 · available 0 (across 0 taps) · discovery index not built"
|
|
11
|
+
|
|
12
|
+
Scenario: one tap with one installed skill
|
|
13
|
+
Given the "brainstorming" skill is installed
|
|
14
|
+
When I run "boost count"
|
|
15
|
+
Then the exit code should be 0
|
|
16
|
+
And the output should contain "installed 1 · available 5 (across 1 tap) · discovery index not built"
|
|
17
|
+
And the output should contain "╭─ inventory"
|
|
18
|
+
|
|
19
|
+
Scenario: --json is machine readable
|
|
20
|
+
Given the "brainstorming" skill is installed
|
|
21
|
+
When I run "boost count --json"
|
|
22
|
+
Then the exit code should be 0
|
|
23
|
+
And the output should match "\"installed\": 1"
|
|
24
|
+
And the output should match "\"taps\": 1"
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
Feature: boost discover
|
|
2
|
+
Browse and filter the GitHub-wide discovery index built by `boost index`.
|
|
3
|
+
|
|
4
|
+
Background:
|
|
5
|
+
Given a fresh boost environment
|
|
6
|
+
|
|
7
|
+
Scenario: without an index and without gh, hints to install gh
|
|
8
|
+
Given the GitHub CLI is not installed
|
|
9
|
+
When I run "boost discover"
|
|
10
|
+
Then the exit code should be 0
|
|
11
|
+
And the output should contain "the discovery index has not been built yet"
|
|
12
|
+
And the output should contain "install the GitHub CLI first"
|
|
13
|
+
|
|
14
|
+
Scenario: without an index but with gh, hints to run boost index
|
|
15
|
+
Given the GitHub CLI is installed and code search returns 2 sample skill files
|
|
16
|
+
When I run "boost discover"
|
|
17
|
+
Then the exit code should be 0
|
|
18
|
+
And the output should contain "build it with `boost index` (GitHub Code Search)"
|
|
19
|
+
|
|
20
|
+
Scenario: a query filters indexed entries
|
|
21
|
+
Given the discovery index is seeded with sample items
|
|
22
|
+
When I run "boost discover acme"
|
|
23
|
+
Then the exit code should be 0
|
|
24
|
+
And the output should contain "skills/web/SKILL.md"
|
|
25
|
+
And the output should not contain "octo/skills"
|
|
26
|
+
And the output should contain "2 of 3 indexed skills · GitHub reports ~42 total"
|
|
27
|
+
|
|
28
|
+
Scenario: a query with no matches reports the index size
|
|
29
|
+
Given the discovery index is seeded with sample items
|
|
30
|
+
When I run "boost discover zzz"
|
|
31
|
+
Then the exit code should be 0
|
|
32
|
+
And the output should contain "no indexed skills match 'zzz'"
|
|
33
|
+
And the output should contain "the index holds 3 entries — rebuild with `boost index`"
|
|
34
|
+
|
|
35
|
+
Scenario: a corrupt index fails cleanly
|
|
36
|
+
Given the discovery index is corrupt
|
|
37
|
+
When I run "boost discover"
|
|
38
|
+
Then the exit code should be 1
|
|
39
|
+
And the output should contain "the discovery index is corrupt"
|