Skip to content

docs(plugin): retire version gates below the 0.80.0 floor - #705

Closed
padak wants to merge 2 commits into
mainfrom
claude/release-process-gates
Closed

docs(plugin): retire version gates below the 0.80.0 floor#705
padak wants to merge 2 commits into
mainfrom
claude/release-process-gates

Conversation

@padak

@padak padak commented Aug 26, 2026

Copy link
Copy Markdown
Member

Retires the stale version gates you asked about, at the 0.80.0 floor, safety gates kept.

557 → 334 gates. 223 tags removed across 18 files. Not one word of content deleted.

Why

A gate earns its place only while some live install predates it. I checked auto_update.py rather than assuming: maybe_auto_update() self-upgrades pip/uv installs on startup, so the population an old gate protects rounds to nothing — only a standalone binary (self-update is disabled for brew/choco/apt/dnf), an explicit KBAGENT_AUTO_UPDATE=false, a dev tree, or a pip install stranded below 0.62.0 by the #424 rename can sit on an old version.

Meanwhile the stale gate keeps doing damage, because keboola-expert.md Rule 6 turns every tag into a refusal: the agent declines a command the user actually has. CONTRIBUTING already calls that strictly worse than no gate.

The two failure modes are asymmetric, and that asymmetry is the whole argument:

Failure Visibility
Gate kept too long agent refuses a command the user has silent, permanent — the user never learns it exists
Gate removed too early agent suggests a command the user lacks loud, self-correctingNo such command 'x', and kbagent context / --help on the real install are authoritative

Tag goes, content stays

This is de-tagging, not deletion. Nearly every old entry is still true — only the qualifier is obsolete:

-## `config detail` has a bulk mode (since 0.23.0)
+## `config detail` has a bulk mode

The body ("omit --config-id for every config under a component…") is current, useful, and untouched.

Safety gates kept, at any age

The rule applied: keep the tag wherever not knowing the version causes silent data loss or a false assurance rather than an error message. Six qualify, all verified by reading the section rather than the title:

Gate Why it stays
sync pull --force (0.53.0) pre-0.53.0 it silently corrupted the sync baseline — local edits stranded with no signal
plaintext #-secret audit (0.55.0) an agent on 0.54.0 reports "no plaintext secrets" having checked nothing — a false all-clear on a leaked credential
manage-token default-deny (0.29.0) below 0.29.0 the env var is read; assuming otherwise is a token-exposure bug
--deny-writes / --deny-destructive (0.22.0) agent would trust a firewall that isn't there
dev-portal writes require a human (0.49.0) human-in-the-loop guarantee
sync trust cluster / --theirs (0.72.0) destructive reconcile

Also out of scope, deliberately

  • changelog.py (33 gates) — the historical record; the version is the content.
  • src/**/*.py except commands/context.py (13) — # DEPRECATED (since 0.43.4), UNAUTHORIZED = "…" # (0.40.0+). Developer provenance; no agent reads these files.
  • X+ inside a sentence (59) — frequently load-bearing prose. created by < 0.66.1 stay dormant until re-run on 0.66.1+ is a migration instruction; stripping the version destroys it. With 0.25.0+: would become With :.
  • kbagent-pr-reviewer.md (3) — prose about the gate mechanism, using 0.22.0+ as an example.

How, and what review caught

The de-tagger is conservative by construction: anything whose rewrite looks suspicious is skipped and reported rather than guessed at. The first attempt had two real bugs, both caught by reading the diff:

  1. The regex consumed emphasis markers, turning **Partial-state envelope**: into **Partial-state envelope*:. Fixed by not matching * around the parenthetical.
  2. A tag at the head of a continuation line left . On projects with **branched storage**… — a line starting with a period. The rewritten script now detects and skips that shape; both instances were then fixed by hand (the bold sentence absorbs the full stop).

New tooling

make gate-floor-report (--list-below VERSION) gives the next floor bump a worklist instead of a hand-rolled grep — the same class of hand-run command that lost the merge race in #702. Four tests.

The policy is documented as release checklist step 4b, including the exclusions and the safety-gate rule, so this stays a decision rather than folklore.

Checks

make check: 6360 passed, 12 skipped. check_command_sync.py OK (267 commands) — worth noting since commands-reference.md took 86 changed lines. keboola-expert.md is well inside its 70 000 B budget.


Open in Devin Review

padak added 2 commits August 25, 2026 23:03
…gate release scope

Three release-process gaps, all found by running the v0.91.0 release. Each was
a rule that existed only as prose plus a hand-run command, and each failed the
same way: a release is exactly when parallel branches converge, so any step of
the form 'run this grep when releasing' eventually loses a merge race.

1. make vnext-resolve VERSION=X.Y.Z
   Checklist step 4 resolved 54 placeholders by hand off the checker's own
   output. The scanner already separates a live gate from prose with perfect
   precision, so --resolve reuses it and rewrites only outside inline-code
   spans -- including on a line carrying both a quoted mention and a live gate,
   which a line-level sed corrupts. Refuses a VERSION disagreeing with
   pyproject.toml, because packaging parses 'v0.91' and '0.91' happily.

2. vNEXT in a markdown heading is now fatal on EVERY PR
   Resolving a placeholder in a heading rewrites its anchor slug and breaks
   inbound links. The rule was a release-time grep; in 0.91.0 it lost a race
   (#697 ran two minutes before #694 and #696 landed headings of their own) and
   three shipped. Checking at authoring time makes the race impossible.
   Numeric headings are deliberately not flagged -- a resolved tag never
   changes again, so its slug is stable.

3. make release-scope-check
   Proves the changelog entry covers every PR the tag will CONTAIN, not the
   scope collected when the release PR was opened. In 0.91.0, #625 merged nine
   minutes before the release PR and landed inside the tag with no release
   note; changelog-check cannot see this, since it proves every released
   version has an entry, never that an entry covers every commit under the tag.
   Armed in CI exactly like the vNEXT gate (version-raising PRs only), with the
   checkout deepened only then and a fail-open path so an ordinary PR can never
   go red on it.

39 new tests. CONTRIBUTING's release checklist grows to 18 steps.
A version gate earns its place only while some live install predates it.
kbagent self-updates on startup, so that population rounds to nothing --
only a standalone binary (self-update disabled), an explicit
KBAGENT_AUTO_UPDATE=false, a dev tree, or a pip install stranded below
0.62.0 by the #424 rename can sit on an old version. Meanwhile the stale
gate keeps making the agent refuse a command the user actually has, which
CONTRIBUTING already calls strictly worse than no gate.

Removes 223 tags across 18 agent-facing files (557 -> 334 gates). The tag
goes, the content stays -- the guidance under these entries is still true,
so not a word of it was deleted.

Out of scope, deliberately:
- changelog.py: the historical record; the version IS the content.
- src/**/*.py except commands/context.py: developer comments are
  provenance and no agent reads them.
- 'X+' inside a sentence: often load-bearing prose ('created by < 0.66.1
  stay dormant until re-run on 0.66.1+').
- Safety gates at any age: sync pull --force (pre-0.53.0 it silently
  stranded local edits), the plaintext-secret audit (a false all-clear on
  a leaked credential), manage-token default-deny, the --deny-writes
  firewall, the dev-portal human-in-the-loop rule, and the sync trust
  cluster.

Adds 'make gate-floor-report' (--list-below) so the next floor bump has a
worklist instead of a hand-rolled grep, and documents the policy as
release checklist step 4b.

@devin-ai-integration devin-ai-integration Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Devin Review: No Issues Found

Devin Review analyzed this PR and found no bugs or issues to report.

Open in Devin Review

@padak

padak commented Aug 26, 2026

Copy link
Copy Markdown
Member Author

Superseded — reopening from a clean branch. This branch name already carried the merged #702, and GitHub never fired CI for the new commit on it.

@padak padak closed this Aug 26, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant