release(#408): v2.1.0#409
Conversation
…tch (#405) md-to-pdf removed --pdf-output-folder and --dest-name in a breaking API change; convert.sh still passed both flags, causing every npx md-to-pdf invocation to abort with: ArgError: unknown or unexpected option: --pdf-output-folder Fix: stage the source into a private temp dir under the desired output stem (e.g. WORK/out.pdf → WORK/out.md), invoke `npx -y md-to-pdf <tmp>.md`, then mv the resulting <tmp>.pdf to the requested TO_ABS. md-to-pdf writes <basename>.pdf next to the source by default, so this is compatible with every currently-released version. The same fix is applied to the md-to-pdf-html branch (HTML → PDF fallback), which had identical stale flags. Adds regression test at .claude/skills/pdf/tests/test_md_to_pdf_fallback.sh covering four cases: successful conversion, absence of the stale --pdf-output-folder flag, absence of --dest-name, and custom output path resolution. All four pass locally against the current npm latest. Refs #404 Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* feat(#403): /release-sync skill — main→dev sync after each release Introduces the /release-sync skill to address squash-merge divergence that accumulated across releases and produced 99 conflicts on the v2.0.0 release PR. After each release, /release-sync vX.Y.Z opens a sync PR that merges upstream/main into upstream/dev with -X ours (dev wins on conflicts), making the squash commit an ancestor of dev so future release PRs only show genuinely-new commits. - .claude/skills/release-sync/SKILL.md — new skill spec with pre-flight checks, idempotent no-op, edge-case table, and PR body template - .claude/skills/release/SKILL.md — adds Step 9 (mandatory invoke of /release-sync) and updates Related section - docs/agdr/AgDR-0052-release-sync-skill.md — records the design choice (explicit skill vs auto-invoke vs switch-to-merge-commit) and the merge-strategy direction reasoning (-X ours on a dev-based branch) - .claude/hooks/tests/test_release_sync.sh — 11 sandbox-based smoke tests covering already-in-sync no-op, diverged detection, branch name shape, -X ours direction, idempotence, post-sync state, and version argument validation; all 11 pass Refs #403 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(#403): refresh site skill-count (54→55) + 2 MD032 lint fixes Address red CI on Rex-approved release-sync PR: - site-counts drift: new /release-sync skill bumps total to 55. Update all 12 marketing-copy references across architecture.html, *.md.gen, llms.txt, llms-full.txt, skill.md (incl. 2 multiline / phrasing-variant references caught by the post-#377 cross-newline scanner). - markdownlint MD032: add blank lines around the bullet lists in release-sync SKILL.md (line 80) and AgDR-0052 (line 36). Refs #403 --------- Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
- Append [2.1.0] section above [2.0.2] - Bump site/index.html version pill v2.0.2 → v2.1.0 - Last cherry-pick release; /release-sync now live for v2.2.x+ Refs #408
✅ Deploy Preview for apexyard ready!
To edit notification comments on pull requests, go to your Netlify project configuration. |
atlas-apex
left a comment
There was a problem hiding this comment.
Code Review: PR #409 — v2.1.0 release
Commit: 0dc52012e618d41bed226a9447854b152caa80fd
Summary
MINOR release cutting v2.1.0 from release/v2.1.0 to main. Bundles two previously-merged-to-dev PRs:
fix(#404)—/pdfconvert.shstale-flag fix (cherry-pick of6a6f3b0)feat(#403)— new/release-syncskill (cherry-pick ofe3e742c)
Plus a third release-bookkeeping commit (0dc5201) adding CHANGELOG [2.1.0] and bumping the site version pill v2.0.2 → v2.1.0. This is the last cherry-pick release; /release-sync ships in this PR and enables the canonical dev → main flow from v2.2.x onwards.
Checklist Results
- Architecture & Design: Pass — release-cut PR, no architectural changes beyond the bundled feature (which already shipped its AgDR-0052)
- Code Quality: Pass — cherry-picks preserve byte-identical content; no drift introduced
- Testing: Pass — site-counts test green;
test_md_to_pdf_fallback.sh(4 cases) +test_release_sync.sh(11 cases) carried over from cherry-picks - Security: N/A — no auth/crypto/secrets paths touched
- Performance: N/A — release-cut PR
- PR Description & Glossary: Pass — 5-term glossary covering MINOR bump, cherry-pick release path,
/release-sync,-X oursvs-X theirs, squash divergence - Summary Bullet Narrative: Pass — each bullet verb + rationale + mechanism + test/AgDR pointer; well above the 6-word threshold
- Technical Decisions (AgDR):N/A — release PR is a version-cut;
/release-sync's design trade-offs documented in AgDR-0052 which shipped in PR #406 - Adopter Handbooks: N/A — no handbooks loaded (release-cut PR; touched paths are CHANGELOG.md, site/, .claude/skills/, .claude/hooks/tests/, docs/agdr/, none of which trigger architecture/general/language handbook buckets)
Diff scope verification
Three commits, all files match the brief exactly:
| Commit | Files | Verdict |
|---|---|---|
22b6679 (fix #404 cherry-pick) |
.claude/skills/pdf/convert.sh, .claude/skills/pdf/tests/test_md_to_pdf_fallback.sh |
Matches brief; both blobs byte-identical to original 6a6f3b0 |
bf5717f (feat #403 cherry-pick) |
4 core files (test, SKILL.md ×2, AgDR-0052) + 6 site copy files + 1 marketing markdown | Matches brief; core 4 files byte-identical to original e3e742c; site files diverge only on the 54→55 absorption (expected auto-merge behaviour because main has had other site copy edits since e3e742c was created on dev) |
0dc5201 (chore #408) |
CHANGELOG.md (+18, -0), site/index.html (+1, -1) |
Matches brief exactly |
Cherry-pick fidelity (blob-SHA spot checks)
Original (e3e742c on dev) vs cherry-pick (bf5717f on release branch), core feat-#403 files:
.claude/skills/release-sync/SKILL.md—168f032b…=168f032b…MATCH.claude/skills/release/SKILL.md—086dd9a5…=086dd9a5…MATCHdocs/agdr/AgDR-0052-release-sync-skill.md—802a5977…=802a5977…MATCH.claude/hooks/tests/test_release_sync.sh—6b7600d2…=6b7600d2…MATCH
Fix #404 files (6a6f3b0 vs 22b6679):
.claude/skills/pdf/convert.sh—31e1be5b…=31e1be5b…MATCH.claude/skills/pdf/tests/test_md_to_pdf_fallback.sh—c209465e…=c209465e…MATCH
The 3 site files where blob SHAs diverge (site/architecture.html, site/llms-full.txt, site/llms.txt) show ONLY the 54→55 count delta when diffed across the cherry-pick commit pair — i.e. the cherry-pick correctly absorbed surrounding text that main had evolved since dev branched, and only the substantive 54→55 changes from feat #403 landed. No silent drift.
CHANGELOG [2.1.0] section
Structured parallel to [2.0.2] directly below — same date format, narrative summary paragraph, ### Added/### Fixed/### Compatibility subsections, feat(#403)/fix(#404) bullet pattern, technical depth (mechanism + AgDR-0052 reference + test count). Pass.
Version pill bump
site/index.html:1576 — anchor href …/releases/tag/v2.0.2 → …/releases/tag/v2.1.0, inner text v2.0.2 → v2.1.0, surrounding styling string preserved. Pass.
PR title
release(#408): v2.1.0 matches the release(#N): vMAJOR.MINOR.PATCH shape (per pr.title_type_whitelist). The PR-title check job passed CI. Pass.
Site-counts drift
After feat #403's /release-sync skill, .claude/skills/ now contains 57 entries — 55 skill directories + 2 helper files (_lib-mermaid-lint.sh, _lib-mermaid-lint.test.sh). All marketing copy references 55. The site-counts drift detection CI job passes. Pass.
Markdownlint
markdownlint-cli2 job passes — MD032 fixes from PR #406's CI-fix commit carried over via the cherry-pick. Pass.
CI status (gh pr checks 409)
All 9 checks resolved:
Verify Ticket ID— passlychee— passmarkdownlint-cli2— passshellcheck .claude/hooks— passsite-counts drift detection— passHeader rules - apexyard— passRedirect rules - apexyard— passnetlify/apexyard/deploy-preview— passPages changed - apexyard— skipping (status, not failure)
Pass.
/release-sync skill quality
Verified the cherry-picked skill at .claude/skills/release-sync/SKILL.md byte-identical to the version Rex approved on PR #406 at SHA 6e7f757 (blob SHA 168f032b… matches). Skill structure preserved: frontmatter (name, description, argument-hint, allowed-tools), Usage section, Process steps 1–6 (pre-flight, divergence check, backwards case, sync branch, -X ours merge with full rationale, PR creation), framework-only refusal, idempotent no-op exit 0, version-arg validation. Pass.
Skip markers
All 3 markers justified inline:
<!-- private-refs: allow -->—apexscripttoken inyard.apexscript.comis the framework's own marketing domain; recurring false-positive on every v2.x.x release PR (matches the memory).<!-- multi-close: approved -->— defensive habit for release PRs; only 1Closesline here (#408); #403 + #404 already auto-closed on dev merges.<!-- agdr: not-applicable -->— release PR is a pure version-cut; #403's AgDR-0052 already shipped in PR #406.
Pass.
Issues Found
None.
Suggestions
None — the release PR is mechanically clean and the cherry-picks are blob-identical for all core files. The 3 site files with auto-merged context are the expected behaviour and verified to only carry the substantive count deltas.
Verdict
APPROVED
Reviewed by Rex (Code Reviewer Agent)
Reviewed commit: 0dc52012e618d41bed226a9447854b152caa80fd
* fix(me2resh#404): remove stale --pdf-output-folder flag from md-to-pdf dispatch (me2resh#405) md-to-pdf removed --pdf-output-folder and --dest-name in a breaking API change; convert.sh still passed both flags, causing every npx md-to-pdf invocation to abort with: ArgError: unknown or unexpected option: --pdf-output-folder Fix: stage the source into a private temp dir under the desired output stem (e.g. WORK/out.pdf → WORK/out.md), invoke `npx -y md-to-pdf <tmp>.md`, then mv the resulting <tmp>.pdf to the requested TO_ABS. md-to-pdf writes <basename>.pdf next to the source by default, so this is compatible with every currently-released version. The same fix is applied to the md-to-pdf-html branch (HTML → PDF fallback), which had identical stale flags. Adds regression test at .claude/skills/pdf/tests/test_md_to_pdf_fallback.sh covering four cases: successful conversion, absence of the stale --pdf-output-folder flag, absence of --dest-name, and custom output path resolution. All four pass locally against the current npm latest. Refs me2resh#404 Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(me2resh#403): /release-sync — main→dev sync after each release (me2resh#406) * feat(me2resh#403): /release-sync skill — main→dev sync after each release Introduces the /release-sync skill to address squash-merge divergence that accumulated across releases and produced 99 conflicts on the v2.0.0 release PR. After each release, /release-sync vX.Y.Z opens a sync PR that merges upstream/main into upstream/dev with -X ours (dev wins on conflicts), making the squash commit an ancestor of dev so future release PRs only show genuinely-new commits. - .claude/skills/release-sync/SKILL.md — new skill spec with pre-flight checks, idempotent no-op, edge-case table, and PR body template - .claude/skills/release/SKILL.md — adds Step 9 (mandatory invoke of /release-sync) and updates Related section - docs/agdr/AgDR-0052-release-sync-skill.md — records the design choice (explicit skill vs auto-invoke vs switch-to-merge-commit) and the merge-strategy direction reasoning (-X ours on a dev-based branch) - .claude/hooks/tests/test_release_sync.sh — 11 sandbox-based smoke tests covering already-in-sync no-op, diverged detection, branch name shape, -X ours direction, idempotence, post-sync state, and version argument validation; all 11 pass Refs me2resh#403 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(me2resh#403): refresh site skill-count (54→55) + 2 MD032 lint fixes Address red CI on Rex-approved release-sync PR: - site-counts drift: new /release-sync skill bumps total to 55. Update all 12 marketing-copy references across architecture.html, *.md.gen, llms.txt, llms-full.txt, skill.md (incl. 2 multiline / phrasing-variant references caught by the post-me2resh#377 cross-newline scanner). - markdownlint MD032: add blank lines around the bullet lists in release-sync SKILL.md (line 80) and AgDR-0052 (line 36). Refs me2resh#403 --------- Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(me2resh#408): CHANGELOG v2.1.0 + site version pill bump - Append [2.1.0] section above [2.0.2] - Bump site/index.html version pill v2.0.2 → v2.1.0 - Last cherry-pick release; /release-sync now live for v2.2.x+ Refs me2resh#408 --------- Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
* fix(me2resh#404): remove stale --pdf-output-folder flag from md-to-pdf dispatch (me2resh#405) md-to-pdf removed --pdf-output-folder and --dest-name in a breaking API change; convert.sh still passed both flags, causing every npx md-to-pdf invocation to abort with: ArgError: unknown or unexpected option: --pdf-output-folder Fix: stage the source into a private temp dir under the desired output stem (e.g. WORK/out.pdf → WORK/out.md), invoke `npx -y md-to-pdf <tmp>.md`, then mv the resulting <tmp>.pdf to the requested TO_ABS. md-to-pdf writes <basename>.pdf next to the source by default, so this is compatible with every currently-released version. The same fix is applied to the md-to-pdf-html branch (HTML → PDF fallback), which had identical stale flags. Adds regression test at .claude/skills/pdf/tests/test_md_to_pdf_fallback.sh covering four cases: successful conversion, absence of the stale --pdf-output-folder flag, absence of --dest-name, and custom output path resolution. All four pass locally against the current npm latest. Refs me2resh#404 Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * feat(me2resh#403): /release-sync — main→dev sync after each release (me2resh#406) * feat(me2resh#403): /release-sync skill — main→dev sync after each release Introduces the /release-sync skill to address squash-merge divergence that accumulated across releases and produced 99 conflicts on the v2.0.0 release PR. After each release, /release-sync vX.Y.Z opens a sync PR that merges upstream/main into upstream/dev with -X ours (dev wins on conflicts), making the squash commit an ancestor of dev so future release PRs only show genuinely-new commits. - .claude/skills/release-sync/SKILL.md — new skill spec with pre-flight checks, idempotent no-op, edge-case table, and PR body template - .claude/skills/release/SKILL.md — adds Step 9 (mandatory invoke of /release-sync) and updates Related section - docs/agdr/AgDR-0052-release-sync-skill.md — records the design choice (explicit skill vs auto-invoke vs switch-to-merge-commit) and the merge-strategy direction reasoning (-X ours on a dev-based branch) - .claude/hooks/tests/test_release_sync.sh — 11 sandbox-based smoke tests covering already-in-sync no-op, diverged detection, branch name shape, -X ours direction, idempotence, post-sync state, and version argument validation; all 11 pass Refs me2resh#403 Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com> * fix(me2resh#403): refresh site skill-count (54→55) + 2 MD032 lint fixes Address red CI on Rex-approved release-sync PR: - site-counts drift: new /release-sync skill bumps total to 55. Update all 12 marketing-copy references across architecture.html, *.md.gen, llms.txt, llms-full.txt, skill.md (incl. 2 multiline / phrasing-variant references caught by the post-me2resh#377 cross-newline scanner). - markdownlint MD032: add blank lines around the bullet lists in release-sync SKILL.md (line 80) and AgDR-0052 (line 36). Refs me2resh#403 --------- Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com> * chore(me2resh#408): CHANGELOG v2.1.0 + site version pill bump - Append [2.1.0] section above [2.0.2] - Bump site/index.html version pill v2.0.2 → v2.1.0 - Last cherry-pick release; /release-sync now live for v2.2.x+ Refs me2resh#408 --------- Co-authored-by: me2resh <ahmed.abdelaliem@gmail.com> Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
v2.1.0 — 2026-05-24
MINOR release. Adds the
/release-syncskill — automates main→dev sync after each release-PR merge so the squash-merge divergence stops compounding. Bundled with a small/pdfconvert.shbug fix. This is the last cherry-pick release; from v2.2.x onwards/release-syncenables the canonical dev → main release flow.This PR will tag
v2.1.0onmainafter merge.Added
feat(#403)/release-syncskill — runs as Step 9 of/release. Creates a sync branch fromupstream/dev, mergesupstream/mainwith--no-ff -X ours(dev wins on conflicts because dev already has the un-squashed equivalents), opens a sync PR. Stops at PR creation; normal Rex + CEO merge gate applies. Framework-only (refuses on managed projects). Defensive cases handled: already-in-sync (no-op exit 0), going-backwards (refuse exit 1). 11 unit tests + AgDR-0052 documents design trade-offs (explicit-skill vs auto-invoke,-X oursvs-X theirs).Fixed
fix(#404)/pdfconvert.shfallback path — removed stale--pdf-output-folderand--dest-nameflags from the md-to-pdf dispatch branch (md-to-pdf removed both flags in a breaking API change). New strategy: stage source into a temp dir under the desired output stem, runnpx md-to-pdf, move the result to the requested destination. Pandoc preferred-path unchanged; graceful-degrade (exit 3) on no converter preserved. New regression test (test_md_to_pdf_fallback.sh) catches future upstream API drift.Compatibility
No breaking changes. Adopters using
/pdfon systems without pandoc see the fallback path work again. Adopters using/releaseget a new optional Step 9; existing release flow unchanged unless/release-syncis invoked.Release strategy
Branched
release/v2.1.0fromupstream/main. Cherry-picked the 2 squashed commits from dev in order:6a6f3b0—fix(#404)(clean, no conflicts — only touches.claude/skills/pdf/)e3e742c—feat(#403)(auto-merge in 3 site files, no manual resolution needed)Then the CHANGELOG + version-pill bump as a third commit. The cherry-pick path is being used for the third release in a row because dev still carries the v1.4→v2.0 squash divergence (124 commits). After this release,
/release-syncis live on main, so v2.2.x and beyond can:/release-sync v2.1.0once to back-fill the v2.1.0 squash into devA separate task should kick off the historical sync for v1.2.0, v1.3.0, v2.0.0 squashes that never made it back to dev (the
/release-syncskill handles N=1 at a time; can be looped).Skip markers
<!-- private-refs: allow -->—yard.apexscript.com(framework's marketing domain) recurring false-positive onapexscripttoken. Same exception used by every v2.x.x release PR.<!-- multi-close: approved -->— defensive habit for release PRs. SingleClosesline here ([Chore] Cut v2.1.0 release #408); [Bug] release workflow — dev/main squash divergence compounds; needs main→dev sync after each release #403 + [Bug] /pdf convert.sh passes stale --pdf-output-folder flag to md-to-pdf; fallback path broken #404 already auto-closed on PR fix(#404): remove stale --pdf-output-folder flag from md-to-pdf dispatch #405 + feat(#403): /release-sync — main→dev sync after each release #406 merges to dev.<!-- agdr: not-applicable -->— release PRs are pure version-cuts. Underlying feature ([Bug] release workflow — dev/main squash divergence compounds; needs main→dev sync after each release #403) shipped with AgDR-0052 in its own PR.Testing
bash .claude/hooks/tests/test_site_counts.sh— PASS (55 skills now actual; site copy updated to match via the feat(#403): /release-sync — main→dev sync after each release #406 cherry-pick)git log upstream/main..HEADshows exactly 3 commits (2 cherry-picks + CHANGELOG/version bump)find .claude/skills -maxdepth 1 -type d | wc -lreturns 55 (was 54 on v2.0.2; +1 for/release-sync)## [2.1.0]section structured parallel to## [2.0.2]directly belowv2.0.2→v2.1.0v2.1.0tag pushed toupstream/mainGlossary
feat:commits — new functionality, no breaking changes.upstream/main, pick specific dev commits, PR back to main. Used here because dev carries 124 commits of v1.4→v2.0 squash divergence that would conflict on a normal release. v2.1.0 is the LAST cherry-pick release —/release-syncships in this PR./release-sync/release). Branches fromupstream/dev, mergesupstream/mainwith--no-ff -X ours, opens a sync PR. Makes the release squash commit an ancestor of dev so future dev→main releases don't re-conflict.-X oursvs-X theirsmerge. Since/release-syncbranches from dev and merges in main, "ours" = dev = correct winner (dev has the unsquashed equivalents). AgDR-0052 details the semantic./release-syncskill prevents future accumulation.Closes #408