20 KiB
Claude Code Prompt: [Feature / Fix Name]
0. Task class & scope
- Implementation — code change with unit-test coverage; build + deploy + verify. (All sections.)
- Spike — empirically validate an unproven mechanism BEFORE any production spec is written.
Output is a findings doc in
felhom.eu/documentation/audits/SPIKE-<topic>-<date>.md, not shipped production code. (§1, §2, §3, §4, §13-verify, §15. Skip §5-§12 unless the spike writes throwaway probes.) - Risky / supervised — touches agent / golden image / provisioning / destructive disk ops, or
anything that mutates real customer data. Spec it; implement during the supervised session itself,
directly on
main. Mandatory STOP point in §13. (All sections + §13 STOP is load-bearing.) - Runbook-style validation — see note above; prefer a RUNBOOK-*.md.
Repos touched (check all — each gets its own baseline, green gate, build/deploy, and wrap-up):
felhom-controller(in-guest; Docker-only; no Proxmox creds) — app domainfelhom-agent(host; operator-tier; owns ALL Proxmox interaction)felhom.eu(hub/,website/,documentation/)app-catalog-felhom.eu(compose templates +.felhom.yml)
Don't confuse the two ex-"controllers": felhom-agent (host, was
proxmox-controller) vs this felhom-controller (in-guest, wasdeploy-felhom-compose). Host/disk/Proxmox/Cloudflare logic lives in the agent; the controller keeps stack/deploy/UI/app-data-backup/metrics/git-sync/notifications.
1. Confirmed baselines (anti-drift anchor — MANDATORY)
| Repo | main @ commit |
Current version | → Target version |
|---|---|---|---|
| felhom-controller | <hash> |
v0.XX.0 |
v0.XX+1.0 |
| felhom-agent | <hash> |
v0.YY.0 |
v0.YY+1.0 |
| felhom.eu (hub) | <hash> |
v0.ZZ.0 |
v0.ZZ+1.0 |
An unpushed change does not exist for validation or deployment. CC commits directly to main
(trunk-based — no feature/fix branches). If a change can't be cleanly shipped, revert + report;
never park it on a branch.
2. Overview
3. Spike-first gate
- Does this rely on any unvalidated mechanism? yes / no
- If yes: is it already validated in a spike doc? Cite it:
felhom.eu/documentation/audits/SPIKE-.... - If yes and not validated: STOP — switch task class to Spike. Do not spec production code on assumptions.
4. Read these files first
e:\git\CLAUDE.md— workspace orientation (the felhom system, shared conventions, access).<repo>/CLAUDE.md— repo build/deploy, code-quality rules, trunk-based + live-validation rules.<repo>/CONTEXT.md— current project state / decisions / roadmap.felhom.eu/documentation/architecture/02-controller-module-map.md— KEEP/PORT/DELETE/MODIFY per-package classification. Read before touchingbackup/,storage/,system/,config/.felhom.eu/documentation/controller/<feature>.md— code-verified feature docs (authoritative; match code, not summaries, if they drift).controller/README.md(orfelhom-agent/README.md) — module map, feature reference, REST API.- [exact source file(s) to modify] — [why it's relevant].
- [exact source file(s) to depend on] — [why it's relevant].
5. Existing functions / helpers to reuse (MUST use — do NOT reinvent)
| Symbol | File (landmark) | Signature / use | Modify? |
|---|---|---|---|
Manager.StopStack |
internal/stacks/manager.go (~L682) |
StopStack(name string) error — idempotent |
No |
Manager.RedeployFromEnv |
internal/stacks/deploy.go (~L478) |
writes app.yaml then compose up -d + post-start status |
No |
appbackup.AppDataDir |
internal/.../paths.go |
namespace+app → data dir | No |
writeDiskJSON |
internal/.../agent_disk_handlers.go |
JSON envelope for disk endpoints | No |
| [helper that needs a change] | path/file.go |
Func(args) |
Yes — add intent param; gate on IntentEnrolled |
Do NOT reuse: [name the dangerous-lookalike + why], e.g. rsyncMirror (has --delete).
6. Pattern references (copy structure from these canonical files)
| Pattern | Canonical file | Key traits to copy |
|---|---|---|
| REST handler | internal/api/router.go + a sibling handler |
stdlib net/http, JSON envelope, error logging |
| Local-API disk handler | internal/localapi/disks.go (handleDiskEject) |
withGuest, scopedFromBody, role gate, fail-safe-to-protected |
| Scheduler job | internal/.../scheduler |
register + skip-if-running, graceful shutdown |
| Crash-safe journal | internal/stacks/backup.go |
journal-before-mutate, atomic tmp+fsync+rename, Recover on startup |
| Unit test | internal/.../*_test.go (a recent non-hollow one) |
t.TempDir(), fakes/seams, effect assertions |
| HTML template | internal/web/templates/*.html |
Hungarian UI, Go template funcs, no inline secrets |
7. Integration scenarios (must pass)
Scenario A — [happy path]
Given: [concrete state]
When: [exact endpoint / CC action]
Then:
- [effect 1 — exact value/state]
- [effect 2]
- [the WRONG outcome this must NOT produce]
Scenario B — [alternative / role / mode]
Given: [what differs from A]
When: [action]
Then: [how outcomes differ and WHY]
Scenario C — [error / boundary / security gate]
Given: [bad input / unauthorised actor / data-bearing device]
When: [action that must be refused]
Then: [exact refusal — HTTP status, error, and the proven non-effect, e.g. "mkfs NOT called"]
8. Edge cases & deduplication rules
| Condition A | Condition B | Result |
|---|---|---|
9. Strict rules
- Green gate (Go): after every commit/phase, in each touched repo:
go build ./... && go vet ./... && go test ./...— all green before proceeding. The build IS the typecheck; do not accumulate compile errors. - Minimal changes: build only what's listed. No "while I'm here" refactors. Note anything worth fixing under "Observations" (§15) — don't act on it.
- No silent failures: never swallow a parse/exec error — log it. Check a subprocess's own exit
code; never pipe in a way that hides a 127. (The silent
.felhom.ymlquoting bug + the spike's exit-swallow lesson.) - Secrets safety: log env var keys, never values. Never write secrets (tokens, passwords,
keys) into
CHANGELOG.md,REPORT.md, or any committed file — reference as "stored out-of-band". - Line numbers are landmarks: reference code by symbol/landmark; reconfirm the line in the real source before editing (bundled files ≠ source files).
- Trunk-based: commit directly to
main. No branches. Can't ship cleanly → revert + report. - Version discipline: never
:latest; bump the version on every task; one CHANGELOG entry per shippable change; overwrite REPORT.md. - Coding standards: follow
<repo>/CLAUDE.md(cross-cutting) and the feature doc / README for domain patterns.
10. Non-hollow test discipline (MANDATORY for any correctness/security fix)
- Assert the effect happened, not just absence of error. Security example: prove
mkfswas NOT called on a data-bearing device by inspecting the device/fake state — not by trusting the caller. - Companion red-proof: for every correctness fix, write the test so it FAILS on the pre-fix / trivial implementation. Demonstrate this: run the mutation (or guard-removed shape), confirm the test fails, revert. State the result in §15.
- FS work uses
t.TempDir(); orchestration uses fakes/seams (introduce a smallstackOps/copierinterface so tests don't shell out to docker/rsync). - Generation/idempotency: assert the negative (e.g. "fetch count does NOT increment on an
unchanged heartbeat"; "a re-run finds its own prior
(N)and adds no(1)(1)").
Part 1: [Foundation / engine]
1.1 [Task]
File(s): path/file.go
Problem: [what's wrong / what to build, and why]
DO: [explicit positive instructions; tricky code snippets only — CC fills the obvious parts]
DO NOT: [the specific anti-pattern for THIS task]
Crash-safety (if stateful): journal-before-mutate; atomic tmp+fsync+rename; Recover on startup;
guaranteed cleanup via defer; single-flight mutex; ListLXC-style ground truth in recovery.
Green gate: go build ./... && go vet ./... && go test ./internal/<pkg>/
Part 2: [Core logic / external surface]
2.1 [Task]
Phase order (risky surfaces): Phase A structural → validate → Phase B security/external surface.
Green gate: full go test ./...
Part 3: [Web / UI — if touched]
3.1 [Task]
Hungarian strings: "[exact copy]" — e.g. "Adatok másolása: (X% — Y/Z GB)…".
Green gate: go build ./... + go test ./...
Part N: Documentation & versioning
N.1 CHANGELOG.md (each touched repo)
Cumulative, newest entry on top. New version number. Cite the files/commits for each item.
N.2 REPORT.md (each touched repo) — OVERWRITE
Most-recent implementation only (not cumulative). MUST contain: confirmed baselines, per-commit hashes, per-test results, deployed versions, and an explicit "NOT yet live-validated — awaiting supervised [Bx]" list. No secrets.
N.3 CONTEXT.md
Decisions made, architectural state, what's next.
N.4 README / architecture docs
<repo>/README.md if architecture/features changed; authoritative architecture/feature docs in
felhom.eu/documentation/{architecture,controller}/. Spikes/audits → felhom.eu/documentation/audits/.
N.5 Website version bump (if controller/hub version is shown on the site).
11. Tests
Test Group A — [Scenario A]
- setup (t.TempDir / fakes)
- action (the exact call)
- assert (effects, exact values/counts)
- companion: [mutation that makes it fail on pre-fix code]
Test Group B — [Scenario B]
Test Group C — [Scenario C — error/security gate]
12. What NOT to do
- Do NOT [specific out-of-scope thing CC might build].
- Do NOT touch [the untouchable: e.g. the operator-signed
DecommissionExecutor/classify.go]. - Do NOT reuse [the dangerous lookalike from §5].
- Do NOT refactor nearby code, change passing tests, or create a branch.
- Do NOT add "Co-Authored by..." anywhere
13. Build / deploy / STOP
Controller (build server 192.168.0.180 → guest via golden/bootstrap):
SSH=/c/Windows/System32/OpenSSH/ssh.exe
# build + push
$SSH kisfenyo@192.168.0.180 "cd ~/build/felhom-controller && git -C ~/git/felhom-controller pull && ./build.sh <VER> --push"
# deploy to guest (golden/bootstrap): docker pull → write /etc/felhom-controller-image → restart bootstrap svc
# verify:
$SSH kisfenyo@<guest> "docker ps --filter name=felhom-controller --format '{{.Image}} {{.Status}}' && docker logs felhom-controller --tail 20"
Agent (build + push felhom-agent:<VER>; deploy to felhom-pve: backup prior binary, replace,
restart service; verify clean restart — e.g. ReassertGuestBinds does not rebind a non-enrolled drive).
Hub (felhom.eu/hub/): build + push, then
$SSH kisfenyo@192.168.0.180 "sudo kubectl set image -n felhom-system deploy/hub hub=...:<VER>" + verify pods/logs.
Live validation rule: if validating a user-facing feature, exercise the real server pipeline
(connect → enroll → deploy), or invoke the exact endpoint the UI invokes (acceptable proxy — no
server logic skipped). Do NOT hand-set state via raw agent attach (the F9 bypass). Browser
automation (claude-in-chrome) is available for true UI coverage — say which method was used.
STOP point (risky/supervised tasks): build + unit-test + build/deploy images, but do NOT run a
live destructive op or migrate real customer data — that is the supervised [Bx] step. Throwaway
marker dirs under a scratch /mnt path are OK only if they touch no enrolled customer data.
14. Implementation order
Phase 1: [Part 1] → go build ./... && go vet ./... && go test ./internal/<pkg>/
Phase 2: [Part 2] → full go test ./...
Phase 3: [Part 3 — UI] → go build ./... && go test ./...
Phase N-1: [Tests] → full go test ./... (all green)
Phase N: [Build/deploy/verify + docs + push to main]
15. Final verification & deliverables
Run, per touched repo: go build ./... && go vet ./... && go test ./...
Report MUST include:
- Confirmed baselines used (repo @ hash, version).
- Files created / modified (paths).
- Per-commit hashes pushed to
main. - Per-test results (name → pass/fail) + the §10 companion red-proof outcomes.
- Test count before / after; all green (or list failures).
- Deployed versions +
docker ps/ agent-service / hub-pod verification output. - NOT yet live-validated — awaiting supervised [Bx]: explicit list (the real put-data → operate → integrity flow).
- Observations: out-of-scope items noticed — documented, NOT acted on.