boost-skill-cli 1.0.135__tar.gz → 1.0.136__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 (289) hide show
  1. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/PKG-INFO +4 -3
  2. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/README.md +3 -2
  3. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/_version.py +2 -2
  4. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/configuration.py +1 -0
  5. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/discovery.py +7 -2
  6. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/pkg.py +44 -16
  7. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/adapters.py +55 -11
  8. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/rag.py +19 -0
  9. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/store.py +51 -3
  10. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_skill_cli.egg-info/PKG-INFO +4 -3
  11. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_skill_cli.egg-info/SOURCES.txt +1 -0
  12. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/adapters.html +9 -4
  13. boost_skill_cli-1.0.136/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +27 -0
  14. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap.html +24 -1
  15. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/examples/README.md +5 -2
  16. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/examples/adapt-demo.sh +16 -10
  17. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_adapt.py +29 -0
  18. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_discovery.py +41 -16
  19. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_pkg.py +36 -1
  20. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_everyday_loop.py +1 -1
  21. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_adapters.py +108 -0
  22. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_rag.py +38 -0
  23. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_store.py +59 -1
  24. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/.gitattributes +0 -0
  25. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/.gitignore +0 -0
  26. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/CLAUDE.md +0 -0
  27. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/CONTRIBUTING.md +0 -0
  28. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/LICENSE +0 -0
  29. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/MANIFEST.in +0 -0
  30. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/Makefile +0 -0
  31. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/SECURITY.md +0 -0
  32. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost +0 -0
  33. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/__init__.py +0 -0
  34. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/__main__.py +0 -0
  35. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/cli.py +0 -0
  36. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/cliparse.py +0 -0
  37. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/__init__.py +0 -0
  38. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/bmad.py +0 -0
  39. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/hooks.py +0 -0
  40. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/info.py +0 -0
  41. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/intelligence.py +0 -0
  42. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/quality.py +0 -0
  43. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/taps.py +0 -0
  44. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/commands/team.py +0 -0
  45. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/__init__.py +0 -0
  46. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/agents.py +0 -0
  47. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/ai.py +0 -0
  48. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/catalog.py +0 -0
  49. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/claude_settings.py +0 -0
  50. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/config.py +0 -0
  51. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/dense.py +0 -0
  52. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/embed.py +0 -0
  53. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/frontmatter.py +0 -0
  54. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/gitutil.py +0 -0
  55. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/imperative.py +0 -0
  56. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/injectscan.py +0 -0
  57. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/journal.py +0 -0
  58. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/lockfile.py +0 -0
  59. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/logs.py +0 -0
  60. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/mcp.py +0 -0
  61. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/nethttp.py +0 -0
  62. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/output.py +0 -0
  63. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/paths.py +0 -0
  64. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/policy.py +0 -0
  65. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/registry.py +0 -0
  66. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/rules.py +0 -0
  67. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/secretscan.py +0 -0
  68. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/serve.py +0 -0
  69. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/stackprobe.py +0 -0
  70. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/staleness.py +0 -0
  71. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/typosquat.py +0 -0
  72. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/updatediff.py +0 -0
  73. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/util.py +0 -0
  74. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/core/workflows.py +0 -0
  75. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/data/registries.json +0 -0
  76. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/errors.py +0 -0
  77. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_cli/spin.py +0 -0
  78. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  79. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  80. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_skill_cli.egg-info/requires.txt +0 -0
  81. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/boost_skill_cli.egg-info/top_level.txt +0 -0
  82. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/.claude/settings.local.json +0 -0
  83. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/DEBUGGING.md +0 -0
  84. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/demo.gif +0 -0
  85. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/demo.tape +0 -0
  86. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/design-roadmap.html +0 -0
  87. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/eval.html +0 -0
  88. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/index.html +0 -0
  89. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/mcp-hub.html +0 -0
  90. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/rag-architecture.md +0 -0
  91. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D01.md +0 -0
  92. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D02.md +0 -0
  93. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D03.md +0 -0
  94. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D04.md +0 -0
  95. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D05.md +0 -0
  96. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D06.md +0 -0
  97. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D07.md +0 -0
  98. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D08.md +0 -0
  99. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D09.md +0 -0
  100. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D10.md +0 -0
  101. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D11.md +0 -0
  102. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D12.md +0 -0
  103. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D13.md +0 -0
  104. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D14.md +0 -0
  105. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D15.md +0 -0
  106. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D16.md +0 -0
  107. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D17.md +0 -0
  108. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D18.md +0 -0
  109. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D19.md +0 -0
  110. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D20.md +0 -0
  111. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D21.md +0 -0
  112. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D22.md +0 -0
  113. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D23.md +0 -0
  114. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D24.md +0 -0
  115. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D25.md +0 -0
  116. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/BOOST-D26.md +0 -0
  117. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
  118. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
  119. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
  120. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
  121. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
  122. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
  123. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
  124. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
  125. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
  126. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
  127. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
  128. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/command-reference-docs-site.md +0 -0
  129. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
  130. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
  131. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
  132. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
  133. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
  134. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
  135. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
  136. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
  137. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
  138. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
  139. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
  140. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
  141. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
  142. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
  143. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
  144. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
  145. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
  146. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
  147. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
  148. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/html-validation-html-validate.md +0 -0
  149. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
  150. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
  151. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
  152. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
  153. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
  154. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
  155. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
  156. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
  157. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
  158. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
  159. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
  160. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
  161. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
  162. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
  163. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
  164. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
  165. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
  166. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
  167. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
  168. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
  169. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
  170. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
  171. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
  172. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
  173. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
  174. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
  175. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
  176. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
  177. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
  178. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
  179. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
  180. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
  181. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
  182. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
  183. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
  184. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
  185. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
  186. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
  187. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
  188. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
  189. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
  190. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
  191. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
  192. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
  193. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
  194. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
  195. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
  196. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
  197. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
  198. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
  199. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
  200. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
  201. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
  202. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
  203. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
  204. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/typo-detection-codespell.md +0 -0
  205. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
  206. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
  207. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
  208. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/update-diff-before-apply.md +0 -0
  209. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
  210. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
  211. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
  212. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
  213. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
  214. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
  215. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
  216. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/docs/roadmap/items/workspace-scope-install.md +0 -0
  217. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/index.html +0 -0
  218. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/pyproject.toml +0 -0
  219. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/scripts/build_registries.py +0 -0
  220. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/scripts/build_roadmap.py +0 -0
  221. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/scripts/ensure_eval_corpus.sh +0 -0
  222. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/scripts/eval_explain.py +0 -0
  223. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/scripts/eval_recommend.py +0 -0
  224. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/scripts/eval_retrieval.py +0 -0
  225. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/scripts/mutation_gate.py +0 -0
  226. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/setup.cfg +0 -0
  227. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/style/README.md +0 -0
  228. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/style/boost.css +0 -0
  229. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/style/boost.js +0 -0
  230. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/style/demo.html +0 -0
  231. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/conftest.py +0 -0
  232. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/eval/baseline.json +0 -0
  233. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/eval/explain.jsonl +0 -0
  234. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/eval/golden.jsonl +0 -0
  235. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/eval/recommend.jsonl +0 -0
  236. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/eval/taps.txt +0 -0
  237. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_bmad.py +0 -0
  238. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_configuration.py +0 -0
  239. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_hooks.py +0 -0
  240. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_info.py +0 -0
  241. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_intelligence.py +0 -0
  242. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_quality.py +0 -0
  243. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_taps.py +0 -0
  244. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_cli_team.py +0 -0
  245. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/functional/test_property_parsers.py +0 -0
  246. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/make_fixture.py +0 -0
  247. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/smoke.sh +0 -0
  248. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_agents.py +0 -0
  249. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_ai.py +0 -0
  250. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_catalog.py +0 -0
  251. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_claude_settings.py +0 -0
  252. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_cliparse.py +0 -0
  253. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_config.py +0 -0
  254. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_dense.py +0 -0
  255. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_dense_fallback.py +0 -0
  256. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_docs_pages_linked.py +0 -0
  257. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_embed.py +0 -0
  258. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_errors_and_cli_table.py +0 -0
  259. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_frontmatter.py +0 -0
  260. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_gitutil.py +0 -0
  261. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_imperative.py +0 -0
  262. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_injectscan.py +0 -0
  263. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_journal.py +0 -0
  264. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_lockfile.py +0 -0
  265. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_logs.py +0 -0
  266. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_mcp.py +0 -0
  267. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_mutation_hardening.py +0 -0
  268. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_nethttp.py +0 -0
  269. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_output.py +0 -0
  270. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_paths.py +0 -0
  271. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_pkg_confusions.py +0 -0
  272. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_pkg_injection.py +0 -0
  273. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_pkg_secrets.py +0 -0
  274. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_policy.py +0 -0
  275. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_registries_fresh.py +0 -0
  276. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_registry.py +0 -0
  277. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_roadmap_fresh.py +0 -0
  278. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_rules.py +0 -0
  279. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_secretscan.py +0 -0
  280. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_serve.py +0 -0
  281. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_spin.py +0 -0
  282. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_stackprobe.py +0 -0
  283. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_staleness.py +0 -0
  284. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_token_parity.py +0 -0
  285. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_typosquat.py +0 -0
  286. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_updatediff.py +0 -0
  287. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_util.py +0 -0
  288. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_version.py +0 -0
  289. {boost_skill_cli-1.0.135 → boost_skill_cli-1.0.136}/tests/unit/test_workflows.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.135
3
+ Version: 1.0.136
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -766,8 +766,9 @@ boost tap --defaults # pull in the 5 starter registries
766
766
  ```
767
767
 
768
768
  The default install is **zero-dependency** (pure stdlib). `boost search` and the
769
- `boost_search` MCP tool rank results with a built-in full-content BM25 engine
770
- (run `boost reindex` once to build the index). For optional **dense semantic
769
+ `boost_search` MCP tool rank results with a built-in full-content BM25 engine
770
+ the index builds automatically on your first search, so BM25 is the default with
771
+ no setup (`boost reindex` just forces a rebuild). For optional **dense semantic
771
772
  search**, install the `[rag]` extra and set an embeddings key — retrieval then
772
773
  embeds every skill and ranks by vector similarity, falling back to BM25 whenever
773
774
  the extra or key is absent:
@@ -54,8 +54,9 @@ boost tap --defaults # pull in the 5 starter registries
54
54
  ```
55
55
 
56
56
  The default install is **zero-dependency** (pure stdlib). `boost search` and the
57
- `boost_search` MCP tool rank results with a built-in full-content BM25 engine
58
- (run `boost reindex` once to build the index). For optional **dense semantic
57
+ `boost_search` MCP tool rank results with a built-in full-content BM25 engine
58
+ the index builds automatically on your first search, so BM25 is the default with
59
+ no setup (`boost reindex` just forces a rebuild). For optional **dense semantic
59
60
  search**, install the `[rag]` extra and set an embeddings key — retrieval then
60
61
  embeds every skill and ranks by vector similarity, falling back to BM25 whenever
61
62
  the extra or key is absent:
@@ -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.135'
22
- __version_tuple__ = version_tuple = (1, 0, 135)
21
+ __version__ = version = '1.0.136'
22
+ __version_tuple__ = version_tuple = (1, 0, 136)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -745,6 +745,7 @@ REGISTRY = mcp.Registry()
745
745
 
746
746
  def _tool_search(args: dict):
747
747
  query = str(args.get("query", ""))
748
+ rag.ensure() # build the full-content index on first use (BM25 by default)
748
749
  rag_result = rag.search(query, limit=10)
749
750
  if rag_result is not None: # full-content index is built
750
751
  hits, _ranker = rag_result
@@ -91,9 +91,14 @@ def cmd_search(argv):
91
91
  if not registry.list_taps():
92
92
  raise BoostError("no taps configured — nothing to search",
93
93
  hint="add the recommended registries with `boost tap --defaults`")
94
- # Prefer the full-content (RAG) index when it exists; otherwise fall back
95
- # to the frontmatter search so nothing regresses before `boost reindex`.
94
+ # Full-content (RAG) search is the default: build the index on first use so
95
+ # every user gets BM25 ranking without having to know about `boost reindex`.
96
+ # rag.ensure() is incremental, offline, and degrades to frontmatter search
97
+ # if the build fails — so a search never hard-fails on an indexing problem.
96
98
  use_rag = rag.ready()
99
+ if not use_rag:
100
+ with spin.Spinner("building the search index (first run)"):
101
+ use_rag = rag.ensure()
97
102
  if use_rag:
98
103
  scored = [(h["entry"], h["score"])
99
104
  for h in rag.retrieve(query, k=max(60, args.limit * 4))]
@@ -15,7 +15,7 @@ from pathlib import Path
15
15
  from typing import Dict, List, Optional
16
16
 
17
17
  from .. import cliparse
18
- from ..core import (adapters, agents, catalog, frontmatter, gitutil,
18
+ from ..core import (adapters, agents, catalog, config, frontmatter, gitutil,
19
19
  injectscan, journal, lockfile, paths, registry,
20
20
  secretscan, staleness, store, typosquat, updatediff, util)
21
21
  from ..core import output as out
@@ -66,36 +66,51 @@ def _check_agents(names: Optional[List[str]]) -> Optional[List[str]]:
66
66
  return names
67
67
 
68
68
 
69
+ def _scan_label(res: store.InstallResult) -> str:
70
+ """What was scanned, for the warning text: skills ship a SKILL.md; rules and
71
+ workflows ship a single file, so name the kind instead."""
72
+ return "SKILL.md" if res.kind == "skill" else "%s content" % res.kind
73
+
74
+
75
+ def _scan_findings(res: store.InstallResult, scanner):
76
+ """Findings for the content boost just installed. Skills scan their
77
+ SKILL.md; rules/workflows scan the raw source (res.scan_text) — the exact
78
+ Markdown that landed, not a non-existent SKILL.md under the dest file."""
79
+ if res.scan_text is not None:
80
+ return scanner.scan_text(res.scan_text)
81
+ return scanner.scan_file(res.dest / "SKILL.md")
82
+
83
+
69
84
  def _warn_injection(res: store.InstallResult) -> None:
70
- """Flag prompt-injection / risky-content patterns in the skill just copied.
85
+ """Flag prompt-injection / risky-content patterns in what was just installed.
71
86
 
72
- boost installs Markdown the agent then executes, so the installed
73
- ``SKILL.md`` is scanned (core.injectscan) and any hits are surfaced worst
74
- -first. Advisory only — it warns, it never blocks the install.
87
+ boost installs Markdown the agent then executes, so the installed content is
88
+ scanned (core.injectscan) and any hits are surfaced worst-first. Advisory
89
+ only — it warns, it never blocks the install.
75
90
  """
76
- findings = injectscan.scan_file(res.dest / "SKILL.md")
91
+ findings = _scan_findings(res, injectscan)
77
92
  if not findings:
78
93
  return
79
- out.warn("%s: %d suspicious pattern%s in SKILL.md (%s) — review before use"
94
+ out.warn("%s: %d suspicious pattern%s in %s (%s) — review before use"
80
95
  % (res.name, len(findings), "" if len(findings) == 1 else "s",
81
- injectscan.worst_severity(findings)))
96
+ _scan_label(res), injectscan.worst_severity(findings)))
82
97
  for f in findings[:3]:
83
98
  out.warn(" L%d [%s] %s" % (f.line, f.severity, f.description))
84
99
 
85
100
 
86
101
  def _warn_secrets(res: store.InstallResult) -> None:
87
- """Flag embedded credentials / secrets in the skill just copied.
102
+ """Flag embedded credentials / secrets in what was just installed.
88
103
 
89
- Scans the installed ``SKILL.md`` (core.secretscan) for known secret shapes
90
- and surfaces any hits worst-first, with the secret value redacted. Advisory
104
+ Scans the installed content (core.secretscan) for known secret shapes and
105
+ surfaces any hits worst-first, with the secret value redacted. Advisory
91
106
  only — it warns, it never blocks the install.
92
107
  """
93
- findings = secretscan.scan_file(res.dest / "SKILL.md")
108
+ findings = _scan_findings(res, secretscan)
94
109
  if not findings:
95
110
  return
96
- out.warn("%s: %d possible secret%s in SKILL.md (%s) — do not commit"
111
+ out.warn("%s: %d possible secret%s in %s (%s) — do not commit"
97
112
  % (res.name, len(findings), "" if len(findings) == 1 else "s",
98
- secretscan.worst_severity(findings)))
113
+ _scan_label(res), secretscan.worst_severity(findings)))
99
114
  for f in findings[:3]:
100
115
  out.warn(" L%d [%s] %s" % (f.line, f.severity, f.description))
101
116
 
@@ -106,6 +121,7 @@ def _report_result(res: store.InstallResult) -> None:
106
121
  out.ok("materialized → %s" % (" · ".join(res.linked) or "(no enabled agents)"))
107
122
  out.ok("lock updated (.skill-lock.json)")
108
123
  _warn_injection(res)
124
+ _warn_secrets(res)
109
125
  return
110
126
  out.ok("copied to %s" % _tilde(res.dest))
111
127
  if res.linked:
@@ -268,6 +284,7 @@ _PLAN_LABELS = [
268
284
  ("missing_links", "missing agent links"),
269
285
  ("stale_links", "stale links"),
270
286
  ("orphaned_store", "orphaned store dirs"),
287
+ ("missing_materializations", "missing rule/workflow files"),
271
288
  ]
272
289
 
273
290
 
@@ -297,6 +314,8 @@ def cmd_sync(argv: List[str]) -> int:
297
314
  for item in plan[key]:
298
315
  if key == "missing_links":
299
316
  out.info("%s → %s" % (item[0], item[1]))
317
+ elif key == "missing_materializations":
318
+ out.info("%s %s" % (item[0], item[1])) # (kind, name)
300
319
  else:
301
320
  out.info(_tilde(item))
302
321
  return 0
@@ -1020,14 +1039,22 @@ def cmd_adapt(argv: List[str]) -> int:
1020
1039
  ap.add_argument("name", help="skill to adapt")
1021
1040
  ap.add_argument("--to", metavar="FRAMEWORK", required=True,
1022
1041
  help="target framework: %s" % ", ".join(adapters.formats()))
1042
+ ap.add_argument("--model", metavar="M", default=None,
1043
+ help="LLM the exported agent runs on (default: boost's "
1044
+ "ai.model; pass 'none' for the framework's own default)")
1023
1045
  ap.add_argument("-o", "--out", metavar="FILE",
1024
1046
  help="write to FILE instead of stdout")
1025
1047
  args = ap.parse_args(argv)
1026
1048
  if args.to not in adapters.FORMATS:
1027
1049
  raise BoostError("unknown framework: %s" % args.to,
1028
1050
  hint="supported: %s" % ", ".join(adapters.formats()))
1051
+ # Default to boost's configured model so exported agents run on the same LLM
1052
+ # boost uses; `--model none` opts out and lets the framework pick.
1053
+ model = args.model if args.model is not None else str(config.get("ai.model") or "")
1054
+ if model.strip().lower() in ("none", "off", ""):
1055
+ model = None
1029
1056
  display, description, body = _resolve_skill_source(args.name)
1030
- source = adapters.render(args.to, display, description, body)
1057
+ source = adapters.render(args.to, display, description, body, model)
1031
1058
  if args.out:
1032
1059
  dest = paths.expand(args.out)
1033
1060
  try:
@@ -1035,7 +1062,8 @@ def cmd_adapt(argv: List[str]) -> int:
1035
1062
  except OSError as e:
1036
1063
  raise BoostError("cannot write %s: %s" % (_tilde(dest), e.strerror or e),
1037
1064
  hint="check the output path exists and is writable")
1038
- out.ok("adapted %s → %s (%s)" % (display, _tilde(dest.resolve()), args.to))
1065
+ out.ok("adapted %s → %s (%s · %s)" % (display, _tilde(dest.resolve()),
1066
+ args.to, model or "framework default"))
1039
1067
  else:
1040
1068
  sys.stdout.write(source)
1041
1069
  return 0
@@ -18,11 +18,11 @@ from __future__ import annotations
18
18
  import json
19
19
  import keyword
20
20
  import re
21
- from typing import Callable, Dict, List
21
+ from typing import Callable, Dict, List, Optional
22
22
 
23
23
  # Public: the format id shown in `--to`/errors -> its renderer.
24
24
  # Populated at the bottom once the render_* functions are defined.
25
- FORMATS: Dict[str, "Callable[[str, str, str], str]"] = {}
25
+ FORMATS: Dict[str, "Callable[..., str]"] = {}
26
26
 
27
27
 
28
28
  def formats() -> List[str]:
@@ -30,12 +30,15 @@ def formats() -> List[str]:
30
30
  return sorted(FORMATS)
31
31
 
32
32
 
33
- def render(fmt: str, name: str, description: str, body: str) -> str:
33
+ def render(fmt: str, name: str, description: str, body: str,
34
+ model: Optional[str] = None) -> str:
34
35
  """Dispatch to the renderer for `fmt`. Raises KeyError on unknown fmt.
35
36
 
36
- The command layer turns that into a friendly BoostError listing formats().
37
+ `model` (a boost/LiteLLM model id) wires the emitted agent to a specific
38
+ LLM; when falsy the agent inherits its framework's default provider. The
39
+ command layer turns a KeyError into a BoostError listing formats().
37
40
  """
38
- return FORMATS[fmt](name, description, body)
41
+ return FORMATS[fmt](name, description, body, model)
39
42
 
40
43
 
41
44
  # --- shared helpers -------------------------------------------------------
@@ -68,47 +71,88 @@ def _clean(text: str) -> str:
68
71
  return text.strip()
69
72
 
70
73
 
74
+ def _litellm_model(model: str) -> str:
75
+ """Normalize a boost model id to a LiteLLM `provider/model` string.
76
+
77
+ boost's AI bridge is Anthropic (the `claude` CLI / Anthropic API), so a bare
78
+ Claude id like `claude-haiku-4-5-20251001` gets an `anthropic/` prefix.
79
+ A value that already names a provider (`anthropic/…`, `openai/gpt-4o`) is
80
+ passed through unchanged. Both CrewAI and the Agents SDK route through
81
+ LiteLLM, so this one form serves both.
82
+ """
83
+ m = model.strip()
84
+ return m if "/" in m else "anthropic/" + m
85
+
86
+
71
87
  # --- renderers ------------------------------------------------------------
72
88
 
73
- def render_crewai(name: str, description: str, body: str) -> str:
74
- """A CrewAI Agent: role=name, goal=description, backstory=instructions."""
89
+ def render_crewai(name: str, description: str, body: str,
90
+ model: Optional[str] = None) -> str:
91
+ """A CrewAI Agent: role=name, goal=description, backstory=instructions.
92
+
93
+ With `model`, pins the agent's LLM via `crewai.LLM` (LiteLLM under the
94
+ hood); without it, the agent uses CrewAI's default provider.
95
+ """
75
96
  var = _ident(name)
97
+ imports = "from crewai import Agent\n"
98
+ llm = ""
99
+ if model:
100
+ imports = "from crewai import Agent, LLM\n"
101
+ llm = " llm=LLM(model=%s),\n" % _py_str(_litellm_model(model))
76
102
  return (
77
103
  "# Generated by `boost adapt %s --to crewai`. Do not edit by hand.\n"
78
- "from crewai import Agent\n"
104
+ "%s"
79
105
  "\n"
80
106
  "%s = Agent(\n"
81
107
  " role=%s,\n"
82
108
  " goal=%s,\n"
83
109
  " backstory=%s,\n"
110
+ "%s"
84
111
  ")\n"
85
112
  ) % (
86
113
  name,
114
+ imports,
87
115
  var,
88
116
  _py_str(name),
89
117
  _py_str(_clean(description)),
90
118
  _py_str(_clean(body)),
119
+ llm,
91
120
  )
92
121
 
93
122
 
94
- def render_agents_sdk(name: str, description: str, body: str) -> str:
95
- """An OpenAI Agents SDK Agent: instructions carry the skill body."""
123
+ def render_agents_sdk(name: str, description: str, body: str,
124
+ model: Optional[str] = None) -> str:
125
+ """An OpenAI Agents SDK Agent: instructions carry the skill body.
126
+
127
+ With `model`, pins the agent's LLM via the SDK's LiteLLM extension
128
+ (`pip install "openai-agents[litellm]"`); without it, the agent uses the
129
+ SDK's default OpenAI model.
130
+ """
96
131
  var = _ident(name)
132
+ imports = "from agents import Agent\n"
133
+ llm = ""
134
+ if model:
135
+ imports = ("from agents import Agent\n"
136
+ "from agents.extensions.models.litellm_model import LitellmModel\n")
137
+ llm = " model=LitellmModel(model=%s),\n" % _py_str(_litellm_model(model))
97
138
  return (
98
139
  "# Generated by `boost adapt %s --to agents-sdk`. Do not edit by hand.\n"
99
- "from agents import Agent\n"
140
+ "%s"
100
141
  "\n"
101
142
  "%s = Agent(\n"
102
143
  " name=%s,\n"
103
144
  " handoff_description=%s,\n"
104
145
  " instructions=%s,\n"
146
+ "%s"
105
147
  ")\n"
106
148
  ) % (
107
149
  name,
150
+ imports,
108
151
  var,
109
152
  _py_str(name),
110
153
  _py_str(_clean(description)),
111
154
  _py_str(_clean(body)),
155
+ llm,
112
156
  )
113
157
 
114
158
 
@@ -303,6 +303,25 @@ def ready() -> bool:
303
303
  return bool(raw and raw.get("docs"))
304
304
 
305
305
 
306
+ def ensure() -> bool:
307
+ """Ensure a usable full-content index exists, building it on first use.
308
+
309
+ This makes BM25 search the default for every surface (CLI + MCP) without the
310
+ user having to run ``boost reindex`` first. Returns True when RAG is usable.
311
+ Never raises: with no taps, or if the build fails, it returns False so the
312
+ caller degrades to frontmatter search instead of erroring.
313
+ """
314
+ if ready():
315
+ return True
316
+ if not registry.list_taps():
317
+ return False
318
+ try:
319
+ build()
320
+ except Exception: # noqa: BLE001 — degrade to heuristic, never crash search
321
+ return False
322
+ return ready()
323
+
324
+
306
325
  def _bm25(query_terms: List[str], raw: dict) -> Dict[int, float]:
307
326
  docs = raw["docs"]
308
327
  n = len(docs)
@@ -26,6 +26,10 @@ class InstallResult:
26
26
  score: int = 0
27
27
  upgraded: bool = False
28
28
  kind: str = "skill"
29
+ # For rules/workflows the installed content is a single file (or a merged
30
+ # CLAUDE.md block), not a SKILL.md tree — carry the raw source so the caller
31
+ # scans exactly what it installed instead of a non-existent SKILL.md.
32
+ scan_text: Optional[str] = None
29
33
 
30
34
 
31
35
  def skill_store_dir(name: str) -> Path:
@@ -233,7 +237,7 @@ def _install_rule(entry: dict, force: bool = False,
233
237
  res = InstallResult(
234
238
  name=name,
235
239
  dest=Path(materializations[0]["path"]) if materializations else paths.store_dir(),
236
- kind="rule")
240
+ kind="rule", scan_text=raw)
237
241
  res.linked = linked
238
242
  res.upgraded = existing is not None
239
243
  return res
@@ -322,7 +326,7 @@ def _install_workflow(entry: dict, force: bool = False,
322
326
  res = InstallResult(
323
327
  name=name,
324
328
  dest=Path(materializations[0]["path"]) if materializations else paths.store_dir(),
325
- kind="workflow")
329
+ kind="workflow", scan_text=raw)
326
330
  res.linked = linked
327
331
  res.upgraded = existing is not None
328
332
  return res
@@ -408,7 +412,8 @@ def sync_plan() -> Dict[str, list]:
408
412
  """
409
413
  lock = lockfile.installed()
410
414
  plan: dict[str, list] = {"missing_store": [], "missing_links": [],
411
- "stale_links": [], "orphaned_store": []}
415
+ "stale_links": [], "orphaned_store": [],
416
+ "missing_materializations": []}
412
417
  for name, entry in lock.items():
413
418
  sdir = skill_store_dir(name)
414
419
  if not sdir.is_dir():
@@ -434,9 +439,34 @@ def sync_plan() -> Dict[str, list]:
434
439
  link.resolve() if link.exists() else link.readlink())
435
440
  if not link.exists() or (points_into_store and link.name not in lock):
436
441
  plan["stale_links"].append(str(link))
442
+ # Rules/workflows don't live in the store — they materialize into agent dirs.
443
+ # A materialization whose file (or CLAUDE.md block) is gone can be repaired
444
+ # by re-materializing from the tap, same as a missing skill store dir.
445
+ for name, entry in lockfile.installed_rules().items():
446
+ if any(not _rule_materialization_ok(name, m)
447
+ for m in entry.get("materializations") or []):
448
+ plan["missing_materializations"].append(("rule", name))
449
+ for name, entry in lockfile.installed_workflows().items():
450
+ if any(not Path(m.get("path", "")).is_file()
451
+ for m in entry.get("materializations") or []):
452
+ plan["missing_materializations"].append(("workflow", name))
437
453
  return plan
438
454
 
439
455
 
456
+ def _rule_materialization_ok(name: str, m: dict) -> bool:
457
+ """True if a rule materialization is still present: a file drop must exist,
458
+ and a Claude rule's CLAUDE.md must still carry its managed block."""
459
+ from . import rules
460
+ p = Path(m.get("path", ""))
461
+ if m.get("mode") == rules.MODE_CLAUDE:
462
+ try:
463
+ return p.exists() and ("boost:rule:%s start" % name) in \
464
+ p.read_text(encoding="utf-8")
465
+ except OSError:
466
+ return False
467
+ return p.is_file()
468
+
469
+
440
470
  def sync_apply(plan: Dict[str, list]) -> List[str]:
441
471
  """Fix what sync_plan found. Returns human-readable actions taken."""
442
472
  actions = []
@@ -466,6 +496,24 @@ def sync_apply(plan: Dict[str, list]) -> List[str]:
466
496
  if not restored:
467
497
  lockfile.remove_skill(name)
468
498
  actions.append("dropped %s from lock (store dir missing, source gone)" % name)
499
+ for kind, name in plan.get("missing_materializations", []):
500
+ getter = lockfile.get_rule if kind == "rule" else lockfile.get_workflow
501
+ entry = getter(name) or {}
502
+ tap_name = entry.get("tap")
503
+ if tap_name and tap_name != "local":
504
+ try:
505
+ from . import catalog
506
+ matches = [e for e in catalog.find(name)
507
+ if e["tap"] == tap_name and e.get("kind", "skill") == kind]
508
+ if matches:
509
+ install(matches[0], force=True)
510
+ actions.append("re-materialized %s %s from %s"
511
+ % (kind, name, tap_name))
512
+ continue
513
+ except BoostError:
514
+ pass
515
+ actions.append("%s %s has a missing materialization but its source is "
516
+ "gone — run `boost update` or reinstall" % (kind, name))
469
517
  if actions:
470
518
  journal.log("sync", "%d fixes" % len(actions))
471
519
  return actions
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.135
3
+ Version: 1.0.136
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -766,8 +766,9 @@ boost tap --defaults # pull in the 5 starter registries
766
766
  ```
767
767
 
768
768
  The default install is **zero-dependency** (pure stdlib). `boost search` and the
769
- `boost_search` MCP tool rank results with a built-in full-content BM25 engine
770
- (run `boost reindex` once to build the index). For optional **dense semantic
769
+ `boost_search` MCP tool rank results with a built-in full-content BM25 engine
770
+ the index builds automatically on your first search, so BM25 is the default with
771
+ no setup (`boost reindex` just forces a rebuild). For optional **dense semantic
771
772
  search**, install the `[rag]` extra and set an embeddings key — retrieval then
772
773
  embeds every skill and ranks by vector similarity, falling back to BM25 whenever
773
774
  the extra or key is absent:
@@ -179,6 +179,7 @@ docs/roadmap/items/rule-install-native-materialization.md
179
179
  docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md
180
180
  docs/roadmap/items/sbom-aware-scanning-osv-scanner.md
181
181
  docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md
182
+ docs/roadmap/items/scan-and-sync-rules-and-workflows.md
182
183
  docs/roadmap/items/second-type-checker-pyright.md
183
184
  docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md
184
185
  docs/roadmap/items/secret-scanning-gitleaks-push-protection.md
@@ -311,10 +311,15 @@ code_reviewer = <span class="fn">Agent</span>(
311
311
  boost adapt code-reviewer --to crewai -o reviewer.py
312
312
 
313
313
  <span class="c"># 2 — in a throwaway venv, install the framework and load it</span>
314
- python3 -m venv /tmp/crew && /tmp/crew/bin/pip install crewai
315
- /tmp/crew/bin/python -c <span class="s">"import reviewer; print(reviewer.code_reviewer.role)"</span>
316
- <span class="c"># → code-reviewer ✦ the emitted file imported and instantiated</span></pre>
317
- <p class="sec-sub" style="margin-top:22px">Supported targets today: <code>crewai</code>,
314
+ python3 -m venv /tmp/crew && /tmp/crew/bin/pip install <span class="s">"crewai[anthropic]"</span>
315
+ /tmp/crew/bin/python -c <span class="s">"import reviewer; print(reviewer.code_reviewer.role, reviewer.code_reviewer.llm.model)"</span>
316
+ <span class="c"># → code-reviewer claude-haiku-4-5-20251001imported, instantiated, on boost's model</span></pre>
317
+ <p class="sec-sub" style="margin-top:22px"><b>Runs on boost's model by default.</b> With no
318
+ <code>--model</code>, the exported agent is wired to boost's configured <code>ai.model</code>
319
+ (Claude) via each framework's LiteLLM path — so it runs on the same LLM boost uses, no OpenAI key.
320
+ Override with <code>--model openai/gpt-4o</code>, or <code>--model none</code> for the framework's
321
+ own default. (The <code>[anthropic]</code>/<code>[litellm]</code> extras carry that provider.)</p>
322
+ <p class="sec-sub" style="margin-top:14px">Supported targets today: <code>crewai</code>,
318
323
  <code>agents-sdk</code>. Adding another framework is one <code>render_*</code> function plus a row in
319
324
  the <code>FORMATS</code> registry and its golden test.</p>
320
325
  </div>
@@ -0,0 +1,27 @@
1
+ ---
2
+ id: scan-and-sync-rules-and-workflows
3
+ board: code
4
+ section: internals
5
+ status: shipped
6
+ category: Install engine · Safety
7
+ complexity: M
8
+ impact: Med
9
+ wow: 2
10
+ note: close the last skill-only gaps for rules/workflows
11
+ order: 26
12
+ owner: loop/scan-sync-all-kinds
13
+ pr: 160
14
+ title: Scan and <code>sync</code> rules/workflows like skills
15
+ ---
16
+ Two skill-only gaps remained after rule (<code>#141</code>) / workflow
17
+ (<code>#150</code>) install: the install-time injection + secret scan
18
+ read <code>res.dest/SKILL.md</code>, which doesn't exist for a
19
+ rule/workflow (a single file / merged block), so their executable
20
+ Markdown went unscanned; and <code>boost sync</code> only reconciled
21
+ skills, so a deleted rule/workflow materialization couldn't be
22
+ repaired. Fix both: carry the raw source on the install result
23
+ (<code>scan_text</code>) so injectscan/secretscan see exactly what was
24
+ installed, and extend <code>sync_plan</code>/<code>sync_apply</code>
25
+ with a <code>missing_materializations</code> pass that re-materializes
26
+ a rule/workflow from its tap when a drop file or CLAUDE.md block is
27
+ gone — mirroring the missing-store-dir repair for skills.
@@ -118,7 +118,7 @@
118
118
  <div class="stat"><b>16</b><span>Shipped</span></div>
119
119
  <div class="stat"><b>1</b><span>Next up</span></div>
120
120
  <div class="stat"><b>4</b><span>Planned</span></div>
121
- <div class="stat"><b>100</b><span>Loop finds</span></div>
121
+ <div class="stat"><b>101</b><span>Loop finds</span></div>
122
122
  <!-- /ROADMAP:stats -->
123
123
  </div>
124
124
  </section>
@@ -817,6 +817,29 @@ chunks instead cost ~70%.</p>
817
817
  <span class="m">update was skill-only after rule/workflow install</span>
818
818
  </div>
819
819
  </article>
820
+
821
+ <article class="cap rcard">
822
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Install engine · Safety</span></div>
823
+ <h3>Scan and <code>sync</code> rules/workflows like skills</h3>
824
+ <p>Two skill-only gaps remained after rule (<code>#141</code>) / workflow
825
+ (<code>#150</code>) install: the install-time injection + secret scan
826
+ read <code>res.dest/SKILL.md</code>, which doesn't exist for a
827
+ rule/workflow (a single file / merged block), so their executable
828
+ Markdown went unscanned; and <code>boost sync</code> only reconciled
829
+ skills, so a deleted rule/workflow materialization couldn't be
830
+ repaired. Fix both: carry the raw source on the install result
831
+ (<code>scan_text</code>) so injectscan/secretscan see exactly what was
832
+ installed, and extend <code>sync_plan</code>/<code>sync_apply</code>
833
+ with a <code>missing_materializations</code> pass that re-materializes
834
+ a rule/workflow from its tap when a drop file or CLAUDE.md block is
835
+ gone — mirroring the missing-store-dir repair for skills.</p>
836
+ <div class="meta">
837
+ <span class="m">Complexity <b>M</b></span>
838
+ <span class="m">Impact <b>Med</b></span>
839
+ <span class="m">Wow <b class="wow">★★</b></span>
840
+ <span class="m">close the last skill-only gaps for rules/workflows</span>
841
+ </div>
842
+ </article>
820
843
  <!-- /ROADMAP:cards -->
821
844
 
822
845
  </div>
@@ -19,11 +19,14 @@ What it does (all offline — **no `OPENAI_API_KEY` needed**):
19
19
  2. Authors **one** `SKILL.md` and imports it into boost.
20
20
  3. **Value 1** — renders it to *both* frameworks and instantiates each:
21
21
  a real `crewai.Agent` and a real `agents.Agent` from the same source, no
22
- hand-porting.
22
+ hand-porting. Both are wired to **boost's configured `ai.model` (Claude)** by
23
+ default, so they run on the same LLM boost uses — no OpenAI key. Override per
24
+ run with `boost adapt … --model openai/gpt-4o`, or `--model none` for the
25
+ framework's own default.
23
26
  4. **Value 2** — edits the skill **once** and re-adapts; the change appears in
24
27
  **both** generated files (before/after `0 0` → `1 1`). That is the
25
28
  drift-killing payoff: one edit, every runtime current.
26
- 5. Optional: if `OPENAI_API_KEY` is set, actually runs the agent.
29
+ 5. Optional: if `ANTHROPIC_API_KEY` is set, actually runs the agent on Claude.
27
30
 
28
31
  Requirements: **Python 3.11–3.13** (CrewAI's `tiktoken` dependency has no 3.14
29
32
  wheel yet; boost itself supports 3.9–3.14). Clean up with