boost-skill-cli 1.0.251__tar.gz → 1.0.253__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 (499) hide show
  1. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/configuration.py +52 -8
  4. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/discovery.py +5 -17
  5. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/info.py +1 -1
  6. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/team.py +2 -1
  7. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/journal.py +8 -2
  8. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/util.py +22 -0
  9. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_skill_cli.egg-info/PKG-INFO +1 -1
  10. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/commands.html +4 -3
  11. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_configuration.py +148 -0
  12. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_info.py +5 -0
  13. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_team.py +6 -0
  14. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_journal.py +23 -0
  15. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_util.py +24 -0
  16. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.gitattributes +0 -0
  17. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.gitignore +0 -0
  18. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.gitleaks.toml +0 -0
  19. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.htmlvalidate.json +0 -0
  20. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.lighthouserc.json +0 -0
  21. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.lycheeignore +0 -0
  22. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.markdownlint-cli2.jsonc +0 -0
  23. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.pre-commit-config.yaml +0 -0
  24. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.stylelintrc.json +0 -0
  25. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.vale/styles/boost/Terminology.yml +0 -0
  26. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
  27. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/.vale.ini +0 -0
  28. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/CLAUDE.md +0 -0
  29. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/CONTRIBUTING.md +0 -0
  30. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/LICENSE +0 -0
  31. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/MANIFEST.in +0 -0
  32. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/Makefile +0 -0
  33. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/README.md +0 -0
  34. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/SECURITY.md +0 -0
  35. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost +0 -0
  36. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/__init__.py +0 -0
  37. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/__main__.py +0 -0
  38. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/cli.py +0 -0
  39. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/cliparse.py +0 -0
  40. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/__init__.py +0 -0
  41. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/_common.py +0 -0
  42. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/bmad.py +0 -0
  43. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/hooks.py +0 -0
  44. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/intelligence.py +0 -0
  45. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/pkg.py +0 -0
  46. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/quality.py +0 -0
  47. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/run.py +0 -0
  48. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/safety.py +0 -0
  49. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/commands/taps.py +0 -0
  50. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/__init__.py +0 -0
  51. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/adapters.py +0 -0
  52. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/agents.py +0 -0
  53. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/ai.py +0 -0
  54. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/capabilities.py +0 -0
  55. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/catalog.py +0 -0
  56. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/claude_settings.py +0 -0
  57. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/config.py +0 -0
  58. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/dense.py +0 -0
  59. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/ed25519.py +0 -0
  60. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/embed.py +0 -0
  61. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/faithfulness.py +0 -0
  62. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/frontmatter.py +0 -0
  63. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/gitutil.py +0 -0
  64. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/imperative.py +0 -0
  65. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/injectscan.py +0 -0
  66. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/integrity.py +0 -0
  67. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/lockfile.py +0 -0
  68. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/logs.py +0 -0
  69. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/mcp.py +0 -0
  70. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/mcpdecl.py +0 -0
  71. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/minisign.py +0 -0
  72. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/nethttp.py +0 -0
  73. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/output.py +0 -0
  74. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/paths.py +0 -0
  75. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/policy.py +0 -0
  76. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/projectlock.py +0 -0
  77. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/provenance.py +0 -0
  78. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/rag.py +0 -0
  79. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/registry.py +0 -0
  80. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/resolve.py +0 -0
  81. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/rules.py +0 -0
  82. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/scopes.py +0 -0
  83. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/secretscan.py +0 -0
  84. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/selfupdate.py +0 -0
  85. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/serve.py +0 -0
  86. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/stackprobe.py +0 -0
  87. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/staleness.py +0 -0
  88. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/store.py +0 -0
  89. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/trustaudit.py +0 -0
  90. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/typosquat.py +0 -0
  91. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/updatediff.py +0 -0
  92. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/core/workflows.py +0 -0
  93. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/data/registries.json +0 -0
  94. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/errors.py +0 -0
  95. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_cli/spin.py +0 -0
  96. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
  97. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  98. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  99. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_skill_cli.egg-info/requires.txt +0 -0
  100. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/boost_skill_cli.egg-info/top_level.txt +0 -0
  101. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/codecov.yml +0 -0
  102. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/.claude/settings.local.json +0 -0
  103. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/DEBUGGING.md +0 -0
  104. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/adapters.html +0 -0
  105. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/gifs/distill.gif +0 -0
  106. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/gifs/doctor.gif +0 -0
  107. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/gifs/explain.gif +0 -0
  108. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/gifs/hooks.gif +0 -0
  109. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/gifs/install.gif +0 -0
  110. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/gifs/pulse.gif +0 -0
  111. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/gifs/search.gif +0 -0
  112. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/gifs/tap.gif +0 -0
  113. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/tapes/distill.tape +0 -0
  114. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/tapes/doctor.tape +0 -0
  115. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/tapes/explain.tape +0 -0
  116. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/tapes/hooks.tape +0 -0
  117. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/tapes/install.tape +0 -0
  118. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/tapes/pulse.tape +0 -0
  119. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/tapes/search.tape +0 -0
  120. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel/tapes/tap.tape +0 -0
  121. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/carousel.html +0 -0
  122. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/demo.gif +0 -0
  123. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/demo.tape +0 -0
  124. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/design-roadmap.html +0 -0
  125. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/eval.html +0 -0
  126. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/index.html +0 -0
  127. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/mcp-hub.html +0 -0
  128. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/rag-architecture.md +0 -0
  129. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D01.md +0 -0
  130. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D02.md +0 -0
  131. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D03.md +0 -0
  132. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D04.md +0 -0
  133. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D05.md +0 -0
  134. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D06.md +0 -0
  135. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D07.md +0 -0
  136. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D08.md +0 -0
  137. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D09.md +0 -0
  138. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D10.md +0 -0
  139. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D11.md +0 -0
  140. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D12.md +0 -0
  141. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D13.md +0 -0
  142. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D14.md +0 -0
  143. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D15.md +0 -0
  144. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D16.md +0 -0
  145. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D17.md +0 -0
  146. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D18.md +0 -0
  147. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D19.md +0 -0
  148. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D20.md +0 -0
  149. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D21.md +0 -0
  150. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D22.md +0 -0
  151. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D23.md +0 -0
  152. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D24.md +0 -0
  153. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D25.md +0 -0
  154. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/BOOST-D26.md +0 -0
  155. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
  156. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
  157. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
  158. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
  159. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
  160. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
  161. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
  162. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/boost-run-live-agents.md +0 -0
  163. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
  164. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
  165. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
  166. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
  167. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
  168. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
  169. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
  170. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
  171. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
  172. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/command-carousel-page.md +0 -0
  173. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/command-reference-docs-site.md +0 -0
  174. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
  175. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
  176. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
  177. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
  178. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
  179. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
  180. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
  181. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
  182. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
  183. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
  184. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
  185. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
  186. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
  187. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
  188. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
  189. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
  190. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
  191. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
  192. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
  193. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
  194. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
  195. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
  196. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
  197. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/github-community-health-files.md +0 -0
  198. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
  199. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
  200. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
  201. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/html-validation-html-validate.md +0 -0
  202. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
  203. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
  204. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
  205. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
  206. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
  207. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
  208. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
  209. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
  210. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
  211. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/license-compliance-scanning.md +0 -0
  212. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
  213. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
  214. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
  215. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
  216. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
  217. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
  218. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
  219. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
  220. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
  221. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
  222. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
  223. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
  224. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
  225. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mcp-aware-skills.md +0 -0
  226. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
  227. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
  228. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
  229. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
  230. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
  231. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
  232. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
  233. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
  234. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
  235. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
  236. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
  237. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
  238. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
  239. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
  240. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
  241. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
  242. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
  243. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
  244. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
  245. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
  246. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
  247. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
  248. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
  249. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
  250. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
  251. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
  252. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
  253. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
  254. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
  255. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
  256. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
  257. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
  258. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
  259. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
  260. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
  261. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
  262. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
  263. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
  264. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
  265. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
  266. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
  267. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/required-checks-config-drift.md +0 -0
  268. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
  269. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
  270. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
  271. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
  272. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
  273. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
  274. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
  275. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
  276. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
  277. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
  278. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
  279. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
  280. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
  281. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
  282. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
  283. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
  284. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
  285. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
  286. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
  287. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
  288. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
  289. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
  290. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
  291. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
  292. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
  293. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
  294. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
  295. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
  296. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
  297. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
  298. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
  299. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/typo-detection-codespell.md +0 -0
  300. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
  301. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
  302. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
  303. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
  304. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/update-diff-before-apply.md +0 -0
  305. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
  306. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
  307. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
  308. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
  309. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
  310. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
  311. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
  312. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
  313. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
  314. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap/items/workspace-scope-install.md +0 -0
  315. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/docs/roadmap.html +0 -0
  316. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/eslint.config.mjs +0 -0
  317. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/examples/README.md +0 -0
  318. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/examples/adapt-demo.sh +0 -0
  319. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/examples/boost-run-prototype.sh +0 -0
  320. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/index.html +0 -0
  321. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/noxfile.py +0 -0
  322. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/pyproject.toml +0 -0
  323. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/coverage-tools.in +0 -0
  324. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/coverage-tools.txt +0 -0
  325. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/lint-tools.in +0 -0
  326. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/lint-tools.txt +0 -0
  327. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/mutation-tools.in +0 -0
  328. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/mutation-tools.txt +0 -0
  329. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/release-tools.in +0 -0
  330. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/release-tools.txt +0 -0
  331. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/test-tools.in +0 -0
  332. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/requirements/test-tools.txt +0 -0
  333. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/a11y_check.py +0 -0
  334. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/bench_cli.sh +0 -0
  335. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/build_command_reference.py +0 -0
  336. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/build_registries.py +0 -0
  337. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/build_roadmap.py +0 -0
  338. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/check_anchors.py +0 -0
  339. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/check_required_checks.py +0 -0
  340. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/ensure_eval_corpus.sh +0 -0
  341. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/eval_explain.py +0 -0
  342. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/eval_recommend.py +0 -0
  343. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/eval_retrieval.py +0 -0
  344. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/eval_stats_summary.py +0 -0
  345. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/import_budget.py +0 -0
  346. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/lock_toolchain.py +0 -0
  347. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/mutation_gate.py +0 -0
  348. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/mutation_shards.py +0 -0
  349. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/mutation_weights.json +0 -0
  350. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/perf_gate.py +0 -0
  351. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/post_deploy_smoke.py +0 -0
  352. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/scripts/release_preflight.py +0 -0
  353. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/setup.cfg +0 -0
  354. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/sonar-project.properties +0 -0
  355. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/style/README.md +0 -0
  356. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/style/boost.css +0 -0
  357. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/style/boost.js +0 -0
  358. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/style/demo.html +0 -0
  359. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/adapt.feature +0 -0
  360. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/browse.feature +0 -0
  361. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/count.feature +0 -0
  362. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/discover.feature +0 -0
  363. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/doctor.feature +0 -0
  364. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/environment.py +0 -0
  365. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/explain.feature +0 -0
  366. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/index.feature +0 -0
  367. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/install.feature +0 -0
  368. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/list.feature +0 -0
  369. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/mcp.feature +0 -0
  370. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/search.feature +0 -0
  371. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/steps/cli_steps.py +0 -0
  372. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/steps/discovery_steps.py +0 -0
  373. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/steps/mcp_steps.py +0 -0
  374. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/bdd/features/steps/quality_steps.py +0 -0
  375. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/conftest.py +0 -0
  376. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/eval/baseline.json +0 -0
  377. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/eval/explain.jsonl +0 -0
  378. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/eval/golden.jsonl +0 -0
  379. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/eval/recommend.jsonl +0 -0
  380. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/eval/taps.txt +0 -0
  381. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_capabilities_policy.py +0 -0
  382. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_adapt.py +0 -0
  383. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_bmad.py +0 -0
  384. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_discovery.py +0 -0
  385. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_hooks.py +0 -0
  386. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_intelligence.py +0 -0
  387. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_pkg.py +0 -0
  388. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_quality.py +0 -0
  389. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_cli_taps.py +0 -0
  390. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_everyday_loop.py +0 -0
  391. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_integrity_enforce.py +0 -0
  392. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_property_parsers.py +0 -0
  393. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_run.py +0 -0
  394. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_tap_signing.py +0 -0
  395. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/functional/test_workspace_scope.py +0 -0
  396. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/README.md +0 -0
  397. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
  398. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
  399. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
  400. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
  401. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
  402. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
  403. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
  404. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
  405. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
  406. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
  407. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
  408. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
  409. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
  410. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/registry/02-https.txt +0 -0
  411. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
  412. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
  413. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
  414. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/registry/06-space.txt +0 -0
  415. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
  416. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
  417. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/fuzz_frontmatter.py +0 -0
  418. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/fuzz/fuzz_registry.py +0 -0
  419. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/make_fixture.py +0 -0
  420. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/perf/test_benchmarks.py +0 -0
  421. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/smoke.sh +0 -0
  422. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_a11y_check.py +0 -0
  423. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_adapters.py +0 -0
  424. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_adapters_multi.py +0 -0
  425. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_adapters_runner.py +0 -0
  426. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_agents.py +0 -0
  427. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_ai.py +0 -0
  428. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_capabilities.py +0 -0
  429. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_catalog.py +0 -0
  430. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_check_anchors.py +0 -0
  431. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_claude_settings.py +0 -0
  432. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_cliparse.py +0 -0
  433. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_command_reference_fresh.py +0 -0
  434. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_config.py +0 -0
  435. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_dense.py +0 -0
  436. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_dense_fallback.py +0 -0
  437. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_docs_pages_linked.py +0 -0
  438. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_docsite_chrome.py +0 -0
  439. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_ed25519.py +0 -0
  440. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_embed.py +0 -0
  441. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_errors_and_cli_table.py +0 -0
  442. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_eval_stats_summary.py +0 -0
  443. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_faithfulness.py +0 -0
  444. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_frontmatter.py +0 -0
  445. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_fuzz_targets.py +0 -0
  446. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_gitleaks_config.py +0 -0
  447. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_gitutil.py +0 -0
  448. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_imperative.py +0 -0
  449. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_import_budget.py +0 -0
  450. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_injectscan.py +0 -0
  451. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_integrity.py +0 -0
  452. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_lockfile.py +0 -0
  453. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_logs.py +0 -0
  454. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_marketing_counts.py +0 -0
  455. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_mcp.py +0 -0
  456. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_mcpdecl.py +0 -0
  457. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_minisign.py +0 -0
  458. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_mutation_hardening.py +0 -0
  459. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_mutation_shards.py +0 -0
  460. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_mutmut_source_paths.py +0 -0
  461. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_nethttp.py +0 -0
  462. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_output.py +0 -0
  463. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_paths.py +0 -0
  464. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_perf_gate.py +0 -0
  465. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_pkg_confusions.py +0 -0
  466. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_pkg_injection.py +0 -0
  467. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_pkg_secrets.py +0 -0
  468. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_policy.py +0 -0
  469. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_post_deploy_smoke.py +0 -0
  470. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_projectlock.py +0 -0
  471. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_provenance.py +0 -0
  472. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_rag.py +0 -0
  473. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_registries_fresh.py +0 -0
  474. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_registry.py +0 -0
  475. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_release_preflight.py +0 -0
  476. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_required_checks.py +0 -0
  477. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_resolve.py +0 -0
  478. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_roadmap_fresh.py +0 -0
  479. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_rules.py +0 -0
  480. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_scopes.py +0 -0
  481. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_secretscan.py +0 -0
  482. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_selfupdate.py +0 -0
  483. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_serve.py +0 -0
  484. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_spin.py +0 -0
  485. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_stackprobe.py +0 -0
  486. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_staleness.py +0 -0
  487. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_store.py +0 -0
  488. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_token_parity.py +0 -0
  489. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_toolchain_lock.py +0 -0
  490. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_trustaudit.py +0 -0
  491. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_typosquat.py +0 -0
  492. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_updatediff.py +0 -0
  493. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_version.py +0 -0
  494. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_workflow_timeouts.py +0 -0
  495. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/unit/test_workflows.py +0 -0
  496. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/visual/a11y_check.mjs +0 -0
  497. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/visual/console_check.mjs +0 -0
  498. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/tests/visual/package.json +0 -0
  499. {boost_skill_cli-1.0.251 → boost_skill_cli-1.0.253}/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.251
3
+ Version: 1.0.253
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.251'
22
- __version_tuple__ = version_tuple = (1, 0, 251)
21
+ __version__ = version = '1.0.253'
22
+ __version_tuple__ = version_tuple = (1, 0, 253)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -2,6 +2,7 @@
2
2
  completions, schedule, serve, mcp, self-update."""
3
3
  from __future__ import annotations
4
4
 
5
+ import argparse
5
6
  import json
6
7
  import os
7
8
  import re
@@ -401,8 +402,41 @@ jobs:
401
402
  """
402
403
 
403
404
 
405
+ def _write_onboard_file(dest: Path, content: str, force: bool) -> bool:
406
+ """Write one generated onboard file; confirm first if it already exists.
407
+
408
+ ``boost onboard`` is routinely re-run on a repo that already has its own
409
+ tracked ``.skill-lock.json``, and a bare ``write_text`` there replaces the
410
+ repo's lock with whatever this machine happens to have installed — while
411
+ still reporting "created". Existence has to be checked *before* the write,
412
+ the same way :func:`intelligence._write_generated` already does.
413
+
414
+ Returns True when the file was written.
415
+ """
416
+ if not dest.exists():
417
+ dest.parent.mkdir(parents=True, exist_ok=True)
418
+ dest.write_text(content, encoding="utf-8")
419
+ out.ok("created %s" % _tilde(dest))
420
+ return True
421
+ try:
422
+ unchanged = dest.read_text(encoding="utf-8") == content
423
+ except (OSError, UnicodeDecodeError):
424
+ unchanged = False # unreadable: treat as different and ask
425
+ if unchanged:
426
+ # Re-running onboard regenerates the workflow byte-for-byte. Prompting
427
+ # to overwrite a file with its own contents is noise, not safety.
428
+ out.info("unchanged %s" % _tilde(dest))
429
+ return False
430
+ if not force and not out.confirm("overwrite %s?" % _tilde(dest)):
431
+ out.info("skipped %s" % _tilde(dest))
432
+ return False
433
+ dest.write_text(content, encoding="utf-8")
434
+ out.ok("updated %s" % _tilde(dest))
435
+ return True
436
+
437
+
404
438
  def cmd_onboard(argv) -> int:
405
- """boost onboard [--repo DIR] [--pr] [--dry-run]"""
439
+ """boost onboard [--repo DIR] [--pr] [--dry-run] [--force]"""
406
440
  p = cliparse.parser(
407
441
  prog="boost onboard",
408
442
  description="Add skill-tracker telemetry to a repo & open a PR")
@@ -411,6 +445,9 @@ def cmd_onboard(argv) -> int:
411
445
  help="commit on a branch and open a PR with `gh`")
412
446
  p.add_argument("--dry-run", action="store_true",
413
447
  help="preview the files without writing anything")
448
+ p.add_argument("-f", "--force", action="store_true",
449
+ help="overwrite existing files without confirming")
450
+ p.add_argument("-y", "--yes", action="store_true", help=argparse.SUPPRESS)
414
451
  args = p.parse_args(argv)
415
452
 
416
453
  repo = paths.expand(args.repo).resolve()
@@ -431,7 +468,10 @@ def cmd_onboard(argv) -> int:
431
468
 
432
469
  if args.dry_run:
433
470
  for rel, content in files:
434
- out.heading("would write %s" % _tilde(repo / rel))
471
+ dest = repo / rel
472
+ out.heading("would %s %s"
473
+ % ("overwrite" if dest.exists() else "write",
474
+ _tilde(dest)))
435
475
  for line in content.splitlines()[:24]:
436
476
  out.dim(" " + line)
437
477
  return 0
@@ -447,17 +487,21 @@ def cmd_onboard(argv) -> int:
447
487
  raise BoostError("the `gh` CLI is required for --pr",
448
488
  hint="brew install gh, or rerun without --pr")
449
489
 
450
- for rel, content in files:
451
- fp = repo / rel
452
- fp.parent.mkdir(parents=True, exist_ok=True)
453
- fp.write_text(content, encoding="utf-8")
454
- out.ok("created %s" % _tilde(fp))
490
+ written = [rel for rel, content in files
491
+ if _write_onboard_file(repo / rel, content,
492
+ args.force or args.yes)]
493
+ if not written:
494
+ # Nothing changed, so there is nothing to journal — and nothing for
495
+ # --pr to commit. Branching here would leave an empty branch behind
496
+ # and then fail on `git commit` with no staged changes.
497
+ out.info("nothing to do — %s already onboarded" % _tilde(repo))
498
+ return 0
455
499
  journal.log("onboard", _tilde(repo), pr=args.pr or None)
456
500
 
457
501
  if args.pr:
458
502
  branch = "boost/onboard-skill-tracker"
459
503
  gitutil.run(["-C", str(repo), "checkout", "-b", branch])
460
- gitutil.run(["-C", str(repo), "add"] + [rel for rel, _ in files])
504
+ gitutil.run(["-C", str(repo), "add", *written])
461
505
  gitutil.run(["-C", str(repo), "commit", "-m",
462
506
  "chore: add boost skill tracking (boost onboard)"])
463
507
  try:
@@ -5,7 +5,6 @@ Also exports detect_stack(), shared with the Quality commands.
5
5
  """
6
6
  from __future__ import annotations
7
7
 
8
- import argparse
9
8
  import contextlib
10
9
  import json
11
10
  import operator
@@ -40,17 +39,6 @@ from ..errors import BoostError
40
39
  __all__ = ["detect_stack"]
41
40
 
42
41
 
43
- def _positive_int(s: str) -> int:
44
- """argparse type for --limit flags: an int that must be >= 1."""
45
- try:
46
- v = int(s)
47
- except ValueError:
48
- raise argparse.ArgumentTypeError("invalid int value: %r" % s) from None
49
- if v < 1:
50
- raise argparse.ArgumentTypeError("must be >= 1")
51
- return v
52
-
53
-
54
42
  _tilde = paths.tilde
55
43
 
56
44
 
@@ -98,7 +86,7 @@ def cmd_search(argv):
98
86
  p.add_argument("query", nargs="+", help="search terms")
99
87
  p.add_argument("--smart", action="store_true",
100
88
  help="rerank the top hits with Claude")
101
- p.add_argument("--limit", type=_positive_int, default=15,
89
+ p.add_argument("--limit", type=util.positive_int, default=15,
102
90
  help="max results (default 15)")
103
91
  p.add_argument("--json", action="store_true", dest="as_json",
104
92
  help="machine-readable output")
@@ -223,7 +211,7 @@ def cmd_index(argv):
223
211
  p = cliparse.parser(
224
212
  prog="boost index",
225
213
  description="Build the discovery registry via GitHub Code Search")
226
- p.add_argument("--limit", type=_positive_int, default=300,
214
+ p.add_argument("--limit", type=util.positive_int, default=300,
227
215
  help="max skill files to index (default 300)")
228
216
  args = p.parse_args(argv)
229
217
  if not shutil.which("gh"):
@@ -329,7 +317,7 @@ def cmd_discover(argv):
329
317
  prog="boost discover",
330
318
  description="Browse & search the GitHub-wide skill discovery index")
331
319
  p.add_argument("query", nargs="*", help="filter terms (repo/path substring)")
332
- p.add_argument("--limit", type=_positive_int, default=25,
320
+ p.add_argument("--limit", type=util.positive_int, default=25,
333
321
  help="max rows (default 25)")
334
322
  p.add_argument("--json", action="store_true", dest="as_json",
335
323
  help="machine-readable output")
@@ -398,7 +386,7 @@ def cmd_recommend(argv):
398
386
  prog="boost recommend",
399
387
  description="Suggest skills based on your project's tech stack")
400
388
  p.add_argument("--path", default=".", help="project directory (default: cwd)")
401
- p.add_argument("--limit", type=_positive_int, default=8,
389
+ p.add_argument("--limit", type=util.positive_int, default=8,
402
390
  help="max suggestions (default 8)")
403
391
  p.add_argument("--json", action="store_true", dest="as_json",
404
392
  help="machine-readable output")
@@ -885,7 +873,7 @@ def cmd_trending(argv):
885
873
  p = cliparse.parser(
886
874
  prog="boost trending",
887
875
  description="Show trending skills by install count")
888
- p.add_argument("--limit", type=_positive_int, default=10,
876
+ p.add_argument("--limit", type=util.positive_int, default=10,
889
877
  help="max rows (default 10)")
890
878
  args = p.parse_args(argv)
891
879
  evs = journal.events(action="install")
@@ -575,7 +575,7 @@ def cmd_log(argv):
575
575
  ap = cliparse.parser(prog="boost log",
576
576
  description="Git log for a skill, or boost's activity log")
577
577
  ap.add_argument("name", nargs="?", help="skill to show upstream history for")
578
- ap.add_argument("-n", "--limit", type=int, default=20, metavar="N",
578
+ ap.add_argument("-n", "--limit", type=util.positive_int, default=20, metavar="N",
579
579
  help="max entries (default 20)")
580
580
  ap.add_argument("--diagnostics", action="store_true",
581
581
  help="show boost's diagnostic log trail (not skill history)")
@@ -456,7 +456,8 @@ def cmd_pulse(argv) -> int:
456
456
  p = cliparse.parser(
457
457
  prog="boost pulse",
458
458
  description="Team activity feed of skill-management events")
459
- p.add_argument("-n", type=int, default=20, help="events to show (default 20)")
459
+ p.add_argument("-n", type=util.positive_int, default=20,
460
+ help="events to show (default 20)")
460
461
  p.add_argument("--all", action="store_true", help="show the whole journal")
461
462
  p.add_argument("--action", help="filter by action (install, tap, ...)")
462
463
  p.add_argument("--json", action="store_true", help="machine-readable output")
@@ -30,7 +30,13 @@ def log(action: str, subject: str = "", **fields) -> None:
30
30
 
31
31
  def events(n: Optional[int] = None, action: Optional[str] = None,
32
32
  subject: Optional[str] = None) -> List[dict]:
33
- """Most-recent-first list of journal events."""
33
+ """Most-recent-first list of journal events; ``n=None`` means all of them.
34
+
35
+ ``n`` must be >= 0: a negative would become a negative slice and silently
36
+ return every event *but* the oldest ones, so it raises instead.
37
+ """
38
+ if n is not None and n < 0:
39
+ raise ValueError("events(n=%d): n must be >= 0" % n)
34
40
  p = paths.pulse_path()
35
41
  if not p.exists():
36
42
  return []
@@ -48,7 +54,7 @@ def events(n: Optional[int] = None, action: Optional[str] = None,
48
54
  continue
49
55
  out.append(e)
50
56
  out.reverse()
51
- return out[:n] if n else out
57
+ return out if n is None else out[:n]
52
58
 
53
59
 
54
60
  def _line_count(p) -> int:
@@ -119,6 +119,28 @@ def atomic_write_text(path: Path, text: str, encoding: str = "utf-8") -> None:
119
119
  raise
120
120
 
121
121
 
122
+ def positive_int(s: str) -> int:
123
+ """argparse ``type=`` for count flags (``-n``/``--limit``): an int >= 1.
124
+
125
+ A bare ``type=int`` lets a negative through, and every count flag in boost
126
+ ends up as a slice bound or a ``git log -n`` argument — where a negative
127
+ silently *inverts* the request instead of failing it. Rejecting it at parse
128
+ time is the only place the user still sees a usable error.
129
+ """
130
+ # Local import: argparse is not on the `boost --help` startup path, and
131
+ # util is (via core.logs). Every caller of this function is a command
132
+ # module that has already imported argparse through cliparse.
133
+ import argparse
134
+
135
+ try:
136
+ v = int(s)
137
+ except (TypeError, ValueError):
138
+ raise argparse.ArgumentTypeError("invalid int value: %r" % s) from None
139
+ if v < 1:
140
+ raise argparse.ArgumentTypeError("must be >= 1")
141
+ return v
142
+
143
+
122
144
  def now_iso() -> str:
123
145
  """Return UTC now as ``'2026-07-16T01:00:00Z'`` (what ``rel_time`` parses)."""
124
146
  return datetime.now(timezone.utc).strftime("%Y-%m-%dT%H:%M:%SZ")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.251
3
+ Version: 1.0.253
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -181,7 +181,7 @@
181
181
  <a class="cmd-link" href="#cmd-clean" data-search="clean clear stale caches &amp; broken symlinks --dry-run --deep">clean</a>
182
182
  <a class="cmd-link" href="#cmd-create" data-search="create scaffold a new skill from a template --description description --dir dir --install name">create</a>
183
183
  <a class="cmd-link" href="#cmd-policy" data-search="policy manage &amp; enforce skill governance policies --json {list,set,unset,check} key value">policy</a>
184
- <a class="cmd-link" href="#cmd-onboard" data-search="onboard add skill-tracker telemetry to a repo &amp; open a pr --repo repo --pr --dry-run">onboard</a>
184
+ <a class="cmd-link" href="#cmd-onboard" data-search="onboard add skill-tracker telemetry to a repo &amp; open a pr --repo repo --pr --dry-run -f, --force">onboard</a>
185
185
  <a class="cmd-link" href="#cmd-completions" data-search="completions generate shell tab-completion scripts {bash,zsh,fish}">completions</a>
186
186
  <a class="cmd-link" href="#cmd-schedule" data-search="schedule manage automatic skill-sync scheduling --interval {6h,12h,daily} --json {status,enable,disable}">schedule</a>
187
187
  <a class="cmd-link" href="#cmd-serve" data-search="serve serve the skill catalog over http (port 8787) --port port --host host">serve</a>
@@ -991,15 +991,16 @@
991
991
  <div class="arg"><code>--json</code><span>machine-readable output</span></div>
992
992
  </div>
993
993
  </section>
994
- <section class="cmd" id="cmd-onboard" data-search="onboard add skill-tracker telemetry to a repo &amp; open a pr --repo repo --pr --dry-run">
994
+ <section class="cmd" id="cmd-onboard" data-search="onboard add skill-tracker telemetry to a repo &amp; open a pr --repo repo --pr --dry-run -f, --force">
995
995
  <h3><span class="cname">onboard</span><span class="gtag">cfg</span></h3>
996
996
  <p class="summary">Add skill-tracker telemetry to a repo &amp; open a PR</p>
997
- <pre class="syn">boost onboard [--repo REPO] [--pr] [--dry-run]</pre>
997
+ <pre class="syn">boost onboard [--repo REPO] [--pr] [--dry-run] [--force]</pre>
998
998
  <div class="args-h">Options</div>
999
999
  <div class="args">
1000
1000
  <div class="arg"><code>--repo REPO</code><span>repository directory (default: .)</span></div>
1001
1001
  <div class="arg"><code>--pr</code><span>commit on a branch and open a PR with `gh`</span></div>
1002
1002
  <div class="arg"><code>--dry-run</code><span>preview the files without writing anything</span></div>
1003
+ <div class="arg"><code>-f, --force</code><span>overwrite existing files without confirming</span></div>
1003
1004
  </div>
1004
1005
  </section>
1005
1006
  <section class="cmd" id="cmd-completions" data-search="completions generate shell tab-completion scripts {bash,zsh,fish}">
@@ -345,6 +345,154 @@ class TestOnboard:
345
345
  assert "is not clean" in r.err
346
346
 
347
347
 
348
+ class TestOnboardOverwrite:
349
+ """Re-running onboard must not silently replace a repo's own files.
350
+
351
+ The interesting file is ``.skill-lock.json``: a repo that tracks its own
352
+ lock gets it replaced by whatever *this machine* has installed, and the
353
+ old code still printed "created". Every test here therefore asserts on
354
+ file contents, not just on the message.
355
+ """
356
+
357
+ LOCK = ".skill-lock.json"
358
+ TELEMETRY = ".boost/telemetry.json"
359
+ WORKFLOW = ".github/workflows/boost-skill-inventory.yml"
360
+
361
+ def _seeded(self, boost, tmp_path):
362
+ """A repo already onboarded, with a hand-edited lock file."""
363
+ repo = tmp_path / "repo"
364
+ repo.mkdir()
365
+ boost("onboard", "--repo", repo) # BOOST_ASSUME_YES: creates
366
+ (repo / self.LOCK).write_text('{"mine": true}\n', encoding="utf-8")
367
+ return repo
368
+
369
+ def test_declining_leaves_the_existing_file_byte_for_byte(
370
+ self, boost, installed, tmp_path, monkeypatch):
371
+ repo = self._seeded(boost, tmp_path)
372
+ monkeypatch.delenv("BOOST_ASSUME_YES") # stdin is not a tty -> "no"
373
+ r = boost("onboard", "--repo", repo)
374
+ assert (repo / self.LOCK).read_text(encoding="utf-8") == '{"mine": true}\n'
375
+ assert "skipped" in r.out
376
+ assert "created %s" % self.LOCK not in r.out
377
+
378
+ def test_force_overwrites_and_says_updated_not_created(
379
+ self, boost, installed, tmp_path, monkeypatch):
380
+ repo = self._seeded(boost, tmp_path)
381
+ monkeypatch.delenv("BOOST_ASSUME_YES")
382
+ r = boost("onboard", "--repo", repo, "--force")
383
+ lock = json.loads((repo / self.LOCK).read_text(encoding="utf-8"))
384
+ assert "brainstorming" in lock["skills"], "the real lock, not the stub"
385
+ assert "updated" in r.out
386
+ # "created" was the lie the old code told about every overwrite.
387
+ assert "created" not in r.out
388
+
389
+ def test_answering_yes_at_the_prompt_overwrites(
390
+ self, boost, installed, tmp_path):
391
+ # BOOST_ASSUME_YES is the fixture default, i.e. the user said yes.
392
+ repo = self._seeded(boost, tmp_path)
393
+ r = boost("onboard", "--repo", repo)
394
+ lock = json.loads((repo / self.LOCK).read_text(encoding="utf-8"))
395
+ assert "brainstorming" in lock["skills"]
396
+ assert "updated" in r.out
397
+
398
+ def test_an_existing_file_boost_cannot_read_is_still_protected(
399
+ self, boost, installed, tmp_path, monkeypatch):
400
+ # The identical-content shortcut reads the file; a binary or
401
+ # permission-denied file must fall back to asking, not to overwriting.
402
+ repo = self._seeded(boost, tmp_path)
403
+ (repo / self.WORKFLOW).write_bytes(b"\xff\xfe not utf-8")
404
+ monkeypatch.delenv("BOOST_ASSUME_YES")
405
+ r = boost("onboard", "--repo", repo)
406
+ assert (repo / self.WORKFLOW).read_bytes() == b"\xff\xfe not utf-8"
407
+ assert "skipped" in r.out
408
+
409
+ def test_the_hidden_yes_alias_also_overwrites(
410
+ self, boost, installed, tmp_path, monkeypatch):
411
+ repo = self._seeded(boost, tmp_path)
412
+ monkeypatch.delenv("BOOST_ASSUME_YES")
413
+ boost("onboard", "--repo", repo, "--yes")
414
+ assert '{"mine": true}' not in (repo / self.LOCK).read_text(encoding="utf-8")
415
+
416
+ def test_identical_content_is_never_prompted_for(
417
+ self, boost, installed, tmp_path, monkeypatch):
418
+ # The workflow YAML regenerates byte-for-byte, so a second run has
419
+ # nothing to ask about it. Asking anyway trains users to say yes.
420
+ repo = self._seeded(boost, tmp_path)
421
+ # Leave *only* the workflow: telemetry carries a timestamp and the lock
422
+ # is live machine state, so neither is a stable "identical" case.
423
+ (repo / self.TELEMETRY).unlink()
424
+ (repo / self.LOCK).unlink()
425
+ monkeypatch.delenv("BOOST_ASSUME_YES")
426
+ monkeypatch.setattr("boost_cli.core.output.confirm",
427
+ lambda *a, **k: pytest.fail(
428
+ "prompted to overwrite an identical file"))
429
+ r = boost("onboard", "--repo", repo)
430
+ assert "unchanged" in r.out
431
+ assert self.WORKFLOW in r.out
432
+
433
+ def test_dry_run_distinguishes_write_from_overwrite(
434
+ self, boost, installed, tmp_path):
435
+ repo = self._seeded(boost, tmp_path)
436
+ r = boost("onboard", "--repo", repo, "--dry-run")
437
+ assert "would overwrite" in r.out
438
+ assert "would write" not in r.out, "every file already exists here"
439
+ assert (repo / self.LOCK).read_text(encoding="utf-8") == '{"mine": true}\n'
440
+
441
+ def test_declining_everything_journals_nothing(
442
+ self, boost, installed, tmp_path, monkeypatch):
443
+ repo = self._seeded(boost, tmp_path)
444
+ # Make all three differ so all three get a prompt, then decline them.
445
+ (repo / self.TELEMETRY).write_text("{}\n", encoding="utf-8")
446
+ (repo / self.WORKFLOW).write_text("# theirs\n", encoding="utf-8")
447
+ before = len(journal.events(action="onboard"))
448
+ monkeypatch.delenv("BOOST_ASSUME_YES")
449
+ r = boost("onboard", "--repo", repo)
450
+ assert "nothing to do" in r.out
451
+ assert len(journal.events(action="onboard")) == before, \
452
+ "a no-op run must not add an onboard event"
453
+
454
+ def test_pr_stages_only_the_files_it_actually_wrote(
455
+ self, boost, installed, tmp_path, monkeypatch):
456
+ repo = _mk_repo(tmp_path / "repo")
457
+ (repo / self.LOCK).write_text('{"mine": true}\n', encoding="utf-8")
458
+ _git(repo, "add", "-A")
459
+ _git(repo, "commit", "-qm", "our own lock")
460
+ monkeypatch.setattr("boost_cli.commands.configuration.shutil.which",
461
+ lambda c: "/usr/bin/" + c)
462
+ real_run = subprocess.run
463
+ monkeypatch.setattr(
464
+ "boost_cli.commands.configuration.subprocess.run",
465
+ lambda cmd, **kw: _proc(cmd, 0, out="https://github.com/o/r/pull/9\n")
466
+ if cmd and cmd[0] == "gh" else real_run(cmd, **kw))
467
+ monkeypatch.delenv("BOOST_ASSUME_YES") # decline the lock overwrite
468
+ boost("onboard", "--repo", repo, "--pr")
469
+
470
+ names = subprocess.run(["git", "show", "--name-only", "--pretty=", "HEAD"],
471
+ cwd=str(repo), capture_output=True, text=True)
472
+ staged = set(names.stdout.split())
473
+ assert staged == {self.TELEMETRY, self.WORKFLOW}
474
+ assert (repo / self.LOCK).read_text(encoding="utf-8") == '{"mine": true}\n'
475
+
476
+ def test_pr_with_nothing_to_write_leaves_no_branch_behind(
477
+ self, boost, installed, tmp_path, monkeypatch):
478
+ repo = _mk_repo(tmp_path / "repo")
479
+ for rel, body in ((self.TELEMETRY, "{}\n"), (self.WORKFLOW, "# theirs\n"),
480
+ (self.LOCK, '{"mine": true}\n')):
481
+ (repo / rel).parent.mkdir(parents=True, exist_ok=True)
482
+ (repo / rel).write_text(body, encoding="utf-8")
483
+ _git(repo, "add", "-A")
484
+ _git(repo, "commit", "-qm", "already ours")
485
+ monkeypatch.setattr("boost_cli.commands.configuration.shutil.which",
486
+ lambda c: "/usr/bin/" + c)
487
+ monkeypatch.delenv("BOOST_ASSUME_YES")
488
+ r = boost("onboard", "--repo", repo, "--pr")
489
+ assert "nothing to do" in r.out
490
+ head = subprocess.run(["git", "rev-parse", "--abbrev-ref", "HEAD"],
491
+ cwd=str(repo), capture_output=True, text=True)
492
+ assert head.stdout.strip() != "boost/onboard-skill-tracker", \
493
+ "an empty branch would fail on `git commit` with nothing staged"
494
+
495
+
348
496
  # ---------------------------------------------------------------- completions
349
497
 
350
498
  class TestCompletions:
@@ -314,6 +314,11 @@ class TestLog:
314
314
  assert len(lines) == 1
315
315
  assert "install brainstorming" in lines[0]
316
316
 
317
+ def test_negative_limit_rejected_on_every_branch(self, boost, installed):
318
+ for extra in ([], ["--diagnostics"], ["--crashes"]):
319
+ r = boost("log", *extra, "-n", "-1", expect=2)
320
+ assert "argument -n/--limit: must be >= 1" in r.err
321
+
317
322
  def test_skill_git_history(self, boost, installed):
318
323
  r = boost("log", "brainstorming")
319
324
  assert "brainstorming — history in fixture-tap" in r.out
@@ -324,6 +324,12 @@ class TestPulse:
324
324
  rows = [l for l in r.out.splitlines() if USER in l]
325
325
  assert len(rows) == 1 and "fixture-tap" in rows[0]
326
326
 
327
+ def test_negative_or_zero_limit_rejected(self, boost, installed):
328
+ r = boost("pulse", "-n", "-1", expect=2)
329
+ assert "argument -n: must be >= 1" in r.err
330
+ r = boost("pulse", "-n", "0", expect=2)
331
+ assert "argument -n: must be >= 1" in r.err
332
+
327
333
  def test_json_purity(self, boost, installed):
328
334
  r = boost("pulse", "--json")
329
335
  events = json.loads(r.out)
@@ -5,6 +5,8 @@ import getpass
5
5
  import json
6
6
  import re
7
7
 
8
+ import pytest
9
+
8
10
  from boost_cli.core import journal, paths
9
11
 
10
12
 
@@ -254,3 +256,24 @@ class TestRotationHealthy:
254
256
  def test_one_over_limit_unhealthy(self, sandbox):
255
257
  write_lines(journal.ROTATE_AT + 1)
256
258
  assert journal.rotation_healthy() is False
259
+
260
+
261
+ class TestEventsLimitGuard:
262
+ """A negative n used to become a negative slice — see the roadmap item."""
263
+
264
+ def test_negative_n_raises_instead_of_inverting(self, sandbox):
265
+ for i in range(3):
266
+ journal.log("install", "s%d" % i)
267
+ with pytest.raises(ValueError) as exc:
268
+ journal.events(-1)
269
+ assert str(exc.value) == "events(n=-1): n must be >= 0"
270
+ assert len(journal.events()) == 3
271
+
272
+ def test_zero_n_is_empty_not_everything(self, sandbox):
273
+ for i in range(3):
274
+ journal.log("install", "s%d" % i)
275
+ assert journal.events(0) == []
276
+
277
+ def test_n_larger_than_feed_returns_all(self, sandbox):
278
+ journal.log("install", "only")
279
+ assert [e["subject"] for e in journal.events(9)] == ["only"]
@@ -1,6 +1,7 @@
1
1
  """Unit tests: boost_cli/core/util.py — time, hashing, versions, scoring."""
2
2
  from __future__ import annotations
3
3
 
4
+ import argparse
4
5
  import hashlib
5
6
  import re
6
7
  import time
@@ -635,3 +636,26 @@ class TestSafeComponent:
635
636
  # parent directory itself.
636
637
  assert util.safe_component("..") == "skill"
637
638
  assert util.safe_component(".") == "skill"
639
+
640
+
641
+ class TestPositiveInt:
642
+ """`util.positive_int` — the argparse type behind every -n/--limit flag."""
643
+
644
+ def test_accepts_one_and_above_exactly(self):
645
+ assert util.positive_int("1") == 1
646
+ assert util.positive_int("20") == 20
647
+
648
+ def test_zero_rejected_with_exact_message(self):
649
+ with pytest.raises(argparse.ArgumentTypeError) as exc:
650
+ util.positive_int("0")
651
+ assert str(exc.value) == "must be >= 1"
652
+
653
+ def test_negative_rejected_with_exact_message(self):
654
+ with pytest.raises(argparse.ArgumentTypeError) as exc:
655
+ util.positive_int("-1")
656
+ assert str(exc.value) == "must be >= 1"
657
+
658
+ def test_non_numeric_rejected_with_exact_message(self):
659
+ with pytest.raises(argparse.ArgumentTypeError) as exc:
660
+ util.positive_int("abc")
661
+ assert str(exc.value) == "invalid int value: 'abc'"