create-quiver 0.14.1 → 0.15.1

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 (94) hide show
  1. package/CHANGELOG.md +22 -0
  2. package/README.md +35 -0
  3. package/README_FOR_AI.md +15 -4
  4. package/ROADMAP.md +13 -2
  5. package/docs/AI_CONTEXT.md.template +4 -0
  6. package/docs/AI_ONBOARDING_PROMPT.md.template +8 -0
  7. package/docs/CLI_UX_GUIDE.md +79 -4
  8. package/docs/COMMANDS.md.template +21 -5
  9. package/docs/TROUBLESHOOTING.md +70 -0
  10. package/docs/TROUBLESHOOTING.md.template +20 -0
  11. package/docs/getting-started/installation.md +86 -0
  12. package/docs/reference/commands.md +33 -1
  13. package/package.json +1 -1
  14. package/specs/quiver-v30-interactive-cli-ux-agent-selection/EVIDENCE_REPORT.md +213 -0
  15. package/specs/quiver-v30-interactive-cli-ux-agent-selection/EXECUTION_PLAN.md +85 -0
  16. package/specs/quiver-v30-interactive-cli-ux-agent-selection/SPEC.md +213 -0
  17. package/specs/quiver-v30-interactive-cli-ux-agent-selection/STATUS.md +31 -0
  18. package/specs/quiver-v30-interactive-cli-ux-agent-selection/pr.md +103 -0
  19. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +33 -0
  20. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +56 -0
  21. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-00-spec-foundation/slice.json +71 -0
  22. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-01-cli-ux-runtime-progress-engine/CLOSURE_BRIEF.md +31 -0
  23. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-01-cli-ux-runtime-progress-engine/EXECUTION_BRIEF.md +54 -0
  24. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-01-cli-ux-runtime-progress-engine/slice.json +69 -0
  25. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-02-agent-profile-selection-selectors/CLOSURE_BRIEF.md +33 -0
  26. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-02-agent-profile-selection-selectors/EXECUTION_BRIEF.md +56 -0
  27. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-02-agent-profile-selection-selectors/slice.json +81 -0
  28. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-03-provider-model-selection-contract/CLOSURE_BRIEF.md +32 -0
  29. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-03-provider-model-selection-contract/EXECUTION_BRIEF.md +54 -0
  30. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-03-provider-model-selection-contract/slice.json +75 -0
  31. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-04-planner-ia-progress-flows/CLOSURE_BRIEF.md +32 -0
  32. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-04-planner-ia-progress-flows/EXECUTION_BRIEF.md +57 -0
  33. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-04-planner-ia-progress-flows/slice.json +85 -0
  34. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-05-executor-pr-progress-flows/CLOSURE_BRIEF.md +33 -0
  35. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-05-executor-pr-progress-flows/EXECUTION_BRIEF.md +57 -0
  36. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-05-executor-pr-progress-flows/slice.json +85 -0
  37. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-06-doctor-visual-json-contract/CLOSURE_BRIEF.md +35 -0
  38. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-06-doctor-visual-json-contract/EXECUTION_BRIEF.md +55 -0
  39. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-06-doctor-visual-json-contract/slice.json +81 -0
  40. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-07-interactive-init-spec-create/CLOSURE_BRIEF.md +34 -0
  41. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-07-interactive-init-spec-create/EXECUTION_BRIEF.md +55 -0
  42. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-07-interactive-init-spec-create/slice.json +85 -0
  43. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-08-tests-docs-cross-platform-release/CLOSURE_BRIEF.md +34 -0
  44. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-08-tests-docs-cross-platform-release/EXECUTION_BRIEF.md +59 -0
  45. package/specs/quiver-v30-interactive-cli-ux-agent-selection/slices/slice-08-tests-docs-cross-platform-release/slice.json +95 -0
  46. package/specs/quiver-v31-ai-model-catalog-agent-selection/EVIDENCE_REPORT.md +185 -0
  47. package/specs/quiver-v31-ai-model-catalog-agent-selection/EXECUTION_PLAN.md +85 -0
  48. package/specs/quiver-v31-ai-model-catalog-agent-selection/SPEC.md +337 -0
  49. package/specs/quiver-v31-ai-model-catalog-agent-selection/STATUS.md +30 -0
  50. package/specs/quiver-v31-ai-model-catalog-agent-selection/pr.md +98 -0
  51. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-00-spec-foundation/CLOSURE_BRIEF.md +30 -0
  52. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-00-spec-foundation/EXECUTION_BRIEF.md +51 -0
  53. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-00-spec-foundation/slice.json +62 -0
  54. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-01-model-catalog-alias-normalization/CLOSURE_BRIEF.md +32 -0
  55. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-01-model-catalog-alias-normalization/EXECUTION_BRIEF.md +53 -0
  56. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-01-model-catalog-alias-normalization/slice.json +72 -0
  57. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-02-interactive-agent-set-selectors/CLOSURE_BRIEF.md +36 -0
  58. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-02-interactive-agent-set-selectors/EXECUTION_BRIEF.md +56 -0
  59. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-02-interactive-agent-set-selectors/slice.json +78 -0
  60. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-03-agent-doctor-repair/CLOSURE_BRIEF.md +36 -0
  61. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-03-agent-doctor-repair/EXECUTION_BRIEF.md +57 -0
  62. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-03-agent-doctor-repair/slice.json +77 -0
  63. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-04-shared-preflight-provider-errors/CLOSURE_BRIEF.md +35 -0
  64. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-04-shared-preflight-provider-errors/EXECUTION_BRIEF.md +55 -0
  65. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-04-shared-preflight-provider-errors/slice.json +84 -0
  66. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-05-ai-models-list/CLOSURE_BRIEF.md +32 -0
  67. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-05-ai-models-list/EXECUTION_BRIEF.md +52 -0
  68. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-05-ai-models-list/slice.json +72 -0
  69. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-06-docs-templates-alignment/CLOSURE_BRIEF.md +33 -0
  70. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-06-docs-templates-alignment/EXECUTION_BRIEF.md +58 -0
  71. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-06-docs-templates-alignment/slice.json +84 -0
  72. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-07-tests-smokes-release-readiness/CLOSURE_BRIEF.md +32 -0
  73. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-07-tests-smokes-release-readiness/EXECUTION_BRIEF.md +59 -0
  74. package/specs/quiver-v31-ai-model-catalog-agent-selection/slices/slice-07-tests-smokes-release-readiness/slice.json +94 -0
  75. package/specs/quiver-v32-npx-installation-guidance/EVIDENCE_REPORT.md +26 -0
  76. package/specs/quiver-v32-npx-installation-guidance/SPEC.md +55 -0
  77. package/specs/quiver-v32-npx-installation-guidance/STATUS.md +23 -0
  78. package/specs/quiver-v32-npx-installation-guidance/pr.md +72 -0
  79. package/specs/quiver-v32-npx-installation-guidance/slices/slice-00-installation-docs/CLOSURE_BRIEF.md +31 -0
  80. package/specs/quiver-v32-npx-installation-guidance/slices/slice-00-installation-docs/EXECUTION_BRIEF.md +56 -0
  81. package/specs/quiver-v32-npx-installation-guidance/slices/slice-00-installation-docs/slice.json +75 -0
  82. package/src/create-quiver/commands/ai.js +797 -99
  83. package/src/create-quiver/commands/flow.js +2 -2
  84. package/src/create-quiver/commands/spec.js +106 -6
  85. package/src/create-quiver/index.js +557 -78
  86. package/src/create-quiver/lib/agent-profiles.js +440 -11
  87. package/src/create-quiver/lib/ai/execution-plan.js +111 -8
  88. package/src/create-quiver/lib/ai/executor.js +291 -28
  89. package/src/create-quiver/lib/ai/model-catalog.js +333 -0
  90. package/src/create-quiver/lib/ai/providers.js +211 -2
  91. package/src/create-quiver/lib/cli/selectors.js +160 -0
  92. package/src/create-quiver/lib/cli/theme.js +5 -2
  93. package/src/create-quiver/lib/cli/ux-flags.js +18 -0
  94. package/src/create-quiver/lib/cli/ux.js +100 -5
@@ -22,6 +22,7 @@ const {
22
22
  runLifecycleResume: runAiLifecycleResume,
23
23
  runLifecycleRun: runAiLifecycleRun,
24
24
  runLifecycleStatus: runAiLifecycleStatus,
25
+ runModelsList: runAiModelsList,
25
26
  runOnboard,
26
27
  runPlan: runAiPlan,
27
28
  runPrepareContext: runAiPrepareContext,
@@ -53,6 +54,8 @@ const { checkPrReadiness, checkScope, checkSliceReadiness } = require('./lib/rea
53
54
  const { cleanupSlice, refreshActiveSlicesBoard, startSlice } = require('./lib/lifecycle');
54
55
  const { buildSpecStatus, closeSpecWorktree, formatSpecCloseResult, formatSpecStartResult, formatSpecStatus, startSpecWorktree } = require('./lib/spec-worktrees');
55
56
  const { getContextPathExclusionReason } = require('./lib/ai/safety');
57
+ const { selectOption } = require('./lib/cli/selectors');
58
+ const { createUx } = require('./lib/cli/ux');
56
59
  const { validateUxFlags } = require('./lib/cli/ux-flags');
57
60
  const { relativePosixPath, resolveTargetRoot } = require('./lib/paths');
58
61
  const {
@@ -170,7 +173,8 @@ const COMMAND_HELP_GROUPS = [
170
173
  ['ai resume', 'Resume guidance from the last valid lifecycle phase without chat memory.'],
171
174
  ['ai onboard', 'Run or print the planner onboarding prompt with a token-aware context pack.'],
172
175
  ['ai prepare-context', 'Preview or write docs-only AI context updates with assumptions and risks.'],
173
- ['ai agent set|list|show', 'Manage planner, executor, reviewer, and doctor provider profiles without secrets; use set --dry-run to preview.'],
176
+ ['ai agent set|list|show|doctor|repair', 'Manage, diagnose, and dry-run repair planner, executor, reviewer, and doctor provider profiles without secrets.'],
177
+ ['ai models list', 'List provider/model ids known by Quiver without claiming account availability.'],
174
178
  ['ai plan', 'Generate versioned planner drafts for acceptance criteria, technical plan, or spec phase.'],
175
179
  ['ai revise', 'Create a new planner draft from human feedback without approving it.'],
176
180
  ['ai repair-plan', 'Repair an approved technical plan into a new structured draft without mutating the approved artifact.'],
@@ -259,7 +263,8 @@ function printUsage() {
259
263
  npx create-quiver ai specs list [--json]
260
264
  npx create-quiver ai slices list [--json]
261
265
  npx create-quiver ai trace report [options]
262
- npx create-quiver ai agent <set|list|show> [role] [options]
266
+ npx create-quiver ai agent <set|list|show|doctor|repair> [role] [options]
267
+ npx create-quiver ai models list [--provider codex|claude|gemini] [--json]
263
268
  npx create-quiver ai prepare-context [options]
264
269
  npx create-quiver ai revise [options]
265
270
  npx create-quiver ai repair-plan [options]
@@ -310,6 +315,7 @@ Options:
310
315
  --with-planner Enable planner-assisted behavior on commands that explicitly support it
311
316
  --interactive Enable prompts on commands that explicitly support interactive choices
312
317
  --review Open or prepare human review before persistent writes where supported
318
+ --methodology <name> Select methodology where supported (currently wdd-sdd)
313
319
  --no-color Disable ANSI colors in human output
314
320
  --fix For doctor, apply safe non-destructive repairs
315
321
  --execute For ai execute-plan, run the planned slices instead of printing commands
@@ -318,7 +324,7 @@ Options:
318
324
  --allow-dirty For ai execute-slice, allow pre-existing dirty files and ignore them for scope diff
319
325
  --mode <name> Execution mode for ai execute-plan (auto, manual, delegated)
320
326
  --provider <name> Provider CLI to preflight for prepare or AI commands
321
- --model <label> Free-form model label for AI agent profiles
327
+ --model <model-id> Technical model id for AI agent profiles or provider-backed AI commands
322
328
  --version <n> Draft version to approve for AI planner phases
323
329
  --run <id> AI lifecycle run id
324
330
  --ssh-host-alias <name> SSH host alias to validate for prepare or AI commands
@@ -334,6 +340,7 @@ Options:
334
340
 
335
341
  Examples:
336
342
  npx create-quiver init --name "My Project"
343
+ npx create-quiver init --interactive
337
344
  npx create-quiver init --name "My Project" --dry-run
338
345
  npx create-quiver --name "My Project"
339
346
  npx create-quiver --name "My Project" --dir ./my-project
@@ -355,7 +362,10 @@ Examples:
355
362
  cd ./my-project && npx create-quiver ai trace report
356
363
  cd ./my-project && npx create-quiver ai agent set planner --provider codex --model gpt-5.5 --dry-run
357
364
  cd ./my-project && npx create-quiver ai agent set planner --provider codex --model gpt-5.5
365
+ cd ./my-project && npx create-quiver ai agent doctor
366
+ cd ./my-project && npx create-quiver ai agent repair --dry-run
358
367
  cd ./my-project && npx create-quiver ai agent list
368
+ cd ./my-project && npx create-quiver ai models list --provider codex
359
369
  cd ./my-project && npx create-quiver ai plan --phase acceptance --input requirements.md --dry-run
360
370
  cd ./my-project && npx create-quiver ai revise --phase acceptance --input feedback.md --dry-run
361
371
  cd ./my-project && npx create-quiver ai approve --phase acceptance --version 1
@@ -434,6 +444,7 @@ function parseArgs(argv) {
434
444
  format: 'tree',
435
445
  formatExplicit: false,
436
446
  showConflicts: false,
447
+ methodology: '',
437
448
  level: null,
438
449
  unicode: false,
439
450
  aiCommand: '',
@@ -749,6 +760,74 @@ function parseArgs(argv) {
749
760
  continue;
750
761
  }
751
762
 
763
+ if (arg === '--id') {
764
+ const value = args[++index];
765
+ if (!value) {
766
+ throw new Error(formatError('missing value for --id'));
767
+ }
768
+ result.aiProfileId = value;
769
+ continue;
770
+ }
771
+
772
+ if (arg === '--display-name') {
773
+ const value = args[++index];
774
+ if (!value) {
775
+ throw new Error(formatError('missing value for --display-name'));
776
+ }
777
+ result.aiDisplayName = value;
778
+ continue;
779
+ }
780
+
781
+ if (arg === '--default') {
782
+ result.aiDefaultProfile = true;
783
+ continue;
784
+ }
785
+
786
+ if (arg === '--planner') {
787
+ const value = args[++index];
788
+ if (!value) {
789
+ throw new Error(formatError('missing value for --planner'));
790
+ }
791
+ result.aiPlannerProfile = value;
792
+ continue;
793
+ }
794
+
795
+ if (arg === '--executor') {
796
+ const value = args[++index];
797
+ if (!value) {
798
+ throw new Error(formatError('missing value for --executor'));
799
+ }
800
+ result.aiExecutorProfile = value;
801
+ continue;
802
+ }
803
+
804
+ if (arg === '--reviewer') {
805
+ const value = args[++index];
806
+ if (!value) {
807
+ throw new Error(formatError('missing value for --reviewer'));
808
+ }
809
+ result.aiReviewerProfile = value;
810
+ continue;
811
+ }
812
+
813
+ if (arg === '--doctor') {
814
+ const value = args[++index];
815
+ if (!value) {
816
+ throw new Error(formatError('missing value for --doctor'));
817
+ }
818
+ result.aiDoctorProfile = value;
819
+ continue;
820
+ }
821
+
822
+ if (arg === '--methodology') {
823
+ const value = args[++index];
824
+ if (!value) {
825
+ throw new Error(formatError('missing value for --methodology'));
826
+ }
827
+ result.methodology = value;
828
+ continue;
829
+ }
830
+
752
831
  if (arg === '--label') {
753
832
  const value = args[++index];
754
833
  if (!value) {
@@ -977,10 +1056,10 @@ function parseArgs(argv) {
977
1056
  if (result.aiCommand === 'run' && !result.aiRunCommand && positional.length > 0) {
978
1057
  result.aiRunCommand = positional.shift();
979
1058
  }
980
- if ((result.aiCommand === 'specs' || result.aiCommand === 'slices' || result.aiCommand === 'trace' || result.aiCommand === 'active-slice') && !result.aiSecondaryCommand && positional.length > 0) {
1059
+ if ((result.aiCommand === 'specs' || result.aiCommand === 'slices' || result.aiCommand === 'models' || result.aiCommand === 'trace' || result.aiCommand === 'active-slice') && !result.aiSecondaryCommand && positional.length > 0) {
981
1060
  result.aiSecondaryCommand = positional.shift();
982
1061
  }
983
- if ((result.aiCommand === 'specs' || result.aiCommand === 'slices') && result.aiSecondaryCommand && result.aiSecondaryCommand !== 'list') {
1062
+ if ((result.aiCommand === 'specs' || result.aiCommand === 'slices' || result.aiCommand === 'models') && result.aiSecondaryCommand && result.aiSecondaryCommand !== 'list') {
984
1063
  throw new Error(formatError(`unsupported ai ${result.aiCommand} subcommand: ${result.aiSecondaryCommand}. Supported tasks: list`));
985
1064
  }
986
1065
  if (result.aiCommand === 'trace' && result.aiSecondaryCommand && result.aiSecondaryCommand !== 'report') {
@@ -2174,28 +2253,21 @@ function runMigrate(targetDir, options = {}) {
2174
2253
  }
2175
2254
  }
2176
2255
 
2177
- function runDoctor(targetDir, options = {}) {
2178
- const projectRoot = resolveTargetRoot(process.cwd(), targetDir);
2179
-
2180
- if (!fs.existsSync(projectRoot)) {
2181
- throw new Error(formatError(`target directory does not exist: ${projectRoot}`));
2182
- }
2183
-
2184
- if (!hasQuiverInitializationEvidence(projectRoot)) {
2185
- throw new Error(formatError('doctor requires a project previously initialized by Quiver.\nRun init first: npx create-quiver --name "Project Name"'));
2186
- }
2187
-
2188
- const fixPlan = buildDoctorFixPlan(projectRoot);
2189
- if (options.fix) {
2190
- if (options.dryRun) {
2191
- console.log(formatDoctorFixPlan(fixPlan, { dryRun: true }));
2192
- return;
2256
+ function uniqueLines(lines) {
2257
+ const seen = new Set();
2258
+ const unique = [];
2259
+ for (const line of lines) {
2260
+ const value = String(line || '').trim();
2261
+ if (!value || seen.has(value)) {
2262
+ continue;
2193
2263
  }
2194
-
2195
- applyDoctorFixPlan(projectRoot, fixPlan);
2196
- console.log(formatDoctorFixPlan(fixPlan));
2264
+ seen.add(value);
2265
+ unique.push(value);
2197
2266
  }
2267
+ return unique;
2268
+ }
2198
2269
 
2270
+ function buildDoctorCommandReport(projectRoot) {
2199
2271
  const doctorReport = collectDoctorReport(projectRoot);
2200
2272
  const specSlugs = doctorReport.specSlugs;
2201
2273
  const doctorExampleTarget = doctorReport.exampleTarget || {
@@ -2282,65 +2354,425 @@ function runDoctor(targetDir, options = {}) {
2282
2354
  ...nonExecutableScripts.map((file) => `missing executable bit: ${file}`),
2283
2355
  ...missingScripts.map((name) => `missing package.json script: ${name}`),
2284
2356
  ];
2285
- const softWarnings = doctorReport.warnings;
2357
+ const checks = [];
2358
+
2359
+ const addCheck = (id, status, message, details = {}) => {
2360
+ checks.push({
2361
+ id,
2362
+ status,
2363
+ message,
2364
+ ...details,
2365
+ });
2366
+ };
2286
2367
 
2287
- if (migrationProblems.length > 0) {
2288
- throw new Error(formatError(`doctor failed:\n- ${migrationProblems.join('\n- ')}\n- Run migration first: npx create-quiver migrate`));
2289
- }
2368
+ addCheck('project-root', 'ok', `Quiver doctor passed for ${projectRoot}`);
2369
+ addCheck(
2370
+ 'layout',
2371
+ doctorReport.layout === 'incomplete' ? 'error' : 'ok',
2372
+ `Layout: ${doctorReport.layout}`,
2373
+ );
2374
+ addCheck('specs', 'ok', specSlugs.length > 0 ? `Specs: ${specSlugs.join(', ')}` : 'Specs: none yet');
2290
2375
 
2291
- console.log(`Quiver doctor passed for ${projectRoot}`);
2292
- console.log(`Layout: ${doctorReport.layout}`);
2293
- if (specSlugs.length > 0) {
2294
- console.log(`Specs: ${specSlugs.join(', ')}`);
2295
- } else {
2296
- console.log('Specs: none yet');
2297
- }
2298
2376
  if (doctorReport.legacySignals.length > 0) {
2299
- console.log(`Legacy signals: ${doctorReport.legacySignals.join(', ')}`);
2300
- }
2301
- console.log('Next steps:');
2302
- for (const recommendation of doctorReport.recommendations) {
2303
- console.log(`- ${recommendation}`);
2304
- }
2305
- for (const warning of stateWarnings) {
2306
- console.log(`- Warning: ${warning}`);
2307
- }
2377
+ addCheck('legacy-signals', doctorReport.layout === 'legacy' || doctorReport.layout === 'hybrid' ? 'warning' : 'ok', `Legacy signals: ${doctorReport.legacySignals.join(', ')}`);
2378
+ }
2379
+
2380
+ addCheck(
2381
+ 'required-files',
2382
+ missingFiles.length > 0 ? 'error' : 'ok',
2383
+ missingFiles.length > 0 ? `Missing required files: ${missingFiles.join(', ')}` : 'Required files found',
2384
+ { missing: missingFiles },
2385
+ );
2386
+
2387
+ if (requiredExecutables.length > 0 || nonExecutableScripts.length > 0) {
2388
+ addCheck(
2389
+ 'legacy-executables',
2390
+ nonExecutableScripts.length > 0 ? 'error' : 'ok',
2391
+ nonExecutableScripts.length > 0 ? `Missing executable bit: ${nonExecutableScripts.join(', ')}` : 'Legacy executable scripts are runnable',
2392
+ { missing: nonExecutableScripts },
2393
+ );
2394
+ }
2395
+
2396
+ addCheck(
2397
+ 'workflow-scripts',
2398
+ missingScripts.length > 0 ? 'error' : 'ok',
2399
+ missingScripts.length > 0 ? `Missing package.json workflow scripts: ${missingScripts.join(', ')}` : 'Workflow scripts available',
2400
+ { missing: missingScripts },
2401
+ );
2402
+
2403
+ addCheck(
2404
+ 'state',
2405
+ hasQuiverState ? 'ok' : 'warning',
2406
+ hasQuiverState ? 'Quiver state metadata found' : 'Warning: missing Quiver state metadata: .quiver/state.json',
2407
+ );
2408
+
2409
+ addCheck(
2410
+ 'project-scan',
2411
+ hasScanArtifacts ? 'ok' : 'warning',
2412
+ hasScanArtifacts ? 'Project analysis artifacts found' : 'Warning: project analysis artifacts not found; run analyze when you need the visible project map',
2413
+ );
2414
+
2308
2415
  for (const scriptName of missingNodeNativeScripts) {
2309
- console.log(`- Warning: missing Node-native script: ${scriptName}`);
2416
+ addCheck(`node-script:${scriptName}`, 'warning', `Warning: missing Node-native script: ${scriptName}`);
2310
2417
  }
2418
+
2311
2419
  for (const scriptName of missingAiScripts) {
2312
- console.log(`- Warning: missing AI orchestration script: ${scriptName}`);
2420
+ addCheck(`ai-script:${scriptName}`, 'warning', `Warning: missing AI orchestration script: ${scriptName}`);
2313
2421
  }
2422
+
2314
2423
  if (legacyOnlyScripts.length > 0) {
2315
- console.log(`- Warning: legacy Bash workflow scripts detected for ${legacyOnlyScripts.join(', ')}. Run npx create-quiver migrate to add quiver:* npm scripts.`);
2424
+ addCheck(
2425
+ 'legacy-only-scripts',
2426
+ 'warning',
2427
+ `Warning: legacy Bash workflow scripts detected for ${legacyOnlyScripts.join(', ')}. Run npx create-quiver migrate to add quiver:* npm scripts.`,
2428
+ );
2316
2429
  }
2430
+
2317
2431
  for (const script of unsupportedCreateQuiverScripts) {
2318
- console.log(`- Warning: package.json script ${script.scriptName} targets ${script.reason}: \`${script.command}\`. Update create-quiver or regenerate scripts with npx create-quiver migrate.`);
2319
- }
2320
- for (const warning of softWarnings) {
2321
- console.log(`- Warning: ${warning}`);
2322
- }
2323
- if (!hasQuiverState) {
2324
- console.log('- Run migration first: npx create-quiver migrate');
2325
- } else if (!hasScanArtifacts) {
2326
- console.log('- Analyze the project first: npx create-quiver analyze');
2327
- } else {
2328
- console.log('- Ask your AI agent: Read AGENTS.md, then docs/AI_ONBOARDING_PROMPT.md and execute it.');
2329
- }
2330
- console.log('- Check the next ready slice: npx create-quiver next');
2432
+ addCheck(
2433
+ `unsupported-script:${script.scriptName}`,
2434
+ 'warning',
2435
+ `Warning: package.json script ${script.scriptName} targets ${script.reason}: \`${script.command}\`. Update create-quiver or regenerate scripts with npx create-quiver migrate.`,
2436
+ { script_name: script.scriptName, command: script.command, reason: script.reason },
2437
+ );
2438
+ }
2439
+
2440
+ for (const warning of doctorReport.warnings) {
2441
+ addCheck(`warning:${checks.length + 1}`, 'warning', `Warning: ${warning}`);
2442
+ }
2443
+
2444
+ const suggestedFixes = [
2445
+ ...doctorReport.recommendations,
2446
+ !hasQuiverState
2447
+ ? 'Run migration first: npx create-quiver migrate'
2448
+ : !hasScanArtifacts
2449
+ ? 'Analyze the project first: npx create-quiver analyze'
2450
+ : 'Ask your AI agent: Read AGENTS.md, then docs/AI_ONBOARDING_PROMPT.md and execute it.',
2451
+ 'Check the next ready slice: npx create-quiver next',
2452
+ ];
2453
+
2331
2454
  if (specSlugs.length > 0) {
2332
2455
  const projectSlug = doctorExampleTarget.specSlug;
2333
2456
  const sliceId = doctorExampleTarget.sliceId || '<slice-id>';
2334
2457
  if (doctorExampleTarget.source === 'active-slice') {
2335
- console.log(`- Example target: ${projectSlug}/${sliceId} (${doctorExampleTarget.status})`);
2458
+ suggestedFixes.push(`Example target: ${projectSlug}/${sliceId} (${doctorExampleTarget.status})`);
2336
2459
  } else if (doctorExampleTarget.source === 'generic-multiple-specs') {
2337
- console.log('- Example target: specs/<spec-slug>/slices/<slice-id>/slice.json (generic because no active slice is obvious)');
2460
+ suggestedFixes.push('Example target: specs/<spec-slug>/slices/<slice-id>/slice.json (generic because no active slice is obvious)');
2338
2461
  }
2339
- console.log(`- Start a slice: npx create-quiver start-slice specs/${projectSlug}/slices/${sliceId}/slice.json`);
2340
- console.log(`- Validate a slice: npx create-quiver check-slice specs/${projectSlug}/slices/${sliceId}/slice.json`);
2341
- console.log(`- Validate the PR gate: npx create-quiver check-pr specs/${projectSlug}/slices/${sliceId}/slice.json`);
2462
+ suggestedFixes.push(`Start a slice: npx create-quiver start-slice specs/${projectSlug}/slices/${sliceId}/slice.json`);
2463
+ suggestedFixes.push(`Validate a slice: npx create-quiver check-slice specs/${projectSlug}/slices/${sliceId}/slice.json`);
2464
+ suggestedFixes.push(`Validate the PR gate: npx create-quiver check-pr specs/${projectSlug}/slices/${sliceId}/slice.json`);
2342
2465
  } else {
2343
- console.log('- Create real specs and slices only after acceptance criteria are approved and the technical plan is reviewed and approved.');
2466
+ suggestedFixes.push('Create real specs and slices only after acceptance criteria are approved and the technical plan is reviewed and approved.');
2467
+ }
2468
+
2469
+ const errors = checks.filter((check) => check.status === 'error').map((check) => check.message);
2470
+ const warnings = checks.filter((check) => check.status === 'warning').map((check) => check.message);
2471
+ const status = errors.length > 0 ? 'error' : warnings.length > 0 ? 'warning' : 'ok';
2472
+
2473
+ return {
2474
+ schema_version: 1,
2475
+ command: 'doctor',
2476
+ project_root: projectRoot,
2477
+ status,
2478
+ exit_code: errors.length > 0 ? 1 : 0,
2479
+ layout: doctorReport.layout,
2480
+ specs: specSlugs,
2481
+ legacy_signals: doctorReport.legacySignals,
2482
+ checks,
2483
+ suggested_fixes: uniqueLines(suggestedFixes),
2484
+ warnings,
2485
+ errors: migrationProblems.length > 0 ? uniqueLines([...migrationProblems, ...errors]) : errors,
2486
+ };
2487
+ }
2488
+
2489
+ function formatDoctorHumanReport(report, options = {}) {
2490
+ const lines = [];
2491
+ const ux = createUx({
2492
+ ...options,
2493
+ spinner: false,
2494
+ write: (text) => lines.push(String(text)),
2495
+ });
2496
+ const symbolForStatus = (status) => {
2497
+ if (status === 'ok') return ux.theme.symbols.success;
2498
+ if (status === 'error') return ux.theme.symbols.error;
2499
+ return ux.theme.symbols.warning;
2500
+ };
2501
+ const colorForStatus = (status) => {
2502
+ if (status === 'ok') return 'success';
2503
+ if (status === 'error') return 'error';
2504
+ return 'warning';
2505
+ };
2506
+
2507
+ ux.section('Quiver Doctor');
2508
+ ux.line('');
2509
+ ux.line('Checks');
2510
+ for (const check of report.checks) {
2511
+ const line = ` ${symbolForStatus(check.status)} ${check.message}`;
2512
+ ux.line(ux.mode.decoration ? ux.theme.status(colorForStatus(check.status), line) : line);
2513
+ }
2514
+
2515
+ ux.line('');
2516
+ ux.line('Suggested fixes');
2517
+ for (const fix of report.suggested_fixes) {
2518
+ const line = ` ${ux.theme.symbols.bullet} ${fix}`;
2519
+ ux.line(ux.mode.decoration ? ux.theme.status('command', line) : line);
2520
+ }
2521
+
2522
+ return lines.join('');
2523
+ }
2524
+
2525
+ const METHODOLOGY_OPTIONS = Object.freeze([
2526
+ {
2527
+ label: 'WDD + SDD',
2528
+ value: 'wdd-sdd',
2529
+ hint: 'Workflow Driven Development + Spec Driven Development',
2530
+ default: true,
2531
+ },
2532
+ ]);
2533
+
2534
+ const INIT_MODE_OPTIONS = Object.freeze([
2535
+ {
2536
+ label: 'Proyecto existente',
2537
+ value: 'existing',
2538
+ hint: 'Agrega Quiver sin sobrescribir archivos existentes',
2539
+ default: true,
2540
+ },
2541
+ {
2542
+ label: 'Proyecto nuevo',
2543
+ value: 'new',
2544
+ hint: 'Crea el contrato base en una carpeta nueva o vacia',
2545
+ },
2546
+ {
2547
+ label: 'Solo validar estructura',
2548
+ value: 'validate',
2549
+ hint: 'Ejecuta Doctor en lugar de escribir archivos',
2550
+ },
2551
+ ]);
2552
+
2553
+ const INIT_PROFILE_OPTIONS = Object.freeze([
2554
+ {
2555
+ label: 'Default',
2556
+ value: 'default',
2557
+ hint: 'Contrato AI-first recomendado',
2558
+ default: true,
2559
+ },
2560
+ {
2561
+ label: 'Minimal',
2562
+ value: 'minimal',
2563
+ hint: 'Solo documentos esenciales',
2564
+ },
2565
+ {
2566
+ label: 'Full compatibility',
2567
+ value: 'full',
2568
+ hint: 'Incluye compatibilidad historica y templates visibles',
2569
+ },
2570
+ ]);
2571
+
2572
+ function hasDirectoryContent(dirPath) {
2573
+ return fs.existsSync(dirPath)
2574
+ && fs.statSync(dirPath).isDirectory()
2575
+ && fs.readdirSync(dirPath).length > 0;
2576
+ }
2577
+
2578
+ function assertSupportedMethodology(value) {
2579
+ const normalized = String(value || '').trim();
2580
+ if (!normalized) {
2581
+ return 'wdd-sdd';
2582
+ }
2583
+ if (normalized !== 'wdd-sdd') {
2584
+ throw new Error(formatError(`unsupported methodology '${normalized}'. Supported methodologies: wdd-sdd.`));
2585
+ }
2586
+ return normalized;
2587
+ }
2588
+
2589
+ async function resolveInteractiveInitOptions(args, targetDir, projectName, options = {}) {
2590
+ const explicitMethodology = assertSupportedMethodology(args.methodology);
2591
+
2592
+ if (args.interactive !== true) {
2593
+ return {
2594
+ action: 'init',
2595
+ full: args.initFull,
2596
+ includeTemplates: args.initIncludeTemplates,
2597
+ legacyScripts: args.initLegacyScripts,
2598
+ methodology: explicitMethodology,
2599
+ minimal: args.initMinimal,
2600
+ projectName,
2601
+ };
2602
+ }
2603
+
2604
+ const ux = createUx({
2605
+ env: options.env,
2606
+ input: options.input,
2607
+ interactive: true,
2608
+ noColor: args.noColor,
2609
+ output: options.output,
2610
+ promptConfirm: options.promptConfirm,
2611
+ stderrIsTTY: options.stderrIsTTY,
2612
+ stdinIsTTY: options.stdinIsTTY,
2613
+ stdoutIsTTY: options.stdoutIsTTY,
2614
+ write: options.write,
2615
+ });
2616
+
2617
+ if (!ux.mode.usePrompts) {
2618
+ throw new Error(formatError('init --interactive requires an interactive TTY. Use explicit flags such as --name, --minimal, --full, --legacy-scripts, --include-templates, or run doctor to validate structure.'));
2619
+ }
2620
+
2621
+ const selectorOptions = {
2622
+ env: options.env,
2623
+ input: options.input,
2624
+ interactive: true,
2625
+ noColor: args.noColor,
2626
+ output: options.output,
2627
+ prompts: options.prompts,
2628
+ promptSelect: options.promptSelect,
2629
+ stderrIsTTY: options.stderrIsTTY,
2630
+ stdinIsTTY: options.stdinIsTTY,
2631
+ stdoutIsTTY: options.stdoutIsTTY,
2632
+ };
2633
+
2634
+ ux.heading('Bienvenido a Quiver');
2635
+ const selectedMode = await selectOption('¿Qué querés configurar?', INIT_MODE_OPTIONS, {
2636
+ ...selectorOptions,
2637
+ defaultValue: hasDirectoryContent(targetDir) ? 'existing' : 'new',
2638
+ flag: 'init|doctor',
2639
+ name: 'init mode',
2640
+ });
2641
+ const selectedMethodology = await selectOption('¿Qué metodología vas a usar?', METHODOLOGY_OPTIONS, {
2642
+ ...selectorOptions,
2643
+ defaultValue: explicitMethodology,
2644
+ flag: '--methodology',
2645
+ name: 'methodology',
2646
+ value: args.methodology || '',
2647
+ });
2648
+
2649
+ assertSupportedMethodology(selectedMethodology.value);
2650
+
2651
+ if (selectedMode.value === 'validate') {
2652
+ ux.summary([
2653
+ { label: 'Modo', value: 'Solo validar estructura' },
2654
+ { label: 'Metodologia', value: selectedMethodology.label },
2655
+ { label: 'Comando equivalente', value: 'npx create-quiver doctor' },
2656
+ ], { title: 'Configuracion elegida' });
2657
+ if (!args.force && !args.dryRun) {
2658
+ const confirmed = await ux.promptConfirm('Ejecutar Doctor ahora?', { initialValue: true });
2659
+ if (!confirmed) {
2660
+ throw new Error(formatError('init interactive validation declined. No files were written.'));
2661
+ }
2662
+ }
2663
+ return {
2664
+ action: 'doctor',
2665
+ methodology: selectedMethodology.value,
2666
+ projectName,
2667
+ };
2668
+ }
2669
+
2670
+ const defaultProfile = args.initFull ? 'full' : args.initMinimal ? 'minimal' : 'default';
2671
+ const selectedProfile = await selectOption('¿Qué contrato inicial querés crear?', INIT_PROFILE_OPTIONS, {
2672
+ ...selectorOptions,
2673
+ defaultValue: defaultProfile,
2674
+ flag: '--minimal|--full',
2675
+ name: 'init profile',
2676
+ });
2677
+ const agentGuidance = await selectOption('¿Querés ver el próximo paso para perfiles de agentes?', [
2678
+ {
2679
+ label: 'Mostrar comandos sugeridos',
2680
+ value: 'show',
2681
+ hint: 'No guarda credenciales ni ejecuta proveedores',
2682
+ default: true,
2683
+ },
2684
+ {
2685
+ label: 'Omitir por ahora',
2686
+ value: 'skip',
2687
+ },
2688
+ ], {
2689
+ ...selectorOptions,
2690
+ defaultValue: 'show',
2691
+ flag: 'ai agent set',
2692
+ name: 'agent profile guidance',
2693
+ });
2694
+ const nextFlags = {
2695
+ full: selectedProfile.value === 'full',
2696
+ includeTemplates: args.initIncludeTemplates || selectedProfile.value === 'full',
2697
+ legacyScripts: args.initLegacyScripts,
2698
+ methodology: selectedMethodology.value,
2699
+ minimal: selectedProfile.value === 'minimal',
2700
+ projectName,
2701
+ };
2702
+
2703
+ ux.summary([
2704
+ { label: 'Proyecto', value: projectName },
2705
+ { label: 'Modo', value: selectedMode.label },
2706
+ { label: 'Metodologia', value: selectedMethodology.label },
2707
+ { label: 'Perfil', value: selectedProfile.label },
2708
+ { label: 'Perfiles de agentes', value: agentGuidance.value === 'show' ? 'mostrar proximo paso' : 'omitir' },
2709
+ ], { title: 'Configuracion elegida' });
2710
+
2711
+ if (agentGuidance.value === 'show') {
2712
+ ux.nextSteps([
2713
+ 'npx create-quiver ai agent set planner --provider codex --model gpt-5.5 --dry-run',
2714
+ 'npx create-quiver ai agent set executor --provider claude --model claude-sonnet-4-6 --dry-run',
2715
+ ], { title: 'Despues de inicializar' });
2716
+ }
2717
+
2718
+ if (!args.force && !args.dryRun) {
2719
+ const confirmed = await ux.promptConfirm(`Inicializar Quiver en ${targetDir}?`, { initialValue: true });
2720
+ if (!confirmed) {
2721
+ throw new Error(formatError('init interactive approval declined. No files were written.'));
2722
+ }
2723
+ }
2724
+
2725
+ return {
2726
+ action: 'init',
2727
+ ...nextFlags,
2728
+ };
2729
+ }
2730
+
2731
+ function runDoctor(targetDir, options = {}) {
2732
+ const projectRoot = resolveTargetRoot(process.cwd(), targetDir);
2733
+
2734
+ if (!fs.existsSync(projectRoot)) {
2735
+ throw new Error(formatError(`target directory does not exist: ${projectRoot}`));
2736
+ }
2737
+
2738
+ if (!hasQuiverInitializationEvidence(projectRoot)) {
2739
+ throw new Error(formatError('doctor requires a project previously initialized by Quiver.\nRun init first: npx create-quiver --name "Project Name"'));
2740
+ }
2741
+
2742
+ const fixPlan = buildDoctorFixPlan(projectRoot);
2743
+ if (options.fix) {
2744
+ if (options.dryRun) {
2745
+ if (options.json) {
2746
+ console.log(JSON.stringify({
2747
+ schema_version: 1,
2748
+ command: 'doctor fix',
2749
+ dry_run: true,
2750
+ fixes: fixPlan,
2751
+ }, null, 2));
2752
+ return;
2753
+ }
2754
+ console.log(formatDoctorFixPlan(fixPlan, { dryRun: true }));
2755
+ return;
2756
+ }
2757
+
2758
+ applyDoctorFixPlan(projectRoot, fixPlan);
2759
+ if (!options.json) {
2760
+ console.log(formatDoctorFixPlan(fixPlan));
2761
+ }
2762
+ }
2763
+
2764
+ const commandReport = buildDoctorCommandReport(projectRoot);
2765
+ if (options.json) {
2766
+ console.log(JSON.stringify(commandReport, null, 2));
2767
+ } else {
2768
+ process.stdout.write(formatDoctorHumanReport(commandReport, {
2769
+ noColor: options.noColor,
2770
+ unicode: options.unicode,
2771
+ }));
2772
+ }
2773
+
2774
+ if (commandReport.exit_code !== 0) {
2775
+ process.exitCode = commandReport.exit_code;
2344
2776
  }
2345
2777
  }
2346
2778
 
@@ -2410,7 +2842,7 @@ async function run(argv) {
2410
2842
 
2411
2843
  if (args.mode === 'ai') {
2412
2844
  if (!args.aiCommand) {
2413
- throw new Error(formatError('missing ai subcommand. Use: npx create-quiver ai onboard | prepare-context | run | active-slice | status | resume | inspect | export | specs | slices | trace | plan | revise | repair-plan | review-plan | approve | approvals | agent | prompt-slice | execute-slice | execute-plan | doctor | pr'));
2845
+ throw new Error(formatError('missing ai subcommand. Use: npx create-quiver ai onboard | prepare-context | run | active-slice | status | resume | inspect | export | specs | slices | models | trace | plan | revise | repair-plan | review-plan | approve | approvals | agent | prompt-slice | execute-slice | execute-plan | doctor | pr'));
2414
2846
  }
2415
2847
 
2416
2848
  if (args.aiCommand === 'run') {
@@ -2483,10 +2915,23 @@ async function run(argv) {
2483
2915
  return;
2484
2916
  }
2485
2917
 
2918
+ if (args.aiCommand === 'models') {
2919
+ runAiModelsList({
2920
+ json: args.json,
2921
+ provider: args.aiProviderExplicit ? args.aiProvider : undefined,
2922
+ });
2923
+ return;
2924
+ }
2925
+
2486
2926
  if (args.aiCommand === 'agent') {
2487
- runAiAgent(process.cwd(), {
2927
+ await runAiAgent(process.cwd(), {
2488
2928
  command: args.aiAgentCommand,
2489
2929
  context: args.aiContext || undefined,
2930
+ defaultProfile: args.aiDefaultProfile,
2931
+ displayName: args.aiDisplayName || undefined,
2932
+ id: args.aiProfileId || undefined,
2933
+ interactive: args.interactive,
2934
+ json: args.json,
2490
2935
  label: args.aiLabel || undefined,
2491
2936
  model: args.aiModel || undefined,
2492
2937
  provider: args.aiProviderExplicit ? args.aiProvider : undefined,
@@ -2504,6 +2949,8 @@ async function run(argv) {
2504
2949
  printPrompt: args.aiPrintPrompt,
2505
2950
  provider: args.aiProvider,
2506
2951
  providerExplicit: args.aiProviderExplicit,
2952
+ model: args.aiModel || undefined,
2953
+ plannerProfile: args.aiPlannerProfile || undefined,
2507
2954
  role: args.aiRole,
2508
2955
  timeout: args.aiTimeout,
2509
2956
  });
@@ -2518,6 +2965,8 @@ async function run(argv) {
2518
2965
  printPrompt: args.aiPrintPrompt,
2519
2966
  provider: args.aiProvider,
2520
2967
  providerExplicit: args.aiProviderExplicit,
2968
+ model: args.aiModel || undefined,
2969
+ plannerProfile: args.aiPlannerProfile || undefined,
2521
2970
  review: args.review,
2522
2971
  role: args.aiRole,
2523
2972
  runId: args.aiRunId || undefined,
@@ -2536,6 +2985,8 @@ async function run(argv) {
2536
2985
  printPrompt: args.aiPrintPrompt,
2537
2986
  provider: args.aiProvider,
2538
2987
  providerExplicit: args.aiProviderExplicit,
2988
+ model: args.aiModel || undefined,
2989
+ plannerProfile: args.aiPlannerProfile || undefined,
2539
2990
  interactive: args.interactive,
2540
2991
  review: args.review,
2541
2992
  role: args.aiRole,
@@ -2555,6 +3006,8 @@ async function run(argv) {
2555
3006
  printPrompt: args.aiPrintPrompt,
2556
3007
  provider: args.aiProvider,
2557
3008
  providerExplicit: args.aiProviderExplicit,
3009
+ model: args.aiModel || undefined,
3010
+ reviewerProfile: args.aiReviewerProfile || undefined,
2558
3011
  timeout: args.aiTimeout,
2559
3012
  });
2560
3013
  return;
@@ -2568,6 +3021,8 @@ async function run(argv) {
2568
3021
  printPrompt: args.aiPrintPrompt,
2569
3022
  provider: args.aiProvider,
2570
3023
  providerExplicit: args.aiProviderExplicit,
3024
+ model: args.aiModel || undefined,
3025
+ plannerProfile: args.aiPlannerProfile || undefined,
2571
3026
  role: args.aiRole,
2572
3027
  runId: args.aiRunId || undefined,
2573
3028
  timeout: args.aiTimeout,
@@ -2584,6 +3039,8 @@ async function run(argv) {
2584
3039
  printPrompt: args.aiPrintPrompt,
2585
3040
  provider: args.aiProvider,
2586
3041
  providerExplicit: args.aiProviderExplicit,
3042
+ model: args.aiModel || undefined,
3043
+ plannerProfile: args.aiPlannerProfile || undefined,
2587
3044
  role: args.aiRole,
2588
3045
  runId: args.aiRunId || undefined,
2589
3046
  timeout: args.aiTimeout,
@@ -2613,6 +3070,9 @@ async function run(argv) {
2613
3070
  commit: args.aiCommit,
2614
3071
  context: args.aiContext || undefined,
2615
3072
  dryRun: args.dryRun,
3073
+ executorProfile: args.aiExecutorProfile || undefined,
3074
+ interactive: args.interactive,
3075
+ model: args.aiModel || undefined,
2616
3076
  provider: args.aiProvider,
2617
3077
  providerExplicit: args.aiProviderExplicit,
2618
3078
  role: args.aiRole,
@@ -2636,7 +3096,10 @@ async function run(argv) {
2636
3096
  context: args.aiContext || undefined,
2637
3097
  dryRun: args.dryRun,
2638
3098
  execute: args.aiExecute,
3099
+ executorProfile: args.aiExecutorProfile || undefined,
3100
+ interactive: args.interactive,
2639
3101
  json: args.json,
3102
+ model: args.aiModel || undefined,
2640
3103
  mode: args.aiExecutionMode,
2641
3104
  provider: args.aiProvider,
2642
3105
  providerExplicit: args.aiProviderExplicit,
@@ -2673,7 +3136,7 @@ async function run(argv) {
2673
3136
  return;
2674
3137
  }
2675
3138
 
2676
- throw new Error(formatError(`unsupported ai subcommand: ${args.aiCommand}. Supported tasks: onboard, prepare-context, run, active-slice, status, resume, inspect, export, specs, slices, trace, plan, revise, repair-plan, review-plan, approve, approvals, agent, prompt-slice, execute-slice, execute-plan, doctor, pr`));
3139
+ throw new Error(formatError(`unsupported ai subcommand: ${args.aiCommand}. Supported tasks: onboard, prepare-context, run, active-slice, status, resume, inspect, export, specs, slices, models, trace, plan, revise, repair-plan, review-plan, approve, approvals, agent, prompt-slice, execute-slice, execute-plan, doctor, pr`));
2677
3140
  }
2678
3141
 
2679
3142
  if (args.mode === 'graph') {
@@ -2734,6 +3197,9 @@ async function run(argv) {
2734
3197
  runDoctor(args.targetDir, {
2735
3198
  dryRun: args.dryRun,
2736
3199
  fix: args.doctorFix,
3200
+ json: args.json,
3201
+ noColor: args.noColor,
3202
+ unicode: args.unicode,
2737
3203
  });
2738
3204
  return;
2739
3205
  }
@@ -2809,6 +3275,7 @@ async function run(argv) {
2809
3275
  dryRun: args.dryRun,
2810
3276
  input: args.aiInput || undefined,
2811
3277
  interactive: args.interactive,
3278
+ methodology: args.methodology || undefined,
2812
3279
  review: args.review,
2813
3280
  specSlug: args.specSlug || undefined,
2814
3281
  withPlanner: args.withPlanner,
@@ -2859,14 +3326,25 @@ async function run(argv) {
2859
3326
  const packageRoot = path.resolve(__dirname, '../..');
2860
3327
  const targetDir = resolveTargetRoot(process.cwd(), args.targetDir);
2861
3328
  const projectName = args.projectName || path.basename(targetDir) || 'Quiver Project';
3329
+ const initOptions = await resolveInteractiveInitOptions(args, targetDir, projectName);
3330
+ if (initOptions.action === 'doctor') {
3331
+ runDoctor(targetDir, {
3332
+ dryRun: args.dryRun,
3333
+ fix: false,
3334
+ json: args.json,
3335
+ noColor: args.noColor,
3336
+ unicode: args.unicode,
3337
+ });
3338
+ return;
3339
+ }
2862
3340
  const initLayout = buildInitLayout(targetDir, {
2863
3341
  compatibilityAlias: !args.explicitInit,
2864
3342
  dryRun: args.dryRun,
2865
- full: args.initFull,
2866
- includeTemplates: args.initIncludeTemplates,
2867
- legacyScripts: args.initLegacyScripts,
2868
- minimal: args.initMinimal,
2869
- projectName,
3343
+ full: initOptions.full,
3344
+ includeTemplates: initOptions.includeTemplates,
3345
+ legacyScripts: initOptions.legacyScripts,
3346
+ minimal: initOptions.minimal,
3347
+ projectName: initOptions.projectName,
2870
3348
  skipInstall: args.skipInstall,
2871
3349
  });
2872
3350
 
@@ -2884,9 +3362,9 @@ async function run(argv) {
2884
3362
  if (initLayout.profile === 'full') {
2885
3363
  exportTemplatesToLegacyRoot(templateRoot, targetDir);
2886
3364
  }
2887
- runInitDocs(targetDir, projectName, {
2888
- includeTemplates: args.initIncludeTemplates,
2889
- legacyScripts: args.initLegacyScripts,
3365
+ runInitDocs(targetDir, initOptions.projectName, {
3366
+ includeTemplates: initOptions.includeTemplates,
3367
+ legacyScripts: initOptions.legacyScripts,
2890
3368
  profile: initLayout.profile,
2891
3369
  templateRoot,
2892
3370
  });
@@ -2901,13 +3379,14 @@ async function run(argv) {
2901
3379
  }
2902
3380
 
2903
3381
  console.log(`Installed Quiver into ${targetDir}`);
2904
- printInitNextSteps(targetDir, projectName);
3382
+ printInitNextSteps(targetDir, initOptions.projectName);
2905
3383
  } finally {
2906
3384
  fs.rmSync(tempRoot, { recursive: true, force: true });
2907
3385
  }
2908
3386
  }
2909
3387
 
2910
3388
  module.exports = {
3389
+ resolveInteractiveInitOptions,
2911
3390
  runAnalyze,
2912
3391
  runDoctor,
2913
3392
  runFlow,