@inspecto-dev/cli 0.3.4 → 0.3.6

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 (44) hide show
  1. package/.turbo/turbo-build.log +7 -7
  2. package/.turbo/turbo-test.log +205 -7275
  3. package/CHANGELOG.md +14 -0
  4. package/dist/bin.js +32 -1
  5. package/dist/{chunk-2MOEVONN.js → chunk-7ABJRH3F.js} +1232 -145
  6. package/dist/index.d.ts +62 -4
  7. package/dist/index.js +7 -1
  8. package/package.json +2 -2
  9. package/src/bin.ts +45 -0
  10. package/src/commands/dev-config.ts +109 -0
  11. package/src/commands/doctor.ts +162 -9
  12. package/src/commands/init.ts +10 -3
  13. package/src/commands/integration-automation.ts +2 -0
  14. package/src/commands/integration-host-ide.ts +18 -15
  15. package/src/commands/integration-install.ts +1 -1
  16. package/src/commands/onboard.ts +72 -21
  17. package/src/detect/build-tool.ts +14 -5
  18. package/src/detect/framework.ts +3 -0
  19. package/src/detect/package-manager.ts +1 -1
  20. package/src/index.ts +1 -0
  21. package/src/inject/gitignore.ts +13 -2
  22. package/src/instructions.ts +33 -7
  23. package/src/onboarding/apply.ts +137 -3
  24. package/src/onboarding/nextjs-guidance.ts +257 -0
  25. package/src/onboarding/nuxt-guidance.ts +129 -0
  26. package/src/onboarding/planner.ts +257 -6
  27. package/src/onboarding/session.ts +117 -27
  28. package/src/onboarding/target-resolution.ts +3 -3
  29. package/src/onboarding/umi-guidance.ts +139 -0
  30. package/src/types.ts +51 -3
  31. package/tests/apply.test.ts +319 -0
  32. package/tests/dev-config.test.ts +73 -0
  33. package/tests/doctor.test.ts +89 -0
  34. package/tests/init.test.ts +17 -0
  35. package/tests/instructions.test.ts +10 -6
  36. package/tests/integration-host-ide.test.ts +20 -0
  37. package/tests/integration-install.test.ts +65 -0
  38. package/tests/nextjs-guidance.test.ts +128 -0
  39. package/tests/nuxt-guidance.test.ts +67 -0
  40. package/tests/onboard.test.ts +416 -0
  41. package/tests/plan.test.ts +181 -21
  42. package/tests/runner-script.test.ts +120 -1
  43. package/tests/session-resolve.test.ts +116 -0
  44. package/tests/session.test.ts +120 -0
package/dist/index.d.ts CHANGED
@@ -61,7 +61,7 @@ interface OnboardingTargetCandidate {
61
61
  automaticInjection: boolean;
62
62
  }
63
63
  interface OnboardingTargetResolution {
64
- status: 'resolved' | 'needs_selection';
64
+ status: 'resolved' | 'needs_selection' | 'guided';
65
65
  selected?: OnboardingTargetCandidate;
66
66
  candidates: OnboardingTargetCandidate[];
67
67
  reason: string;
@@ -74,6 +74,13 @@ interface OnboardingSummary {
74
74
  risks: string[];
75
75
  manualFollowUp: string[];
76
76
  }
77
+ interface OnboardingPatchPlan {
78
+ path: string;
79
+ status: 'planned' | 'manual_patch_required';
80
+ reason: string;
81
+ snippet: string;
82
+ confidence: 'high' | 'medium' | 'low';
83
+ }
77
84
  interface OnboardingConfirmation {
78
85
  required: boolean;
79
86
  reason?: string;
@@ -104,6 +111,15 @@ interface OnboardingVerification {
104
111
  devCommand?: string;
105
112
  message: string;
106
113
  }
114
+ interface OnboardingAssistantHandoff {
115
+ framework?: string;
116
+ metaFramework?: string;
117
+ routerMode?: 'app' | 'pages' | 'mixed' | 'unknown';
118
+ autoApplied?: string[];
119
+ pendingSteps?: string[];
120
+ assistantPrompt?: string;
121
+ patches?: OnboardingPatchPlan[];
122
+ }
107
123
  interface ResolvedOnboardingSession {
108
124
  status: OnboardStatus;
109
125
  target: OnboardingTargetResolution;
@@ -118,6 +134,14 @@ interface ResolvedOnboardingSession {
118
134
  supported: boolean;
119
135
  } | null;
120
136
  providerDefault?: string;
137
+ framework?: string;
138
+ metaFramework?: string;
139
+ routerMode?: 'app' | 'pages' | 'mixed' | 'unknown';
140
+ autoApplied?: string[];
141
+ pendingSteps?: string[];
142
+ assistantPrompt?: string;
143
+ patches?: OnboardingPatchPlan[];
144
+ handoff?: OnboardingAssistantHandoff;
121
145
  }
122
146
  interface OnboardCommandResult {
123
147
  status: OnboardStatus;
@@ -128,6 +152,14 @@ interface OnboardCommandResult {
128
152
  verification?: OnboardingVerification;
129
153
  result?: OnboardingExecutionResult;
130
154
  diagnostics?: OnboardingDiagnostics;
155
+ framework?: string;
156
+ metaFramework?: string;
157
+ routerMode?: 'app' | 'pages' | 'mixed' | 'unknown';
158
+ autoApplied?: string[];
159
+ pendingSteps?: string[];
160
+ assistantPrompt?: string;
161
+ patches?: OnboardingPatchPlan[];
162
+ handoff?: OnboardingAssistantHandoff;
131
163
  }
132
164
  /** Machine-readable detection output for skill-first onboarding */
133
165
  interface DetectionResult {
@@ -155,9 +187,9 @@ interface PlanResult {
155
187
  status: CommandStatus;
156
188
  warnings: CommandMessage[];
157
189
  blockers: CommandMessage[];
158
- strategy: 'supported' | 'manual' | 'unsupported';
190
+ strategy: 'supported' | 'guided' | 'manual' | 'unsupported';
159
191
  actions: Array<{
160
- type: 'install_dependency' | 'modify_file' | 'install_extension' | 'manual_step';
192
+ type: 'install_dependency' | 'modify_file' | 'install_extension' | 'manual_step' | 'generate_patch_plan' | 'generate_file' | 'manual_confirmation';
161
193
  target: string;
162
194
  description: string;
163
195
  }>;
@@ -167,6 +199,13 @@ interface PlanResult {
167
199
  shared: boolean;
168
200
  extension: boolean;
169
201
  };
202
+ framework?: string;
203
+ metaFramework?: string;
204
+ routerMode?: 'app' | 'pages' | 'mixed' | 'unknown';
205
+ autoApplied?: string[];
206
+ pendingSteps?: string[];
207
+ assistantPrompt?: string;
208
+ patches?: OnboardingPatchPlan[];
170
209
  }
171
210
  /** A single doctor diagnostic check/result */
172
211
  interface DoctorDiagnostic {
@@ -244,6 +283,24 @@ declare function apply(options?: ApplyCommandOptions): Promise<ApplyCommandResul
244
283
 
245
284
  declare function detect(json?: boolean): Promise<DetectionResult>;
246
285
 
286
+ interface InspectoDevConfig {
287
+ cliBin?: string;
288
+ devRepo?: string;
289
+ }
290
+ interface DevConfigCommandResult {
291
+ status: 'ok';
292
+ configPath: string;
293
+ config: InspectoDevConfig;
294
+ }
295
+ interface DevLinkOptions {
296
+ cliBin?: string;
297
+ devRepo?: string;
298
+ json?: boolean;
299
+ }
300
+ declare function devLink(options: DevLinkOptions): Promise<DevConfigCommandResult>;
301
+ declare function devStatus(json?: boolean): Promise<DevConfigCommandResult>;
302
+ declare function devUnlink(json?: boolean): Promise<DevConfigCommandResult>;
303
+
247
304
  declare function init(options: InitOptions): Promise<void>;
248
305
 
249
306
  interface DoctorCommandOptions {
@@ -257,6 +314,7 @@ interface IntegrationAutomationOptions {
257
314
  inspectoVsix?: string;
258
315
  preview?: boolean;
259
316
  silent?: boolean;
317
+ ignoreProjectArtifacts?: boolean;
260
318
  }
261
319
  interface IntegrationAutomationDetails {
262
320
  hostIde?: {
@@ -349,4 +407,4 @@ declare function reportCommandError(error: unknown, options?: ReportCommandError
349
407
 
350
408
  type Framework = 'react' | 'vue';
351
409
 
352
- export { type BuildTool, type DoctorDiagnostic, type DoctorResult, type Framework, type InitOptions, type InstallLock, type OnboardCommandResult, type OnboardStatus, type PackageManager, type ResolvedOnboardingSession, apply, collectDoctorResult, detect, doctor, init, integrationDoctor, onboard, plan, reportCommandError, teardown, writeCommandOutput };
410
+ export { type BuildTool, type DoctorDiagnostic, type DoctorResult, type Framework, type InitOptions, type InstallLock, type OnboardCommandResult, type OnboardStatus, type PackageManager, type ResolvedOnboardingSession, apply, collectDoctorResult, detect, devLink, devStatus, devUnlink, doctor, init, integrationDoctor, onboard, plan, reportCommandError, teardown, writeCommandOutput };
package/dist/index.js CHANGED
@@ -2,6 +2,9 @@ import {
2
2
  apply,
3
3
  collectDoctorResult,
4
4
  detect,
5
+ devLink,
6
+ devStatus,
7
+ devUnlink,
5
8
  doctor,
6
9
  init,
7
10
  integrationDoctor,
@@ -10,11 +13,14 @@ import {
10
13
  reportCommandError,
11
14
  teardown,
12
15
  writeCommandOutput
13
- } from "./chunk-2MOEVONN.js";
16
+ } from "./chunk-7ABJRH3F.js";
14
17
  export {
15
18
  apply,
16
19
  collectDoctorResult,
17
20
  detect,
21
+ devLink,
22
+ devStatus,
23
+ devUnlink,
18
24
  doctor,
19
25
  init,
20
26
  integrationDoctor,
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inspecto-dev/cli",
3
- "version": "0.3.4",
3
+ "version": "0.3.6",
4
4
  "description": "CLI tools for Inspecto onboarding and lifecycle management",
5
5
  "keywords": [
6
6
  "inspecto",
@@ -20,7 +20,7 @@
20
20
  "ora": "^9.3.0",
21
21
  "picocolors": "^1.0.0",
22
22
  "prompts": "^2.4.2",
23
- "@inspecto-dev/types": "0.3.4"
23
+ "@inspecto-dev/types": "0.3.6"
24
24
  },
25
25
  "devDependencies": {
26
26
  "@types/node": "^20.19.39",
package/src/bin.ts CHANGED
@@ -8,6 +8,7 @@ import { fileURLToPath } from 'node:url'
8
8
  import { createRequire } from 'node:module'
9
9
  import { apply } from './commands/apply.js'
10
10
  import { detect } from './commands/detect.js'
11
+ import { devLink, devStatus, devUnlink } from './commands/dev-config.js'
11
12
  import { init } from './commands/init.js'
12
13
  import { doctor } from './commands/doctor.js'
13
14
  import { onboard } from './commands/onboard.js'
@@ -69,6 +70,11 @@ interface IntegrationCommandOptions extends JsonCommandOptions {
69
70
  force?: boolean
70
71
  }
71
72
 
73
+ interface DevCommandOptions extends JsonCommandOptions {
74
+ cliBin?: string
75
+ repo?: string
76
+ }
77
+
72
78
  const integrationScopes = ['project', 'user'] as const
73
79
  const integrationModes = ['skills', 'instructions', 'agents', 'rules'] as const
74
80
 
@@ -83,6 +89,45 @@ function exitWithError(error: unknown, options: JsonCommandOptions = {}): never
83
89
  export function createCli(_argv: readonly string[] = process.argv): CAC {
84
90
  const cli: CAC = cac('inspecto')
85
91
 
92
+ cli
93
+ .command('dev <subcommand>', 'Manage project-local Inspecto development overrides')
94
+ .option('--cli-bin <path>', 'Point this project at a local CLI dist/bin.js')
95
+ .option('--repo <path>', 'Point this project at a local Inspecto repository root')
96
+ .option('--json', 'Print machine-readable JSON output', { default: false })
97
+ .option('--debug', 'Enable debug mode to show full error traces', { default: false })
98
+ .action(async (subcommand: string, options: DevCommandOptions) => {
99
+ try {
100
+ if (subcommand === 'link') {
101
+ if (!options.cliBin && !options.repo) {
102
+ throw new Error('The `dev link` subcommand requires --cli-bin <path> or --repo <path>.')
103
+ }
104
+
105
+ await devLink({
106
+ ...(options.cliBin ? { cliBin: options.cliBin } : {}),
107
+ ...(options.repo ? { devRepo: options.repo } : {}),
108
+ json: options.json ?? false,
109
+ })
110
+ return
111
+ }
112
+
113
+ if (subcommand === 'status') {
114
+ await devStatus(options.json ?? false)
115
+ return
116
+ }
117
+
118
+ if (subcommand === 'unlink') {
119
+ await devUnlink(options.json ?? false)
120
+ return
121
+ }
122
+
123
+ throw new Error(
124
+ 'Usage:\n inspecto dev link [--cli-bin <path>] [--repo <path>]\n inspecto dev status [--json]\n inspecto dev unlink [--json]',
125
+ )
126
+ } catch (error) {
127
+ exitWithError(error, options)
128
+ }
129
+ })
130
+
86
131
  cli
87
132
  .command('init', 'Set up Inspecto in your project')
88
133
  .option('--shared', 'Share .inspecto/settings.json with your team via Git', { default: false })
@@ -0,0 +1,109 @@
1
+ import path from 'node:path'
2
+ import { readJSON, removeFile, writeJSON } from '../utils/fs.js'
3
+ import { updateGitignore } from '../inject/gitignore.js'
4
+ import { log } from '../utils/logger.js'
5
+ import { writeCommandOutput } from '../utils/output.js'
6
+
7
+ export interface InspectoDevConfig {
8
+ cliBin?: string
9
+ devRepo?: string
10
+ }
11
+
12
+ export interface DevConfigCommandResult {
13
+ status: 'ok'
14
+ configPath: string
15
+ config: InspectoDevConfig
16
+ }
17
+
18
+ interface DevLinkOptions {
19
+ cliBin?: string
20
+ devRepo?: string
21
+ json?: boolean
22
+ }
23
+
24
+ const DEV_CONFIG_PATH = path.join('.inspecto', 'dev.json')
25
+
26
+ function absoluteDevConfigPath(root: string): string {
27
+ return path.join(root, DEV_CONFIG_PATH)
28
+ }
29
+
30
+ function printDevConfigResult(result: DevConfigCommandResult): void {
31
+ log.header('Inspecto Dev')
32
+ log.info(`Config: ${result.configPath}`)
33
+ if (result.config.cliBin) {
34
+ log.hint(`cliBin: ${result.config.cliBin}`)
35
+ }
36
+ if (result.config.devRepo) {
37
+ log.hint(`devRepo: ${result.config.devRepo}`)
38
+ }
39
+ if (!result.config.cliBin && !result.config.devRepo) {
40
+ log.hint('No local dev overrides are configured.')
41
+ }
42
+ }
43
+
44
+ async function readExistingConfig(root: string): Promise<InspectoDevConfig> {
45
+ const configPath = absoluteDevConfigPath(root)
46
+ const config = await readJSON<InspectoDevConfig>(configPath)
47
+ if (!config || typeof config !== 'object') {
48
+ return {}
49
+ }
50
+
51
+ return config
52
+ }
53
+
54
+ export async function devLink(options: DevLinkOptions): Promise<DevConfigCommandResult> {
55
+ const root = process.cwd()
56
+ const configPath = absoluteDevConfigPath(root)
57
+ const existing = await readExistingConfig(root)
58
+ const nextConfig: InspectoDevConfig = {
59
+ ...existing,
60
+ ...(options.cliBin ? { cliBin: options.cliBin } : {}),
61
+ ...(options.devRepo ? { devRepo: options.devRepo } : {}),
62
+ }
63
+
64
+ await writeJSON(configPath, nextConfig)
65
+ await updateGitignore(root, false, false, true)
66
+
67
+ return writeCommandOutput(
68
+ {
69
+ status: 'ok',
70
+ configPath,
71
+ config: nextConfig,
72
+ },
73
+ options.json ?? false,
74
+ printDevConfigResult,
75
+ )
76
+ }
77
+
78
+ export async function devStatus(json = false): Promise<DevConfigCommandResult> {
79
+ const root = process.cwd()
80
+ const configPath = absoluteDevConfigPath(root)
81
+ const config = await readExistingConfig(root)
82
+
83
+ return writeCommandOutput(
84
+ {
85
+ status: 'ok',
86
+ configPath,
87
+ config,
88
+ },
89
+ json,
90
+ printDevConfigResult,
91
+ )
92
+ }
93
+
94
+ export async function devUnlink(json = false): Promise<DevConfigCommandResult> {
95
+ const root = process.cwd()
96
+ const configPath = absoluteDevConfigPath(root)
97
+
98
+ await removeFile(configPath)
99
+
100
+ return writeCommandOutput(
101
+ {
102
+ status: 'ok',
103
+ configPath,
104
+ config: {},
105
+ },
106
+ json,
107
+ printDevConfigResult,
108
+ )
109
+ }
@@ -10,8 +10,15 @@ import { detectFrameworks } from '../detect/framework.js'
10
10
  import { detectIDE } from '../detect/ide.js'
11
11
  import { detectProviders } from '../detect/provider.js'
12
12
  import { isExtensionInstalled } from '../inject/extension.js'
13
+ import { createPlanResult } from '../onboarding/planner.js'
13
14
  import { writeCommandOutput } from '../utils/output.js'
14
- import type { CommandStatus, DoctorDiagnostic, DoctorResult } from '../types.js'
15
+ import type {
16
+ CommandStatus,
17
+ DoctorDiagnostic,
18
+ DoctorResult,
19
+ OnboardingContext,
20
+ PlanResult,
21
+ } from '../types.js'
15
22
 
16
23
  export interface DoctorCommandOptions {
17
24
  json?: boolean
@@ -39,6 +46,113 @@ function doctorStatus(errors: number, warnings: number): CommandStatus {
39
46
  return 'ok'
40
47
  }
41
48
 
49
+ function isGuidedMetaFramework(buildTool: string): boolean {
50
+ return buildTool === 'Next.js' || buildTool === 'Nuxt'
51
+ }
52
+
53
+ function buildDoctorOnboardingContext(input: {
54
+ root: string
55
+ packageManager: NonNullable<DoctorResult['project']['packageManager']>
56
+ buildTools: Awaited<ReturnType<typeof detectBuildTools>>
57
+ frameworks: Awaited<ReturnType<typeof detectFrameworks>>
58
+ ides: Awaited<ReturnType<typeof detectIDE>>
59
+ providers: Awaited<ReturnType<typeof detectProviders>>
60
+ }): OnboardingContext {
61
+ return {
62
+ root: input.root,
63
+ packageManager: input.packageManager,
64
+ buildTools: input.buildTools,
65
+ frameworks: {
66
+ supported: input.frameworks.supported,
67
+ unsupported: input.frameworks.unsupported.map(item => item.name),
68
+ },
69
+ ides: input.ides.detected.map(({ ide, supported }) => ({ ide, supported })),
70
+ providers: input.providers.detected.map(({ id, label, supported, preferredMode }) => ({
71
+ id,
72
+ label,
73
+ supported,
74
+ preferredMode,
75
+ })),
76
+ }
77
+ }
78
+
79
+ function isConfigPatchReason(reason: string): boolean {
80
+ return reason.startsWith('next_config_') || reason.startsWith('nuxt_config_')
81
+ }
82
+
83
+ function isNextWebpackDevPatchReason(reason: string): boolean {
84
+ return reason === 'next_dev_script_requires_webpack'
85
+ }
86
+
87
+ async function collectGuidedPatchDiagnostics(
88
+ root: string,
89
+ plan: PlanResult,
90
+ ): Promise<DoctorDiagnostic[]> {
91
+ if (plan.strategy !== 'guided' || !plan.patches?.length) {
92
+ return []
93
+ }
94
+
95
+ const diagnostics: DoctorDiagnostic[] = []
96
+
97
+ for (const patch of plan.patches) {
98
+ if (isConfigPatchReason(patch.reason)) {
99
+ const content = await readFile(path.join(root, patch.path))
100
+ if (content?.includes('@inspecto-dev/plugin')) {
101
+ diagnostics.push(
102
+ createDiagnostic(
103
+ 'guided-config-patch-detected',
104
+ 'ok',
105
+ `Guided config patch appears to be applied in ${patch.path}`,
106
+ [],
107
+ { path: patch.path, reason: patch.reason },
108
+ ),
109
+ )
110
+ } else {
111
+ diagnostics.push(
112
+ createDiagnostic(
113
+ 'guided-config-patch-pending',
114
+ 'warning',
115
+ `Guided config patch still needs review in ${patch.path}`,
116
+ ['Run `inspecto onboard --json` to review the generated patch details.'],
117
+ { path: patch.path, reason: patch.reason },
118
+ ),
119
+ )
120
+ }
121
+ continue
122
+ }
123
+
124
+ if (isNextWebpackDevPatchReason(patch.reason)) {
125
+ const packageJson = await readJSON<{ scripts?: Record<string, string> }>(
126
+ path.join(root, 'package.json'),
127
+ )
128
+ const devScript = packageJson?.scripts?.dev ?? ''
129
+ if (/next\s+dev\b/.test(devScript) && /--webpack\b/.test(devScript)) {
130
+ diagnostics.push(
131
+ createDiagnostic(
132
+ 'guided-dev-script-configured',
133
+ 'ok',
134
+ 'Next.js dev script is configured for webpack mode',
135
+ [],
136
+ { script: devScript },
137
+ ),
138
+ )
139
+ } else {
140
+ diagnostics.push(
141
+ createDiagnostic(
142
+ 'guided-dev-script-pending',
143
+ 'warning',
144
+ 'Next.js dev script still needs webpack mode for Inspecto validation',
145
+ ['Update the `dev` script to `next dev --webpack` before browser validation.'],
146
+ { script: devScript },
147
+ ),
148
+ )
149
+ }
150
+ }
151
+ }
152
+
153
+ return diagnostics
154
+ }
155
+
42
156
  function printDoctorResult(result: DoctorResult): void {
43
157
  log.header('Inspecto Doctor')
44
158
 
@@ -99,6 +213,15 @@ export async function collectDoctorResult(root = process.cwd()): Promise<DoctorR
99
213
  detectBuildTools(root),
100
214
  isExtensionInstalled(),
101
215
  ])
216
+ const onboardingContext = buildDoctorOnboardingContext({
217
+ root,
218
+ packageManager: pm,
219
+ buildTools: buildResult,
220
+ frameworks: frameworkResult,
221
+ ides: ideProbe,
222
+ providers: providerProbe,
223
+ })
224
+ const onboardingPlan = createPlanResult(onboardingContext)
102
225
 
103
226
  // Check 2: IDE
104
227
  if (ideProbe.detected.length === 0) {
@@ -229,15 +352,45 @@ export async function collectDoctorResult(root = process.cwd()): Promise<DoctorR
229
352
  )
230
353
  }
231
354
  } else if (buildResult.unsupported.length > 0) {
232
- const names = buildResult.unsupported.join(', ')
233
- checks.push(
234
- createDiagnostic(
235
- `build-tool-unsupported`,
236
- 'warning',
237
- `Build tool: ${names} (not supported in v1)`,
238
- ['current version supports: Vite, Webpack, Rspack, esbuild, Rollup'],
239
- ),
355
+ const guidedBuildTools = buildResult.unsupported.filter(isGuidedMetaFramework)
356
+ const trulyUnsupportedBuildTools = buildResult.unsupported.filter(
357
+ buildTool => !isGuidedMetaFramework(buildTool),
240
358
  )
359
+
360
+ if (guidedBuildTools.length > 0) {
361
+ checks.push(
362
+ createDiagnostic(
363
+ 'build-tool-guided',
364
+ 'warning',
365
+ `Build tool: ${guidedBuildTools.join(', ')} (guided onboarding available)`,
366
+ [
367
+ 'Run `inspecto onboard --json` to generate the remaining patch plan and assistant handoff.',
368
+ ...(onboardingPlan.pendingSteps ?? []),
369
+ ],
370
+ {
371
+ metaFrameworks: guidedBuildTools,
372
+ ...(onboardingPlan.pendingSteps ? { pendingSteps: onboardingPlan.pendingSteps } : {}),
373
+ ...(onboardingPlan.assistantPrompt
374
+ ? { assistantPrompt: onboardingPlan.assistantPrompt }
375
+ : {}),
376
+ ...(onboardingPlan.patches ? { patchCount: onboardingPlan.patches.length } : {}),
377
+ },
378
+ ),
379
+ )
380
+ }
381
+
382
+ checks.push(...(await collectGuidedPatchDiagnostics(root, onboardingPlan)))
383
+
384
+ if (trulyUnsupportedBuildTools.length > 0) {
385
+ checks.push(
386
+ createDiagnostic(
387
+ 'build-tool-unsupported',
388
+ 'warning',
389
+ `Build tool: ${trulyUnsupportedBuildTools.join(', ')} (not supported in v1)`,
390
+ ['current version supports: Vite, Webpack, Rspack, esbuild, Rollup'],
391
+ ),
392
+ )
393
+ }
241
394
  } else {
242
395
  checks.push(
243
396
  createDiagnostic('build-tool-missing', 'warning', 'No recognized build config found'),
@@ -24,7 +24,11 @@ import {
24
24
  promptMonorepoPackageChoice,
25
25
  promptUnsupportedFrameworkContinue,
26
26
  } from '../prompts.js'
27
- import { printNextJsManualInstructions, printNuxtManualInstructions } from '../instructions.js'
27
+ import {
28
+ printNextJsManualInstructions,
29
+ printNuxtManualInstructions,
30
+ printUmiManualInstructions,
31
+ } from '../instructions.js'
28
32
 
29
33
  export async function init(options: InitOptions): Promise<void> {
30
34
  const repoRoot = process.cwd()
@@ -175,8 +179,8 @@ export async function init(options: InitOptions): Promise<void> {
175
179
  if (buildResult.unsupported.length > 0) {
176
180
  const names = buildResult.unsupported.join(', ')
177
181
  manualConfigRequiredFor = buildResult.unsupported[0] || ''
178
- log.warn(`Detected ${names} — automatic plugin injection is not supported in current version`)
179
- log.hint('You can still manually configure it by modifying your configuration file')
182
+ log.warn(`Detected ${names} — guided onboarding is available in the current version`)
183
+ log.hint('Inspecto can prepare the remaining patch plan and assistant handoff for this stack.')
180
184
 
181
185
  if (buildResult.unsupported.includes('Next.js')) {
182
186
  printNextJsManualInstructions()
@@ -184,6 +188,9 @@ export async function init(options: InitOptions): Promise<void> {
184
188
  if (buildResult.unsupported.includes('Nuxt')) {
185
189
  printNuxtManualInstructions()
186
190
  }
191
+ if (buildResult.unsupported.includes('Umi')) {
192
+ printUmiManualInstructions()
193
+ }
187
194
  }
188
195
  if (buildResult.supported.length === 0 && buildResult.unsupported.length === 0) {
189
196
  log.warn('No recognized build tool detected')
@@ -24,6 +24,7 @@ interface IntegrationAutomationOptions {
24
24
  inspectoVsix?: string
25
25
  preview?: boolean
26
26
  silent?: boolean
27
+ ignoreProjectArtifacts?: boolean
27
28
  }
28
29
 
29
30
  interface IntegrationAutomationDetails {
@@ -93,6 +94,7 @@ export async function runIntegrationAutomation(
93
94
  const resolvedHostIde = await resolveIntegrationHostIde({
94
95
  ...(options.ide ? { explicitIde: options.ide } : {}),
95
96
  ...(cwd ? { cwd } : {}),
97
+ ...(options.ignoreProjectArtifacts ? { ignoreProjectArtifacts: true } : {}),
96
98
  })
97
99
 
98
100
  const details: IntegrationAutomationDetails = {
@@ -12,6 +12,7 @@ export type HostIdeSource = 'explicit' | 'config' | 'env' | 'artifact' | 'ambigu
12
12
  export interface ResolveIntegrationHostIdeOptions {
13
13
  explicitIde?: string
14
14
  cwd?: string
15
+ ignoreProjectArtifacts?: boolean
15
16
  }
16
17
 
17
18
  export interface ResolvedIntegrationHostIde {
@@ -51,7 +52,7 @@ export async function resolveIntegrationHostIde(
51
52
  const envCandidates = detectEnvHostIdes()
52
53
  if (envCandidates.length === 1) {
53
54
  return {
54
- ide: envCandidates[0],
55
+ ide: envCandidates[0]!,
55
56
  confidence: 'high',
56
57
  source: 'env',
57
58
  candidates: envCandidates,
@@ -67,22 +68,24 @@ export async function resolveIntegrationHostIde(
67
68
  }
68
69
  }
69
70
 
70
- const artifactCandidates = await detectArtifactHostIdes(cwd)
71
- if (artifactCandidates.length === 1) {
72
- return {
73
- ide: artifactCandidates[0],
74
- confidence: 'medium',
75
- source: 'artifact',
76
- candidates: artifactCandidates,
71
+ if (!options.ignoreProjectArtifacts) {
72
+ const artifactCandidates = await detectArtifactHostIdes(cwd)
73
+ if (artifactCandidates.length === 1) {
74
+ return {
75
+ ide: artifactCandidates[0]!,
76
+ confidence: 'medium',
77
+ source: 'artifact',
78
+ candidates: artifactCandidates,
79
+ }
77
80
  }
78
- }
79
81
 
80
- if (artifactCandidates.length > 1) {
81
- return {
82
- ide: null,
83
- confidence: 'low',
84
- source: 'ambiguous',
85
- candidates: artifactCandidates,
82
+ if (artifactCandidates.length > 1) {
83
+ return {
84
+ ide: null,
85
+ confidence: 'low',
86
+ source: 'ambiguous',
87
+ candidates: artifactCandidates,
88
+ }
86
89
  }
87
90
  }
88
91
 
@@ -266,7 +266,7 @@ export async function installIntegration(
266
266
 
267
267
  const automationResult = await runIntegrationAutomation(
268
268
  assistant,
269
- { ...options, silent },
269
+ { ...options, silent, ignoreProjectArtifacts: true },
270
270
  process.cwd(),
271
271
  )
272
272
  const result: IntegrationInstallResult = {