boost-skill-cli 1.0.154__tar.gz → 1.0.155__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.154 → boost_skill_cli-1.0.155}/Makefile +1 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/discovery.py +9 -1
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/SOURCES.txt +2 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +3 -3
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap.html +1 -1
- boost_skill_cli-1.0.155/scripts/import_budget.py +156 -0
- boost_skill_cli-1.0.155/tests/unit/test_import_budget.py +135 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/.gitattributes +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/.gitignore +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/LICENSE +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/README.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/adapters.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/imperative.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/injectscan.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/mcp.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/nethttp.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/output.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/rules.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/secretscan.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/serve.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/stackprobe.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/staleness.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/typosquat.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/updatediff.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/workflows.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/spin.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/adapters.html +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/design-roadmap.html +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/eval.html +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/index.html +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/mcp-hub.html +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D01.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D02.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D03.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D04.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D05.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D06.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D07.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D08.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D09.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D10.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D11.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D12.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D13.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D14.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D15.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D16.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D17.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D18.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D19.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D20.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D21.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D22.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D23.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D24.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D25.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D26.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/boost-run-live-agents.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/command-reference-docs-site.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/html-validation-html-validate.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/typo-detection-codespell.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/update-diff-before-apply.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/workspace-scope-install.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/examples/README.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/examples/adapt-demo.sh +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/examples/boost-run-prototype.sh +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/index.html +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/bench_cli.sh +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/build_roadmap.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/ensure_eval_corpus.sh +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/eval_explain.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/eval_recommend.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/eval_retrieval.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/setup.cfg +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/style/README.md +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/style/boost.css +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/style/boost.js +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/style/demo.html +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/adapt.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/browse.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/count.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/discover.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/doctor.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/environment.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/explain.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/index.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/install.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/list.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/mcp.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/search.feature +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/steps/cli_steps.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/steps/discovery_steps.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/steps/mcp_steps.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/steps/quality_steps.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/baseline.json +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/explain.jsonl +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/golden.jsonl +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/recommend.jsonl +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/taps.txt +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_adapt.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_property_parsers.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/perf/test_benchmarks.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_adapters.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_dense_fallback.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_docs_pages_linked.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_imperative.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_injectscan.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_mcp.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_nethttp.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_output.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_pkg_confusions.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_pkg_injection.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_pkg_secrets.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_registries_fresh.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_roadmap_fresh.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_rules.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_secretscan.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_serve.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_spin.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_stackprobe.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_staleness.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_token_parity.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_typosquat.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_updatediff.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_version.py +0 -0
- {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_workflows.py +0 -0
|
@@ -43,6 +43,7 @@ lint:
|
|
|
43
43
|
@command -v actionlint >/dev/null 2>&1 && actionlint || echo "actionlint not on PATH — skipping (CI enforces it)"
|
|
44
44
|
$(PY) scripts/build_registries.py --check
|
|
45
45
|
$(PY) scripts/build_roadmap.py --check
|
|
46
|
+
$(PY) scripts/import_budget.py
|
|
46
47
|
|
|
47
48
|
# Supply-chain CVE gate: fail on a known OSV/PyPI advisory in the project's
|
|
48
49
|
# dependency closure. Mirrors the pip-audit CI workflow; run before releasing.
|
|
@@ -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.155'
|
|
22
|
+
__version_tuple__ = version_tuple = (1, 0, 155)
|
|
23
23
|
|
|
24
24
|
__commit_id__ = commit_id = None
|
|
@@ -17,7 +17,7 @@ import urllib.parse
|
|
|
17
17
|
from pathlib import Path
|
|
18
18
|
|
|
19
19
|
from .. import cliparse, spin
|
|
20
|
-
from ..core import (agents, ai, catalog, config,
|
|
20
|
+
from ..core import (agents, ai, catalog, config, gitutil,
|
|
21
21
|
journal, lockfile, paths, rag, registry, store, util)
|
|
22
22
|
from ..core import output as out
|
|
23
23
|
from ..core.stackprobe import detect_stack # re-exported: shared with Quality
|
|
@@ -165,6 +165,11 @@ def cmd_reindex(argv):
|
|
|
165
165
|
stats = rag.build(force=args.force)
|
|
166
166
|
dense_stats = None
|
|
167
167
|
if args.dense:
|
|
168
|
+
# Imported lazily (only on `--dense`) so the optional dense/embedding
|
|
169
|
+
# stack never loads for the common offline commands this module also
|
|
170
|
+
# holds — count, stats, trending, plain search. See the import-budget
|
|
171
|
+
# gate (scripts/import_budget.py).
|
|
172
|
+
from ..core import embed
|
|
168
173
|
with spin.Spinner("embedding chunks into the dense store"):
|
|
169
174
|
dense_stats = _reindex_dense(args.force)
|
|
170
175
|
if args.as_json:
|
|
@@ -192,6 +197,9 @@ def cmd_reindex(argv):
|
|
|
192
197
|
|
|
193
198
|
def _reindex_dense(force):
|
|
194
199
|
"""Build the dense vector store; returns stats or None when unavailable."""
|
|
200
|
+
# Local import: the dense/embedding engines are opt-in (`search --dense`),
|
|
201
|
+
# so they stay out of startup for every other command in this module.
|
|
202
|
+
from ..core import dense, embed
|
|
195
203
|
if not dense.have_backend() or not embed.available():
|
|
196
204
|
return None
|
|
197
205
|
return dense.build(force=force)
|
|
@@ -224,6 +224,7 @@ scripts/ensure_eval_corpus.sh
|
|
|
224
224
|
scripts/eval_explain.py
|
|
225
225
|
scripts/eval_recommend.py
|
|
226
226
|
scripts/eval_retrieval.py
|
|
227
|
+
scripts/import_budget.py
|
|
227
228
|
scripts/mutation_gate.py
|
|
228
229
|
style/README.md
|
|
229
230
|
style/boost.css
|
|
@@ -282,6 +283,7 @@ tests/unit/test_errors_and_cli_table.py
|
|
|
282
283
|
tests/unit/test_frontmatter.py
|
|
283
284
|
tests/unit/test_gitutil.py
|
|
284
285
|
tests/unit/test_imperative.py
|
|
286
|
+
tests/unit/test_import_budget.py
|
|
285
287
|
tests/unit/test_injectscan.py
|
|
286
288
|
tests/unit/test_journal.py
|
|
287
289
|
tests/unit/test_lockfile.py
|
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
id: startup-and-import-time-budget-x-importtime
|
|
3
3
|
board: code
|
|
4
4
|
section: compat
|
|
5
|
-
status:
|
|
5
|
+
status: shipped
|
|
6
6
|
category: Perf · Startup
|
|
7
7
|
complexity: M
|
|
8
8
|
impact: High
|
|
9
9
|
wow: 4
|
|
10
10
|
note: lazy-import guard
|
|
11
11
|
order: 5
|
|
12
|
-
owner:
|
|
13
|
-
pr:
|
|
12
|
+
owner: loop/import-budget
|
|
13
|
+
pr: 179
|
|
14
14
|
title: Startup & import-time budget — <code>-X importtime</code>
|
|
15
15
|
---
|
|
16
16
|
For a CLI, cold-start latency <em>is</em> the UX — every command pays it.
|
|
@@ -1787,7 +1787,7 @@ and the work stays visible.</p>
|
|
|
1787
1787
|
</article>
|
|
1788
1788
|
|
|
1789
1789
|
<article class="cap rcard">
|
|
1790
|
-
<div class="head"><span class="pill
|
|
1790
|
+
<div class="head"><span class="pill shipped">Shipped</span><span class="cat">Perf · Startup</span></div>
|
|
1791
1791
|
<h3>Startup & import-time budget — <code>-X importtime</code></h3>
|
|
1792
1792
|
<p>For a CLI, cold-start latency <em>is</em> the UX — every command pays it.
|
|
1793
1793
|
A gate on <code>python -X importtime boost</code> catches the accidental
|
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Startup import-time budget — the lazy-import guard.
|
|
3
|
+
|
|
4
|
+
For a CLI, cold-start latency *is* the UX: every command pays it before it does
|
|
5
|
+
anything. This gate runs ``python -X importtime`` for a set of common, fully
|
|
6
|
+
offline commands and asserts that a denylist of heavy or optional-only modules
|
|
7
|
+
never gets imported at startup.
|
|
8
|
+
|
|
9
|
+
The classic regression it catches is the accidental *top-level* import of an
|
|
10
|
+
optional dependency — the ``[rag]`` stack (``sqlite_vec``), an embedding/AI SDK,
|
|
11
|
+
or a scientific-python tree — that a hot path only ever needs lazily. boost is
|
|
12
|
+
architected so those load inside the one function that needs them (e.g.
|
|
13
|
+
``search --dense``); this gate keeps it that way.
|
|
14
|
+
|
|
15
|
+
Deliberately name-based, not timing-based: a denylisted module is either
|
|
16
|
+
imported or it isn't, identically on a fast laptop and a slow, differently
|
|
17
|
+
CPU-throttled CI runner across every Python version — so the gate is
|
|
18
|
+
deterministic and never flakes. A coarse module-count ceiling is reported as an
|
|
19
|
+
advisory only (stdlib import graphs differ across Python versions), never a hard
|
|
20
|
+
failure.
|
|
21
|
+
|
|
22
|
+
Usage:
|
|
23
|
+
python scripts/import_budget.py # exit 1 if anything leaked
|
|
24
|
+
python scripts/import_budget.py --list # also print each command's count
|
|
25
|
+
"""
|
|
26
|
+
from __future__ import annotations
|
|
27
|
+
|
|
28
|
+
import os
|
|
29
|
+
import subprocess
|
|
30
|
+
import sys
|
|
31
|
+
import tempfile
|
|
32
|
+
from pathlib import Path
|
|
33
|
+
from typing import Dict, List, Set
|
|
34
|
+
|
|
35
|
+
ROOT = Path(__file__).resolve().parent.parent
|
|
36
|
+
|
|
37
|
+
# Common commands that must stay lean. All are fully offline and touch the core
|
|
38
|
+
# dispatch + store/catalog paths, so a leak anywhere in that surface is caught.
|
|
39
|
+
COMMANDS: List[List[str]] = [["--help"], ["--version"], ["list"], ["count"]]
|
|
40
|
+
|
|
41
|
+
# Modules that must NEVER load for the commands above. Heavy C extensions,
|
|
42
|
+
# scientific-python, and the embedding/AI SDKs — plus boost's own optional-only
|
|
43
|
+
# engines, which stay lazy behind `search --dense`. A leak means a hot path grew
|
|
44
|
+
# a top-level import of an optional dependency.
|
|
45
|
+
DENYLIST: Set[str] = {
|
|
46
|
+
# the [rag] extra's native dependency
|
|
47
|
+
"sqlite_vec",
|
|
48
|
+
# scientific-python / vector libs an embedding backend might drag in
|
|
49
|
+
"numpy", "scipy", "pandas", "torch", "transformers",
|
|
50
|
+
"sentence_transformers", "faiss",
|
|
51
|
+
# embedding / LLM provider SDKs (boost talks to them over stdlib urllib,
|
|
52
|
+
# so none of these should ever import at startup)
|
|
53
|
+
"openai", "voyageai", "anthropic", "cohere",
|
|
54
|
+
"langchain", "langchain_core", "langchain_community",
|
|
55
|
+
"ragas", "ranx",
|
|
56
|
+
# boost's own optional-only engines
|
|
57
|
+
"boost_cli.core.dense", "boost_cli.core.embed",
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
# Advisory ceiling on total modules imported by a single command — reported, not
|
|
61
|
+
# enforced (import graphs legitimately differ across Python versions/platforms).
|
|
62
|
+
SOFT_MODULE_CEILING = 260
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
def parse_modules(importtime_stderr: str) -> Set[str]:
|
|
66
|
+
"""Module names from ``python -X importtime`` stderr.
|
|
67
|
+
|
|
68
|
+
Each line is ``import time: <self> | <cumulative> | <indent><module>``; the
|
|
69
|
+
module name is the third ``|``-delimited field with its nesting indent
|
|
70
|
+
stripped. The header line (``self [us] | cumulative | imported package``)
|
|
71
|
+
has no numeric first field and is skipped.
|
|
72
|
+
"""
|
|
73
|
+
modules: Set[str] = set()
|
|
74
|
+
for line in importtime_stderr.splitlines():
|
|
75
|
+
if "import time:" not in line:
|
|
76
|
+
continue
|
|
77
|
+
_, _, rest = line.partition("import time:")
|
|
78
|
+
parts = rest.split("|")
|
|
79
|
+
if len(parts) != 3:
|
|
80
|
+
continue
|
|
81
|
+
if not parts[0].strip().isdigit(): # the header row
|
|
82
|
+
continue
|
|
83
|
+
name = parts[2].strip()
|
|
84
|
+
if name:
|
|
85
|
+
modules.add(name)
|
|
86
|
+
return modules
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def imported_modules(command: List[str]) -> Set[str]:
|
|
90
|
+
"""The set of modules imported when running ``boost <command>``.
|
|
91
|
+
|
|
92
|
+
Runs in a subprocess with a throwaway ``$HOME`` so a real ``~/.boost`` can
|
|
93
|
+
never influence which modules load (or leave state behind), and with
|
|
94
|
+
``PYTHONPATH`` pointed at the repo so no editable install is required.
|
|
95
|
+
"""
|
|
96
|
+
env = dict(os.environ)
|
|
97
|
+
with tempfile.TemporaryDirectory(prefix="boost-import-budget-") as home:
|
|
98
|
+
env["HOME"] = home
|
|
99
|
+
env["PYTHONPATH"] = str(ROOT)
|
|
100
|
+
env["BOOST_NO_AI"] = "1"
|
|
101
|
+
env.pop("BOOST_HOME", None)
|
|
102
|
+
proc = subprocess.run(
|
|
103
|
+
[sys.executable, "-X", "importtime", "-c",
|
|
104
|
+
"from boost_cli.cli import main; main(%r)" % (command,)],
|
|
105
|
+
cwd=str(ROOT), env=env, capture_output=True, text=True,
|
|
106
|
+
)
|
|
107
|
+
return parse_modules(proc.stderr)
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
def leaks_for(modules: Set[str]) -> List[str]:
|
|
111
|
+
"""Sorted denylisted modules present in ``modules`` (empty = clean)."""
|
|
112
|
+
return sorted(DENYLIST & modules)
|
|
113
|
+
|
|
114
|
+
|
|
115
|
+
def check() -> Dict[str, dict]:
|
|
116
|
+
"""Run every command; return ``{label: {"leaks": [...], "count": int}}``."""
|
|
117
|
+
report: Dict[str, dict] = {}
|
|
118
|
+
for command in COMMANDS:
|
|
119
|
+
mods = imported_modules(command)
|
|
120
|
+
report["boost " + " ".join(command)] = {
|
|
121
|
+
"leaks": leaks_for(mods),
|
|
122
|
+
"count": len(mods),
|
|
123
|
+
}
|
|
124
|
+
return report
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
def main(argv: List[str] | None = None) -> int:
|
|
128
|
+
argv = list(sys.argv[1:] if argv is None else argv)
|
|
129
|
+
show_counts = "--list" in argv
|
|
130
|
+
report = check()
|
|
131
|
+
|
|
132
|
+
failed = False
|
|
133
|
+
for label, data in report.items():
|
|
134
|
+
if data["leaks"]:
|
|
135
|
+
failed = True
|
|
136
|
+
print("import-budget: FAIL %s imported %s"
|
|
137
|
+
% (label, ", ".join(data["leaks"])))
|
|
138
|
+
if show_counts:
|
|
139
|
+
print(" %-16s %d modules" % (label, data["count"]))
|
|
140
|
+
if data["count"] > SOFT_MODULE_CEILING:
|
|
141
|
+
print("import-budget: note — %s imported %d modules (advisory "
|
|
142
|
+
"ceiling %d); check for a new heavy dependency"
|
|
143
|
+
% (label, data["count"], SOFT_MODULE_CEILING))
|
|
144
|
+
|
|
145
|
+
if failed:
|
|
146
|
+
print("\nimport-budget: heavy/optional modules must stay lazy — move "
|
|
147
|
+
"the import inside the function that needs it (see "
|
|
148
|
+
"scripts/import_budget.py DENYLIST).")
|
|
149
|
+
return 1
|
|
150
|
+
print("import-budget: OK — no heavy/optional module imported by %d common "
|
|
151
|
+
"commands" % len(COMMANDS))
|
|
152
|
+
return 0
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
if __name__ == "__main__":
|
|
156
|
+
sys.exit(main())
|
|
@@ -0,0 +1,135 @@
|
|
|
1
|
+
"""Unit tests: scripts/import_budget.py — the startup lazy-import guard.
|
|
2
|
+
|
|
3
|
+
The pure parsing/denylist logic is tested directly; a single integration test
|
|
4
|
+
runs the real gate over the live interpreter so a genuine leak (a heavy module
|
|
5
|
+
newly imported at startup) fails here too, not just in CI.
|
|
6
|
+
"""
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import importlib.util
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
|
|
12
|
+
import pytest
|
|
13
|
+
|
|
14
|
+
_SCRIPT = Path(__file__).resolve().parents[2] / "scripts" / "import_budget.py"
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def _load():
|
|
18
|
+
spec = importlib.util.spec_from_file_location("import_budget", _SCRIPT)
|
|
19
|
+
mod = importlib.util.module_from_spec(spec)
|
|
20
|
+
spec.loader.exec_module(mod)
|
|
21
|
+
return mod
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
pytestmark = pytest.mark.skipif(
|
|
25
|
+
not _SCRIPT.exists(), reason="repo-root scripts/ not reachable (e.g. mutation sandbox)")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
# A realistic slice of `python -X importtime` stderr (the real header + rows).
|
|
29
|
+
_SAMPLE = """\
|
|
30
|
+
import time: self [us] | cumulative | imported package
|
|
31
|
+
import time: 120 | 120 | _io
|
|
32
|
+
import time: 200 | 900 | urllib.request
|
|
33
|
+
import time: 90 | 90 | http.client
|
|
34
|
+
import time: 300 | 1200 | boost_cli.cli
|
|
35
|
+
import time: 150 | 150 | sqlite_vec
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
class TestParseModules:
|
|
40
|
+
def test_extracts_names_and_skips_header(self):
|
|
41
|
+
mod = _load()
|
|
42
|
+
names = mod.parse_modules(_SAMPLE)
|
|
43
|
+
assert "urllib.request" in names
|
|
44
|
+
assert "boost_cli.cli" in names
|
|
45
|
+
assert "sqlite_vec" in names
|
|
46
|
+
# the header row ("self [us] | cumulative | imported package") is not a
|
|
47
|
+
# module and must not be captured
|
|
48
|
+
assert "imported package" not in names
|
|
49
|
+
assert "cumulative" not in names
|
|
50
|
+
|
|
51
|
+
def test_strips_nesting_indent(self):
|
|
52
|
+
mod = _load()
|
|
53
|
+
# deeply nested rows keep only the dotted module name, no leading spaces
|
|
54
|
+
names = mod.parse_modules("import time: 90 | 90 | a.b.c\n")
|
|
55
|
+
assert names == {"a.b.c"}
|
|
56
|
+
|
|
57
|
+
def test_ignores_non_importtime_lines(self):
|
|
58
|
+
mod = _load()
|
|
59
|
+
noise = "some other stderr line\nWARNING: whatever\n"
|
|
60
|
+
assert mod.parse_modules(noise) == set()
|
|
61
|
+
|
|
62
|
+
def test_ignores_malformed_rows(self):
|
|
63
|
+
mod = _load()
|
|
64
|
+
# a row missing the third field yields nothing rather than a bad name
|
|
65
|
+
assert mod.parse_modules("import time: 10 | 10\n") == set()
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
class TestLeaksFor:
|
|
69
|
+
def test_flags_denylisted_modules_only(self):
|
|
70
|
+
mod = _load()
|
|
71
|
+
present = {"json", "os", "sqlite_vec", "boost_cli.core.dense", "urllib.request"}
|
|
72
|
+
assert mod.leaks_for(present) == ["boost_cli.core.dense", "sqlite_vec"]
|
|
73
|
+
|
|
74
|
+
def test_clean_set_has_no_leaks(self):
|
|
75
|
+
mod = _load()
|
|
76
|
+
assert mod.leaks_for({"json", "os", "boost_cli.cli", "urllib.request"}) == []
|
|
77
|
+
|
|
78
|
+
def test_result_is_sorted(self):
|
|
79
|
+
mod = _load()
|
|
80
|
+
present = {"ranx", "anticipation", "numpy", "torch"}
|
|
81
|
+
assert mod.leaks_for(present) == sorted(mod.DENYLIST & present)
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
class TestMain:
|
|
85
|
+
def test_returns_1_and_reports_on_leak(self, monkeypatch, capsys):
|
|
86
|
+
mod = _load()
|
|
87
|
+
monkeypatch.setattr(mod, "check", lambda: {
|
|
88
|
+
"boost count": {"leaks": ["sqlite_vec"], "count": 210},
|
|
89
|
+
})
|
|
90
|
+
rc = mod.main([])
|
|
91
|
+
out = capsys.readouterr().out
|
|
92
|
+
assert rc == 1
|
|
93
|
+
assert "FAIL" in out and "sqlite_vec" in out and "boost count" in out
|
|
94
|
+
|
|
95
|
+
def test_returns_0_when_clean(self, monkeypatch, capsys):
|
|
96
|
+
mod = _load()
|
|
97
|
+
monkeypatch.setattr(mod, "check", lambda: {
|
|
98
|
+
"boost --help": {"leaks": [], "count": 177},
|
|
99
|
+
})
|
|
100
|
+
rc = mod.main([])
|
|
101
|
+
assert rc == 0
|
|
102
|
+
assert "OK" in capsys.readouterr().out
|
|
103
|
+
|
|
104
|
+
def test_list_flag_prints_counts(self, monkeypatch, capsys):
|
|
105
|
+
mod = _load()
|
|
106
|
+
monkeypatch.setattr(mod, "check", lambda: {
|
|
107
|
+
"boost list": {"leaks": [], "count": 201},
|
|
108
|
+
})
|
|
109
|
+
mod.main(["--list"])
|
|
110
|
+
assert "201 modules" in capsys.readouterr().out
|
|
111
|
+
|
|
112
|
+
def test_soft_ceiling_is_advisory_not_fatal(self, monkeypatch, capsys):
|
|
113
|
+
mod = _load()
|
|
114
|
+
over = mod.SOFT_MODULE_CEILING + 50
|
|
115
|
+
monkeypatch.setattr(mod, "check", lambda: {
|
|
116
|
+
"boost --help": {"leaks": [], "count": over},
|
|
117
|
+
})
|
|
118
|
+
rc = mod.main([])
|
|
119
|
+
# a high module count is a note, not a failure (import graphs differ
|
|
120
|
+
# across Python versions/platforms)
|
|
121
|
+
assert rc == 0
|
|
122
|
+
assert "advisory ceiling" in capsys.readouterr().out
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
class TestIntegration:
|
|
126
|
+
def test_live_startup_has_no_heavy_imports(self):
|
|
127
|
+
"""The real gate over this interpreter must be clean — a genuine
|
|
128
|
+
regression (a heavy module imported at startup) fails the suite here."""
|
|
129
|
+
mod = _load()
|
|
130
|
+
report = mod.check()
|
|
131
|
+
offenders = {label: data["leaks"]
|
|
132
|
+
for label, data in report.items() if data["leaks"]}
|
|
133
|
+
assert not offenders, (
|
|
134
|
+
"heavy/optional modules leaked into startup: %s — keep the import "
|
|
135
|
+
"lazy (see scripts/import_budget.py)" % offenders)
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
{boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/entry_points.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|