fix(#493): release site-version bump + correct issue-filing version on dev + tracker shape-only fallback#505
Conversation
…n dev + tracker shape-only fallback - #493: /release now bumps site/index.html version strings (JSON-LD softwareVersion + dateModified, hero pill, hero version link text/href, releases-shipped count + range) from the version being cut, as a new step 3.5; test_site_counts.sh asserts site softwareVersion == CHANGELOG top entry so drift fails CI. - #503: report-apexyard-bug + request-apexyard-feature derive the framework version from CHANGELOG.md's top `## [X.Y.Z]` (carried main->dev by /release-sync) instead of `git describe`, which returns a stale tag on dev. - #501: validate-pr-create.sh + verify-commit-refs.sh fall back to shape-only (advisory, exit 0) when a non-gh tracker returns empty; gh existence enforcement unchanged. Closes #493 Closes #503 Closes #501
atlas-apex
left a comment
There was a problem hiding this comment.
Code Review: PR #505
Commit: 0e2bbd6b37327cee9e0e19d07d560f58a953da7c
Summary
Three independent .claude/-only framework fixes batched on one branch (base dev): #493 (/release auto-bumps site/index.html version strings + durable drift guard), #503 (issue-filing skills capture the correct version on dev via CHANGELOG instead of git describe), #501 (non-gh trackers fall back to shape-only validation when unqueryable). All claims independently verified on this checkout.
Checklist Results
- Architecture & Design: Pass
- Code Quality: Pass
- Testing: Pass
- Security: Pass (no secrets, no injection surface; doc/test/hook edits)
- Performance: Pass (N/A — shell + markdown)
- PR Description & Glossary: Pass (7-term glossary, ticket links, testing steps)
- Summary Bullet Narrative: Pass (every bullet = what changed + why it matters)
- Technical Decisions (AgDR): N/A (bug fixes implementing already-decided models — release-cut AgDR-0007, tracker abstraction AgDR-0033; no new decision)
- Adopter Handbooks: N/A (no migration files → blocking migration-safety handbook does not fire; no language files → no language handbooks)
Verification performed (not taken on trust)
#493 — site-version drift guard is NOT a no-op.
bash test_site_counts.sh→ green; printsok site softwareVersion=2.2.0 matches CHANGELOG top entry 2.2.0.- Synthesized drift by mutating CHANGELOG top to
## [3.0.0]→ test went red withFAIL: site/index.html softwareVersion=2.2.0 but CHANGELOG.md top entry is 3.0.0and exit 1. Restored CHANGELOG cleanly. The assertion ([ "$SITE_VERSION" != "$CHANGELOG_VERSION" ] && exit 1) is a real comparison, not a tautology. - Step 3.5 is correctly placed between the CHANGELOG-draft step (3) and Open-the-release-PR step (4); it derives all seven version locations from the version being cut and explicitly leaves historical strings (CHANGELOG entries,
migrate-v1-to-v2.ts, AgDR examples) untouched.
#503 — snippets identical and correct.
- The bash code blocks in
report-apexyard-bug/SKILL.md(L88–98) andrequest-apexyard-feature/SKILL.md(L77–87) are byte-identical, including the surrounding "Do NOT use git describe" prose. - Ran the new snippet on this
devcheckout →FW_VERSION = v2.2.0(correct). The oldgit describe --tags --abbrev=0yields the stalev1.1.0— exactly the bug #503 fixes (release tags live onmain, not ancestors ofdev). v-prefix consistent: CHANGELOG top is bare2.2.0, primary path addsv→v2.2.0; thegit tag --sort=-v:refnamefallback already returnsv2.2.0. Both paths render the samev-prefixed value the field shows today.
#501 — shape-only fallback is correctly scoped; gh is NOT loosened.
bash test_tracker_aware_hooks.sh→ 22 passed, 0 failed.- The one modified existing test ("linear: missing → blocked" → "tracker CLI returns empty → shape-only PASS") is the correct #501 contract: a non-gh CLI returning empty is indistinguishable from "not queryable / unauthenticated", so it cannot hard-block a real ticket. This is not a gh weakening.
- Confirmed gh stays hard: in
validate-pr-create.shthe shape-only branch isif [ -z "$ISSUE_JSON" ] && [ "$TRACKER_KIND" != "gh" ]; the existence-block is theelifbelow it, structurally unreachable for non-gh and fully intact (exit 2) for gh. Case 12 (live) proves gh fabricated#Nstill BLOCKS in both hooks. - Closed-state still blocks: the
done|cancelled|resolved|completed → exit 2path is reached only when the tracker returned a ticket (non-emptyISSUE_JSON), so a returned-but-closed non-gh ticket still hard-blocks. Live: "linear closed (Done) → blocked" and "jira closed (Resolved) → blocked" both PASS.
Scope & hygiene.
- All 7 changed files are under
.claude/— confirmed no other paths in the diff. shellcheck 0.11.0:verify-commit-refs.shis warning-clean;validate-pr-create.shcarries SC1091/SC2059/SC2086 — verified identical on thedevmerge-base, so zero new warnings.- PR title
fix(#493): …matches format; bodyCloses #493 / #503 / #501; Glossary + narrative Summary present.
Issues Found
None.
Suggestions
- Minor (non-blocking): step 3.5's table lists approximate line numbers (
~L54,~L1568, …). These will drift assite/index.htmlevolves; thesoftwareVersiondrift guard backstops only that one location. Consider a follow-up that anchors the other six on stable markers (or extends the guard) so the operator isn't hunting by line number. Not a merge blocker — the durablesoftwareVersionguard is the load-bearing one.
Verdict
APPROVED
🤖 Reviewed by Rex (Code Reviewer Agent)
📌 Reviewed commit: 0e2bbd6b37327cee9e0e19d07d560f58a953da7c
…n dev + tracker shape-only fallback (#505) - #493: /release now bumps site/index.html version strings (JSON-LD softwareVersion + dateModified, hero pill, hero version link text/href, releases-shipped count + range) from the version being cut, as a new step 3.5; test_site_counts.sh asserts site softwareVersion == CHANGELOG top entry so drift fails CI. - #503: report-apexyard-bug + request-apexyard-feature derive the framework version from CHANGELOG.md's top `## [X.Y.Z]` (carried main->dev by /release-sync) instead of `git describe`, which returns a stale tag on dev. - #501: validate-pr-create.sh + verify-commit-refs.sh fall back to shape-only (advisory, exit 0) when a non-gh tracker returns empty; gh existence enforcement unchanged. Closes #493 Closes #503 Closes #501 Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com>
Three independent framework fixes batched on one branch (all touch
.claude/paths only).Summary
/releaseauto-bumps the marketing-site version strings + a durable drift guard. The release flow bumped the git tag and CHANGELOG but never touchedsite/index.html's hard-coded version, so the site advertised a stale version that drifted across ~5 release cycles before anyone noticed ([Chore] Fix stale framework version on marketing site (1.3.0/v1.1 → 2.2.0) #491). A new step 3.5 in.claude/skills/release/SKILL.mdupdates all seven version locations (JSON-LDsoftwareVersion+dateModified, hero pillapexyard vX.Y, hero version link text +releases/tag/vX.Y.Zhref, releases-shipped count +(v0.1 → vX.Y)range) — derived from the version being cut, not hand-edited — and explicitly leaves historical strings (CHANGELOG entries, migration filenames, AgDR examples) untouched.test_site_counts.shnow asserts the site'ssoftwareVersionequals the top## [X.Y.Z]CHANGELOG entry, so any future cut that bumps one without the other fails CI instead of drifting silently. The existingsite-counts-check.ymlworkflow already runs this test, so no workflow change is needed.dev. Under the release-cut model, release tags live onmainand are not ancestors ofdev, sogit describe --tags --abbrev=0from adevcheckout returned a stale version (v1.1.0when the line was actuallyv2.2.0), mislabeling every issue filed fromdev. Bothreport-apexyard-bugandrequest-apexyard-featurenow derive the version from the top## [X.Y.Z]inCHANGELOG.md(carriedmain → devby/release-sync, so always current ondev), with robust fallbacks: highest semver tag across all refs (git tag --sort=-v:refname) → short HEAD →unknown. Thevprefix the field renders today is preserved.validate-pr-create.shandverify-commit-refs.shhardwired a GitHub-issue existence check, so a project with.tracker.kind = linear/jira/etc. could not open a PR or commit referencing a real tracker key when the tracker CLI was absent or not queryable — the hook looked for a GitHub issue that would never exist and blocked at creation. Now, whenTRACKER_KIND != ghandtracker_viewreturns empty, both hooks fall back to shape-only validation (the key already passed the title/commit regex againsttracker_id_pattern), emit a one-line advisory to stderr, and exit 0. The hard existence block is retained only forTRACKER_KIND == gh— GitHub behaviour is entirely unchanged.Testing
bash .claude/hooks/tests/test_tracker_aware_hooks.sh→ 22 passed, 0 failed. Added cases for [Feature] Make ticket-existence hooks tracker-aware (don't require a GitHub issue when the configured tracker isn't GitHub) #501: non-gh tracker not queryable → shape-only PASS (both hooks); ill-formed title still fails the shape check under a non-gh tracker; gh fabricated#Nstill BLOCKS (gh behaviour unchanged, both hooks). The pre-existing "linear: missing ticket → blocked" case was updated to the new [Feature] Make ticket-existence hooks tracker-aware (don't require a GitHub issue when the configured tracker isn't GitHub) #501 contract (a non-gh CLI returning empty is indistinguishable from "not queryable" → shape-only PASS); the closed-state (Linear "Done", Jira "Resolved") block cases remain green.bash .claude/hooks/tests/test_site_counts.sh→ PASS. The new version-drift guard reportsok site softwareVersion=2.2.0 matches CHANGELOG top entry 2.2.0. Verified it FAILS (exit 1) on a synthesised drift fixture (CHANGELOG3.0.0vs site2.2.0).devcheckout: new snippet yieldsFW_VERSION = v2.2.0(correct); the oldgit describe --tags --abbrev=0yields the stalev1.1.0.shellcheckonvalidate-pr-create.shandverify-commit-refs.sh: no new warnings.validate-pr-create.shcarries the same 3 pre-existing info-level warnings (SC1091, SC2059, SC2086) as theupstream/devbaseline;verify-commit-refs.shis warning-clean in both.Glossary
devaccumulates daily merges andmainreceives tagged release PRs (vX.Y.Z); tags are not ancestors ofdev.softwareVersionSoftwareApplicationfield insite/index.htmlthat advertises the current framework version.git describe --tags --abbrev=0dev..tracker.kindgh,jira,linear,asana,custom,none).tracker_id_patternwithout asserting it exists in a tracker.tracker_view_lib-tracker.shfunction that dispatches the configured tracker's view command and emits normalised JSON; empty output = not found / not queryable.Closes #493
Closes #503
Closes #501