feat(init): discovery validation pass + field-report onboarding improvements#58
Conversation
…ck setup A real agent-driven onboarding hit a polyglot monorepo where heavy native toolchains (.NET) and existing host workflows made full containerization the wrong call, but nothing told the agent that running only backing services under hack — with app dev servers on the host pointed at routed services — was a supported, deliberate end state rather than a fallback to fix later. - docs/guides/agent-first-setup.md: add a "Partial adoption" section covering when to choose it, what hack still provides (stable hostnames/TLS, branch instances, committed env, lifecycle hooks), how to wire it, and tradeoffs vs full containerization. - src/agents/onboarding-prompt.ts (Phase 2): add a bullet presenting full containerization vs backing-services-only as an explicit decision, plus a bullet to prefer reusing existing prod Dockerfiles/compose contexts over authoring new dev-mode services from scratch. - src/agents/onboarding-prompt.ts (Phase 1): extend the env-inventory bullet so agents also harvest hack env candidates from compose `environment:` blocks, Dockerfile `ENV` lines, and CI config when a repo has no `.env*` files. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Field repos were shipping duplicated services (web/web-2), everything crammed onto port 3000, silently-wrong bun-node images on non-JS services, and missing backing-service infra (postgres/temporal) — all with zero warnings. Add a validation pass (src/init/validation.ts) that runs after discovery and before compose generation in both the --auto and interactive init paths: - Candidate dedupe: collapse same-package duplicate scripts (dev + start) and drop root-level aggregator scripts that just delegate to a workspace package's own dev script (turbo --filter, dotnet run --project, pnpm --cwd), which is what actually produced the reported web/web-2 and phantom "backend" duplicates. - Port collision handling: reassign colliding HTTP ports to the next free port (ascending) and rewrite the container command. - Runtime detection: flag non-JS services (csproj/fsproj, go.mod, Cargo.toml, pyproject.toml, mix.exs, Gemfile, or command sniffing — including root aggregator commands that target another dir) and use an obviously-wrong alpine:3 placeholder image with a TODO comment instead of silently defaulting to bun-node. - Backing-service detection: surface postgres/mysql/redis/temporal/ kafka/rabbitmq/mongodb signals from dependencies, prisma schema, and .env* key names (values never read) as warnings + a compose header comment, without auto-scaffolding them. - Existing-compose pointer: if a repo-root docker-compose*.yml already exists, point at it as ground truth instead of re-deriving. renderCompose gains header/service comment injection (idempotent post-process over the stringified YAML). buildDiscoveredComposeAuto and ComposeWizardInput are now exported for direct pipeline testing. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Both init paths now tell first-time users/agents that full *.hack routing needs hack global install (sudo, machine-wide DNS/CA) — field agents hit this as a late surprise. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
## 3.3.0 (2026-07-08) * Merge branch 'docs/partial-adoption' into feat/init-discovery-validation ([064db0e](064db0e)) * Merge pull request #58 from hack-dance/feat/init-discovery-validation ([9dd469f](9dd469f)), closes [#58](#58) * feat(init): add post-discovery validation pass for hack init ([6b50b76](6b50b76)) * feat(init): surface the hack global install requirement in init output ([739a581](739a581)) * docs: document partial adoption (backing-services-only) as a valid hack setup ([871a247](871a247))
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 739a581776
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| const dedupe = dedupeCandidates({ candidates: input.candidates }); | ||
| const selectedCandidates = selectAutoCandidates({ | ||
| candidates: input.candidates, | ||
| candidates: dedupe.selected, |
There was a problem hiding this comment.
Preserve distinct root dev: services during auto init*
Here auto init feeds only dedupe.selected into service selection. Because the new package-level dedupe keeps a single script per packageId, a single-package repo with distinct scripts like dev:web and dev:api (not aggregators; no workspace package candidates to match) will generate only one service and silently omit the other. Please keep all distinct dev:* candidates unless they are proven aggregators or true duplicates.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Addressed in PR #59 (or as noted): dedupeCandidatesByPackage now groups by (package, script suffix): distinct dev:web/dev:api scripts in a single-package repo are distinct services and all survive; only same-service variants (dev vs start/serve/watch, same suffix) collapse. Regression test added.
Everything the two field reports (real
hack init --with clauderuns on a polyglot Vite/Astro/Bun/.NET/Temporal monorepo) taught us about init:Discovery validation pass (src/init/validation.ts)
dev:web-style scripts that delegate to workspace packages no longer produce duplicate services (the field repo's web/web-2) or phantom services (a bun-imaged "backend" that actually ran dotnet)--projecttargets): obviously-wrong placeholder image + TODO comment instead of a silently wrong bun-node guessOnboarding improvements
hack global install(sudo)Tests: 12 new validation tests on a polyglot fixture modeled on the field repo; full suite 805/0; e2e green.
🤖 Generated with Claude Code