boost-skill-cli 1.0.199__tar.gz → 1.0.201__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 (374) hide show
  1. {boost_skill_cli-1.0.199/boost_skill_cli.egg-info → boost_skill_cli-1.0.201}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/pkg.py +39 -7
  4. boost_skill_cli-1.0.201/boost_cli/core/adapters.py +564 -0
  5. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201/boost_skill_cli.egg-info}/PKG-INFO +1 -1
  6. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/SOURCES.txt +1 -0
  7. boost_skill_cli-1.0.201/docs/roadmap/items/finish-mutation-hardening-across-core.md +31 -0
  8. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/framework-adapter-multi-agent.md +3 -3
  9. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap.html +19 -7
  10. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_adapt.py +55 -0
  11. boost_skill_cli-1.0.201/tests/unit/test_adapters_multi.py +380 -0
  12. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_agents.py +7 -0
  13. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_ai.py +4 -1
  14. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_catalog.py +40 -0
  15. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_config.py +18 -0
  16. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_lockfile.py +30 -0
  17. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_output.py +6 -0
  18. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_paths.py +13 -0
  19. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_policy.py +35 -0
  20. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_registry.py +13 -0
  21. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_util.py +72 -0
  22. boost_skill_cli-1.0.199/boost_cli/core/adapters.py +0 -294
  23. boost_skill_cli-1.0.199/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -19
  24. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.gitattributes +0 -0
  25. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.gitignore +0 -0
  26. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.gitleaks.toml +0 -0
  27. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.htmlvalidate.json +0 -0
  28. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.lighthouserc.json +0 -0
  29. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.lycheeignore +0 -0
  30. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.markdownlint-cli2.jsonc +0 -0
  31. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.pre-commit-config.yaml +0 -0
  32. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.stylelintrc.json +0 -0
  33. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.vale/styles/boost/Terminology.yml +0 -0
  34. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
  35. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/.vale.ini +0 -0
  36. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/CLAUDE.md +0 -0
  37. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/CONTRIBUTING.md +0 -0
  38. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/LICENSE +0 -0
  39. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/MANIFEST.in +0 -0
  40. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/Makefile +0 -0
  41. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/README.md +0 -0
  42. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/SECURITY.md +0 -0
  43. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost +0 -0
  44. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/__init__.py +0 -0
  45. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/__main__.py +0 -0
  46. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/cli.py +0 -0
  47. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/cliparse.py +0 -0
  48. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/__init__.py +0 -0
  49. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/_common.py +0 -0
  50. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/bmad.py +0 -0
  51. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/configuration.py +0 -0
  52. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/discovery.py +0 -0
  53. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/hooks.py +0 -0
  54. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/info.py +0 -0
  55. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/intelligence.py +0 -0
  56. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/quality.py +0 -0
  57. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/run.py +0 -0
  58. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/safety.py +0 -0
  59. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/taps.py +0 -0
  60. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/commands/team.py +0 -0
  61. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/__init__.py +0 -0
  62. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/agents.py +0 -0
  63. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/ai.py +0 -0
  64. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/capabilities.py +0 -0
  65. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/catalog.py +0 -0
  66. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/claude_settings.py +0 -0
  67. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/config.py +0 -0
  68. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/dense.py +0 -0
  69. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/ed25519.py +0 -0
  70. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/embed.py +0 -0
  71. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/faithfulness.py +0 -0
  72. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/frontmatter.py +0 -0
  73. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/gitutil.py +0 -0
  74. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/imperative.py +0 -0
  75. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/injectscan.py +0 -0
  76. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/integrity.py +0 -0
  77. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/journal.py +0 -0
  78. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/lockfile.py +0 -0
  79. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/logs.py +0 -0
  80. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/mcp.py +0 -0
  81. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/minisign.py +0 -0
  82. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/nethttp.py +0 -0
  83. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/output.py +0 -0
  84. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/paths.py +0 -0
  85. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/policy.py +0 -0
  86. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/projectlock.py +0 -0
  87. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/provenance.py +0 -0
  88. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/rag.py +0 -0
  89. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/registry.py +0 -0
  90. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/rules.py +0 -0
  91. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/scopes.py +0 -0
  92. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/secretscan.py +0 -0
  93. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/serve.py +0 -0
  94. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/stackprobe.py +0 -0
  95. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/staleness.py +0 -0
  96. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/store.py +0 -0
  97. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/typosquat.py +0 -0
  98. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/updatediff.py +0 -0
  99. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/util.py +0 -0
  100. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/core/workflows.py +0 -0
  101. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/data/registries.json +0 -0
  102. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/errors.py +0 -0
  103. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_cli/spin.py +0 -0
  104. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  105. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  106. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/requires.txt +0 -0
  107. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/boost_skill_cli.egg-info/top_level.txt +0 -0
  108. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/.claude/settings.local.json +0 -0
  109. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/DEBUGGING.md +0 -0
  110. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/adapters.html +0 -0
  111. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/commands.html +0 -0
  112. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/demo.gif +0 -0
  113. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/demo.tape +0 -0
  114. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/design-roadmap.html +0 -0
  115. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/eval.html +0 -0
  116. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/index.html +0 -0
  117. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/mcp-hub.html +0 -0
  118. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/rag-architecture.md +0 -0
  119. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D01.md +0 -0
  120. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D02.md +0 -0
  121. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D03.md +0 -0
  122. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D04.md +0 -0
  123. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D05.md +0 -0
  124. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D06.md +0 -0
  125. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D07.md +0 -0
  126. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D08.md +0 -0
  127. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D09.md +0 -0
  128. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D10.md +0 -0
  129. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D11.md +0 -0
  130. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D12.md +0 -0
  131. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D13.md +0 -0
  132. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D14.md +0 -0
  133. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D15.md +0 -0
  134. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D16.md +0 -0
  135. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D17.md +0 -0
  136. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D18.md +0 -0
  137. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D19.md +0 -0
  138. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D20.md +0 -0
  139. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D21.md +0 -0
  140. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D22.md +0 -0
  141. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D23.md +0 -0
  142. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D24.md +0 -0
  143. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D25.md +0 -0
  144. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/BOOST-D26.md +0 -0
  145. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
  146. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
  147. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
  148. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
  149. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/boost-run-live-agents.md +0 -0
  150. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
  151. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
  152. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
  153. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
  154. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
  155. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
  156. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
  157. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/command-reference-docs-site.md +0 -0
  158. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
  159. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
  160. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
  161. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
  162. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
  163. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
  164. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
  165. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
  166. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
  167. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
  168. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
  169. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
  170. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
  171. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
  172. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
  173. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
  174. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
  175. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
  176. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
  177. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/html-validation-html-validate.md +0 -0
  178. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
  179. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
  180. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
  181. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
  182. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
  183. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
  184. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
  185. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
  186. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
  187. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
  188. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
  189. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
  190. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
  191. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
  192. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
  193. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
  194. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
  195. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
  196. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
  197. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
  198. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
  199. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
  200. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
  201. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
  202. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
  203. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
  204. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
  205. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
  206. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
  207. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
  208. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
  209. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
  210. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
  211. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
  212. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
  213. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
  214. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
  215. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
  216. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
  217. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
  218. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
  219. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
  220. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
  221. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
  222. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
  223. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
  224. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
  225. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
  226. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
  227. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
  228. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
  229. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
  230. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
  231. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
  232. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
  233. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
  234. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
  235. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
  236. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
  237. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
  238. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
  239. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
  240. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
  241. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
  242. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/typo-detection-codespell.md +0 -0
  243. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
  244. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
  245. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
  246. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/update-diff-before-apply.md +0 -0
  247. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
  248. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
  249. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
  250. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
  251. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
  252. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
  253. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
  254. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/docs/roadmap/items/workspace-scope-install.md +0 -0
  255. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/eslint.config.mjs +0 -0
  256. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/examples/README.md +0 -0
  257. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/examples/adapt-demo.sh +0 -0
  258. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/examples/boost-run-prototype.sh +0 -0
  259. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/index.html +0 -0
  260. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/noxfile.py +0 -0
  261. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/pyproject.toml +0 -0
  262. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/requirements/lint-tools.txt +0 -0
  263. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/bench_cli.sh +0 -0
  264. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/build_command_reference.py +0 -0
  265. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/build_registries.py +0 -0
  266. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/build_roadmap.py +0 -0
  267. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/check_anchors.py +0 -0
  268. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/ensure_eval_corpus.sh +0 -0
  269. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/eval_explain.py +0 -0
  270. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/eval_recommend.py +0 -0
  271. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/eval_retrieval.py +0 -0
  272. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/eval_stats_summary.py +0 -0
  273. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/import_budget.py +0 -0
  274. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/mutation_gate.py +0 -0
  275. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/scripts/perf_gate.py +0 -0
  276. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/setup.cfg +0 -0
  277. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/style/README.md +0 -0
  278. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/style/boost.css +0 -0
  279. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/style/boost.js +0 -0
  280. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/style/demo.html +0 -0
  281. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/adapt.feature +0 -0
  282. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/browse.feature +0 -0
  283. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/count.feature +0 -0
  284. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/discover.feature +0 -0
  285. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/doctor.feature +0 -0
  286. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/environment.py +0 -0
  287. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/explain.feature +0 -0
  288. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/index.feature +0 -0
  289. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/install.feature +0 -0
  290. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/list.feature +0 -0
  291. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/mcp.feature +0 -0
  292. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/search.feature +0 -0
  293. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/steps/cli_steps.py +0 -0
  294. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/steps/discovery_steps.py +0 -0
  295. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/steps/mcp_steps.py +0 -0
  296. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/bdd/features/steps/quality_steps.py +0 -0
  297. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/conftest.py +0 -0
  298. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/eval/baseline.json +0 -0
  299. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/eval/explain.jsonl +0 -0
  300. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/eval/golden.jsonl +0 -0
  301. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/eval/recommend.jsonl +0 -0
  302. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/eval/taps.txt +0 -0
  303. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_capabilities_policy.py +0 -0
  304. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_bmad.py +0 -0
  305. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_configuration.py +0 -0
  306. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_discovery.py +0 -0
  307. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_hooks.py +0 -0
  308. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_info.py +0 -0
  309. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_intelligence.py +0 -0
  310. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_pkg.py +0 -0
  311. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_quality.py +0 -0
  312. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_taps.py +0 -0
  313. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_cli_team.py +0 -0
  314. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_everyday_loop.py +0 -0
  315. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_integrity_enforce.py +0 -0
  316. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_property_parsers.py +0 -0
  317. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_run.py +0 -0
  318. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_tap_signing.py +0 -0
  319. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/functional/test_workspace_scope.py +0 -0
  320. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/make_fixture.py +0 -0
  321. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/perf/test_benchmarks.py +0 -0
  322. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/smoke.sh +0 -0
  323. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_adapters.py +0 -0
  324. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_adapters_runner.py +0 -0
  325. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_capabilities.py +0 -0
  326. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_check_anchors.py +0 -0
  327. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_claude_settings.py +0 -0
  328. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_cliparse.py +0 -0
  329. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_command_reference_fresh.py +0 -0
  330. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_dense.py +0 -0
  331. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_dense_fallback.py +0 -0
  332. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_docs_pages_linked.py +0 -0
  333. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_ed25519.py +0 -0
  334. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_embed.py +0 -0
  335. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_errors_and_cli_table.py +0 -0
  336. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_eval_stats_summary.py +0 -0
  337. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_faithfulness.py +0 -0
  338. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_frontmatter.py +0 -0
  339. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_gitleaks_config.py +0 -0
  340. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_gitutil.py +0 -0
  341. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_imperative.py +0 -0
  342. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_import_budget.py +0 -0
  343. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_injectscan.py +0 -0
  344. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_integrity.py +0 -0
  345. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_journal.py +0 -0
  346. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_logs.py +0 -0
  347. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_mcp.py +0 -0
  348. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_minisign.py +0 -0
  349. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_mutation_hardening.py +0 -0
  350. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_nethttp.py +0 -0
  351. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_perf_gate.py +0 -0
  352. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_pkg_confusions.py +0 -0
  353. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_pkg_injection.py +0 -0
  354. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_pkg_secrets.py +0 -0
  355. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_projectlock.py +0 -0
  356. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_provenance.py +0 -0
  357. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_rag.py +0 -0
  358. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_registries_fresh.py +0 -0
  359. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_roadmap_fresh.py +0 -0
  360. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_rules.py +0 -0
  361. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_scopes.py +0 -0
  362. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_secretscan.py +0 -0
  363. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_serve.py +0 -0
  364. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_spin.py +0 -0
  365. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_stackprobe.py +0 -0
  366. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_staleness.py +0 -0
  367. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_store.py +0 -0
  368. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_token_parity.py +0 -0
  369. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_typosquat.py +0 -0
  370. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_updatediff.py +0 -0
  371. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_version.py +0 -0
  372. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/unit/test_workflows.py +0 -0
  373. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/visual/package.json +0 -0
  374. {boost_skill_cli-1.0.199 → boost_skill_cli-1.0.201}/tests/visual/visual_check.mjs +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.199
3
+ Version: 1.0.201
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.199'
22
- __version_tuple__ = version_tuple = (1, 0, 199)
21
+ __version__ = version = '1.0.201'
22
+ __version_tuple__ = version_tuple = (1, 0, 201)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -1093,9 +1093,15 @@ def cmd_export(argv: List[str]) -> int:
1093
1093
  return 0
1094
1094
 
1095
1095
 
1096
- def _resolve_skill_source(name: str):
1097
- """(display_name, description, body) for a skill — installed store first,
1098
- then any tap clone. Raises BoostError if the name resolves nowhere."""
1096
+ def _resolve_skill(name: str):
1097
+ """(display, description, body, skill_md_path, meta) for a skill.
1098
+
1099
+ Resolves the installed store first, then any tap clone, and returns the
1100
+ SKILL.md path + parsed frontmatter alongside the display fields so callers
1101
+ that need the skill's directory (e.g. subagent discovery for multi-agent
1102
+ adaptation) don't re-resolve. Raises BoostError if the name resolves
1103
+ nowhere.
1104
+ """
1099
1105
  p = store.skill_store_dir(name) / "SKILL.md"
1100
1106
  if not p.exists():
1101
1107
  entry = catalog.resolve_one(name) # raises BoostError if unknown
@@ -1105,7 +1111,14 @@ def _resolve_skill_source(name: str):
1105
1111
  hint="refresh the tap with `boost update`")
1106
1112
  meta, body = frontmatter.parse(p.read_text(encoding="utf-8", errors="replace"))
1107
1113
  display = str(meta.get("name") or name).strip() or name
1108
- return display, str(meta.get("description") or "").strip(), body
1114
+ return display, str(meta.get("description") or "").strip(), body, p, meta
1115
+
1116
+
1117
+ def _resolve_skill_source(name: str):
1118
+ """(display_name, description, body) for a skill — the text-only view of
1119
+ :func:`_resolve_skill`, used where the skill's directory isn't needed."""
1120
+ display, description, body, _p, _meta = _resolve_skill(name)
1121
+ return display, description, body
1109
1122
 
1110
1123
 
1111
1124
  def cmd_adapt(argv: List[str]) -> int:
@@ -1129,8 +1142,26 @@ def cmd_adapt(argv: List[str]) -> int:
1129
1142
  model = args.model if args.model is not None else str(config.get("ai.model") or "")
1130
1143
  if model.strip().lower() in ("none", "off", ""):
1131
1144
  model = None
1132
- display, description, body = _resolve_skill_source(args.name)
1133
- source = adapters.render(args.to, display, description, body, model)
1145
+ display, description, body, skill_md, meta = _resolve_skill(args.name)
1146
+ # A skill that declares subagents projects to a runnable multi-agent
1147
+ # workflow (a CrewAI Crew / LangGraph StateGraph) when the target supports
1148
+ # one; flat skills — and multi-agent targets without a crew path — keep the
1149
+ # single-Agent render.
1150
+ subagents = adapters.discover_subagents(skill_md.parent)
1151
+ crew_size = 0
1152
+ if subagents and adapters.supports_multi(args.to):
1153
+ primary = adapters.AgentSpec(display, description, body,
1154
+ adapters.parse_tools(meta))
1155
+ source = adapters.render_multi(args.to, display, description,
1156
+ [primary, *subagents], model)
1157
+ crew_size = len(subagents) + 1
1158
+ else:
1159
+ if subagents:
1160
+ sys.stderr.write(
1161
+ "note: %s declares %d subagent(s); %s has no crew/graph path, "
1162
+ "so only its primary agent was rendered.\n"
1163
+ % (display, len(subagents), args.to))
1164
+ source = adapters.render(args.to, display, description, body, model)
1134
1165
  if args.out:
1135
1166
  dest = paths.expand(args.out)
1136
1167
  try:
@@ -1138,8 +1169,9 @@ def cmd_adapt(argv: List[str]) -> int:
1138
1169
  except OSError as e:
1139
1170
  raise BoostError("cannot write %s: %s" % (_tilde(dest), e.strerror or e),
1140
1171
  hint="check the output path exists and is writable") from e
1172
+ shape = "crew of %d" % crew_size if crew_size else args.to
1141
1173
  out.ok("adapted %s → %s (%s · %s)" % (display, _tilde(dest.resolve()),
1142
- args.to, model or "framework default"))
1174
+ shape, model or "framework default"))
1143
1175
  else:
1144
1176
  sys.stdout.write(source)
1145
1177
  return 0
@@ -0,0 +1,564 @@
1
+ """Render a boost skill into another agent framework's native source.
2
+
3
+ boost installs skills as files for editor-style agents (Claude Code, Cursor,
4
+ Windsurf). Frameworks like CrewAI or the OpenAI Agents SDK are *application
5
+ code* — they have no skills directory to install into; an agent is a value
6
+ constructed in a Python source file. `boost adapt <name> --to <framework>`
7
+ bridges that gap by emitting the framework's own idiom.
8
+
9
+ Each renderer is a pure, deterministic string transform: (name, description,
10
+ body) -> valid Python source. No framework is imported here — the emitted text
11
+ is a template, so the stdlib-only, zero-dependency runtime contract holds. The
12
+ generated code's *validity* is what the tests pin (it must `compile()`); whether
13
+ a given framework version accepts the kwargs is verified out-of-gate, with that
14
+ framework installed.
15
+ """
16
+ from __future__ import annotations
17
+
18
+ import collections
19
+ import json
20
+ import keyword
21
+ import re
22
+ from pathlib import Path
23
+ from typing import Callable, Dict, List, Optional
24
+
25
+ from . import frontmatter
26
+
27
+ # Public: the format id shown in `--to`/errors -> its renderer.
28
+ # Populated at the bottom once the render_* functions are defined.
29
+ FORMATS: Dict[str, "Callable[..., str]"] = {}
30
+
31
+ # Subagent (crew member) directories: a Markdown file under one of these, at any
32
+ # depth beneath a skill, is one of the skill's subagents — so both a flat
33
+ # `agents/reviewer.md` and a plugin-style `plugins/x/agents/reviewer.md` match.
34
+ SUBAGENT_DIRS = {"agents", "subagents"}
35
+ # Frontmatter keys a skill/subagent uses to declare the tools it can call.
36
+ _TOOL_KEYS = ("tools", "allowed-tools", "allowed_tools")
37
+
38
+ # One agent in a (possibly multi-agent) skill: its display name, one-line
39
+ # description/role, full instruction body, and declared tool identifiers. Built
40
+ # via collections.namedtuple (an assignment, so interrogate needs no docstring)
41
+ # rather than a NamedTuple subclass.
42
+ AgentSpec = collections.namedtuple("AgentSpec",
43
+ "name description instructions tools")
44
+
45
+
46
+ def formats() -> List[str]:
47
+ """Sorted list of supported target framework ids (for help/errors)."""
48
+ return sorted(FORMATS)
49
+
50
+
51
+ def render(fmt: str, name: str, description: str, body: str,
52
+ model: Optional[str] = None) -> str:
53
+ """Dispatch to the renderer for `fmt`. Raises KeyError on unknown fmt.
54
+
55
+ `model` (a boost/LiteLLM model id) wires the emitted agent to a specific
56
+ LLM; when falsy the agent inherits its framework's default provider. The
57
+ command layer turns a KeyError into a BoostError listing formats().
58
+ """
59
+ return FORMATS[fmt](name, description, body, model)
60
+
61
+
62
+ # --- shared helpers -------------------------------------------------------
63
+
64
+ def _py_str(s: str) -> str:
65
+ """A safely-escaped Python string literal for ANY input.
66
+
67
+ JSON string syntax is a subset of Python's, so json.dumps yields a literal
68
+ that is valid Python too — quotes, backslashes and newlines all escaped —
69
+ with ensure_ascii=False keeping non-ASCII readable (and still valid). This
70
+ is the whole defense against a skill body that contains quotes or `\"\"\"`.
71
+ """
72
+ return json.dumps(s, ensure_ascii=False)
73
+
74
+
75
+ def _ident(name: str) -> str:
76
+ """A safe Python identifier derived from a skill name.
77
+
78
+ `code-reviewer` -> `code_reviewer`; leading digits or a Python keyword get
79
+ an `s_` prefix so the emitted assignment target always parses.
80
+ """
81
+ ident = re.sub(r"\W+", "_", name.strip().lower()).strip("_")
82
+ if not ident or ident[0].isdigit() or keyword.iskeyword(ident):
83
+ ident = "s_" + ident
84
+ return ident
85
+
86
+
87
+ def _clean(text: str) -> str:
88
+ """Collapse trailing whitespace so emitted literals stay tidy."""
89
+ return text.strip()
90
+
91
+
92
+ def _litellm_model(model: str) -> str:
93
+ """Normalize a boost model id to a LiteLLM `provider/model` string.
94
+
95
+ boost's AI bridge is Anthropic (the `claude` CLI / Anthropic API), so a bare
96
+ Claude id like `claude-haiku-4-5-20251001` gets an `anthropic/` prefix.
97
+ A value that already names a provider (`anthropic/…`, `openai/gpt-4o`) is
98
+ passed through unchanged. Both CrewAI and the Agents SDK route through
99
+ LiteLLM, so this one form serves both.
100
+ """
101
+ m = model.strip()
102
+ return m if "/" in m else "anthropic/" + m
103
+
104
+
105
+ def _langchain_model(model: str) -> str:
106
+ """Normalize a boost model id to a LangChain ``init_chat_model`` string.
107
+
108
+ LangGraph's ``create_react_agent`` builds its model via LangChain's
109
+ ``init_chat_model``, which wants ``provider:model`` (colon) — not LiteLLM's
110
+ ``provider/model`` (slash). A bare Claude id gets ``anthropic:``; a
111
+ litellm-style ``anthropic/x`` becomes ``anthropic:x``; a value that already
112
+ uses the colon form passes through.
113
+ """
114
+ m = model.strip()
115
+ if ":" in m:
116
+ return m
117
+ if "/" in m:
118
+ return m.replace("/", ":", 1)
119
+ return "anthropic:" + m
120
+
121
+
122
+ # --- multi-agent detection ------------------------------------------------
123
+
124
+ def parse_tools(meta: dict) -> List[str]:
125
+ """Tool identifiers a skill/subagent declares in its frontmatter.
126
+
127
+ Reads the first present of the ``tools`` / ``allowed-tools`` keys — either a
128
+ YAML list or a comma/space-separated string — normalizes each entry to a
129
+ safe Python identifier via :func:`_ident`, and dedupes preserving first-seen
130
+ order. Returns ``[]`` for a skill that declares no tools (the flat case).
131
+ """
132
+ raw = None
133
+ for key in _TOOL_KEYS:
134
+ if meta.get(key):
135
+ raw = meta[key]
136
+ break
137
+ if raw is None:
138
+ return []
139
+ parts = re.split(r"[,\s]+", raw.strip()) if isinstance(raw, str) else [str(x) for x in raw]
140
+ seen: List[str] = []
141
+ for part in parts:
142
+ part = part.strip()
143
+ if not part:
144
+ continue
145
+ ident = _ident(part)
146
+ # `s_` is _ident's sentinel for a token with no usable characters (e.g.
147
+ # all punctuation) — not a real tool, so drop it.
148
+ if not ident or ident == "s_":
149
+ continue
150
+ if ident not in seen:
151
+ seen.append(ident)
152
+ return seen
153
+
154
+
155
+ def discover_subagents(skill_dir: Path) -> List[AgentSpec]:
156
+ """Discover a skill's subagents for multi-agent adaptation.
157
+
158
+ A subagent is a Markdown file (other than ``SKILL.md``) that lives under an
159
+ ``agents/`` or ``subagents/`` directory anywhere beneath ``skill_dir`` and
160
+ carries both a frontmatter ``name`` and ``description``. Files are visited in
161
+ sorted path order so the emitted crew/graph is deterministic. Returns the
162
+ subagents as :class:`AgentSpec`s — an empty list for a flat single-agent
163
+ skill or a missing directory.
164
+ """
165
+ specs: List[AgentSpec] = []
166
+ if not skill_dir or not skill_dir.is_dir():
167
+ return specs
168
+ for path in sorted(skill_dir.rglob("*.md")):
169
+ if path.name == "SKILL.md":
170
+ continue
171
+ if not (SUBAGENT_DIRS & {part.lower() for part in path.parent.parts}):
172
+ continue
173
+ try:
174
+ meta, body = frontmatter.parse(
175
+ path.read_text(encoding="utf-8", errors="replace"))
176
+ except OSError:
177
+ continue
178
+ name = str(meta.get("name") or "").strip()
179
+ description = str(meta.get("description") or "").strip()
180
+ if not name or not description:
181
+ continue
182
+ specs.append(AgentSpec(name, description, _clean(body), parse_tools(meta)))
183
+ return specs
184
+
185
+
186
+ def _unique_idents(specs: List[AgentSpec]) -> List[str]:
187
+ """A unique Python identifier per spec, in order — two agents whose names
188
+ normalize to the same ident get numeric suffixes so emitted assignments and
189
+ node names never collide."""
190
+ counts: Dict[str, int] = {}
191
+ idents: List[str] = []
192
+ for spec in specs:
193
+ base = _ident(spec.name)
194
+ if base in counts:
195
+ counts[base] += 1
196
+ idents.append("%s_%d" % (base, counts[base]))
197
+ else:
198
+ counts[base] = 0
199
+ idents.append(base)
200
+ return idents
201
+
202
+
203
+ def _unique_tools(specs: List[AgentSpec]) -> List[str]:
204
+ """Union of every spec's declared tools, first-seen order preserved."""
205
+ seen: List[str] = []
206
+ for spec in specs:
207
+ for tool in spec.tools:
208
+ if tool not in seen:
209
+ seen.append(tool)
210
+ return seen
211
+
212
+
213
+ # --- renderers ------------------------------------------------------------
214
+
215
+ def render_crewai(name: str, description: str, body: str,
216
+ model: Optional[str] = None) -> str:
217
+ """A CrewAI Agent: role=name, goal=description, backstory=instructions.
218
+
219
+ With `model`, pins the agent's LLM via `crewai.LLM` (LiteLLM under the
220
+ hood); without it, the agent uses CrewAI's default provider.
221
+ """
222
+ var = _ident(name)
223
+ imports = "from crewai import Agent\n"
224
+ llm = ""
225
+ if model:
226
+ imports = "from crewai import Agent, LLM\n"
227
+ llm = " llm=LLM(model=%s),\n" % _py_str(_litellm_model(model))
228
+ return (
229
+ "# Generated by `boost adapt %s --to crewai`. Do not edit by hand.\n"
230
+ "%s"
231
+ "\n"
232
+ "%s = Agent(\n"
233
+ " role=%s,\n"
234
+ " goal=%s,\n"
235
+ " backstory=%s,\n"
236
+ "%s"
237
+ ")\n"
238
+ ) % (
239
+ name,
240
+ imports,
241
+ var,
242
+ _py_str(name),
243
+ _py_str(_clean(description)),
244
+ _py_str(_clean(body)),
245
+ llm,
246
+ )
247
+
248
+
249
+ def render_agents_sdk(name: str, description: str, body: str,
250
+ model: Optional[str] = None) -> str:
251
+ """An OpenAI Agents SDK Agent: instructions carry the skill body.
252
+
253
+ With `model`, pins the agent's LLM via the SDK's LiteLLM extension
254
+ (`pip install "openai-agents[litellm]"`); without it, the agent uses the
255
+ SDK's default OpenAI model.
256
+ """
257
+ var = _ident(name)
258
+ imports = "from agents import Agent\n"
259
+ llm = ""
260
+ if model:
261
+ imports = ("from agents import Agent\n"
262
+ "from agents.extensions.models.litellm_model import LitellmModel\n")
263
+ llm = " model=LitellmModel(model=%s),\n" % _py_str(_litellm_model(model))
264
+ return (
265
+ "# Generated by `boost adapt %s --to agents-sdk`. Do not edit by hand.\n"
266
+ "%s"
267
+ "\n"
268
+ "%s = Agent(\n"
269
+ " name=%s,\n"
270
+ " handoff_description=%s,\n"
271
+ " instructions=%s,\n"
272
+ "%s"
273
+ ")\n"
274
+ ) % (
275
+ name,
276
+ imports,
277
+ var,
278
+ _py_str(name),
279
+ _py_str(_clean(description)),
280
+ _py_str(_clean(body)),
281
+ llm,
282
+ )
283
+
284
+
285
+ def render_langgraph(name: str, description: str, body: str,
286
+ model: Optional[str] = None) -> str:
287
+ """A LangGraph node factory: prebuilt ``create_react_agent`` bound to the
288
+ skill body as its system prompt.
289
+
290
+ Unlike CrewAI / the Agents SDK, a LangGraph agent isn't one constructor —
291
+ it's a node compiled with a model and dropped into a ``StateGraph``. So we
292
+ emit a *factory* (``make_<name>``) the caller invokes with a model and any
293
+ tools, rather than a module-level value. With `model`, the factory's
294
+ ``model`` argument defaults to the normalized LiteLLM id; without it, the
295
+ caller must supply one (LangGraph has no default provider to inherit).
296
+ """
297
+ var = _ident(name)
298
+ if model:
299
+ sig = "model=%s, tools=None" % _py_str(_langchain_model(model))
300
+ else:
301
+ sig = "model, tools=None"
302
+ return (
303
+ "# Generated by `boost adapt %s --to langgraph`. Do not edit by hand.\n"
304
+ "from langgraph.prebuilt import create_react_agent\n"
305
+ "\n"
306
+ "SYSTEM_PROMPT = %s\n"
307
+ "\n"
308
+ "\n"
309
+ "def make_%s(%s):\n"
310
+ " %s\n"
311
+ " return create_react_agent(model, tools=tools or [], prompt=SYSTEM_PROMPT)\n"
312
+ ) % (
313
+ name,
314
+ _py_str(_clean(body)),
315
+ var,
316
+ sig,
317
+ _py_str(_clean(description)),
318
+ )
319
+
320
+
321
+ FORMATS.update({
322
+ "crewai": render_crewai,
323
+ "agents-sdk": render_agents_sdk,
324
+ "langgraph": render_langgraph,
325
+ })
326
+
327
+
328
+ # --- multi-agent renderers (crew / graph) ---------------------------------
329
+ # A flat skill projects to one Agent (above); a skill that declares subagents
330
+ # projects to a runnable *workflow* — a CrewAI Crew or a LangGraph StateGraph —
331
+ # with one agent per subagent and declared tools surfaced as stubs. Same
332
+ # contract as the single-agent renderers: pure text that must ``compile()``.
333
+
334
+ def _tool_stub(tool: str, decorator: str) -> str:
335
+ """One tool stub — a decorated function that raises until implemented.
336
+
337
+ ``decorator`` is the full decorator line (``@tool`` for LangChain,
338
+ ``@tool("name")`` for CrewAI); the body is a docstring plus a
339
+ ``NotImplementedError`` so the generated module ``compile()``s and fails
340
+ loudly rather than silently no-op'ing if run before the tool is filled in.
341
+ """
342
+ return (
343
+ "%s\n"
344
+ "def %s(argument: str) -> str:\n"
345
+ " %s\n"
346
+ " raise NotImplementedError(%s)\n"
347
+ ) % (decorator, tool,
348
+ _py_str("TODO: implement the %s tool (declared by the skill)." % tool),
349
+ _py_str("boost adapt: implement the '%s' tool" % tool))
350
+
351
+
352
+ def _crew_header(kind: str, workflow: str, description: str) -> str:
353
+ """The two-line generated-file banner (provenance + crew description)."""
354
+ summary = _clean(description).replace("\n", " ") or workflow
355
+ return ("# Generated by `boost adapt %s --to %s`. Do not edit by hand.\n"
356
+ "# %s\n") % (workflow, kind, summary)
357
+
358
+
359
+ def render_crew(workflow: str, description: str, specs: List[AgentSpec],
360
+ model: Optional[str] = None) -> str:
361
+ """Render a multi-agent skill as a CrewAI ``Crew``.
362
+
363
+ Each :class:`AgentSpec` becomes an ``Agent`` (role / goal / backstory) paired
364
+ with a ``Task``, assembled into a sequential ``Crew``. Tools any agent
365
+ declares are surfaced as ``NotImplementedError`` stubs to fill in. `model`
366
+ pins every agent's LLM via ``crewai.LLM``; without it CrewAI's default
367
+ provider is used. ``description`` documents the crew as a whole.
368
+ """
369
+ idents = _unique_idents(specs)
370
+ tools = _unique_tools(specs)
371
+ imports = ["from crewai import Agent, Crew, Process, Task" + (", LLM" if model else "")]
372
+ if tools:
373
+ imports.append("from crewai.tools import tool")
374
+ llm_line = " llm=LLM(model=%s),\n" % _py_str(_litellm_model(model)) if model else ""
375
+
376
+ blocks: List[str] = []
377
+ for ident, spec in zip(idents, specs):
378
+ tline = " tools=[%s],\n" % ", ".join(spec.tools) if spec.tools else ""
379
+ blocks.append(
380
+ "%s = Agent(\n"
381
+ " role=%s,\n"
382
+ " goal=%s,\n"
383
+ " backstory=%s,\n"
384
+ "%s%s"
385
+ ")\n" % (ident, _py_str(_clean(spec.name)),
386
+ _py_str(_clean(spec.description)),
387
+ _py_str(_clean(spec.instructions)), tline, llm_line))
388
+ for ident, spec in zip(idents, specs):
389
+ blocks.append(
390
+ "%s_task = Task(\n"
391
+ " description=%s,\n"
392
+ " expected_output=%s,\n"
393
+ " agent=%s,\n"
394
+ ")\n" % (ident, _py_str(_clean(spec.description)),
395
+ _py_str("The result of the %s step." % _clean(spec.name)), ident))
396
+ crew = ("crew = Crew(\n"
397
+ " agents=[%s],\n"
398
+ " tasks=[%s],\n"
399
+ " process=Process.sequential,\n"
400
+ ")\n") % (", ".join(idents), ", ".join(i + "_task" for i in idents))
401
+
402
+ parts = [_crew_header("crewai", workflow, description), "\n".join(imports) + "\n", "\n"]
403
+ if tools:
404
+ parts.append("\n".join(_tool_stub(t, "@tool(%s)" % _py_str(t)) for t in tools))
405
+ parts.append("\n")
406
+ parts.append("\n".join(blocks))
407
+ parts.append("\n" + crew)
408
+ return "".join(parts)
409
+
410
+
411
+ def render_graph(workflow: str, description: str, specs: List[AgentSpec],
412
+ model: Optional[str] = None) -> str:
413
+ """Render a multi-agent skill as a LangGraph ``StateGraph``.
414
+
415
+ Emits a ``build_<workflow>(model)`` factory that constructs one
416
+ ``create_react_agent`` node per :class:`AgentSpec`, wires them into a
417
+ sequential graph (``START`` → … → ``END``) over ``MessagesState``, and
418
+ returns the compiled graph. Declared tools become ``@tool`` stubs. With
419
+ `model` the factory's ``model`` argument defaults to the normalized LangChain
420
+ id; without it the caller must supply one (LangGraph has no default
421
+ provider). ``description`` documents the graph.
422
+ """
423
+ idents = _unique_idents(specs)
424
+ tools = _unique_tools(specs)
425
+ imports = ["from langgraph.graph import END, START, MessagesState, StateGraph",
426
+ "from langgraph.prebuilt import create_react_agent"]
427
+ if tools:
428
+ imports.append("from langchain_core.tools import tool")
429
+ sig = "model=%s" % _py_str(_langchain_model(model)) if model else "model"
430
+
431
+ prompts = "SYSTEM_PROMPTS = {\n%s}\n" % "".join(
432
+ " %s: %s,\n" % (_py_str(ident), _py_str(_clean(spec.instructions)))
433
+ for ident, spec in zip(idents, specs))
434
+
435
+ lines: List[str] = [' """Build and compile the %s crew as a graph."""' % workflow]
436
+ lines.extend(
437
+ " %s = create_react_agent(model, tools=[%s], prompt=SYSTEM_PROMPTS[%s])"
438
+ % (ident, ", ".join(spec.tools), _py_str(ident))
439
+ for ident, spec in zip(idents, specs))
440
+ lines.append("")
441
+ for ident in idents:
442
+ lines.append(" def %s_node(state):" % ident)
443
+ lines.append(" return {\"messages\": %s.invoke(state)[\"messages\"]}" % ident)
444
+ lines.append("")
445
+ lines.append(" builder = StateGraph(MessagesState)")
446
+ lines.extend(" builder.add_node(%s, %s_node)" % (_py_str(ident), ident)
447
+ for ident in idents)
448
+ prev = "START"
449
+ for ident in idents:
450
+ lines.append(" builder.add_edge(%s, %s)" % (prev, _py_str(ident)))
451
+ prev = _py_str(ident)
452
+ lines.append(" builder.add_edge(%s, END)" % prev)
453
+ lines.append(" return builder.compile()")
454
+ factory = "def build_%s(%s):\n%s\n" % (_ident(workflow), sig, "\n".join(lines))
455
+
456
+ parts = [_crew_header("langgraph", workflow, description),
457
+ "\n".join(imports) + "\n", "\n", prompts, "\n"]
458
+ if tools:
459
+ parts.append("\n".join(_tool_stub(t, "@tool") for t in tools))
460
+ parts.append("\n\n")
461
+ parts.append(factory)
462
+ return "".join(parts)
463
+
464
+
465
+ # Multi-agent (crew/graph) renderers, keyed by the same format id as FORMATS.
466
+ # A format absent here has no multi-agent path; the command layer falls back to
467
+ # the single-agent renderer (flattening the skill to its primary agent).
468
+ MULTI_FORMATS: Dict[str, "Callable[..., str]"] = {
469
+ "crewai": render_crew,
470
+ "langgraph": render_graph,
471
+ }
472
+
473
+
474
+ def supports_multi(fmt: str) -> bool:
475
+ """True if `fmt` has a multi-agent (crew/graph) renderer."""
476
+ return fmt in MULTI_FORMATS
477
+
478
+
479
+ def render_multi(fmt: str, workflow: str, description: str,
480
+ specs: List[AgentSpec], model: Optional[str] = None) -> str:
481
+ """Dispatch to the crew/graph renderer for `fmt`.
482
+
483
+ Raises ``KeyError`` for a format with no multi-agent path — callers guard
484
+ with :func:`supports_multi` and fall back to :func:`render` (single agent).
485
+ """
486
+ return MULTI_FORMATS[fmt](workflow, description, specs, model)
487
+
488
+
489
+ # A default read-only toolset appended to the adapted agent so it can *act*,
490
+ # not roleplay. Emitted as text (never imported here) — the framework only loads
491
+ # when the generated runner is executed. `chr(10)` avoids escaping newlines in
492
+ # this template; the inner `%s`/`%d` are runtime formatting in the emitted code
493
+ # and must NOT be touched by render_runner's `%` on _RUNNER_MAIN alone.
494
+ _RUNNER_TOOLS = '''
495
+ # --- boost run: default read-only tools (the agent's hands) ---
496
+ import pathlib as _boost_pl
497
+ from agents import Runner as _boost_Runner, function_tool as _boost_tool
498
+
499
+
500
+ @_boost_tool
501
+ def read_file(path: str) -> str:
502
+ """Read a UTF-8 text file and return its first ~16000 characters."""
503
+ return _boost_pl.Path(path).read_text(encoding="utf-8", errors="replace")[:16000]
504
+
505
+
506
+ @_boost_tool
507
+ def list_dir(path: str = ".") -> str:
508
+ """List a directory's entries, one per line (directories end with /)."""
509
+ entries = sorted(p.name + ("/" if p.is_dir() else "")
510
+ for p in _boost_pl.Path(path).iterdir())
511
+ return chr(10).join(entries)
512
+
513
+
514
+ @_boost_tool
515
+ def grep(pattern: str, path: str = ".") -> str:
516
+ """Case-insensitive substring search across text files under path."""
517
+ root = _boost_pl.Path(path)
518
+ files = [root] if root.is_file() else [p for p in root.rglob("*") if p.is_file()]
519
+ hits = []
520
+ for _f in files[:500]:
521
+ try:
522
+ _text = _f.read_text(encoding="utf-8", errors="replace")
523
+ except OSError:
524
+ continue
525
+ for _i, _line in enumerate(_text.splitlines(), 1):
526
+ if pattern.lower() in _line.lower():
527
+ hits.append("%s:%d: %s" % (_f, _i, _line.strip()[:200]))
528
+ if len(hits) >= 200:
529
+ return chr(10).join(hits)
530
+ return chr(10).join(hits) or "no matches"
531
+ '''
532
+
533
+ _RUNNER_MAIN = '''
534
+ # --- boost run: wire the tools onto the adapted agent and execute ---
535
+ _boost_agent = Agent(name=_boost_brain.name, instructions=_boost_brain.instructions,
536
+ model=getattr(_boost_brain, "model", None),
537
+ tools=[read_file, list_dir, grep])
538
+ print(_boost_Runner.run_sync(_boost_agent, %s).final_output)
539
+ '''
540
+
541
+
542
+ def render_runner(name: str, description: str, body: str,
543
+ model: Optional[str] = None, target: Optional[str] = None) -> str:
544
+ """A self-contained OpenAI Agents SDK *runner* for ``boost run``.
545
+
546
+ The adapted agent (its brain — instructions + model, via
547
+ :func:`render_agents_sdk`) plus a default read-only toolset (its hands) and a
548
+ ``Runner.run_sync`` call on a prompt built from ``target``. Like the rest of
549
+ this module it imports no framework — the text only needs to ``compile()``;
550
+ ``boost run`` either prints it (``--print``) or executes it where the SDK is
551
+ installed.
552
+ """
553
+ brain = render_agents_sdk(name, description, body, model)
554
+ # Capture the adapted agent under a reserved name *before* the tool defs — a
555
+ # skill literally named `grep`/`read-file`/`list-dir` normalizes (_ident) to
556
+ # a tool identifier, and the emitted `def grep(...)` would otherwise rebind
557
+ # (clobber) the brain. `_boost_*` names never collide: _ident strips the
558
+ # leading underscore, so no skill name maps onto them.
559
+ capture = "\n_boost_brain = %s\n" % _ident(name)
560
+ tgt = _clean(target or "")
561
+ where = "`" + tgt + "`" if tgt else "the current directory (`.`)"
562
+ prompt = ("Apply your instructions to %s. Use the read_file, list_dir, and "
563
+ "grep tools to inspect it, then produce your output." % where)
564
+ return brain + capture + _RUNNER_TOOLS + (_RUNNER_MAIN % _py_str(prompt))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.199
3
+ Version: 1.0.201
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -307,6 +307,7 @@ tests/functional/test_tap_signing.py
307
307
  tests/functional/test_workspace_scope.py
308
308
  tests/perf/test_benchmarks.py
309
309
  tests/unit/test_adapters.py
310
+ tests/unit/test_adapters_multi.py
310
311
  tests/unit/test_adapters_runner.py
311
312
  tests/unit/test_agents.py
312
313
  tests/unit/test_ai.py