fix: serve healthz path/address and seeder archetype constants

Problem

Three local-server and seeder defects.

  1. serve printed a malformed URL and ignored config. The format string http://localhost%s with addr 127.0.0.1:8080 produced http://localhost127.0.0.1:8080 (two hosts mashed together). Separately, runServe never loaded manifold.yml, so a serve.addr setting was silently ignored even though config.LoadFile already merges it.

  2. Seeder archetypes diverged from the schema constants. internal/seeder/ (seeder.go, users.go, activity.go) hardcoded hyphenated and short labels (solo-contributor, platform-engineer, emerging, dormant) while internal/schema/analyzer.go defines the canonical Personal Access Token user archetype constants Archetype* (solo_contributor, platform_engineer, emerging_user, dormant_expert). Seeded fixtures therefore never matched real analyzer output.

  3. /healthz was reported as always returning 503 because the handler checks <dir>/data/summary.json. Investigation found that path is already correct (see below), so no code change to the handler was warranted; the gap was the absence of a regression test.

Fix

  1. serve: print the real address with http:// + addr, and wire config loading with the same FlagSet.Visit precedence pattern used by collect/run. An explicit --addr flag wins; otherwise the manifold.yml serve.addr (then default) is honored. Address resolution and URL formatting are extracted into pure helpers (resolveServeAddr, serveURL) for direct testing.

  2. seeder: replace every archetype assignment with the matching schema.Archetype* constant via a shared archetypeOrder slice. The username slug now reflects the canonical value (e.g. manifold-solo_contributor-01), valid for GitLab usernames. Existing seeder tests updated to the constants.

  3. healthz: the renderer writes summary.json to OutputDir/data/ (render.go), the dashboard JavaScript fetches data/summary.json (app.src.js), and serve defaults to --dir public, so the served file lives at public/data/summary.json. The handler's <dir>/data/summary.json check is correct. Added regression tests; left the handler unchanged.

Validation

  • make check (go vet plus full test suite): pass on Go 1.24.2.
  • go test -race ./...: pass on Go 1.24.2.

Fails-on-old proofs:

  • seeder: reverting one archetypeOrder entry to solo-contributor makes TestSeededArchetypesMatchSchemaConstants fail (archetypeDistribution(N) produced non-schema archetype "solo-contributor"); restoring the constant passes.
  • healthz: changing the handler to the flat <dir>/summary.json makes TestHealthz_PresentSummary fail with 503 when data is present (want 200, got 503); the existing data/ path passes 200-present / 503-absent. This confirms the flat path is the regression, not the fix.

Tests shipped

  • internal/server/server_test.go: TestHealthz_PresentSummary, TestHealthz_AbsentSummary.
  • cmd/manifold/serve_test.go: TestServeURLWellFormed, TestResolveServeAddr, TestServeConfigAddrHonored.
  • internal/seeder/seeder_test.go: TestSeededArchetypesMatchSchemaConstants plus existing tests migrated to schema constants.

Merge request reports

Loading