Skip to content

feat: unify state dir to ~/.qmax with first-run migration - #8

Merged
Desperado merged 2 commits into
mainfrom
feat/unify-qmax-dir
Jul 13, 2026
Merged

feat: unify state dir to ~/.qmax with first-run migration#8
Desperado merged 2 commits into
mainfrom
feat/unify-qmax-dir

Conversation

@Desperado

@Desperado Desperado commented Jul 13, 2026

Copy link
Copy Markdown
Contributor

What

Unifies the agent's on-disk state directory to ~/.qmax (state was in ~/.qamax, binary already in ~/.qmax), with a safe first-run migration.

Why

Persistent state — config.json (auth token + agent registration), the receipts/ dir, and the ed25519 receipt signing key — lived in ~/.qamax (historical "QA Max"), while the binary installs to ~/.qmax. The qamax name is legacy; the brand/command is qmax. This removes the split.

Change

  • config.go: configDirName .qamax.qmax.
  • main.go: sets receipt.BaseDir = ~/.qmax and runs migrateLegacyStateDir() first, before any config read or receipt write.
  • migrate.go: recursively merges legacy ~/.qamax state into ~/.qmax (a dir rename won't work — ~/.qmax already exists, holding the binary). Directories are merged file-by-file, never overwriting an existing destination file; best-effort + idempotent — existing logins and the agent's signing identity survive the rename, and legacy receipts stay reachable even when ~/.qmax/receipts already exists.
  • migrate_test.go: covers the flat move + no-clobber + idempotency, the recursive receipts merge with both dirs present (incl. same-named no-clobber), and the no-legacy no-op.

install.sh needs no change — it already uses ~/.qmax.

Verification

  • go build / go vet / golangci-lint / migration tests all green.
  • No receipt-module change needed — the agent sets receipt.BaseDir explicitly.

Note: two TestHeartbeatLoop_* tests are flaky on macOS only (sysmetrics shells a slow top -l 1, eating the test's time budget) — pre-existing, reproduces on main, passes on Linux CI. Unrelated to this change.

Persistent state (config/auth, receipts, the ed25519 signing key) lived in
~/.qamax (historical "QA Max") while the binary installs to ~/.qmax. Unify
everything under ~/.qmax.

- config.go: configDirName .qamax -> .qmax.
- main.go: set receipt.BaseDir = ~/.qmax and run migrateLegacyStateDir() first,
  before any config read or receipt write.
- migrate.go: merge legacy ~/.qamax state into ~/.qmax entry-by-entry (never
  clobbering the binary dir's existing files); best-effort + idempotent, so
  existing logins and the agent signing identity survive the rename.
- install.sh: CONFIG_DIR -> ~/.qmax.
- migrate_test.go: covers the move, no-clobber, idempotency, and no-legacy no-op.

No receipt-module change needed — the agent sets receipt.BaseDir explicitly.
@qualitymaxapp

qualitymaxapp Bot commented Jul 13, 2026

Copy link
Copy Markdown

✅ QualityMax Pipeline

Gate Result
🔍 AI Review ✅ Clean
🧪 Repo Tests ✅ 235/272 passed (go)

Powered by QualityMax — AI-Powered Test Automation

…tranded

The first version skipped a whole legacy subdirectory when the destination
subdirectory already existed — so if ~/.qmax/receipts already existed (e.g. after
an upgrade or an overlapping old daemon), every remaining ~/.qamax/receipts file
became unreachable. Recurse into subdirectories, moving file-by-file and
preserving any destination file. Adds TestMigrateMergesReceiptsRecursively
(both receipts/ dirs present, incl. a same-named no-clobber case).
@Desperado
Desperado merged commit d475a1e into main Jul 13, 2026
5 checks passed
@Desperado
Desperado deleted the feat/unify-qmax-dir branch July 13, 2026 12:20
Desperado added a commit that referenced this pull request Jul 13, 2026
The bump was intended for #8 but missed its squash. Version is the source of
qmax --version and receipts' agent_version; bump before tagging v4.5.0 so the
released binary and the tag agree.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant