boost-skill-cli 1.0.42__tar.gz → 1.0.43__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 (109) hide show
  1. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/discovery.py +1 -0
  4. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/spin.py +25 -0
  5. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_skill_cli.egg-info/PKG-INFO +1 -1
  6. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/docs/design-roadmap.html +1 -1
  7. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_spin.py +38 -0
  8. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/.gitignore +0 -0
  9. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/CLAUDE.md +0 -0
  10. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/CONTRIBUTING.md +0 -0
  11. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/LICENSE +0 -0
  12. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/MANIFEST.in +0 -0
  13. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/Makefile +0 -0
  14. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/README.md +0 -0
  15. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/SECURITY.md +0 -0
  16. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost +0 -0
  17. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/__init__.py +0 -0
  18. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/__main__.py +0 -0
  19. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/cli.py +0 -0
  20. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/cliparse.py +0 -0
  21. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/__init__.py +0 -0
  22. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/bmad.py +0 -0
  23. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/configuration.py +0 -0
  24. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/hooks.py +0 -0
  25. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/info.py +0 -0
  26. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/intelligence.py +0 -0
  27. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/pkg.py +0 -0
  28. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/quality.py +0 -0
  29. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/taps.py +0 -0
  30. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/commands/team.py +0 -0
  31. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/__init__.py +0 -0
  32. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/agents.py +0 -0
  33. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/ai.py +0 -0
  34. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/catalog.py +0 -0
  35. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/claude_settings.py +0 -0
  36. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/config.py +0 -0
  37. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/dense.py +0 -0
  38. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/embed.py +0 -0
  39. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/frontmatter.py +0 -0
  40. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/gitutil.py +0 -0
  41. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/journal.py +0 -0
  42. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/lockfile.py +0 -0
  43. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/logs.py +0 -0
  44. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/output.py +0 -0
  45. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/paths.py +0 -0
  46. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/policy.py +0 -0
  47. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/rag.py +0 -0
  48. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/registry.py +0 -0
  49. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/store.py +0 -0
  50. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/core/util.py +0 -0
  51. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/data/registries.json +0 -0
  52. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_cli/errors.py +0 -0
  53. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
  54. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  55. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  56. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_skill_cli.egg-info/requires.txt +0 -0
  57. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/boost_skill_cli.egg-info/top_level.txt +0 -0
  58. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/docs/.claude/settings.local.json +0 -0
  59. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/docs/DEBUGGING.md +0 -0
  60. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/docs/demo.gif +0 -0
  61. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/docs/demo.tape +0 -0
  62. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/docs/index.html +0 -0
  63. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/docs/rag-architecture.md +0 -0
  64. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/docs/roadmap.html +0 -0
  65. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/pyproject.toml +0 -0
  66. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/scripts/build_registries.py +0 -0
  67. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/scripts/mutation_gate.py +0 -0
  68. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/setup.cfg +0 -0
  69. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/style/README.md +0 -0
  70. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/style/boost.css +0 -0
  71. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/style/boost.js +0 -0
  72. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/style/demo.html +0 -0
  73. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/conftest.py +0 -0
  74. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_bmad.py +0 -0
  75. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_configuration.py +0 -0
  76. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_discovery.py +0 -0
  77. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_hooks.py +0 -0
  78. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_info.py +0 -0
  79. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_intelligence.py +0 -0
  80. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_pkg.py +0 -0
  81. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_quality.py +0 -0
  82. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_taps.py +0 -0
  83. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_cli_team.py +0 -0
  84. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/functional/test_everyday_loop.py +0 -0
  85. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/make_fixture.py +0 -0
  86. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/smoke.sh +0 -0
  87. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_agents.py +0 -0
  88. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_ai.py +0 -0
  89. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_catalog.py +0 -0
  90. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_claude_settings.py +0 -0
  91. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_cliparse.py +0 -0
  92. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_config.py +0 -0
  93. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_dense.py +0 -0
  94. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_embed.py +0 -0
  95. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_errors_and_cli_table.py +0 -0
  96. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_frontmatter.py +0 -0
  97. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_gitutil.py +0 -0
  98. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_journal.py +0 -0
  99. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_lockfile.py +0 -0
  100. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_logs.py +0 -0
  101. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_mutation_hardening.py +0 -0
  102. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_output.py +0 -0
  103. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_paths.py +0 -0
  104. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_policy.py +0 -0
  105. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_rag.py +0 -0
  106. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_registry.py +0 -0
  107. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_store.py +0 -0
  108. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/tests/unit/test_util.py +0 -0
  109. {boost_skill_cli-1.0.42 → boost_skill_cli-1.0.43}/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.42
3
+ Version: 1.0.43
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.42'
22
- __version_tuple__ = version_tuple = (1, 0, 42)
21
+ __version__ = version = '1.0.43'
22
+ __version_tuple__ = version_tuple = (1, 0, 43)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -300,6 +300,7 @@ def cmd_index(argv):
300
300
  items, total = [], 0
301
301
  pages = min((max(1, args.limit) + 99) // 100, 10) # code search caps at 1000
302
302
  for page in range(1, pages + 1):
303
+ spin.progress(page, pages, "searching GitHub for SKILL.md")
303
304
  if page > 1:
304
305
  time.sleep(1) # stay under the code-search rate limit
305
306
  try:
@@ -54,3 +54,28 @@ class Spinner:
54
54
  if self.active():
55
55
  self.stream.write("\r" + " " * (out.visible_len(self.label) + 2) + "\r")
56
56
  self.stream.flush()
57
+
58
+
59
+ def bar(current: int, total: int, width: int = 20) -> str:
60
+ """A determinate progress bar (filled ▓ vs light ░) for current/total."""
61
+ total = total if total > 0 else 1
62
+ frac = current / total
63
+ frac = 0.0 if frac < 0 else 1.0 if frac > 1 else frac
64
+ filled = round(frac * width)
65
+ return "▓" * filled + "░" * (width - filled)
66
+
67
+
68
+ def progress(current: int, total: int, label: str = "", stream=None) -> None:
69
+ """Redraw a determinate progress line in place. Silent (no output) unless
70
+ the stream is an interactive, color-capable TTY, so piped/CI/test output
71
+ stays clean. Clears the line once current reaches total.
72
+ """
73
+ s = stream if stream is not None else sys.stderr
74
+ if not (out.color_level(s) > 0 and hasattr(s, "isatty") and s.isatty()):
75
+ return
76
+ line = "%s %d/%d %s" % (out.aurora(bar(current, total), "cyan"),
77
+ current, total, label)
78
+ s.write("\r" + line)
79
+ if current >= total:
80
+ s.write("\r" + " " * out.visible_len(line) + "\r")
81
+ s.flush()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.42
3
+ Version: 1.0.43
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -357,7 +357,7 @@
357
357
  </article>
358
358
 
359
359
  <article class="ritem" data-track="motion" data-impact="med">
360
- <div class="ritem-top"><span class="rid">BOOST-D11</span><span class="rstatus proposed">Proposed</span></div>
360
+ <div class="ritem-top"><span class="rid">BOOST-D11</span><span class="rstatus done">Shipped</span></div>
361
361
  <h4>Determinate progress bars for batch ops</h4>
362
362
  <p>Multi-item commands — <code>reindex</code>, <code>update</code>, <code>sync</code>, <code>snapshot</code> restore — give no sense of "how far in." Add a gradient-filled progress bar (<code>N/total</code> + ETA) for anything looping over a known count, so long operations read as intentional rather than hung.</p>
363
363
  <div class="rmeta"><span class="m-cat">motion</span><span>Complexity M</span><span class="m-imp med">Impact Med</span><span class="m-wow">★★★★☆</span></div>
@@ -57,6 +57,44 @@ def test_context_manager_returns_self():
57
57
  assert sp.__exit__(None, None, None) is None # doesn't suppress exceptions
58
58
 
59
59
 
60
+ class TestBar:
61
+ def test_empty(self):
62
+ assert spin.bar(0, 10, 20) == "░" * 20
63
+
64
+ def test_full(self):
65
+ assert spin.bar(10, 10, 20) == "▓" * 20
66
+
67
+ def test_half(self):
68
+ assert spin.bar(5, 10, 20) == "▓" * 10 + "░" * 10
69
+
70
+ def test_clamps_over(self):
71
+ assert spin.bar(15, 10, 20) == "▓" * 20
72
+
73
+ def test_zero_total_is_safe(self):
74
+ assert spin.bar(1, 0, 4) == "▓" * 4 # total coerced to 1 -> full
75
+
76
+
77
+ class TestProgress:
78
+ def test_silent_on_non_tty(self):
79
+ s = FakeStream(tty=False)
80
+ spin.progress(1, 3, "x", stream=s)
81
+ assert s.getvalue() == ""
82
+
83
+ def test_writes_on_tty(self, monkeypatch):
84
+ monkeypatch.setenv("CLICOLOR_FORCE", "1")
85
+ s = FakeStream(tty=True)
86
+ spin.progress(1, 3, "go", stream=s)
87
+ out = s.getvalue()
88
+ assert "1/3" in out and "go" in out and out.startswith("\r")
89
+
90
+ def test_clears_when_complete(self, monkeypatch):
91
+ monkeypatch.setenv("CLICOLOR_FORCE", "1")
92
+ s = FakeStream(tty=True)
93
+ spin.progress(3, 3, "done", stream=s)
94
+ # ends by returning the cursor to the start of a blanked line
95
+ assert s.getvalue().endswith("\r")
96
+
97
+
60
98
  def test_tty_run_writes_and_clears():
61
99
  # exercise the animated path: wait (bounded) for the thread's first frame
62
100
  import time
File without changes