Skip to content

feat(core): pre/post backup shell hooks - #16

Merged
pmaxhogan merged 1 commit into
mainfrom
claude/feat-backup-hooks
Jun 25, 2026
Merged

pmaxhogan merged 1 commit into
mainfrom
claude/feat-backup-hooks

Conversation

@pmaxhogan

Copy link
Copy Markdown
Owner

What

Implements pre/post backup shell hooks from the V2 backlog (DESIGN s17): optional user-configured shell commands that run around each backup cycle.

  • Pre-hook runs before the cycle touches any source. A non-zero / timed-out / unspawnable pre-hook aborts that cycle's backup (no scan, no upload); the next cycle retries.
  • Post-hook runs after the cycle's source loop, regardless of outcome, with DRIVEN_RESULT=ok|error.
  • Every run is recorded as a hook.<kind> activity row (Info on success, Warn on failure).
  • Env passed to hooks: DRIVEN_HOOK (pre/post), DRIVEN_ACCOUNT_ID, and DRIVEN_RESULT (post only).

Design

driven-core stays I/O-free: it runs hooks through a new injected CommandRunner seam. The orchestrator defaults to an inert NoopCommandRunner and gains a with_command_runner builder (mirrors with_vss), so none of the existing constructors churn — only the app opts into the real runner. The real TokioCommandRunner (in src-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 s22 global settings group.

Changes

  • core: hooks module (CommandRunner, HookOutcome, NoopCommandRunner); OrchestratorConfig hook fields; orchestrator pre/post invocation + run_backup_hook helper recording activity.
  • app: TokioCommandRunner wired in assembly.
  • settings: DTO + patch (blank command clears the hook) + snake_case storage (serde(default)) + default + load_orchestrator_config.
  • UI: a "Backup hooks" Settings section (before/after command + timeout).

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. TokioCommandRunner unix tests (exit code / env / timeout-kill). clippy clean.
  • UI: build + 166 unit tests + lint + prettier; coverage up to 82.06%.

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

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
@github-actions

Copy link
Copy Markdown
Contributor

Coverage

Area main this PR delta
Rust (lib crates) 75.83% 76.01% +0.18 (OK)
UI (vue/ts) 81.92% 82.06% +0.14 (OK)

Gate: passed - no coverage regression (epsilon 0.1 pp).

@pmaxhogan
pmaxhogan merged commit 35df924 into main Jun 25, 2026
13 checks passed
@pmaxhogan
pmaxhogan deleted the claude/feat-backup-hooks branch June 25, 2026 18:38
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
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.

2 participants