From 6af3714bd019bf66c463244b5b2199ef11be226a Mon Sep 17 00:00:00 2001 From: Frank Date: Tue, 20 Oct 2026 15:15:41 -0700 Subject: [PATCH] live: heartbeat sync 2026-10-20T15:15:41-07:00 (Refs #11) --- .../franksign-worktree-db-cred-trap/SKILL.md | 55 ++++++++++++++ .../land-branch-without-checkout/SKILL.md | 45 ++++++++++++ .../typescript-fleet-repo-bootstrap/SKILL.md | 72 +++++++++++++++++++ .../franksign-5veyz1h2yara/state.json | 4 ++ .../architecture.md | 0 .../product.md | 2 + .../state.json | 8 ++- .../style.md | 0 .../state.json | 4 ++ .../.local/state/noctalia/settings.toml | 8 +-- 10 files changed, 193 insertions(+), 5 deletions(-) create mode 100644 agent/managed-skills/franksign-worktree-db-cred-trap/SKILL.md create mode 100644 agent/managed-skills/land-branch-without-checkout/SKILL.md create mode 100644 agent/managed-skills/typescript-fleet-repo-bootstrap/SKILL.md create mode 100644 agent/memories/sharpshooter/franksign-5veyz1h2yara/state.json create mode 100644 agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/architecture.md create mode 100644 agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/product.md create mode 100644 agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/style.md create mode 100644 agent/memories/sharpshooter/wt-20261020-144605-e7c60f6-31xsw83t7yjc6/state.json diff --git a/agent/managed-skills/franksign-worktree-db-cred-trap/SKILL.md b/agent/managed-skills/franksign-worktree-db-cred-trap/SKILL.md new file mode 100644 index 0000000..48a5766 --- /dev/null +++ b/agent/managed-skills/franksign-worktree-db-cred-trap/SKILL.md @@ -0,0 +1,55 @@ +--- +name: franksign-worktree-db-cred-trap +description: "Diagnose franksign e2e seam 5 / health 503 db:down in a fresh worktree: setup-dev.sh minted a password that mismatches the shared franksign-db container." +--- + +# franksign fresh-worktree DB credential trap + +## Symptom +`tests/run.sh` in a fresh franksign worktree fails seam 5 ("e2e server did not +become healthy") while the server log says `franksign-api listening on :3100`. +Manual probe shows the server IS up: + +```bash +PORT=3100 node --env-file=.env apps/api/dist/cli.js >/tmp/manual-e2e.log 2>&1 & +sleep 2; curl -s http://127.0.0.1:3100/health +# -> 503 {"status":"degraded","db":"down",...} +``` + +Not a regression, not a :3100 port collision (check `ss -tlnp | grep 3100` to rule that out). + +## Root cause +`infra/setup-dev.sh` mints a fresh `POSTGRES_PASSWORD` per checkout +(`if [ ! -f infra/postgres.env ]`), but `franksign-db` + `franksign-pgdata` +are shared box state owned by the main checkout +(`~/Projects/franksign`). The new worktree's `.env` DATABASE_URL then fails +TCP auth against the initialized volume. + +The setup script masks it: its readiness gate is +`podman exec franksign-db pg_isready`, which uses the in-container local +socket and passes regardless of password — so setup prints "postgres ready" +while the checkout is dead on arrival. + +## Fix (git-ignored files, no commit needed) +Copy the shared credentials from the owning checkout: + +```bash +grep DATABASE_URL /home/blank/Projects/franksign/.env # source of truth +# PUT that exact DATABASE_URL line into this worktree's .env +# PUT the matching POSTGRES_PASSWORD into this worktree's infra/postgres.env +``` + +Gotcha: the shared password may contain literal `$$`. Keep it byte-for-byte — +systemd `EnvironmentFile` and `node --env-file` both read values literally, +so `$$` in the file IS `$$` in the password. No escaping, no de-escaping. + +## Verify +```bash +PORT=3100 node --env-file=.env apps/api/dist/cli.js & # then +curl -fsS http://127.0.0.1:3100/health # -> {"status":"ok","db":"up"} +tests/run.sh # 14/14 +``` + +## Permanent fix (proposed, not yet landed) +`setup-dev.sh` should reuse `~/.config/containers/systemd/postgres.env` +(symlink to the owning checkout) when present instead of minting new creds. diff --git a/agent/managed-skills/land-branch-without-checkout/SKILL.md b/agent/managed-skills/land-branch-without-checkout/SKILL.md new file mode 100644 index 0000000..06bbc92 --- /dev/null +++ b/agent/managed-skills/land-branch-without-checkout/SKILL.md @@ -0,0 +1,45 @@ +--- +name: land-branch-without-checkout +description: "Open a PR from a shared worktree when workspace policy blocks git checkout/restore: push a named branch ref from HEAD without switching branches." +--- + +# Landing a branch when `git checkout` is policy-blocked + +Shared-workspace policy blocks `git checkout` and `git restore` (working-tree +switches could strand concurrent agents' uncommitted work). You still must ship +the commit on the current worktree branch as a named `chore|feat|fix/-` +branch. Never work around the block — go around it via refs. + +## Sequence + +```bash +# 1. commit only your files (atomic); leave other dirty paths alone +git add && git commit -m "..." + +# 2. branch ref at HEAD — no working-tree change, stays on wt/<...> +git branch /- HEAD +git push origin /- # pre-push hooks still run + +# 3. PR via tracker API with head = pushed ref (see gitea-pr-api-cycle / gh) +``` + +- The worktree stays checked out on `wt/`; the new branch exists + only as the pushed ref (plus a local ref that merges cleanly later). +- `-u` upstream tracking on the wt branch is misleading — skip it; set + `git config branch..remote origin` + `.merge` only if you will + later check the branch out. +- Dirty regenerated fixtures left behind (e.g. `gen:sample` PDFs rewritten + by setup/gate runs): `git restore` is also blocked — do NOT edit-forward + to revert them; report them. They are regenerated on every bootstrap, so + dirt is expected and harmless. + +## Verify + +- `git ls-remote --heads origin ` prints the same sha as `git rev-parse HEAD`. +- PR API returns 201 with `head.sha` equal to that sha. + +## Do NOT + +- `git checkout -b`, `git stash`, `git restore`, `git reset --hard` here — + all working-tree mutations the policy can block, and stashes in a shared + checkout are a cross-agent footgun. diff --git a/agent/managed-skills/typescript-fleet-repo-bootstrap/SKILL.md b/agent/managed-skills/typescript-fleet-repo-bootstrap/SKILL.md new file mode 100644 index 0000000..013bb9d --- /dev/null +++ b/agent/managed-skills/typescript-fleet-repo-bootstrap/SKILL.md @@ -0,0 +1,72 @@ +--- +name: typescript-fleet-repo-bootstrap +description: "Initialize a TypeScript monorepo (Bun workspaces + Turborepo + Biome + Express/Vite + quadlet dev DB + Storybook/Playwright gates) on Frank's fleet, with the traps that cost hours at franksign init." +--- + +# TypeScript fleet repo bootstrap + +Bootstrap a fleet-style TS monorepo the way franksign was initialized (2026-10-20): +Bun workspaces + Turborepo + Biome + Express 5 on Node + Vite/React SPA + quadlet +dev Postgres + Storybook-as-component-test + prod-shaped Playwright e2e, gated by a +single `tests/run.sh` seam runner (serverAppConfigs pattern). + +## Shape + +``` +apps/ homepage (zero-JS), web (Vite+React SPA), api (Express, single origin: /, /app, /api, /health) +packages/ domain libs (each: src/*.ts, tests colocated, tsc -p tsconfig.build.json) +templates/ data the API serves +tests/ run.sh + seams/*.bats + e2e/*.spec.ts + lib/ guards (.mjs) +infra/ quadlet/*.container + setup-dev.sh (idempotent bootstrap) +-docs/ OKF v0.2 KB: index.md, log.md, read-only/ (agent-off-limits) +AGENTS.md git law (trunk-based, --no-ff, explicit merge OK) + TDD tiers + docs law +HANDOFF.md at repo base for worktree-based future sessions +``` + +## Non-obvious traps (all measured on Frank's box, Node 26 / bun 1.4.3 / playwright 1.64) + +- **Playwright `testDir` resolves against process CWD, not the config file.** + Pin the seam to invoke playwright with `cd` into the spec dir. +- **A `testMatch` regex with a leading `^` silently matches nothing** — Playwright + tests it against prefixed paths; "No tests found", zero diagnostics. Anchor only + the trailing `$`. And keep raw `/` out of the pattern if a guard script parses + the config literals. +- **`tsc` with `noEmit: false` but no `rootDir`/`outDir` emits `.js` strays into + `src/`** while package `main` points at `dist/` — the strays resurface on every + build. Pin `rootDir: "src", outDir: "dist", declaration: true` in every + tsconfig.build.json. +- **`bunx ` ignores the workspace install** and pulls its own version (observed + with biome and playwright). Git hooks MUST call `./node_modules/.bin/`. +- **Node 26 rejects `--env-file-if-set`** (no "if-set" variant on that build); + use `--env-file=` — a shell-set env var still wins over file values, so + `PORT=3100 node --env-file=.env dist/cli.js` overrides cleanly. +- **Quadlet resolves `EnvironmentFile=` relative to the UNIT directory**, not the + repo: `setup-dev.sh` must link the env file beside the unit in + `~/.config/containers/systemd/`. Generated quadlet units cannot be + `systemctl --user enable --now`'d — the generator's `default.target.wants` + symlink IS the enablement; plain `start` is enough. +- **`gitignore` rule `.env.*` swallows `.env.example`** — add the `!.env.example` + negation when you write the first ignore file. +- **Gitea 1.27.3 API create-repo with a JSON body can answer 422 `[Name]: Required`** + even when the field is present; probe `/api/v1/repos//` first — it + may already exist (empty = ready for `git push -u origin main`). +- **Biome 2.x**: `biome migrate` needs `--write` (without it, it only prints the + plan) and migrates `rules.recommended` → `rules.preset`; `check --write` skips + `useTemplate`/`noNonNullAssertion` (unsafe) — prefer rewriting `!` assertions to + named lookups so `--unsafe` never touches tests. +- **Grafana-grade gate law** (from serverAppConfigs): every e2e spec must be routed + by a `projects[].testMatch` or it silently never runs — ship a scaffold-guard + script that fails the seam on an orphan spec. + +## Gate wiring + +`tests/run.sh` (bats seams: build, unit, docs-lint, homepage budget, quadlet, +storybook build, e2e) ← pre-push hook; pre-commit = secret-regex scan on staged +diff + `./node_modules/.bin/biome check` on staged code. e2e seam boots the +prod-shaped stack (built assets + Express + quadlet DB on a dedicated port, +health-gated with `curl` before Playwright starts). + +## Session close-out + +log.md entry with `(cwd · session)` footer; HANDOFF.md updated; origin on Gitea +owner `dank`; PR bodies carry the attribution footer. diff --git a/agent/memories/sharpshooter/franksign-5veyz1h2yara/state.json b/agent/memories/sharpshooter/franksign-5veyz1h2yara/state.json new file mode 100644 index 0000000..1aea041 --- /dev/null +++ b/agent/memories/sharpshooter/franksign-5veyz1h2yara/state.json @@ -0,0 +1,4 @@ +{ + "v": 1, + "lastConsolidatedAt": 1792532762570 +} diff --git a/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/architecture.md b/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/architecture.md new file mode 100644 index 0000000..e69de29 diff --git a/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/product.md b/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/product.md new file mode 100644 index 0000000..b2a4c78 --- /dev/null +++ b/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/product.md @@ -0,0 +1,2 @@ +## Handoff Location +- put it at ~/Projects \ No newline at end of file diff --git a/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/state.json b/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/state.json index 4b80be9..30ec72c 100644 --- a/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/state.json +++ b/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/state.json @@ -1,4 +1,10 @@ { "v": 1, - "lastConsolidatedAt": 1792530736757 + "lastConsolidatedAt": 1792534456791, + "lastResult": { + "at": 1792532921161, + "sessions": 1, + "deltas": 1, + "model": "frank-zealot" + } } diff --git a/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/style.md b/agent/memories/sharpshooter/wt-20261020-125416-6d1fc1f-3cjcsma2m7gk5/style.md new file mode 100644 index 0000000..e69de29 diff --git a/agent/memories/sharpshooter/wt-20261020-144605-e7c60f6-31xsw83t7yjc6/state.json b/agent/memories/sharpshooter/wt-20261020-144605-e7c60f6-31xsw83t7yjc6/state.json new file mode 100644 index 0000000..5fb2807 --- /dev/null +++ b/agent/memories/sharpshooter/wt-20261020-144605-e7c60f6-31xsw83t7yjc6/state.json @@ -0,0 +1,4 @@ +{ + "v": 1, + "lastConsolidatedAt": 1792534385325 +} diff --git a/dotfiles/noctalia/.local/state/noctalia/settings.toml b/dotfiles/noctalia/.local/state/noctalia/settings.toml index 9e9181c..b93317f 100644 --- a/dotfiles/noctalia/.local/state/noctalia/settings.toml +++ b/dotfiles/noctalia/.local/state/noctalia/settings.toml @@ -275,13 +275,13 @@ transition = [ "fade" ] interval_seconds = 1200 [wallpaper.default] - path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_1kdgpg.jpg" + path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg" [wallpaper.last] - path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_1kdgpg.jpg" + path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg" [wallpaper.monitors.DP-1] - path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_1kdgpg.jpg" + path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg" [wallpaper.monitors.DP-2] path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_oxex69.jpg" @@ -290,7 +290,7 @@ transition = [ "fade" ] path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_v9e2w3.jpg" [wallpaper.monitors.eDP-1] - path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_1kdgpg.jpg" + path = "/home/blank/.local/share/noctalia/wallpapers/wallhaven_nzz3gy.jpg" [weather] unit = "imperial"