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.
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/PKG-INFO +1 -1
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/_version.py +2 -2
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/output.py +14 -4
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/PKG-INFO +1 -1
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/design-roadmap.html +1 -1
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_output.py +21 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/.gitignore +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/CLAUDE.md +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/CONTRIBUTING.md +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/LICENSE +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/MANIFEST.in +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/Makefile +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/README.md +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/SECURITY.md +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/__init__.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/__main__.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/cli.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/cliparse.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/__init__.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/bmad.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/configuration.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/discovery.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/hooks.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/info.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/intelligence.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/pkg.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/quality.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/taps.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/commands/team.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/__init__.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/agents.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/ai.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/catalog.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/claude_settings.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/config.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/dense.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/embed.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/frontmatter.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/gitutil.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/journal.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/lockfile.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/logs.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/paths.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/policy.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/rag.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/registry.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/store.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/core/util.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/data/registries.json +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_cli/errors.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/SOURCES.txt +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/dependency_links.txt +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/entry_points.txt +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/requires.txt +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/top_level.txt +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/.claude/settings.local.json +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/DEBUGGING.md +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/demo.gif +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/demo.tape +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/index.html +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/rag-architecture.md +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/docs/roadmap.html +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/pyproject.toml +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/scripts/build_registries.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/scripts/mutation_gate.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/setup.cfg +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/style/README.md +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/style/boost.css +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/style/boost.js +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/style/demo.html +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/conftest.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_bmad.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_configuration.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_discovery.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_hooks.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_info.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_intelligence.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_pkg.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_quality.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_taps.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_team.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_everyday_loop.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/make_fixture.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/smoke.sh +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_agents.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_ai.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_catalog.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_claude_settings.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_cliparse.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_config.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_dense.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_embed.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_errors_and_cli_table.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_frontmatter.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_gitutil.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_journal.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_lockfile.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_logs.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_mutation_hardening.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_paths.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_policy.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_rag.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_registry.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_store.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_util.py +0 -0
- {boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/unit/test_version.py +0 -0
|
@@ -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.
|
|
22
|
-
__version_tuple__ = version_tuple = (1, 0,
|
|
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(
|
|
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)
|
|
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
|
|
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:
|
|
@@ -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
|
|
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
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/boost_skill_cli.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{boost_skill_cli-1.0.37 → boost_skill_cli-1.0.38}/tests/functional/test_cli_configuration.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|