Skip to content

Scheduler: redesign the installed-labels ledger around artifact OWNERSHIP, not bookkeeping #352

Description

@kengio

Reverted from v3.4.21 before shipping. The v3.4.21 cold recovery review found the ledger could silently delete live scheduled jobs; the approach needs a different foundation, not patches.

Why the bookkeeping approach failed

The ledger recorded which labels a vault installed, and removed any that disappeared from the config. Two problems are structural, not bugs:

  1. Labels are global; the ledger is per-vault. label_for_entry takes no vault input — it is a pure function of command basename + args (or skill name). Two vaults with the same entry produce the same label and the same artifact path. Vault A's routine register therefore deleted vault B's live job, printing "no longer in onebrain.yml" — true of A, false of B. Nothing in vault B ever mentioned it.
  2. The guard test was vacuous. sweep_never_touches_an_artifact_this_vault_did_not_install planted a label the ledger never contained, and the sweep only iterates the ledger — so it could not fail regardless of the bug.

Also found, and worth carrying into any redesign:

  • deleting the whole schedule: block early-returns before the sweep, so the most common form of "entry deleted" left every job installed
  • --remove --dry-run deletes for real (remove is handled before dry_run is consulted, and the flags have no conflicts_with)
  • run_embedded hardcodes quiet = true, so onebrain plugin update could delete artifacts and print nothing
  • the ledger was unvalidated: any line reaching it was passed to backend::remove, so one line written into a vault file could delete any com.onebrain.* job on the machine
  • it lived inside the vault, hence synced across machines — per-machine state in a multi-machine document, which is exactly why Scheduler logs live in the iCloud-synced vault, so launchd can't open them and every job dies silently #315 moved scheduler logs out

Direction

Decide ownership, then delete. Before removing anything, confirm the installed artifact actually belongs to this vault — its program args / working directory already carry the vault path. That subsumes the ledger's job and fixes the cross-vault case, because it stops trusting a name and starts checking the artifact.

Store any state that remains outside the vault (alongside the scheduler logs, per #315), keyed per machine.

The bug this was meant to fix is still open

Editing a schedule entry's args leaves the old artifact installed and firing, unreachable by --remove. Verified present in shipped v3.4.20 by building the tag and reproducing it, so this is long-standing, not a regression. v3.4.21 ships the label-collision fix (#345) without the sweep.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions