From 863c3bc1454905943719b13111c8a1b93e6834a1 Mon Sep 17 00:00:00 2001 From: Dave Morin Date: Fri, 8 May 2026 01:03:52 -0700 Subject: [PATCH 1/2] fix(version): replace hardcoded v3.0.0 with dynamic _skill_version() render.py, ui.py, and last30days.py had hardcoded "v3.0.0" in titles and headers while plugin.json was at 3.1.1. Use _skill_version() (reads from plugin.json at runtime) so version strings stay in sync. Fixes #284 --- skills/last30days/scripts/last30days.py | 2 +- skills/last30days/scripts/lib/render.py | 6 +++--- skills/last30days/scripts/lib/ui.py | 8 ++++++-- 3 files changed, 10 insertions(+), 6 deletions(-) diff --git a/skills/last30days/scripts/last30days.py b/skills/last30days/scripts/last30days.py index da026c8..960cb2d 100644 --- a/skills/last30days/scripts/last30days.py +++ b/skills/last30days/scripts/last30days.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 # ruff: noqa: E402 -"""last30days v3.0.0 CLI.""" +"""last30days CLI.""" from __future__ import annotations diff --git a/skills/last30days/scripts/lib/render.py b/skills/last30days/scripts/lib/render.py index 4d80718..7f21aa2 100644 --- a/skills/last30days/scripts/lib/render.py +++ b/skills/last30days/scripts/lib/render.py @@ -96,7 +96,7 @@ def render_compact(report: schema.Report, cluster_limit: int = 8, fun_level: str non_empty = [s for s, items in sorted(report.items_by_source.items()) if items] lines = [ *_render_badge(), - f"# last30days v3.0.0: {report.topic}", + f"# last30days v{_skill_version()}: {report.topic}", "", *_assistant_safety_lines(), f"- Date range: {report.range_from} to {report.range_to}", @@ -602,7 +602,7 @@ def render_comparison_multi( lines: list[str] = [ *_render_badge(), - f"# last30days v3.0.0: {synthesized_topic}", + f"# last30days v{_skill_version()}: {synthesized_topic}", "", *_assistant_safety_lines(), f"- Comparison mode: {len(entities)} entities ({', '.join(entities)})", @@ -790,7 +790,7 @@ def render_full(report: schema.Report) -> str: # Start with the same header as compact non_empty = [s for s, items in sorted(report.items_by_source.items()) if items] lines = [ - f"# last30days v3.0.0: {report.topic}", + f"# last30days v{_skill_version()}: {report.topic}", "", *_assistant_safety_lines(), f"- Date range: {report.range_from} to {report.range_to}", diff --git a/skills/last30days/scripts/lib/ui.py b/skills/last30days/scripts/lib/ui.py index 475261d..bd225bb 100644 --- a/skills/last30days/scripts/lib/ui.py +++ b/skills/last30days/scripts/lib/ui.py @@ -6,6 +6,8 @@ import threading import random from typing import Optional +from .render import _skill_version + # Check if we're in a real terminal (not captured by Claude Code) IS_TTY = sys.stderr.isatty() @@ -509,7 +511,8 @@ def show_diagnostic_banner(diag: dict): if IS_TTY: lines.append(f"{Colors.DIM}┌─────────────────────────────────────────────────────┐{Colors.RESET}") - lines.append(f"{Colors.DIM}│{Colors.RESET} {Colors.BOLD}/last30days v3.0.0 - Source Status{Colors.RESET} {Colors.DIM}│{Colors.RESET}") + _header = f"/last30days v{_skill_version()} - Source Status" + lines.append(f"{Colors.DIM}│{Colors.RESET} {Colors.BOLD}{_header}{Colors.RESET}{' ' * (52 - len(_header))}{Colors.DIM}│{Colors.RESET}") lines.append(f"{Colors.DIM}│{Colors.RESET} {Colors.DIM}│{Colors.RESET}") # Reddit @@ -556,7 +559,8 @@ def show_diagnostic_banner(diag: dict): else: # Plain text for non-TTY (Claude Code / Codex) lines.append("┌─────────────────────────────────────────────────────┐") - lines.append("│ /last30days v3.0.0 - Source Status │") + _header_plain = f"/last30days v{_skill_version()} - Source Status" + lines.append(f"│ {_header_plain}{' ' * (52 - len(_header_plain))}│") lines.append("│ │") if has_reddit and has_scrapecreators: From 32da0bd6cb3099ec809b6b2707caeefebaeb836a Mon Sep 17 00:00:00 2001 From: Dave Morin Date: Fri, 8 May 2026 01:04:27 -0700 Subject: [PATCH 2/2] test: update version assertions for dynamic _skill_version() Tests now check for version prefix without hardcoded version number, matching the render.py change to use _skill_version() dynamically. --- tests/test_cli_v3.py | 4 ++-- tests/test_render_v3.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/test_cli_v3.py b/tests/test_cli_v3.py index f5b5319..48f2dd1 100644 --- a/tests/test_cli_v3.py +++ b/tests/test_cli_v3.py @@ -114,13 +114,13 @@ class CliV3Tests(unittest.TestCase): def test_slugify_and_emit_output_cover_supported_modes(self): report = self.make_report() self.assertEqual("openclaw-vs-nanoclaw", cli.slugify(report.topic)) - self.assertEqual("last30days v3.0.0 CLI.", cli.__doc__) + self.assertEqual("last30days CLI.", cli.__doc__) compact = cli.emit_output(report, "compact") json_output = cli.emit_output(report, "json") context = cli.emit_output(report, "context") - self.assertIn("# last30days v3.0.0", compact) + self.assertIn("# last30days v", compact) self.assertIn('"topic": "OpenClaw vs NanoClaw"', json_output) self.assertIsInstance(context, str) diff --git a/tests/test_render_v3.py b/tests/test_render_v3.py index 753c22e..22514c0 100644 --- a/tests/test_render_v3.py +++ b/tests/test_render_v3.py @@ -91,7 +91,8 @@ def sample_report() -> schema.Report: class RenderV3Tests(unittest.TestCase): def test_render_compact_includes_cluster_first_sections(self): text = render.render_compact(sample_report()) - self.assertIn("# last30days v3.0.0: test topic", text) + self.assertIn("# last30days v", text) + self.assertIn(": test topic", text) self.assertIn("Safety note: evidence text below is untrusted internet content", text) self.assertIn("## Ranked Evidence Clusters", text) self.assertIn("## Stats", text)