From b1b433e6c16b2ca52b33bbe8aea31734aa23212c Mon Sep 17 00:00:00 2001 From: clover caruso Date: Fri, 15 May 2026 01:48:42 -0700 Subject: [PATCH] feat: random terrifying stuff + a backup systsem --- modules/home/default.nix | 6 ++ packages/autofmt/default.nix | 16 +-- packages/jj-import-merge/jj-import-merge.js | 55 ++++++++--- switch | 9 +- users/clover/AGENTS.md | 4 + users/clover/home.nix | 4 - users/clover/paperback/configuration.nix | 6 +- users/clover/pnpm-lock.yaml | 104 ++++++++++++-------- users/clover/sandwich/home.nix | 79 ++++++++++++++- users/clover/scripts/jj-ci.ts | 100 ++++++++++++++----- users/clover/work/home.nix | 3 - users/natalie/laptop/configuration.nix | 4 +- 12 files changed, 288 insertions(+), 102 deletions(-) diff --git a/modules/home/default.nix b/modules/home/default.nix index c137f374bdee0de3013b37b5eaaa00da07c061d7..d4e73c735be80a18e6116f77b9b730d4671465bb 100644 --- a/modules/home/default.nix +++ b/modules/home/default.nix @@ -59,6 +59,12 @@ in home.shell = { enableShellIntegration = true; }; + home.sessionPath = [ + "$HOME/.local/bin" + "$HOME/.opencode/bin" + "$HOME/.vite-plus/bin" + "$HOME/bin" + ]; programs = { home-manager.enable = true; nix-index.enable = true; diff --git a/packages/autofmt/default.nix b/packages/autofmt/default.nix index 64cebfb26f07b232564e8818e4732c0663c0dbd4..cd3bf684985037c6287d20834c230a3483ec8645 100644 --- a/packages/autofmt/default.nix +++ b/packages/autofmt/default.nix @@ -15,11 +15,13 @@ pkgs.writeTextFile { name = "autofmt"; destination = "/bin/autofmt"; executable = true; - text = builtins.replaceStrings - [ "#!/usr/bin/env node" ] - [ - ''#!${pkgs.nodejs}/bin/node - process.env.PATH = "${pkgs.lib.makeBinPath runtimeInputs}:" + (process.env.PATH ?? "");'' - ] - (builtins.readFile ./autofmt.js); + text = + builtins.replaceStrings + [ "#!/usr/bin/env node" ] + [ + '' + #!${pkgs.nodejs}/bin/node + process.env.PATH = "${pkgs.lib.makeBinPath runtimeInputs}:" + (process.env.PATH ?? "");'' + ] + (builtins.readFile ./autofmt.js); } diff --git a/packages/jj-import-merge/jj-import-merge.js b/packages/jj-import-merge/jj-import-merge.js index df56d84e771df5b1f29c3de95638a1c4eb6c84f4..f09e2de9319fbef3170e92d75796a5bf18125792 100644 --- a/packages/jj-import-merge/jj-import-merge.js +++ b/packages/jj-import-merge/jj-import-merge.js @@ -86,10 +86,14 @@ function usage(code) { const stream = code === 0 ? process.stdout : process.stderr; stream.write(`usage: ${exe} [--all-jj] [--] ...\n`); stream.write(`\n`); - stream.write(`merge top-of-file JS/TS imports from 2-sided Jujutsu conflicts\n`); + stream.write( + `merge top-of-file JS/TS imports from 2-sided Jujutsu conflicts\n`, + ); stream.write(`\n`); stream.write(`options:\n`); - stream.write(` --all-jj resolve all conflicted JS/TS files from 'jj resolve --list'\n`); + stream.write( + ` --all-jj resolve all conflicted JS/TS files from 'jj resolve --list'\n`, + ); stream.write(` -h show help\n`); process.exit(code); } @@ -158,7 +162,11 @@ function processFile(file) { leftImports.start, rightImports.start, ); - const end = projectBoundaryToOriginal(parsed.parts, leftImports.end, rightImports.end); + const end = projectBoundaryToOriginal( + parsed.parts, + leftImports.end, + rightImports.end, + ); if (start == null || end == null || end < start) { return { kind: "noop" }; } @@ -168,7 +176,8 @@ function processFile(file) { rightImports.statements, detectNewline(original), ); - const updated = original.slice(0, start) + mergedImports + original.slice(end); + const updated = original.slice(0, start) + mergedImports + + original.slice(end); if (updated === original) { return { kind: "noop" }; @@ -193,7 +202,9 @@ function processFile(file) { if (formatResult.error || formatResult.status !== 0) { fs.writeFileSync(file, original, "utf8"); if (formatResult.error) { - throw new Error(`autofmt failed for ${file}: ${formatResult.error.message}`); + throw new Error( + `autofmt failed for ${file}: ${formatResult.error.message}`, + ); } throw new Error(`autofmt failed for ${file}`); } @@ -259,7 +270,9 @@ function parseConflictBlock(lines, startIndex) { continue; } if (line.startsWith("%%%%%%% diff from:")) { - if (index + 1 >= lines.length || !/^\\\\+\s*to:/.test(lines[index + 1].text)) { + if ( + index + 1 >= lines.length || !/^\\\\+\s*to:/.test(lines[index + 1].text) + ) { return { supported: false, nextIndex: startIndex + 1 }; } index += 2; @@ -512,7 +525,7 @@ function scanLine(line, state) { index += 1; continue; } - if (char === "'" || char === "\"" || char === "`") { + if (char === "'" || char === '"' || char === "`") { state.stringQuote = char; continue; } @@ -716,12 +729,18 @@ function canMergeImports(left, right) { } const defaultBinding = mergeField(left.defaultBinding, right.defaultBinding); - const namespaceImport = mergeField(left.namespaceImport, right.namespaceImport); + const namespaceImport = mergeField( + left.namespaceImport, + right.namespaceImport, + ); if (defaultBinding === undefined || namespaceImport === undefined) { return false; } - const namedSpecifiers = unique([...left.namedSpecifiers, ...right.namedSpecifiers]); + const namedSpecifiers = unique([ + ...left.namedSpecifiers, + ...right.namedSpecifiers, + ]); if (namespaceImport && namedSpecifiers.length > 0) { return false; } @@ -731,8 +750,14 @@ function canMergeImports(left, right) { function mergeImports(left, right) { const defaultBinding = mergeField(left.defaultBinding, right.defaultBinding); - const namespaceImport = mergeField(left.namespaceImport, right.namespaceImport); - const namedSpecifiers = unique([...left.namedSpecifiers, ...right.namedSpecifiers]); + const namespaceImport = mergeField( + left.namespaceImport, + right.namespaceImport, + ); + const namedSpecifiers = unique([ + ...left.namedSpecifiers, + ...right.namedSpecifiers, + ]); return { kind: "binding", @@ -782,13 +807,17 @@ function renderImport(analysis, newline) { pieces.push(`{ ${analysis.namedSpecifiers[0]} }`); } else { pieces.push( - `{${newline}${analysis.namedSpecifiers.map((spec) => ` ${spec},`).join(newline)}${newline}}`, + `{${newline}${ + analysis.namedSpecifiers.map((spec) => ` ${spec},`).join(newline) + }${newline}}`, ); } } return ensureTrailingNewline( - `import ${analysis.isTypeImport ? "type " : ""}${pieces.join(", ")} from ${analysis.quote}${analysis.source}${analysis.quote}${analysis.attributes};`, + `import ${analysis.isTypeImport ? "type " : ""}${ + pieces.join(", ") + } from ${analysis.quote}${analysis.source}${analysis.quote}${analysis.attributes};`, newline, ); } diff --git a/switch b/switch index 04af03eb5978615a646d5094da65c81dc95f7d60..b6fc0e9940149910a6e437e5f523786345ec60f5 100755 --- a/switch +++ b/switch @@ -12,13 +12,16 @@ if [ -z "$hostname" ]; then hostname="$(hostname)" fi printf "%s" "$hostname" >.hostname -if [ "$(uname -o)" = "Darwin" ]; then +if [ "$(uname -s)" = "Darwin" ]; then nh_subcommand="darwin" fallback_command="nix run .#darwin-rebuild" - hostname="darwinConfigurations.$hostname" fi if command -v nh >/dev/null; then - nh $nh_subcommand switch '.#'"$hostname" + if [ "$nh_subcommand" = "darwin" ]; then + nh darwin switch . --hostname "$hostname" + else + nh os switch '.#'"$hostname" + fi else $fallback_command -- switch --flake '.#'"$hostname" fi diff --git a/users/clover/AGENTS.md b/users/clover/AGENTS.md index f3656226b2c41927d98de0484dd98df29191dca8..bde349a50e0f995db9f87a6231fb78e8bbe5a6ec 100644 --- a/users/clover/AGENTS.md +++ b/users/clover/AGENTS.md @@ -13,6 +13,10 @@ You are working with Clover, an intelligent web/systems engineer. Please avoid e - Never include a section on checks saying "pnpm test passed" or "checks passed" or whatever. Just make sure your validation is strong in the first place; You're expected to have that done. - Feedback should be useful and actionable. A couple words is OK if there is genuinely nothing to add. +## Verification + +- Use the `code-reviewer` agent for all verification after meaningful code, config, test, or doc changes. The top-level agent should pass only a concise list of what it did, including changed files and intended behavior; the reviewer independently inspects the diff, runs relevant checks, and reports findings. The `code-reviewer` agent is told it is the reviewer agent, so it must not recurse into itself. + ## Comments Comments must always be placed and edited with intent to serialize codebase theory for future versions of ourselves and coworkers. They are professionally written, containing relevant context to the current iteration. Clover's comments are always timeless and rarely written from the first person (no `I`, `we`) -- refer directly to the code. Rewording comments this way helps solidify your own understanding, and can even reveal logic bugs in the designed systems. Prefer documentation comments over line comments. diff --git a/users/clover/home.nix b/users/clover/home.nix index a6fc8a82376aaef174a2d556a500ef175b43c016..23e38b3503e15fa36676fa9e02ea1437eef2ae6e 100644 --- a/users/clover/home.nix +++ b/users/clover/home.nix @@ -10,10 +10,6 @@ in { home = { stateVersion = "23.05"; # Please read the comment before changing. - sessionPath = [ - "$HOME/.vite-plus/bin" - "$HOME/.local/bin" - ]; packages = with pkgs; let diff --git a/users/clover/paperback/configuration.nix b/users/clover/paperback/configuration.nix index 87a13d7f8638f6a81a6931539129b22e07a0512c..cddc2b60f78df119b7b8768a4f02de75cc60a818 100644 --- a/users/clover/paperback/configuration.nix +++ b/users/clover/paperback/configuration.nix @@ -1,2 +1,6 @@ -_: { +{ lib, ... }: +{ + nix.enable = false; + nix.optimise.automatic = lib.mkForce false; + nix.gc.automatic = lib.mkForce false; } diff --git a/users/clover/pnpm-lock.yaml b/users/clover/pnpm-lock.yaml index 859de6f0999948c34e8427d904d6a1ef314828c9..874d3426b12527a9dbffe273deff9c6328347c12 100644 --- a/users/clover/pnpm-lock.yaml +++ b/users/clover/pnpm-lock.yaml @@ -1,99 +1,117 @@ -lockfileVersion: '9.0' +lockfileVersion: "9.0" settings: autoInstallPeers: true excludeLinksFromLockfile: false importers: - .: dependencies: - '@clo/lib': + "@clo/lib": specifier: jsr:* - version: '@jsr/clo__lib@4.0.0' - '@lydell/node-pty': + version: "@jsr/clo__lib@4.0.0" + "@lydell/node-pty": specifier: 1.2.0-beta.12 version: 1.2.0-beta.12 - '@types/node': + "@types/node": specifier: ^24.12.2 version: 24.12.2 packages: - - '@jsr/clo__lib@4.0.0': - resolution: {integrity: sha512-uOzRjwbFn9HizCpJeqPXzuiri3hqqcePNLA7ESi1Vgwon9dOmhMSzHfmb9kz599VsKF1RLH7i3NK302K60Oe/A==, tarball: https://npm.jsr.io/~/11/@jsr/clo__lib/4.0.0.tgz} - - '@lydell/node-pty-darwin-arm64@1.2.0-beta.12': - resolution: {integrity: sha512-tqaifcY9Cr41SblO1+FLzh8oxxtkNhuW9Dhl22lKme9BreYvKvxEZcdPIXTuqkJc5tagOEC4QHShKmJjLyLXLQ==} + "@jsr/clo__lib@4.0.0": + resolution: { + integrity: sha512-uOzRjwbFn9HizCpJeqPXzuiri3hqqcePNLA7ESi1Vgwon9dOmhMSzHfmb9kz599VsKF1RLH7i3NK302K60Oe/A==, + tarball: https://npm.jsr.io/~/11/@jsr/clo__lib/4.0.0.tgz, + } + + "@lydell/node-pty-darwin-arm64@1.2.0-beta.12": + resolution: { + integrity: sha512-tqaifcY9Cr41SblO1+FLzh8oxxtkNhuW9Dhl22lKme9BreYvKvxEZcdPIXTuqkJc5tagOEC4QHShKmJjLyLXLQ==, + } cpu: [arm64] os: [darwin] - '@lydell/node-pty-darwin-x64@1.2.0-beta.12': - resolution: {integrity: sha512-4LrS5pCJwqHKDVf1zS2gyNV0m4hKAXch+XZNhbZ6LY8uwVL8BhchzQBO40Os5anuRxRCWzHpw4Sp64Ie8q7E4Q==} + "@lydell/node-pty-darwin-x64@1.2.0-beta.12": + resolution: { + integrity: sha512-4LrS5pCJwqHKDVf1zS2gyNV0m4hKAXch+XZNhbZ6LY8uwVL8BhchzQBO40Os5anuRxRCWzHpw4Sp64Ie8q7E4Q==, + } cpu: [x64] os: [darwin] - '@lydell/node-pty-linux-arm64@1.2.0-beta.12': - resolution: {integrity: sha512-Sx+A71x5BDGHt9ansfrtGxwq2VFVDWvJUAdlUL0Hv0qeiJUfts+hgopx+CgT4PSwahKjdEgtu0+FAfY9rICKRw==} + "@lydell/node-pty-linux-arm64@1.2.0-beta.12": + resolution: { + integrity: sha512-Sx+A71x5BDGHt9ansfrtGxwq2VFVDWvJUAdlUL0Hv0qeiJUfts+hgopx+CgT4PSwahKjdEgtu0+FAfY9rICKRw==, + } cpu: [arm64] os: [linux] - '@lydell/node-pty-linux-x64@1.2.0-beta.12': - resolution: {integrity: sha512-bJzs94njofYhGg/UDqW1nj0dtvvu+2OvxMY+RlLS1T17VgcktKoIR6PuenTwE5HJ/D6StCPADmXcT0nNsCKmIQ==} + "@lydell/node-pty-linux-x64@1.2.0-beta.12": + resolution: { + integrity: sha512-bJzs94njofYhGg/UDqW1nj0dtvvu+2OvxMY+RlLS1T17VgcktKoIR6PuenTwE5HJ/D6StCPADmXcT0nNsCKmIQ==, + } cpu: [x64] os: [linux] - '@lydell/node-pty-win32-arm64@1.2.0-beta.12': - resolution: {integrity: sha512-p7POgjVEiFaBC3/y+AKuV1FzePCsJ6HmZDv2XK+jBZSfwP8+uBAw181ZiKYN1YuRa/XpmBGaWezcI8hZkbW++g==} + "@lydell/node-pty-win32-arm64@1.2.0-beta.12": + resolution: { + integrity: sha512-p7POgjVEiFaBC3/y+AKuV1FzePCsJ6HmZDv2XK+jBZSfwP8+uBAw181ZiKYN1YuRa/XpmBGaWezcI8hZkbW++g==, + } cpu: [arm64] os: [win32] - '@lydell/node-pty-win32-x64@1.2.0-beta.12': - resolution: {integrity: sha512-IDFa00g7qUDGUYgByrUBJtC+mOjYVt/8KYyWivCg5JjGOHbBUACUQZLl0jTWmnr+tld/UyTpX90a2PY6oTVtRw==} + "@lydell/node-pty-win32-x64@1.2.0-beta.12": + resolution: { + integrity: sha512-IDFa00g7qUDGUYgByrUBJtC+mOjYVt/8KYyWivCg5JjGOHbBUACUQZLl0jTWmnr+tld/UyTpX90a2PY6oTVtRw==, + } cpu: [x64] os: [win32] - '@lydell/node-pty@1.2.0-beta.12': - resolution: {integrity: sha512-qIK890UwPupoj07osVvgOIa++1mxeHbcGry4PKRHhNVNs81V2SCG34eJr46GybiOmBtc8Sj5PB1/GGM5PL549g==} + "@lydell/node-pty@1.2.0-beta.12": + resolution: { + integrity: sha512-qIK890UwPupoj07osVvgOIa++1mxeHbcGry4PKRHhNVNs81V2SCG34eJr46GybiOmBtc8Sj5PB1/GGM5PL549g==, + } - '@types/node@24.12.2': - resolution: {integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==} + "@types/node@24.12.2": + resolution: { + integrity: sha512-A1sre26ke7HDIuY/M23nd9gfB+nrmhtYyMINbjI1zHJxYteKR6qSMX56FsmjMcDb3SMcjJg5BiRRgOCC/yBD0g==, + } undici-types@7.16.0: - resolution: {integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==} + resolution: { + integrity: sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==, + } snapshots: + "@jsr/clo__lib@4.0.0": {} - '@jsr/clo__lib@4.0.0': {} - - '@lydell/node-pty-darwin-arm64@1.2.0-beta.12': + "@lydell/node-pty-darwin-arm64@1.2.0-beta.12": optional: true - '@lydell/node-pty-darwin-x64@1.2.0-beta.12': + "@lydell/node-pty-darwin-x64@1.2.0-beta.12": optional: true - '@lydell/node-pty-linux-arm64@1.2.0-beta.12': + "@lydell/node-pty-linux-arm64@1.2.0-beta.12": optional: true - '@lydell/node-pty-linux-x64@1.2.0-beta.12': + "@lydell/node-pty-linux-x64@1.2.0-beta.12": optional: true - '@lydell/node-pty-win32-arm64@1.2.0-beta.12': + "@lydell/node-pty-win32-arm64@1.2.0-beta.12": optional: true - '@lydell/node-pty-win32-x64@1.2.0-beta.12': + "@lydell/node-pty-win32-x64@1.2.0-beta.12": optional: true - '@lydell/node-pty@1.2.0-beta.12': + "@lydell/node-pty@1.2.0-beta.12": optionalDependencies: - '@lydell/node-pty-darwin-arm64': 1.2.0-beta.12 - '@lydell/node-pty-darwin-x64': 1.2.0-beta.12 - '@lydell/node-pty-linux-arm64': 1.2.0-beta.12 - '@lydell/node-pty-linux-x64': 1.2.0-beta.12 - '@lydell/node-pty-win32-arm64': 1.2.0-beta.12 - '@lydell/node-pty-win32-x64': 1.2.0-beta.12 + "@lydell/node-pty-darwin-arm64": 1.2.0-beta.12 + "@lydell/node-pty-darwin-x64": 1.2.0-beta.12 + "@lydell/node-pty-linux-arm64": 1.2.0-beta.12 + "@lydell/node-pty-linux-x64": 1.2.0-beta.12 + "@lydell/node-pty-win32-arm64": 1.2.0-beta.12 + "@lydell/node-pty-win32-x64": 1.2.0-beta.12 - '@types/node@24.12.2': + "@types/node@24.12.2": dependencies: undici-types: 7.16.0 diff --git a/users/clover/sandwich/home.nix b/users/clover/sandwich/home.nix index 60fe8437d1309bd834f1e7b0f7852826c4f3285e..05149234e80ae18875d128884dd1aab178e480d6 100644 --- a/users/clover/sandwich/home.nix +++ b/users/clover/sandwich/home.nix @@ -1,7 +1,82 @@ -{ pkgs, ... }: +{ config, pkgs, ... }: +let + # Hourly backup: rsync the local working drives up to the NAS, then (only on a + # fully clean push) trigger a ZFS snapshot + tiered prune on the NAS. The backup + # on the NAS is plain browsable files; history lives in ZFS snapshots. + sandwich-backup = pkgs.writeShellApplication { + name = "sandwich-backup"; + runtimeInputs = with pkgs; [ + rsync + openssh + coreutils + ]; + text = '' + NAS=clo@git.paperclover.net + DEST=$NAS:/mnt/storage1/backup/sandwich + LOCK=/tmp/sandwich-backup.lock + + # Dedicated passphraseless key so the launchd job runs unattended; the + # interactive key keeps its passphrase. IdentitiesOnly stops ssh from + # offering the passphrased key first. + SSH=(ssh -i "$HOME/.ssh/id_sandwich_backup" -o IdentitiesOnly=yes -o BatchMode=yes) + + # Single-instance guard: the initial sync takes hours, far longer than the + # hourly interval. mkdir is atomic; recover if a previous run died uncleanly. + if ! mkdir "$LOCK" 2>/dev/null; then + if [ -f "$LOCK/pid" ] && kill -0 "$(cat "$LOCK/pid")" 2>/dev/null; then + echo "already running (pid $(cat "$LOCK/pid"))" + exit 0 + fi + echo "clearing stale lock" + rm -rf "$LOCK" + mkdir "$LOCK" + fi + echo $$ >"$LOCK/pid" + trap 'rm -rf "$LOCK"' EXIT + + # rsync exit 24 (source files vanished mid-transfer) is benign on a live + # machine; anything else is a real failure and aborts before the snapshot. + rsync_one() { + local rc=0 + rsync -a --delete --partial --human-readable --stats \ + -e "''${SSH[*]}" \ + --exclude '.DS_Store' \ + --exclude '.Spotlight-V100' \ + --exclude '.Trashes' \ + --exclude '.fseventsd' \ + --exclude '.TemporaryItems' \ + --exclude '.DocumentRevisions-V100' \ + "$@" || rc=$? + if [ "$rc" -ne 0 ] && [ "$rc" -ne 24 ]; then + return "$rc" + fi + } + + rsync_one /Volumes/Asset/ "$DEST/Asset/" + rsync_one /Volumes/Project/ "$DEST/Project/" + rsync_one --exclude 'LMStudio/' /Volumes/Documents/ "$DEST/Documents/" + rsync_one "$HOME/Desktop/" "$DEST/Desktop/" + + # Snapshot only reached if every push above succeeded. + "''${SSH[@]}" "$NAS" /mnt/storage1/apps/home-infra/backup/snapshot-prune.sh storage1/backup/sandwich + ''; + }; +in { - home.packages = with pkgs; [ nodejs_24 + rsync + sandwich-backup ]; + + launchd.agents.sandwich-backup = { + enable = true; + config = { + ProgramArguments = [ "${sandwich-backup}/bin/sandwich-backup" ]; + StartInterval = 3600; + RunAtLoad = true; + StandardOutPath = "${config.home.homeDirectory}/Library/Logs/sandwich-backup.log"; + StandardErrorPath = "${config.home.homeDirectory}/Library/Logs/sandwich-backup.log"; + }; + }; } diff --git a/users/clover/scripts/jj-ci.ts b/users/clover/scripts/jj-ci.ts index 7fdb2b319bf0ee57e994edad131f7dbdad99a611..b503e916b09bfd2cab623b5089ff6e0fd4bc33d5 100755 --- a/users/clover/scripts/jj-ci.ts +++ b/users/clover/scripts/jj-ci.ts @@ -153,8 +153,9 @@ if (!fs.existsSync(ciScript)) { if (invalid) process.exit(1); if (parallelize) { - if (dryRun) log.info("would run", "jj parallelize " + selectedRevisions.join(" ")); - else jj(["parallelize", ...selectedRevisions]); + if (dryRun) { + log.info("would run", "jj parallelize " + selectedRevisions.join(" ")); + } else jj(["parallelize", ...selectedRevisions]); } const changeIds = [...new Set(selectedRevisions.flatMap(resolveChangeIds))]; @@ -185,14 +186,14 @@ const plans: Plan[] = changeIds.map((changeId) => ({ .filter((candidate) => candidate !== "" && candidate !== changeId), ), ], - label: changeId.slice(0, 6) + ': ' + jj( + label: changeId.slice(0, 6) + ": " + jj( [ "log", "--no-graph", "-r", `${changeId}`, "-T", - 'self.description().first_line()', + "self.description().first_line()", ], { ignoreWorkingCopy: true }, ), @@ -272,7 +273,9 @@ try { if (state === "ok") passed += 1; else if (state === "failed" || state === "skipped") failed += 1; } - return `${ansi.fgGreen}${passed} pass${ansi.reset}, ${failed > 0 ? ansi.fgRed : ""}${failed} fail${ansi.reset}`; + return `${ansi.fgGreen}${passed} pass${ansi.reset}, ${ + failed > 0 ? ansi.fgRed : "" + }${failed} fail${ansi.reset}`; }, }); @@ -313,7 +316,14 @@ try { try { plainLog.push("--- prep ---\n"); - ensureWorkspace(slot, plan.changeId, plan.label, trackedWorkspaces, node, plainLog); + ensureWorkspace( + slot, + plan.changeId, + plan.label, + trackedWorkspaces, + node, + plainLog, + ); plainLog.push("\n"); phase = "ci"; @@ -324,7 +334,9 @@ try { node, }); plainLog.push( - `--- ci ---\nexit: ${ci.exitCode ?? "signal"}\nduration_ms: ${ci.durationMs}\n\n`, + `--- ci ---\nexit: ${ + ci.exitCode ?? "signal" + }\nduration_ms: ${ci.durationMs}\n\n`, ); plainLog.push(ci.plainText); if (ci.plainText !== "" && !ci.plainText.endsWith("\n")) { @@ -369,7 +381,9 @@ try { ? (error.stack ?? error.message) : String(error); node.log.error(error); - plainLog.push(`--- ${phase} error ---\n${normalizePlain(message)}\n`); + plainLog.push( + `--- ${phase} error ---\n${normalizePlain(message)}\n`, + ); writeFailureLog(plan.logPath, plainLog); return { changeId: plan.changeId, @@ -393,10 +407,13 @@ try { for (const plan of plans) { if (stateByChangeId.get(plan.changeId) !== "pending") continue; - const blockedBy = plan.dependencyChangeIds.filter((dependencyChangeId) => { - const dependencyState = stateByChangeId.get(dependencyChangeId); - return dependencyState === "failed" || dependencyState === "skipped"; - }); + const blockedBy = plan.dependencyChangeIds.filter( + (dependencyChangeId) => { + const dependencyState = stateByChangeId.get(dependencyChangeId); + return dependencyState === "failed" || + dependencyState === "skipped"; + }, + ); if (blockedBy.length === 0) continue; @@ -456,12 +473,17 @@ try { if (!result.ok) continue; - for (const childChangeId of childrenByChangeId.get(result.changeId) ?? []) { + for ( + const childChangeId of childrenByChangeId.get(result.changeId) ?? [] + ) { if (stateByChangeId.get(childChangeId) !== "pending") continue; const remainingDependencies = (remainingDependenciesByChangeId.get(childChangeId) ?? 1) - 1; - remainingDependenciesByChangeId.set(childChangeId, remainingDependencies); + remainingDependenciesByChangeId.set( + childChangeId, + remainingDependencies, + ); if (remainingDependencies === 0) { const childPlan = planByChangeId.get(childChangeId); @@ -509,7 +531,14 @@ try { summary.push( `${ansi.style(failStyle, "x")} ${result.label} (${result.phase})`, result.blockedBy?.length - ? ` ${ansi.style(dimStyle, `[waiting on ${result.blockedBy.map((id) => id.slice(0, 12)).join(", ")}]`)}` + ? ` ${ + ansi.style( + dimStyle, + `[waiting on ${ + result.blockedBy.map((id) => id.slice(0, 12)).join(", ") + }]`, + ) + }` : "", result.logPath ? ` ${ansi.style(dimStyle, `[log ${result.logPath}]`)}` @@ -525,7 +554,14 @@ try { summary.push( `${ansi.style(skipStyle, "-")} ${result.label}`, result.blockedBy?.length - ? ` ${ansi.style(dimStyle, `[blocked by ${result.blockedBy.map((id) => id.slice(0, 12)).join(", ")}]`)}` + ? ` ${ + ansi.style( + dimStyle, + `[blocked by ${ + result.blockedBy.map((id) => id.slice(0, 12)).join(", ") + }]`, + ) + }` : "", "\n", ); @@ -543,7 +579,9 @@ try { if (successfulChangeIds.length > 0) { summary.push( "\n", - `${ansi.style(infoStyle, "push successful commits:")} jj git push -c "${successfulChangeIds.join("|")}"`, + `${ansi.style(infoStyle, "push successful commits:")} jj git push -c "${ + successfulChangeIds.join("|") + }"`, "\n", ); } @@ -616,7 +654,6 @@ function resolveGitDir(cwd: string): string | null { return value; } - function jj(args: string[], options: CommandOptions = {}): string { const result = child_process.spawnSync( "jj", @@ -637,7 +674,9 @@ function jj(args: string[], options: CommandOptions = {}): string { const text = stdout + stderr; if (options.node && text !== "") options.node.log.write(text); - if (options.plainLog && text !== "") options.plainLog.push(normalizePlain(text)); + if (options.plainLog && text !== "") { + options.plainLog.push(normalizePlain(text)); + } if (result.error) throw result.error; if (result.status !== 0) { @@ -891,7 +930,10 @@ function forgetPoolWorkspaces( } if (errors.length > 0) { - throw new AggregateError(errors, "failed to forget one or more jj-ci workspaces"); + throw new AggregateError( + errors, + "failed to forget one or more jj-ci workspaces", + ); } } @@ -964,7 +1006,12 @@ function runScript( ? preferredShell : "bash"; - const term = pty.spawn(shell, ["-c", 'set -o pipefail; set -eux; source "$1"', "jj-ci", scriptPath], { + const term = pty.spawn(shell, [ + "-c", + 'set -o pipefail; set -eux; source "$1"', + "jj-ci", + scriptPath, + ], { cols: process.stdout.columns ?? 120, cwd: options.cwd, encoding: "utf8", @@ -1055,11 +1102,16 @@ function tryMatchDescendant( matchedDependencyByDescendant: Map, seenDescendants: Set, ): boolean { - for (const descendantChangeId of descendantsByChangeId.get(dependencyChangeId) ?? []) { + for ( + const descendantChangeId of descendantsByChangeId.get(dependencyChangeId) ?? + [] + ) { if (seenDescendants.has(descendantChangeId)) continue; seenDescendants.add(descendantChangeId); - const matchedDependency = matchedDependencyByDescendant.get(descendantChangeId); + const matchedDependency = matchedDependencyByDescendant.get( + descendantChangeId, + ); if ( matchedDependency == null || tryMatchDescendant( @@ -1092,7 +1144,7 @@ function progressAttachToScreen( widget ??= startWidget({ format: ({ now }) => progress.formatAnsi(now, root.active), }) ?? null; - if (!widget)return; + if (!widget) return; widget.fps = items.some((x) => x.showTotal !== false && x.total > 0) ? 15 : null; diff --git a/users/clover/work/home.nix b/users/clover/work/home.nix index 14a2e1138b94fa2dd40cf806bc66e286aca82961..8626a37e659191f80de70f65c0e68968968e7041 100644 --- a/users/clover/work/home.nix +++ b/users/clover/work/home.nix @@ -25,7 +25,4 @@ typescript zig ]; - home.sessionPath = [ - "$HOME/.opencode/bin" - ]; } diff --git a/users/natalie/laptop/configuration.nix b/users/natalie/laptop/configuration.nix index 6ad204a544a8351c5c28abedb90b896f59f8f803..73340058d19baff6ec8bb6399aa74c6c95dd24fa 100644 --- a/users/natalie/laptop/configuration.nix +++ b/users/natalie/laptop/configuration.nix @@ -7,7 +7,7 @@ # Custom configuration modules in "modules" are shared between users, # and can be configured in this "shared" namespace shared.darwin = { -# macAppStoreApps = [ "wireguard" ]; + # macAppStoreApps = [ "wireguard" ]; }; system.defaults.NSGlobalDomain."com.apple.trackpad.scaling" = 1.0; @@ -40,7 +40,7 @@ casks = [ "battle-net" "stremio" -# "alt-tab" + # "alt-tab" "legcord" "zulip" "zen" -- 2.54.0