@ryuenn3123/agentic-senior-core 3.0.19 → 3.0.21
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.
- package/.agent-context/prompts/bootstrap-design.md +96 -103
- package/.agent-context/prompts/init-project.md +32 -100
- package/.agent-context/prompts/refactor.md +22 -44
- package/.agent-context/prompts/review-code.md +28 -52
- package/.agent-context/review-checklists/architecture-review.md +31 -62
- package/.agent-context/review-checklists/pr-checklist.md +74 -108
- package/.agent-context/rules/api-docs.md +18 -206
- package/.agent-context/rules/architecture.md +40 -207
- package/.agent-context/rules/database-design.md +10 -199
- package/.agent-context/rules/docker-runtime.md +5 -5
- package/.agent-context/rules/efficiency-vs-hype.md +11 -149
- package/.agent-context/rules/error-handling.md +9 -231
- package/.agent-context/rules/event-driven.md +17 -221
- package/.agent-context/rules/frontend-architecture.md +74 -119
- package/.agent-context/rules/git-workflow.md +1 -1
- package/.agent-context/rules/microservices.md +28 -161
- package/.agent-context/rules/naming-conv.md +8 -138
- package/.agent-context/rules/performance.md +9 -175
- package/.agent-context/rules/realtime.md +11 -44
- package/.agent-context/rules/security.md +11 -295
- package/.agent-context/rules/testing.md +9 -174
- package/.agent-context/state/benchmark-analysis.json +3 -3
- package/.agent-context/state/memory-continuity-benchmark.json +1 -1
- package/.agent-context/state/onboarding-report.json +71 -11
- package/.agents/workflows/init-project.md +7 -24
- package/.agents/workflows/refactor.md +7 -24
- package/.agents/workflows/review-code.md +7 -24
- package/.cursorrules +22 -21
- package/.gemini/instructions.md +2 -2
- package/.github/copilot-instructions.md +2 -2
- package/.instructions.md +112 -213
- package/.windsurfrules +22 -21
- package/AGENTS.md +4 -4
- package/CONTRIBUTING.md +13 -22
- package/README.md +6 -20
- package/lib/cli/commands/init.mjs +102 -148
- package/lib/cli/commands/launch.mjs +3 -3
- package/lib/cli/commands/optimize.mjs +14 -4
- package/lib/cli/commands/upgrade.mjs +25 -23
- package/lib/cli/compiler.mjs +96 -62
- package/lib/cli/constants.mjs +28 -136
- package/lib/cli/detector/design-evidence.mjs +189 -6
- package/lib/cli/detector.mjs +6 -7
- package/lib/cli/init-detection-flow.mjs +10 -93
- package/lib/cli/init-selection.mjs +2 -68
- package/lib/cli/project-scaffolder/constants.mjs +1 -1
- package/lib/cli/project-scaffolder/design-contract.mjs +183 -108
- package/lib/cli/project-scaffolder/discovery.mjs +36 -82
- package/lib/cli/project-scaffolder/prompt-builders.mjs +45 -55
- package/lib/cli/project-scaffolder/storage.mjs +0 -2
- package/lib/cli/token-optimization.mjs +1 -1
- package/lib/cli/utils.mjs +75 -9
- package/package.json +2 -2
- package/scripts/detection-benchmark.mjs +4 -15
- package/scripts/documentation-boundary-audit.mjs +9 -9
- package/scripts/explain-on-demand-audit.mjs +11 -11
- package/scripts/forbidden-content-check.mjs +9 -9
- package/scripts/frontend-usability-audit.mjs +45 -35
- package/scripts/llm-judge.mjs +1 -1
- package/scripts/mcp-server/constants.mjs +2 -2
- package/scripts/mcp-server/tool-registry.mjs +1 -1
- package/scripts/release-gate/audit-checks.mjs +22 -7
- package/scripts/release-gate/static-checks.mjs +5 -5
- package/scripts/release-gate.mjs +1 -1
- package/scripts/rules-guardian-audit.mjs +14 -13
- package/scripts/single-source-lazy-loading-audit.mjs +3 -3
- package/scripts/sync-thin-adapters.mjs +5 -5
- package/scripts/ui-design-judge/design-execution-summary.mjs +27 -1
- package/scripts/ui-design-judge/prompting.mjs +5 -5
- package/scripts/ui-design-judge/reporting.mjs +3 -1
- package/scripts/ui-design-judge/rubric-calibration.mjs +8 -5
- package/scripts/ui-design-judge/rubric-goldset.json +2 -2
- package/scripts/ui-design-judge.mjs +75 -7
- package/scripts/validate/config.mjs +138 -48
- package/scripts/validate/coverage-checks.mjs +32 -7
- package/scripts/validate.mjs +8 -4
- 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
|
|
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
|
};
|
package/lib/cli/detector.mjs
CHANGED
|
@@ -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
|
-
|
|
602
|
+
detectedStackFileName: null,
|
|
604
603
|
secondaryStackFileNames: [],
|
|
605
|
-
|
|
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
|
-
|
|
645
|
+
detectedStackFileName: strongestCandidate.stackFileName,
|
|
647
646
|
secondaryStackFileNames,
|
|
648
|
-
|
|
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.
|
|
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.
|
|
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
|
-
'
|
|
18
|
-
'Explicit stack or blueprint overrides
|
|
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
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
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-
|
|
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
|
-
|
|
89
|
-
|
|
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
|
|
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',
|