diff options
| -rwxr-xr-x | scripts/cmail-setup-finish.sh | 44 | ||||
| -rwxr-xr-x | scripts/post-rebuild-check | 11 | ||||
| -rw-r--r-- | tests/post-rebuild-check/test_post_rebuild_check.py | 23 | ||||
| -rw-r--r-- | todo.org | 6 |
4 files changed, 58 insertions, 26 deletions
diff --git a/scripts/cmail-setup-finish.sh b/scripts/cmail-setup-finish.sh index 949023f..bd72499 100755 --- a/scripts/cmail-setup-finish.sh +++ b/scripts/cmail-setup-finish.sh @@ -1,28 +1,29 @@ #!/usr/bin/env bash # SPDX-License-Identifier: GPL-3.0-or-later -# cmail-setup-finish.sh — finish Proton Mail Bridge + cmail-action setup after -# Bridge first-run. Idempotent; safe to re-run after a Bridge cert rotation or -# a claude-templates re-clone. +# cmail-setup-finish.sh — finish Proton Mail Bridge setup after Bridge +# first-run. Idempotent; safe to re-run after a Bridge cert rotation. # # Pre-reqs (the script aborts if any are missing): # - protonmail-bridge installed (archsetup handles it) # - You have run 'protonmail-bridge --cli', logged in, and quit at least once # (the script looks for state at ~/.config/protonmail/bridge-v3/) -# - claude-templates cloned at ~/projects/claude-templates +# - cmail-action on PATH (rulesets' `make install` links it; session start +# runs that, so it arrives on its own) # - dotfiles stowed (~/.config/.cmailpass.gpg present) # # What it does: # 1. Decrypts ~/.config/.cmailpass.gpg → ~/.config/.cmailpass (mode 0600) # 2. Copies Bridge's self-signed cert → ~/.config/protonbridge.pem -# 3. Symlinks ~/projects/claude-templates/.ai/scripts/cmail-action.py -# → ~/.local/bin/cmail-action -# 4. Removes the leftover ~/.config/autostart/Proton Mail Bridge.desktop +# 3. Removes the leftover ~/.config/autostart/Proton Mail Bridge.desktop # stub (it double-launches Bridge alongside the systemd user service # and throws an "orphan instance" dialog every login) -# 5. Installs a wait-for-dns drop-in so Bridge doesn't spam +# 4. Installs a wait-for-dns drop-in so Bridge doesn't spam # name-resolution errors during the early-boot DNS race -# 6. Enables + starts the protonmail-bridge user service -# 7. Verifies Bridge is listening on 127.0.0.1:1143 / :1025 +# 5. Enables + starts the protonmail-bridge user service +# 6. Verifies Bridge is listening on 127.0.0.1:1143 / :1025 +# +# It no longer installs cmail-action. That moved to rulesets +# (claude-templates/bin/), whose `make install` owns the symlink. set -euo pipefail @@ -47,9 +48,12 @@ bridge_state="$HOME/.config/protonmail/bridge-v3" [ -d "$bridge_state" ] \ || err "Bridge has no state at $bridge_state — run 'protonmail-bridge --cli' and log in first" -cmail_action_src="$HOME/projects/claude-templates/.ai/scripts/cmail-action.py" -[ -f "$cmail_action_src" ] \ - || err "cmail-action.py not found at $cmail_action_src — clone claude-templates first" +# cmail-action is no longer this script's to install. It lives in rulesets at +# claude-templates/bin/, and rulesets' `make install` links everything there +# into ~/.local/bin — which every session start runs, so the symlink reaches +# each machine on its own. Check that it arrived rather than placing it. +command -v cmail-action >/dev/null 2>&1 \ + || err "cmail-action not on PATH — run 'make -C ~/code/rulesets install'" cmailpass_enc="$HOME/.config/.cmailpass.gpg" [ -f "$cmailpass_enc" ] \ @@ -69,13 +73,7 @@ cert_dst="$HOME/.config/protonbridge.pem" cp "$cert_src" "$cert_dst" ok "copied $cert_src → $cert_dst" -# 4. Symlink cmail-action -info "symlinking cmail-action" -mkdir -p "$HOME/.local/bin" -ln -sf "$cmail_action_src" "$HOME/.local/bin/cmail-action" -ok "linked $HOME/.local/bin/cmail-action → $cmail_action_src" - -# 5. Remove leftover XDG autostart stub +# 4. Remove leftover XDG autostart stub # The systemd --user service is the canonical launcher. The autostart .desktop # starts a second Bridge instance that can't get the lock and pops up an # "orphan instance" dialog every login. @@ -88,7 +86,7 @@ else ok "no autostart stub present" fi -# 6. Install wait-for-dns drop-in +# 5. Install wait-for-dns drop-in # User-instance systemd doesn't carry network-online.target / nss-lookup.target, # so the packaged unit's After=network.target doesn't imply DNS readiness. # Bridge starts before the resolver is up and its first API calls all fail @@ -107,7 +105,7 @@ ok "wrote $dropin_file" systemctl --user daemon-reload ok "reloaded systemd user units" -# 7. Enable + start systemd user service +# 6. Enable + start systemd user service info "enabling protonmail-bridge user service" was_active=0 systemctl --user is-active --quiet protonmail-bridge.service && was_active=1 @@ -119,7 +117,7 @@ else ok "service active" fi -# 8. Verify +# 7. Verify info "verifying Bridge is listening" listening="$(ss -ltn 2>/dev/null || true)" missing="" diff --git a/scripts/post-rebuild-check b/scripts/post-rebuild-check index ee77a19..aa7ef83 100755 --- a/scripts/post-rebuild-check +++ b/scripts/post-rebuild-check @@ -428,6 +428,16 @@ printf '%s\n' "$projects" > "$WORK/projects" 2>/dev/null || { # steady state rather than reinstall drift, and flagging it would put nine # standing findings in front of every real one. # +# .claude/ is absent for the same reason and proven the same way. The +# bootstrap and the gitignore sweep write it into the ignore set of every +# gitignore-mode project whether or not one ever exists there, so the entry is +# aspirational rather than a promise -- pearl, rsyncshot and yt-sync each name +# it and none of the three has ever had one, on velox or on ratio. Dropping it +# loses no real signal either: a project that genuinely carries a .claude/ +# (rules and hooks from a language bundle) has it re-synced by +# sync-language-bundle.sh at every session start, so a true absence heals +# itself before this check would run. +# # The list is fed to the inner loop straight from a heredoc rather than # staged through a file. It is a constant, so a file bought nothing and cost # a fifth unguarded write: had it failed (a full tmpfs, say) the inner loop @@ -458,7 +468,6 @@ while IFS= read -r proj; do esac done <<'EOF' .ai \.ai -.claude \.claude todo.org todo\.org inbox inbox EOF diff --git a/tests/post-rebuild-check/test_post_rebuild_check.py b/tests/post-rebuild-check/test_post_rebuild_check.py index a034f87..bc887c6 100644 --- a/tests/post-rebuild-check/test_post_rebuild_check.py +++ b/tests/post-rebuild-check/test_post_rebuild_check.py @@ -765,12 +765,31 @@ class ProjectTooling(unittest.TestCase): def test_ignored_but_absent_tooling_flags(self): with tempfile.TemporaryDirectory() as root: - self.project(root, [".ai/", ".claude/", "todo.org"]) + self.project(root, [".ai/", "todo.org"]) r = run_check(project_roots=root) self.assertEqual(r.returncode, 1) - for missing in (".ai", ".claude", "todo.org"): + for missing in (".ai", "todo.org"): self.assertIn(missing, r.stdout) + def test_claude_dir_absence_never_flags(self): + # Same shape as CLAUDE.md below, and proven the same way. The bootstrap + # and the gitignore sweep write `.claude/` into the ignore set of every + # gitignore-mode project whether or not one ever exists there, so the + # entry is aspirational rather than a promise. Three projects tripped + # this on velox, and ratio is missing the identical directory in the + # identical three, which is what proves it is the steady state and not + # reinstall drift. + # + # Nor does dropping it lose a real signal. A project that genuinely + # carries one (rules and hooks from a language bundle) has it re-synced + # by sync-language-bundle.sh at every session start, so a true absence + # heals itself before this check would ever run. + with tempfile.TemporaryDirectory() as root: + self.project(root, [".ai/", ".claude/"], present=(".ai/",)) + r = run_check(project_roots=root) + self.assertEqual(r.returncode, 0, r.stdout) + self.assertNotIn(".claude", r.stdout) + def test_ignored_and_present_tooling_passes(self): with tempfile.TemporaryDirectory() as root: self.project(root, [".ai/", "CLAUDE.md"], @@ -3913,6 +3913,12 @@ From the roam inbox (Craig, claimed 2026-07-23): velox needs bringing up to date Resolved 2026-07-23 by a full sweep over tailscale. The touchpad module was already gone — velox's running waybar (started 01:05, after the reboot) and its tracked config both carry zero =custom/touchpad= entries; what Craig saw was the pre-restow waybar process from before the reboot, and the reboot cleared it. Sweep results: both machines at dotfiles f9b6404 (all three hyprland lock/exit fixes live on velox, config errors clean, =allow_session_lock_restore= reads true); stow restow clean, only the expected skip-worktree files; rulesets pulled to 50fc7ca and =make install= run (agent-text verified working by invoking it — an earlier "MISSING" reading was a PATH artifact of the non-interactive ssh shell, not a real gap); desktop-settings tick timer active; mpvpaper, power-profiles-daemon, gtk4-layer-shell, webkit2gtk all present. Genuine remaining differences, all per-machine installs rather than sync failures: =cmail-action=, =gcalcli=, and =playwright= aren't installed on velox, and =obsbot-wb-guard.service= isn't enabled there (the OBSBOT lives on ratio). None block anything; file separately if velox should send mail or drive browser tests. +*** 2026-08-20 Thu @ 09:53:04 -0700 One of those three closed itself; two still stand +=cmail-action= is on both daily drivers now, and nothing did it deliberately. It moved into rulesets at =claude-templates/bin/=, and rulesets' =make install= links that whole directory into =~/.local/bin= at every session start — so velox picked it up on its own. Verified here: the symlink was written 05:44 this morning by this session's own startup, and the tool runs. + +=gcalcli= and =playwright= are still absent on velox, which stays correct until I say velox should send calendar invites or drive browser tests. =obsbot-wb-guard= is still right to be off here; the camera is on ratio. + +Leaving the paragraph above as written rather than striking it (rulesets suggested striking). It is the resolution note of a task closed 2026-07-23 and it was accurate that day. Editing a closed record to match today makes it a worse record, and the useful correction is this dated entry, not a redaction. ** DONE [#C] Weather tooltip sunrise and sunset :feature:waybar:weather:quick:solo: CLOSED: [2026-07-23 Thu] Shipped 2026-07-23 as dotfiles =de62e9d=. The two rows sit directly below Humidity in the current-conditions block, rendered in the footer's 12-hour format (=%-I:%M %p=) so the tooltip reads one way throughout. |
