boost-skill-cli 1.0.266__tar.gz → 1.0.268__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 (505) hide show
  1. {boost_skill_cli-1.0.266/boost_skill_cli.egg-info → boost_skill_cli-1.0.268}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/store.py +50 -1
  4. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268/boost_skill_cli.egg-info}/PKG-INFO +1 -1
  5. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_skill_cli.egg-info/SOURCES.txt +3 -0
  6. boost_skill_cli-1.0.268/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +36 -0
  7. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap.html +33 -1
  8. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/release-tools.in +4 -0
  9. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/release-tools.txt +12 -0
  10. boost_skill_cli-1.0.268/scripts/check_licenses.py +108 -0
  11. boost_skill_cli-1.0.268/tests/unit/test_check_licenses.py +163 -0
  12. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_store.py +146 -0
  13. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.gitattributes +0 -0
  14. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.gitignore +0 -0
  15. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.gitleaks.toml +0 -0
  16. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.htmlvalidate.json +0 -0
  17. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.lighthouserc.json +0 -0
  18. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.lycheeignore +0 -0
  19. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.markdownlint-cli2.jsonc +0 -0
  20. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.pre-commit-config.yaml +0 -0
  21. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.stylelintrc.json +0 -0
  22. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.vale/styles/boost/Terminology.yml +0 -0
  23. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
  24. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/.vale.ini +0 -0
  25. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/CLAUDE.md +0 -0
  26. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/CODE_OF_CONDUCT.md +0 -0
  27. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/CONTRIBUTING.md +0 -0
  28. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/LICENSE +0 -0
  29. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/MANIFEST.in +0 -0
  30. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/Makefile +0 -0
  31. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/README.md +0 -0
  32. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/SECURITY.md +0 -0
  33. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost +0 -0
  34. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/__init__.py +0 -0
  35. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/__main__.py +0 -0
  36. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/cli.py +0 -0
  37. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/cliparse.py +0 -0
  38. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/__init__.py +0 -0
  39. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/_common.py +0 -0
  40. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/bmad.py +0 -0
  41. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/configuration.py +0 -0
  42. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/discovery.py +0 -0
  43. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/hooks.py +0 -0
  44. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/info.py +0 -0
  45. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/intelligence.py +0 -0
  46. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/pkg.py +0 -0
  47. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/quality.py +0 -0
  48. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/run.py +0 -0
  49. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/safety.py +0 -0
  50. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/taps.py +0 -0
  51. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/commands/team.py +0 -0
  52. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/__init__.py +0 -0
  53. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/adapters.py +0 -0
  54. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/agents.py +0 -0
  55. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/ai.py +0 -0
  56. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/capabilities.py +0 -0
  57. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/catalog.py +0 -0
  58. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/claude_settings.py +0 -0
  59. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/config.py +0 -0
  60. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/dense.py +0 -0
  61. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/ed25519.py +0 -0
  62. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/embed.py +0 -0
  63. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/faithfulness.py +0 -0
  64. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/frontmatter.py +0 -0
  65. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/gitutil.py +0 -0
  66. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/imperative.py +0 -0
  67. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/injectscan.py +0 -0
  68. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/integrity.py +0 -0
  69. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/journal.py +0 -0
  70. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/lockfile.py +0 -0
  71. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/logs.py +0 -0
  72. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/mcp.py +0 -0
  73. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/mcpdecl.py +0 -0
  74. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/minisign.py +0 -0
  75. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/nethttp.py +0 -0
  76. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/output.py +0 -0
  77. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/paths.py +0 -0
  78. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/policy.py +0 -0
  79. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/projectlock.py +0 -0
  80. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/provenance.py +0 -0
  81. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/rag.py +0 -0
  82. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/registry.py +0 -0
  83. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/resolve.py +0 -0
  84. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/rules.py +0 -0
  85. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/scopes.py +0 -0
  86. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/secretscan.py +0 -0
  87. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/selfupdate.py +0 -0
  88. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/serve.py +0 -0
  89. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/stackprobe.py +0 -0
  90. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/staleness.py +0 -0
  91. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/trustaudit.py +0 -0
  92. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/typosquat.py +0 -0
  93. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/updatediff.py +0 -0
  94. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/util.py +0 -0
  95. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/core/workflows.py +0 -0
  96. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/data/registries.json +0 -0
  97. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/errors.py +0 -0
  98. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_cli/spin.py +0 -0
  99. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  100. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  101. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_skill_cli.egg-info/requires.txt +0 -0
  102. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/boost_skill_cli.egg-info/top_level.txt +0 -0
  103. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/codecov.yml +0 -0
  104. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/.claude/settings.local.json +0 -0
  105. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/DEBUGGING.md +0 -0
  106. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/adapters.html +0 -0
  107. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/gifs/distill.gif +0 -0
  108. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/gifs/doctor.gif +0 -0
  109. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/gifs/explain.gif +0 -0
  110. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/gifs/hooks.gif +0 -0
  111. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/gifs/install.gif +0 -0
  112. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/gifs/pulse.gif +0 -0
  113. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/gifs/search.gif +0 -0
  114. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/gifs/tap.gif +0 -0
  115. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/tapes/distill.tape +0 -0
  116. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/tapes/doctor.tape +0 -0
  117. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/tapes/explain.tape +0 -0
  118. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/tapes/hooks.tape +0 -0
  119. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/tapes/install.tape +0 -0
  120. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/tapes/pulse.tape +0 -0
  121. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/tapes/search.tape +0 -0
  122. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel/tapes/tap.tape +0 -0
  123. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/carousel.html +0 -0
  124. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/commands.html +0 -0
  125. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/demo.gif +0 -0
  126. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/demo.tape +0 -0
  127. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/design-roadmap.html +0 -0
  128. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/eval.html +0 -0
  129. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/index.html +0 -0
  130. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/mcp-hub.html +0 -0
  131. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/rag-architecture.md +0 -0
  132. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D01.md +0 -0
  133. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D02.md +0 -0
  134. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D03.md +0 -0
  135. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D04.md +0 -0
  136. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D05.md +0 -0
  137. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D06.md +0 -0
  138. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D07.md +0 -0
  139. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D08.md +0 -0
  140. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D09.md +0 -0
  141. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D10.md +0 -0
  142. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D11.md +0 -0
  143. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D12.md +0 -0
  144. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D13.md +0 -0
  145. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D14.md +0 -0
  146. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D15.md +0 -0
  147. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D16.md +0 -0
  148. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D17.md +0 -0
  149. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D18.md +0 -0
  150. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D19.md +0 -0
  151. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D20.md +0 -0
  152. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D21.md +0 -0
  153. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D22.md +0 -0
  154. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D23.md +0 -0
  155. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D24.md +0 -0
  156. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D25.md +0 -0
  157. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/BOOST-D26.md +0 -0
  158. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
  159. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
  160. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
  161. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
  162. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
  163. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
  164. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
  165. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/boost-run-live-agents.md +0 -0
  166. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
  167. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
  168. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
  169. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
  170. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
  171. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
  172. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
  173. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
  174. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
  175. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/command-carousel-page.md +0 -0
  176. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/command-reference-docs-site.md +0 -0
  177. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
  178. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
  179. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
  180. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
  181. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
  182. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
  183. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
  184. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
  185. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
  186. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
  187. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
  188. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
  189. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
  190. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
  191. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
  192. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
  193. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
  194. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
  195. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
  196. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
  197. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
  198. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
  199. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
  200. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/github-community-health-files.md +0 -0
  201. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
  202. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
  203. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
  204. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/html-validation-html-validate.md +0 -0
  205. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
  206. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
  207. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
  208. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
  209. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
  210. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
  211. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
  212. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
  213. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
  214. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/license-compliance-scanning.md +0 -0
  215. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
  216. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
  217. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
  218. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
  219. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
  220. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
  221. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
  222. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
  223. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
  224. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
  225. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
  226. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
  227. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
  228. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mcp-aware-skills.md +0 -0
  229. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
  230. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
  231. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
  232. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
  233. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
  234. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
  235. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
  236. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
  237. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
  238. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
  239. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
  240. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
  241. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
  242. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
  243. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
  244. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
  245. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
  246. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
  247. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
  248. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
  249. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
  250. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
  251. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
  252. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
  253. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
  254. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
  255. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
  256. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
  257. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
  258. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
  259. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
  260. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
  261. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
  262. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
  263. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
  264. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
  265. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
  266. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
  267. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
  268. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
  269. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
  270. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/required-checks-config-drift.md +0 -0
  271. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
  272. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
  273. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
  274. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
  275. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
  276. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
  277. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
  278. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
  279. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
  280. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
  281. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
  282. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
  283. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
  284. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
  285. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
  286. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
  287. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
  288. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
  289. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
  290. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
  291. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
  292. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
  293. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
  294. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
  295. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
  296. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
  297. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
  298. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
  299. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
  300. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
  301. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
  302. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/typo-detection-codespell.md +0 -0
  303. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
  304. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
  305. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
  306. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
  307. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/update-diff-before-apply.md +0 -0
  308. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
  309. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
  310. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
  311. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
  312. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
  313. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
  314. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
  315. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
  316. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
  317. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/docs/roadmap/items/workspace-scope-install.md +0 -0
  318. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/eslint.config.mjs +0 -0
  319. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/examples/README.md +0 -0
  320. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/examples/adapt-demo.sh +0 -0
  321. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/examples/boost-run-prototype.sh +0 -0
  322. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/index.html +0 -0
  323. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/noxfile.py +0 -0
  324. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/pyproject.toml +0 -0
  325. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/coverage-tools.in +0 -0
  326. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/coverage-tools.txt +0 -0
  327. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/lint-tools.in +0 -0
  328. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/lint-tools.txt +0 -0
  329. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/mutation-tools.in +0 -0
  330. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/mutation-tools.txt +0 -0
  331. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/test-tools.in +0 -0
  332. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/requirements/test-tools.txt +0 -0
  333. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/a11y_check.py +0 -0
  334. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/bench_cli.sh +0 -0
  335. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/build_command_reference.py +0 -0
  336. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/build_registries.py +0 -0
  337. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/build_roadmap.py +0 -0
  338. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/check_anchors.py +0 -0
  339. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/check_required_checks.py +0 -0
  340. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/ensure_eval_corpus.sh +0 -0
  341. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/eval_explain.py +0 -0
  342. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/eval_recommend.py +0 -0
  343. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/eval_retrieval.py +0 -0
  344. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/eval_stats_summary.py +0 -0
  345. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/import_budget.py +0 -0
  346. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/lock_toolchain.py +0 -0
  347. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/mutation_gate.py +0 -0
  348. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/mutation_shards.py +0 -0
  349. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/mutation_weights.json +0 -0
  350. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/perf_gate.py +0 -0
  351. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/post_deploy_smoke.py +0 -0
  352. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/scripts/release_preflight.py +0 -0
  353. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/setup.cfg +0 -0
  354. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/sonar-project.properties +0 -0
  355. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/style/README.md +0 -0
  356. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/style/boost.css +0 -0
  357. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/style/boost.js +0 -0
  358. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/style/demo.html +0 -0
  359. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/adapt.feature +0 -0
  360. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/browse.feature +0 -0
  361. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/count.feature +0 -0
  362. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/discover.feature +0 -0
  363. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/doctor.feature +0 -0
  364. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/environment.py +0 -0
  365. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/explain.feature +0 -0
  366. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/index.feature +0 -0
  367. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/install.feature +0 -0
  368. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/list.feature +0 -0
  369. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/mcp.feature +0 -0
  370. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/search.feature +0 -0
  371. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/steps/cli_steps.py +0 -0
  372. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/steps/discovery_steps.py +0 -0
  373. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/steps/mcp_steps.py +0 -0
  374. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/bdd/features/steps/quality_steps.py +0 -0
  375. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/conftest.py +0 -0
  376. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/eval/baseline.json +0 -0
  377. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/eval/explain.jsonl +0 -0
  378. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/eval/golden.jsonl +0 -0
  379. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/eval/recommend.jsonl +0 -0
  380. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/eval/taps.txt +0 -0
  381. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_capabilities_policy.py +0 -0
  382. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_adapt.py +0 -0
  383. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_bmad.py +0 -0
  384. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_configuration.py +0 -0
  385. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_discovery.py +0 -0
  386. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_hooks.py +0 -0
  387. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_info.py +0 -0
  388. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_intelligence.py +0 -0
  389. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_pkg.py +0 -0
  390. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_quality.py +0 -0
  391. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_taps.py +0 -0
  392. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_cli_team.py +0 -0
  393. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_everyday_loop.py +0 -0
  394. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_integrity_enforce.py +0 -0
  395. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_property_parsers.py +0 -0
  396. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_run.py +0 -0
  397. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_tap_signing.py +0 -0
  398. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/functional/test_workspace_scope.py +0 -0
  399. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/README.md +0 -0
  400. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
  401. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
  402. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
  403. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
  404. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
  405. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
  406. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
  407. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
  408. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
  409. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
  410. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
  411. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
  412. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
  413. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/registry/02-https.txt +0 -0
  414. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
  415. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
  416. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
  417. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/registry/06-space.txt +0 -0
  418. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
  419. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
  420. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/fuzz_frontmatter.py +0 -0
  421. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/fuzz/fuzz_registry.py +0 -0
  422. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/make_fixture.py +0 -0
  423. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/perf/test_benchmarks.py +0 -0
  424. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/smoke.sh +0 -0
  425. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_a11y_check.py +0 -0
  426. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_adapters.py +0 -0
  427. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_adapters_multi.py +0 -0
  428. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_adapters_runner.py +0 -0
  429. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_agents.py +0 -0
  430. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_ai.py +0 -0
  431. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_capabilities.py +0 -0
  432. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_catalog.py +0 -0
  433. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_check_anchors.py +0 -0
  434. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_claude_settings.py +0 -0
  435. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_cliparse.py +0 -0
  436. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_command_reference_fresh.py +0 -0
  437. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_community_health_files.py +0 -0
  438. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_config.py +0 -0
  439. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_dense.py +0 -0
  440. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_dense_fallback.py +0 -0
  441. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_dependabot_config.py +0 -0
  442. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_docs_pages_linked.py +0 -0
  443. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_docsite_chrome.py +0 -0
  444. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_ed25519.py +0 -0
  445. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_embed.py +0 -0
  446. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_errors_and_cli_table.py +0 -0
  447. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_eval_stats_summary.py +0 -0
  448. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_faithfulness.py +0 -0
  449. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_frontmatter.py +0 -0
  450. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_fuzz_targets.py +0 -0
  451. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_gitleaks_config.py +0 -0
  452. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_gitutil.py +0 -0
  453. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_imperative.py +0 -0
  454. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_import_budget.py +0 -0
  455. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_injectscan.py +0 -0
  456. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_integrity.py +0 -0
  457. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_journal.py +0 -0
  458. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_lockfile.py +0 -0
  459. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_logs.py +0 -0
  460. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_marketing_counts.py +0 -0
  461. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_mcp.py +0 -0
  462. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_mcpdecl.py +0 -0
  463. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_minisign.py +0 -0
  464. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_mutation_hardening.py +0 -0
  465. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_mutation_shards.py +0 -0
  466. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_mutmut_source_paths.py +0 -0
  467. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_nethttp.py +0 -0
  468. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_output.py +0 -0
  469. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_paths.py +0 -0
  470. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_perf_gate.py +0 -0
  471. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_pkg_confusions.py +0 -0
  472. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_pkg_injection.py +0 -0
  473. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_pkg_secrets.py +0 -0
  474. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_policy.py +0 -0
  475. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_post_deploy_smoke.py +0 -0
  476. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_projectlock.py +0 -0
  477. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_provenance.py +0 -0
  478. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_rag.py +0 -0
  479. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_registries_fresh.py +0 -0
  480. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_registry.py +0 -0
  481. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_release_preflight.py +0 -0
  482. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_required_checks.py +0 -0
  483. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_resolve.py +0 -0
  484. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_roadmap_fresh.py +0 -0
  485. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_rules.py +0 -0
  486. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_scopes.py +0 -0
  487. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_secretscan.py +0 -0
  488. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_selfupdate.py +0 -0
  489. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_serve.py +0 -0
  490. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_spin.py +0 -0
  491. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_stackprobe.py +0 -0
  492. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_staleness.py +0 -0
  493. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_token_parity.py +0 -0
  494. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_toolchain_lock.py +0 -0
  495. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_trustaudit.py +0 -0
  496. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_typosquat.py +0 -0
  497. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_updatediff.py +0 -0
  498. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_util.py +0 -0
  499. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_version.py +0 -0
  500. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_workflow_timeouts.py +0 -0
  501. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/unit/test_workflows.py +0 -0
  502. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/visual/a11y_check.mjs +0 -0
  503. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/visual/console_check.mjs +0 -0
  504. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/tests/visual/package.json +0 -0
  505. {boost_skill_cli-1.0.266 → boost_skill_cli-1.0.268}/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.266
3
+ Version: 1.0.268
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.266'
22
- __version_tuple__ = version_tuple = (1, 0, 266)
21
+ __version__ = version = '1.0.268'
22
+ __version_tuple__ = version_tuple = (1, 0, 268)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -126,6 +126,41 @@ def preserved_agent_scope(only_agents: Optional[List[str]],
126
126
  return [a for a in recorded if a] or None
127
127
 
128
128
 
129
+ def declared_agent_scope(only_agents: Optional[List[str]],
130
+ existing: Optional[dict]) -> Optional[List[str]]:
131
+ """The scope to RECORD in the lock: an explicit narrowing, or the last one.
132
+
133
+ Deliberately *not* :func:`preserved_agent_scope`. That one answers "which
134
+ agents should this install link into", and falls back to the lock's
135
+ ``agents`` — which records what happens to be linked right now. Writing
136
+ that back as a declared scope would promote "these were the enabled agents
137
+ at install time" into "the user asked for exactly these", permanently
138
+ freezing a skill out of any agent enabled later. The two questions look
139
+ alike and are not, so they get separate functions.
140
+
141
+ Only an explicit ``--agent`` narrows. Absent that, an earlier declaration
142
+ is carried forward so ``update``/``reinstall`` don't drop it, and a skill
143
+ that was never narrowed keeps no scope at all (``None``).
144
+ """
145
+ if only_agents is not None:
146
+ return list(only_agents)
147
+ return (existing or {}).get("only_agents")
148
+
149
+
150
+ def scoped_agents(entry: dict, enabled: Dict[str, Path]) -> Dict[str, Path]:
151
+ """The enabled agents a locked skill is supposed to be linked into.
152
+
153
+ Fails **open**: an entry with no ``only_agents`` — every entry written
154
+ before this field existed — means "not narrowed", so it gets every enabled
155
+ agent. That keeps ``boost sync`` doing its other job, which is linking
156
+ already-installed skills into an agent that was enabled afterwards.
157
+ """
158
+ scope = entry.get("only_agents")
159
+ if not scope:
160
+ return enabled.copy()
161
+ return {a: d for a, d in enabled.items() if a in scope}
162
+
163
+
129
164
  def unlink_agents(name: str) -> List[str]:
130
165
  """Remove the ``name`` symlink from every enabled agent dir.
131
166
 
@@ -326,6 +361,11 @@ def install(entry: dict, force: bool = False,
326
361
  "pinned": bool((existing or {}).get("pinned")),
327
362
  "quarantined": False,
328
363
  "agents": res.linked,
364
+ # `agents` is what IS linked; `only_agents` is what the user ASKED for.
365
+ # sync needs the second: it links a skill into every enabled agent, and
366
+ # without a record of the request it cannot tell a deliberate `--agent`
367
+ # narrowing from a skill that simply predates a newly enabled agent.
368
+ "only_agents": declared_agent_scope(only_agents, existing),
329
369
  "tags": (existing or {}).get("tags", []),
330
370
  })
331
371
  journal.log("install", name, tap=entry["tap"], version=entry.get("version"))
@@ -806,6 +846,10 @@ def install_from_path(src_dir: Path, name: Optional[str] = None,
806
846
  "pinned": bool((existing or {}).get("pinned")),
807
847
  "quarantined": False,
808
848
  "agents": res.linked,
849
+ # `boost import --agent ...` narrows the same way `install` does, so it
850
+ # has to record the same declaration — otherwise the links are narrow
851
+ # but sync sees no scope and widens them right back.
852
+ "only_agents": declared_agent_scope(only_agents, existing),
809
853
  "tags": (existing or {}).get("tags", []),
810
854
  })
811
855
  journal.log("import", name, source=str(src_dir))
@@ -922,7 +966,12 @@ def sync_plan() -> Dict[str, list]:
922
966
  continue
923
967
  if entry.get("quarantined"):
924
968
  continue
925
- for agent, adir in agents.enabled_agents().items():
969
+ # Only the agents this skill was installed for. Walking every enabled
970
+ # agent made `boost sync` a second path to the scope leak that
971
+ # `preserved_agent_scope` closed on the install side: it reported a
972
+ # missing_link for each agent outside the narrowing, and sync_apply
973
+ # dutifully linked them, undoing `install --agent` in one command.
974
+ for agent, adir in scoped_agents(entry, agents.enabled_agents()).items():
926
975
  link = adir / name
927
976
  if not link.is_symlink() or not link.exists():
928
977
  plan["missing_links"].append((name, agent))
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.266
3
+ Version: 1.0.268
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -296,6 +296,7 @@ docs/roadmap/items/structured-json-log-output-mode.md
296
296
  docs/roadmap/items/supply-chain-posture-openssf-scorecard.md
297
297
  docs/roadmap/items/surface-every-docs-page-from-the-guide.md
298
298
  docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md
299
+ docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md
299
300
  docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md
300
301
  docs/roadmap/items/theme-asset-linting-stylelint-eslint.md
301
302
  docs/roadmap/items/typo-detection-codespell.md
@@ -333,6 +334,7 @@ scripts/build_command_reference.py
333
334
  scripts/build_registries.py
334
335
  scripts/build_roadmap.py
335
336
  scripts/check_anchors.py
337
+ scripts/check_licenses.py
336
338
  scripts/check_required_checks.py
337
339
  scripts/ensure_eval_corpus.sh
338
340
  scripts/eval_explain.py
@@ -426,6 +428,7 @@ tests/unit/test_ai.py
426
428
  tests/unit/test_capabilities.py
427
429
  tests/unit/test_catalog.py
428
430
  tests/unit/test_check_anchors.py
431
+ tests/unit/test_check_licenses.py
429
432
  tests/unit/test_claude_settings.py
430
433
  tests/unit/test_cliparse.py
431
434
  tests/unit/test_command_reference_fresh.py
@@ -0,0 +1,36 @@
1
+ ---
2
+ id: sync-relinks-into-every-agent-ignoring-scope
3
+ board: code
4
+ section: internals
5
+ status: shipped
6
+ category: Bug
7
+ complexity: S
8
+ impact: Med
9
+ wow: 2
10
+ note: the half of the scope leak PR #288 deliberately left open
11
+ order: 34
12
+ owner: loop/sync-agent-scope
13
+ pr:
14
+ title: <code>sync</code> relinks a narrowed skill into every agent
15
+ ---
16
+ <code>store.preserved_agent_scope</code> (PR #288) stopped <code>update</code> and
17
+ <code>reinstall</code> widening a skill installed with <code>--agent</code> narrowing, but
18
+ <code>sync_plan()</code> was a second, independent path to the same leak: it walked
19
+ <code>agents.enabled_agents()</code> for <b>every</b> locked skill and reported a
20
+ <code>missing_link</code> for any agent the skill was not linked into — the lock's recorded
21
+ scope was never consulted. <code>sync_apply</code> then dutifully linked them, so a
22
+ single <code>boost sync</code> undid the narrowing that <code>install --agent</code> asked for and
23
+ rewrote the lock to match.
24
+
25
+ It was left out of #288 because the fix is a real trade-off, not an oversight:
26
+ <code>boost sync</code> is also how a <i>newly enabled</i> agent picks up skills installed
27
+ before it existed, and honouring the lock's <code>agents</code> list would silently break that —
28
+ <code>agents</code> records what is linked <i>right now</i>, so reading it as a scope would
29
+ freeze every existing skill out of any agent enabled later.
30
+
31
+ Resolved by separating the two questions. A new <code>only_agents</code> field records what the
32
+ user <i>asked</i> for, written only by an explicit <code>--agent</code> and carried forward across
33
+ <code>update</code>/<code>reinstall</code>; <code>agents</code> keeps meaning what is actually linked.
34
+ <code>sync_plan</code> filters through <code>scoped_agents()</code>, which <b>fails open</b> — an entry
35
+ with no declaration, which is every entry written before this field existed, still fans out to
36
+ every enabled agent. So narrowing is honoured and the newly-enabled-agent path is untouched.
@@ -110,7 +110,7 @@
110
110
  <div class="stat"><b>16</b><span>Shipped</span></div>
111
111
  <div class="stat"><b>1</b><span>Next up</span></div>
112
112
  <div class="stat"><b>4</b><span>Planned</span></div>
113
- <div class="stat"><b>160</b><span>Loop finds</span></div>
113
+ <div class="stat"><b>161</b><span>Loop finds</span></div>
114
114
  <!-- /ROADMAP:stats -->
115
115
  </div>
116
116
  </section>
@@ -1102,6 +1102,38 @@ already used elsewhere in <code>pkg.py</code>.</p>
1102
1102
  </div>
1103
1103
  </article>
1104
1104
 
1105
+ <article class="cap rcard" id="sync-relinks-into-every-agent-ignoring-scope">
1106
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Bug</span></div>
1107
+ <h3><code>sync</code> relinks a narrowed skill into every agent</h3>
1108
+ <p><code>store.preserved_agent_scope</code> (PR #288) stopped <code>update</code> and
1109
+ <code>reinstall</code> widening a skill installed with <code>--agent</code> narrowing, but
1110
+ <code>sync_plan()</code> was a second, independent path to the same leak: it walked
1111
+ <code>agents.enabled_agents()</code> for <b>every</b> locked skill and reported a
1112
+ <code>missing_link</code> for any agent the skill was not linked into — the lock's recorded
1113
+ scope was never consulted. <code>sync_apply</code> then dutifully linked them, so a
1114
+ single <code>boost sync</code> undid the narrowing that <code>install --agent</code> asked for and
1115
+ rewrote the lock to match.
1116
+
1117
+ It was left out of #288 because the fix is a real trade-off, not an oversight:
1118
+ <code>boost sync</code> is also how a <i>newly enabled</i> agent picks up skills installed
1119
+ before it existed, and honouring the lock's <code>agents</code> list would silently break that —
1120
+ <code>agents</code> records what is linked <i>right now</i>, so reading it as a scope would
1121
+ freeze every existing skill out of any agent enabled later.
1122
+
1123
+ Resolved by separating the two questions. A new <code>only_agents</code> field records what the
1124
+ user <i>asked</i> for, written only by an explicit <code>--agent</code> and carried forward across
1125
+ <code>update</code>/<code>reinstall</code>; <code>agents</code> keeps meaning what is actually linked.
1126
+ <code>sync_plan</code> filters through <code>scoped_agents()</code>, which <b>fails open</b> — an entry
1127
+ with no declaration, which is every entry written before this field existed, still fans out to
1128
+ every enabled agent. So narrowing is honoured and the newly-enabled-agent path is untouched.</p>
1129
+ <div class="meta">
1130
+ <span class="m">Complexity <b>S</b></span>
1131
+ <span class="m">Impact <b>Med</b></span>
1132
+ <span class="m">Wow <b class="wow">★★</b></span>
1133
+ <span class="m">the half of the scope leak PR</span>
1134
+ </div>
1135
+ </article>
1136
+
1105
1137
  <article class="cap rcard" id="onboard-overwrites-generated-files-without-confirm">
1106
1138
  <div class="head"><span class="pill planned">Planned</span><span class="cat">UX · Bug</span></div>
1107
1139
  <h3><code>boost onboard</code> silently overwrites existing generated files</h3>
@@ -15,3 +15,7 @@ twine
15
15
  check-wheel-contents
16
16
  pyroma
17
17
  pip-audit
18
+ # SPDX license compliance of a resolved closure (licenses.yml). Pinned for the
19
+ # same reason as the rest: a verdict that changes on an upstream release of the
20
+ # scanner is a verdict about the scanner, not about the dependencies.
21
+ pip-licenses
@@ -483,6 +483,10 @@ pip-audit==2.10.1 \
483
483
  --hash=sha256:1eb4565d19ebe5d48996f4b770b4d2b32887e12cb12cfa637f1a064011b55ffc \
484
484
  --hash=sha256:99ef3f600a317c1945f1e89e227ef26e1c2d618429b8bd3fa6f4f7c440c4611a
485
485
  # via -r requirements/release-tools.in
486
+ pip-licenses==5.5.5 \
487
+ --hash=sha256:60750c006adf7a0910347b726e8ee9fee3bc8d2e7c8307a5c4ec0776c8e2a276 \
488
+ --hash=sha256:f4c4c6d9e6a03612cf59f29f19dc8ab54904d82e055b8e191498f2279a224e14
489
+ # via -r requirements/release-tools.in
486
490
  pip-requirements-parser==32.0.1 \
487
491
  --hash=sha256:4659bc2a667783e7a15d190f6fccf8b2486685b6dba4c19c3876314769c57526 \
488
492
  --hash=sha256:b4fa3a7a0be38243123cf9d1f3518da10c51bdb165a2b2985566247f9155a7d3
@@ -491,6 +495,10 @@ platformdirs==4.11.0 \
491
495
  --hash=sha256:0555d18370482847566ffabcaa53ad7c6c1c29f195989ae1ed634a05f76ea1e0 \
492
496
  --hash=sha256:360ccded2b7fce0af0ff80cc8f5942a1c5d99b0e856033acb030bfc634709e74
493
497
  # via pip-audit
498
+ prettytable==3.18.0 \
499
+ --hash=sha256:439217116152244369caf3d9f1caf2f9fe29b03bd79e88d2928c8e718c95d680 \
500
+ --hash=sha256:b3346e0e6f79180833aebaac088ae926340586cf6d7d991b9eb125b65f72313a
501
+ # via pip-licenses
494
502
  py-serializable==2.1.0 \
495
503
  --hash=sha256:9d5db56154a867a9b897c0163b33a793c804c80cee984116d02d49e4578fc103 \
496
504
  --hash=sha256:b56d5d686b5a03ba4f4db5e769dc32336e142fc3bd4d68a8c25579ebb0a67304
@@ -767,6 +775,10 @@ urllib3==2.7.0 \
767
775
  # id
768
776
  # requests
769
777
  # twine
778
+ wcwidth==0.8.2 \
779
+ --hash=sha256:91fbef97204b96a3d4d421609b80340b760cf33e26da123ff243d76b1fda8dda \
780
+ --hash=sha256:d63947694a0539a1d51e01eda7caf800c291020e6cdd7e28ad7b14dd33ad4f85
781
+ # via prettytable
770
782
  wheel-filename==1.4.2 \
771
783
  --hash=sha256:3fa599046443d4ca830d06e3d180cd0a675d5871af0a68daa5623318bb4d17e3 \
772
784
  --hash=sha256:87891c465dcbb40b40394a906f01a93214bdd51aa5d25e3a9a59cae62bc298fd
@@ -0,0 +1,108 @@
1
+ #!/usr/bin/env python3
2
+ """Fail when a resolved dependency's licence is incompatible with GPL-3.0.
3
+
4
+ `pip-audit` gates known CVEs; nothing gated licence *terms*. boost's shipped
5
+ runtime is stdlib-only, so the exposure is entirely in the opt-in extras —
6
+ `[eval]` alone resolves to 94 packages, including the pinned langchain stack —
7
+ and none of them had ever been checked against the project's own GPL-3.0.
8
+
9
+ Reads ``pip-licenses --format=json`` (stdin, or a path) rather than shelling out,
10
+ so the check is a pure function of its input and can be unit-tested without a
11
+ resolved environment.
12
+
13
+ Why not ``pip-licenses --fail-on``: it compares the declared licence string
14
+ exactly, and that string is not a well-formed identifier. Real values observed
15
+ in boost's own `[eval]` closure:
16
+
17
+ ragas -> "UNKNOWN" (no licence metadata at all)
18
+ tiktoken -> "MIT License\\n\\nCopyright (c) 2022 OpenAI, …" (the whole text)
19
+ sqlite-vec -> "MIT License, Apache License, Version 2.0" (two, comma-joined)
20
+
21
+ so matching is done here by regex over the whole field instead.
22
+
23
+ Usage:
24
+ pip-licenses --format=json | python3 scripts/check_licenses.py
25
+ python3 scripts/check_licenses.py licenses.json
26
+ """
27
+ from __future__ import annotations
28
+
29
+ import json
30
+ import re
31
+ import sys
32
+ from typing import List, Tuple
33
+
34
+ # (pattern, why). Matched case-insensitively against the whole declared licence
35
+ # string. Deliberately short: the aim is high-confidence incompatibility, not a
36
+ # taxonomy. LGPL, MPL and EPL are all fine to *consume* from a GPL-3.0 project
37
+ # and are not listed.
38
+ DENIED: Tuple[Tuple[str, str], ...] = (
39
+ (r"affero|\bagpl\b",
40
+ "AGPL adds network-use copyleft that GPL-3.0 does not carry"),
41
+ # GPLv2-*only* cannot be combined with GPL-3.0. "v2 or later" / "GPLv2+"
42
+ # can (it permits taking v3), so both spellings are excluded explicitly.
43
+ (r"gplv2(?!\+)|gpl-2\.0(?!-or-later)|general public license v2 \(",
44
+ "GPLv2-only is incompatible with GPL-3.0"),
45
+ (r"proprietary|all rights reserved|\bsspl\b|commons clause|\bbusl\b",
46
+ "not an open-source licence"),
47
+ )
48
+
49
+ # Packages whose *metadata* omits a licence even though the project has one.
50
+ # Each needs the upstream licence named, so the exception is auditable rather
51
+ # than a silence. Anything undeclared and unlisted fails.
52
+ UNDECLARED_OK = {
53
+ # https://github.com/explodinggradients/ragas — Apache-2.0 in the repo;
54
+ # the published wheel carries no License field or classifier.
55
+ "ragas": "Apache-2.0 upstream; wheel metadata omits it",
56
+ }
57
+
58
+ _UNDECLARED = re.compile(r"^\s*(unknown|none|)\s*$", re.IGNORECASE)
59
+
60
+
61
+ def is_undeclared(licence: str) -> bool:
62
+ """True when the package declared no licence at all."""
63
+ return bool(_UNDECLARED.match(licence or ""))
64
+
65
+
66
+ def violations(rows: List[dict]) -> List[str]:
67
+ """Human-readable problems in a ``pip-licenses --format=json`` payload."""
68
+ problems = []
69
+ for row in rows:
70
+ name = str(row.get("Name", "?"))
71
+ licence = str(row.get("License", ""))
72
+ if is_undeclared(licence):
73
+ if name.lower() not in UNDECLARED_OK:
74
+ problems.append(
75
+ "%s declares no licence — add it to UNDECLARED_OK with the "
76
+ "upstream licence, or drop the dependency" % name)
77
+ continue
78
+ for pattern, why in DENIED:
79
+ if re.search(pattern, licence, re.IGNORECASE):
80
+ problems.append("%s: %s (%s)" % (
81
+ name, why, licence.splitlines()[0][:60]))
82
+ break
83
+ return problems
84
+
85
+
86
+ def main(argv: List[str]) -> int:
87
+ raw = (open(argv[0], encoding="utf-8").read() if argv
88
+ else sys.stdin.read())
89
+ try:
90
+ rows = json.loads(raw)
91
+ except ValueError as e:
92
+ print("::error::could not parse pip-licenses JSON: %s" % e)
93
+ return 2
94
+ if not isinstance(rows, list) or not rows:
95
+ # An empty scan is not a pass: it means the environment was never
96
+ # populated, which is how a licence gate quietly stops gating.
97
+ print("::error::no packages in the licence report — nothing was scanned")
98
+ return 2
99
+
100
+ problems = violations(rows)
101
+ for p in problems:
102
+ print("::error::%s" % p)
103
+ print("checked %d package(s): %d problem(s)" % (len(rows), len(problems)))
104
+ return 1 if problems else 0
105
+
106
+
107
+ if __name__ == "__main__":
108
+ sys.exit(main(sys.argv[1:]))
@@ -0,0 +1,163 @@
1
+ """Unit tests: scripts/check_licenses.py — the SPDX compatibility gate.
2
+
3
+ Driven against the licence strings dependencies *actually* publish, not against
4
+ tidy identifiers. Every awkward value below was observed in boost's own
5
+ resolved closures, which is the whole reason the check matches by regex instead
6
+ of using ``pip-licenses --fail-on``.
7
+ """
8
+ from __future__ import annotations
9
+
10
+ import importlib.util
11
+ import json
12
+ from pathlib import Path
13
+
14
+ import pytest
15
+
16
+ SCRIPT = Path(__file__).resolve().parents[2] / "scripts" / "check_licenses.py"
17
+
18
+ # Verbatim from `pip-licenses --format=json` over `pip install .[eval]`.
19
+ TIKTOKEN = ("MIT License\n\nCopyright (c) 2022 OpenAI, Shantanu Jain\n\n"
20
+ "Permission is hereby granted, free of charge, …")
21
+ SQLITE_VEC = "MIT License, Apache License, Version 2.0"
22
+
23
+
24
+ @pytest.fixture(scope="module")
25
+ def mod():
26
+ spec = importlib.util.spec_from_file_location("check_licenses", SCRIPT)
27
+ m = importlib.util.module_from_spec(spec)
28
+ assert spec.loader is not None
29
+ spec.loader.exec_module(m)
30
+ return m
31
+
32
+
33
+ def rows(*pairs):
34
+ return [{"Name": n, "Version": "1.0", "License": lic} for n, lic in pairs]
35
+
36
+
37
+ class TestPermissiveLicencesPass:
38
+ @pytest.mark.parametrize("licence", [
39
+ "MIT", "MIT License", "BSD License", "BSD-3-Clause", "Apache-2.0",
40
+ "Apache Software License", "Python Software Foundation License",
41
+ "PSF-2.0", "MIT-CMU", "Apache-2.0 OR BSD-2-Clause",
42
+ "BSD-3-Clause AND 0BSD AND MIT AND Zlib AND CC0-1.0",
43
+ "MPL-2.0 AND (Apache-2.0 OR MIT)",
44
+ "Mozilla Public License 2.0 (MPL 2.0)",
45
+ SQLITE_VEC, TIKTOKEN,
46
+ ])
47
+ def test_no_violation(self, mod, licence):
48
+ assert mod.violations(rows(("pkg", licence))) == []
49
+
50
+ def test_lgpl_and_mpl_are_fine_to_consume(self, mod):
51
+ # Weak copyleft is not a problem for a GPL-3.0 project, and banning it
52
+ # would fail builds for no reason.
53
+ assert mod.violations(rows(
54
+ ("a", "GNU Lesser General Public License v3 (LGPLv3)"),
55
+ ("b", "GNU Lesser General Public License v2 or later (LGPLv2+)"),
56
+ ("c", "Mozilla Public License 2.0 (MPL 2.0)"),
57
+ ("d", "Eclipse Public License 2.0"))) == []
58
+
59
+ def test_gplv3_and_gplv2_or_later_pass(self, mod):
60
+ # GPL-3.0 is the project's own licence; "v2 or later" permits taking
61
+ # v3, so both combine cleanly. Only v2-*only* does not.
62
+ assert mod.violations(rows(
63
+ ("a", "GNU General Public License v3 (GPLv3)"),
64
+ ("b", "GNU General Public License v2 or later (GPLv2+)"),
65
+ ("c", "GPL-2.0-or-later"))) == []
66
+
67
+
68
+ class TestIncompatibleLicencesFail:
69
+ @pytest.mark.parametrize("licence", [
70
+ "GNU Affero General Public License v3",
71
+ "AGPL-3.0", "AGPL-3.0-only", "agpl-3.0-or-later",
72
+ ])
73
+ def test_agpl(self, mod, licence):
74
+ [problem] = mod.violations(rows(("pkg", licence)))
75
+ assert "network-use copyleft" in problem
76
+ assert problem.startswith("pkg: ")
77
+
78
+ @pytest.mark.parametrize("licence", [
79
+ "GNU General Public License v2 (GPLv2)", "GPL-2.0", "GPL-2.0-only",
80
+ ])
81
+ def test_gplv2_only(self, mod, licence):
82
+ [problem] = mod.violations(rows(("pkg", licence)))
83
+ assert "GPLv2-only" in problem
84
+
85
+ @pytest.mark.parametrize("licence", [
86
+ "Other/Proprietary License", "Proprietary", "All Rights Reserved",
87
+ "SSPL-1.0", "BUSL-1.1", "MIT with Commons Clause",
88
+ ])
89
+ def test_non_open_source(self, mod, licence):
90
+ [problem] = mod.violations(rows(("pkg", licence)))
91
+ assert "not an open-source licence" in problem
92
+
93
+ def test_a_multi_line_licence_reports_only_its_first_line(self, mod):
94
+ # A whole licence text in the failure message would bury the finding.
95
+ [problem] = mod.violations(rows(
96
+ ("pkg", "Other/Proprietary License\n\nblah\n" * 40)))
97
+ assert "\n" not in problem
98
+ assert len(problem) < 200
99
+
100
+ def test_every_offender_is_reported_not_just_the_first(self, mod):
101
+ problems = mod.violations(rows(("a", "AGPL-3.0"), ("b", "MIT"),
102
+ ("c", "Other/Proprietary License")))
103
+ assert len(problems) == 2
104
+ assert problems[0].startswith("a: ") and problems[1].startswith("c: ")
105
+
106
+ def test_a_package_is_reported_once_even_if_it_trips_twice(self, mod):
107
+ [problem] = mod.violations(rows(("pkg", "AGPL-3.0 AND Proprietary")))
108
+ assert problem.startswith("pkg: ")
109
+
110
+
111
+ class TestUndeclaredLicences:
112
+ @pytest.mark.parametrize("licence", ["UNKNOWN", "unknown", "", " ", "None"])
113
+ def test_recognised_as_undeclared(self, mod, licence):
114
+ assert mod.is_undeclared(licence) is True
115
+
116
+ @pytest.mark.parametrize("licence", ["MIT", "Unknown Software License"])
117
+ def test_not_undeclared(self, mod, licence):
118
+ assert mod.is_undeclared(licence) is False
119
+
120
+ def test_an_undeclared_package_fails_by_default(self, mod):
121
+ [problem] = mod.violations(rows(("mystery", "UNKNOWN")))
122
+ assert "declares no licence" in problem
123
+
124
+ def test_the_documented_exception_passes(self, mod):
125
+ # ragas is Apache-2.0 upstream; its wheel carries no License field.
126
+ assert mod.violations(rows(("ragas", "UNKNOWN"))) == []
127
+ assert "ragas" in mod.UNDECLARED_OK
128
+
129
+ def test_every_exception_names_the_upstream_licence(self, mod):
130
+ # An allowlist entry with no reason is indistinguishable from silence.
131
+ for pkg, reason in mod.UNDECLARED_OK.items():
132
+ assert reason.strip(), pkg
133
+ assert pkg == pkg.lower(), "keys are matched lowercased"
134
+
135
+
136
+ class TestMain:
137
+ def test_a_clean_report_exits_zero(self, mod, tmp_path, capsys):
138
+ p = tmp_path / "l.json"
139
+ p.write_text(json.dumps(rows(("a", "MIT"))), encoding="utf-8")
140
+ assert mod.main([str(p)]) == 0
141
+ assert "1 package(s): 0 problem(s)" in capsys.readouterr().out
142
+
143
+ def test_a_violation_exits_one_with_an_annotation(self, mod, tmp_path,
144
+ capsys):
145
+ p = tmp_path / "l.json"
146
+ p.write_text(json.dumps(rows(("a", "AGPL-3.0"))), encoding="utf-8")
147
+ assert mod.main([str(p)]) == 1
148
+ assert "::error::a: AGPL" in capsys.readouterr().out
149
+
150
+ def test_an_empty_report_is_a_failure_not_a_pass(self, mod, tmp_path,
151
+ capsys):
152
+ # This is how a licence gate quietly stops gating: the environment was
153
+ # never populated, every package passes, the step goes green.
154
+ p = tmp_path / "l.json"
155
+ p.write_text("[]", encoding="utf-8")
156
+ assert mod.main([str(p)]) == 2
157
+ assert "nothing was scanned" in capsys.readouterr().out
158
+
159
+ def test_unparseable_input_is_a_failure(self, mod, tmp_path, capsys):
160
+ p = tmp_path / "l.json"
161
+ p.write_text("not json", encoding="utf-8")
162
+ assert mod.main([str(p)]) == 2
163
+ assert "could not parse" in capsys.readouterr().out