--- name: wf-new description: 'WellForge command — Scaffold a new WellForge project — interview, stack recommendation, generation, connections. Invoke explicitly: $wf-new (optional — interview fills the gaps)' --- > WellForge command, generated for Codex from `wellforge-plugin/commands/new.md` — do not edit; regenerate with `adapters/codex/generate.py`. > Invoked as `$wf-new (optional — interview fills the gaps)`. **ARGUMENTS** below means the text the user wrote after `$wf-new` in the invoking message (empty if nothing). Scaffold a new WellForge project end-to-end: analyze what's being built, recommend a stack, generate from the versioned template, verify it builds, and guide tool connections (load the **connections** skill for that last stage). Product: ARGUMENTS ## Stage 1 — Understand the product Interview with AskUserQuestion (batch, max 2 rounds). You need: - Product type: internal tool / customer-facing app / API-only service / prototype — or **infrastructure** (the cloud resources an app runs on, rather than the app). Ask this explicitly: an IaC project is a first-class preset here, and a user who says "set up our GCP environment" will otherwise be pushed toward an application stack they didn't ask for. - Scale & lifetime: throwaway experiment vs long-lived product; expected load. - Domain complexity: rich domain logic and transactions vs thin CRUD/aggregation. - Team & ecosystem constraints: who maintains it, existing systems it must talk to. - Anything already decided (DB, hosting, auth provider) — record as constraints. From the "scale & lifetime" answer, also settle the **rigor tier** (load the **rigor-tiers** skill; it becomes the project default in `.forge/manifest.json`): - throwaway experiment / feasibility PoC → `spike` - first release to validate with users → `mvp` - long-lived product / critical use case → `production` (default) State the tier you'll use and why; the user can override. It sets how strict generated CI is (`spike` = build + secret-scan floor; `mvp` = coverage advisory; `production` = full gates) and can be raised later with `$wf-promote`. ## Stage 2 — Recommend a stack **The preset list is the root `copier.yml`'s `preset:` choices — read it, don't trust this table's age.** Never invent a preset that isn't in that list; if the two disagree, `copier.yml` wins and this table is the bug. As of writing, three: | Preset | Sweet spot | |---|---| | `spring-kotlin-react` | rich domain logic, transactions, long-lived products, JVM ecosystem integration, Spring Modulith boundaries | | `hono-react` | lightweight APIs, fast iteration, prototypes→small products, all-TypeScript team, edge/container deploys | | `pulumi-gcp-ts` | **infrastructure, not an application** — Pulumi IaC in TypeScript on GCP: stacks, ComponentResources, CrossGuard policy, mock tests | The first two are alternatives to each other; `pulumi-gcp-ts` is **orthogonal** to both — it answers "what runs this", not "what is this". So: - Application project → recommend ONE of the two app presets with a 3-5 line rationale tied to the interview answers, and say why not the other. - Infrastructure project → `pulumi-gcp-ts`. Do not "fall back" to an app preset. - Both needed (an app *and* its infra) → they are two projects, and this command does one per invocation (hard rules). Scaffold the one they need first, and tell them the exact second command to run for the other. - Genuinely fits none (mobile, ML pipeline, desktop) → say so and stop; don't force a preset. "Fits none" now means none of **three**, and an infra project is no longer one of them. User confirms or overrides; their choice wins. ## Stage 3 — Generate 1. Locate the wellforge repo (checkout path or git URL — ask once, remember for the session). The template source is the REPO ROOT: one `copier.yml` serves all presets. 2. Collect the answers (read the root `copier.yml` for the full list — questions are preset-conditional, so let the file tell you which apply): always `preset`, `project_name`, `project_slug`, `description`, `ci`, `rigor`; plus `base_package` for `spring-kotlin-react`, `db` for the two app presets, and `gcp_project` + `gcp_region` for `pulumi-gcp-ts` (which has no `db`). 3. Run, from the target parent directory: ```bash uvx copier copy --trust \ --data preset= --data project_name=... [--data ...] ``` (requires `uv`; if missing: `brew install uv` or `mise use -g uv`.) Prefer the git URL over a local path once wellforge is hosted — it makes `$wf-upgrade` work for every team member, not just this machine. 4. **Stamp the plugin version into `.forge/manifest.json`** — copier cannot, and this is the only record of which plugin set the project up (its `AGENTS.md` conventions, spec formats, trace schema and hooks all move with the plugin): ```jsonc // added to the generated manifest, alongside template/version/answers "plugin": { "version": "", "set_by": "new", "at": "", "marketplace": "" } ``` Read the version from the installed plugin's own `.claude-plugin/plugin.json` — never from memory, and never a copier answer (a persisted answer would replay the scaffold-time version forever; see the template-contract skill for why). Record **where the plugin came from** too, in the same object: ```bash # marketplace install → "wellforge@wellforge"; nothing here → "local" (--plugin-dir) jq -r '.plugins | keys[] | select(startswith("wellforge@"))' \ ~/.claude/plugins/installed_plugins.json 2>/dev/null | head -1 ``` A project set up by a checkout and a project set up by a published release are different provenance, and only one of them can be reproduced by a teammate. `$wf-doctor` reports it; if it is `local`, doctor says so rather than implying the release is pinned. 5. Initialize: `git init -b main && git add -A && git commit -m "chore: scaffold from