boost-skill-cli 1.0.25__tar.gz → 1.0.26__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 (105) hide show
  1. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/discovery.py +9 -3
  4. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/output.py +13 -0
  5. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_skill_cli.egg-info/PKG-INFO +1 -1
  6. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/docs/design-roadmap.html +1 -1
  7. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_discovery.py +8 -0
  8. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_output.py +26 -0
  9. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/.gitignore +0 -0
  10. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/CLAUDE.md +0 -0
  11. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/CONTRIBUTING.md +0 -0
  12. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/LICENSE +0 -0
  13. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/MANIFEST.in +0 -0
  14. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/Makefile +0 -0
  15. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/README.md +0 -0
  16. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/SECURITY.md +0 -0
  17. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost +0 -0
  18. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/__init__.py +0 -0
  19. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/__main__.py +0 -0
  20. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/cli.py +0 -0
  21. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/__init__.py +0 -0
  22. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/bmad.py +0 -0
  23. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/configuration.py +0 -0
  24. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/hooks.py +0 -0
  25. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/info.py +0 -0
  26. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/intelligence.py +0 -0
  27. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/pkg.py +0 -0
  28. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/quality.py +0 -0
  29. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/taps.py +0 -0
  30. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/commands/team.py +0 -0
  31. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/__init__.py +0 -0
  32. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/agents.py +0 -0
  33. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/ai.py +0 -0
  34. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/catalog.py +0 -0
  35. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/claude_settings.py +0 -0
  36. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/config.py +0 -0
  37. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/dense.py +0 -0
  38. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/embed.py +0 -0
  39. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/frontmatter.py +0 -0
  40. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/gitutil.py +0 -0
  41. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/journal.py +0 -0
  42. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/lockfile.py +0 -0
  43. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/logs.py +0 -0
  44. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/paths.py +0 -0
  45. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/policy.py +0 -0
  46. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/rag.py +0 -0
  47. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/registry.py +0 -0
  48. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/store.py +0 -0
  49. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/core/util.py +0 -0
  50. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/data/registries.json +0 -0
  51. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_cli/errors.py +0 -0
  52. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
  53. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  54. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  55. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_skill_cli.egg-info/requires.txt +0 -0
  56. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/boost_skill_cli.egg-info/top_level.txt +0 -0
  57. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/docs/.claude/settings.local.json +0 -0
  58. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/docs/DEBUGGING.md +0 -0
  59. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/docs/demo.gif +0 -0
  60. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/docs/demo.tape +0 -0
  61. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/docs/index.html +0 -0
  62. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/docs/rag-architecture.md +0 -0
  63. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/docs/roadmap.html +0 -0
  64. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/pyproject.toml +0 -0
  65. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/scripts/build_registries.py +0 -0
  66. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/scripts/mutation_gate.py +0 -0
  67. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/setup.cfg +0 -0
  68. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/style/README.md +0 -0
  69. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/style/boost.css +0 -0
  70. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/style/boost.js +0 -0
  71. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/style/demo.html +0 -0
  72. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/conftest.py +0 -0
  73. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_bmad.py +0 -0
  74. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_configuration.py +0 -0
  75. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_hooks.py +0 -0
  76. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_info.py +0 -0
  77. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_intelligence.py +0 -0
  78. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_pkg.py +0 -0
  79. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_quality.py +0 -0
  80. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_taps.py +0 -0
  81. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_cli_team.py +0 -0
  82. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/functional/test_everyday_loop.py +0 -0
  83. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/make_fixture.py +0 -0
  84. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/smoke.sh +0 -0
  85. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_agents.py +0 -0
  86. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_ai.py +0 -0
  87. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_catalog.py +0 -0
  88. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_claude_settings.py +0 -0
  89. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_config.py +0 -0
  90. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_dense.py +0 -0
  91. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_embed.py +0 -0
  92. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_errors_and_cli_table.py +0 -0
  93. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_frontmatter.py +0 -0
  94. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_gitutil.py +0 -0
  95. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_journal.py +0 -0
  96. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_lockfile.py +0 -0
  97. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_logs.py +0 -0
  98. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_mutation_hardening.py +0 -0
  99. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_paths.py +0 -0
  100. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_policy.py +0 -0
  101. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_rag.py +0 -0
  102. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_registry.py +0 -0
  103. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_store.py +0 -0
  104. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_util.py +0 -0
  105. {boost_skill_cli-1.0.25 → boost_skill_cli-1.0.26}/tests/unit/test_version.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.25
3
+ Version: 1.0.26
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.25'
22
- __version_tuple__ = version_tuple = (1, 0, 25)
21
+ __version__ = version = '1.0.26'
22
+ __version_tuple__ = version_tuple = (1, 0, 26)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -212,13 +212,19 @@ def cmd_search(argv):
212
212
  # Cap the name column so one long name can't pad every row, and clip each
213
213
  # description to the remaining terminal width so results stay one line each.
214
214
  name_w = min(max(len(e["name"]) for e, _ in shown), 32)
215
+ top = max((s for _e, s in shown), default=0) or 1
215
216
  cols = out.term_width()
216
- for e, _s in shown:
217
+ for e, sc in shown:
218
+ # A relevance meter makes the ranking visible; tint it by magnitude.
219
+ frac = sc / top
220
+ hue = "cyan" if frac >= 0.66 else "violet" if frac >= 0.33 else "pink"
221
+ bar = out.aurora(out.meter(frac), hue)
217
222
  tag = " " + out.c("★ curated", out.YELLOW) if e.get("curated") else ""
218
223
  tag_w = len(" ★ curated") if e.get("curated") else 0
219
- desc_w = max(cols - 2 - name_w - 2 - tag_w, 8)
224
+ desc_w = max(cols - 2 - 5 - name_w - 2 - tag_w, 8) # 5 = meter + space
220
225
  name_cell = out.c(out.truncate(e["name"], name_w).ljust(name_w), out.CYAN)
221
- out.info(name_cell + " " + out.truncate(e["description"] or "", desc_w) + tag)
226
+ out.info(bar + " " + name_cell + " "
227
+ + out.truncate(e["description"] or "", desc_w) + tag)
222
228
  out.info(out.c("%d match%s · ranked by %s"
223
229
  % (len(scored), "" if len(scored) == 1 else "es", ranker),
224
230
  out.DIM))
@@ -183,6 +183,19 @@ def badge(label: str, hue: str = "cyan") -> str:
183
183
  return aurora("[" + label + "]", hue)
184
184
 
185
185
 
186
+ def meter(fraction: float, width: int = 4) -> str:
187
+ """A tiny proportional bar for a 0..1 fraction — filled ▰ vs empty ▱.
188
+
189
+ Uncolored on purpose so callers can Aurora-tint it by magnitude.
190
+ """
191
+ if fraction < 0:
192
+ fraction = 0.0
193
+ elif fraction > 1:
194
+ fraction = 1.0
195
+ filled = round(fraction * width)
196
+ return "▰" * filled + "▱" * (width - filled)
197
+
198
+
186
199
  def kv(key: str, value: str, width: int = 14) -> None:
187
200
  print(" " + c(key.ljust(width), DIM) + str(value))
188
201
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.25
3
+ Version: 1.0.26
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -294,7 +294,7 @@
294
294
  </article>
295
295
 
296
296
  <article class="ritem" data-track="layout" data-impact="med">
297
- <div class="ritem-top"><span class="rid">BOOST-D07</span><span class="rstatus proposed">Proposed</span></div>
297
+ <div class="ritem-top"><span class="rid">BOOST-D07</span><span class="rstatus done">Shipped</span></div>
298
298
  <h4>Relevance visualization in search</h4>
299
299
  <p>Results are "ranked by heuristic relevance" but the ranking is invisible — every row looks equal. Render a tiny gradient relevance bar or score glyph per hit and visually separate <b>curated</b> from GitHub-wide matches, so the eye lands on the best result first.</p>
300
300
  <div class="rmeta"><span class="m-cat">layout</span><span>Complexity M</span><span class="m-imp med">Impact Med</span><span class="m-wow">★★★★☆</span></div>
@@ -69,6 +69,14 @@ class TestSearch:
69
69
  assert r.out.index("commit-messages") < r.out.index("jira-integration")
70
70
  assert "2 matches · ranked by heuristic relevance" in r.out
71
71
 
72
+ def test_results_show_relevance_meter(self, boost, tapped):
73
+ # D07: the ranking is visible as a per-result meter; the top exact
74
+ # match earns a full bar.
75
+ r = boost("search", "commit", "messages")
76
+ assert "▰" in r.out
77
+ top = next(l for l in r.out.splitlines() if "commit-messages" in l)
78
+ assert "▰▰▰▰" in top
79
+
72
80
  def test_limit_caps_rows_but_footer_counts_all(self, boost, tapped):
73
81
  r = boost("search", "workflow", "--limit", "1")
74
82
  assert "tdd-workflow" in r.out
@@ -296,6 +296,32 @@ class TestBadge:
296
296
  "\033[38;2;74;222;128m[installed]\033[0m")
297
297
 
298
298
 
299
+ class TestMeter:
300
+ def test_full(self):
301
+ assert output.meter(1.0, 4) == "▰▰▰▰"
302
+
303
+ def test_empty(self):
304
+ assert output.meter(0.0, 4) == "▱▱▱▱"
305
+
306
+ def test_half(self):
307
+ assert output.meter(0.5, 4) == "▰▰▱▱"
308
+
309
+ def test_default_width_is_four(self):
310
+ assert output.meter(1.0) == "▰▰▰▰"
311
+
312
+ def test_clamps_above_one(self):
313
+ # 1.5 lands in (1, 2] — must still clamp, not overflow to 6 cells
314
+ assert output.meter(1.5, 4) == "▰▰▰▰"
315
+ assert output.meter(2.5, 4) == "▰▰▰▰"
316
+
317
+ def test_clamps_below_zero(self):
318
+ assert output.meter(-3.0, 4) == "▱▱▱▱"
319
+
320
+ def test_rounds_to_nearest_cell(self):
321
+ # 0.6 * 5 = 3.0 -> exactly three filled
322
+ assert output.meter(0.6, 5) == "▰▰▰▱▱"
323
+
324
+
299
325
  class TestHelpers:
300
326
  @pytest.fixture(autouse=True)
301
327
  def plain(self, monkeypatch):
File without changes