docs: version bumps move out of feature PRs into dedicated release PRs - #648
Merged
Conversation
…ted release PRs Parallel feature PRs (one AI session per issue) each bumping pyproject.toml collide on every merge and silently renumber releases -- the KNOWN_UNRELEASED list in scripts/generate_changelog.py is the accumulated damage of that pattern. Version bumps and changelog.py entries now happen ONLY in a dedicated release PR that batches everything merged since the last release. - CLAUDE.md Versioning: new 'Version bumps happen ONLY in a dedicated release PR' subsection with the two-step flow and the vNEXT placeholder convention for version-gated docs in feature PRs (version-gate-check rejects guessed numeric versions in per-PR CI, so the placeholder is the only workable tag before the release assigns a number). - CONTRIBUTING.md: new 'No version bumps in feature PRs' commit convention; per-command gotchas checklist and sync map updated for vNEXT; 'Releasing a new version' rewritten around the release PR -- new step 1 (collect merged PRs since the last tag as the exact scope of the changelog and release notes) and step 4 (replace every vNEXT, grep must come back empty); beta releases documented as the one deliberate exception where the bump rides the feature branch.
…has.md Both '(Release step: once this ships, tag this sentence (since vX.Y.Z)...)' parentheticals in the storage-descriptions gotcha referred to behavior that has since merged: the table-detail human-mode Description column (#642) and the describe-batch --from-file shape rejection (#645). Neither commit is contained in the v0.88.0 tag and main is bumped to 0.89.0, so both are tagged (since v0.89.0) -- a version version-gate-check resolves via its existing changelog entry. This is a live instance of the leftover-placeholder failure mode this PR's release checklist step 4 now guards against.
padak
added a commit
that referenced
this pull request
Aug 23, 2026
…XT gates Rebased onto main, which added four more merged PRs to the release scope. Changelog (0.89.0): * Fix (#649): sync diff/push scoped to a single branch tree; cross-tree manifest entries are reported under the new `orphaned` bucket instead of being planned as creates (a production diff after a dev-branch pull was one push away from duplicating the whole project). * Fix (#644): `config new --push --output-dir` stamps the created config's ID into the scaffold and writes it into the branch it was actually created in, so the next `sync push` adopts it instead of POSTing a duplicate. * Fix (#650): the `keboola.flow` scaffold gains the `_keboola` footer and the push-compatible `version: 2` / `_configuration_extra` shape. * Internal (#648): version bumps and changelog entries now happen only in a dedicated release PR; feature PRs tag version-gated docs with `vNEXT`. vNEXT placeholders: 17 usages rewritten to the released version across CLAUDE.md, keboola-expert.md, gotchas.md, commands-reference.md, branch-workflow.md, scaffold-workflow.md, sync-workflow.md and AGENT_CONTEXT (context.py). The only surviving `vNEXT` mentions are the three CLAUDE.md lines that document the convention itself. Rebase conflict: gotchas.md storage-descriptions bullet -- both sides kept (main's reflow plus the release commit's added pre-0.89.0 sentence). keboola-expert.md is 50 113 B, inside the 70 000 B budget. make check green (6009 passed, 12 skipped); version-gate-check resolves all 450 markers across 72 versions.
padak
added a commit
that referenced
this pull request
Aug 23, 2026
…es (#651) Release prep for 0.89.0: adds the changelog entries for everything merged since v0.88.0 (#620, #642, #643, #644, #645, #646, #647, #648, #649, #650, #517, #586, #641), resolves every vNEXT placeholder left by feature PRs to v0.89.0 per the new #648 release process, closes the 10 gaps a full doc-surface audit found across the kbagent plugin (SKILL.md triggers, commands-reference, gotchas, workflow files, keboola-expert.md, AGENT_CONTEXT, CLAUDE.md), and records the live e2e verification evidence. Version files were already at 0.89.0 (bumped by #643); make version-sync is a no-op.
claude Bot
pushed a commit
that referenced
this pull request
Aug 23, 2026
Resolves the sync-map conflict in CONTRIBUTING.md. main moved from 0.86.0 to 0.89.0 while this branch sat, and two adjacent table rows collided: - `keboola-expert.md` row: keep main's "70 000 B prompt budget". v0.88.0 raised the ceiling from 62 000 B, and tests/test_agent_prompt.py (test_documented_budget_matches_enforced_budget, added in #586) now gates CONTRIBUTING.md against PROMPT_BYTE_BUDGET, so this branch's stale "60 KB" would fail CI. - `commands/*.md` row: keep this branch's widened row plus its follow-through list for adding a new slash-command file. No version or changelog change: main's #648 moved version bumps into dedicated release PRs, and this branch bumps nothing.
This was referenced Aug 23, 2026
padak
added a commit
that referenced
this pull request
Aug 23, 2026
* fix(ci): stop the live vNEXT gate turning main and every PR red `TestLiveRepositoryVnext::test_no_unresolved_placeholder_survives_a_release` asserted that the live tree carries no `(since vNEXT)` placeholder. That is not an invariant of this repo -- it is the opposite of the documented process. Since #648, a feature PR that documents version-gated behaviour writes the literal `vNEXT` placeholder and only the release PR rewrites it. CLAUDE.md says so directly ("Writing `vNEXT` in a feature PR is correct and stays green"), and TestReleaseModeSelection, added by the same PR as this assertion, explains that arming the gate outside a release PR "would demand a contributor delete a placeholder the process requires them to write". So main legitimately carries placeholders for most of a release cycle. The assertion was green only because #670 landed days after 0.90.0 had just rewritten every one of them. #675 added the first placeholder of the next cycle and the assertion went red -- on main, and on every open PR, since a PR run tests the merge commit. The release-time requirement itself is real and stays enforced where it can see the base branch's version: the "Unresolved vNEXT placeholder check" step in ci.yml (`--release-if-newer-than`) and its local twin `make vnext-check`. A unit test cannot see that version, so it cannot make this call. What a test CAN assert is that the live scan works, and that replaces it: every gate the scanner reports must point at a real line that really contains the placeholder. Zero hits and ten hits are both valid answers depending on where in the cycle the tree sits. The neighbouring "guards the guard" test already covers the globs resolving at all. * fix(test): anchor the live vNEXT scan on REPO_ROOT, not the cwd `VnextResidue.path` is repo-root-relative -- find_vnext_residue stores `path.relative_to(REPO_ROOT).as_posix()` -- so reading it back as a bare `Path(gate.path)` resolves against the current working directory. The loop body only executes when the tree actually carries a placeholder, which is precisely the state main is in now, so running pytest from anywhere but the repo root raised FileNotFoundError. Reproduced from tests/ before the change and confirmed green after, from both the repo root and a subdirectory. `REPO_ROOT / gate.path` also covers the one fallback branch, where a path outside the repo is stored absolute: joining an absolute right-hand side discards the left, yielding that path unchanged. Raised by Devin review on #678.
claude Bot
pushed a commit
that referenced
this pull request
Aug 24, 2026
…che dirs Review found a real bug in the claude_plugin check, not just a gap in the tests. `_check_claude_plugin` probed the two cache dirs in order and broke out of the loop at the first one holding any version dir, so `latest` was the max WITHIN that dir only. While ai-kit trails a cli release -- the exact state publishing through ai-kit creates -- a user with both installs and a newer copy under the legacy `keboola-agent-cli` dir was told the OLDER `keboola-claude-kit` version, got no migration note, and got a drift hint aimed at a copy they were not running. Reporting a stale version as current is worse than reporting nothing. The probe now collects every version dir under every marketplace dir that exists and picks the single newest, so version, path, marketplace name, drift hint and migration note all describe the same copy: - a newest-copy-under-the-shim install gets the migration note it was missing; - the drift hint names the marketplace of the reported copy (`/plugin update kbagent@<marketplace>`), unambiguous when both are installed; - the message and a new `plugin_marketplace` result key name where the copy came from; - ties (same version cached under both) resolve to the current marketplace -- same code, nothing to migrate off. Ordering is PEP 440 via `packaging.version`, the idiom version_service already uses, rather than dir-name string compare: a string sort puts "0.100.0" below "0.90.0" and would report a stale copy as newest once the minor rolls past 99, which this repo is ten releases from. Unparseable dir names sort below every real version but stay eligible, so a hand-made dir never hides an install. Single-cache-dir behaviour is unchanged; all 11 pre-existing tests pass as-is. Also adds the sync job's missing automated test. `ai-kit-marketplace` is the only job here that writes to another repo, and its entry shape is owned by ai-kit, so the failure worth pinning is a shape change on the far side. tests/test_release_kbagent_ai_kit_sync.py extracts the step's real `run:` block from the workflow and executes it with bash against a throwaway git repo -- same "load the real artifact by path, then exercise it" approach as test_sync_version_script.py -- covering the at-target no-op (byte-identical file, changed=false), a genuine bump rewriting both `version` and `source.ref` while leaving the git-subdir coordinates and sibling plugins alone, either field stale alone still counting as a bump, a missing `source.ref` getting added, a missing `kbagent` entry failing loudly, and a `source` that is a plain string (the shape this repo's own deprecated marketplace.json still uses) aborting with the file untouched instead of publishing an unpinned version. No version bump and no changelog entry, per #648. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01RiYtKRNF8XDx3dDZAAeBGV
This was referenced Aug 25, 2026
padak
added a commit
that referenced
this pull request
Aug 25, 2026
…criptions (#695) Closes #690. Adds the write path to the kbagent notification group (client POST/DELETE, service create/delete/replace-recipient, CLI commands with write/destructive permission gating, serve routes, docs across all agent surfaces tagged (since vNEXT)). replace-recipient is create-new-first-then-delete-old so a failed second step leaves a recoverable duplicate, never a lost alert. No version bump (feature PR per #648 process).
padak
added a commit
that referenced
this pull request
Aug 25, 2026
…operations (#693) Closes #688. `permissions set --allow/--deny` now validates every pattern before the interactive confirmation: valid = a cli:* category (cli:read, cli:write, cli:destructive, cli:admin), an exact known operation (OPERATION_REGISTRY plus FLAG_ESCALATIONS strings), or a glob matching at least one of those. Anything else fails fast with VALIDATION_ERROR, exit 2, listing every offending pattern in error.details.invalid_patterns. find_inert_patterns is generalized: permissions show and kbagent doctor now flag ANY persisted pattern matching zero operations (typos included), not only the retired tool: namespace; the MCP-migration hint appears only when a tool:-prefixed pattern is present. doctor --json's details.inert_since is now conditional on a tool: pattern being present. Runtime evaluation is unchanged -- PermissionEngine stays lenient with pre-existing dead patterns. Docs drift surfaces updated with (since vNEXT) tags; no version bump (feature PR per #648 process). Includes a validator/engine parity test guarding against reintroducing this bug class.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Feature PRs are routinely developed in parallel (one AI session per GitHub issue). Today each of them bumps
pyproject.tomland adds achangelog.pyentry, so every merge is a version conflict, and merging all of them renumbers releases after the fact. TheKNOWN_UNRELEASEDlist inscripts/generate_changelog.py-- 18 versions whose content shipped with no release notes -- is the accumulated damage of exactly that pattern.What changes (docs/process only, no code)
Feature PRs no longer bump the version or touch
changelog.py. A release becomes a dedicated release PR that batches everything merged since the last release: one bump, one changelog entry covering every merged PR (that entry is whatscripts/gen_release_notes.pyrenders into the GitHub release notes), one tag.vNEXTplaceholders, grep must come back empty);The
vNEXTplaceholderA feature PR cannot tag version-gated docs (
gotchas.mdetc.) with a numeric future version:make version-gate-checkruns in per-PR CI and rejects any(since vX.Y.Z)whose version has nochangelog.pyentry. Feature PRs therefore tag with the literal placeholder(since vNEXT)(invisible to the gate's numeric-only regex); the release PR rewrites everyvNEXTto the released version, with an explicit must-be-empty grep step in the checklist.Verified
make version-gate-check-- all 423 gates still resolve (no numeric gates added by this PR)make command-sync-check-- green (the## All CLI Commandssection is untouched)Bonus: the failure mode, caught live
Second commit resolves two stale
(Release step: once this ships, tag this sentence (since vX.Y.Z)...)placeholders ingotchas.md-- exactly the leftover-placeholder failure this PR's release checklist step 4 guards against. Both referred to behavior merged after the v0.88.0 tag (table-detail human Description column #642, describe-batch shape rejection #645), so both are tagged(since v0.89.0)(main is already bumped to 0.89.0 and the changelog key exists, somake version-gate-checkresolves them -- 425 gates green). If the 0.89.0 release ever gets renumbered, these two tags renumber with it.