Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 3 additions & 50 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 3 additions & 13 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -90,19 +90,6 @@
# while attached, and a persistent session survives disconnects server-side.
zmx.url = "github:neurosnap/zmx";

# git-ai — AI-authorship tracking CLI (github.com/git-ai-project/git-ai).
# Consume its flake package directly and pin it in flake.lock. The Home
# Manager profile installs upstream's `minimal` output, which provides
# `git-ai` and `git-og` without replacing the `git` binary already owned
# by programs.git. Following nixpkgs keeps the Rust build on our one package
# pin instead of adding another nixpkgs universe to the lock.
# `nix flake update git-ai` bumps to the latest pushed commit.
git-ai = {
url = "github:git-ai-project/git-ai";
inputs.nixpkgs.follows = "nixpkgs";
inputs.flake-utils.follows = "tally/flake-utils";
};

# llm-agents.nix — numtide's daily-rebuilt catalog of ~100 AI coding agents
# and tooling (claude-code, codex, gemini-cli, opencode, crush, goose, amp,
# ...). Its `overlays.default` exposes the whole set, prebuilt against its OWN
Expand Down Expand Up @@ -481,6 +468,7 @@
local-ai-monthly
mactahoe-gtk-theme
mactahoe-icon-theme
music-acquire
sfmono-liga
;

Expand Down Expand Up @@ -525,6 +513,8 @@

# The RAW out-of-store dotfiles are never checked at switch, so check them here.
checks.${system} = {
music-acquire = pkgs.music-acquire;

nas-topology =
let
nas = self.nixosConfigurations.nas.config;
Expand Down
4 changes: 1 addition & 3 deletions home/home.nix
Original file line number Diff line number Diff line change
Expand Up @@ -460,9 +460,6 @@ in
# seed via modules/secrets.nix, and DISABLE_UPDATES=1 keeps the native
# updater from clobbering ~/.local/bin.
llmAgentsSelected
# Upstream's minimal flake output: git-ai + git-og, while programs.git below
# remains the sole provider of the real git binary.
inputs.git-ai.packages.${pkgs.stdenv.hostPlatform.system}.minimal
huggingface-cli # metadata CLI; agenix authentication is coordinator-only
gh
google-cloud-sdk
Expand All @@ -472,6 +469,7 @@ in
backlog-md # bespoke pkg via overlay — see pkgs/backlog-md.nix
pkgs.crm # vendored personal CRM CLI; data stays at its built-in notes path
pkgs.dcal # vendored calendar CLI; data lives under XDG, nothing in git
music-acquire # evidence-gated SoundCloud → YouTube → capture acquisition
cliamp # terminal music player → navidrome. overlay pkg, see pkgs/cliamp.nix
uv # Astral Python pkg/project manager. "hot" overlay pkg — rides nixpkgs-fresh HEAD (flake.nix), so it stays latest independent of the main pin.

Expand Down
19 changes: 8 additions & 11 deletions home/tally.nix
Original file line number Diff line number Diff line change
Expand Up @@ -155,17 +155,6 @@ in
};
};

# E5 (dotfiles#138): bind code-result revisions to git-ai authorship
# notes, advisory posture first — an unprovisioned host and a squash that
# lost its attribution produce identical evidence, so advisory is how the
# binding proves itself before anything is allowed to fail on it. git-ai
# 1.6.17 is externally provisioned (verified on the estate 2026-08-03);
# tally.nix does not ship the binary.
gitAi = {
enable = true;
mode = "advisory";
};

# One low-priority durable row replaces the old 02:00/03:30/04:30/06:00 chain.
# It holds the build and coordinator GPU lanes end-to-end, making the measured
# single-node build plus activation one exclusive maintenance window.
Expand Down Expand Up @@ -262,4 +251,12 @@ in
};
};

# Freeze the nightly deploy at its admission boundary while any campaign is
# registered. This replaces the dated, hand-maintained ExecCondition
# drop-ins used during the silent-factory ladder.
systemd.user.services = lib.optionalAttrs isCoordinator {
"tally-producer-nightly-fleet-deploy".Service.ExecCondition =
"${tallyPackage}/bin/tally --config /home/tom/.config/tally/config.json campaign quiescent --state-dir /home/tom/.local/state/tally";
};

}
4 changes: 4 additions & 0 deletions hosts/coordinator/fleet-deploy.nix
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
let
system = pkgs.stdenv.hostPlatform.system;
deployPackage = inputs.deploy-rs.packages.${system}.deploy-rs;
tallyPackage = inputs.tally.packages.${system}.tally;
failureMarker = "/var/lib/fleet-deploy/fleet-deploy.service.fail";
rollingResolution = lib.concatMapStringsSep "\n" (input: ''
resolved="$(resolve_flake ${lib.escapeShellArg input.url})"
Expand Down Expand Up @@ -192,6 +193,9 @@ in
Type = "oneshot";
User = "tom";
Group = "users";
# Re-check at activation time as well as producer admission so a queued
# or manually started deploy cannot move the pin under an armed campaign.
ExecCondition = "${tallyPackage}/bin/tally --config /home/tom/.config/tally/config.json campaign quiescent --state-dir /home/tom/.local/state/tally";
ExecStart = "${fleetDeploy}/bin/fleet-deploy";
StateDirectory = "fleet-deploy";
StateDirectoryMode = "0755";
Expand Down
3 changes: 3 additions & 0 deletions overlays/default.nix
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ final: prev: {
# Personal git-backed CRM CLI, vendored with its package definition.
crm = final.callPackage ../pkgs/crm/nix/package.nix { };

# Evidence-gated, resumable front door over the music acquisition campaign.
music-acquire = final.callPackage ../pkgs/music-acquire { };

# Headless calendar CLI, vendored with its package definition.
dcal = final.callPackage ../pkgs/dcal/nix/package.nix { };

Expand Down
24 changes: 24 additions & 0 deletions pkgs/music-acquire/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# music-acquire

`acquire` is the durable front door for the music-consolidation acquisition
cascade. It writes an immutable worklist, an append-only evidence ledger, and a
separate archive resume gate under `~/.local/state/music-acquire/<batch>/`.

```text
acquire tracklist worklist.jsonl [--source goldcast|synapson|vent-2024]
acquire soundcloud ARTIST [--likes] [--reposts] [--sets]
acquire bandcamp ARTIST [--alias "Project Pablo"]
acquire ytmusic ARTIST
acquire status [--batch NAME] [--json]
acquire resume --batch NAME
```

Global controls are `--batch`, `--dry-run`, `--limit`, `--no-capture`, and
`--out`. Final downloads always retain the source audio stream; no extraction,
format coercion, or recoding option is used. SoundCloud and YouTube cookies are
copied from agenix into the batch's mode-0600 cookie directory before use.

The calibrated fingerprint and capture engines remain in
`~/mecattaf/music-consolidation/scripts/`; set `MUSIC_CONSOLIDATION_REPO` if that
checkout lives elsewhere. Capture is dispatched to `worker` by default and can
be changed with `MUSIC_ACQUIRE_CAPTURE_HOST`.
8 changes: 8 additions & 0 deletions pkgs/music-acquire/acquire.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
#!/usr/bin/env python3
"""Executable entry point for the packaged music-acquire utility."""

from music_acquire.cli import main


if __name__ == "__main__":
raise SystemExit(main())
74 changes: 74 additions & 0 deletions pkgs/music-acquire/default.nix
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
{
lib,
stdenvNoCC,
makeWrapper,
python3,
bash,
chromaprint,
coreutils,
curl,
ffmpeg,
jq,
nodejs,
openssh,
pipewire,
yt-dlp,
}:
let
python = python3.withPackages (ps: [ ps.websocket-client ]);
in
stdenvNoCC.mkDerivation {
pname = "music-acquire";
version = "2026.08.13";

src = builtins.path {
path = ./.;
name = "music-acquire-src";
};

nativeBuildInputs = [
makeWrapper
python
];

dontBuild = true;
doCheck = true;

checkPhase = ''
runHook preCheck
PYTHONPATH=$PWD ${python}/bin/python -m unittest discover -s tests -v
runHook postCheck
'';

installPhase = ''
runHook preInstall
install -d $out/libexec/music-acquire $out/bin
cp acquire.py $out/libexec/music-acquire/
cp -r music_acquire $out/libexec/music-acquire/

makeWrapper ${python}/bin/python $out/bin/acquire \
--add-flags $out/libexec/music-acquire/acquire.py \
--set FPCALC ${chromaprint}/bin/fpcalc \
--prefix PATH : ${
lib.makeBinPath [
bash
chromaprint
coreutils
curl
ffmpeg
jq
nodejs
openssh
pipewire
yt-dlp
]
}
runHook postInstall
'';

meta = {
description = "Resumable, evidence-gated SoundCloud/YouTube/Bandcamp music acquisition";
mainProgram = "acquire";
platforms = lib.platforms.linux;
};
}
3 changes: 3 additions & 0 deletions pkgs/music-acquire/music_acquire/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
"""Reusable, evidence-gated music acquisition."""

__version__ = "2026.08.13"
Loading