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.
Files changed (317) hide show
  1. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/Makefile +1 -0
  2. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/PKG-INFO +1 -1
  3. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/_version.py +2 -2
  4. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/discovery.py +9 -1
  5. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/PKG-INFO +1 -1
  6. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/SOURCES.txt +2 -0
  7. {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
  8. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap.html +1 -1
  9. boost_skill_cli-1.0.155/scripts/import_budget.py +156 -0
  10. boost_skill_cli-1.0.155/tests/unit/test_import_budget.py +135 -0
  11. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/.gitattributes +0 -0
  12. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/.gitignore +0 -0
  13. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/CLAUDE.md +0 -0
  14. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/CONTRIBUTING.md +0 -0
  15. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/LICENSE +0 -0
  16. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/MANIFEST.in +0 -0
  17. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/README.md +0 -0
  18. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/SECURITY.md +0 -0
  19. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost +0 -0
  20. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/__init__.py +0 -0
  21. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/__main__.py +0 -0
  22. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/cli.py +0 -0
  23. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/cliparse.py +0 -0
  24. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/__init__.py +0 -0
  25. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/bmad.py +0 -0
  26. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/configuration.py +0 -0
  27. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/hooks.py +0 -0
  28. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/info.py +0 -0
  29. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/intelligence.py +0 -0
  30. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/pkg.py +0 -0
  31. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/quality.py +0 -0
  32. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/taps.py +0 -0
  33. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/commands/team.py +0 -0
  34. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/__init__.py +0 -0
  35. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/adapters.py +0 -0
  36. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/agents.py +0 -0
  37. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/ai.py +0 -0
  38. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/catalog.py +0 -0
  39. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/claude_settings.py +0 -0
  40. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/config.py +0 -0
  41. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/dense.py +0 -0
  42. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/embed.py +0 -0
  43. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/frontmatter.py +0 -0
  44. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/gitutil.py +0 -0
  45. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/imperative.py +0 -0
  46. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/injectscan.py +0 -0
  47. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/journal.py +0 -0
  48. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/lockfile.py +0 -0
  49. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/logs.py +0 -0
  50. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/mcp.py +0 -0
  51. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/nethttp.py +0 -0
  52. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/output.py +0 -0
  53. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/paths.py +0 -0
  54. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/policy.py +0 -0
  55. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/rag.py +0 -0
  56. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/registry.py +0 -0
  57. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/rules.py +0 -0
  58. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/secretscan.py +0 -0
  59. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/serve.py +0 -0
  60. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/stackprobe.py +0 -0
  61. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/staleness.py +0 -0
  62. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/store.py +0 -0
  63. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/typosquat.py +0 -0
  64. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/updatediff.py +0 -0
  65. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/util.py +0 -0
  66. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/core/workflows.py +0 -0
  67. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/data/registries.json +0 -0
  68. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/errors.py +0 -0
  69. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_cli/spin.py +0 -0
  70. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  71. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  72. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/requires.txt +0 -0
  73. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/boost_skill_cli.egg-info/top_level.txt +0 -0
  74. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/.claude/settings.local.json +0 -0
  75. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/DEBUGGING.md +0 -0
  76. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/adapters.html +0 -0
  77. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/demo.gif +0 -0
  78. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/demo.tape +0 -0
  79. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/design-roadmap.html +0 -0
  80. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/eval.html +0 -0
  81. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/index.html +0 -0
  82. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/mcp-hub.html +0 -0
  83. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/rag-architecture.md +0 -0
  84. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D01.md +0 -0
  85. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D02.md +0 -0
  86. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D03.md +0 -0
  87. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D04.md +0 -0
  88. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D05.md +0 -0
  89. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D06.md +0 -0
  90. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D07.md +0 -0
  91. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D08.md +0 -0
  92. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D09.md +0 -0
  93. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D10.md +0 -0
  94. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D11.md +0 -0
  95. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D12.md +0 -0
  96. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D13.md +0 -0
  97. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D14.md +0 -0
  98. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D15.md +0 -0
  99. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D16.md +0 -0
  100. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D17.md +0 -0
  101. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D18.md +0 -0
  102. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D19.md +0 -0
  103. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D20.md +0 -0
  104. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D21.md +0 -0
  105. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D22.md +0 -0
  106. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D23.md +0 -0
  107. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D24.md +0 -0
  108. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D25.md +0 -0
  109. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/BOOST-D26.md +0 -0
  110. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
  111. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
  112. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
  113. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
  114. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/boost-run-live-agents.md +0 -0
  115. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
  116. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
  117. {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
  118. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
  119. {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
  120. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
  121. {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
  122. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/command-reference-docs-site.md +0 -0
  123. {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
  124. {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
  125. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
  126. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
  127. {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
  128. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
  129. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
  130. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
  131. {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
  132. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
  133. {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
  134. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
  135. {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
  136. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
  137. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
  138. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
  139. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
  140. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
  141. {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
  142. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
  143. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
  144. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/html-validation-html-validate.md +0 -0
  145. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
  146. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
  147. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
  148. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
  149. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
  150. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
  151. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
  152. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
  153. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
  154. {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
  155. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
  156. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
  157. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
  158. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
  159. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
  160. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
  161. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
  162. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
  163. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
  164. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
  165. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
  166. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
  167. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
  168. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
  169. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
  170. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
  171. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
  172. {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
  173. {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
  174. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
  175. {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
  176. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
  177. {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
  178. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
  179. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
  180. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
  181. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
  182. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
  183. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
  184. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
  185. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
  186. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
  187. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
  188. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
  189. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
  190. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
  191. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
  192. {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
  193. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
  194. {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
  195. {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
  196. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
  197. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
  198. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
  199. {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
  200. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
  201. {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
  202. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
  203. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
  204. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/typo-detection-codespell.md +0 -0
  205. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
  206. {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
  207. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
  208. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/update-diff-before-apply.md +0 -0
  209. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
  210. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
  211. {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
  212. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
  213. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
  214. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
  215. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
  216. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/docs/roadmap/items/workspace-scope-install.md +0 -0
  217. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/examples/README.md +0 -0
  218. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/examples/adapt-demo.sh +0 -0
  219. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/examples/boost-run-prototype.sh +0 -0
  220. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/index.html +0 -0
  221. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/pyproject.toml +0 -0
  222. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/bench_cli.sh +0 -0
  223. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/build_registries.py +0 -0
  224. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/build_roadmap.py +0 -0
  225. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/ensure_eval_corpus.sh +0 -0
  226. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/eval_explain.py +0 -0
  227. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/eval_recommend.py +0 -0
  228. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/eval_retrieval.py +0 -0
  229. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/scripts/mutation_gate.py +0 -0
  230. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/setup.cfg +0 -0
  231. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/style/README.md +0 -0
  232. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/style/boost.css +0 -0
  233. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/style/boost.js +0 -0
  234. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/style/demo.html +0 -0
  235. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/adapt.feature +0 -0
  236. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/browse.feature +0 -0
  237. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/count.feature +0 -0
  238. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/discover.feature +0 -0
  239. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/doctor.feature +0 -0
  240. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/environment.py +0 -0
  241. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/explain.feature +0 -0
  242. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/index.feature +0 -0
  243. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/install.feature +0 -0
  244. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/list.feature +0 -0
  245. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/mcp.feature +0 -0
  246. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/search.feature +0 -0
  247. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/steps/cli_steps.py +0 -0
  248. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/steps/discovery_steps.py +0 -0
  249. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/steps/mcp_steps.py +0 -0
  250. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/bdd/features/steps/quality_steps.py +0 -0
  251. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/conftest.py +0 -0
  252. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/baseline.json +0 -0
  253. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/explain.jsonl +0 -0
  254. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/golden.jsonl +0 -0
  255. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/recommend.jsonl +0 -0
  256. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/eval/taps.txt +0 -0
  257. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_adapt.py +0 -0
  258. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_bmad.py +0 -0
  259. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_configuration.py +0 -0
  260. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_discovery.py +0 -0
  261. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_hooks.py +0 -0
  262. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_info.py +0 -0
  263. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_intelligence.py +0 -0
  264. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_pkg.py +0 -0
  265. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_quality.py +0 -0
  266. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_taps.py +0 -0
  267. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_cli_team.py +0 -0
  268. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_everyday_loop.py +0 -0
  269. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/functional/test_property_parsers.py +0 -0
  270. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/make_fixture.py +0 -0
  271. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/perf/test_benchmarks.py +0 -0
  272. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/smoke.sh +0 -0
  273. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_adapters.py +0 -0
  274. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_agents.py +0 -0
  275. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_ai.py +0 -0
  276. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_catalog.py +0 -0
  277. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_claude_settings.py +0 -0
  278. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_cliparse.py +0 -0
  279. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_config.py +0 -0
  280. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_dense.py +0 -0
  281. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_dense_fallback.py +0 -0
  282. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_docs_pages_linked.py +0 -0
  283. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_embed.py +0 -0
  284. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_errors_and_cli_table.py +0 -0
  285. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_frontmatter.py +0 -0
  286. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_gitutil.py +0 -0
  287. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_imperative.py +0 -0
  288. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_injectscan.py +0 -0
  289. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_journal.py +0 -0
  290. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_lockfile.py +0 -0
  291. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_logs.py +0 -0
  292. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_mcp.py +0 -0
  293. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_mutation_hardening.py +0 -0
  294. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_nethttp.py +0 -0
  295. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_output.py +0 -0
  296. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_paths.py +0 -0
  297. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_pkg_confusions.py +0 -0
  298. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_pkg_injection.py +0 -0
  299. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_pkg_secrets.py +0 -0
  300. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_policy.py +0 -0
  301. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_rag.py +0 -0
  302. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_registries_fresh.py +0 -0
  303. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_registry.py +0 -0
  304. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_roadmap_fresh.py +0 -0
  305. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_rules.py +0 -0
  306. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_secretscan.py +0 -0
  307. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_serve.py +0 -0
  308. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_spin.py +0 -0
  309. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_stackprobe.py +0 -0
  310. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_staleness.py +0 -0
  311. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_store.py +0 -0
  312. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_token_parity.py +0 -0
  313. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_typosquat.py +0 -0
  314. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_updatediff.py +0 -0
  315. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_util.py +0 -0
  316. {boost_skill_cli-1.0.154 → boost_skill_cli-1.0.155}/tests/unit/test_version.py +0 -0
  317. {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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.154
3
+ Version: 1.0.155
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -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.154'
22
- __version_tuple__ = version_tuple = (1, 0, 154)
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, dense, embed, gitutil,
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)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.154
3
+ Version: 1.0.155
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -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: planned
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 &amp; 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 planned">Planned</span><span class="cat">Perf · Startup</span></div>
1790
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Perf · Startup</span></div>
1791
1791
  <h3>Startup &amp; 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)