1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
//! Path builders for the moadim jobs and handlers directory layout.
use OsString;
use PathBuf;
pub use *;
/// Environment variable that, when set, overrides the home directory all moadim paths resolve
/// under. Used by tests to redirect config/routines/jobs/agents/workbenches into a tempdir so they
/// never read or write the user's real `~/.config/moadim`.
const HOME_OVERRIDE_ENV: &str = "MOADIM_HOME_OVERRIDE";
/// Environment variable from the XDG Base Directory spec that relocates the user's config root.
const XDG_CONFIG_HOME_ENV: &str = "XDG_CONFIG_HOME";
/// Resolve the base home directory, honoring the [`HOME_OVERRIDE_ENV`] test seam when set.
///
/// Exposed to the crate so platform service installers resolve their home-relative paths (e.g. the
/// macOS `LaunchAgents` plist) through the same override seam, keeping tests off the real home.
pub
/// Resolve the config root the moadim config tree nests under, honoring the XDG Base Directory
/// spec.
///
/// When `$XDG_CONFIG_HOME` is set to an **absolute** path it is used verbatim; an unset, empty, or
/// relative value falls back to `$HOME/.config`. This mirrors the `dirs` crate that the Linux
/// systemd installer ([`crate::service`]) already uses for the unit path, so a user who relocates
/// their config root via `$XDG_CONFIG_HOME` gets a single coherent config tree instead of a
/// surprise second one under `~/.config`.
/// Resolve the config root from an explicit `$XDG_CONFIG_HOME` value and home directory.
///
/// Split out from [`config_root`] so the resolution rules are unit-testable without mutating
/// process-global environment variables. A relative `$XDG_CONFIG_HOME` is ignored, per the spec
/// ("All paths set in these environment variables must be absolute"). Falls back to `.` when the
/// home directory is undeterminable.
/// Returns the moadim config directory: `$XDG_CONFIG_HOME/moadim`, defaulting to `~/.config/moadim`.
// ─── Routines ────────────────────────────────────────────────────────────────
/// Returns the path to `{config_dir}/routines/` (default `~/.config/moadim/routines/`).
/// Returns the path to `{routines_dir}/{id}/`.
/// Returns the path to `{routines_dir}/README.md`, a daemon-generated orientation doc explaining
/// the per-routine directory layout.
/// Returns the path to `{routines_dir}/{id}/routine.toml`, the tracked routine metadata.
/// Returns the path to `{routines_dir}/{id}/schedule.cron`, the routine's tracked cron entry.
/// Returns the path to `{routines_dir}/{id}/schedule.compailed.cron`, the gitignored cron-union output.
///
/// `schedule.cron` stays the human-authored source; this derived file is rewritten by crontab
/// sync and ignored by git.
/// Returns the path to `{routines_dir}/{id}/prompts/`.
/// Returns the path to `{routines_dir}/{id}/prompts/prompt.pure.md`, the raw user-authored prompt.
/// Returns the path to `{routines_dir}/{id}/prompts/prompt.compiled.local.md`, the composed prompt
/// (repositories preamble + pure prompt) that the launch command copies into the workbench.
///
/// `.local.` keeps it matching the config `.gitignore`'s `*.local.*` pattern: it is fully derived
/// from `prompt.pure.md` + `routine.toml` and rewritten on every [`crate::routine_storage::write_routine`]
/// call, so (unlike `prompt.pure.md`) it should never be tracked (issue #1046).
/// Returns the path to `{routines_dir}/{id}/.gitignore`, the legacy per-routine gitignore an
/// older daemon generated. No longer written (the config dir's root `.gitignore` covers every
/// routine directory recursively); an existing file is left untouched, since it may carry
/// user-added patterns. Test-only: production code no longer touches this path.
/// Returns the path to `{routines_dir}/{id}/state.local.toml`, the gitignored sidecar holding
/// daemon-written runtime state (`snoozed_until`, `skip_runs`) kept out of the tracked `routine.toml`.
///
/// The `.local.` infix matches the `*.local.*` pattern seeded into the config `.gitignore`, so
/// snooze churn never produces version-control diffs.
/// Returns the path to `{routines_dir}/{id}/routine.local.toml`, the gitignored sidecar a human
/// (not the daemon) edits directly to layer secret or machine-local environment variable
/// overrides on top of `routine.toml`'s tracked `[env]` table — see
/// [`crate::routines::build_routine_command`] and issue #408.
///
/// The `.local.` infix matches the `*.local.*` pattern seeded into the config `.gitignore`, so it
/// is never accidentally committed.
include!;