Commit Graph
2 Commits
Author SHA1 Message Date
bvandeusenandClaude Opus 5 64cb719a12 fix(plugin): mint() rendered whatever offset it was handed, not UTC (#3327)
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 8s
CI & Build / integration (push) Successful in 30s
CI & Build / TypeScript typecheck (push) Successful in 34s
CI & Build / Python tests (push) Successful in 1m10s
CI & Build / Build & push image (push) Successful in 15s
Run 5175 red on the Python tests lane. The failing assertion was
test_the_mint_is_UTC_not_local, and it was right: `strftime` renders the
offset the datetime carries, so mint() only produced UTC because its DEFAULT
argument happens to be datetime.now(timezone.utc). Hand it an aware datetime
in any other zone and it formats that zone's wall clock -- 22:52Z and its
+09:00 twin, the same instant, minted as 2026.09.01.2252 and 2026.09.02.0752.

The docstring already claimed "UTC, always", so this was a contract the code
did not hold rather than a test asking for something new. Two people minting
the same instant would disagree, and the string IS the artifact's identity.

Now converts explicitly. A naive datetime is read as UTC rather than as the
machine's zone: that is this function's stated contract, and guessing the
host's offset is how the same bug returns by another route.

Two things found while walking the rest of the module by hand:

- test_a_failed_diff_FAILS_rather_than_passing_quietly stubbed EVERY git call
  to fail, so it tripped the base-branch guard first and passed while proving
  nothing about the diff arm. rev-parse now succeeds and only the diff fails,
  and the assertion names the diff message instead of the substring both
  messages happen to share.
- the base-branch failure still said "version-bump check", a name that went
  away with check_version_bump.

The mint script is in the version-relevant set, so fixing it is itself a
version-relevant change and forced a fresh mint -- 2026.09.02.0415. That is
the asymmetry in #3127 section 3 working as intended rather than a quirk: a
format change that did not re-mint would leave the manifest reporting a value
the current deriver can no longer produce.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DN4zBVFWhBST9YqjCfQmPb
2026-09-02 00:15:45 -04:00
bvandeusenandClaude Opus 5 f1896bfe9d feat(plugin): mint the version, and make CI the control that it moved (#3327)
CI & Build / Python tests (push) Failing after 3s
CI & Build / Python lint (push) Successful in 4s
CI & Build / Plugin hooks (push) Successful in 11s
CI & Build / integration (push) Successful in 32s
CI & Build / TypeScript typecheck (push) Successful in 35s
CI & Build / Build & push image (push) Skipped
Milestone 334 step 3. 0.1.48 was the last of 48 numbers a person typed by
hand; forgetting to type the 49th is #2209, #1040 and #2220, three separate
times a shipped fix reached the repo and stopped there.

WHY A SCRIPT AND NOT A BUILD STEP. plugin/ is not in the image -- installs
fetch it from this repo via marketplace.json, so the push IS the release and
there is no moment at which CI could stamp a version in. Every other artifact
in the family derives during a build (#3127 section 2). This one has no build
to derive during, so the value is minted before the commit and CI's job is to
prove it moved when it had to.

MINT TIME, a fourth clock section 2 does not name. It prescribes commit time
so two lanes building one source report one string; the plugin has one lane
and no build, so that reason does not reach it. What is given up is
reproducibility-from-history -- you cannot recompute the value, only verify it
moved. That is acceptable ONLY because #3325 read the installer's code and
found the refresh test is `P.version === H`, plain equality, with zero
ordering comparisons anywhere. Where a comparator orders, an unreproducible
version would be unverifiable too.

Two artifacts in one repo now derive from different clocks on purpose, one
directory apart. "Let's make these consistent" is the obvious tidy-up and
breaks whichever loses, so the divergence is pinned in tests rather than only
explained in a comment -- including an AST assertion that the mint script
never imports subprocess, since a mint that can read history is a commit-time
deriver wearing the wrong name.

check_version_bump becomes check_version_is_minted. It gains the shape gate
and a future-value gate, and it keeps deliberately NOT failing when the
version moved without content changing: a needless re-mint costs one cache
refresh, and failing the lane over a harmless act is how a check earns a
--no-version in somebody's muscle memory and stops running at all. The
implication that matters is one-directional.

The mint script joins the version-relevant set, which is step 2's DERIVERS
table finally being read by something. Section 3's asymmetry is why it is not
optional: change the format string, change nothing else, and a diff over the
shipped paths alone says "no content change" while the manifest keeps a value
in the old format forever. Its own introduction demonstrates this -- adding
the deriver is itself the version-relevant change that forced this mint.

fetch-depth: 0 was NOT added, against this step's own brief. The plugin job
carries a comment refusing it, backed by an observed act_runner failure (any
`with:` block made checkout fail to extract, run 3027), and the reasoning
holds: the check diffs two trees and the workflow already fetches main at
depth 1. Checklist 6 is about jobs that derive; this one checks.

Verified live before pushing: the session-context marker reports
v2026.09.01.2252 keylessly, and both failure arms were probed by hand rather
than assumed. The shape gate fires first on a reverted 0.1.48, so the stale
arm is covered by unit test rather than by that probe.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DN4zBVFWhBST9YqjCfQmPb
2026-09-01 18:54:55 -04:00