boost-skill-cli 1.0.374__tar.gz → 1.0.375__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 (613) hide show
  1. {boost_skill_cli-1.0.374/boost_skill_cli.egg-info → boost_skill_cli-1.0.375}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375/boost_skill_cli.egg-info}/PKG-INFO +1 -1
  4. boost_skill_cli-1.0.375/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +83 -0
  5. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap.html +44 -2
  6. boost_skill_cli-1.0.375/scripts/ensure_eval_corpus.sh +45 -0
  7. boost_skill_cli-1.0.375/scripts/eval_corpus.py +423 -0
  8. boost_skill_cli-1.0.375/tests/eval/taps.txt +98 -0
  9. boost_skill_cli-1.0.375/tests/unit/test_eval_corpus.py +461 -0
  10. boost_skill_cli-1.0.374/docs/roadmap/items/eval-corpus-is-one-strangers-repo.md +0 -42
  11. boost_skill_cli-1.0.374/scripts/ensure_eval_corpus.sh +0 -30
  12. boost_skill_cli-1.0.374/scripts/eval_corpus.py +0 -142
  13. boost_skill_cli-1.0.374/tests/eval/taps.txt +0 -68
  14. boost_skill_cli-1.0.374/tests/unit/test_eval_corpus.py +0 -198
  15. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.gitattributes +0 -0
  16. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.gitignore +0 -0
  17. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.gitleaks.toml +0 -0
  18. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.htmlvalidate.json +0 -0
  19. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.lighthouserc.json +0 -0
  20. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.lycheeignore +0 -0
  21. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.markdownlint-cli2.jsonc +0 -0
  22. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.pre-commit-config.yaml +0 -0
  23. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.stylelintrc.json +0 -0
  24. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.vale/styles/boost/Terminology.yml +0 -0
  25. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.vale/styles/config/vocabularies/boost/accept.txt +0 -0
  26. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/.vale.ini +0 -0
  27. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/CLAUDE.md +0 -0
  28. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/CODE_OF_CONDUCT.md +0 -0
  29. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/CONTRIBUTING.md +0 -0
  30. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/LICENSE +0 -0
  31. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/MANIFEST.in +0 -0
  32. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/Makefile +0 -0
  33. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/README.md +0 -0
  34. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/SECURITY.md +0 -0
  35. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost +0 -0
  36. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/__init__.py +0 -0
  37. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/__main__.py +0 -0
  38. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/cli.py +0 -0
  39. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/cliparse.py +0 -0
  40. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/__init__.py +0 -0
  41. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/_common.py +0 -0
  42. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/bmad.py +0 -0
  43. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/configuration.py +0 -0
  44. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/discovery.py +0 -0
  45. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/hooks.py +0 -0
  46. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/info.py +0 -0
  47. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/intelligence.py +0 -0
  48. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/pkg.py +0 -0
  49. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/quality.py +0 -0
  50. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/run.py +0 -0
  51. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/safety.py +0 -0
  52. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/taps.py +0 -0
  53. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/commands/team.py +0 -0
  54. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/__init__.py +0 -0
  55. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/adapters.py +0 -0
  56. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/agents.py +0 -0
  57. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/ai.py +0 -0
  58. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/capabilities.py +0 -0
  59. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/catalog.py +0 -0
  60. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/chat.py +0 -0
  61. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/claude_settings.py +0 -0
  62. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/complete.py +0 -0
  63. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/config.py +0 -0
  64. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/dense.py +0 -0
  65. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/ed25519.py +0 -0
  66. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/embed.py +0 -0
  67. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/faithfulness.py +0 -0
  68. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/frontmatter.py +0 -0
  69. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/gitutil.py +0 -0
  70. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/imperative.py +0 -0
  71. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/injectscan.py +0 -0
  72. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/installscan.py +0 -0
  73. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/integrity.py +0 -0
  74. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/journal.py +0 -0
  75. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/localembed.py +0 -0
  76. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/lockfile.py +0 -0
  77. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/logs.py +0 -0
  78. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/mcp.py +0 -0
  79. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/mcpdecl.py +0 -0
  80. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/mcphost.py +0 -0
  81. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/minisign.py +0 -0
  82. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/nethttp.py +0 -0
  83. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/output.py +0 -0
  84. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/paths.py +0 -0
  85. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/policy.py +0 -0
  86. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/projectlock.py +0 -0
  87. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/provenance.py +0 -0
  88. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/rag.py +0 -0
  89. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/registry.py +0 -0
  90. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/resolve.py +0 -0
  91. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/rules.py +0 -0
  92. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/scopes.py +0 -0
  93. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/secretscan.py +0 -0
  94. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/selfupdate.py +0 -0
  95. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/serve.py +0 -0
  96. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/stackprobe.py +0 -0
  97. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/staleness.py +0 -0
  98. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/store.py +0 -0
  99. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/trustaudit.py +0 -0
  100. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/typosquat.py +0 -0
  101. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/updatediff.py +0 -0
  102. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/util.py +0 -0
  103. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/core/workflows.py +0 -0
  104. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/data/registries.json +0 -0
  105. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/errors.py +0 -0
  106. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_cli/spin.py +0 -0
  107. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
  108. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  109. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  110. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/requires.txt +0 -0
  111. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/boost_skill_cli.egg-info/top_level.txt +0 -0
  112. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/codecov.yml +0 -0
  113. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/.claude/settings.local.json +0 -0
  114. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/DEBUGGING.md +0 -0
  115. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/adapters.html +0 -0
  116. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/README.md +0 -0
  117. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/c4-components-core.md +0 -0
  118. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/c4-containers.md +0 -0
  119. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/c4-context.md +0 -0
  120. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/architecture/c4-dynamic-install.md +0 -0
  121. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/distill.gif +0 -0
  122. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/doctor.gif +0 -0
  123. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/explain.gif +0 -0
  124. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/hooks.gif +0 -0
  125. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/install.gif +0 -0
  126. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/pulse.gif +0 -0
  127. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/search.gif +0 -0
  128. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/gifs/tap.gif +0 -0
  129. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/distill.tape +0 -0
  130. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/doctor.tape +0 -0
  131. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/explain.tape +0 -0
  132. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/hooks.tape +0 -0
  133. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/install.tape +0 -0
  134. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/pulse.tape +0 -0
  135. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/search.tape +0 -0
  136. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel/tapes/tap.tape +0 -0
  137. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/carousel.html +0 -0
  138. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/chat.html +0 -0
  139. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/commands.html +0 -0
  140. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/demo-index.json +0 -0
  141. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/demo.gif +0 -0
  142. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/demo.html +0 -0
  143. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/demo.tape +0 -0
  144. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/design-roadmap.html +0 -0
  145. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/eval-latest.json +0 -0
  146. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/eval.html +0 -0
  147. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/index.html +0 -0
  148. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/mcp-hub.html +0 -0
  149. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/rag-architecture.md +0 -0
  150. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D01.md +0 -0
  151. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D02.md +0 -0
  152. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D03.md +0 -0
  153. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D04.md +0 -0
  154. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D05.md +0 -0
  155. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D06.md +0 -0
  156. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D07.md +0 -0
  157. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D08.md +0 -0
  158. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D09.md +0 -0
  159. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D10.md +0 -0
  160. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D11.md +0 -0
  161. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D12.md +0 -0
  162. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D13.md +0 -0
  163. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D14.md +0 -0
  164. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D15.md +0 -0
  165. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D16.md +0 -0
  166. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D17.md +0 -0
  167. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D18.md +0 -0
  168. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D19.md +0 -0
  169. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D20.md +0 -0
  170. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D21.md +0 -0
  171. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D22.md +0 -0
  172. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D23.md +0 -0
  173. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D24.md +0 -0
  174. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D25.md +0 -0
  175. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/BOOST-D26.md +0 -0
  176. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/a11y-sweep-flakes-on-color-contrast.md +0 -0
  177. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/accessibility-audit-pa11y-ci-axe-core.md +0 -0
  178. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/actionlint-skips-shellcheck-silently.md +0 -0
  179. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/adapter-conformance-langgraph-leg-never-ran.md +0 -0
  180. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ai-bridge-silent-failure-logging.md +0 -0
  181. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ambiguous-tap-short-name-resolution.md +0 -0
  182. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/atomic-corruption-safe-lock-file-writes.md +0 -0
  183. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/atomic-skill-install-temp-dir-swap.md +0 -0
  184. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/autonomous-ship-workflow-and-isolated-worktree.md +0 -0
  185. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/bm25-index-is-one-json-blob.md +0 -0
  186. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/boost-run-live-agents.md +0 -0
  187. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/bring-commands-under-mutation-testing.md +0 -0
  188. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/broken-link-and-anchor-checking-lychee.md +0 -0
  189. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/browse-crashes-selecting-a-rule-or-workflow.md +0 -0
  190. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/build-provenance-slsa-attestations.md +0 -0
  191. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/cache-the-catalog-entry-set-across-rag-queries.md +0 -0
  192. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/capability-manifest-and-least-privilege-policy.md +0 -0
  193. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/chat-cites-sources-by-a-number-it-never-prints.md +0 -0
  194. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/chat-command-grounded-conversational-search.md +0 -0
  195. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ci-job-timeout-minutes.md +0 -0
  196. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ci-summary-step-fails-itself.md +0 -0
  197. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ci-time-is-now-runner-queueing.md +0 -0
  198. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/clean-env-install-smoke-pip-and-pipx.md +0 -0
  199. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/code-scanning-rule-can-be-restored.md +0 -0
  200. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/codeql-job-rename-stranded-merge-protection.md +0 -0
  201. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/command-carousel-page.md +0 -0
  202. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/command-reference-docs-site.md +0 -0
  203. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/completions-complete-only-command-names.md +0 -0
  204. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/complexity-and-dead-code-radar-xenon-vulture.md +0 -0
  205. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/consolidate-skill-staleness-drift-logic-into-cor.md +0 -0
  206. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/coverage-dashboard-codecov-free-for-oss.md +0 -0
  207. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/coverage-guided-fuzzing-atheris-oss-fuzz.md +0 -0
  208. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/crash-listing-branch-untested.md +0 -0
  209. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/crash-recorder-error-paths-core-logs-py.md +0 -0
  210. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/demo-cannot-open-its-own-pr.md +0 -0
  211. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/demo-gif-workflow-has-never-succeeded.md +0 -0
  212. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dense-search-fallback-and-stale-tap-pruning.md +0 -0
  213. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dependabot-missing-pip-ecosystem.md +0 -0
  214. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dependabot-regeneration-drops-platform-pins.md +0 -0
  215. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dependabot-root-pip-entry-duplicates-requirements.md +0 -0
  216. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/dependency-cve-gate-pip-audit.md +0 -0
  217. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/docsite-chrome-and-content-audit.md +0 -0
  218. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/docstring-coverage-interrogate.md +0 -0
  219. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/doctor-checks-rules-and-workflows.md +0 -0
  220. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/end-of-options-guard-on-git-commands.md +0 -0
  221. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-corpus-cannot-see-real-retrieval.md +0 -0
  222. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-corpus-is-96x-smaller-than-a-real-install.md +0 -0
  223. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-corpus-pins-have-no-refresh-path.md +0 -0
  224. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-corpus-was-not-actually-pinned.md +0 -0
  225. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/eval-deduped-ranked-lists-by-name.md +0 -0
  226. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/extension-free-tests-core-dense-py.md +0 -0
  227. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/extract-mcp-http-servers-out-of-configuration-py.md +0 -0
  228. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/finish-mutation-hardening-across-core.md +0 -0
  229. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/fix-self-update-version-detection-dead-branch.md +0 -0
  230. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/fork-safe-network-proxy-handler.md +0 -0
  231. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/framework-adapter-langgraph.md +0 -0
  232. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/framework-adapter-multi-agent.md +0 -0
  233. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/framework-adapters-boost-adapt.md +0 -0
  234. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/frontmatter-scalar-over-coercion.md +0 -0
  235. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/gemini-cli-agent-target.md +0 -0
  236. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/github-community-health-files.md +0 -0
  237. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/github-pages-deploy-is-broken-every-push.md +0 -0
  238. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/golden-set-grades-by-name-not-by-skill.md +0 -0
  239. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/golden-set-statistical-power.md +0 -0
  240. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/hash-pinned-reproducible-toolchain-uv-lock.md +0 -0
  241. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/html-validation-html-validate.md +0 -0
  242. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/info-rejects-the-qualified-name-it-recommends.md +0 -0
  243. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/install-docs-never-mentioned-upgrading.md +0 -0
  244. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/install-from-path-bypasses-policy-and-pin-checks.md +0 -0
  245. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/install-resolves-skill-dependencies.md +0 -0
  246. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/install-scope-user-or-project.md +0 -0
  247. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/installed-skill-trust-audit.md +0 -0
  248. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/integrity-verification-boost-verify.md +0 -0
  249. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/internal-architecture-diagrams.md +0 -0
  250. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/invocation-pid-logging-for-crash-correlation.md +0 -0
  251. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/journal-rotation-race-and-handle-leak.md +0 -0
  252. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/keyless-dense-tier-local-static-embeddings.md +0 -0
  253. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/keyless-semantic-search-for-everyone.md +0 -0
  254. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/layering-guard-import-linter.md +0 -0
  255. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/license-compliance-scanning.md +0 -0
  256. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lighthouse-ci-on-the-pages-site.md +0 -0
  257. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lint-tap-misscopes-rule-workflow-entries.md +0 -0
  258. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/list-rules-and-workflows.md +0 -0
  259. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/localize-the-stored-bm25-snippet.md +0 -0
  260. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lock-invariant-cannot-parse-extras-pins.md +0 -0
  261. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lockfile-enforcement-and-commit-pinning.md +0 -0
  262. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/log-timestamps-mislabeled-utc.md +0 -0
  263. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/lowest-version-resolution-uv-resolution-lowest-d.md +0 -0
  264. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/main-has-no-branch-protection.md +0 -0
  265. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/main-ruleset-ref-pattern-has-literal-quotes.md +0 -0
  266. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/make-lint-masks-actionlint-failures.md +0 -0
  267. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/make-the-roadmaps-discoverable.md +0 -0
  268. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/markdown-consistency-markdownlint-cli2.md +0 -0
  269. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/markdownlint-lints-the-fuzz-corpus.md +0 -0
  270. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-aware-skills.md +0 -0
  271. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-check-skills-before-starting-a-task.md +0 -0
  272. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-hub-diagram-node-text-overflow.md +0 -0
  273. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-install-skips-the-injection-scan.md +0 -0
  274. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-launch-objc-fork-safety.md +0 -0
  275. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-one-benefit-nameable-task.md +0 -0
  276. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-register-names-server-before-env.md +0 -0
  277. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-search-before-reinventing.md +0 -0
  278. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-search-cost-was-understated.md +0 -0
  279. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-servers-ignore-install-scope.md +0 -0
  280. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mcp-startup-self-harden-fork-safety.md +0 -0
  281. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/memoize-config-load-in-process.md +0 -0
  282. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/merge-queue-would-deadlock-most-required-checks.md +0 -0
  283. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/merged-loop-branches-are-never-pruned.md +0 -0
  284. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/modernization-smells-refurb-pyupgrade.md +0 -0
  285. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-gate-was-the-whole-critical-path.md +0 -0
  286. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-hardening-core-frontmatter-py.md +0 -0
  287. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-hardening-core-gitutil-py.md +0 -0
  288. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-hardening-core-store-py.md +0 -0
  289. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mutation-shard-floor-is-one-file.md +0 -0
  290. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/mypy-strict-mode-for-commands.md +0 -0
  291. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/near-duplicate-items-eat-the-result-slots.md +0 -0
  292. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/negative-limit-inverts-log-pulse-output.md +0 -0
  293. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/onboard-overwrites-generated-files-without-confirm.md +0 -0
  294. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/one-command-every-env-nox.md +0 -0
  295. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/one-commit-can-cut-two-releases.md +0 -0
  296. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/one-shared-atomic-write-helper.md +0 -0
  297. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/package-metadata-validation-twine-check-friends.md +0 -0
  298. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/patch-coverage-gate-diff-cover.md +0 -0
  299. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/path-traversal-unsanitized-rule-workflow-name.md +0 -0
  300. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/performance-regression-gate-pytest-benchmark.md +0 -0
  301. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/pin-the-lint-toolchain.md +0 -0
  302. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/post-deploy-always-defeated-by-skipped-setup.md +0 -0
  303. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/post-deploy-smoke-headless-load-check.md +0 -0
  304. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/pre-release-python-canary-3-14t-free-threaded.md +0 -0
  305. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/prerequisites-and-semantic-search-setup.md +0 -0
  306. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/project-scope-across-every-command.md +0 -0
  307. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/project-scope-symlink-escape-on-write.md +0 -0
  308. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/promote-nav-footer-into-the-shared-style-system.md +0 -0
  309. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/prompt-injection-scanning-of-skill-markdown.md +0 -0
  310. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/property-based-tests-hypothesis-on-the-parsers.md +0 -0
  311. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/prose-and-terminology-linting-vale.md +0 -0
  312. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/prune-ignored-dirs-during-scan-dir-walk.md +0 -0
  313. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/publish-gate-ignores-pip-audit-and-metadata.md +0 -0
  314. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/publish-trigger-was-reachable-from-a-fork.md +0 -0
  315. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/pytest-tmpdir-cve-blocked-by-py39-floor.md +0 -0
  316. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/quality-dashboard-sonarcloud-free-for-oss.md +0 -0
  317. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ranx-significance-monitor.md +0 -0
  318. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/reconcile-the-theme-drift.md +0 -0
  319. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/refresh-the-marketing-surface.md +0 -0
  320. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/rel-time-tests-race-the-wall-clock.md +0 -0
  321. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/release-verifies-the-wrong-commit.md +0 -0
  322. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/required-checks-can-declare-a-check-that-deadlocks-prs.md +0 -0
  323. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/required-checks-config-drift.md +0 -0
  324. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/resolve-vendored-duplicate-copies.md +0 -0
  325. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/retrieval-quality-eval-harness.md +0 -0
  326. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/reuse-helpers-kill-minor-dead-work.md +0 -0
  327. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/roadmap-html-goes-stale-on-every-rebase.md +0 -0
  328. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/roadmap-page-weight-grows-without-bound.md +0 -0
  329. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/roadmap-perf-budget-has-no-local-guard.md +0 -0
  330. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/robust-tag-argument-parsing.md +0 -0
  331. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/ruff-016-widens-the-default-rule-set.md +0 -0
  332. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/rule-install-native-materialization.md +0 -0
  333. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/runner-egress-monitoring-stepsecurity-harden-run.md +0 -0
  334. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/runtime-explain-faithfulness-guardrail.md +0 -0
  335. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sbom-aware-scanning-osv-scanner.md +0 -0
  336. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sbom-declares-the-wrong-version.md +0 -0
  337. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sbom-on-every-release-cyclonedx-syft.md +0 -0
  338. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sbom-release-event-never-fires.md +0 -0
  339. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/scan-and-sync-rules-and-workflows.md +0 -0
  340. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/scheduled-toolchain-lock-regeneration.md +0 -0
  341. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/scorecard-findings-triage.md +0 -0
  342. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/second-type-checker-pyright.md +0 -0
  343. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/secret-and-pii-scanning-of-installed-skills.md +0 -0
  344. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/secret-scanning-gitleaks-push-protection.md +0 -0
  345. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/security-linting-bandit-via-ruff-s-rules.md +0 -0
  346. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/self-update-broken-for-pip-pipx-installs.md +0 -0
  347. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/serve-py-traversal-guards-untested.md +0 -0
  348. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/shift-left-gate-pre-commit-pre-commit-ci.md +0 -0
  349. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/single-imperative-rule-extractor.md +0 -0
  350. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/single-tech-stack-prober.md +0 -0
  351. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/split-oversized-command-modules.md +0 -0
  352. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/startup-and-import-time-budget-x-importtime.md +0 -0
  353. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/stop-re-serializing-entry-meta-on-every-search.md +0 -0
  354. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/structured-json-log-output-mode.md +0 -0
  355. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/supply-chain-posture-openssf-scorecard.md +0 -0
  356. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/surface-every-docs-page-from-the-guide.md +0 -0
  357. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sync-deletes-unowned-broken-symlinks.md +0 -0
  358. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/sync-relinks-into-every-agent-ignoring-scope.md +0 -0
  359. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/tap-signing-and-provenance-sigstore-minisign.md +0 -0
  360. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/theme-asset-linting-stylelint-eslint.md +0 -0
  361. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/typo-detection-codespell.md +0 -0
  362. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/typosquat-and-name-confusion-detection.md +0 -0
  363. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/unify-tilde-two-copies-have-a-boundary-bug.md +0 -0
  364. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/uninstall-has-no-confirmation-prompt.md +0 -0
  365. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/untrack-generated-build-noise.md +0 -0
  366. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/update-diff-before-apply.md +0 -0
  367. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/update-refreshes-rules-and-workflows.md +0 -0
  368. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/update-reinstall-widens-agent-scope.md +0 -0
  369. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/visual-regression-pass-on-the-guide.md +0 -0
  370. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/widen-the-ruff-rule-surface-b-sim-c4-perf-ruf.md +0 -0
  371. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/windows-in-the-ci-matrix.md +0 -0
  372. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/wire-bdd-suite-into-ci.md +0 -0
  373. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/workflow-install-native-materialization.md +0 -0
  374. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/workflow-linting-actionlint.md +0 -0
  375. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/workflow-sast-zizmor.md +0 -0
  376. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/workspace-scope-install.md +0 -0
  377. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/docs/roadmap/items/zizmor-pin-is-a-yanked-release.md +0 -0
  378. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/eslint.config.mjs +0 -0
  379. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/README.md +0 -0
  380. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/__init__.py +0 -0
  381. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/baseline.json +0 -0
  382. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/faithfulness.py +0 -0
  383. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/golden_set.json +0 -0
  384. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/make_corpus.py +0 -0
  385. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/make_golden.py +0 -0
  386. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/metrics.py +0 -0
  387. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/evals/run_evals.py +0 -0
  388. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/examples/README.md +0 -0
  389. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/examples/adapt-demo.sh +0 -0
  390. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/examples/boost-run-prototype.sh +0 -0
  391. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/index.html +0 -0
  392. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/noxfile.py +0 -0
  393. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/pyproject.toml +0 -0
  394. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/coverage-tools.in +0 -0
  395. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/coverage-tools.txt +0 -0
  396. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/lint-tools.in +0 -0
  397. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/lint-tools.txt +0 -0
  398. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/mutation-tools.in +0 -0
  399. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/mutation-tools.txt +0 -0
  400. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/platform-pins.lock +0 -0
  401. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/release-tools.in +0 -0
  402. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/release-tools.txt +0 -0
  403. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/test-tools.in +0 -0
  404. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/requirements/test-tools.txt +0 -0
  405. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/a11y_check.py +0 -0
  406. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/bench_cli.sh +0 -0
  407. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/build_command_reference.py +0 -0
  408. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/build_demo_index.py +0 -0
  409. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/build_registries.py +0 -0
  410. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/build_roadmap.py +0 -0
  411. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/check_anchors.py +0 -0
  412. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/check_licenses.py +0 -0
  413. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/check_required_checks.py +0 -0
  414. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_explain.py +0 -0
  415. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_gate.py +0 -0
  416. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_recommend.py +0 -0
  417. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_retrieval.py +0 -0
  418. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/eval_stats_summary.py +0 -0
  419. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/import_budget.py +0 -0
  420. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/lock_toolchain.py +0 -0
  421. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/mutation_gate.py +0 -0
  422. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/mutation_shards.py +0 -0
  423. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/mutation_weights.json +0 -0
  424. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/perf_gate.py +0 -0
  425. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/post_deploy_smoke.py +0 -0
  426. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/publish_eval_json.py +0 -0
  427. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/release_guard.py +0 -0
  428. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/scripts/release_preflight.py +0 -0
  429. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/setup.cfg +0 -0
  430. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/sonar-project.properties +0 -0
  431. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/style/README.md +0 -0
  432. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/style/boost.css +0 -0
  433. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/style/boost.js +0 -0
  434. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/style/demo.html +0 -0
  435. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/adapt.feature +0 -0
  436. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/browse.feature +0 -0
  437. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/count.feature +0 -0
  438. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/discover.feature +0 -0
  439. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/doctor.feature +0 -0
  440. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/environment.py +0 -0
  441. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/explain.feature +0 -0
  442. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/index.feature +0 -0
  443. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/install.feature +0 -0
  444. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/list.feature +0 -0
  445. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/mcp.feature +0 -0
  446. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/search.feature +0 -0
  447. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/steps/cli_steps.py +0 -0
  448. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/steps/discovery_steps.py +0 -0
  449. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/steps/mcp_steps.py +0 -0
  450. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/bdd/features/steps/quality_steps.py +0 -0
  451. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/conftest.py +0 -0
  452. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/baseline.json +0 -0
  453. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/explain.jsonl +0 -0
  454. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/golden-natural.jsonl +0 -0
  455. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/golden.jsonl +0 -0
  456. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/eval/recommend.jsonl +0 -0
  457. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_capabilities_policy.py +0 -0
  458. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_adapt.py +0 -0
  459. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_bmad.py +0 -0
  460. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_chat.py +0 -0
  461. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_configuration.py +0 -0
  462. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_discovery.py +0 -0
  463. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_hooks.py +0 -0
  464. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_info.py +0 -0
  465. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_intelligence.py +0 -0
  466. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_pkg.py +0 -0
  467. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_quality.py +0 -0
  468. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_taps.py +0 -0
  469. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_cli_team.py +0 -0
  470. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_everyday_loop.py +0 -0
  471. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_integrity_enforce.py +0 -0
  472. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_property_parsers.py +0 -0
  473. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_run.py +0 -0
  474. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_tap_signing.py +0 -0
  475. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/functional/test_workspace_scope.py +0 -0
  476. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/README.md +0 -0
  477. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/01-typical.md +0 -0
  478. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/02-lossy-version.md +0 -0
  479. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/03-lossy-numbers.md +0 -0
  480. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/04-lists.md +0 -0
  481. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/05-nested.md +0 -0
  482. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/06-empty-block.md +0 -0
  483. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/07-unterminated.md +0 -0
  484. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/08-none.md +0 -0
  485. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/09-unbalanced-quote.md +0 -0
  486. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/10-keywords.md +0 -0
  487. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/11-crlf.md +0 -0
  488. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/frontmatter/12-bom.md +0 -0
  489. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/01-shorthand.txt +0 -0
  490. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/02-https.txt +0 -0
  491. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/03-ssh.txt +0 -0
  492. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/04-traversal.txt +0 -0
  493. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/05-empty.txt +0 -0
  494. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/06-space.txt +0 -0
  495. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/07-slash.txt +0 -0
  496. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/corpus/registry/08-bare-host.txt +0 -0
  497. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/fuzz_frontmatter.py +0 -0
  498. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/fuzz/fuzz_registry.py +0 -0
  499. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/make_fixture.py +0 -0
  500. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/perf/test_benchmarks.py +0 -0
  501. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/smoke.sh +0 -0
  502. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_a11y_check.py +0 -0
  503. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_adapters.py +0 -0
  504. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_adapters_multi.py +0 -0
  505. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_adapters_runner.py +0 -0
  506. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_agents.py +0 -0
  507. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_ai.py +0 -0
  508. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_capabilities.py +0 -0
  509. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_catalog.py +0 -0
  510. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_chat.py +0 -0
  511. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_check_anchors.py +0 -0
  512. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_check_licenses.py +0 -0
  513. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_claude_settings.py +0 -0
  514. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_cliparse.py +0 -0
  515. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_codeql_analysis_key.py +0 -0
  516. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_command_reference_fresh.py +0 -0
  517. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_community_health_files.py +0 -0
  518. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_complete.py +0 -0
  519. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_config.py +0 -0
  520. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_content_dedupe.py +0 -0
  521. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dedup_trust.py +0 -0
  522. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_demo_index.py +0 -0
  523. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense.py +0 -0
  524. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense_fallback.py +0 -0
  525. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense_fix_hint.py +0 -0
  526. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense_shards.py +0 -0
  527. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dense_status.py +0 -0
  528. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_dependabot_config.py +0 -0
  529. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_docs_pages_linked.py +0 -0
  530. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_docsite_chrome.py +0 -0
  531. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_ed25519.py +0 -0
  532. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_embed.py +0 -0
  533. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_embed_local.py +0 -0
  534. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_entry_key.py +0 -0
  535. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_errors_and_cli_table.py +0 -0
  536. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_baseline.py +0 -0
  537. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_faithfulness.py +0 -0
  538. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_gate.py +0 -0
  539. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_grading.py +0 -0
  540. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_metrics.py +0 -0
  541. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_eval_stats_summary.py +0 -0
  542. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_faithfulness.py +0 -0
  543. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_frontmatter.py +0 -0
  544. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_fuzz_targets.py +0 -0
  545. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_gitleaks_config.py +0 -0
  546. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_gitutil.py +0 -0
  547. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_imperative.py +0 -0
  548. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_import_budget.py +0 -0
  549. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_injectscan.py +0 -0
  550. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_installscan.py +0 -0
  551. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_integrity.py +0 -0
  552. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_journal.py +0 -0
  553. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_localembed.py +0 -0
  554. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_localembed_e2e.py +0 -0
  555. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_lockfile.py +0 -0
  556. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_logs.py +0 -0
  557. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_marketing_counts.py +0 -0
  558. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mcp.py +0 -0
  559. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mcp_install_scan.py +0 -0
  560. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mcpdecl.py +0 -0
  561. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mcphost.py +0 -0
  562. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_minisign.py +0 -0
  563. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mutation_hardening.py +0 -0
  564. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mutation_shards.py +0 -0
  565. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mutation_subfile_shards.py +0 -0
  566. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_mutmut_source_paths.py +0 -0
  567. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_nethttp.py +0 -0
  568. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_output.py +0 -0
  569. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_paths.py +0 -0
  570. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_perf_gate.py +0 -0
  571. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_pkg_confusions.py +0 -0
  572. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_pkg_injection.py +0 -0
  573. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_pkg_secrets.py +0 -0
  574. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_platform_pins.py +0 -0
  575. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_policy.py +0 -0
  576. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_post_deploy_smoke.py +0 -0
  577. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_project_mcp_sidecar.py +0 -0
  578. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_projectlock.py +0 -0
  579. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_provenance.py +0 -0
  580. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_rag.py +0 -0
  581. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_rag_fusion.py +0 -0
  582. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_registries_fresh.py +0 -0
  583. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_registry.py +0 -0
  584. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_registry_categories.py +0 -0
  585. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_release_guard.py +0 -0
  586. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_release_preflight.py +0 -0
  587. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_required_checks.py +0 -0
  588. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_resolve.py +0 -0
  589. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_roadmap_fresh.py +0 -0
  590. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_rules.py +0 -0
  591. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_scopes.py +0 -0
  592. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_secretscan.py +0 -0
  593. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_selfupdate.py +0 -0
  594. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_serve.py +0 -0
  595. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_spin.py +0 -0
  596. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_stackprobe.py +0 -0
  597. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_staleness.py +0 -0
  598. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_store.py +0 -0
  599. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_token_parity.py +0 -0
  600. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_toolchain_lock.py +0 -0
  601. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_trustaudit.py +0 -0
  602. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_typosquat.py +0 -0
  603. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_updatediff.py +0 -0
  604. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_util.py +0 -0
  605. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_version.py +0 -0
  606. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_workflow_concurrency.py +0 -0
  607. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_workflow_timeouts.py +0 -0
  608. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/unit/test_workflows.py +0 -0
  609. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/visual/a11y_check.mjs +0 -0
  610. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/visual/console_check.mjs +0 -0
  611. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/visual/package-lock.json +0 -0
  612. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/tests/visual/package.json +0 -0
  613. {boost_skill_cli-1.0.374 → boost_skill_cli-1.0.375}/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.374
3
+ Version: 1.0.375
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.374'
22
- __version_tuple__ = version_tuple = (1, 0, 374)
21
+ __version__ = version = '1.0.375'
22
+ __version_tuple__ = version_tuple = (1, 0, 375)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.374
3
+ Version: 1.0.375
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -0,0 +1,83 @@
1
+ ---
2
+ id: eval-corpus-is-one-strangers-repo
3
+ board: code
4
+ section: internals
5
+ status: shipped
6
+ category: Eval · Correctness
7
+ complexity: S
8
+ impact: High
9
+ wow: 3
10
+ note: one third-party repo is 62% of the gate's corpus, and if it disappears every PR goes red
11
+ order: 84
12
+ owner: loop/eval-corpus-availability
13
+ pr: 428
14
+ title: 62% of the required gate's corpus is a single third-party repository
15
+ ---
16
+ <b>Pinning the eval corpus to commit SHAs fixed drift. It did not fix concentration, and cannot fix
17
+ availability.</b> The twenty repositories in <code>tests/eval/taps.txt</code> resolve to 10,152
18
+ entries, wildly unevenly: <code>sickn33/antigravity-awesome-skills</code> is <b>6,309 of them
19
+ (62%)</b> and <code>affaan-m/ECC</code> another 1,616 (16%). Two strangers' repositories are
20
+ <b>78%</b> of what this project measures retrieval quality against.
21
+
22
+ <b>The failure mode is every open PR going red at once.</b>
23
+ <code>ensure_eval_corpus.sh</code> runs under <code>set -euo pipefail</code> and a failed clone takes
24
+ it with it &mdash; verified, not assumed: one unreachable repo in the list exits <b>1</b>, failing
25
+ CI's <code>lint</code> job, a required context. A pinned SHA does not help, because a commit still
26
+ has to be <em>fetchable</em>, and a repo that is deleted, renamed or made private takes its history
27
+ along. Not hypothetical for twenty personal repos: one was already missing from the machine that
28
+ measured this.
29
+
30
+ <b>It also biases the numbers while everything is up.</b> 62% of the corpus being one publisher's
31
+ house style is a sampling bias in every recall figure the project reports.
32
+
33
+ <b>Options, none obviously right.</b> <em>Vendor</em> the needed files into the repo &mdash; no
34
+ network, no third parties, but a corpus that no longer resembles a real tap. <em>Cache</em> the
35
+ clones in CI keyed on the taps file, so a disappearance degrades to a stale corpus rather than a red
36
+ gate, though a cold cache still fails. <em>Rebalance</em> so no single source exceeds some share,
37
+ costing corpus size and drawing an arbitrary line. <em>Fail soft</em> on N missing repos, which keeps
38
+ merges flowing but silently weakens the gate &mdash; the failure mode this line of work has been
39
+ removing. Not proposed: dropping or lowering the gate.
40
+
41
+ <b>Provenance.</b> The per-repo counts had to be printed to verify the pins in
42
+ [[eval-corpus-was-not-actually-pinned]]; the distribution was the surprise.
43
+
44
+ <b>Measured, and it eliminates one of the four options.</b> &ldquo;Fail soft on N missing repos&rdquo;
45
+ reads like the pragmatic choice. It is the dangerous one, because a corpus that loses a repo does not
46
+ get harder to pass &mdash; it gets easier. Same 91-query required set, one repo removed and everything
47
+ else identical: <code>all 20 &rarr; 10,152 entries, <b>0.852 / 0.473 / 0.605 / 0.657</b></code><br>
48
+ <code>minus sickn33 (62%) &rarr; 3,843, <b>0.885 / 0.593 / 0.711 / 0.746</b></code><br>
49
+ <code>minus that and ECC (78%) &rarr; 2,227, <b>0.967 / 0.659 / 0.769 / 0.814</b></code><br>
50
+ <code>minus LessUp (holds golden targets) &rarr; 9,682, <b>0.676 / 0.374 / 0.483 / 0.523</b></code><br>
51
+ <code>floors &rarr; 0.780 / 0.400 / 0.520 / 0.580</code>
52
+
53
+ So dropping a <em>scale</em> repo sails through all four floors having measured a third of the
54
+ intended corpus, and dropping a repo that carries golden targets fails all four in a way
55
+ indistinguishable from &ldquo;this PR broke retrieval&rdquo;. Fail-soft is unsafe in both directions.
56
+ The same table also kills <em>rebalancing by trimming</em>: cutting the big repo to fix the 62% would
57
+ inflate every published number. Diluting concentration means adding breadth, which is
58
+ [[eval-corpus-is-96x-smaller-than-a-real-install]]'s problem, not this one.
59
+
60
+ <b>What shipped.</b> The corpus is now <em>verifiable</em> and its unavailability
61
+ <em>distinguishable</em>. Each <code>taps.txt</code> row carries an entry count beside its SHA, and
62
+ <code>--ensure</code> refuses to leave a corpus that does not match &mdash; so the "quietly measured
63
+ 3,843 entries" case above cannot reach the scorer. Unreachable repos exit <b>75</b> (EX_TEMPFAIL)
64
+ rather than 1, and every failing repo is named rather than just the first, so a third party's outage
65
+ stops reading as a regression here. CI restores the clones from a cache keyed on the tap list's
66
+ content, which is what actually stops one deleted repository reddening every open PR; only
67
+ third-party bytes are cached, never anything this repo derives, and there are no
68
+ <code>restore-keys</code> &mdash; a near-miss restore would carry taps this file no longer pins, and
69
+ the index is built from <em>every configured tap</em>. That last hazard is now checked directly:
70
+ a <code>BOOST_HOME</code> holding taps outside the list is a hard failure, which is exactly what
71
+ [[local-boost-install-is-not-the-eval-corpus]] walked into from the other side.
72
+
73
+ <b>A second, closer bug fell out of it.</b> The sentinel that makes a local <code>make eval</code>
74
+ fast was <em>empty</em> &mdash; it meant &ldquo;some corpus was built here&rdquo;. So editing
75
+ <code>taps.txt</code> (moving a pin, adding a repo) left the previous corpus in place and scored it
76
+ against the new file's baseline, silently, for as long as the sentinel survived. It now carries the
77
+ tap list's digest, so an edit is a cache miss.
78
+
79
+ <b>What did not ship, and why.</b> The 62% itself. There is no honest way to fix it by removing
80
+ anything, and adding breadth changes every published number and needs its own re-baselining. What is
81
+ enforced instead is a ratchet: <code>MAX_SHARE</code> fails the audit if any single publisher goes
82
+ above 65%, ~3 points over today's measured 62.1%. That stops it getting worse without pretending it
83
+ is fixed.
@@ -2646,8 +2646,9 @@ rank conventions. Measuring that is what exposed the name-collapse underneath it
2646
2646
  </article>
2647
2647
 
2648
2648
  <article class="cap rcard" id="eval-corpus-is-one-strangers-repo">
2649
- <div class="head"><span class="pill planned">Planned</span><span class="cat">Eval · Correctness</span></div>
2649
+ <div class="head"><span class="pill shipped">Shipped</span><span class="cat">Eval · Correctness</span></div>
2650
2650
  <h3>62% of the required gate's corpus is a single third-party repository</h3>
2651
+ <details class="cardbody"><summary>Write-up</summary>
2651
2652
  <p><b>Pinning the eval corpus to commit SHAs fixed drift. It did not fix concentration, and cannot fix
2652
2653
  availability.</b> The twenty repositories in <code>tests/eval/taps.txt</code> resolve to 10,152
2653
2654
  entries, wildly unevenly: <code>sickn33/antigravity-awesome-skills</code> is <b>6,309 of them
@@ -2674,7 +2675,48 @@ merges flowing but silently weakens the gate &mdash; the failure mode this line
2674
2675
  removing. Not proposed: dropping or lowering the gate.
2675
2676
 
2676
2677
  <b>Provenance.</b> The per-repo counts had to be printed to verify the pins in
2677
- [[eval-corpus-was-not-actually-pinned]]; the distribution was the surprise.</p>
2678
+ [[eval-corpus-was-not-actually-pinned]]; the distribution was the surprise.
2679
+
2680
+ <b>Measured, and it eliminates one of the four options.</b> &ldquo;Fail soft on N missing repos&rdquo;
2681
+ reads like the pragmatic choice. It is the dangerous one, because a corpus that loses a repo does not
2682
+ get harder to pass &mdash; it gets easier. Same 91-query required set, one repo removed and everything
2683
+ else identical: <code>all 20 &rarr; 10,152 entries, <b>0.852 / 0.473 / 0.605 / 0.657</b></code><br>
2684
+ <code>minus sickn33 (62%) &rarr; 3,843, <b>0.885 / 0.593 / 0.711 / 0.746</b></code><br>
2685
+ <code>minus that and ECC (78%) &rarr; 2,227, <b>0.967 / 0.659 / 0.769 / 0.814</b></code><br>
2686
+ <code>minus LessUp (holds golden targets) &rarr; 9,682, <b>0.676 / 0.374 / 0.483 / 0.523</b></code><br>
2687
+ <code>floors &rarr; 0.780 / 0.400 / 0.520 / 0.580</code>
2688
+
2689
+ So dropping a <em>scale</em> repo sails through all four floors having measured a third of the
2690
+ intended corpus, and dropping a repo that carries golden targets fails all four in a way
2691
+ indistinguishable from &ldquo;this PR broke retrieval&rdquo;. Fail-soft is unsafe in both directions.
2692
+ The same table also kills <em>rebalancing by trimming</em>: cutting the big repo to fix the 62% would
2693
+ inflate every published number. Diluting concentration means adding breadth, which is
2694
+ [[eval-corpus-is-96x-smaller-than-a-real-install]]'s problem, not this one.
2695
+
2696
+ <b>What shipped.</b> The corpus is now <em>verifiable</em> and its unavailability
2697
+ <em>distinguishable</em>. Each <code>taps.txt</code> row carries an entry count beside its SHA, and
2698
+ <code>--ensure</code> refuses to leave a corpus that does not match &mdash; so the "quietly measured
2699
+ 3,843 entries" case above cannot reach the scorer. Unreachable repos exit <b>75</b> (EX_TEMPFAIL)
2700
+ rather than 1, and every failing repo is named rather than just the first, so a third party's outage
2701
+ stops reading as a regression here. CI restores the clones from a cache keyed on the tap list's
2702
+ content, which is what actually stops one deleted repository reddening every open PR; only
2703
+ third-party bytes are cached, never anything this repo derives, and there are no
2704
+ <code>restore-keys</code> &mdash; a near-miss restore would carry taps this file no longer pins, and
2705
+ the index is built from <em>every configured tap</em>. That last hazard is now checked directly:
2706
+ a <code>BOOST_HOME</code> holding taps outside the list is a hard failure, which is exactly what
2707
+ [[local-boost-install-is-not-the-eval-corpus]] walked into from the other side.
2708
+
2709
+ <b>A second, closer bug fell out of it.</b> The sentinel that makes a local <code>make eval</code>
2710
+ fast was <em>empty</em> &mdash; it meant &ldquo;some corpus was built here&rdquo;. So editing
2711
+ <code>taps.txt</code> (moving a pin, adding a repo) left the previous corpus in place and scored it
2712
+ against the new file's baseline, silently, for as long as the sentinel survived. It now carries the
2713
+ tap list's digest, so an edit is a cache miss.
2714
+
2715
+ <b>What did not ship, and why.</b> The 62% itself. There is no honest way to fix it by removing
2716
+ anything, and adding breadth changes every published number and needs its own re-baselining. What is
2717
+ enforced instead is a ratchet: <code>MAX_SHARE</code> fails the audit if any single publisher goes
2718
+ above 65%, ~3 points over today's measured 62.1%. That stops it getting worse without pretending it
2719
+ is fixed.</p></details>
2678
2720
  <div class="meta">
2679
2721
  <span class="m">Complexity <b>S</b></span>
2680
2722
  <span class="m hi">Impact <b>High</b></span>
@@ -0,0 +1,45 @@
1
+ #!/usr/bin/env bash
2
+ # Tap the pinned Tier 1 eval corpus (tests/eval/taps.txt) into $BOOST_HOME so
3
+ # scripts/eval_retrieval.py has the repos its golden set grades against. Used by
4
+ # CI's lint job and by `make eval`.
5
+ #
6
+ # Idempotent: a sentinel skips re-tapping so a local `make check` stays fast (and
7
+ # offline) after the first run. Set FORCE=1 to re-tap; CI does, because a cached
8
+ # corpus must still be re-verified rather than trusted. Honors $PYTHON (defaults
9
+ # to python3) so make can pass its venv interpreter.
10
+ #
11
+ # THE SENTINEL CARRIES THE TAP LIST'S DIGEST, and that is not decoration. An
12
+ # empty sentinel said "some corpus has been built here", so editing taps.txt —
13
+ # moving a pin, adding a repo — left `make eval` scoring the OLD corpus against
14
+ # the NEW file's baseline, silently, for as long as the sentinel survived. That
15
+ # is the same class of bug as the unpinned list this whole area exists to fix,
16
+ # one directory further along. Keying on the digest makes an edit a cache miss.
17
+ #
18
+ # The tap list carries a commit SHA and an entry count per repo, and the loop
19
+ # that reads it lives in scripts/eval_corpus.py rather than here: the format
20
+ # needs parsing, the pin needs a fetch-then-checkout, and the count needs
21
+ # verifying — none of which a shell loop can be unit-tested on. This file keeps
22
+ # what it is good at, the sentinel and the environment.
23
+ set -euo pipefail
24
+
25
+ root=$(cd "$(dirname "$0")/.." && pwd)
26
+ py="${PYTHON:-python3}"
27
+ home="${BOOST_HOME:-$HOME/.boost}"
28
+ sentinel="$home/.eval-corpus-ready"
29
+ taps="$root/tests/eval/taps.txt"
30
+
31
+ digest=$("$py" -c 'import hashlib,sys
32
+ print(hashlib.sha256(open(sys.argv[1],"rb").read()).hexdigest())' "$taps")
33
+
34
+ if [ -z "${FORCE:-}" ] && [ -f "$sentinel" ] && [ "$(cat "$sentinel")" = "$digest" ]; then
35
+ echo "eval corpus already tapped for this taps.txt — skipping (FORCE=1 to re-tap)"
36
+ exit 0
37
+ fi
38
+
39
+ PYTHONPATH="$root" "$py" "$root/scripts/eval_corpus.py" --ensure
40
+
41
+ # Only after a clean --ensure: `set -e` means a corpus that could not be
42
+ # materialised, or that did not match its pinned counts, never gets a sentinel
43
+ # and so is never skipped on the next run.
44
+ mkdir -p "$home"
45
+ printf '%s\n' "$digest" > "$sentinel"
@@ -0,0 +1,423 @@
1
+ #!/usr/bin/env python3
2
+ """Materialise the Tier 1 eval corpus at the exact commits it was measured on.
3
+
4
+ WHY THIS EXISTS. `tests/eval/taps.txt` used to pin repository NAMES. Tapping is
5
+ a shallow clone of whatever the default branch points at, so the corpus the
6
+ required `eval` gate scores against was a moving target: the list was written
7
+ recording **743** entries and the same 20 repos later resolved to **3,843**, a
8
+ 5.2x growth nobody caused by editing a file. `affaan-m/ECC` alone is 1,616 of
9
+ them, so one third-party repository can move the gate's number by itself.
10
+
11
+ That is not academic. Measured on a clean 20-tap install, BM25 scores recall@10
12
+ **0.912** against a floor of **0.85** — a margin of +0.062. Unpinned growth
13
+ spends that margin quietly, and the first thing anyone would see is a required
14
+ gate failing on a pull request that touched nothing to do with retrieval.
15
+
16
+ So each row now carries a commit SHA, and this script checks each clone out at
17
+ it. `boost tap` still does the cloning (the corpus must be built the way a user
18
+ builds one); pinning is a step applied after, because the alternative — teaching
19
+ `boost tap` to pin — would add a CLI surface for a test-harness problem.
20
+
21
+ WHY A ROW ALSO CARRIES AN ENTRY COUNT. A SHA fixes the *tree*; it does not fix
22
+ what this project makes of that tree, and it does nothing at all when the tree
23
+ cannot be fetched. Both gaps end in the same place — the gate scoring a corpus
24
+ that is not the one its floors were set on — and the direction of the error is
25
+ the surprise. Measured over the 91-query required set, one repo removed and
26
+ everything else identical:
27
+
28
+ all 20 repos 10,152 entries 0.852 / 0.473 / 0.605 / 0.657
29
+ minus sickn33 (62%) 3,843 entries 0.885 / 0.593 / 0.711 / 0.746
30
+ minus that and ECC 2,227 entries 0.967 / 0.659 / 0.769 / 0.814
31
+ minus LessUp (targets) 9,682 entries 0.676 / 0.374 / 0.483 / 0.523
32
+ floors 0.780 / 0.400 / 0.520 / 0.580
33
+
34
+ Losing a *scale* repo makes the gate EASIER — all four metrics rise and the
35
+ check goes green having measured a third of the intended corpus. Losing a repo
36
+ that holds golden targets fails all four floors in a way indistinguishable from
37
+ "this pull request broke retrieval". So "skip whichever repos are missing today"
38
+ is unsafe in both directions, and the count is what makes the first case
39
+ detectable at all: a corpus that does not match its pins stops the run before
40
+ anything is scored.
41
+
42
+ WHY UNAVAILABILITY EXITS 75. `ensure_eval_corpus.sh` runs under `set -euo
43
+ pipefail` inside CI's `lint` job, a required context, so one deleted, renamed or
44
+ privatised repository reddens every open pull request at once. That is a real
45
+ risk for twenty personal repositories, not a hypothetical. Nothing here can keep
46
+ a vanished repository available — CI caches the materialised corpus for that —
47
+ but the failure can at least say what it is. EX_TEMPFAIL separates "a third
48
+ party took their repo down" from "your ranker regressed", which today arrive as
49
+ the same red check.
50
+
51
+ Usage:
52
+ python3 scripts/eval_corpus.py --ensure # tap, pin and verify every row
53
+ python3 scripts/eval_corpus.py --audit # static checks, no network
54
+ python3 scripts/eval_corpus.py --relock # re-measure the entry counts
55
+ python3 scripts/eval_corpus.py --list # print "repo sha count" rows
56
+ """
57
+ from __future__ import annotations
58
+
59
+ import argparse
60
+ import re
61
+ import subprocess
62
+ import sys
63
+ from pathlib import Path
64
+ from typing import Dict, List, Optional, Sequence, Tuple
65
+
66
+ ROOT = Path(__file__).resolve().parent.parent
67
+ TAPS = ROOT / "tests" / "eval" / "taps.txt"
68
+
69
+ _SHA = re.compile(r"[0-9a-f]{40}")
70
+
71
+ #: ``(owner/repo, pinned commit or None, pinned entry count or None)``.
72
+ Row = Tuple[str, Optional[str], Optional[int]]
73
+
74
+ #: A repository, or the commit a row pins, could not be fetched.
75
+ UNAVAILABLE = "unavailable"
76
+ #: The repository materialised, but into a different number of entries.
77
+ DRIFT = "drift"
78
+
79
+ # 75 is EX_TEMPFAIL from sysexits.h, and the distinction is the point: an
80
+ # unreachable third-party repository is not a defect in the change under test,
81
+ # and it must not arrive looking like one.
82
+ EXIT_DRIFT = 1
83
+ EXIT_UNAVAILABLE = 75
84
+
85
+ # No single repository may hold more than this share of the corpus. Measured,
86
+ # not chosen: sickn33/antigravity-awesome-skills is 62.1% of the 10,152 entries
87
+ # today. So this is a ratchet against making the concentration worse — not a
88
+ # claim that 62% is a healthy number, which it is not. Diluting it means adding
89
+ # breadth, never dropping the big repo: the table above shows that dropping it
90
+ # raises every metric, so "rebalancing" by trimming would flatter the gate.
91
+ MAX_SHARE = 0.65
92
+
93
+
94
+ class CorpusError(RuntimeError):
95
+ """A corpus problem that carries which KIND of problem it is.
96
+
97
+ The kind is the whole reason this class exists. A corpus can fail to be the
98
+ one the floors were measured on in two unrelated ways — someone else's
99
+ repository went away, or the tree we did get scans into a different number
100
+ of entries — and only the second says anything about this project. Collapsed
101
+ into one exit status they are indistinguishable, which is how a third
102
+ party's force-push comes to look like a retrieval regression.
103
+ """
104
+
105
+ def __init__(self, kind: str, repo: str, detail: str) -> None:
106
+ super().__init__("%s: %s" % (repo, detail))
107
+ self.kind = kind
108
+ self.repo = repo
109
+ self.detail = detail
110
+
111
+
112
+ def parse_taps(text: str) -> List[Row]:
113
+ """Rows of ``owner/repo [sha [count]]``, comments and blanks dropped.
114
+
115
+ An absent SHA parses as ``None`` rather than an error so the format stays
116
+ backward compatible, but a SHA that is *present and malformed* is fatal: a
117
+ typo silently degrading to "unpinned" would reintroduce the exact drift this
118
+ file exists to stop, while still looking pinned to a reader. A count is
119
+ fatal on the same grounds, and requires a SHA — a count beside an unpinned
120
+ repo describes a tree that is free to change underneath it.
121
+ """
122
+ rows: List[Row] = []
123
+ for raw in text.splitlines():
124
+ line = raw.strip()
125
+ if not line or line.startswith("#"):
126
+ continue
127
+ parts = line.split()
128
+ repo = parts[0]
129
+ if len(parts) == 1:
130
+ rows.append((repo, None, None))
131
+ continue
132
+ sha = parts[1]
133
+ if not _SHA.fullmatch(sha):
134
+ raise SystemExit(
135
+ "tests/eval/taps.txt: %s is pinned to %r, which is not a "
136
+ "40-character commit SHA" % (repo, sha))
137
+ if len(parts) == 2:
138
+ rows.append((repo, sha, None))
139
+ continue
140
+ if len(parts) > 3:
141
+ raise SystemExit(
142
+ "tests/eval/taps.txt: %s has %d fields, expected at most 3 "
143
+ "(repo, sha, entry count)" % (repo, len(parts)))
144
+ count = parts[2]
145
+ if not count.isdigit():
146
+ raise SystemExit(
147
+ "tests/eval/taps.txt: %s records %r entries, which is not a "
148
+ "non-negative integer" % (repo, count))
149
+ rows.append((repo, sha, int(count)))
150
+ return rows
151
+
152
+
153
+ def shares(rows: Sequence[Row]) -> List[Tuple[str, int, float]]:
154
+ """``(repo, count, share)`` for every counted row, largest first.
155
+
156
+ Rows with no recorded count are omitted rather than treated as zero: a
157
+ partially counted list should report the concentration of what it knows,
158
+ not a share diluted by rows it cannot see.
159
+ """
160
+ counted = [(repo, n) for repo, _sha, n in rows if n is not None]
161
+ total = sum(n for _repo, n in counted)
162
+ if not total:
163
+ return []
164
+ return sorted(((repo, n, n / total) for repo, n in counted),
165
+ key=lambda row: (-row[1], row[0]))
166
+
167
+
168
+ def check_concentration(rows: Sequence[Row]) -> Optional[str]:
169
+ """Return a message when one repository exceeds ``MAX_SHARE``, else ``None``.
170
+
171
+ Static — it reads the counts already in the file, so it costs no network and
172
+ runs anywhere. Concentration is a sampling bias in every recall figure this
173
+ project publishes, and the bias is invisible in a list of twenty names that
174
+ look equally weighted.
175
+ """
176
+ ranked = shares(rows)
177
+ if not ranked:
178
+ return None
179
+ repo, count, share = ranked[0]
180
+ if share <= MAX_SHARE:
181
+ return None
182
+ return ("%s is %d of %d entries (%.1f%%), over the %.0f%% ceiling. The "
183
+ "corpus would be mostly one publisher's house style, which biases "
184
+ "every recall figure this project reports. Add breadth rather than "
185
+ "dropping the big repo: a smaller corpus scores HIGHER, so trimming "
186
+ "to rebalance would flatter the gate."
187
+ % (repo, count, sum(n for _r, n, _s in ranked), share * 100,
188
+ MAX_SHARE * 100))
189
+
190
+
191
+ def extra_taps(configured: Sequence[str], pinned: Sequence[str]) -> List[str]:
192
+ """Configured taps that this list does not pin, sorted.
193
+
194
+ The third way to score a corpus that is not the pinned one, and the easiest
195
+ to walk into: the index is built from ``catalog.all_entries()``, which is
196
+ every configured tap, not the twenty in this file. Point BOOST_HOME at a
197
+ real install — 445 taps and 71,655 entries on the machine this was written
198
+ on — and `make eval` reports numbers for that catalogue while every comment
199
+ in the tree says it measured twenty repos.
200
+ """
201
+ return sorted(set(configured) - set(pinned))
202
+
203
+
204
+ def _run(path: Path, *args: str) -> subprocess.CompletedProcess:
205
+ return subprocess.run(["git", "-C", str(path), *args],
206
+ capture_output=True, text=True)
207
+
208
+
209
+ def has_commit(path: Path, sha: str) -> bool:
210
+ """True when ``sha`` names a commit already present in ``path``.
211
+
212
+ ``^{commit}`` matters: `cat-file -e` succeeds for any object, so a tree or
213
+ blob SHA would otherwise report as present and then fail at checkout.
214
+ """
215
+ return _run(path, "cat-file", "-e", "%s^{commit}" % sha).returncode == 0
216
+
217
+
218
+ def _fetch(path: Path, sha: str) -> subprocess.CompletedProcess:
219
+ # Shallow: the corpus needs the tree at one commit, not the history to it.
220
+ return _run(path, "fetch", "--quiet", "--depth", "1", "origin", sha)
221
+
222
+
223
+ def pin_clone(path: Path, sha: str) -> None:
224
+ """Check ``path`` out at ``sha``, fetching the commit first if it is absent.
225
+
226
+ Raises ``CorpusError(UNAVAILABLE, ...)``, which is the same class of event as
227
+ the whole repository being gone: the tree the floors were measured on is not
228
+ obtainable here and now, and that is not a statement about this project.
229
+ """
230
+ if not has_commit(path, sha):
231
+ _fetch(path, sha)
232
+ if not has_commit(path, sha):
233
+ raise CorpusError(
234
+ UNAVAILABLE, path.name,
235
+ "commit %s is not reachable — the pin in tests/eval/taps.txt is "
236
+ "stale, or the repository rewrote history" % sha)
237
+ res = _run(path, "checkout", "--quiet", "--detach", sha)
238
+ if res.returncode != 0:
239
+ raise CorpusError(UNAVAILABLE, path.name,
240
+ "could not check out %s: %s" % (sha, res.stderr.strip()))
241
+
242
+
243
+ def _materialise(rows: Sequence[Row], verify: bool = True
244
+ ) -> Tuple[Dict[str, int], List[CorpusError]]:
245
+ """Tap, pin and rescan every row. Returns ``(counts, failures)``.
246
+
247
+ Every row is attempted even after one fails. Stopping at the first would
248
+ report "one repository is unreachable" when five are, and the difference
249
+ decides whether the answer is "re-run it" or "the list needs work".
250
+ """
251
+ sys.path.insert(0, str(ROOT))
252
+ from boost_cli.core import catalog, registry # deferred: repo-root import shim
253
+
254
+ counts: Dict[str, int] = {}
255
+ failures: List[CorpusError] = []
256
+ for repo, sha, want in rows:
257
+ try:
258
+ try:
259
+ tap = registry.get(repo)
260
+ except Exception: # not yet tapped; add it below
261
+ tap = registry.add(repo)
262
+ if sha:
263
+ pin_clone(tap.path, sha)
264
+ except CorpusError as exc:
265
+ # Re-name it: pin_clone only knows the clone directory, and the
266
+ # report has to say what taps.txt says so the reader can grep for it.
267
+ failures.append(CorpusError(exc.kind, repo, exc.detail))
268
+ print(" %-44s %s" % (repo, exc.detail))
269
+ continue
270
+ except Exception as exc: # any failure to obtain the tree at all
271
+ failures.append(CorpusError(UNAVAILABLE, repo, str(exc)))
272
+ print(" %-44s could not be tapped: %s" % (repo, exc))
273
+ continue
274
+ # Always after pinning: `boost tap` built the cache from the default
275
+ # branch, so an unrebuilt cache would describe a tree we just replaced.
276
+ entries = catalog.rebuild_tap(tap)
277
+ counts[repo] = len(entries)
278
+ note = ""
279
+ if verify and want is not None and len(entries) != want:
280
+ failures.append(CorpusError(
281
+ DRIFT, repo,
282
+ "taps.txt records %d entries, this tree scans into %d"
283
+ % (want, len(entries))))
284
+ note = " != %d pinned" % want
285
+ print(" %-44s %s %5d entries%s"
286
+ % (repo, (sha or "unpinned")[:7], len(entries), note))
287
+
288
+ extras = extra_taps([t.name for t in registry.list_taps()],
289
+ [r for r, _s, _n in rows])
290
+ if verify and extras:
291
+ failures.append(CorpusError(
292
+ DRIFT, "BOOST_HOME",
293
+ "%d tap(s) are configured here but not pinned by taps.txt, and the "
294
+ "index is built from ALL configured taps: %s"
295
+ % (len(extras), ", ".join(extras[:5])
296
+ + (", ..." if len(extras) > 5 else ""))))
297
+ return counts, failures
298
+
299
+
300
+ def _report_failures(failures: Sequence[CorpusError], total_rows: int) -> int:
301
+ """Print the failures grouped by kind and return the exit code to use."""
302
+ unavailable = [f for f in failures if f.kind == UNAVAILABLE]
303
+ drift = [f for f in failures if f.kind == DRIFT]
304
+ if unavailable:
305
+ print("\nCORPUS UNAVAILABLE — this is not a retrieval regression.")
306
+ print("%d of %d pinned repositories could not be materialised:"
307
+ % (len(unavailable), total_rows))
308
+ for f in unavailable:
309
+ print(" %s — %s" % (f.repo, f.detail))
310
+ print("The gate cannot run, and scoring the repos that ARE reachable is\n"
311
+ "not a fallback: measured, dropping the largest repo alone moves\n"
312
+ "BM25 recall@10 0.852 -> 0.885 and hit@1 0.473 -> 0.593, so a\n"
313
+ "partial corpus clears the floors MORE easily than the real one.")
314
+ if drift:
315
+ print("\nCORPUS DRIFT — what materialised is not what taps.txt pins.")
316
+ for f in drift:
317
+ print(" %s — %s" % (f.repo, f.detail))
318
+ print("A count mismatch means the scanner changed or a pin moved: "
319
+ "re-measure with\n`--relock`, then regenerate "
320
+ "tests/eval/baseline.json. An unpinned tap means\nBOOST_HOME is "
321
+ "not a corpus this file describes — point it at a scratch\n"
322
+ "directory (`make eval` uses ./.eval-home).")
323
+ # Drift wins when both happen: it is the one that says something about this
324
+ # repository, and it is not fixed by waiting or re-running.
325
+ return EXIT_DRIFT if drift else EXIT_UNAVAILABLE
326
+
327
+
328
+ def relock_text(text: str, counts: Dict[str, int]) -> str:
329
+ """Rewrite each pinned row's entry count, preserving everything else.
330
+
331
+ A whole-file rewrite would lose the header, which is where the reasoning
332
+ lives; this touches only rows it has a new count for. A row with no SHA is
333
+ left alone — a count beside an unpinned repo describes a tree free to change
334
+ underneath it, so it must never be written.
335
+ """
336
+ width = max([len(r) for r in counts] or [1])
337
+ out = []
338
+ for raw in text.splitlines():
339
+ line = raw.strip()
340
+ parts = line.split()
341
+ if not line or line.startswith("#") or len(parts) < 2 \
342
+ or parts[0] not in counts or not _SHA.fullmatch(parts[1]):
343
+ out.append(raw)
344
+ continue
345
+ out.append("%-*s %s %5d" % (width, parts[0], parts[1], counts[parts[0]]))
346
+ return "\n".join(out) + ("\n" if text.endswith("\n") else "")
347
+
348
+
349
+ def _print_concentration(rows: Sequence[Row]) -> None:
350
+ ranked = shares(rows)
351
+ if not ranked:
352
+ return
353
+ total = sum(n for _r, n, _s in ranked)
354
+ top = ranked[0]
355
+ print("corpus: %d entries across %d taps" % (total, len(ranked)))
356
+ line = "concentration: %s is %.1f%%" % (top[0], top[2] * 100)
357
+ if len(ranked) > 1:
358
+ line += "; top two are %.1f%%" % ((top[2] + ranked[1][2]) * 100)
359
+ print(line)
360
+
361
+
362
+ def _ensure(relock: bool = False) -> int:
363
+ rows = parse_taps(TAPS.read_text(encoding="utf-8"))
364
+ counts, failures = _materialise(rows, verify=not relock)
365
+ if failures:
366
+ return _report_failures(failures, len(rows))
367
+ if relock:
368
+ TAPS.write_text(relock_text(TAPS.read_text(encoding="utf-8"), counts),
369
+ encoding="utf-8")
370
+ print("relocked %d rows in tests/eval/taps.txt" % len(counts))
371
+ rows = parse_taps(TAPS.read_text(encoding="utf-8"))
372
+ _print_concentration(rows)
373
+ problem = check_concentration(rows)
374
+ if problem:
375
+ print("\nCORPUS CONCENTRATION — %s" % problem)
376
+ return EXIT_DRIFT
377
+ return 0
378
+
379
+
380
+ def _audit() -> int:
381
+ """Static checks over the shipped list — no network, no clones."""
382
+ rows = parse_taps(TAPS.read_text(encoding="utf-8"))
383
+ for repo, count, share in shares(rows):
384
+ print(" %-44s %5d entries %5.1f%%" % (repo, count, share * 100))
385
+ _print_concentration(rows)
386
+ uncounted = [r for r, _s, n in rows if n is None]
387
+ if uncounted:
388
+ print("\nuncounted rows (run --relock): %s" % ", ".join(uncounted))
389
+ return EXIT_DRIFT
390
+ problem = check_concentration(rows)
391
+ if problem:
392
+ print("\nCORPUS CONCENTRATION — %s" % problem)
393
+ return EXIT_DRIFT
394
+ return 0
395
+
396
+
397
+ def main(argv: Optional[List[str]] = None) -> int:
398
+ p = argparse.ArgumentParser(prog="eval_corpus.py", description=__doc__)
399
+ p.add_argument("--ensure", action="store_true",
400
+ help="tap, pin and verify every row, then rebuild its cache")
401
+ p.add_argument("--relock", action="store_true",
402
+ help="re-measure entry counts and write them into taps.txt")
403
+ p.add_argument("--audit", action="store_true",
404
+ help="static concentration/count checks, no network")
405
+ p.add_argument("--list", action="store_true",
406
+ help="print the parsed rows and exit")
407
+ args = p.parse_args(argv)
408
+ if args.list:
409
+ for repo, sha, count in parse_taps(TAPS.read_text(encoding="utf-8")):
410
+ print("%s %s %s" % (repo, sha or "", "" if count is None else count))
411
+ return 0
412
+ if args.audit:
413
+ return _audit()
414
+ if args.relock:
415
+ return _ensure(relock=True)
416
+ if args.ensure:
417
+ return _ensure()
418
+ p.error("provide --ensure, --relock, --audit or --list")
419
+ return 2
420
+
421
+
422
+ if __name__ == "__main__":
423
+ raise SystemExit(main())