diff --git a/plugin/.claude-plugin/plugin.json b/plugin/.claude-plugin/plugin.json index 4e078a1..ae00a4f 100644 --- a/plugin/.claude-plugin/plugin.json +++ b/plugin/.claude-plugin/plugin.json @@ -1,7 +1,7 @@ { "name": "scribe", "description": "Scribe system-of-record for Claude Code: MCP tools over your notes/tasks/projects/rules, a session-start push channel that surfaces your always-on rules + active-project context, process-skills (writing-plans, systematic-debugging, verification, brainstorming, reusing-code), and your saved Scribe Processes auto-surfaced as skills (/scribe:sync). Replaces superpowers + file-memory with one app-backed plugin.", - "version": "2026.09.01.2252", + "version": "2026.09.02.0415", "author": { "name": "Bryan Van Deusen" }, diff --git a/scripts/check_plugin.py b/scripts/check_plugin.py index 150e72c..9066a7a 100755 --- a/scripts/check_plugin.py +++ b/scripts/check_plugin.py @@ -596,7 +596,7 @@ def check_version_is_minted(base: str = "origin/main") -> None: # Do NOT pass silently — a check that quietly no-ops is how this class # of bug survives in the first place. fail( - f"cannot resolve {base}, so the version-bump check could not run. " + f"cannot resolve {base}, so the minted-version check could not run. " f"Fetch it first — `git fetch --depth=1 origin main:refs/remotes/" f"origin/main` is enough, since this diffs two trees and needs no " f"common ancestor — or pass --no-version deliberately." diff --git a/scripts/mint_plugin_version.py b/scripts/mint_plugin_version.py index 2d45d77..c37df47 100644 --- a/scripts/mint_plugin_version.py +++ b/scripts/mint_plugin_version.py @@ -64,9 +64,19 @@ VERSION_LINE_RE = re.compile(r'^(\s*"version"\s*:\s*")([^"]*)(".*)$', re.M) def mint(now: datetime | None = None) -> str: - """The version for this moment. UTC, always — a local-time mint would make - the value depend on who ran it.""" - return (now or datetime.now(timezone.utc)).strftime(VERSION_FORMAT) + """The version for this moment. UTC, always. + + The conversion is not decoration: `strftime` renders whatever offset the + datetime carries, so without it two people minting the same instant in + different zones produce different strings — and the string IS the + artifact's identity. A naive datetime is read as UTC rather than as the + machine's zone, because that is this function's stated contract and + guessing the host's offset is how the bug comes back by another route. + """ + moment = now or datetime.now(timezone.utc) + if moment.tzinfo is None: + moment = moment.replace(tzinfo=timezone.utc) + return moment.astimezone(timezone.utc).strftime(VERSION_FORMAT) def rewrite(text: str, version: str) -> str: diff --git a/tests/test_plugin_version_mint.py b/tests/test_plugin_version_mint.py index 8943e5f..4b2d33c 100644 --- a/tests/test_plugin_version_mint.py +++ b/tests/test_plugin_version_mint.py @@ -250,13 +250,21 @@ def test_a_version_that_moved_with_no_content_change_is_NOT_a_failure(monkeypatc def test_a_failed_diff_FAILS_rather_than_passing_quietly(monkeypatch): """A check that cannot run must not report the same thing as a check that - passed — #2663's lesson, and the reason this whole file's siblings exist.""" - monkeypatch.setattr(check_plugin, "_git", lambda *a: (128, "fatal")) + passed — #2663's lesson, and the reason this file's siblings exist. + + `rev-parse` is stubbed to SUCCEED so only the diff fails. Failing every git + call would trip the base-branch guard first and this would pass while + proving nothing about the diff arm. + """ + monkeypatch.setattr( + check_plugin, "_git", + lambda *a: (128, "fatal: bad object") if a[0] == "diff" else (0, ""), + ) monkeypatch.setattr(check_plugin, "manifest_version", lambda ref=None: "2026.09.01.2252") check_plugin.check_version_is_minted("origin/main") assert len(check_plugin.failures) == 1 - assert "could not run" in check_plugin.failures[0] + assert "git diff" in check_plugin.failures[0] # ── The real manifest ──────────────────────────────────────────────────────