@zigrivers/scaffold 3.9.2 → 3.10.0

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 (190) hide show
  1. package/README.md +39 -8
  2. package/dist/cli/commands/adopt.d.ts +2 -0
  3. package/dist/cli/commands/adopt.d.ts.map +1 -1
  4. package/dist/cli/commands/adopt.js +428 -58
  5. package/dist/cli/commands/adopt.js.map +1 -1
  6. package/dist/cli/commands/adopt.performance.test.d.ts +2 -0
  7. package/dist/cli/commands/adopt.performance.test.d.ts.map +1 -0
  8. package/dist/cli/commands/adopt.performance.test.js +30 -0
  9. package/dist/cli/commands/adopt.performance.test.js.map +1 -0
  10. package/dist/cli/commands/adopt.test.js +18 -6
  11. package/dist/cli/commands/adopt.test.js.map +1 -1
  12. package/dist/cli/commands/init.d.ts.map +1 -1
  13. package/dist/cli/commands/init.js +4 -157
  14. package/dist/cli/commands/init.js.map +1 -1
  15. package/dist/cli/init-flag-families.d.ts +86 -0
  16. package/dist/cli/init-flag-families.d.ts.map +1 -0
  17. package/dist/cli/init-flag-families.js +418 -0
  18. package/dist/cli/init-flag-families.js.map +1 -0
  19. package/dist/cli/init-flag-families.test.d.ts +2 -0
  20. package/dist/cli/init-flag-families.test.d.ts.map +1 -0
  21. package/dist/cli/init-flag-families.test.js +268 -0
  22. package/dist/cli/init-flag-families.test.js.map +1 -0
  23. package/dist/config/schema.d.ts +6 -6
  24. package/dist/config/schema.js +2 -2
  25. package/dist/config/schema.js.map +1 -1
  26. package/dist/config/schema.test.js +10 -4
  27. package/dist/config/schema.test.js.map +1 -1
  28. package/dist/e2e/adopt-multi-type.test.d.ts +2 -0
  29. package/dist/e2e/adopt-multi-type.test.d.ts.map +1 -0
  30. package/dist/e2e/adopt-multi-type.test.js +35 -0
  31. package/dist/e2e/adopt-multi-type.test.js.map +1 -0
  32. package/dist/project/__frozen-schemas__/schema-v3.9.2.d.ts +2891 -0
  33. package/dist/project/__frozen-schemas__/schema-v3.9.2.d.ts.map +1 -0
  34. package/dist/project/__frozen-schemas__/schema-v3.9.2.js +177 -0
  35. package/dist/project/__frozen-schemas__/schema-v3.9.2.js.map +1 -0
  36. package/dist/project/adopt.d.ts +38 -2
  37. package/dist/project/adopt.d.ts.map +1 -1
  38. package/dist/project/adopt.error-messages.test.d.ts +2 -0
  39. package/dist/project/adopt.error-messages.test.d.ts.map +1 -0
  40. package/dist/project/adopt.error-messages.test.js +112 -0
  41. package/dist/project/adopt.error-messages.test.js.map +1 -0
  42. package/dist/project/adopt.forward-compat.test.d.ts +2 -0
  43. package/dist/project/adopt.forward-compat.test.d.ts.map +1 -0
  44. package/dist/project/adopt.forward-compat.test.js +71 -0
  45. package/dist/project/adopt.forward-compat.test.js.map +1 -0
  46. package/dist/project/adopt.js +218 -27
  47. package/dist/project/adopt.js.map +1 -1
  48. package/dist/project/adopt.merge.test.d.ts +2 -0
  49. package/dist/project/adopt.merge.test.d.ts.map +1 -0
  50. package/dist/project/adopt.merge.test.js +62 -0
  51. package/dist/project/adopt.merge.test.js.map +1 -0
  52. package/dist/project/adopt.re-adoption.test.d.ts +2 -0
  53. package/dist/project/adopt.re-adoption.test.d.ts.map +1 -0
  54. package/dist/project/adopt.re-adoption.test.js +222 -0
  55. package/dist/project/adopt.re-adoption.test.js.map +1 -0
  56. package/dist/project/adopt.test.js +72 -27
  57. package/dist/project/adopt.test.js.map +1 -1
  58. package/dist/project/detectors/backend.d.ts +4 -0
  59. package/dist/project/detectors/backend.d.ts.map +1 -0
  60. package/dist/project/detectors/backend.js +199 -0
  61. package/dist/project/detectors/backend.js.map +1 -0
  62. package/dist/project/detectors/backend.test.d.ts +2 -0
  63. package/dist/project/detectors/backend.test.d.ts.map +1 -0
  64. package/dist/project/detectors/backend.test.js +64 -0
  65. package/dist/project/detectors/backend.test.js.map +1 -0
  66. package/dist/project/detectors/browser-extension.d.ts +4 -0
  67. package/dist/project/detectors/browser-extension.d.ts.map +1 -0
  68. package/dist/project/detectors/browser-extension.js +61 -0
  69. package/dist/project/detectors/browser-extension.js.map +1 -0
  70. package/dist/project/detectors/browser-extension.test.d.ts +2 -0
  71. package/dist/project/detectors/browser-extension.test.d.ts.map +1 -0
  72. package/dist/project/detectors/browser-extension.test.js +64 -0
  73. package/dist/project/detectors/browser-extension.test.js.map +1 -0
  74. package/dist/project/detectors/cli.d.ts +4 -0
  75. package/dist/project/detectors/cli.d.ts.map +1 -0
  76. package/dist/project/detectors/cli.js +68 -0
  77. package/dist/project/detectors/cli.js.map +1 -0
  78. package/dist/project/detectors/cli.test.d.ts +2 -0
  79. package/dist/project/detectors/cli.test.d.ts.map +1 -0
  80. package/dist/project/detectors/cli.test.js +70 -0
  81. package/dist/project/detectors/cli.test.js.map +1 -0
  82. package/dist/project/detectors/context.d.ts +105 -0
  83. package/dist/project/detectors/context.d.ts.map +1 -0
  84. package/dist/project/detectors/context.js +652 -0
  85. package/dist/project/detectors/context.js.map +1 -0
  86. package/dist/project/detectors/context.test.d.ts +2 -0
  87. package/dist/project/detectors/context.test.d.ts.map +1 -0
  88. package/dist/project/detectors/context.test.js +240 -0
  89. package/dist/project/detectors/context.test.js.map +1 -0
  90. package/dist/project/detectors/data-pipeline.d.ts +4 -0
  91. package/dist/project/detectors/data-pipeline.d.ts.map +1 -0
  92. package/dist/project/detectors/data-pipeline.js +97 -0
  93. package/dist/project/detectors/data-pipeline.js.map +1 -0
  94. package/dist/project/detectors/data-pipeline.test.d.ts +2 -0
  95. package/dist/project/detectors/data-pipeline.test.d.ts.map +1 -0
  96. package/dist/project/detectors/data-pipeline.test.js +67 -0
  97. package/dist/project/detectors/data-pipeline.test.js.map +1 -0
  98. package/dist/project/detectors/disambiguate.d.ts +12 -0
  99. package/dist/project/detectors/disambiguate.d.ts.map +1 -0
  100. package/dist/project/detectors/disambiguate.js +87 -0
  101. package/dist/project/detectors/disambiguate.js.map +1 -0
  102. package/dist/project/detectors/disambiguate.test.d.ts +2 -0
  103. package/dist/project/detectors/disambiguate.test.d.ts.map +1 -0
  104. package/dist/project/detectors/disambiguate.test.js +114 -0
  105. package/dist/project/detectors/disambiguate.test.js.map +1 -0
  106. package/dist/project/detectors/file-text-match.d.ts +3 -0
  107. package/dist/project/detectors/file-text-match.d.ts.map +1 -0
  108. package/dist/project/detectors/file-text-match.js +60 -0
  109. package/dist/project/detectors/file-text-match.js.map +1 -0
  110. package/dist/project/detectors/file-text-match.test.d.ts +2 -0
  111. package/dist/project/detectors/file-text-match.test.d.ts.map +1 -0
  112. package/dist/project/detectors/file-text-match.test.js +81 -0
  113. package/dist/project/detectors/file-text-match.test.js.map +1 -0
  114. package/dist/project/detectors/game.d.ts +18 -0
  115. package/dist/project/detectors/game.d.ts.map +1 -0
  116. package/dist/project/detectors/game.js +83 -0
  117. package/dist/project/detectors/game.js.map +1 -0
  118. package/dist/project/detectors/game.test.d.ts +2 -0
  119. package/dist/project/detectors/game.test.d.ts.map +1 -0
  120. package/dist/project/detectors/game.test.js +87 -0
  121. package/dist/project/detectors/game.test.js.map +1 -0
  122. package/dist/project/detectors/index.d.ts +5 -0
  123. package/dist/project/detectors/index.d.ts.map +1 -0
  124. package/dist/project/detectors/index.js +29 -0
  125. package/dist/project/detectors/index.js.map +1 -0
  126. package/dist/project/detectors/library.d.ts +4 -0
  127. package/dist/project/detectors/library.d.ts.map +1 -0
  128. package/dist/project/detectors/library.js +117 -0
  129. package/dist/project/detectors/library.js.map +1 -0
  130. package/dist/project/detectors/library.test.d.ts +2 -0
  131. package/dist/project/detectors/library.test.d.ts.map +1 -0
  132. package/dist/project/detectors/library.test.js +73 -0
  133. package/dist/project/detectors/library.test.js.map +1 -0
  134. package/dist/project/detectors/ml.d.ts +4 -0
  135. package/dist/project/detectors/ml.d.ts.map +1 -0
  136. package/dist/project/detectors/ml.js +112 -0
  137. package/dist/project/detectors/ml.js.map +1 -0
  138. package/dist/project/detectors/ml.test.d.ts +2 -0
  139. package/dist/project/detectors/ml.test.d.ts.map +1 -0
  140. package/dist/project/detectors/ml.test.js +75 -0
  141. package/dist/project/detectors/ml.test.js.map +1 -0
  142. package/dist/project/detectors/mobile-app.d.ts +4 -0
  143. package/dist/project/detectors/mobile-app.d.ts.map +1 -0
  144. package/dist/project/detectors/mobile-app.js +58 -0
  145. package/dist/project/detectors/mobile-app.js.map +1 -0
  146. package/dist/project/detectors/mobile-app.test.d.ts +2 -0
  147. package/dist/project/detectors/mobile-app.test.d.ts.map +1 -0
  148. package/dist/project/detectors/mobile-app.test.js +57 -0
  149. package/dist/project/detectors/mobile-app.test.js.map +1 -0
  150. package/dist/project/detectors/required-fields.d.ts +4 -0
  151. package/dist/project/detectors/required-fields.d.ts.map +1 -0
  152. package/dist/project/detectors/required-fields.js +13 -0
  153. package/dist/project/detectors/required-fields.js.map +1 -0
  154. package/dist/project/detectors/required-fields.test.d.ts +2 -0
  155. package/dist/project/detectors/required-fields.test.d.ts.map +1 -0
  156. package/dist/project/detectors/required-fields.test.js +24 -0
  157. package/dist/project/detectors/required-fields.test.js.map +1 -0
  158. package/dist/project/detectors/resolve-detection.d.ts +18 -0
  159. package/dist/project/detectors/resolve-detection.d.ts.map +1 -0
  160. package/dist/project/detectors/resolve-detection.js +184 -0
  161. package/dist/project/detectors/resolve-detection.js.map +1 -0
  162. package/dist/project/detectors/resolve-detection.test.d.ts +2 -0
  163. package/dist/project/detectors/resolve-detection.test.d.ts.map +1 -0
  164. package/dist/project/detectors/resolve-detection.test.js +158 -0
  165. package/dist/project/detectors/resolve-detection.test.js.map +1 -0
  166. package/dist/project/detectors/types.d.ts +56 -0
  167. package/dist/project/detectors/types.d.ts.map +1 -0
  168. package/dist/project/detectors/types.js +9 -0
  169. package/dist/project/detectors/types.js.map +1 -0
  170. package/dist/project/detectors/web-app.d.ts +15 -0
  171. package/dist/project/detectors/web-app.d.ts.map +1 -0
  172. package/dist/project/detectors/web-app.js +228 -0
  173. package/dist/project/detectors/web-app.js.map +1 -0
  174. package/dist/project/detectors/web-app.test.d.ts +2 -0
  175. package/dist/project/detectors/web-app.test.d.ts.map +1 -0
  176. package/dist/project/detectors/web-app.test.js +95 -0
  177. package/dist/project/detectors/web-app.test.js.map +1 -0
  178. package/dist/types/config.d.ts +33 -0
  179. package/dist/types/config.d.ts.map +1 -1
  180. package/dist/types/enums.d.ts +2 -1
  181. package/dist/types/enums.d.ts.map +1 -1
  182. package/dist/types/enums.js +1 -0
  183. package/dist/types/enums.js.map +1 -1
  184. package/dist/utils/errors.d.ts +7 -0
  185. package/dist/utils/errors.d.ts.map +1 -1
  186. package/dist/utils/errors.js +38 -0
  187. package/dist/utils/errors.js.map +1 -1
  188. package/dist/utils/errors.test.js +42 -1
  189. package/dist/utils/errors.test.js.map +1 -1
  190. package/package.json +6 -2
@@ -0,0 +1,24 @@
1
+ import { describe, it, expect } from 'vitest';
2
+ import { z } from 'zod';
3
+ import { getRequiredFieldsWithoutDefaults } from './required-fields.js';
4
+ import { WebAppConfigSchema, BackendConfigSchema } from '../../config/schema.js';
5
+ describe('getRequiredFieldsWithoutDefaults', () => {
6
+ it('returns the anchor field for WebAppConfigSchema', () => {
7
+ const required = getRequiredFieldsWithoutDefaults(WebAppConfigSchema);
8
+ expect(required).toEqual(['renderingStrategy']);
9
+ });
10
+ it('returns the anchor field for BackendConfigSchema', () => {
11
+ const required = getRequiredFieldsWithoutDefaults(BackendConfigSchema);
12
+ expect(required).toEqual(['apiStyle']);
13
+ });
14
+ it('excludes optional fields', () => {
15
+ const schema = z.object({
16
+ a: z.string(),
17
+ b: z.string().optional(),
18
+ c: z.string().default('c'),
19
+ });
20
+ const required = getRequiredFieldsWithoutDefaults(schema);
21
+ expect(required).toEqual(['a']);
22
+ });
23
+ });
24
+ //# sourceMappingURL=required-fields.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"required-fields.test.js","sourceRoot":"","sources":["../../../src/project/detectors/required-fields.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAA;AAC7C,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AACvB,OAAO,EAAE,gCAAgC,EAAE,MAAM,sBAAsB,CAAA;AACvE,OAAO,EAAE,kBAAkB,EAAE,mBAAmB,EAAE,MAAM,wBAAwB,CAAA;AAEhF,QAAQ,CAAC,kCAAkC,EAAE,GAAG,EAAE;IAChD,EAAE,CAAC,iDAAiD,EAAE,GAAG,EAAE;QACzD,MAAM,QAAQ,GAAG,gCAAgC,CAAC,kBAAkB,CAAC,CAAA;QACrE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,mBAAmB,CAAC,CAAC,CAAA;IACjD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,GAAG,EAAE;QAC1D,MAAM,QAAQ,GAAG,gCAAgC,CAAC,mBAAmB,CAAC,CAAA;QACtE,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,UAAU,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0BAA0B,EAAE,GAAG,EAAE;QAClC,MAAM,MAAM,GAAG,CAAC,CAAC,MAAM,CAAC;YACtB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE;YACb,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,QAAQ,EAAE;YACxB,CAAC,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC;SAC3B,CAAC,CAAA;QACF,MAAM,QAAQ,GAAG,gCAAgC,CAAC,MAAM,CAAC,CAAA;QACzD,MAAM,CAAC,QAAQ,CAAC,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,CAAA;IACjC,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,18 @@
1
+ import type { DetectionMatch } from './types.js';
2
+ import type { ProjectType } from '../../types/index.js';
3
+ import type { ScaffoldError, ScaffoldWarning } from '../../types/index.js';
4
+ import { type DisambiguateOptions } from './disambiguate.js';
5
+ export interface ResolveDetectionInput {
6
+ readonly matches: readonly DetectionMatch[];
7
+ readonly explicitProjectType?: ProjectType;
8
+ readonly opts: DisambiguateOptions;
9
+ }
10
+ export interface ResolveDetectionResult {
11
+ readonly chosen: DetectionMatch | null;
12
+ readonly error?: ScaffoldError;
13
+ readonly warnings: readonly ScaffoldWarning[];
14
+ }
15
+ /** Synthesize an empty detection match for an explicitly-specified projectType. */
16
+ export declare function synthesizeEmptyMatch(projectType: ProjectType): DetectionMatch;
17
+ export declare function resolveDetection(input: ResolveDetectionInput): Promise<ResolveDetectionResult>;
18
+ //# sourceMappingURL=resolve-detection.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-detection.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/resolve-detection.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,YAAY,CAAA;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,sBAAsB,CAAA;AACvD,OAAO,KAAK,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAA;AAE1E,OAAO,EAAgB,KAAK,mBAAmB,EAAE,MAAM,mBAAmB,CAAA;AAE1E,MAAM,WAAW,qBAAqB;IACpC,QAAQ,CAAC,OAAO,EAAE,SAAS,cAAc,EAAE,CAAA;IAC3C,QAAQ,CAAC,mBAAmB,CAAC,EAAE,WAAW,CAAA;IAC1C,QAAQ,CAAC,IAAI,EAAE,mBAAmB,CAAA;CACnC;AAED,MAAM,WAAW,sBAAsB;IACrC,QAAQ,CAAC,MAAM,EAAE,cAAc,GAAG,IAAI,CAAA;IACtC,QAAQ,CAAC,KAAK,CAAC,EAAE,aAAa,CAAA;IAC9B,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAA;CAC9C;AAED,mFAAmF;AACnF,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,WAAW,GAAG,cAAc,CAO7E;AAED,wBAAsB,gBAAgB,CACpC,KAAK,EAAE,qBAAqB,GAC3B,OAAO,CAAC,sBAAsB,CAAC,CAiLjC"}
@@ -0,0 +1,184 @@
1
+ import { ExitCode } from '../../types/enums.js';
2
+ import { disambiguate } from './disambiguate.js';
3
+ /** Synthesize an empty detection match for an explicitly-specified projectType. */
4
+ export function synthesizeEmptyMatch(projectType) {
5
+ return {
6
+ projectType,
7
+ confidence: 'high',
8
+ partialConfig: {},
9
+ evidence: [{ signal: 'user-specified', note: '--project-type flag' }],
10
+ };
11
+ }
12
+ export async function resolveDetection(input) {
13
+ const warnings = [];
14
+ // Case G: user passed --project-type → short-circuits Cases A-F
15
+ if (input.explicitProjectType) {
16
+ const found = input.matches.find(m => m.projectType === input.explicitProjectType);
17
+ if (found) {
18
+ // Promote the detected match — user's explicit choice overrides disambiguation
19
+ return {
20
+ chosen: {
21
+ ...found,
22
+ confidence: 'high',
23
+ evidence: [...found.evidence, { signal: 'user-specified', note: '--project-type flag' }],
24
+ },
25
+ warnings,
26
+ };
27
+ }
28
+ // Type not detected — synthesize empty match (flags/existing may fill in the rest)
29
+ return { chosen: synthesizeEmptyMatch(input.explicitProjectType), warnings };
30
+ }
31
+ const high = input.matches.filter(m => m.confidence === 'high');
32
+ const medium = input.matches.filter(m => m.confidence === 'medium');
33
+ const low = input.matches.filter(m => m.confidence === 'low');
34
+ // Case A: no matches
35
+ if (input.matches.length === 0) {
36
+ return { chosen: null, warnings };
37
+ }
38
+ // Case B: single high match
39
+ if (high.length === 1) {
40
+ if (medium.length > 0 || low.length > 0) {
41
+ warnings.push({
42
+ code: 'ADOPT_SECONDARY_MATCHES',
43
+ message: `Committed ${high[0].projectType}; runners-up: `
44
+ + `${[...medium, ...low].map(m => m.projectType).join(', ')}`,
45
+ context: {
46
+ winner: high[0].projectType,
47
+ runners_up: [...medium, ...low].map(m => m.projectType).join(','),
48
+ },
49
+ });
50
+ }
51
+ return { chosen: high[0], warnings };
52
+ }
53
+ // Case C: multiple high matches → disambiguate (pass ALL eligible matches so runners-up are visible)
54
+ if (high.length >= 2) {
55
+ const eligible = [...high, ...medium, ...low]; // user sees the full picture
56
+ // Override acceptLowConfidence: true when runners-up include low tier,
57
+ // so disambiguate.filterEligible doesn't drop them from the picker
58
+ const opts = low.length > 0
59
+ ? { ...input.opts, acceptLowConfidence: true }
60
+ : input.opts;
61
+ const result = await disambiguate(eligible, opts);
62
+ if (result.nonTtyFallback) {
63
+ warnings.push({
64
+ code: 'ADOPT_NON_TTY',
65
+ message: 'Non-TTY environment detected; disambiguation skipped (treated as --auto)',
66
+ });
67
+ }
68
+ if (result.chosen)
69
+ return { chosen: result.chosen, warnings };
70
+ if (result.skipReason === 'auto') {
71
+ return {
72
+ chosen: null,
73
+ error: {
74
+ code: 'ADOPT_AMBIGUOUS',
75
+ message: 'Detection found multiple plausible project types: '
76
+ + `${high.map(m => m.projectType).join(', ')}. `
77
+ + 'Re-run with --project-type <type> to choose.',
78
+ exitCode: ExitCode.Ambiguous,
79
+ },
80
+ warnings,
81
+ };
82
+ }
83
+ if (result.skipReason === 'user-cancelled') {
84
+ // User Ctrl-C is a deliberate cancellation; surface as exit code 4
85
+ return {
86
+ chosen: null,
87
+ error: {
88
+ code: 'ADOPT_USER_CANCELLED',
89
+ message: 'User cancelled the disambiguation prompt',
90
+ exitCode: ExitCode.UserCancellation,
91
+ },
92
+ warnings,
93
+ };
94
+ }
95
+ return { chosen: null, warnings };
96
+ }
97
+ // Case D: single medium match
98
+ if (medium.length === 1) {
99
+ if (low.length > 0) {
100
+ warnings.push({
101
+ code: 'ADOPT_SECONDARY_MATCHES',
102
+ message: `Committed ${medium[0].projectType}; `
103
+ + `low-confidence runners-up: ${low.map(m => m.projectType).join(', ')}`,
104
+ });
105
+ }
106
+ return { chosen: medium[0], warnings };
107
+ }
108
+ // Case E: multiple medium matches → disambiguate (pass medium + low so runners-up are visible)
109
+ if (medium.length >= 2) {
110
+ const eligible = [...medium, ...low];
111
+ // Override acceptLowConfidence: true when runners-up include low tier
112
+ const opts = low.length > 0
113
+ ? { ...input.opts, acceptLowConfidence: true }
114
+ : input.opts;
115
+ const result = await disambiguate(eligible, opts);
116
+ if (result.nonTtyFallback) {
117
+ warnings.push({
118
+ code: 'ADOPT_NON_TTY',
119
+ message: 'Non-TTY environment detected; disambiguation skipped (treated as --auto)',
120
+ });
121
+ }
122
+ if (result.chosen)
123
+ return { chosen: result.chosen, warnings };
124
+ if (result.skipReason === 'auto') {
125
+ return {
126
+ chosen: null,
127
+ error: {
128
+ code: 'ADOPT_AMBIGUOUS',
129
+ message: 'Detection found multiple plausible project types: '
130
+ + `${medium.map(m => m.projectType).join(', ')}. `
131
+ + 'Re-run with --project-type <type> to choose.',
132
+ exitCode: ExitCode.Ambiguous,
133
+ },
134
+ warnings,
135
+ };
136
+ }
137
+ if (result.skipReason === 'user-cancelled') {
138
+ return {
139
+ chosen: null,
140
+ error: {
141
+ code: 'ADOPT_USER_CANCELLED',
142
+ message: 'User cancelled the disambiguation prompt',
143
+ exitCode: ExitCode.UserCancellation,
144
+ },
145
+ warnings,
146
+ };
147
+ }
148
+ return { chosen: null, warnings };
149
+ }
150
+ // Case F: only low matches — route through disambiguate so non-TTY/CI fallback is consistent
151
+ if (low.length > 0) {
152
+ const result = await disambiguate(low, { ...input.opts, acceptLowConfidence: true });
153
+ if (result.nonTtyFallback) {
154
+ warnings.push({
155
+ code: 'ADOPT_NON_TTY',
156
+ message: 'Non-TTY environment detected; low-tier disambiguation skipped',
157
+ });
158
+ }
159
+ if (result.chosen)
160
+ return { chosen: result.chosen, warnings };
161
+ if (result.skipReason === 'auto') {
162
+ // No interactive prompt available — emit ADOPT_LOW_ONLY warning + no commit
163
+ warnings.push({
164
+ code: 'ADOPT_LOW_ONLY',
165
+ message: `Only low-confidence matches found: ${low.map(m => m.projectType).join(', ')}`,
166
+ });
167
+ return { chosen: null, warnings };
168
+ }
169
+ if (result.skipReason === 'user-cancelled') {
170
+ return {
171
+ chosen: null,
172
+ error: {
173
+ code: 'ADOPT_USER_CANCELLED',
174
+ message: 'User cancelled the disambiguation prompt',
175
+ exitCode: ExitCode.UserCancellation,
176
+ },
177
+ warnings,
178
+ };
179
+ }
180
+ return { chosen: null, warnings };
181
+ }
182
+ return { chosen: null, warnings };
183
+ }
184
+ //# sourceMappingURL=resolve-detection.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-detection.js","sourceRoot":"","sources":["../../../src/project/detectors/resolve-detection.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=resolve-detection.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-detection.test.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/resolve-detection.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,158 @@
1
+ /* eslint-disable @typescript-eslint/no-explicit-any -- test mocks need flexible typing */
2
+ import { describe, it, expect, vi, beforeEach } from 'vitest';
3
+ import { resolveDetection, synthesizeEmptyMatch } from './resolve-detection.js';
4
+ vi.mock('./disambiguate.js', () => ({
5
+ disambiguate: vi.fn(),
6
+ }));
7
+ import { disambiguate } from './disambiguate.js';
8
+ const match = (t, c) => ({
9
+ projectType: t, confidence: c, partialConfig: {}, evidence: [],
10
+ });
11
+ describe('resolveDetection Cases A-G', () => {
12
+ beforeEach(() => {
13
+ vi.clearAllMocks();
14
+ });
15
+ it('Case A: no matches → no projectType', async () => {
16
+ const result = await resolveDetection({
17
+ matches: [],
18
+ opts: { interactive: true, acceptLowConfidence: false },
19
+ });
20
+ expect(result.chosen).toBeNull();
21
+ expect(result.error).toBeUndefined();
22
+ });
23
+ it('Case B: single high → commit', async () => {
24
+ const m = match('web-app', 'high');
25
+ const result = await resolveDetection({
26
+ matches: [m],
27
+ opts: { interactive: true, acceptLowConfidence: false },
28
+ });
29
+ expect(result.chosen).toBe(m);
30
+ });
31
+ it('Case B with runners-up: warns ADOPT_SECONDARY_MATCHES', async () => {
32
+ const result = await resolveDetection({
33
+ matches: [match('web-app', 'high'), match('backend', 'medium')],
34
+ opts: { interactive: true, acceptLowConfidence: false },
35
+ });
36
+ expect(result.chosen?.projectType).toBe('web-app');
37
+ expect(result.warnings.some(w => w.code === 'ADOPT_SECONDARY_MATCHES')).toBe(true);
38
+ });
39
+ it('Case C: multiple high → disambiguate is called', async () => {
40
+ vi.mocked(disambiguate).mockResolvedValueOnce({ chosen: match('backend', 'high') });
41
+ const result = await resolveDetection({
42
+ matches: [match('web-app', 'high'), match('backend', 'high')],
43
+ opts: { interactive: true, acceptLowConfidence: false },
44
+ });
45
+ expect(disambiguate).toHaveBeenCalled();
46
+ expect(result.chosen?.projectType).toBe('backend');
47
+ });
48
+ it('Case C under --auto: emits ADOPT_AMBIGUOUS error', async () => {
49
+ vi.mocked(disambiguate).mockResolvedValueOnce({ chosen: null, skipReason: 'auto' });
50
+ const result = await resolveDetection({
51
+ matches: [match('web-app', 'high'), match('backend', 'high')],
52
+ opts: { interactive: false, acceptLowConfidence: false },
53
+ });
54
+ expect(result.chosen).toBeNull();
55
+ expect(result.error?.code).toBe('ADOPT_AMBIGUOUS');
56
+ expect(result.error?.exitCode).toBe(6);
57
+ });
58
+ it('Case D: single medium → commit', async () => {
59
+ const m = match('library', 'medium');
60
+ const result = await resolveDetection({
61
+ matches: [m],
62
+ opts: { interactive: true, acceptLowConfidence: false },
63
+ });
64
+ expect(result.chosen).toBe(m);
65
+ });
66
+ it('Case F: only low interactive → delegates to disambiguate', async () => {
67
+ vi.mocked(disambiguate).mockResolvedValueOnce({ chosen: match('library', 'low') });
68
+ const result = await resolveDetection({
69
+ matches: [match('library', 'low')],
70
+ opts: { interactive: true, acceptLowConfidence: false },
71
+ });
72
+ expect(result.chosen?.projectType).toBe('library');
73
+ });
74
+ it('Case F: only low --auto → ADOPT_LOW_ONLY warning + no commit', async () => {
75
+ vi.mocked(disambiguate).mockResolvedValueOnce({ chosen: null, skipReason: 'auto' });
76
+ const result = await resolveDetection({
77
+ matches: [match('library', 'low')],
78
+ opts: { interactive: false, acceptLowConfidence: false },
79
+ });
80
+ expect(result.chosen).toBeNull();
81
+ expect(result.warnings.some(w => w.code === 'ADOPT_LOW_ONLY')).toBe(true);
82
+ });
83
+ it('Case G: explicitProjectType short-circuits detection', async () => {
84
+ const result = await resolveDetection({
85
+ matches: [match('backend', 'high')], // Would otherwise pick backend
86
+ explicitProjectType: 'web-app', // But user said web-app
87
+ opts: { interactive: true, acceptLowConfidence: false },
88
+ });
89
+ expect(result.chosen?.projectType).toBe('web-app');
90
+ expect(disambiguate).not.toHaveBeenCalled();
91
+ });
92
+ it('Case G: explicitProjectType promotes detected match instead of synthesizing empty', async () => {
93
+ const webMatch = match('web-app', 'medium');
94
+ // Manually add partialConfig for realism
95
+ const richMatch = { ...webMatch, partialConfig: { renderingStrategy: 'ssr' } };
96
+ const result = await resolveDetection({
97
+ matches: [richMatch, match('backend', 'high')],
98
+ explicitProjectType: 'web-app',
99
+ opts: { interactive: true, acceptLowConfidence: false },
100
+ });
101
+ expect(result.chosen?.projectType).toBe('web-app');
102
+ expect(result.chosen?.confidence).toBe('high'); // promoted
103
+ expect(result.chosen?.partialConfig?.renderingStrategy).toBe('ssr'); // preserved
104
+ expect(result.chosen?.evidence).toContainEqual(expect.objectContaining({ signal: 'user-specified' }));
105
+ expect(disambiguate).not.toHaveBeenCalled();
106
+ });
107
+ it('Case C user-cancelled → ADOPT_USER_CANCELLED error with exit code 4', async () => {
108
+ vi.mocked(disambiguate).mockResolvedValueOnce({ chosen: null, skipReason: 'user-cancelled' });
109
+ const result = await resolveDetection({
110
+ matches: [match('web-app', 'high'), match('backend', 'high')],
111
+ opts: { interactive: true, acceptLowConfidence: false },
112
+ });
113
+ expect(result.error?.code).toBe('ADOPT_USER_CANCELLED');
114
+ expect(result.error?.exitCode).toBe(4);
115
+ });
116
+ it('Case C non-TTY fallback → ADOPT_NON_TTY warning + ADOPT_AMBIGUOUS error', async () => {
117
+ vi.mocked(disambiguate).mockResolvedValueOnce({ chosen: null, skipReason: 'auto', nonTtyFallback: true });
118
+ const result = await resolveDetection({
119
+ matches: [match('web-app', 'high'), match('backend', 'high')],
120
+ opts: { interactive: true, acceptLowConfidence: false },
121
+ });
122
+ expect(result.warnings.some(w => w.code === 'ADOPT_NON_TTY')).toBe(true);
123
+ expect(result.error?.code).toBe('ADOPT_AMBIGUOUS');
124
+ });
125
+ it('Case E: multiple medium matches → disambiguate called', async () => {
126
+ vi.mocked(disambiguate).mockResolvedValueOnce({ chosen: match('library', 'medium') });
127
+ const result = await resolveDetection({
128
+ matches: [match('library', 'medium'), match('cli', 'medium')],
129
+ opts: { interactive: true, acceptLowConfidence: false },
130
+ });
131
+ expect(disambiguate).toHaveBeenCalled();
132
+ expect(result.chosen?.projectType).toBe('library');
133
+ });
134
+ it('Case B with low runner-up: warns ADOPT_SECONDARY_MATCHES', async () => {
135
+ const result = await resolveDetection({
136
+ matches: [match('web-app', 'high'), match('library', 'low')],
137
+ opts: { interactive: true, acceptLowConfidence: false },
138
+ });
139
+ expect(result.chosen?.projectType).toBe('web-app');
140
+ expect(result.warnings.some(w => w.code === 'ADOPT_SECONDARY_MATCHES')).toBe(true);
141
+ });
142
+ it('Case D with low runner-up: warns ADOPT_SECONDARY_MATCHES', async () => {
143
+ const result = await resolveDetection({
144
+ matches: [match('backend', 'medium'), match('library', 'low')],
145
+ opts: { interactive: true, acceptLowConfidence: false },
146
+ });
147
+ expect(result.chosen?.projectType).toBe('backend');
148
+ expect(result.warnings.some(w => w.code === 'ADOPT_SECONDARY_MATCHES')).toBe(true);
149
+ });
150
+ it('synthesizeEmptyMatch produces a match with empty partialConfig', () => {
151
+ const m = synthesizeEmptyMatch('web-app');
152
+ expect(m.projectType).toBe('web-app');
153
+ expect(m.confidence).toBe('high');
154
+ expect(Object.keys(m.partialConfig)).toHaveLength(0);
155
+ expect(m.evidence[0].signal).toBe('user-specified');
156
+ });
157
+ });
158
+ //# sourceMappingURL=resolve-detection.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve-detection.test.js","sourceRoot":"","sources":["../../../src/project/detectors/resolve-detection.test.ts"],"names":[],"mappings":"AAAA,0FAA0F;AAC1F,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAA;AAC7D,OAAO,EAAE,gBAAgB,EAAE,oBAAoB,EAAE,MAAM,wBAAwB,CAAA;AAG/E,EAAE,CAAC,IAAI,CAAC,mBAAmB,EAAE,GAAG,EAAE,CAAC,CAAC;IAClC,YAAY,EAAE,EAAE,CAAC,EAAE,EAAE;CACtB,CAAC,CAAC,CAAA;AACH,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAA;AAEhD,MAAM,KAAK,GAAG,CAAC,CAAM,EAAE,CAAM,EAAkB,EAAE,CAAC,CAAC;IACjD,WAAW,EAAE,CAAC,EAAE,UAAU,EAAE,CAAC,EAAE,aAAa,EAAE,EAAS,EAAE,QAAQ,EAAE,EAAE;CACtE,CAAmB,CAAA;AAEpB,QAAQ,CAAC,4BAA4B,EAAE,GAAG,EAAE;IAC1C,UAAU,CAAC,GAAG,EAAE;QACd,EAAE,CAAC,aAAa,EAAE,CAAA;IACpB,CAAC,CAAC,CAAA;IACF,EAAE,CAAC,qCAAqC,EAAE,KAAK,IAAI,EAAE;QACnD,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,EAAE;YACX,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,aAAa,EAAE,CAAA;IACtC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8BAA8B,EAAE,KAAK,IAAI,EAAE;QAC5C,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAA;QAClC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,CAAC,CAAC;YACZ,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAC;YAC/D,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gDAAgD,EAAE,KAAK,IAAI,EAAE;QAC9D,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,CAAC,CAAA;QACnF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC7D,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,YAAY,CAAC,CAAC,gBAAgB,EAAE,CAAA;QACvC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;QAChE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;QACnF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC7D,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACzD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gCAAgC,EAAE,KAAK,IAAI,EAAE;QAC9C,MAAM,CAAC,GAAG,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QACpC,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,CAAC,CAAC;YACZ,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IAC/B,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,EAAE,CAAC,CAAA;QAClF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAClC,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,8DAA8D,EAAE,KAAK,IAAI,EAAE;QAC5E,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,CAAC,CAAA;QACnF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAClC,IAAI,EAAE,EAAE,WAAW,EAAE,KAAK,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACzD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,QAAQ,EAAE,CAAA;QAChC,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,gBAAgB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IAC3E,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,sDAAsD,EAAE,KAAK,IAAI,EAAE;QACpE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC,EAAK,+BAA+B;YACvE,mBAAmB,EAAE,SAAS,EAAW,wBAAwB;YACjE,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAClD,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,mFAAmF,EAAE,KAAK,IAAI,EAAE;QACjG,MAAM,QAAQ,GAAG,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,CAAA;QAC3C,yCAAyC;QACzC,MAAM,SAAS,GAAG,EAAE,GAAG,QAAQ,EAAE,aAAa,EAAE,EAAE,iBAAiB,EAAE,KAAK,EAAE,EAAoB,CAAA;QAChG,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,SAAS,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC9C,mBAAmB,EAAE,SAAS;YAC9B,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA,CAAG,WAAW;QAC5D,MAAM,CAAE,MAAM,CAAC,MAAM,EAAE,aAAqB,EAAE,iBAAiB,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAA,CAAE,YAAY;QAC1F,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC,cAAc,CAC5C,MAAM,CAAC,gBAAgB,CAAC,EAAE,MAAM,EAAE,gBAAgB,EAAE,CAAC,CACtD,CAAA;QACD,MAAM,CAAC,YAAY,CAAC,CAAC,GAAG,CAAC,gBAAgB,EAAE,CAAA;IAC7C,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,qEAAqE,EAAE,KAAK,IAAI,EAAE;QACnF,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,gBAAgB,EAAE,CAAC,CAAA;QAC7F,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC7D,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,sBAAsB,CAAC,CAAA;QACvD,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAA;IACxC,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,yEAAyE,EAAE,KAAK,IAAI,EAAE;QACvF,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,cAAc,EAAE,IAAI,EAAE,CAAC,CAAA;QACzG,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,CAAC;YAC7D,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,eAAe,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;QACxE,MAAM,CAAC,MAAM,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,uDAAuD,EAAE,KAAK,IAAI,EAAE;QACrE,EAAE,CAAC,MAAM,CAAC,YAAY,CAAC,CAAC,qBAAqB,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,CAAC,CAAA;QACrF,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;YAC7D,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,YAAY,CAAC,CAAC,gBAAgB,EAAE,CAAA;QACvC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;IACpD,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,MAAM,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC5D,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,0DAA0D,EAAE,KAAK,IAAI,EAAE;QACxE,MAAM,MAAM,GAAG,MAAM,gBAAgB,CAAC;YACpC,OAAO,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;YAC9D,IAAI,EAAE,EAAE,WAAW,EAAE,IAAI,EAAE,mBAAmB,EAAE,KAAK,EAAE;SACxD,CAAC,CAAA;QACF,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QAClD,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,yBAAyB,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAA;IACpF,CAAC,CAAC,CAAA;IAEF,EAAE,CAAC,gEAAgE,EAAE,GAAG,EAAE;QACxE,MAAM,CAAC,GAAG,oBAAoB,CAAC,SAAS,CAAC,CAAA;QACzC,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAA;QACrC,MAAM,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC,CAAA;QACjC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,aAAuB,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAA;QAC9D,MAAM,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAA;IACrD,CAAC,CAAC,CAAA;AACJ,CAAC,CAAC,CAAA"}
@@ -0,0 +1,56 @@
1
+ import type { z } from 'zod';
2
+ import type { WebAppConfigSchema, BackendConfigSchema, CliConfigSchema, LibraryConfigSchema, MobileAppConfigSchema, DataPipelineConfigSchema, MlConfigSchema, BrowserExtensionConfigSchema, GameConfigSchema } from '../../config/schema.js';
3
+ export type Confidence = 'high' | 'medium' | 'low';
4
+ export interface DetectionEvidence {
5
+ readonly signal: string;
6
+ readonly file?: string;
7
+ readonly note?: string;
8
+ }
9
+ interface BaseMatch {
10
+ readonly confidence: Confidence;
11
+ readonly evidence: readonly DetectionEvidence[];
12
+ }
13
+ export interface WebAppMatch extends BaseMatch {
14
+ readonly projectType: 'web-app';
15
+ readonly partialConfig: Partial<z.infer<typeof WebAppConfigSchema>>;
16
+ }
17
+ export interface BackendMatch extends BaseMatch {
18
+ readonly projectType: 'backend';
19
+ readonly partialConfig: Partial<z.infer<typeof BackendConfigSchema>>;
20
+ }
21
+ export interface CliMatch extends BaseMatch {
22
+ readonly projectType: 'cli';
23
+ readonly partialConfig: Partial<z.infer<typeof CliConfigSchema>>;
24
+ }
25
+ export interface LibraryMatch extends BaseMatch {
26
+ readonly projectType: 'library';
27
+ readonly partialConfig: Partial<z.infer<typeof LibraryConfigSchema>>;
28
+ }
29
+ export interface MobileAppMatch extends BaseMatch {
30
+ readonly projectType: 'mobile-app';
31
+ readonly partialConfig: Partial<z.infer<typeof MobileAppConfigSchema>>;
32
+ }
33
+ export interface DataPipelineMatch extends BaseMatch {
34
+ readonly projectType: 'data-pipeline';
35
+ readonly partialConfig: Partial<z.infer<typeof DataPipelineConfigSchema>>;
36
+ }
37
+ export interface MlMatch extends BaseMatch {
38
+ readonly projectType: 'ml';
39
+ readonly partialConfig: Partial<z.infer<typeof MlConfigSchema>>;
40
+ }
41
+ export interface BrowserExtensionMatch extends BaseMatch {
42
+ readonly projectType: 'browser-extension';
43
+ readonly partialConfig: Partial<z.infer<typeof BrowserExtensionConfigSchema>>;
44
+ }
45
+ export interface GameMatch extends BaseMatch {
46
+ readonly projectType: 'game';
47
+ readonly partialConfig: Partial<z.infer<typeof GameConfigSchema>>;
48
+ }
49
+ export type DetectionMatch = WebAppMatch | BackendMatch | CliMatch | LibraryMatch | MobileAppMatch | DataPipelineMatch | MlMatch | BrowserExtensionMatch | GameMatch;
50
+ export type Detector = (ctx: import('./context.js').SignalContext) => DetectionMatch | null;
51
+ /** Exhaustiveness helper for discriminated-union routing. */
52
+ export declare function assertNever(value: never): never;
53
+ /** Ergonomic evidence builder. */
54
+ export declare function evidence(signal: string, file?: string, note?: string): DetectionEvidence;
55
+ export {};
56
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/types.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,CAAC,EAAE,MAAM,KAAK,CAAA;AAC5B,OAAO,KAAK,EACV,kBAAkB,EAAE,mBAAmB,EAAE,eAAe,EAAE,mBAAmB,EAC7E,qBAAqB,EAAE,wBAAwB,EAAE,cAAc,EAC/D,4BAA4B,EAAE,gBAAgB,EAC/C,MAAM,wBAAwB,CAAA;AAE/B,MAAM,MAAM,UAAU,GAAG,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAA;AAElD,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;IACvB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;IACtB,QAAQ,CAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CACvB;AAED,UAAU,SAAS;IACjB,QAAQ,CAAC,UAAU,EAAE,UAAU,CAAA;IAC/B,QAAQ,CAAC,QAAQ,EAAE,SAAS,iBAAiB,EAAE,CAAA;CAChD;AAED,MAAM,WAAW,WAAY,SAAQ,SAAS;IAC5C,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,kBAAkB,CAAC,CAAC,CAAA;CACpE;AACD,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAA;CACrE;AACD,MAAM,WAAW,QAAS,SAAQ,SAAS;IACzC,QAAQ,CAAC,WAAW,EAAE,KAAK,CAAA;IAC3B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,eAAe,CAAC,CAAC,CAAA;CACjE;AACD,MAAM,WAAW,YAAa,SAAQ,SAAS;IAC7C,QAAQ,CAAC,WAAW,EAAE,SAAS,CAAA;IAC/B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,mBAAmB,CAAC,CAAC,CAAA;CACrE;AACD,MAAM,WAAW,cAAe,SAAQ,SAAS;IAC/C,QAAQ,CAAC,WAAW,EAAE,YAAY,CAAA;IAClC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,qBAAqB,CAAC,CAAC,CAAA;CACvE;AACD,MAAM,WAAW,iBAAkB,SAAQ,SAAS;IAClD,QAAQ,CAAC,WAAW,EAAE,eAAe,CAAA;IACrC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,wBAAwB,CAAC,CAAC,CAAA;CAC1E;AACD,MAAM,WAAW,OAAQ,SAAQ,SAAS;IACxC,QAAQ,CAAC,WAAW,EAAE,IAAI,CAAA;IAC1B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,cAAc,CAAC,CAAC,CAAA;CAChE;AACD,MAAM,WAAW,qBAAsB,SAAQ,SAAS;IACtD,QAAQ,CAAC,WAAW,EAAE,mBAAmB,CAAA;IACzC,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,4BAA4B,CAAC,CAAC,CAAA;CAC9E;AACD,MAAM,WAAW,SAAU,SAAQ,SAAS;IAC1C,QAAQ,CAAC,WAAW,EAAE,MAAM,CAAA;IAC5B,QAAQ,CAAC,aAAa,EAAE,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,gBAAgB,CAAC,CAAC,CAAA;CAClE;AAED,MAAM,MAAM,cAAc,GACtB,WAAW,GAAG,YAAY,GAAG,QAAQ,GAAG,YAAY,GAAG,cAAc,GACrE,iBAAiB,GAAG,OAAO,GAAG,qBAAqB,GAAG,SAAS,CAAA;AAEnE,MAAM,MAAM,QAAQ,GAAG,CAAC,GAAG,EAAE,OAAO,cAAc,EAAE,aAAa,KAAK,cAAc,GAAG,IAAI,CAAA;AAE3F,6DAA6D;AAC7D,wBAAgB,WAAW,CAAC,KAAK,EAAE,KAAK,GAAG,KAAK,CAE/C;AAED,kCAAkC;AAClC,wBAAgB,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,iBAAiB,CAExF"}
@@ -0,0 +1,9 @@
1
+ /** Exhaustiveness helper for discriminated-union routing. */
2
+ export function assertNever(value) {
3
+ throw new Error(`Unhandled detection match variant: ${JSON.stringify(value)}`);
4
+ }
5
+ /** Ergonomic evidence builder. */
6
+ export function evidence(signal, file, note) {
7
+ return { signal, file, note };
8
+ }
9
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/project/detectors/types.ts"],"names":[],"mappings":"AAgEA,6DAA6D;AAC7D,MAAM,UAAU,WAAW,CAAC,KAAY;IACtC,MAAM,IAAI,KAAK,CAAC,sCAAsC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,EAAE,CAAC,CAAA;AAChF,CAAC;AAED,kCAAkC;AAClC,MAAM,UAAU,QAAQ,CAAC,MAAc,EAAE,IAAa,EAAE,IAAa;IACnE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,IAAI,EAAE,CAAA;AAC/B,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { SignalContext } from './context.js';
2
+ import type { WebAppMatch } from './types.js';
3
+ /**
4
+ * Detects web-app projects by framework signature.
5
+ *
6
+ * Framework cascade: Next.js > Astro > Remix > Nuxt > SvelteKit > Vite > Angular.
7
+ * First match wins. Also infers rendering strategy, deploy target, realtime, and auth flow.
8
+ *
9
+ * Mobile disqualifier: returns null if the project looks mobile-only (Flutter,
10
+ * Expo, React Native) UNLESS a web framework config file is present (monorepo).
11
+ *
12
+ * IMPORTANT: this detector ONLY uses the SignalContext API — no direct fs/path imports.
13
+ */
14
+ export declare function detectWebApp(ctx: SignalContext): WebAppMatch | null;
15
+ //# sourceMappingURL=web-app.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"web-app.d.ts","sourceRoot":"","sources":["../../../src/project/detectors/web-app.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AACjD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,YAAY,CAAA;AAgN7C;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,GAAG,EAAE,aAAa,GAAG,WAAW,GAAG,IAAI,CAoCnE"}