@ryuenn3123/agentic-senior-core 3.0.17 → 3.0.20

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 (85) hide show
  1. package/.agent-context/prompts/bootstrap-design.md +84 -94
  2. package/.agent-context/prompts/init-project.md +32 -100
  3. package/.agent-context/prompts/refactor.md +22 -44
  4. package/.agent-context/prompts/review-code.md +28 -52
  5. package/.agent-context/review-checklists/architecture-review.md +31 -62
  6. package/.agent-context/review-checklists/pr-checklist.md +74 -108
  7. package/.agent-context/rules/api-docs.md +18 -206
  8. package/.agent-context/rules/architecture.md +40 -207
  9. package/.agent-context/rules/database-design.md +10 -199
  10. package/.agent-context/rules/docker-runtime.md +5 -5
  11. package/.agent-context/rules/efficiency-vs-hype.md +11 -149
  12. package/.agent-context/rules/error-handling.md +9 -231
  13. package/.agent-context/rules/event-driven.md +17 -221
  14. package/.agent-context/rules/frontend-architecture.md +66 -119
  15. package/.agent-context/rules/git-workflow.md +1 -1
  16. package/.agent-context/rules/microservices.md +28 -161
  17. package/.agent-context/rules/naming-conv.md +8 -138
  18. package/.agent-context/rules/performance.md +9 -175
  19. package/.agent-context/rules/realtime.md +11 -44
  20. package/.agent-context/rules/security.md +11 -295
  21. package/.agent-context/rules/testing.md +9 -174
  22. package/.agent-context/state/benchmark-analysis.json +3 -3
  23. package/.agent-context/state/memory-continuity-benchmark.json +1 -1
  24. package/.agent-context/state/onboarding-report.json +71 -11
  25. package/.agents/workflows/init-project.md +7 -24
  26. package/.agents/workflows/refactor.md +7 -24
  27. package/.agents/workflows/review-code.md +7 -24
  28. package/.cursorrules +22 -21
  29. package/.gemini/instructions.md +2 -2
  30. package/.github/copilot-instructions.md +2 -2
  31. package/.instructions.md +112 -213
  32. package/.windsurfrules +22 -21
  33. package/AGENTS.md +4 -4
  34. package/CONTRIBUTING.md +13 -22
  35. package/README.md +6 -20
  36. package/lib/cli/commands/init.mjs +102 -148
  37. package/lib/cli/commands/launch.mjs +3 -3
  38. package/lib/cli/commands/optimize.mjs +14 -4
  39. package/lib/cli/commands/upgrade.mjs +25 -23
  40. package/lib/cli/compiler.mjs +96 -62
  41. package/lib/cli/constants.mjs +28 -136
  42. package/lib/cli/detector/design-evidence.mjs +189 -6
  43. package/lib/cli/detector.mjs +6 -7
  44. package/lib/cli/init-detection-flow.mjs +10 -93
  45. package/lib/cli/init-selection.mjs +2 -68
  46. package/lib/cli/project-scaffolder/constants.mjs +1 -1
  47. package/lib/cli/project-scaffolder/design-contract.mjs +438 -335
  48. package/lib/cli/project-scaffolder/discovery.mjs +36 -82
  49. package/lib/cli/project-scaffolder/prompt-builders.mjs +55 -63
  50. package/lib/cli/project-scaffolder/storage.mjs +0 -4
  51. package/lib/cli/token-optimization.mjs +1 -1
  52. package/lib/cli/utils.mjs +75 -9
  53. package/package.json +2 -2
  54. package/scripts/detection-benchmark.mjs +4 -15
  55. package/scripts/documentation-boundary-audit.mjs +9 -9
  56. package/scripts/explain-on-demand-audit.mjs +11 -11
  57. package/scripts/forbidden-content-check.mjs +9 -9
  58. package/scripts/frontend-usability-audit.mjs +57 -36
  59. package/scripts/llm-judge.mjs +1 -1
  60. package/scripts/mcp-server/constants.mjs +60 -0
  61. package/scripts/mcp-server/tool-registry.mjs +149 -0
  62. package/scripts/mcp-server/tools.mjs +446 -0
  63. package/scripts/mcp-server.mjs +23 -661
  64. package/scripts/release-gate/audit-checks.mjs +426 -0
  65. package/scripts/release-gate/constants.mjs +53 -0
  66. package/scripts/release-gate/runtime.mjs +63 -0
  67. package/scripts/release-gate/static-checks.mjs +182 -0
  68. package/scripts/release-gate.mjs +13 -794
  69. package/scripts/rules-guardian-audit.mjs +14 -13
  70. package/scripts/single-source-lazy-loading-audit.mjs +3 -3
  71. package/scripts/sync-thin-adapters.mjs +5 -5
  72. package/scripts/ui-design-judge/constants.mjs +24 -0
  73. package/scripts/ui-design-judge/design-execution-summary.mjs +259 -0
  74. package/scripts/ui-design-judge/git-input.mjs +131 -0
  75. package/scripts/ui-design-judge/prompting.mjs +73 -0
  76. package/scripts/ui-design-judge/providers.mjs +102 -0
  77. package/scripts/ui-design-judge/reporting.mjs +182 -0
  78. package/scripts/ui-design-judge/rubric-calibration.mjs +214 -0
  79. package/scripts/ui-design-judge/rubric-goldset.json +188 -0
  80. package/scripts/ui-design-judge.mjs +166 -771
  81. package/scripts/ui-rubric-calibration.mjs +35 -0
  82. package/scripts/validate/config.mjs +198 -55
  83. package/scripts/validate/coverage-checks.mjs +32 -7
  84. package/scripts/validate.mjs +8 -4
  85. package/lib/cli/architect.mjs +0 -431
@@ -25,7 +25,10 @@ const TRANSITION_PATTERN = /\btransition(?:-[a-z]+)?\b/g;
25
25
  const ANIMATION_PATTERN = /\banimation(?:-[a-z]+)?\b/g;
26
26
  const DURATION_PATTERN = /\b\d+(?:\.\d+)?m?s\b/g;
27
27
  const MEDIA_WIDTH_PATTERN = /\((?:min|max)-width:\s*([0-9.]+(?:px|rem|em))\)/g;
28
- const TAILWIND_UTILITY_PATTERN = /\b([a-z]+(?:-[a-z]+)?)-[^\s"'`{}()<>]+/g;
28
+ const STRING_CLASS_ATTRIBUTE_PATTERN = /\b(?:className|class)\s*=\s*(?:"([^"]*)"|'([^']*)'|\{`([^`]*)`\}|\{"([^"]*)"\}|\{'([^']*)'\})/g;
29
+ const EXPRESSION_CLASS_ATTRIBUTE_PATTERN = /\b(?:className|class|:class)\s*=\s*\{([^}\n]+)\}/g;
30
+ const JSX_INLINE_STYLE_PATTERN = /\bstyle\s*=\s*\{\{([\s\S]*?)\}\}/g;
31
+ const VUE_INLINE_STYLE_PATTERN = /\b:style\s*=\s*["']\{([^"']*)\}["']/g;
29
32
 
30
33
  async function collectFrontendSourceFilePaths(directoryPath, collectedFilePaths = []) {
31
34
  if (collectedFilePaths.length >= FRONTEND_FILE_SCAN_LIMIT) {
@@ -132,6 +135,137 @@ function incrementCountMap(countMap, key) {
132
135
  countMap[key] = (countMap[key] || 0) + 1;
133
136
  }
134
137
 
138
+ function getFirstDefinedCapture(matchGroups) {
139
+ for (const capturedValue of matchGroups) {
140
+ if (typeof capturedValue === 'string' && capturedValue.trim().length > 0) {
141
+ return capturedValue;
142
+ }
143
+ }
144
+
145
+ return '';
146
+ }
147
+
148
+ function normalizeEvidenceSample(rawValue) {
149
+ return String(rawValue || '').replace(/\s+/g, ' ').trim();
150
+ }
151
+
152
+ function inferUtilityFamily(rawUtilityToken) {
153
+ const normalizedUtilityToken = String(rawUtilityToken || '')
154
+ .trim()
155
+ .split(':')
156
+ .pop()
157
+ ?.replace(/^!/, '')
158
+ ?.replace(/\/.+$/, '')
159
+ ?.trim();
160
+
161
+ if (!normalizedUtilityToken) {
162
+ return '';
163
+ }
164
+
165
+ if (/^grid(?:-|$)/.test(normalizedUtilityToken)) {
166
+ return 'grid';
167
+ }
168
+
169
+ if (/^flex(?:-|$)/.test(normalizedUtilityToken)) {
170
+ return 'flex';
171
+ }
172
+
173
+ if (/^(?:block|inline|hidden|contents)$/.test(normalizedUtilityToken)) {
174
+ return normalizedUtilityToken;
175
+ }
176
+
177
+ if (/^(?:min|max)-\[/.test(normalizedUtilityToken)) {
178
+ return 'arbitrary-breakpoint';
179
+ }
180
+
181
+ return normalizedUtilityToken.split('-')[0];
182
+ }
183
+
184
+ function collectTailwindUtilityFamilies(classValue, utilityFamilyCounts, utilityFamilySamples, utilityFamilySampleSet) {
185
+ for (const utilityToken of String(classValue || '').split(/\s+/g)) {
186
+ const utilityFamily = inferUtilityFamily(utilityToken);
187
+ if (!utilityFamily) {
188
+ continue;
189
+ }
190
+
191
+ incrementCountMap(utilityFamilyCounts, utilityFamily);
192
+ pushSampleValue(utilityFamilySamples, utilityFamily, utilityFamilySampleSet);
193
+ }
194
+ }
195
+
196
+ function applyInlineStyleInspection(styleSourceText, summary, styleSampleSet) {
197
+ const normalizedStyleSource = normalizeEvidenceSample(styleSourceText);
198
+ pushSampleValue(summary.structuredInspection.inlineStyleSamples, normalizedStyleSource, styleSampleSet);
199
+
200
+ const hardcodedColorCount = countPatternMatches(styleSourceText, COLOR_PATTERN);
201
+ const rawSpacingCount = countPatternMatches(styleSourceText, RAW_SPACING_PATTERN);
202
+ const rawRadiusCount = countPatternMatches(styleSourceText, RAW_RADIUS_PATTERN);
203
+ const rawShadowCount = countPatternMatches(styleSourceText, RAW_SHADOW_PATTERN);
204
+ const cssVariableReferenceCount = countPatternMatches(styleSourceText, CSS_VARIABLE_REFERENCE_PATTERN);
205
+
206
+ summary.structuredInspection.inlineTokenBypassSignals.hardcodedColorCount += hardcodedColorCount;
207
+ summary.structuredInspection.inlineTokenBypassSignals.rawSpacingCount += rawSpacingCount;
208
+ summary.structuredInspection.inlineTokenBypassSignals.rawRadiusCount += rawRadiusCount;
209
+ summary.structuredInspection.inlineTokenBypassSignals.rawShadowCount += rawShadowCount;
210
+ summary.structuredInspection.inlineTokenBypassSignals.cssVariableReferenceCount += cssVariableReferenceCount;
211
+ }
212
+
213
+ function collectStructuredAttributeEvidence(sourceText, summary, classSampleSet, styleSampleSet, utilityFamilySampleSet) {
214
+ for (const classAttributeMatch of sourceText.matchAll(STRING_CLASS_ATTRIBUTE_PATTERN)) {
215
+ const classValue = getFirstDefinedCapture(classAttributeMatch.slice(1));
216
+ if (!classValue) {
217
+ continue;
218
+ }
219
+
220
+ summary.structuredInspection.classAttributeCount += 1;
221
+ pushSampleValue(
222
+ summary.structuredInspection.classAttributeSamples,
223
+ normalizeEvidenceSample(classValue),
224
+ classSampleSet
225
+ );
226
+ collectTailwindUtilityFamilies(
227
+ classValue,
228
+ summary.structuredInspection.utilityFamilyCounts,
229
+ summary.structuredInspection.utilityFamilySamples,
230
+ utilityFamilySampleSet
231
+ );
232
+ }
233
+
234
+ for (const expressionClassAttributeMatch of sourceText.matchAll(EXPRESSION_CLASS_ATTRIBUTE_PATTERN)) {
235
+ const expressionValue = getFirstDefinedCapture(expressionClassAttributeMatch.slice(1));
236
+ if (!expressionValue) {
237
+ continue;
238
+ }
239
+
240
+ summary.structuredInspection.boundClassExpressionCount += 1;
241
+ pushSampleValue(
242
+ summary.structuredInspection.classAttributeSamples,
243
+ normalizeEvidenceSample(expressionValue),
244
+ classSampleSet
245
+ );
246
+ }
247
+
248
+ for (const inlineStyleMatch of sourceText.matchAll(JSX_INLINE_STYLE_PATTERN)) {
249
+ const inlineStyleSource = getFirstDefinedCapture(inlineStyleMatch.slice(1));
250
+ if (!inlineStyleSource) {
251
+ continue;
252
+ }
253
+
254
+ summary.structuredInspection.inlineStyleObjectCount += 1;
255
+ applyInlineStyleInspection(inlineStyleSource, summary, styleSampleSet);
256
+ }
257
+
258
+ for (const vueInlineStyleMatch of sourceText.matchAll(VUE_INLINE_STYLE_PATTERN)) {
259
+ const inlineStyleSource = getFirstDefinedCapture(vueInlineStyleMatch.slice(1));
260
+ if (!inlineStyleSource) {
261
+ continue;
262
+ }
263
+
264
+ summary.structuredInspection.inlineStyleBindingCount += 1;
265
+ applyInlineStyleInspection(inlineStyleSource, summary, styleSampleSet);
266
+ }
267
+ }
268
+
135
269
  function createDesignEvidenceSummary(scanRootRelativePaths) {
136
270
  return {
137
271
  summaryVersion: 'v1',
@@ -203,11 +337,34 @@ function createDesignEvidenceSummary(scanRootRelativePaths) {
203
337
  layoutFileCount: 0,
204
338
  surfaceFileSamples: [],
205
339
  },
340
+ structuredInspection: {
341
+ mode: 'attribute-aware-static-scan',
342
+ classAttributeCount: 0,
343
+ boundClassExpressionCount: 0,
344
+ inlineStyleObjectCount: 0,
345
+ inlineStyleBindingCount: 0,
346
+ classAttributeSamples: [],
347
+ inlineStyleSamples: [],
348
+ utilityFamilyCounts: {},
349
+ utilityFamilySamples: [],
350
+ inlineTokenBypassSignals: {
351
+ hardcodedColorCount: 0,
352
+ rawSpacingCount: 0,
353
+ rawRadiusCount: 0,
354
+ rawShadowCount: 0,
355
+ cssVariableReferenceCount: 0,
356
+ },
357
+ },
206
358
  tokenBypassSignals: {
207
359
  hardcodedColorCount: 0,
208
360
  rawSpacingCount: 0,
209
361
  rawRadiusCount: 0,
210
362
  rawShadowCount: 0,
363
+ inlineHardcodedColorCount: 0,
364
+ inlineRawSpacingCount: 0,
365
+ inlineRawRadiusCount: 0,
366
+ inlineRawShadowCount: 0,
367
+ inlineCssVariableReferenceCount: 0,
211
368
  },
212
369
  };
213
370
  }
@@ -282,6 +439,9 @@ export async function collectFrontendDesignEvidence({
282
439
  const letterSpacingSamples = new Set();
283
440
  const durationSamples = new Set();
284
441
  const utilityFamilySamples = new Set();
442
+ const structuredClassAttributeSamples = new Set();
443
+ const structuredInlineStyleSamples = new Set();
444
+ const structuredUtilityFamilySamples = new Set();
285
445
  const seenSurfaceFiles = new Set();
286
446
  let hardcodedColorCount = 0;
287
447
  let propDrillingCandidateCount = 0;
@@ -314,6 +474,13 @@ export async function collectFrontendDesignEvidence({
314
474
  }
315
475
 
316
476
  registerSurfaceFile(designEvidenceSummary, targetDirectoryPath, scannedFilePath, seenSurfaceFiles);
477
+ collectStructuredAttributeEvidence(
478
+ sourceText,
479
+ designEvidenceSummary,
480
+ structuredClassAttributeSamples,
481
+ structuredInlineStyleSamples,
482
+ structuredUtilityFamilySamples
483
+ );
317
484
 
318
485
  for (const cssVariableMatch of sourceText.matchAll(CSS_VARIABLE_DEFINITION_PATTERN)) {
319
486
  designEvidenceSummary.cssVariables.definitionCount += 1;
@@ -398,18 +565,25 @@ export async function collectFrontendDesignEvidence({
398
565
  uniqueMediaWidths.add(mediaWidthMatch[1]);
399
566
  }
400
567
 
401
- for (const utilityMatch of sourceText.matchAll(TAILWIND_UTILITY_PATTERN)) {
402
- const utilityFamily = utilityMatch[1];
403
- incrementCountMap(designEvidenceSummary.tailwind.utilityFamilyCounts, utilityFamily);
404
- pushSampleValue(designEvidenceSummary.tailwind.utilityFamilySamples, utilityFamily, utilityFamilySamples);
405
- }
406
568
  }
407
569
 
570
+ designEvidenceSummary.tailwind.utilityFamilyCounts = {
571
+ ...designEvidenceSummary.structuredInspection.utilityFamilyCounts,
572
+ };
573
+ designEvidenceSummary.tailwind.utilityFamilySamples = [
574
+ ...designEvidenceSummary.structuredInspection.utilityFamilySamples,
575
+ ];
576
+
408
577
  designEvidenceSummary.tokenBypassSignals = {
409
578
  hardcodedColorCount: designEvidenceSummary.colors.hardcodedCount,
410
579
  rawSpacingCount: designEvidenceSummary.spacing.rawValueCount,
411
580
  rawRadiusCount: designEvidenceSummary.radius.rawValueCount,
412
581
  rawShadowCount: designEvidenceSummary.shadow.rawValueCount,
582
+ inlineHardcodedColorCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.hardcodedColorCount,
583
+ inlineRawSpacingCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawSpacingCount,
584
+ inlineRawRadiusCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawRadiusCount,
585
+ inlineRawShadowCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawShadowCount,
586
+ inlineCssVariableReferenceCount: designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.cssVariableReferenceCount,
413
587
  };
414
588
 
415
589
  return {
@@ -421,6 +595,15 @@ export async function collectFrontendDesignEvidence({
421
595
  tailwindBreakpointUsageCount,
422
596
  arbitraryBreakpointCount,
423
597
  uniqueMediaWidthCount: uniqueMediaWidths.size,
598
+ structuredClassAttributeCount: designEvidenceSummary.structuredInspection.classAttributeCount,
599
+ boundClassExpressionCount: designEvidenceSummary.structuredInspection.boundClassExpressionCount,
600
+ inlineStyleObjectCount: designEvidenceSummary.structuredInspection.inlineStyleObjectCount,
601
+ inlineStyleBindingCount: designEvidenceSummary.structuredInspection.inlineStyleBindingCount,
602
+ inlineStyleTokenBypassCount:
603
+ designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.hardcodedColorCount
604
+ + designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawSpacingCount
605
+ + designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawRadiusCount
606
+ + designEvidenceSummary.structuredInspection.inlineTokenBypassSignals.rawShadowCount,
424
607
  },
425
608
  designEvidenceSummary,
426
609
  };
@@ -5,7 +5,6 @@
5
5
  import fs from 'node:fs/promises';
6
6
  import path from 'node:path';
7
7
 
8
- import { BLUEPRINT_RECOMMENDATIONS } from './constants.mjs';
9
8
  import {
10
9
  collectFrontendDesignEvidence,
11
10
  FRONTEND_SCAN_IGNORE_DIRECTORY_NAMES,
@@ -600,9 +599,9 @@ export async function detectProjectContext(targetDirectoryPath) {
600
599
  if (detectionCandidates.length === 0) {
601
600
  return {
602
601
  hasExistingProjectFiles,
603
- recommendedStackFileName: null,
602
+ detectedStackFileName: null,
604
603
  secondaryStackFileNames: [],
605
- recommendedBlueprintFileName: null,
604
+ detectedBlueprintFileName: null,
606
605
  confidenceLabel: null,
607
606
  confidenceScore: 0,
608
607
  confidenceGap: 0,
@@ -643,9 +642,9 @@ export async function detectProjectContext(targetDirectoryPath) {
643
642
 
644
643
  return {
645
644
  hasExistingProjectFiles,
646
- recommendedStackFileName: strongestCandidate.stackFileName,
645
+ detectedStackFileName: strongestCandidate.stackFileName,
647
646
  secondaryStackFileNames,
648
- recommendedBlueprintFileName: BLUEPRINT_RECOMMENDATIONS[strongestCandidate.stackFileName] || null,
647
+ detectedBlueprintFileName: null,
649
648
  confidenceLabel,
650
649
  confidenceScore: strongestCandidate.confidenceScore,
651
650
  confidenceGap,
@@ -656,7 +655,7 @@ export async function detectProjectContext(targetDirectoryPath) {
656
655
  }
657
656
 
658
657
  export function buildDetectionSummary(projectDetection) {
659
- if (!projectDetection.recommendedStackFileName) {
658
+ if (!projectDetection.detectedStackFileName) {
660
659
  return 'I did not find enough stack markers to auto-detect this project confidently.';
661
660
  }
662
661
 
@@ -672,7 +671,7 @@ export function buildDetectionSummary(projectDetection) {
672
671
  ? ` Secondary stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}.`
673
672
  : '';
674
673
 
675
- return `This folder looks like ${toTitleCase(projectDetection.recommendedStackFileName)} with ${projectDetection.confidenceLabel} confidence based on ${readableEvidence}.${confidenceGapSummary}${secondaryStacksSummary}`;
674
+ return `This folder looks like ${toTitleCase(projectDetection.detectedStackFileName)} with ${projectDetection.confidenceLabel} confidence based on ${readableEvidence}.${confidenceGapSummary}${secondaryStacksSummary}`;
676
675
  }
677
676
 
678
677
  export function formatDetectionCandidates(rankedCandidates) {
@@ -1,35 +1,15 @@
1
- import {
2
- BLUEPRINT_RECOMMENDATIONS,
3
- } from './constants.mjs';
4
-
5
- import {
6
- filterBlueprintFileNamesByCandidates,
7
- normalizeAdditionalStackSelection,
8
- } from './init-selection.mjs';
9
-
10
- import {
11
- toTitleCase,
12
- } from './utils.mjs';
13
-
14
1
  export function buildExistingProjectMajorConstraints() {
15
2
  return [
16
3
  'Preserve existing project markers and avoid forced stack migration.',
17
- 'Keep stack rule loading lazy and scoped to touched code.',
18
- 'Explicit stack or blueprint overrides always win over auto-detection.',
4
+ 'Use detected runtime markers as evidence only; do not convert them into stack migration or design direction.',
5
+ 'Explicit stack or blueprint overrides are constraints only when the user provides them.',
19
6
  ];
20
7
  }
21
8
 
22
9
  export async function resolveDetectedSetupDecision({
23
10
  shouldAutoApplyDetectedStack,
24
11
  projectDetection,
25
- stackFileNames,
26
- blueprintFileNames,
27
- userInterface,
28
- isInteractiveSession,
29
12
  detectionTransparency,
30
- askYesNo,
31
- askStackSelection,
32
- askBlueprintSelection,
33
13
  initialSelectedManualStackFileName,
34
14
  initialSelectedManualBlueprintFileName,
35
15
  initialSelectedAdditionalStackFileNames,
@@ -39,78 +19,16 @@ export async function resolveDetectedSetupDecision({
39
19
  let selectedAdditionalStackFileNames = initialSelectedAdditionalStackFileNames || [];
40
20
  let detectedSetupWasApplied = false;
41
21
 
42
- const detectedBlueprintFileName = projectDetection.recommendedBlueprintFileName
43
- || BLUEPRINT_RECOMMENDATIONS[projectDetection.recommendedStackFileName]
44
- || null;
45
-
46
22
  if (shouldAutoApplyDetectedStack) {
47
- if (isInteractiveSession) {
48
- detectionTransparency.quickConfirmation.offered = true;
49
- console.log('\nQuick confirmation for existing project detection:');
50
- console.log(`- Suggested stack: ${toTitleCase(projectDetection.recommendedStackFileName)}`);
51
- if (detectedBlueprintFileName) {
52
- console.log(`- Suggested blueprint: ${toTitleCase(detectedBlueprintFileName)}`);
53
- }
54
-
55
- const shouldUseDetectedSetup = await askYesNo(
56
- 'Use detected setup for this existing project?',
57
- userInterface,
58
- true
59
- );
60
-
61
- if (shouldUseDetectedSetup) {
62
- detectedSetupWasApplied = true;
63
- detectionTransparency.quickConfirmation.response = 'confirmed-detected';
64
- detectionTransparency.decision.mode = 'confirmed-detected';
65
- console.log(`Using detected stack automatically for this existing project: ${toTitleCase(projectDetection.recommendedStackFileName)}.`);
66
- if (projectDetection.secondaryStackFileNames?.length) {
67
- console.log(`Detected additional stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}.`);
68
- }
69
- selectedAdditionalStackFileNames = projectDetection.secondaryStackFileNames || [];
70
- } else {
71
- const overrideStackFileName = await askStackSelection(
72
- 'Override detected stack (quick selection):',
73
- stackFileNames,
74
- userInterface
75
- );
76
- const overrideBlueprintCandidates = filterBlueprintFileNamesByCandidates(
77
- blueprintFileNames,
78
- [BLUEPRINT_RECOMMENDATIONS[overrideStackFileName]].filter(Boolean)
79
- );
80
- const overrideBlueprintFileName = await askBlueprintSelection(
81
- 'Override detected blueprint (quick selection):',
82
- overrideBlueprintCandidates,
83
- userInterface
84
- );
85
-
86
- selectedManualStackFileName = overrideStackFileName;
87
- selectedManualBlueprintFileName = overrideBlueprintFileName;
88
- selectedAdditionalStackFileNames = normalizeAdditionalStackSelection(
89
- overrideStackFileName,
90
- projectDetection.secondaryStackFileNames || []
91
- );
92
- detectionTransparency.quickConfirmation.response = 'overridden-detected';
93
- detectionTransparency.decision.mode = 'overridden-detected';
94
- console.log(
95
- `Detection override applied: ${toTitleCase(overrideStackFileName)} + ${toTitleCase(overrideBlueprintFileName)}.`
96
- );
97
- }
98
- } else {
99
- detectedSetupWasApplied = true;
100
- detectionTransparency.quickConfirmation.response = 'non-interactive-auto';
101
- detectionTransparency.decision.mode = 'non-interactive-auto';
102
- console.log(`Using detected stack automatically for this existing project: ${toTitleCase(projectDetection.recommendedStackFileName)}.`);
103
- if (projectDetection.secondaryStackFileNames?.length) {
104
- console.log(`Detected additional stack signals: ${projectDetection.secondaryStackFileNames.map((stackFileName) => toTitleCase(stackFileName)).join(', ')}.`);
105
- }
106
- selectedAdditionalStackFileNames = projectDetection.secondaryStackFileNames || [];
107
- }
108
- } else if (projectDetection.hasExistingProjectFiles && projectDetection.recommendedStackFileName) {
109
- detectionTransparency.quickConfirmation.response = 'explicit-selection-or-low-confidence';
110
- detectionTransparency.decision.mode = 'explicit-selection-or-low-confidence';
23
+ detectionTransparency.quickConfirmation.response = 'evidence-only';
24
+ detectionTransparency.decision.mode = 'existing-project-evidence-only';
25
+ selectedAdditionalStackFileNames = [];
26
+ } else if (projectDetection.hasExistingProjectFiles && projectDetection.detectedStackFileName) {
27
+ detectionTransparency.quickConfirmation.response = 'evidence-only';
28
+ detectionTransparency.decision.mode = 'existing-project-evidence-only';
111
29
  } else if (!projectDetection.hasExistingProjectFiles) {
112
30
  detectionTransparency.quickConfirmation.response = 'not-applicable';
113
- detectionTransparency.decision.mode = 'fresh-directory';
31
+ detectionTransparency.decision.mode = 'fresh-agent-decision-required';
114
32
  }
115
33
 
116
34
  return {
@@ -118,6 +36,5 @@ export async function resolveDetectedSetupDecision({
118
36
  selectedManualStackFileName,
119
37
  selectedManualBlueprintFileName,
120
38
  selectedAdditionalStackFileNames,
121
- detectedBlueprintFileName,
122
39
  };
123
- }
40
+ }
@@ -2,34 +2,9 @@
2
2
  * Init Selection Helpers — stack/blueprint filtering and scope normalization.
3
3
  */
4
4
  import {
5
- BLUEPRINT_RECOMMENDATIONS,
6
5
  PROJECT_SCOPE_CHOICES,
7
- PROJECT_SCOPE_STACK_FILTERS,
8
- WEB_FRONTEND_BLUEPRINT_CANDIDATES,
9
- WEB_BACKEND_BLUEPRINT_CANDIDATES,
10
6
  } from './constants.mjs';
11
7
 
12
- export function filterStackFileNamesByCandidates(allStackFileNames, preferredStackFileNames) {
13
- if (!Array.isArray(preferredStackFileNames) || preferredStackFileNames.length === 0) {
14
- return allStackFileNames;
15
- }
16
-
17
- const filteredStackFileNames = preferredStackFileNames.filter((stackFileName) => allStackFileNames.includes(stackFileName));
18
- return filteredStackFileNames.length > 0 ? filteredStackFileNames : allStackFileNames;
19
- }
20
-
21
- export function filterBlueprintFileNamesByCandidates(allBlueprintFileNames, preferredBlueprintFileNames) {
22
- if (!Array.isArray(preferredBlueprintFileNames) || preferredBlueprintFileNames.length === 0) {
23
- return allBlueprintFileNames;
24
- }
25
-
26
- const filteredBlueprintFileNames = preferredBlueprintFileNames.filter(
27
- (blueprintFileName) => allBlueprintFileNames.includes(blueprintFileName)
28
- );
29
-
30
- return filteredBlueprintFileNames.length > 0 ? filteredBlueprintFileNames : allBlueprintFileNames;
31
- }
32
-
33
8
  export function resolveProjectScopeKeyFromLabel(selectedProjectScopeLabel) {
34
9
  const projectScopeEntry = PROJECT_SCOPE_CHOICES.find((scopeChoice) => scopeChoice.label === selectedProjectScopeLabel);
35
10
  return projectScopeEntry?.key || 'both';
@@ -53,48 +28,7 @@ export function normalizeAdditionalBlueprintSelection(selectedBlueprintFileName,
53
28
  )));
54
29
  }
55
30
 
56
- export function deriveAdditionalBlueprintFileNamesFromStacks(
57
- additionalStackFileNames,
58
- allBlueprintFileNames,
59
- selectedBlueprintFileName
60
- ) {
61
- const derivedBlueprintFileNames = [];
62
-
63
- for (const additionalStackFileName of additionalStackFileNames || []) {
64
- const mappedBlueprintFileName = BLUEPRINT_RECOMMENDATIONS[additionalStackFileName];
65
- if (!mappedBlueprintFileName) {
66
- continue;
67
- }
68
-
69
- if (!allBlueprintFileNames.includes(mappedBlueprintFileName)) {
70
- continue;
71
- }
72
-
73
- if (mappedBlueprintFileName === selectedBlueprintFileName) {
74
- continue;
75
- }
76
-
77
- derivedBlueprintFileNames.push(mappedBlueprintFileName);
78
- }
79
-
80
- return Array.from(new Set(derivedBlueprintFileNames));
81
- }
82
-
83
- export function resolveScopeStackCandidates(projectScopeKey) {
84
- return PROJECT_SCOPE_STACK_FILTERS[projectScopeKey] || null;
85
- }
86
-
87
31
  export function resolveScopeBlueprintCandidates(projectScopeKey) {
88
- if (projectScopeKey === 'frontend-only') {
89
- return WEB_FRONTEND_BLUEPRINT_CANDIDATES;
90
- }
91
-
92
- if (projectScopeKey === 'backend-only') {
93
- return WEB_BACKEND_BLUEPRINT_CANDIDATES;
94
- }
95
-
96
- return Array.from(new Set([
97
- ...WEB_FRONTEND_BLUEPRINT_CANDIDATES,
98
- ...WEB_BACKEND_BLUEPRINT_CANDIDATES,
99
- ]));
32
+ void projectScopeKey;
33
+ return null;
100
34
  }
@@ -61,7 +61,7 @@ export const DESIGN_REQUIRED_SECTIONS = [
61
61
  'Responsive Strategy and Cross-Viewport Adaptation Matrix',
62
62
  'Interaction, Motion, and Feedback Rules',
63
63
  'Component Language, Morphology, and Shared Patterns',
64
- 'Context Hygiene and Approved Reference Boundaries',
64
+ 'Context Hygiene and Source Boundaries',
65
65
  'Accessibility Non-Negotiables',
66
66
  'Anti-Patterns to Avoid',
67
67
  'Implementation Notes for Future UI Tasks',