feat(core): pre/post backup shell hooks - #16
Merged
Merged
Conversation
Run optional user-configured shell commands around each backup cycle (V2 pre/post backup hooks, DESIGN s17). Core: a new I/O-free `CommandRunner` seam (`hooks` module) with an inert `NoopCommandRunner` default and a `with_command_runner` builder (mirrors `with_vss`, so none of the existing constructors churn). The orchestrator runs the pre-hook before the per-cycle source loop - a non-zero / timed out / unspawnable pre-hook ABORTS that cycle's backup - and the post-hook after the loop with `DRIVEN_RESULT` = ok/error. Each run is recorded as a `hook.<kind>` activity row. Hook commands + a kill timeout live in `OrchestratorConfig`. Pre/post success/abort and env passing are tested with a fake runner. App: a real `TokioCommandRunner` (sh -c / cmd /C, env, kill-on-timeout) wired in `assembly`, with unix tests for exit code / env / timeout. Settings: threaded through the SPEC s22 `global` group (DTO, patch with null-clears semantics, snake_case storage with serde(default), default, and `load_orchestrator_config`). UI: a "Backup hooks" Settings section (before/after command + timeout), wired through the store with TS types, i18n, and a component test. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WvXMHHbYGddVPpmQR2XmK1
Contributor
Coverage
Gate: passed - no coverage regression (epsilon 0.1 pp). |
pmaxhogan
added a commit
that referenced
this pull request
Jun 26, 2026
… V2+" list (C4) DESIGN s17 still listed schedule windows, pre/post shell hooks, and metered-network throttle as deferred, and the schedule-windows entry asserted "V1 does NOT ship this" - all three shipped in 0.2.0 (#12/#16/#17), plus CLI local-state inspection (#13). Annotate each "(SHIPPED 0.2.0)" + add a header note; keep the historical design text. Also note metered detection is Windows-only (conservative default on macOS/Linux). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012CyiRqk2DVwmJjEu5gcD1m
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.
What
Implements pre/post backup shell hooks from the V2 backlog (DESIGN s17): optional user-configured shell commands that run around each backup cycle.
DRIVEN_RESULT=ok|error.hook.<kind>activity row (Info on success, Warn on failure).DRIVEN_HOOK(pre/post),DRIVEN_ACCOUNT_ID, andDRIVEN_RESULT(post only).Design
driven-corestays I/O-free: it runs hooks through a new injectedCommandRunnerseam. The orchestrator defaults to an inertNoopCommandRunnerand gains awith_command_runnerbuilder (mirrorswith_vss), so none of the existing constructors churn — only the app opts into the real runner. The realTokioCommandRunner(insrc-tauri) spawns through the platform shell (sh -c/cmd /C) with the env vars and a hard kill-on-timeout.Hook commands + the kill timeout live in
OrchestratorConfig, threaded through the SPEC s22globalsettings group.Changes
hooksmodule (CommandRunner,HookOutcome,NoopCommandRunner);OrchestratorConfighook fields; orchestrator pre/post invocation +run_backup_hookhelper recording activity.TokioCommandRunnerwired inassembly.serde(default)) + default +load_orchestrator_config.Tests / gates (all green locally)
driven-core: 223 tests incl. hook-outcome unit tests + orchestrator pre-abort / post-runs / env-passing tests (fake runner). clippy clean.driven-app: 212 tests incl.TokioCommandRunnerunix tests (exit code / env / timeout-kill). clippy clean.Behaviour note
Hooks run once per backup cycle (every non-gated scan tick when sources exist), not only when files changed — documented on the config fields. A natural refinement is "only when work happened"; deferred to keep this focused.
🤖 Generated with Claude Code
Generated by Claude Code