Skip to content

tick: make the skills-disable opt-out survive ForceTick (pilotctl update / skills check) - #31

Merged
Alexgodoroja merged 1 commit into
mainfrom
fix/disabled-opt-out-sticky
Jul 17, 2026
Merged

Alexgodoroja merged 1 commit into
mainfrom
fix/disabled-opt-out-sticky

Conversation

@Alexgodoroja

Copy link
Copy Markdown
Collaborator

Make the skills disable opt-out survive ForceTick

pilotctl skills disable sets mode=disabled and removes the injected skill,
but ForceTick bypassed the disabled gate entirely — it carried a force flag
whose only effect was to skip the GetMode() == ModeDisabled check. ForceTick
is the entry point for pilotctl skills check, pilotctl update's post-update
reconcile, and the installer's first-pass, so any of those re-injected skills a
user had explicitly turned off.
The opt-out did not survive an update.

Fix

Gate on !dryRun instead of !force. disabled is now a hard opt-out for every
write path (Tick and ForceTick), while the read-only Plan() behind
pilotctl skills status still previews what a re-enable would do. The vestigial
force parameter is removed; ForceTick remains the immediate-reconcile entry
point (it's equivalent to Tick now — manual mode was never gated here, and
skills enable persists mode=auto before reconciling, so re-enable still runs).

Behavior

path before after
daemon periodic/startup tick, disabled no-op no-op
skills check / update / installer re-run, disabled re-injects no-op
skills enable all re-injects re-injects (mode set to auto first)
pilotctl skills status (Plan), disabled previews previews

Tests

  • Rewrote TestForceTick_SkipsDisabledGateTestForceTick_HonorsDisabledGate
    (it had pinned the bypass): a disabled config now short-circuits with no fetch
    and a Disabled report.
  • Added TestPlan_PreviewsEvenWhenDisabled — the gate is write-only, not a
    status blackout.
  • Full suite green.

End-to-end (container, patched pilotctl over a real install)

install → disable all (removed, mode:disabled) → skills check stays
removed
(released v1.12.8 re-injects here) → daemon restart stays removed →
enable all restores.

Downstream: needs a skillinject release + a core go.mod bump to ship in a
pilotprotocol patch (1.12.9).

`pilotctl skills disable` set mode=disabled, but ForceTick bypassed the gate
entirely (it took a `force` flag whose only effect was to skip the disabled
check). ForceTick backs `pilotctl skills check`, `pilotctl update`'s
post-update reconcile, and the installer's first-pass — so any of those
re-injected skills a user had explicitly turned off. The opt-out did not
survive an update.

Gate on !dryRun instead of !force: disabled is now a hard opt-out for every
write path, while the read-only Plan() (behind `pilotctl skills` status) still
previews. The vestigial `force` parameter is removed; ForceTick stays as the
immediate-reconcile entry point (enable persists mode=auto before calling in,
so re-enable still works). Rewrites the test that pinned the old bypass and
adds one for Plan previewing while disabled.
@codecov

codecov Bot commented Jul 17, 2026

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@Alexgodoroja
Alexgodoroja merged commit 902f745 into main Jul 17, 2026
5 checks passed
matthew-pilot pushed a commit to pilot-protocol/pilotprotocol that referenced this pull request Jul 19, 2026
Bumps skillinject to the commit merged in pilot-protocol/skillinject#31, so the
`pilotctl skills disable` opt-out survives `pilotctl update` / `skills check`
/ installer re-runs. skillinject is compiled into the daemon + pilotctl, so this
bump is what ships that fix in a pilotprotocol release.
Alexgodoroja added a commit to pilot-protocol/pilotprotocol that referenced this pull request Jul 20, 2026
…sable opt-out fix (#400)

* go.mod: pin skillinject with the disabled-opt-out fix

Bumps skillinject to the commit merged in pilot-protocol/skillinject#31, so the
`pilotctl skills disable` opt-out survives `pilotctl update` / `skills check`
/ installer re-runs. skillinject is compiled into the daemon + pilotctl, so this
bump is what ships that fix in a pilotprotocol release.

* updater: add APP_UPDATE_OPT_OUT to opt out of app auto-updates

The pilot-updater keeps installed apps current by periodically running
`pilotctl appstore upgrade --all`. Add APP_UPDATE_OPT_OUT=true as the documented
way to turn that off — installed apps then stay at the version the operator
installed, while the pilot daemon/CLI binaries keep updating. Unset or false
(the default) keeps app auto-updates on. Extracts the gate into a testable
appAutoUpgradeEnabled() helper following the existing envBool pattern, and keeps
PILOT_UPDATER_NO_APP_UPGRADE working as a back-compat alias. Documents the var
in the README env-var table and CHANGELOG [1.12.9].

* updater: rename opt-out var to PILOT_APP_UPDATE_OPT_OUT + drop version from changelog

Follow the repo's PILOT_-prefixed env-var convention: the app-update opt-out is
now PILOT_APP_UPDATE_OPT_OUT (global boolean, default false). PILOT_UPDATER_NO_APP_UPGRADE
stays as the back-compat alias. Moves the changelog entry under [Unreleased] so
the release version isn't pinned in the PR.

---------

Co-authored-by: Alexgodoroja <alex@vulturelabs.io>
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