@userreason/wizard 0.3.1 → 0.3.3

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.
package/README.md CHANGED
@@ -36,7 +36,7 @@ terminal. The [first survey guide](https://docs.userreason.com/get-started/first
36
36
  walks through creating and publishing a survey. Installing the SDK does not
37
37
  publish a survey.
38
38
 
39
- In development mode (`--dev`), onboarding opens in the browser by default.
39
+ Onboarding opens in the browser by default in production and development (`--dev`).
40
40
  Survey suggestions and the Agent test step are paused in production and development.
41
41
  Setup does not prepare or upload application source for recommendations, and it
42
42
  neither offers nor creates suggested drafts. The terminal flow skips the
@@ -178,7 +178,8 @@ package builds. With a published package, select the development API:
178
178
  npx -y @userreason/wizard@latest --dev
179
179
  ```
180
180
 
181
- Production still requires `--browser-setup`. Compatible builds also support:
181
+ Production and development both use browser setup by default. `--browser-setup`
182
+ remains an optional explicit alias. Compatible builds also support:
182
183
 
183
184
  ```sh
184
185
  npx -y @userreason/wizard@latest --browser-setup
@@ -196,10 +197,11 @@ creating a session or local effects.
196
197
  Malformed protocol data and already-started setups never fall back silently.
197
198
  Server rollout flags remain off by default; publication is a separate release.
198
199
 
199
- The browser owns workspace/site selection, optional choices, local-plan approval,
200
+ The browser owns workspace/site selection, optional choices, installation options,
200
201
  finish and cancellation. Source analysis, suggested drafts and the Agent test
201
202
  remain implemented but are hidden and skipped while their rollout flags are off. The local runner executes only approved typed effects
202
- using the separate owner-only setup capability. It does not read or replace
203
+ using the separate owner-only setup capability. Press **Continue** on the setup
204
+ options to begin installation; there is no separate local-change review screen. It does not read or replace
203
205
  normal CLI credentials. Stopping the local process leaves the setup resumable;
204
206
  cancelling in the browser does not undo completed edits or delete created drafts.
205
207
  Terminal results list verified, failed and manual outcomes separately.
@@ -220,11 +222,11 @@ skill never grants ongoing CLI access. Authorize continuing access separately
220
222
  with `userreason login --open` when wanted. Standalone CLI survey tools remain
221
223
  available outside onboarding.
222
224
 
223
- The production profile for wizard 0.3.1 selects `@userreason/js@0.5.3` and
225
+ The production profile for wizard 0.3.3 selects `@userreason/js@0.5.3` and
224
226
  `@userreason/cli@0.2.1`. New installs use those exact versions; an installed
225
227
  stable patch in the same release line is reused. Earlier SDK 0.4 and CLI 0.1
226
- releases are upgraded when installation is selected. Browser setup still
227
- requires explicit `--browser-setup` and a server advertising the capability.
228
+ releases are upgraded when installation is selected. Browser setup is the default and requires a server advertising the capability.
229
+ Use `--terminal-setup` for the terminal flow.
228
230
 
229
231
  Browser-guided installation prints package-manager failures in the connected
230
232
  terminal, including failed registry requests when npm provides them. Diagnostic
package/dist/bin.js CHANGED
@@ -2,7 +2,7 @@
2
2
  import { createRequire as createWizardRequire } from 'node:module'; import { fileURLToPath as wizardFileURLToPath } from 'node:url'; import { dirname as wizardDirname } from 'node:path'; const require = createWizardRequire(import.meta.url); const __filename = wizardFileURLToPath(import.meta.url); const __dirname = wizardDirname(__filename);
3
3
  import {
4
4
  runBrowserWizard
5
- } from "./chunk-CSZW2ULJ.js";
5
+ } from "./chunk-FWEZ2ZWN.js";
6
6
  import {
7
7
  clearInstallation,
8
8
  resolveInstallation,
@@ -26,7 +26,7 @@ import {
26
26
  beginFirstSurveyPreparation,
27
27
  offerFirstSurvey
28
28
  } from "./chunk-ZHJV247H.js";
29
- import "./chunk-Q5U5UOQN.js";
29
+ import "./chunk-5EAHX5BX.js";
30
30
  import "./chunk-4INLEQE2.js";
31
31
  import {
32
32
  offerAgentSkill,
@@ -97,7 +97,7 @@ var help = `UserReason installation wizard
97
97
 
98
98
  userreason-wizard [--directory PATH] [--origin URL]
99
99
 
100
- --browser-setup (browser-guided setup; default for development onboarding)
100
+ --browser-setup (browser-guided setup; default for onboarding)
101
101
  --terminal-setup (use terminal onboarding instead)
102
102
  --resume-setup UUID (resume this project's saved browser setup)
103
103
  --browser-origin ORIGIN (trusted dashboard origin for a custom API)
@@ -214,7 +214,7 @@ async function main() {
214
214
  if (values["resume-setup"]) uuid(values["resume-setup"], "Setup ID");
215
215
  const terminalFlags = ["refresh", "dry-run", "install", "skip-install", "integrate", "skip-integrate", "agent-note", "skip-agent-note", "agent-skill", "skip-agent-skill", "global-cli", "skip-global-cli", "cli-access", "skip-cli-access", "workspace", "workspace-name", "site", "site-name", "origin", "environment", "force", "diff", "session-only", "client-id", "credential-store"];
216
216
  const hasTerminalFlags = terminalFlags.some((key) => values[key] !== void 0 && values[key] !== false);
217
- const browserMode = explicitBrowserMode || developmentApi && !values["terminal-setup"] && !hasTerminalFlags && !values.yes && !values.json;
217
+ const browserMode = explicitBrowserMode || !values["terminal-setup"] && !hasTerminalFlags && !values.yes && !values.json;
218
218
  if (values["browser-origin"]) {
219
219
  if (!browserMode) throw new Error("--browser-origin requires browser setup");
220
220
  apiUrl(values["browser-origin"], "Browser origin");
@@ -41,8 +41,9 @@ import {
41
41
  import { basename } from "node:path";
42
42
 
43
43
  // src/setup-plan.ts
44
- import { randomUUID } from "node:crypto";
45
- import { lstat, readdir, readFile } from "node:fs/promises";
44
+ import { createHash, randomUUID } from "node:crypto";
45
+ import { constants } from "node:fs";
46
+ import { lstat, open, readdir } from "node:fs/promises";
46
47
  import { join, relative } from "node:path";
47
48
  var relativeName = (project, path) => relative(project.directory, path).replaceAll("\\", "/");
48
49
  var metadata = (files) => files.map((file2) => ({ path: file2.path, before_hash: file2.before === null ? null : setupHash(file2.before), after_hash: setupHash(file2.after) }));
@@ -170,10 +171,27 @@ async function prepare(project, session, profile, config, operations = [], manua
170
171
  }
171
172
  return { wire: { project_fingerprint: session.project_fingerprint, choices_digest: setupDigest(session.choices), effects: operations.map((item) => item.effect), ...manual.length ? { manual_steps: manual } : {} }, operations };
172
173
  }
173
- async function snapshot(project) {
174
+ async function snapshotFile(path, expected, signal) {
175
+ const handle = await open(path, constants.O_RDONLY | (constants.O_NOFOLLOW ?? 0));
176
+ try {
177
+ const before = await handle.stat();
178
+ if (!before.isFile() || before.dev !== expected.dev || before.ino !== expected.ino)
179
+ throw new SetupError("setup_files_changed", "A project file changed while checking package installation.");
180
+ const hash = createHash("sha256");
181
+ for await (const chunk of handle.createReadStream({ autoClose: false, signal })) hash.update(chunk);
182
+ const after = await handle.stat();
183
+ if (before.size !== after.size || before.mtimeMs !== after.mtimeMs || before.ctimeMs !== after.ctimeMs)
184
+ throw new SetupError("setup_files_changed", "A project file changed while checking package installation.");
185
+ return hash.digest("hex");
186
+ } finally {
187
+ await handle.close();
188
+ }
189
+ }
190
+ async function snapshot(project, signal) {
174
191
  const result = {}, stack = [""];
175
- let entries = 0, bytes = 0;
192
+ let entries = 0;
176
193
  while (stack.length) {
194
+ signal.throwIfAborted();
177
195
  const folder = stack.pop();
178
196
  for (const entry of await readdir(join(project.directory, folder), { withFileTypes: true })) {
179
197
  if (++entries > 2e4) throw new SetupError("setup_files_changed", "Project scanning exceeds the bounded review budget.");
@@ -185,11 +203,7 @@ async function snapshot(project) {
185
203
  continue;
186
204
  }
187
205
  if (info.isDirectory()) stack.push(path);
188
- else if (info.isFile()) {
189
- bytes += info.size;
190
- if (info.size > 2e7 || bytes > 64e6) throw new SetupError("setup_files_changed", "Project scanning exceeds the bounded byte budget.");
191
- result[path] = setupHash(await readFile(join(project.directory, path)));
192
- }
206
+ else if (info.isFile()) result[path] = await snapshotFile(join(project.directory, path), info, signal);
193
207
  }
194
208
  }
195
209
  return result;
@@ -224,7 +238,7 @@ function setupRuntime(project, apiOrigin, selectedProfile = packageProfile()) {
224
238
  }
225
239
  if (operation.effect.package_manager !== current.packageManager) throw new SetupError("setup_command_mismatch", "The package manager differs from the reviewed command.");
226
240
  for (const item of operation.effect.packages) if (item.version !== (item.name === "@userreason/js" ? profile.sdkVersion : profile.cliVersion)) throw new SetupError("setup_package_version", "The approved package version differs from this local package profile.");
227
- const before = await snapshot(project);
241
+ const before = await snapshot(project, signal);
228
242
  for (const file2 of operation.files.filter((file3) => file3.path !== "package.json")) await writeSetupFile(project.directory, file2);
229
243
  for (const item of operation.effect.packages) {
230
244
  signal.throwIfAborted();
@@ -234,7 +248,7 @@ function setupRuntime(project, apiOrigin, selectedProfile = packageProfile()) {
234
248
  const actual = await readSetupFile(project.directory, manifest.path);
235
249
  if (!actual || setupDigest(JSON.parse(actual)) !== setupDigest(JSON.parse(manifest.after))) throw new Error("The package manager made unexpected manifest changes");
236
250
  await writeSetupFile(project.directory, { ...manifest, before: actual });
237
- const after = await snapshot(project), allowed = /* @__PURE__ */ new Set([...operation.files.map((file2) => file2.path), ...(operation.effect.managed_outputs ?? []).map((file2) => file2.path)]);
251
+ const after = await snapshot(project, signal), allowed = /* @__PURE__ */ new Set([...operation.files.map((file2) => file2.path), ...(operation.effect.managed_outputs ?? []).map((file2) => file2.path)]);
238
252
  for (const path of /* @__PURE__ */ new Set([...Object.keys(before), ...Object.keys(after)])) if (!allowed.has(path) && before[path] !== after[path]) throw new Error("The package manager changed an unreviewed project file");
239
253
  return "verified";
240
254
  },
@@ -3,7 +3,7 @@ import {
3
3
  connectSetup,
4
4
  resumeSetup,
5
5
  runSetup
6
- } from "./chunk-Q5U5UOQN.js";
6
+ } from "./chunk-5EAHX5BX.js";
7
7
  import {
8
8
  clean,
9
9
  openBrowser
@@ -46,14 +46,14 @@ async function runBrowserWizard(input) {
46
46
  let connected;
47
47
  try {
48
48
  connected = input.resumeId ? await resumeSetup(apiOrigin, input.resumeId, project, { signal, measurementDisabled: input.measurementDisabled }) : await connectSetup(apiOrigin, project, async (url, code) => {
49
- terminal.block("Continue in your browser", [url, `Verification code: ${code}`, input.development ? "Choose your workspace, site and installation options in the browser." : "Review the project, local changes and source permissions there."]);
49
+ terminal.block("Continue in your browser", [url, `Verification code: ${code}`, "Choose your workspace, site and installation options in the browser."]);
50
50
  if (!input.noOpen && !await openBrowser(url)) terminal.info("Open the link above to continue.");
51
51
  }, {
52
52
  signal,
53
53
  browserOrigin: input.browserOrigin,
54
- automaticSetup: input.development,
54
+ automaticSetup: true,
55
55
  measurementDisabled: input.measurementDisabled,
56
- ...input.development ? { launcher: { wizard_version: input.version, api_origin: apiOrigin, ...input.profile.kind === "local-development" ? { registry: input.profile.registry } : {} } } : {}
56
+ launcher: { wizard_version: input.version, api_origin: apiOrigin, ...input.profile.kind === "local-development" ? { registry: input.profile.registry } : {} }
57
57
  });
58
58
  } catch (error) {
59
59
  if (!input.resumeId && error instanceof BrowserSetupUnavailable) return false;
@@ -5,8 +5,8 @@ import {
5
5
  setupResumeCommand,
6
6
  setupSampleCommand,
7
7
  setupSummary
8
- } from "./chunk-CSZW2ULJ.js";
9
- import "./chunk-Q5U5UOQN.js";
8
+ } from "./chunk-FWEZ2ZWN.js";
9
+ import "./chunk-5EAHX5BX.js";
10
10
  import "./chunk-4INLEQE2.js";
11
11
  import "./chunk-SB3AYQWG.js";
12
12
  import "./chunk-LEJFE4U5.js";
package/dist/setup.js CHANGED
@@ -6,7 +6,7 @@ import {
6
6
  resumeSetup,
7
7
  runSetup,
8
8
  setupRuntime
9
- } from "./chunk-Q5U5UOQN.js";
9
+ } from "./chunk-5EAHX5BX.js";
10
10
  import "./chunk-4INLEQE2.js";
11
11
  import "./chunk-SB3AYQWG.js";
12
12
  import "./chunk-LEJFE4U5.js";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@userreason/wizard",
3
- "version": "0.3.1",
3
+ "version": "0.3.3",
4
4
  "description": "Authenticated UserReason SDK installation wizard",
5
5
  "type": "module",
6
6
  "license": "UNLICENSED",