v0.17 β v0.18: opt-in ForcedUpdate policy¶
What changed¶
The root command's background self-update check is now governed by a
three-state update policy (disabled / prompt / enabled) instead of
always prompting. The framework default is now disabled: a tool built on
GTB logs that an update is available and continues, rather than prompting on
every run. A new configurable update.check_interval replaces the hard-coded
24-hour throttle, and the latest version discovered by a check is remembered so
a persistent out-of-date WARN is shown on subsequent runs.
This implements docs/development/specs/2026-06-16-forced-update-feature.md and
remediates the keryx bug report (a background update could hijack an unrelated
command, and a failed update could exit 0).
Impact¶
- Downstream tools built on GTB: the default behaviour changes from "prompt to update" to "log only". If you relied on the old prompting/forcing, opt back in (below). No code change is required to keep building.
- The
gtbCLI itself now usesprompt(was effectively always-prompt), so its interactive UX is unchanged in practice. - A failed forced update now exits non-zero (previously it could exit 0). CI/scripts that swallowed that masked success may now correctly see a failure.
How to migrate¶
Keep the old prompting behaviour¶
Set the baseline on your Tool:
props.Tool{
// ...
UpdatePolicy: props.UpdatePolicyPrompt, // or props.UpdatePolicyEnabled to block
UpdateCheckInterval: 7 * 24 * time.Hour, // optional; zero value = framework default (24h)
}
β¦or let your users (or your shipped config) set it:
update:
policy: prompt # disabled | prompt | enabled
check_interval: 24h # any Go duration; 0 = check every invocation
Resolution precedence¶
Policy: --ci / ci: true (bypass entirely) β update.policy config β
tool baseline (props.Tool.UpdatePolicy, default disabled).
Check interval: a valid update.check_interval config value (where 0/0s
means "check every run") β tool baseline (props.Tool.UpdateCheckInterval, if
positive) β framework default (setup.DefaultCheckInterval, 24h). A zero-value
tool baseline is treated as "unset" and falls through to 24h β runtime config is
the only way to request the no-throttle "every run" behaviour.
Generating a tool with these baselines¶
gtb generate project exposes both baselines so a tool author can bake them in
at scaffold time (persisted to the manifest, preserved across gtb regenerate):
gtb generate project -n mytool -r myorg/mytool \
--update-policy prompt --update-check-interval 168h
Interactively, the Self-Update Policy and Update Check Interval wizard steps collect the same values. See generate.
Public API note (pre-1.0)¶
setup.SkipUpdateCheck gained a checkInterval time.Duration parameter;
setup.ResolveCheckInterval gained a leading toolDefault time.Duration
parameter (now ResolveCheckInterval(toolDefault, configValue)); props.Tool
gained UpdatePolicy and UpdateCheckInterval fields; and new
setup.SetCheckedVersion / setup.GetCheckedVersion plus props.UpdatePolicy /
props.ResolveUpdatePolicy are added. These ship as a v0.x minor per the
pre-1.0 policy.