@starlein/paperclip-plugin-company-wizard 0.4.17 → 0.4.20

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (47) hide show
  1. package/CHANGELOG.md +91 -0
  2. package/README.md +11 -8
  3. package/dist/manifest.js +3 -1
  4. package/dist/manifest.js.map +2 -2
  5. package/dist/ui/index.css +9 -0
  6. package/dist/ui/index.css.map +2 -2
  7. package/dist/ui/index.js +164 -9
  8. package/dist/ui/index.js.map +4 -4
  9. package/dist/worker.js +2401 -635
  10. package/dist/worker.js.map +4 -4
  11. package/package.json +21 -21
  12. package/templates/bootstrap-instructions.md +0 -5
  13. package/templates/modules/auto-assign/agents/ceo/skills/auto-assign.fallback.md +2 -1
  14. package/templates/modules/auto-assign/skills/auto-assign.md +1 -0
  15. package/templates/modules/backlog/agents/ceo/skills/backlog-health.fallback.md +1 -0
  16. package/templates/modules/backlog/module.meta.json +2 -1
  17. package/templates/modules/backlog/skills/backlog-health.md +3 -1
  18. package/templates/modules/dependency-management/agents/security-engineer/skills/dependency-audit.fallback.md +18 -0
  19. package/templates/modules/game-design/agents/engineer/skills/game-design.fallback.md +17 -0
  20. package/templates/modules/github-repo/agents/engineer/skills/git-workflow.md +1 -1
  21. package/templates/modules/github-repo/docs/git-workflow.md +2 -2
  22. package/templates/modules/pr-review/README.md +2 -2
  23. package/templates/modules/pr-review/agents/code-reviewer/skills/code-review.md +3 -3
  24. package/templates/modules/pr-review/agents/engineer/skills/pr-workflow.md +6 -6
  25. package/templates/modules/pr-review/docs/pr-conventions.md +2 -2
  26. package/templates/modules/stall-detection/agents/ceo/skills/stall-detection.md +20 -17
  27. package/templates/modules/triage/agents/engineer/skills/issue-triage.fallback.md +20 -0
  28. package/templates/roles/audio-designer/HEARTBEAT.md +2 -2
  29. package/templates/roles/ceo/HEARTBEAT.md +2 -2
  30. package/templates/roles/ceo/role.meta.json +1 -1
  31. package/templates/roles/cmo/HEARTBEAT.md +2 -2
  32. package/templates/roles/code-reviewer/AGENTS.md +1 -1
  33. package/templates/roles/code-reviewer/HEARTBEAT.md +3 -2
  34. package/templates/roles/cto/HEARTBEAT.md +2 -2
  35. package/templates/roles/cto/role.meta.json +1 -1
  36. package/templates/roles/customer-success/HEARTBEAT.md +2 -2
  37. package/templates/roles/devops/HEARTBEAT.md +2 -2
  38. package/templates/roles/engineer/HEARTBEAT.md +3 -2
  39. package/templates/roles/game-artist/HEARTBEAT.md +2 -2
  40. package/templates/roles/game-designer/HEARTBEAT.md +2 -2
  41. package/templates/roles/level-designer/HEARTBEAT.md +2 -2
  42. package/templates/roles/product-owner/HEARTBEAT.md +2 -2
  43. package/templates/roles/qa/HEARTBEAT.md +2 -1
  44. package/templates/roles/security-engineer/HEARTBEAT.md +2 -2
  45. package/templates/roles/technical-writer/HEARTBEAT.md +2 -2
  46. package/templates/roles/ui-designer/HEARTBEAT.md +2 -2
  47. package/templates/roles/ux-researcher/HEARTBEAT.md +2 -2
package/dist/ui/index.js CHANGED
@@ -581,7 +581,7 @@ var __iconNode45 = [
581
581
  var Zap = createLucideIcon("zap", __iconNode45);
582
582
 
583
583
  // src/ui/components/WizardShell.tsx
584
- import { useEffect as useEffect9 } from "react";
584
+ import { useEffect as useEffect9, useRef as useRef8 } from "react";
585
585
 
586
586
  // src/ui/context/WizardContext.tsx
587
587
  import { createContext, useCallback, useContext, useState } from "react";
@@ -650,7 +650,9 @@ var initialState = {
650
650
  goals: [],
651
651
  projects: [],
652
652
  issues: [],
653
- ceoAdapter: { type: "codex_local", cwd: "", model: "gpt-5.5" },
653
+ // model is an optional override; empty means "use the adapter-appropriate default"
654
+ // (gpt-5.6 for Codex, claude-opus-4-8 for Claude) resolved in buildCeoAdapterConfig.
655
+ ceoAdapter: { type: "codex_local", cwd: "", model: "" },
654
656
  existingCompanyId: "",
655
657
  presetName: "",
656
658
  selectedModules: [],
@@ -679,6 +681,8 @@ function reducer(state, action) {
679
681
  }
680
682
  case "GO_TO":
681
683
  return { ...state, step: action.step, error: null };
684
+ case "RESTORE_NAV":
685
+ return { ...state, path: action.path, step: action.step, error: null };
682
686
  case "SET_COMPANY_NAME":
683
687
  return { ...state, companyName: action.value };
684
688
  case "SET_GOALS":
@@ -4024,6 +4028,19 @@ CardFooter.displayName = "CardFooter";
4024
4028
 
4025
4029
  // src/ui/components/steps/StepOnboarding.tsx
4026
4030
  import { Fragment, jsx as jsx3, jsxs } from "react/jsx-runtime";
4031
+ async function upgradeInstalledPlugin(pluginId, version) {
4032
+ const response = await fetch(`/api/plugins/${encodeURIComponent(pluginId)}/upgrade`, {
4033
+ method: "POST",
4034
+ headers: { "Content-Type": "application/json" },
4035
+ credentials: "include",
4036
+ body: JSON.stringify({ version })
4037
+ });
4038
+ if (!response.ok) {
4039
+ const body = await response.json().catch(() => null);
4040
+ throw new Error(body?.error || `Plugin upgrade failed (${response.status})`);
4041
+ }
4042
+ return response.json();
4043
+ }
4027
4044
  function PathCard({
4028
4045
  icon: Icon2,
4029
4046
  title,
@@ -4060,9 +4077,12 @@ function StepOnboarding() {
4060
4077
  const dispatch = useWizardDispatch();
4061
4078
  const refreshTemplates = usePluginAction("refresh-templates");
4062
4079
  const checkUpdate = usePluginAction("check-update");
4080
+ const preparePluginUpdate = usePluginAction("prepare-plugin-update");
4063
4081
  const [refreshing, setRefreshing] = useState2(false);
4064
4082
  const [refreshMsg, setRefreshMsg] = useState2(null);
4065
4083
  const [updateInfo, setUpdateInfo] = useState2(null);
4084
+ const [pluginUpdating, setPluginUpdating] = useState2(false);
4085
+ const [pluginUpdateMsg, setPluginUpdateMsg] = useState2(null);
4066
4086
  useEffect(() => {
4067
4087
  let cancelled = false;
4068
4088
  checkUpdate({}).then((result) => {
@@ -4090,6 +4110,43 @@ function StepOnboarding() {
4090
4110
  setRefreshing(false);
4091
4111
  }
4092
4112
  };
4113
+ const handlePluginUpdate = async () => {
4114
+ setPluginUpdating(true);
4115
+ setPluginUpdateMsg("Updating templates...");
4116
+ try {
4117
+ const prepared = await preparePluginUpdate({});
4118
+ if (!prepared?.ok) {
4119
+ throw new Error(prepared?.error || "Could not prepare plugin update");
4120
+ }
4121
+ if (!prepared.updateAvailable) {
4122
+ setUpdateInfo({
4123
+ ok: true,
4124
+ currentVersion: prepared.currentVersion,
4125
+ latestVersion: prepared.latestVersion,
4126
+ updateAvailable: false
4127
+ });
4128
+ setPluginUpdateMsg("Templates updated. Plugin is already current.");
4129
+ return;
4130
+ }
4131
+ if (!prepared.pluginId || !prepared.latestVersion) {
4132
+ throw new Error("Could not resolve installed plugin record or target version");
4133
+ }
4134
+ setPluginUpdateMsg(`Installing Company Wizard ${prepared.latestVersion}...`);
4135
+ await upgradeInstalledPlugin(prepared.pluginId, prepared.latestVersion);
4136
+ setUpdateInfo({
4137
+ ok: true,
4138
+ currentVersion: prepared.latestVersion,
4139
+ latestVersion: prepared.latestVersion,
4140
+ updateAvailable: false
4141
+ });
4142
+ setPluginUpdateMsg("Plugin updated. Reloading...");
4143
+ window.setTimeout(() => window.location.reload(), 1200);
4144
+ } catch (err) {
4145
+ setPluginUpdateMsg(err instanceof Error ? err.message : "Plugin update failed");
4146
+ } finally {
4147
+ setPluginUpdating(false);
4148
+ }
4149
+ };
4093
4150
  return /* @__PURE__ */ jsxs("div", { className: "space-y-8", children: [
4094
4151
  /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
4095
4152
  /* @__PURE__ */ jsx3("h1", { className: "text-2xl font-semibold tracking-tight", children: "Create a company" }),
@@ -4147,7 +4204,7 @@ function StepOnboarding() {
4147
4204
  "button",
4148
4205
  {
4149
4206
  onClick: handleRefresh,
4150
- disabled: refreshing,
4207
+ disabled: refreshing || pluginUpdating,
4151
4208
  className: "flex items-center gap-1.5 text-xs text-muted-foreground hover:text-foreground transition-colors disabled:opacity-50",
4152
4209
  children: [
4153
4210
  /* @__PURE__ */ jsx3(RefreshCw, { className: cn("h-3 w-3", refreshing && "animate-spin") }),
@@ -4163,14 +4220,28 @@ function StepOnboarding() {
4163
4220
  updateInfo.currentVersion,
4164
4221
  " \u2192 ",
4165
4222
  updateInfo.latestVersion,
4223
+ /* @__PURE__ */ jsxs(
4224
+ "button",
4225
+ {
4226
+ type: "button",
4227
+ onClick: handlePluginUpdate,
4228
+ disabled: pluginUpdating,
4229
+ className: "inline-flex items-center gap-1 font-medium text-foreground hover:underline disabled:opacity-50 disabled:no-underline",
4230
+ title: "Install the latest Company Wizard plugin, refresh templates, and reload",
4231
+ children: [
4232
+ /* @__PURE__ */ jsx3(RefreshCw, { className: cn("h-3 w-3", pluginUpdating && "animate-spin") }),
4233
+ pluginUpdating ? "Updating..." : "Update now"
4234
+ ]
4235
+ }
4236
+ ),
4166
4237
  updateInfo.url && /* @__PURE__ */ jsxs(
4167
4238
  "a",
4168
4239
  {
4169
4240
  href: updateInfo.url,
4170
4241
  target: "_blank",
4171
4242
  rel: "noreferrer",
4172
- className: "inline-flex items-center gap-0.5 font-medium text-foreground hover:underline",
4173
- title: "Update the Company Wizard plugin package, then reload Paperclip",
4243
+ className: "inline-flex items-center gap-0.5 text-muted-foreground hover:text-foreground hover:underline",
4244
+ title: "Open the npm package page",
4174
4245
  children: [
4175
4246
  "npm",
4176
4247
  /* @__PURE__ */ jsx3(ExternalLink, { className: "h-3 w-3" })
@@ -4179,6 +4250,16 @@ function StepOnboarding() {
4179
4250
  )
4180
4251
  ] })
4181
4252
  ] }),
4253
+ pluginUpdateMsg && /* @__PURE__ */ jsx3(
4254
+ "span",
4255
+ {
4256
+ className: cn(
4257
+ "basis-full text-center text-xs",
4258
+ pluginUpdateMsg.includes("failed") || pluginUpdateMsg.includes("Could not") ? "text-destructive" : "text-muted-foreground"
4259
+ ),
4260
+ children: pluginUpdateMsg
4261
+ }
4262
+ ),
4182
4263
  refreshMsg && /* @__PURE__ */ jsx3("span", { className: "text-xs text-muted-foreground", children: refreshMsg })
4183
4264
  ] })
4184
4265
  ] });
@@ -4302,6 +4383,13 @@ var ADAPTER_TYPES = [
4302
4383
  { value: "openclaw_gateway", label: "OpenClaw", desc: "OpenClaw gateway" },
4303
4384
  { value: "hermes_local", label: "Hermes", desc: "Local Hermes agent" }
4304
4385
  ];
4386
+ var MODEL_SUGGESTIONS = {
4387
+ codex_local: ["gpt-5.6", "gpt-5.6-sol", "gpt-5.6-terra", "gpt-5.6-luna", "gpt-5.5", "gpt-5.4"],
4388
+ claude_local: ["claude-opus-4-8", "claude-fable-5", "claude-mythos-5", "claude-sonnet-4-6"]
4389
+ };
4390
+ function modelSuggestionsFor(adapterType) {
4391
+ return MODEL_SUGGESTIONS[adapterType] ?? [];
4392
+ }
4305
4393
  function StepName() {
4306
4394
  const state = useWizard();
4307
4395
  const dispatch = useWizardDispatch();
@@ -4396,11 +4484,18 @@ function StepName() {
4396
4484
  /* @__PURE__ */ jsx6(
4397
4485
  Input,
4398
4486
  {
4399
- placeholder: "gpt-5.5",
4487
+ list: "ceo-model-suggestions",
4488
+ placeholder: modelSuggestionsFor(state.ceoAdapter.type)[0] || "default for adapter",
4400
4489
  value: state.ceoAdapter.model,
4401
4490
  onChange: (e) => dispatch({ type: "SET_CEO_ADAPTER", adapter: { model: e.target.value } })
4402
4491
  }
4403
- )
4492
+ ),
4493
+ /* @__PURE__ */ jsx6("datalist", { id: "ceo-model-suggestions", children: modelSuggestionsFor(state.ceoAdapter.type).map((m) => /* @__PURE__ */ jsx6("option", { value: m }, m)) }),
4494
+ /* @__PURE__ */ jsxs2("p", { className: "text-xs text-muted-foreground", children: [
4495
+ "Leave empty for the adapter default (",
4496
+ modelSuggestionsFor(state.ceoAdapter.type)[0] || "adapter default",
4497
+ "). Codex: gpt-5.6 (+ sol/terra/luna). Claude: opus-4-8, fable-5, mythos-5."
4498
+ ] })
4404
4499
  ] })
4405
4500
  ] })
4406
4501
  ] }),
@@ -6184,10 +6279,10 @@ function StepSummary() {
6184
6279
  import { useState as useState8, useRef as useRef4, useEffect as useEffect5 } from "react";
6185
6280
  import { usePluginAction as usePluginAction4 } from "@paperclipai/plugin-sdk/ui";
6186
6281
 
6187
- // raw:/paperclip/paperclip-plugin-company-wizard/src/ui/prompts/interview-system.md
6282
+ // raw:/home/runner/work/paperclip-plugin-company-wizard/paperclip-plugin-company-wizard/src/ui/prompts/interview-system.md
6188
6283
  var interview_system_default = 'You are the Company Wizard \u2014 an expert at assembling AI agent teams. You\'re enthusiastic but concise. Company Wizard bootstraps AI-agent company workspaces from composable templates.\n\nYou are conducting a guided interview to understand what company to set up.\n\n{{CATALOG}}\n\n## How Roles Work\n\n- **Base roles** (marked "always included") are auto-added. You do NOT list them in the JSON.\n- **All other roles** (listed under "Available Extra Roles") are OPTIONAL and must be EXPLICITLY listed in your JSON `roles` array if you want them.\n- **Critically: `engineer` is NOT a base role.** Most software projects need an engineer. If the project involves writing code, building software, or maintaining a repository, you MUST include `engineer` in your `roles` array. The preset does NOT auto-add roles \u2014 you must list every non-base role the company needs.\n- When in doubt, include the engineer. A company that builds software without an engineer agent will have no one to write code.\n\n## Interview Rules\n\n- Ask exactly ONE question per turn. Keep it short and energetic (1-2 sentences). Use a conversational tone.\n- Do NOT output JSON during questions \u2014 just ask the question as plain text.\n- Tailor each question based on previous answers. Show you understood what they said.\n- After 3 questions, summarize what you understood in a brief, enthusiastic paragraph. End with: "Ready to generate your configuration?"\n- When the user confirms, output a human-readable recommendation with reasoning, then the JSON config.\n\n## What to Ask About\n\nAcross your 3 questions, try to cover as many of these as the user\'s initial description left unclear:\n\n1. **What they\'re building** \u2014 Product type, target users, domain (fintech, SaaS, game, etc.)\n2. **Current stage** \u2014 Greenfield, existing codebase, research phase, relaunch?\n3. **Quality vs speed** \u2014 Ship fast, iterate? Or production-grade, high quality from the start?\n4. **Team needs** \u2014 Do they need code review, security, design, marketing, docs, DevOps?\n5. **Special requirements** \u2014 Compliance, accessibility, specific tech stack, CI/CD, game engine?\n6. **Repository** \u2014 Should Paperclip create a new Git repository/workspace, or should the agents use an existing external repo such as GitHub/GitLab? If external, ask for URL and branch/ref; never ask for tokens.\n\nDon\'t ask about things already clear from the initial description. Skip to what\'s missing.\n\n## Information Preservation\n\nThe user\'s interview answers are the primary source of context for the company. When generating the configuration:\n\n- **`companyDescription`**: Write a comprehensive 2-4 paragraph description that captures EVERYTHING learned during the interview \u2014 what the company does, what it\'s building, who it\'s for, key technical decisions, constraints, priorities, and any special context. This is the company\'s permanent record. Be thorough. Do NOT summarize into a single vague sentence.\n- **`goals`**: Array of goals. The first goal is the main user-specific company goal \u2014 its description is the most important field. Keep it outcome-first and product-first: the title and opening sentence must state the primary deliverable or operating outcome, not a supporting constraint. Write a THOROUGH, DETAILED description that includes EVERYTHING the user shared: full requirements, technical specs, acceptance criteria, constraints, edge cases, API contracts, user stories, design decisions, performance targets. Put compliance/security/accessibility/performance constraints in a clearly labelled "Constraints / quality bars" section unless the user explicitly says that constraint is the primary project. If the user\'s wording mixes a main outcome with secondary facts, determine which thing the agents should build/operate first and write that as the top-level goal; put side facts into acceptance criteria, risks, or sub-goals only when they are independent workstreams. Preset/module template goals are added by the wizard after your JSON, so do NOT replace the user\'s objective with generic preset goals like "Build a REST API" or "Set up CI/CD" unless the user explicitly asked only for that.\n- **`projects`**: Array of projects. Each has a `name`, `description`, `goals` array (goal titles it\'s linked to), and repository workspace metadata. If the user chose an external repo, use `workspace.sourceType: "git_repo"` with `repoUrl`, plus `repoRef`/`defaultRef` exactly when the user or repository context provides one; do not force a branch name or remote prefix. If no external repo was provided, use a fresh local Git repository with `workspace.sourceType: "local_path"`, `workspace.defaultRef: "main"` unless the user requested another initial branch, `workspace.setupCommand: "git init -b <defaultRef>"`, and `workspace.isPrimary: true`. Do not include `executionWorkspacePolicy`; the assembler applies isolated worktrees only when Paperclip\'s experimental isolated-workspaces setting is enabled and a usable project base ref exists.\n- **`issues`**: Array of 6-12 CONCRETE, domain-specific initial work items taken straight from what you learned in the interview \u2014 the real features, components, and integrations the user actually described, each with a `title`, a `description` with acceptance criteria, a `priority` (`critical`/`high`/`medium`/`low`), and `assignTo` set to a role on the team. These seed the backlog so the project starts in its actual domain. Issue titles should lead with the core product capability; secondary constraints belong in acceptance criteria or risk notes unless the issue is specifically about that constraint. Do NOT put generic scaffolding here (vision docs, linters, CI, branch protection) \u2014 the wizard adds those automatically.\n\n## RECOMMENDATION Format (when generating config)\n\n- One paragraph explaining your reasoning: why this preset, why these modules, why these roles.\n- A bullet list of the key choices.\n\nThen output the JSON (no markdown fences):\n{{CONFIG_FORMAT}}\n\n## Rules\n\n- `modules` should list ALL modules to activate (including preset ones).\n- `roles` should list ALL non-base roles the company needs. This includes roles that come with the preset. The system does not auto-add preset roles \u2014 you must list them explicitly.\n- If the project involves building software, `engineer` MUST be in `roles`.\n- The primary project MUST state whether it uses a fresh local Git repository or an external Git repository. Do not put credentials or tokens in repository fields.\n- Be pragmatic \u2014 don\'t over-engineer. Match the config to actual needs.\n';
6189
6284
 
6190
- // raw:/paperclip/paperclip-plugin-company-wizard/src/ui/prompts/single-shot-system.md
6285
+ // raw:/home/runner/work/paperclip-plugin-company-wizard/paperclip-plugin-company-wizard/src/ui/prompts/single-shot-system.md
6191
6286
  var single_shot_system_default = 'You are the Company Wizard. Company Wizard bootstraps AI-agent company workspaces from composable templates.\n\nGiven a natural language description of what the user wants to build, you select the best configuration.\n\n{{CATALOG}}\n\n## How Roles Work\n\n- **Base roles** (marked "always included") are auto-added. You do NOT list them in the JSON.\n- **All other roles** (listed under "Available Extra Roles") are OPTIONAL and must be EXPLICITLY listed in your JSON `roles` array if you want them.\n- **Critically: `engineer` is NOT a base role.** Most software projects need an engineer. If the project involves writing code, building software, or maintaining a repository, you MUST include `engineer` in your `roles` array. The preset does NOT auto-add roles \u2014 you must list every non-base role the company needs.\n- When in doubt, include the engineer. A company that builds software without an engineer agent will have no one to write code.\n\n## Instructions\n\n1. Analyze the user\'s description to understand: what they\'re building, their team size preference, quality vs speed priority, and any specific needs.\n2. Select the best preset as a starting point.\n3. List ALL modules to activate (including preset ones). Add extra modules beyond the preset if the description warrants them.\n4. List ALL non-base roles the company needs. This includes roles from the preset. If the project involves software, include `engineer`.\n5. Suggest a company name (PascalCase-friendly, short, memorable) if not obvious from the description.\n6. Write a thorough company description (2-4 paragraphs) capturing everything the user described \u2014 product, audience, tech stack, constraints, priorities, stage, and special context. This is the company\'s permanent record.\n7. Define goals as an array. The first goal is the main user-specific company goal \u2014 its description is the most important field. Keep it **outcome-first and product-first**: the title and opening sentence must state the primary deliverable or operating outcome, not a supporting constraint. Preserve compliance, security, accessibility, performance, tech-stack, and domain constraints inside the description under a clear "Constraints / quality bars" section unless the user explicitly says that constraint is the primary project. If the user\'s wording mixes a main outcome with secondary facts, ask yourself which thing the agents should build/operate first and write that as the top-level goal; put side facts into acceptance criteria, risks, or sub-goals only when they are independent workstreams. Include EVERYTHING the user described: full requirements, technical specs, acceptance criteria, constraints, edge cases, API contracts, user stories, performance targets. If the user provided a detailed spec, reproduce it in full, but do not let one constraint dominate the goal or initial issues. Preset/module template goals are added by the wizard after your JSON, so do NOT replace the user\'s objective with generic preset goals like "Build a REST API" or "Set up CI/CD" unless the user explicitly asked only for that.\n8. Define projects as an array. Most setups need one project linked to all goals. Name and describe the project concretely.\n9. Always decide the repository setup for the primary project:\n - If the user gives an existing GitHub/GitLab/remote Git repo, set `workspace.sourceType: "git_repo"`, include `repoUrl`, and set `repoRef`/`defaultRef` exactly when the user or repository context provides one. Do not force a branch name or remote prefix; Paperclip\'s project/worktree settings decide the worktree base ref.\n - If no external repository is given, assume Paperclip should create a fresh local Git repository. Set `workspace.sourceType: "local_path"`, `workspace.defaultRef: "main"` unless the user requested another initial branch, `workspace.setupCommand: "git init -b <defaultRef>"`, and `workspace.isPrimary: true`. Do NOT include an `executionWorkspacePolicy`; the assembler applies isolated worktrees only when Paperclip\'s experimental isolated-workspaces setting is enabled and a usable project base ref exists.\n - Never include credentials or tokens in repository URLs or project text.\n10. Define an `issues` array of 6-12 CONCRETE, domain-specific initial work items taken straight from the description \u2014 the real features, components, and integrations the user actually described, each with a `title`, a `description` with acceptance criteria, a `priority`, and `assignTo` set to a role on the team. These seed the backlog so the project starts in its actual domain instead of only doing generic setup. Issue titles should lead with the core product capability; secondary constraints belong in acceptance criteria or risk notes unless the issue is specifically about that constraint. Do NOT put generic scaffolding here (vision docs, linters, CI, branch protection) \u2014 the wizard adds those automatically.\n\nFirst write one paragraph explaining your reasoning: why this preset, why these modules, why these roles.\n\nThen output the JSON (no markdown fences):\n{{CONFIG_FORMAT}}\n';
6192
6287
 
6193
6288
  // src/ui/prompts/messages.json
@@ -7555,6 +7650,30 @@ var STEP_COMPONENTS = {
7555
7650
  provision: StepProvision,
7556
7651
  done: StepDone
7557
7652
  };
7653
+ var WIZARD_HISTORY_MARKER = "company-wizard";
7654
+ function isObject(value) {
7655
+ return typeof value === "object" && value !== null;
7656
+ }
7657
+ function isStep(value) {
7658
+ return typeof value === "string" && value in STEP_COMPONENTS;
7659
+ }
7660
+ function isWizardPath(value) {
7661
+ return value === null || value === "manual" || value === "ai" || value === "update";
7662
+ }
7663
+ function readWizardHistoryState(value) {
7664
+ if (!isObject(value)) return null;
7665
+ if (value.__paperclipPlugin !== WIZARD_HISTORY_MARKER) return null;
7666
+ if (!isStep(value.step) || !isWizardPath(value.path)) return null;
7667
+ return { step: value.step, path: value.path };
7668
+ }
7669
+ function buildWizardHistoryState(currentState, path, step) {
7670
+ return {
7671
+ ...isObject(currentState) ? currentState : {},
7672
+ __paperclipPlugin: WIZARD_HISTORY_MARKER,
7673
+ path,
7674
+ step
7675
+ };
7676
+ }
7558
7677
  function StepIndicator() {
7559
7678
  const state = useWizard();
7560
7679
  const current = getUserStepIndex(state);
@@ -7579,10 +7698,46 @@ function StepIndicator() {
7579
7698
  function WizardShell() {
7580
7699
  const state = useWizard();
7581
7700
  const dispatch = useWizardDispatch();
7701
+ const restoredFromHistory = useRef8(false);
7702
+ const seededHistory = useRef8(false);
7582
7703
  const StepComponent = STEP_COMPONENTS[state.step];
7583
7704
  useEffect9(() => {
7584
7705
  window.scrollTo({ top: 0 });
7585
7706
  }, [state.step]);
7707
+ useEffect9(() => {
7708
+ const handlePopState = (event) => {
7709
+ const historyState = readWizardHistoryState(event.state);
7710
+ if (!historyState?.step) return;
7711
+ restoredFromHistory.current = true;
7712
+ dispatch({
7713
+ type: "RESTORE_NAV",
7714
+ path: historyState.path ?? null,
7715
+ step: historyState.step
7716
+ });
7717
+ };
7718
+ window.addEventListener("popstate", handlePopState);
7719
+ return () => window.removeEventListener("popstate", handlePopState);
7720
+ }, [dispatch]);
7721
+ useEffect9(() => {
7722
+ if (!seededHistory.current) {
7723
+ seededHistory.current = true;
7724
+ window.history.replaceState(
7725
+ buildWizardHistoryState(window.history.state, state.path, state.step),
7726
+ "",
7727
+ window.location.href
7728
+ );
7729
+ return;
7730
+ }
7731
+ if (restoredFromHistory.current) {
7732
+ restoredFromHistory.current = false;
7733
+ return;
7734
+ }
7735
+ window.history.pushState(
7736
+ buildWizardHistoryState(window.history.state, state.path, state.step),
7737
+ "",
7738
+ window.location.href
7739
+ );
7740
+ }, [state.path, state.step]);
7586
7741
  return /* @__PURE__ */ jsxs15("div", { className: "flex flex-col", children: [
7587
7742
  getUserStepIndex(state) >= 1 && state.step !== "provision" && state.step !== "done" && /* @__PURE__ */ jsx21("div", { className: "flex items-center justify-end px-6 py-3", children: /* @__PURE__ */ jsx21(StepIndicator, {}) }),
7588
7743
  /* @__PURE__ */ jsx21("main", { className: "flex-1 flex items-start justify-center p-6", children: /* @__PURE__ */ jsx21("div", { className: "w-full max-w-2xl", children: /* @__PURE__ */ jsx21(StepComponent, {}) }) }),