Files
command-center/agent/managed-skills/fleet-service-precommit-iteration/SKILL.md
T
Frank 135bb2194d agent: repoint roles to frank-medium/dankclaw-3090; sync niri tweaks, memories, managed skills
- config.yml: default/commit -> frank-medium (dankserver); task/tiny/smol/vision -> frank-small (dankclaw-3090); vision xhigh
- models.yml: add llamacpp (dankclaw-3090) provider; frank-large preserve_thinking + context notes
- niri: focus-ring/border/shadow layout, hot-corners off, re-add noctalia.kdl include; blankpad eDP-1 scale 1.0
- memories: flush rollouts; retire frank_large + marreta_authentik skills; add auth-chain/kv-pool/quadlet-log skills
- managed-skills: 40+ new fleet runbook skills
- agent/skills: import built-in skill set
2026-09-17 12:27:08 -07:00

65 lines
3.5 KiB
Markdown

---
name: fleet-service-precommit-iteration
description: "Iterate on a service that lives in the serverAppConfigs git checkout on a fleet host (dankclaw/dankserver) before committing: ship files for live testing, keep the checkout pullable, then commit and deploy — covers the untracked-files pull trap that recurs every session."
---
# Iterating on a fleet service before you commit
This repo's contract is git → `deploy.sh` → host. But live testing needs the new
file *on the host* before it is committed, and the naive way (copy it into the
host checkout) blocks the very deploy that would install it. This is the loop
that works, plus the traps that cost real time.
## The loop
1. Edit in the local repo. Run the seams: `./tests/run.sh`.
2. Ship the working files to the host **for testing**:
`cat local/file | ssh <host> 'cat > /home/dank/serverAppConfigs/<path>'`
(then `chmod +x` if it is executed — scp/`cat >` drops the exec bit, and a
container entrypoint mounted from that path fails with status 126, "command
found but not executable").
3. Test against the live service; iterate until it works.
4. **Before committing**, prove the host copy is byte-identical to what you are
about to commit: `sha256sum` locally and on the host. If they differ, you are
about to lose work in step 5.
5. Commit and push.
6. Clean the host checkout so the deploy can pull:
- untracked hand copies → move them out of the checkout
(`mkdir -p /tmp/handcopy && mv <paths> /tmp/handcopy/`);
- modified tracked files → `git checkout -- <paths>` (this *discards* the
hand copy, which is safe only because of step 4);
- confirm with `git status --short` printing nothing.
7. `./scripts/deploy.sh <target> --service <svc>` — it pushes, pulls ff-only,
installs units/config, restarts, waits for health, then runs the Playwright
e2e gate.
## Traps, in the order they bite
- **The pull aborts on hand copies.** `deploy.sh` pulls with ff-only and git
refuses: *"The following untracked working tree files would be overwritten by
merge"*. Any untracked file in the checkout whose path the pull wants to
create stops the deploy — which is exactly the file you just shipped. Always
do step 6.
- **`git checkout --` silently eats uncommitted work.** Without step 4 you can
destroy the only copy of an edit that exists nowhere else.
- **A runtime mounts files *straight out of the checkout*.** Here
`dankserver/frank-medium/**` and `shared/grafana/provisioning/**` are mounted
read-only into containers, so a hand copy takes effect at the next container
restart with no deploy. Test that way, then let the deploy make it official.
- **Root-owned files from a container write** (e.g. a patched `.so` produced
inside a build container) can land in the checkout as `root:root`; `chown` them
back to the deploy user before git operations.
- **A restart is not a verification.** Health endpoints answer from a stale
process, a proxied service can be served by a peer, and a provisioned
dashboard may live in unified storage rather than the SQLite table you grep.
Verify the *specific* claim: the new code path's own output, the file's
checksum on the host, the API that serves the resource.
## Why not keep a scratch copy on the host?
Because the deployed artifact must be the committed one. Iterating outside git
(the `/tmp` loop is fine for *probes*) is for measurement scripts; anything the
service actually runs has to land in the checkout, and the checkout has to stay
pullable. Two directories, one rule: probes may live anywhere, runtime state
lives in git.