boost-skill-cli 1.0.37__tar.gz → 1.0.38__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 (107) hide show
  1. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/PKG-INFO +1 -1
  2. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/_version.py +2 -2
  3. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/output.py +14 -4
  4. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/PKG-INFO +1 -1
  5. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/design-roadmap.html +1 -1
  6. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_output.py +21 -0
  7. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/.gitignore +0 -0
  8. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/CLAUDE.md +0 -0
  9. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/CONTRIBUTING.md +0 -0
  10. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/LICENSE +0 -0
  11. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/MANIFEST.in +0 -0
  12. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/Makefile +0 -0
  13. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/README.md +0 -0
  14. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/SECURITY.md +0 -0
  15. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost +0 -0
  16. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/__init__.py +0 -0
  17. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/__main__.py +0 -0
  18. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/cli.py +0 -0
  19. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/cliparse.py +0 -0
  20. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/__init__.py +0 -0
  21. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/bmad.py +0 -0
  22. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/configuration.py +0 -0
  23. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/discovery.py +0 -0
  24. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/hooks.py +0 -0
  25. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/info.py +0 -0
  26. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/intelligence.py +0 -0
  27. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/pkg.py +0 -0
  28. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/quality.py +0 -0
  29. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/taps.py +0 -0
  30. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/team.py +0 -0
  31. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/__init__.py +0 -0
  32. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/agents.py +0 -0
  33. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/ai.py +0 -0
  34. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/catalog.py +0 -0
  35. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/claude_settings.py +0 -0
  36. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/config.py +0 -0
  37. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/dense.py +0 -0
  38. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/embed.py +0 -0
  39. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/frontmatter.py +0 -0
  40. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/gitutil.py +0 -0
  41. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/journal.py +0 -0
  42. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/lockfile.py +0 -0
  43. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/logs.py +0 -0
  44. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/paths.py +0 -0
  45. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/policy.py +0 -0
  46. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/rag.py +0 -0
  47. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/registry.py +0 -0
  48. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/store.py +0 -0
  49. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/util.py +0 -0
  50. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/data/registries.json +0 -0
  51. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/errors.py +0 -0
  52. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
  53. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
  54. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/entry_points.txt +0 -0
  55. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/requires.txt +0 -0
  56. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/top_level.txt +0 -0
  57. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/.claude/settings.local.json +0 -0
  58. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/DEBUGGING.md +0 -0
  59. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/demo.gif +0 -0
  60. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/demo.tape +0 -0
  61. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/index.html +0 -0
  62. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/rag-architecture.md +0 -0
  63. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/roadmap.html +0 -0
  64. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/pyproject.toml +0 -0
  65. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/scripts/build_registries.py +0 -0
  66. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/scripts/mutation_gate.py +0 -0
  67. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/setup.cfg +0 -0
  68. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/style/README.md +0 -0
  69. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/style/boost.css +0 -0
  70. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/style/boost.js +0 -0
  71. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/style/demo.html +0 -0
  72. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/conftest.py +0 -0
  73. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_bmad.py +0 -0
  74. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_configuration.py +0 -0
  75. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_discovery.py +0 -0
  76. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_hooks.py +0 -0
  77. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_info.py +0 -0
  78. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_intelligence.py +0 -0
  79. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_pkg.py +0 -0
  80. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_quality.py +0 -0
  81. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_taps.py +0 -0
  82. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_team.py +0 -0
  83. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_everyday_loop.py +0 -0
  84. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/make_fixture.py +0 -0
  85. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/smoke.sh +0 -0
  86. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_agents.py +0 -0
  87. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_ai.py +0 -0
  88. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_catalog.py +0 -0
  89. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_claude_settings.py +0 -0
  90. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_cliparse.py +0 -0
  91. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_config.py +0 -0
  92. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_dense.py +0 -0
  93. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_embed.py +0 -0
  94. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_errors_and_cli_table.py +0 -0
  95. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_frontmatter.py +0 -0
  96. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_gitutil.py +0 -0
  97. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_journal.py +0 -0
  98. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_lockfile.py +0 -0
  99. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_logs.py +0 -0
  100. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_mutation_hardening.py +0 -0
  101. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_paths.py +0 -0
  102. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_policy.py +0 -0
  103. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_rag.py +0 -0
  104. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_registry.py +0 -0
  105. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_store.py +0 -0
  106. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_util.py +0 -0
  107. {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/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.37
3
+ Version: 1.0.38
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.37'
22
- __version_tuple__ = version_tuple = (1, 0, 37)
21
+ __version__ = version = '1.0.38'
22
+ __version_tuple__ = version_tuple = (1, 0, 38)
23
23
 
24
24
  __commit_id__ = commit_id = None
@@ -272,19 +272,29 @@ def kv(key: str, value: str, width: int = 14) -> None:
272
272
  print(" " + c(key.ljust(width), DIM) + str(value))
273
273
 
274
274
 
275
+ def _pad(cell: str, width: int) -> str:
276
+ """Left-justify by *visible* width, so ANSI-colored cells still align
277
+ (str.ljust counts the invisible escape bytes and under-pads)."""
278
+ return cell + " " * (width - visible_len(cell))
279
+
280
+
275
281
  def table(rows, headers=None) -> None:
276
- """Print an aligned table. rows: list of tuples of strings."""
282
+ """Print an aligned table. rows: list of tuples of strings.
283
+
284
+ Column widths are measured by visible width (ignoring ANSI color codes),
285
+ so colored cells line up the same as plain ones.
286
+ """
277
287
  rows = [[str(x) for x in r] for r in rows]
278
288
  all_rows = ([list(map(str, headers))] if headers else []) + rows
279
289
  if not all_rows:
280
290
  return
281
- widths = [max(len(r[i]) for r in all_rows if i < len(r))
291
+ widths = [max(visible_len(r[i]) for r in all_rows if i < len(r))
282
292
  for i in range(max(len(r) for r in all_rows))]
283
293
  if headers:
284
- line = " ".join(str(h).ljust(widths[i]) for i, h in enumerate(headers))
294
+ line = " ".join(_pad(str(h), widths[i]) for i, h in enumerate(headers))
285
295
  print(c(line, BOLD))
286
296
  for r in rows:
287
- print(" ".join(cell.ljust(widths[i]) for i, cell in enumerate(r)).rstrip())
297
+ print(" ".join(_pad(cell, widths[i]) for i, cell in enumerate(r)).rstrip())
288
298
 
289
299
 
290
300
  def confirm(prompt: str, default: bool = False) -> bool:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: boost-skill-cli
3
- Version: 1.0.37
3
+ Version: 1.0.38
4
4
  Summary: boost — Homebrew for AI coding skills
5
5
  Author: Jonathan Reyes
6
6
  License: GNU GENERAL PUBLIC LICENSE
@@ -302,7 +302,7 @@
302
302
  </article>
303
303
 
304
304
  <article class="ritem" data-track="layout" data-impact="med">
305
- <div class="ritem-top"><span class="rid">BOOST-D08</span><span class="rstatus proposed">Proposed</span></div>
305
+ <div class="ritem-top"><span class="rid">BOOST-D08</span><span class="rstatus progress">In progress</span></div>
306
306
  <h4>Width-aware, right-aligned tables</h4>
307
307
  <p><code>table()</code> is a naive <code>ljust</code> that ignores terminal width and left-aligns numeric columns. Make it width-aware (shrink the widest text column to fit), right-align counts with tabular figures, and add dim column separators — matching the web's <code>font-variant-numeric: tabular-nums</code> stat blocks.</p>
308
308
  <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>
@@ -501,6 +501,27 @@ class TestHelpers:
501
501
  assert capsys.readouterr().out == " n 42\n"
502
502
 
503
503
 
504
+ class TestTableColor:
505
+ def test_pad_uses_visible_width(self, monkeypatch):
506
+ monkeypatch.setenv("CLICOLOR_FORCE", "1")
507
+ colored = output.aurora("ab", "cyan") # visible width 2
508
+ assert output._pad(colored, 5) == colored + " " # 3 trailing spaces
509
+
510
+ def test_colored_cells_align_by_visible_width(self, capsys, monkeypatch):
511
+ import re
512
+ monkeypatch.setenv("CLICOLOR_FORCE", "1")
513
+ # a colored cell must not push the next column out of alignment
514
+ output.table([[output.aurora("ab", "cyan"), "x"], ["cd", "y"]])
515
+ vis = [re.sub(r"\x1b\[[0-9;]*m", "", ln)
516
+ for ln in capsys.readouterr().out.splitlines()]
517
+ assert vis == ["ab x", "cd y"]
518
+
519
+ def test_header_row_is_bold_when_forced(self, capsys, monkeypatch):
520
+ monkeypatch.setenv("CLICOLOR_FORCE", "1")
521
+ output.table([["x", "1"]], headers=["NAME", "N"])
522
+ assert capsys.readouterr().out.startswith("\033[1mNAME")
523
+
524
+
504
525
  class TestTable:
505
526
  @pytest.fixture(autouse=True)
506
527
  def plain(self, monkeypatch):
File without changes