refactor(cli): extract init command into framework-agnostic initAction#999
refactor(cli): extract init command into framework-agnostic initAction#999
Conversation
|
Claude finished @mttdnt's task in 3m 20s —— View job Review
Changeset: No changeset — correctly absent for a pure refactor with no public API change. 1.
await promptForProjectCreation({
coupon,
isUsersFirstProject: projects.length === 0,
organizationId,
organizations: [], // ← always empty
planId,
user,
})
const org = organizationId || (await promptUserForOrganization({organizations, user}))
Fix: either assert non-nullability at the callsite, or fetch and pass the real organizations list (the same list already fetched in 2. The coverage report shows Note: The |
📦 Bundle Stats —
|
| Metric | Value | vs main (26f0fb5) |
|---|---|---|
| Internal (raw) | 2.1 KB | - |
| Internal (gzip) | 799 B | - |
| Bundled (raw) | 10.94 MB | - |
| Bundled (gzip) | 2.05 MB | - |
| Import time | 746ms | +1ms, +0.1% |
bin:sanity
| Metric | Value | vs main (26f0fb5) |
|---|---|---|
| Internal (raw) | 975 B | - |
| Internal (gzip) | 460 B | - |
| Bundled (raw) | 9.84 MB | - |
| Bundled (gzip) | 1.77 MB | - |
| Import time | 1.80s | +16ms, +0.9% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — @sanity/cli-core
Compared against main (26f0fb57)
| Metric | Value | vs main (26f0fb5) |
|---|---|---|
| Internal (raw) | 93.1 KB | - |
| Internal (gzip) | 21.9 KB | - |
| Bundled (raw) | 21.62 MB | - |
| Bundled (gzip) | 3.42 MB | - |
| Import time | 703ms | -1ms, -0.1% |
🗺️ View treemap · Artifacts
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
📦 Bundle Stats — create-sanity
Compared against main (26f0fb57)
| Metric | Value | vs main (26f0fb5) |
|---|---|---|
| Internal (raw) | 976 B | - |
| Internal (gzip) | 507 B | - |
| Bundled (raw) | 50.7 KB | - |
| Bundled (gzip) | 12.6 KB | - |
| Import time | ❌ ChildProcess denied: node | - |
Details
- Import time regressions over 10% are flagged with
⚠️ - Sizes shown as raw / gzip 🗜️. Internal bytes = own code only. Total bytes = with all dependencies. Import time = Node.js cold-start median.
Coverage Delta
Comparing 23 changed files against main @ Overall Coverage
|
binoy14
left a comment
There was a problem hiding this comment.
Looks good overall, smaller comments
| } | ||
| }) | ||
|
|
||
| describe('InitCommand.run() mcpMode computation', () => { |
There was a problem hiding this comment.
this naming style is weird for the describe block
| }) | ||
|
|
||
| test('translates InitError to oclif error', async () => { | ||
| const {InitError} = await import('../../../actions/init/initError.js') |
There was a problem hiding this comment.
can this just be a static import?
| packageName, | ||
| templateName, | ||
| useTypeScript, | ||
| useTypeScript: useTypeScript ?? false, |
There was a problem hiding this comment.
🤔 if useTypescript is boolean is the conditional needed?
There was a problem hiding this comment.
For better readability does it make sense to split this files by functions aka move some functions out of here so it's not 1k lines
…Action Moves ~1100 lines of logic out of the oclif InitCommand into actions/init/initAction.ts, leaving init.ts as a thin wrapper that maps oclif flags → InitOptions and catches InitError. Flow files (initApp, initStudio, initNextJs, scaffoldTemplate) now accept `options: InitOptions` instead of individual flag params, and throw InitError directly instead of receiving an `error` callback. Zero test assertion changes — all 14 init test files pass as-is. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Make `visibility` optional in `CreateOrSelectDatasetStep` (can be undefined in unattended mode) - Remove dead `ConfigureAppProjectStep` interface (no trace.log call exists for it) - Remove unnecessary `as 'private' | 'public'` cast now that the type accepts undefined Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
…d tests
- Restore configureAppProject trace calls dropped during extraction
(thread `trace` param into promptForAppTemplateSetup)
- Replace `throw new InitError('', 0)` with plain `return` on --env path
(it's a normal success path, not an error)
- Remove exitCode===0 special-case from command wrapper
- Add ConfigureAppProjectStep to telemetry union type
- Port 4 new test files from #845: flagsToInitOptions, initAction,
initError, init.command
- Update 2 existing tests: --env path no longer throws
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- bootstrapTemplate: make overwriteFiles/useTypeScript optional - initHelpers: use InitContext['output'] instead of Output - initNextJs: throw InitError instead of output.error(), pass options directly - initStudio: dynamic import for ImportDatasetCommand, use workDir over process.cwd() - initApp: use workDir over process.cwd() - scaffoldTemplate: remove as boolean casts and unnecessary try/catch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
… tighten useTypeScript type - Rename describe blocks to simpler names (mcpMode resolution, error handling) - Use static import for InitError instead of dynamic import - Make useTypeScript a required boolean since flagOrDefault always returns boolean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
6ee3bb0 to
6ffc884
Compare
Tests from #1004 used the old flat-argument signature; wrap in options object to match the current selectTemplate interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Extract helper functions from the 1175-line initAction.ts into one-function-per-file modules under plan/ and project/ subdirectories. initAction.ts now contains only the main orchestrator, flag validation, and auth — down to ~300 lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
There was a problem hiding this comment.
Cursor Bugbot has reviewed your changes and found 1 potential issue.
There are 2 total unresolved issues (including 1 from previous review).
❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, enable autofix in the Cursor dashboard.
Reviewed by Cursor Bugbot for commit 401d4a8. Configure here.
The refactor from class methods to standalone functions dropped the implicit this.flags['dataset-default'] read that getOrCreateDataset relied on. Thread datasetDefault through getProjectDetails → promptForAppTemplateSetup → getOrCreateDataset so --dataset-default applies to app templates again. Adds a regression test exercising the app template + --dataset-default code path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Resolves conflicts from the init refactor on main (#999) by integrating feat/workbench's federation flag and prompt flow into the new initAction pipeline and its flagsToInitOptions helper. Conflicted files: - packages/@sanity/cli/src/commands/init.ts - packages/@sanity/cli/src/actions/init/{initApp,initStudio,scaffoldTemplate}.ts - packages/@sanity/cli/src/actions/dev/startStudioDevServer.ts - pnpm-lock.yaml Also applied federation changes to newly-added files from main that weren't seen by the 3-way merge: - packages/@sanity/cli/src/actions/init/initAction.ts - packages/@sanity/cli/src/actions/init/types.ts Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
* fix(cli): replace preferred-pm with local implementation (#984) * fix(cli): replace preferred-pm with local implementation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): address review feedback for preferredPm Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): detect pnpm-workspace.yaml in parent directory walk-up Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): normalize path separators for workspace glob matching on windows Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): continue workspace walk-up when inner workspace globs don't match When a nested package.json has a workspaces field whose globs don't match the target path, continue traversing parent directories instead of returning null. Also simplify error handling in detectFromNodeModules to swallow all read errors for best-effort detection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove continue that caused infinite loop in workspace walk-up The continue statement skipped dir = path.dirname(dir) at the bottom of the while loop, causing an infinite loop when a workspace's globs didn't match the target path. Removing it lets the code fall through to the directory advancement naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): skip chmod-based permission test on Windows chmod doesn't enforce read permissions on Windows, so the file remains readable and the test returns 'pnpm' instead of falling through to 'npm'. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove circular import and add malformed package.json test Address PR review feedback: inline DetectablePackageManager type to break circular dependency between preferredPm and packageManagerChoice, and add test covering malformed package.json handling in workspace walk-up. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: split e2e workflow into PR and scheduled runs (#995) Move registry-mode e2e tests and Slack failure notifications into a dedicated hourly scheduled workflow. The PR/push workflow now only runs in pack mode. Post-release dispatch in release.yml updated to target the new scheduled workflow with `latest` instead of a specific version. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(cli): replace default namespace imports with named imports (#993) Use named imports for semver, nock, and typescript to resolve 167 import-x/no-named-as-default-member lint warnings. Also replace one `as any` with a proper type cast. CJS modules (json5, dotenv, tar-fs, tar-stream) are left unchanged since they don't support named ESM imports at runtime. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): default to TypeScript in unattended mode for sanity init (#1004) * fix(cli): default to TypeScript in unattended mode for sanity init When running sanity init in unattended mode (non-interactive terminal or --yes flag), the CLI now defaults to TypeScript when --typescript or --no-typescript is not explicitly provided, matching the interactive prompt default. Uses the existing flagOrDefault/shouldPrompt helpers already used by initNextJs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update auto-generated changeset for PR #1004 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com> * refactor(cli): extract init command into framework-agnostic initAction (#999) * refactor(cli): extract init command body into framework-agnostic initAction Moves ~1100 lines of logic out of the oclif InitCommand into actions/init/initAction.ts, leaving init.ts as a thin wrapper that maps oclif flags → InitOptions and catches InitError. Flow files (initApp, initStudio, initNextJs, scaffoldTemplate) now accept `options: InitOptions` instead of individual flag params, and throw InitError directly instead of receiving an `error` callback. Zero test assertion changes — all 14 init test files pass as-is. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): clean up init telemetry types - Make `visibility` optional in `CreateOrSelectDatasetStep` (can be undefined in unattended mode) - Remove dead `ConfigureAppProjectStep` interface (no trace.log call exists for it) - Remove unnecessary `as 'private' | 'public'` cast now that the type accepts undefined Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — restore telemetry, fix env path, add tests - Restore configureAppProject trace calls dropped during extraction (thread `trace` param into promptForAppTemplateSetup) - Replace `throw new InitError('', 0)` with plain `return` on --env path (it's a normal success path, not an error) - Remove exitCode===0 special-case from command wrapper - Add ConfigureAppProjectStep to telemetry union type - Port 4 new test files from #845: flagsToInitOptions, initAction, initError, init.command - Update 2 existing tests: --env path no longer throws Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): close remaining oclif decoupling gaps in init flow files - bootstrapTemplate: make overwriteFiles/useTypeScript optional - initHelpers: use InitContext['output'] instead of Output - initNextJs: throw InitError instead of output.error(), pass options directly - initStudio: dynamic import for ImportDatasetCommand, use workDir over process.cwd() - initApp: use workDir over process.cwd() - scaffoldTemplate: remove as boolean casts and unnecessary try/catch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — clean up test names, static import, tighten useTypeScript type - Rename describe blocks to simpler names (mcpMode resolution, error handling) - Use static import for InitError instead of dynamic import - Make useTypeScript a required boolean since flagOrDefault always returns boolean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update selectTemplate tests for refactored options signature Tests from #1004 used the old flat-argument signature; wrap in options object to match the current selectTemplate interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): split initAction.ts into plan/ and project/ modules Extract helper functions from the 1175-line initAction.ts into one-function-per-file modules under plan/ and project/ subdirectories. initAction.ts now contains only the main orchestrator, flag validation, and auth — down to ~300 lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: forward datasetDefault to app template dataset creation The refactor from class methods to standalone functions dropped the implicit this.flags['dataset-default'] read that getOrCreateDataset relied on. Thread datasetDefault through getProjectDetails → promptForAppTemplateSetup → getOrCreateDataset so --dataset-default applies to app templates again. Adds a regression test exercising the app template + --dataset-default code path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Binoy Patel <me@binoy.io> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com> Co-authored-by: Matthew Dent <mttdnt@gmail.com>
* fix(cli): replace preferred-pm with local implementation (#984) * fix(cli): replace preferred-pm with local implementation Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): address review feedback for preferredPm Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): detect pnpm-workspace.yaml in parent directory walk-up Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): normalize path separators for workspace glob matching on windows Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): continue workspace walk-up when inner workspace globs don't match When a nested package.json has a workspaces field whose globs don't match the target path, continue traversing parent directories instead of returning null. Also simplify error handling in detectFromNodeModules to swallow all read errors for best-effort detection. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove continue that caused infinite loop in workspace walk-up The continue statement skipped dir = path.dirname(dir) at the bottom of the while loop, causing an infinite loop when a workspace's globs didn't match the target path. Removing it lets the code fall through to the directory advancement naturally. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): skip chmod-based permission test on Windows chmod doesn't enforce read permissions on Windows, so the file remains readable and the test returns 'pnpm' instead of falling through to 'npm'. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): remove circular import and add malformed package.json test Address PR review feedback: inline DetectablePackageManager type to break circular dependency between preferredPm and packageManagerChoice, and add test covering malformed package.json handling in workspace walk-up. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * ci: split e2e workflow into PR and scheduled runs (#995) Move registry-mode e2e tests and Slack failure notifications into a dedicated hourly scheduled workflow. The PR/push workflow now only runs in pack mode. Post-release dispatch in release.yml updated to target the new scheduled workflow with `latest` instead of a specific version. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * refactor(cli): replace default namespace imports with named imports (#993) Use named imports for semver, nock, and typescript to resolve 167 import-x/no-named-as-default-member lint warnings. Also replace one `as any` with a proper type cast. CJS modules (json5, dotenv, tar-fs, tar-stream) are left unchanged since they don't support named ESM imports at runtime. Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * fix(cli): default to TypeScript in unattended mode for sanity init (#1004) * fix(cli): default to TypeScript in unattended mode for sanity init When running sanity init in unattended mode (non-interactive terminal or --yes flag), the CLI now defaults to TypeScript when --typescript or --no-typescript is not explicitly provided, matching the interactive prompt default. Uses the existing flagOrDefault/shouldPrompt helpers already used by initNextJs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * chore: update auto-generated changeset for PR #1004 --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com> * refactor(cli): extract init command into framework-agnostic initAction (#999) * refactor(cli): extract init command body into framework-agnostic initAction Moves ~1100 lines of logic out of the oclif InitCommand into actions/init/initAction.ts, leaving init.ts as a thin wrapper that maps oclif flags → InitOptions and catches InitError. Flow files (initApp, initStudio, initNextJs, scaffoldTemplate) now accept `options: InitOptions` instead of individual flag params, and throw InitError directly instead of receiving an `error` callback. Zero test assertion changes — all 14 init test files pass as-is. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): clean up init telemetry types - Make `visibility` optional in `CreateOrSelectDatasetStep` (can be undefined in unattended mode) - Remove dead `ConfigureAppProjectStep` interface (no trace.log call exists for it) - Remove unnecessary `as 'private' | 'public'` cast now that the type accepts undefined Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — restore telemetry, fix env path, add tests - Restore configureAppProject trace calls dropped during extraction (thread `trace` param into promptForAppTemplateSetup) - Replace `throw new InitError('', 0)` with plain `return` on --env path (it's a normal success path, not an error) - Remove exitCode===0 special-case from command wrapper - Add ConfigureAppProjectStep to telemetry union type - Port 4 new test files from #845: flagsToInitOptions, initAction, initError, init.command - Update 2 existing tests: --env path no longer throws Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): close remaining oclif decoupling gaps in init flow files - bootstrapTemplate: make overwriteFiles/useTypeScript optional - initHelpers: use InitContext['output'] instead of Output - initNextJs: throw InitError instead of output.error(), pass options directly - initStudio: dynamic import for ImportDatasetCommand, use workDir over process.cwd() - initApp: use workDir over process.cwd() - scaffoldTemplate: remove as boolean casts and unnecessary try/catch Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: address PR review feedback — clean up test names, static import, tighten useTypeScript type - Rename describe blocks to simpler names (mcpMode resolution, error handling) - Use static import for InitError instead of dynamic import - Make useTypeScript a required boolean since flagOrDefault always returns boolean Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: update selectTemplate tests for refactored options signature Tests from #1004 used the old flat-argument signature; wrap in options object to match the current selectTemplate interface. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * refactor(cli): split initAction.ts into plan/ and project/ modules Extract helper functions from the 1175-line initAction.ts into one-function-per-file modules under plan/ and project/ subdirectories. initAction.ts now contains only the main orchestrator, flag validation, and auth — down to ~300 lines. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> * fix: forward datasetDefault to app template dataset creation The refactor from class methods to standalone functions dropped the implicit this.flags['dataset-default'] read that getOrCreateDataset relied on. Thread datasetDefault through getProjectDetails → promptForAppTemplateSetup → getOrCreateDataset so --dataset-default applies to app templates again. Adds a regression test exercising the app template + --dataset-default code path. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com> --------- Co-authored-by: Binoy Patel <me@binoy.io> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com> Co-authored-by: squiggler-app[bot] <265501495+squiggler-app[bot]@users.noreply.github.com> Co-authored-by: Matthew Dent <mttdnt@gmail.com>
Squashed merge of workbench commits up through 8535ccd (PR #1014) onto current main (737ab0b). Resolves conflicts between main's init refactor (#999), TypeScript default (#1004), preferred-pm replacement (#984), named-import refactor (#993), e2e workflow split (#995), post-release trigger removal (#1021), Slack action SHA bump (#1023), CSS bundle loader (#893), and init flag fix (#1015) on the main side, against the federation prompt, workbench dev server, and federation vite plugin work on the workbench side. This is the third-branch resolution; feat/workbench is untouched. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>

Description
Extracts ~1100 lines of logic from the oclif
InitCommand(commands/init.ts) into a framework-agnosticactions/init/initAction.ts. This is the structural refactor from PR #929 / #845, using main's current logic (no regressions).Key changes:
commands/init.tsis now a thin oclif wrapper: static declarations +run()that maps flags →InitOptions, callsinitAction(), and catchesInitErrorInitOptions/InitContexttypes intypes.tswithflagsToInitOptions()converterInitErrorclass replaces oclif'sthis.error()for non-zero exitsinitApp,initStudio,initNextJs,scaffoldTemplate) acceptoptions: InitOptionsinstead of individual flag paramsInitErrordirectly instead of receiving anerrorcallbackbootstrapTemplate.tsunchanged (only receives computed values)What this enables:
create-sanity, programmatic use)What to review
initAction.tsis the main new file (~1166 lines) containing all extracted functionstypes.tshas the newInitOptions,InitContext, andflagsToInitOptionsoptions: InitOptionsdestructuringerrorFnadapter removed frominitAction.tssince flow files now throwInitErrordirectlyTesting
All 14 existing init test files pass with zero assertion changes, confirming behavior is identical:
init.authentication.test.tsinit.bootstrap-app.test.tsinit.create-new-project.test.tsinit.get-project-details.test.tsinit.nextjs.test.tsinit.plan.test.tsinit.setup.test.tsinit.staging-env.test.tsTypecheck, lint, and build all pass cleanly.
Note
Medium Risk
Large refactor of
sanity initcontrol flow and error handling (moving from oclifthis.error()to thrownInitError), which could subtly change CLI exit/early-return behavior despite intent to be mechanical.Overview
Refactors
sanity initby extracting the ~1k lines of init orchestration out ofcommands/init.tsinto a new framework-agnosticinitAction()with a typedInitOptions/InitContextinterface and aflagsToInitOptions()converter.Reworks init subflows (
initStudio,initApp,initNextJs,scaffoldTemplate, plan/project/dataset helpers) to accept a singleoptionsobject and to throwInitErrorfor controlled failures;InitCommandis now a thin wrapper that resolvesmcpMode, callsinitAction, and translatesInitErrorto an oclif exit code.Adds targeted unit tests for
flagsToInitOptions,InitError, and directinitActionbehavior, and updates existing init command tests to align with the new error/exit semantics (including optionalvisibilityin init telemetry).Reviewed by Cursor Bugbot for commit abac9ba. Bugbot is set up for automated code reviews on this repo. Configure here.