@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.
- package/.agent-context/prompts/bootstrap-design.md +84 -94
- 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 +66 -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 +438 -335
- package/lib/cli/project-scaffolder/discovery.mjs +36 -82
- package/lib/cli/project-scaffolder/prompt-builders.mjs +55 -63
- package/lib/cli/project-scaffolder/storage.mjs +0 -4
- 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 +57 -36
- package/scripts/llm-judge.mjs +1 -1
- package/scripts/mcp-server/constants.mjs +60 -0
- package/scripts/mcp-server/tool-registry.mjs +149 -0
- package/scripts/mcp-server/tools.mjs +446 -0
- package/scripts/mcp-server.mjs +23 -661
- package/scripts/release-gate/audit-checks.mjs +426 -0
- package/scripts/release-gate/constants.mjs +53 -0
- package/scripts/release-gate/runtime.mjs +63 -0
- package/scripts/release-gate/static-checks.mjs +182 -0
- package/scripts/release-gate.mjs +13 -794
- 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/constants.mjs +24 -0
- package/scripts/ui-design-judge/design-execution-summary.mjs +259 -0
- package/scripts/ui-design-judge/git-input.mjs +131 -0
- package/scripts/ui-design-judge/prompting.mjs +73 -0
- package/scripts/ui-design-judge/providers.mjs +102 -0
- package/scripts/ui-design-judge/reporting.mjs +182 -0
- package/scripts/ui-design-judge/rubric-calibration.mjs +214 -0
- package/scripts/ui-design-judge/rubric-goldset.json +188 -0
- package/scripts/ui-design-judge.mjs +166 -771
- package/scripts/ui-rubric-calibration.mjs +35 -0
- package/scripts/validate/config.mjs +198 -55
- package/scripts/validate/coverage-checks.mjs +32 -7
- package/scripts/validate.mjs +8 -4
- package/lib/cli/architect.mjs +0 -431
|
@@ -29,174 +29,56 @@ export function shouldBootstrapDesignDocument(discoveryAnswers, initContext) {
|
|
|
29
29
|
return false;
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
function
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
'Keep decision-critical information prominent while secondary merchandising stays quiet.',
|
|
52
|
-
'Let imagery and spacing create premium perception before decorative effects do.',
|
|
53
|
-
],
|
|
54
|
-
motionPurpose: 'Use motion to reinforce buying confidence, product continuity, and premium delight. It may be theatrical at key moments if it stays fast, legible, and supportive of decision-making.',
|
|
55
|
-
motionChoreography: 'Favor fast hover and focus feedback, confident sheet choreography, product-media continuity, and one or two signature reveal moments. Avoid autoplay spectacle that distracts from purchase decisions.',
|
|
56
|
-
motionDurations: {
|
|
57
|
-
desktop: 180,
|
|
58
|
-
mobile: 240,
|
|
59
|
-
},
|
|
60
|
-
componentMorphology: {
|
|
61
|
-
mobile: 'Product cards should compress supporting metadata, pin purchase actions closer to the thumb zone, and move comparison into progressive disclosure or bottom sheets.',
|
|
62
|
-
tablet: 'Cards and merch modules should preserve comparison affordances while reducing tertiary chrome and keeping visual hierarchy stable.',
|
|
63
|
-
desktop: 'Cards can expand media, comparison, and reassurance copy while keeping buying cues dominant and visually disciplined.',
|
|
64
|
-
},
|
|
65
|
-
mutationRules: {
|
|
66
|
-
mobile: 'Convert browsing into vertically stacked product cards, move cart and filter actions into sticky or bottom-sheet patterns, and keep thumb-reach actions persistent.',
|
|
67
|
-
tablet: 'Preserve browsing flow with a two-column rhythm, collapse tertiary filters, and keep comparison moments visible without forcing desktop density.',
|
|
68
|
-
desktop: 'Expose multi-column merchandising, comparison views, and richer product context while keeping the purchase path visually dominant.',
|
|
69
|
-
},
|
|
70
|
-
};
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
if (aggregateText.includes('dashboard') || aggregateText.includes('operations') || aggregateText.includes('report')) {
|
|
74
|
-
return {
|
|
75
|
-
designPhilosophy: 'Operational calm under high information density.',
|
|
76
|
-
brandAdjectives: ['calm', 'precise', 'trustworthy'],
|
|
77
|
-
antiAdjectives: ['chaotic', 'gimmicky', 'visually exhausting'],
|
|
78
|
-
typographyScaleRatio: '1.125',
|
|
79
|
-
baseGridUnit: 4,
|
|
80
|
-
densityMode: 'high-density-scanning',
|
|
81
|
-
colorIntent: 'Use neutrals for structure and reserve accent saturation for status shifts, risky actions, and alerts.',
|
|
82
|
-
distinctiveMoves: [
|
|
83
|
-
'Prioritize scanning clarity and status recognition over decorative density.',
|
|
84
|
-
'Use visual weight to separate signal from operational noise.',
|
|
85
|
-
'Reserve strong accents for alerts, decisions, and state transitions only.',
|
|
86
|
-
],
|
|
87
|
-
motionPurpose: 'Use motion as operational feedback and state continuity, while still allowing decisive state transitions that make dense workflows feel alive and controlled.',
|
|
88
|
-
motionChoreography: 'Prefer fast transitions for filters, drawers, status reveals, and row expansion, but allow strong confirmation moments when they improve confidence and scan clarity.',
|
|
89
|
-
motionDurations: {
|
|
90
|
-
desktop: 160,
|
|
91
|
-
mobile: 220,
|
|
92
|
-
},
|
|
93
|
-
componentMorphology: {
|
|
94
|
-
mobile: 'Data rows should become prioritized cards or grouped summaries, with filters and secondary tools moving into sheets or drawers.',
|
|
95
|
-
tablet: 'Operational panels should retain split-view logic where possible, while tertiary panels collapse behind explicit toggles.',
|
|
96
|
-
desktop: 'Dense tables, side panels, and comparison surfaces can remain visible simultaneously, with state treatments optimized for rapid scanning.',
|
|
97
|
-
},
|
|
98
|
-
mutationRules: {
|
|
99
|
-
mobile: 'Collapse dense tables into prioritized cards or row groups, move filters into drawers or sheets, and pin the most critical actions to the bottom reach zone.',
|
|
100
|
-
tablet: 'Keep two-column or split-pane workflows, collapse tertiary panels, and maintain fast scan paths for operators using touch or keyboard.',
|
|
101
|
-
desktop: 'Expose the highest-density views with visible navigation, comparison surfaces, and simultaneous context panels for power users.',
|
|
102
|
-
},
|
|
103
|
-
};
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
if (aggregateText.includes('developer') || aggregateText.includes('api') || aggregateText.includes('platform')) {
|
|
107
|
-
return {
|
|
108
|
-
designPhilosophy: 'Technical precision with explicit structure and honest feedback.',
|
|
109
|
-
brandAdjectives: ['precise', 'technical', 'transparent'],
|
|
110
|
-
antiAdjectives: ['vague', 'marketing-heavy', 'template-polished'],
|
|
111
|
-
typographyScaleRatio: '1.125',
|
|
112
|
-
baseGridUnit: 4,
|
|
113
|
-
densityMode: 'technical-utility',
|
|
114
|
-
colorIntent: 'Anchor the interface in disciplined neutrals and use accent color only where state, feedback, or code-adjacent interaction needs emphasis.',
|
|
115
|
-
distinctiveMoves: [
|
|
116
|
-
'Make structure and feedback feel exact without becoming sterile.',
|
|
117
|
-
'Use code-adjacent rhythm and hierarchy to build trust with technical users.',
|
|
118
|
-
'Keep complexity legible through spacing, grouping, and explicit interaction states.',
|
|
119
|
-
],
|
|
120
|
-
motionPurpose: 'Use motion to clarify causality, reveal system state, preserve context, and give technical workflows a sense of precision instead of dead stillness.',
|
|
121
|
-
motionChoreography: 'Prefer sharp panel transitions, command feedback, disclosure motion, and occasional signature transitions that feel exact rather than ornamental.',
|
|
122
|
-
motionDurations: {
|
|
123
|
-
desktop: 170,
|
|
124
|
-
mobile: 230,
|
|
125
|
-
},
|
|
126
|
-
componentMorphology: {
|
|
127
|
-
mobile: 'Technical panes should flatten into sequential sections, with commands and diagnostics colocated near the content they affect.',
|
|
128
|
-
tablet: 'Split views should survive where useful, with explicit panel toggles and condensed chrome for code-adjacent tasks.',
|
|
129
|
-
desktop: 'Navigation, documentation, diagnostics, and active work surfaces can remain concurrently visible when it improves expert comprehension.',
|
|
130
|
-
},
|
|
131
|
-
mutationRules: {
|
|
132
|
-
mobile: 'Switch multi-pane technical layouts into stacked sections, turn secondary navigation into segmented or sheet-based controls, and keep commands near the content they affect.',
|
|
133
|
-
tablet: 'Retain split-view comprehension where possible, compress chrome, and keep documentation or diagnostics adjacent to the active task.',
|
|
134
|
-
desktop: 'Expose full navigation, dense comparison surfaces, and multi-pane workflows for expert scanning and debugging.',
|
|
135
|
-
},
|
|
136
|
-
};
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
if (aggregateText.includes('content') || aggregateText.includes('community') || aggregateText.includes('publish')) {
|
|
140
|
-
return {
|
|
141
|
-
designPhilosophy: 'Editorial flow with warm but controlled expression.',
|
|
142
|
-
brandAdjectives: ['editorial', 'warm', 'expressive'],
|
|
143
|
-
antiAdjectives: ['flat', 'anonymous', 'feed-generic'],
|
|
144
|
-
typographyScaleRatio: '1.200',
|
|
145
|
-
baseGridUnit: 8,
|
|
146
|
-
densityMode: 'reading-first',
|
|
147
|
-
colorIntent: 'Let typography and surface contrast lead while chroma supports hierarchy and key participation actions.',
|
|
148
|
-
distinctiveMoves: [
|
|
149
|
-
'Build a strong reading rhythm so content feels curated rather than dumped into cards.',
|
|
150
|
-
'Use contrast and spacing to guide attention between creation, moderation, and discovery.',
|
|
151
|
-
'Give key interaction moments personality without sacrificing clarity.',
|
|
152
|
-
],
|
|
153
|
-
motionPurpose: 'Use motion to support reading rhythm, reveal structure, and reward contribution moments with visible craft, not generic restraint.',
|
|
154
|
-
motionChoreography: 'Favor reveal choreography for section transitions, expressive but measured feedback on participation, and media behavior that feels alive without becoming noisy.',
|
|
155
|
-
motionDurations: {
|
|
156
|
-
desktop: 190,
|
|
157
|
-
mobile: 250,
|
|
158
|
-
},
|
|
159
|
-
componentMorphology: {
|
|
160
|
-
mobile: 'Reading surfaces should dominate while secondary discovery and community tools collapse behind sheets, tabs, or segmented controls.',
|
|
161
|
-
tablet: 'Editorial modules can balance reading and discovery, provided the primary narrative flow remains obvious.',
|
|
162
|
-
desktop: 'Long-form content, secondary navigation, and related discovery modules can coexist without fragmenting the reading rhythm.',
|
|
163
|
-
},
|
|
164
|
-
mutationRules: {
|
|
165
|
-
mobile: 'Prioritize reading and contribution flows in a single-column narrative stack, tuck secondary discovery tools behind sheets, and keep primary creation actions within reach.',
|
|
166
|
-
tablet: 'Balance narrative reading with supporting discovery modules, using two-column compositions only where hierarchy stays obvious.',
|
|
167
|
-
desktop: 'Use wider editorial compositions, visible secondary navigation, and modular discovery surfaces without breaking reading rhythm.',
|
|
168
|
-
},
|
|
169
|
-
};
|
|
170
|
-
}
|
|
32
|
+
function buildStructureFirstSeedSignals({
|
|
33
|
+
projectName,
|
|
34
|
+
projectDescription,
|
|
35
|
+
primaryDomain,
|
|
36
|
+
supplementalFields = {},
|
|
37
|
+
}) {
|
|
38
|
+
const normalizedDescription = String(projectDescription || '').trim();
|
|
39
|
+
const repoEvidenceSummary = supplementalFields?.repoEvidence?.designEvidenceSummary || null;
|
|
40
|
+
const hasRepoEvidence = Boolean(
|
|
41
|
+
repoEvidenceSummary
|
|
42
|
+
|| (Array.isArray(supplementalFields?.repoEvidence?.workspaceUiEntries)
|
|
43
|
+
&& supplementalFields.repoEvidence.workspaceUiEntries.length > 0)
|
|
44
|
+
);
|
|
45
|
+
const evidenceSourceLabel = hasRepoEvidence
|
|
46
|
+
? 'current repo evidence, existing UI code, and the active brief'
|
|
47
|
+
: 'the active brief and any repo evidence available at synthesis time';
|
|
48
|
+
const projectContextLabel = normalizedDescription
|
|
49
|
+
? `the product context "${normalizedDescription}"`
|
|
50
|
+
: 'the current product context';
|
|
171
51
|
|
|
172
52
|
return {
|
|
173
|
-
designPhilosophy: '
|
|
174
|
-
brandAdjectives: ['
|
|
175
|
-
antiAdjectives: ['
|
|
176
|
-
typographyScaleRatio: '
|
|
177
|
-
baseGridUnit:
|
|
178
|
-
|
|
179
|
-
|
|
53
|
+
designPhilosophy: `Use ${evidenceSourceLabel} to synthesize the design system for ${projectName || 'this project'}. This seed is only a decision scaffold: the LLM must choose the visual language, libraries, color system, typography, spacing, and interaction model from ${projectContextLabel}, current repo evidence, and live official documentation when a technology claim is needed.`,
|
|
54
|
+
brandAdjectives: ['agent-synthesized-from-current-context'],
|
|
55
|
+
antiAdjectives: ['offline-prescribed-style', 'template-by-default', 'scale-only-responsive', 'unresearched-library-choice'],
|
|
56
|
+
typographyScaleRatio: 'agent-calibrated-from-content-platform-and-readability',
|
|
57
|
+
baseGridUnit: 'agent-calibrated-from-platform-density-and-implementation-stack',
|
|
58
|
+
spacingPattern: 'agent-defined-from-task-flow-and-viewport-needs',
|
|
59
|
+
densityMode: 'agent-defined-from-user-task-device-and-content-pressure',
|
|
60
|
+
colorIntent: `Choose semantic palette roles from ${projectContextLabel}, current repo evidence, and accessibility needs. Do not inherit fixed palettes or generic SaaS color defaults from this scaffold.`,
|
|
61
|
+
paletteRoles: ['agent-defined-semantic-roles'],
|
|
180
62
|
distinctiveMoves: [
|
|
181
|
-
'
|
|
182
|
-
'
|
|
183
|
-
'
|
|
63
|
+
'Research and choose a current, project-fit visual direction instead of inheriting any offline preset from this scaffold.',
|
|
64
|
+
'Define at least one recognizable design move from the product task, audience, content, and repo evidence before implementation.',
|
|
65
|
+
'Document why the chosen move belongs to this project and which common LLM bad habit it intentionally avoids.',
|
|
184
66
|
],
|
|
185
|
-
motionPurpose: '
|
|
186
|
-
motionChoreography: '
|
|
67
|
+
motionPurpose: 'Use modern motion when it improves hierarchy, continuity, feedback, memorability, or perceived product quality. If implementation needs a motion library, the LLM must choose a current compatible option from official docs instead of relying on an offline default.',
|
|
68
|
+
motionChoreography: 'Define choreography from the product experience and implementation stack. Keep it performant and reduced-motion-safe; do not suppress rich interaction by default.',
|
|
187
69
|
motionDurations: {
|
|
188
|
-
desktop:
|
|
189
|
-
mobile:
|
|
70
|
+
desktop: 'agent-calibrated',
|
|
71
|
+
mobile: 'agent-calibrated',
|
|
190
72
|
},
|
|
191
73
|
componentMorphology: {
|
|
192
|
-
mobile: '
|
|
193
|
-
tablet: '
|
|
194
|
-
desktop: '
|
|
74
|
+
mobile: 'Recompose the experience for touch, task priority, and constrained attention. Mobile should be a deliberate mobile design, not a shrunken desktop.',
|
|
75
|
+
tablet: 'Regroup surfaces for medium-width use, preserving task clarity without cloning either desktop or mobile blindly.',
|
|
76
|
+
desktop: 'Use the available space to improve hierarchy, scanability, and interaction quality without defaulting to template grids or generic dashboard chrome.',
|
|
195
77
|
},
|
|
196
78
|
mutationRules: {
|
|
197
|
-
mobile: '
|
|
198
|
-
tablet: '
|
|
199
|
-
desktop: '
|
|
79
|
+
mobile: 'Define a mobile-specific composition with reordered, merged, or disclosed content where appropriate. Scale-only shrink behavior is failure.',
|
|
80
|
+
tablet: 'Define a tablet-specific regrouping strategy rather than a width-only reduction of desktop.',
|
|
81
|
+
desktop: 'Define a desktop composition that uses space intentionally and avoids generic equal-weight modules unless the project evidence justifies them.',
|
|
200
82
|
},
|
|
201
83
|
};
|
|
202
84
|
}
|
|
@@ -207,47 +89,54 @@ function buildDesignIntentContractObject({
|
|
|
207
89
|
primaryDomain,
|
|
208
90
|
features = [],
|
|
209
91
|
initContext,
|
|
210
|
-
architectureRecommendation = null,
|
|
211
92
|
status = 'seed-needs-design-synthesis',
|
|
212
93
|
supplementalFields = {},
|
|
213
94
|
}) {
|
|
214
|
-
const inferredKeywords =
|
|
95
|
+
const inferredKeywords = buildStructureFirstSeedSignals({
|
|
96
|
+
projectName,
|
|
215
97
|
projectDescription,
|
|
216
98
|
primaryDomain,
|
|
217
99
|
features,
|
|
100
|
+
supplementalFields,
|
|
218
101
|
});
|
|
219
|
-
const normalizedPrimaryDomain = String(primaryDomain || '').trim().toLowerCase();
|
|
220
|
-
const resolvedSpacingPattern = inferredKeywords.densityMode === 'dense'
|
|
221
|
-
? 'compact-grid'
|
|
222
|
-
: normalizedPrimaryDomain.includes('mobile')
|
|
223
|
-
? 'mobile-first-single-axis'
|
|
224
|
-
: inferredKeywords.densityMode === 'focused'
|
|
225
|
-
? 'high-contrast-rhythm'
|
|
226
|
-
: 'balanced-grid';
|
|
227
102
|
|
|
228
103
|
return {
|
|
229
104
|
mode: 'dynamic',
|
|
230
105
|
status,
|
|
106
|
+
seedPolicy: {
|
|
107
|
+
mode: 'structure-first-scaffold',
|
|
108
|
+
requiresProjectSpecificRefinement: true,
|
|
109
|
+
forbidLiteralCarryoverAsFinalArtDirection: true,
|
|
110
|
+
repoEvidenceShouldOverrideSeedTaste: true,
|
|
111
|
+
},
|
|
231
112
|
project: {
|
|
232
113
|
name: projectName,
|
|
233
114
|
context: projectDescription,
|
|
234
115
|
domain: primaryDomain,
|
|
235
|
-
|
|
236
|
-
|
|
116
|
+
runtimeConstraint: initContext.stackFileName === 'agent-decision-runtime.md'
|
|
117
|
+
? 'agent-recommendation-required'
|
|
118
|
+
: toTitleCase(initContext.stackFileName),
|
|
119
|
+
architectureConstraint: initContext.blueprintFileName === 'agent-decision-architecture.md'
|
|
120
|
+
? 'agent-recommendation-required'
|
|
121
|
+
: toTitleCase(initContext.blueprintFileName),
|
|
237
122
|
},
|
|
238
123
|
designPhilosophy: inferredKeywords.designPhilosophy,
|
|
239
124
|
brandAdjectives: inferredKeywords.brandAdjectives,
|
|
240
125
|
antiAdjectives: inferredKeywords.antiAdjectives,
|
|
241
126
|
visualDirection: {
|
|
242
|
-
|
|
127
|
+
seedMode: 'scaffold-only',
|
|
128
|
+
requiresProjectSpecificSynthesis: true,
|
|
129
|
+
selectionAuthority: 'agent-llm-after-current-context-repo-evidence-and-live-official-docs',
|
|
130
|
+
trendStance: 'current-context-first-not-offline-preset-first',
|
|
243
131
|
distinctiveMoves: inferredKeywords.distinctiveMoves,
|
|
244
132
|
copiedReferenceAllowed: false,
|
|
245
133
|
},
|
|
246
134
|
mathSystems: {
|
|
247
135
|
typographyScaleRatio: inferredKeywords.typographyScaleRatio,
|
|
248
136
|
baseGridUnit: inferredKeywords.baseGridUnit,
|
|
249
|
-
spacingPattern:
|
|
137
|
+
spacingPattern: inferredKeywords.spacingPattern,
|
|
250
138
|
densityMode: inferredKeywords.densityMode,
|
|
139
|
+
seedValuesRequireCalibration: true,
|
|
251
140
|
},
|
|
252
141
|
tokenSystem: {
|
|
253
142
|
sourceOfTruth: 'docs/design-intent.json',
|
|
@@ -280,7 +169,10 @@ function buildDesignIntentContractObject({
|
|
|
280
169
|
format: 'OKLCH',
|
|
281
170
|
allowHexDerivatives: true,
|
|
282
171
|
requirePerceptualLightnessCurve: true,
|
|
283
|
-
paletteRoles:
|
|
172
|
+
paletteRoles: inferredKeywords.paletteRoles,
|
|
173
|
+
rolePolicy: 'minimum-semantic-scaffold',
|
|
174
|
+
rolesAreMinimumScaffold: true,
|
|
175
|
+
rolesMustBeAgentDefined: true,
|
|
284
176
|
intent: inferredKeywords.colorIntent,
|
|
285
177
|
},
|
|
286
178
|
crossViewportAdaptation: {
|
|
@@ -294,6 +186,7 @@ function buildDesignIntentContractObject({
|
|
|
294
186
|
choreography: inferredKeywords.motionChoreography,
|
|
295
187
|
desktopDurationMs: inferredKeywords.motionDurations.desktop,
|
|
296
188
|
mobileDurationMs: inferredKeywords.motionDurations.mobile,
|
|
189
|
+
seedToneLocked: false,
|
|
297
190
|
respectReducedMotion: true,
|
|
298
191
|
preferTransformAndOpacity: true,
|
|
299
192
|
avoidDecorativeMotionForItsOwnSake: true,
|
|
@@ -301,6 +194,7 @@ function buildDesignIntentContractObject({
|
|
|
301
194
|
componentMorphology: {
|
|
302
195
|
requireStateBehaviorMatrix: true,
|
|
303
196
|
preserveIdentityAcrossViewports: true,
|
|
197
|
+
seedBehaviorsRequireRefinement: true,
|
|
304
198
|
stateKeys: ['default', 'hover', 'focus', 'active', 'disabled', 'loading', 'error'],
|
|
305
199
|
viewportBehavior: inferredKeywords.componentMorphology,
|
|
306
200
|
},
|
|
@@ -327,51 +221,204 @@ function buildDesignIntentContractObject({
|
|
|
327
221
|
typographyReadabilityTuning: true,
|
|
328
222
|
},
|
|
329
223
|
},
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
224
|
+
designExecutionPolicy: {
|
|
225
|
+
representationStrategy: 'surface-plan-v1',
|
|
226
|
+
seedRefinementRequiredBeforeUiImplementation: true,
|
|
227
|
+
requireSurfacePlan: true,
|
|
228
|
+
requireComponentGraph: true,
|
|
229
|
+
requireViewportMutationPlan: true,
|
|
230
|
+
requireInteractionStateMatrix: true,
|
|
231
|
+
requireContentPriorityMap: true,
|
|
232
|
+
requireTaskFlowNarrative: true,
|
|
233
|
+
requireSignatureMoveRationale: true,
|
|
234
|
+
requireStructuredHandoff: true,
|
|
235
|
+
requireRepoEvidenceAlignment: true,
|
|
236
|
+
forbidScreenshotDependency: true,
|
|
237
|
+
handoffFormatVersion: 'ui-handoff-v1',
|
|
238
|
+
requirePerSurfaceMutationOps: true,
|
|
239
|
+
forbidUniformSiblingSurfaceTreatment: true,
|
|
240
|
+
semanticReviewFocus: [
|
|
241
|
+
'distinctiveness-vs-genericity',
|
|
242
|
+
'contract-fidelity',
|
|
243
|
+
'hierarchy-and-task-priority',
|
|
244
|
+
'component-state-behavior',
|
|
245
|
+
'cross-viewport-mutation',
|
|
246
|
+
],
|
|
247
|
+
},
|
|
248
|
+
designExecutionHandoff: {
|
|
249
|
+
version: 'ui-handoff-v1',
|
|
250
|
+
location: 'inline-design-intent',
|
|
251
|
+
status: 'seed-needs-refinement',
|
|
252
|
+
seedMode: 'structure-first-scaffold',
|
|
253
|
+
requiresTaskSpecificRefinement: true,
|
|
254
|
+
primaryExperienceGoal: `Ask the LLM to define the main ${String(primaryDomain || 'product').toLowerCase()} journey in ${projectName} from repo evidence, product context, user goals, and current official documentation where technology choices matter. This scaffold must not prescribe the final visual layout.`,
|
|
255
|
+
surfacePlan: [
|
|
256
|
+
{
|
|
257
|
+
surfaceId: 'agent-defined-primary-experience',
|
|
258
|
+
role: 'llm-synthesized-from-current-context',
|
|
259
|
+
goal: `Define the primary UI experience for ${projectName} from the actual product task, audience, data, and repo evidence before coding.`,
|
|
260
|
+
primaryAction: 'The LLM must choose the first decisive action or reading path and explain why it fits the project.',
|
|
261
|
+
supportingModules: ['agent-defined-from-current-context'],
|
|
262
|
+
layoutAntiPatternToAvoid: 'template-default-without-product-rationale',
|
|
263
|
+
signatureMoveHint: 'Choose and document one project-specific visual, interaction, or content move. Do not inherit it from this scaffold.',
|
|
264
|
+
},
|
|
265
|
+
{
|
|
266
|
+
surfaceId: 'agent-defined-supporting-experience',
|
|
267
|
+
role: 'llm-synthesized-supporting-context',
|
|
268
|
+
goal: 'Define supporting, proof, utility, or recovery surfaces from actual user needs instead of cloning generic cards or rails.',
|
|
269
|
+
primaryAction: 'The LLM must decide what belongs beside, below, hidden behind disclosure, or removed based on task priority.',
|
|
270
|
+
supportingModules: ['agent-defined-from-current-context'],
|
|
271
|
+
layoutAntiPatternToAvoid: 'scale-only-responsive-layout',
|
|
272
|
+
signatureMoveHint: 'Explain how supporting content changes across viewports and why the change improves the experience.',
|
|
273
|
+
},
|
|
274
|
+
],
|
|
275
|
+
componentGraph: {
|
|
276
|
+
nodes: [
|
|
277
|
+
{
|
|
278
|
+
id: 'agent-defined-primary-experience',
|
|
279
|
+
role: 'primary-experience-after-synthesis',
|
|
280
|
+
priority: 'high',
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
id: 'agent-defined-supporting-experience',
|
|
284
|
+
role: 'supporting-experience-after-synthesis',
|
|
285
|
+
priority: 'medium',
|
|
286
|
+
},
|
|
287
|
+
],
|
|
288
|
+
edges: [
|
|
289
|
+
{
|
|
290
|
+
from: 'agent-defined-primary-experience',
|
|
291
|
+
to: 'agent-defined-supporting-experience',
|
|
292
|
+
relationship: 'agent-defined-from-task-priority',
|
|
293
|
+
},
|
|
347
294
|
],
|
|
348
295
|
},
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
'
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
'
|
|
296
|
+
contentPriorityMap: {
|
|
297
|
+
primary: [
|
|
298
|
+
'agent-defined-core-task-or-reading-path',
|
|
299
|
+
],
|
|
300
|
+
secondary: [
|
|
301
|
+
'agent-defined-supporting-context',
|
|
302
|
+
],
|
|
303
|
+
deferred: [
|
|
304
|
+
'agent-defined-deferred-or-hidden-content',
|
|
358
305
|
],
|
|
359
306
|
},
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
307
|
+
viewportMutationPlan: {
|
|
308
|
+
mobile: {
|
|
309
|
+
primaryOperation: 'agent-defined-mobile-recomposition',
|
|
310
|
+
requiredSurfaceActions: [
|
|
311
|
+
'choose-mobile-specific-task-order',
|
|
312
|
+
'merge-disclose-or-remove-low-priority-content',
|
|
313
|
+
'adapt-interaction-model-for-touch',
|
|
314
|
+
],
|
|
315
|
+
forbiddenPatterns: [
|
|
316
|
+
'scale-only-shrink',
|
|
317
|
+
'desktop-order-preserved-without-priority-shift',
|
|
318
|
+
],
|
|
319
|
+
rationale: inferredKeywords.mutationRules.mobile,
|
|
320
|
+
},
|
|
321
|
+
tablet: {
|
|
322
|
+
primaryOperation: 'agent-defined-tablet-regrouping',
|
|
323
|
+
requiredSurfaceActions: [
|
|
324
|
+
'define-medium-width-information-architecture',
|
|
325
|
+
'avoid-cloning-desktop-by-width-only',
|
|
326
|
+
'preserve-task-clarity',
|
|
327
|
+
],
|
|
328
|
+
forbiddenPatterns: [
|
|
329
|
+
'desktop-layout-reduced-by-width-only',
|
|
330
|
+
'uniform-module-grid-without-role-change',
|
|
331
|
+
],
|
|
332
|
+
rationale: inferredKeywords.mutationRules.tablet,
|
|
333
|
+
},
|
|
334
|
+
desktop: {
|
|
335
|
+
primaryOperation: 'agent-defined-desktop-composition',
|
|
336
|
+
requiredSurfaceActions: [
|
|
337
|
+
'use-space-to-improve-hierarchy',
|
|
338
|
+
'define-scan-pattern-and-action-priority',
|
|
339
|
+
'avoid-equalizing-unrelated-content',
|
|
340
|
+
],
|
|
341
|
+
forbiddenPatterns: [
|
|
342
|
+
'template-shell-without-product-rationale',
|
|
343
|
+
'interchangeable-dashboard-or-landing-chrome',
|
|
344
|
+
],
|
|
345
|
+
rationale: inferredKeywords.mutationRules.desktop,
|
|
346
|
+
},
|
|
364
347
|
},
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
348
|
+
interactionStateMatrix: [
|
|
349
|
+
{
|
|
350
|
+
componentId: 'primary-action-control',
|
|
351
|
+
states: ['default', 'hover', 'focus', 'loading', 'success', 'error'],
|
|
352
|
+
notes: 'Refine these states with project-specific feedback language and visual treatment, but keep them legible, decisive, and consistent across all supported viewports.',
|
|
353
|
+
},
|
|
354
|
+
{
|
|
355
|
+
componentId: 'primary-content-module',
|
|
356
|
+
states: ['default', 'focus', 'expanded', 'loading', 'error'],
|
|
357
|
+
notes: 'Refine this module so it preserves hierarchy and progressive disclosure without collapsing into anonymous cards or safe default dashboard panels.',
|
|
358
|
+
},
|
|
359
|
+
],
|
|
360
|
+
taskFlowNarrative: [
|
|
361
|
+
`Entry: the LLM must define how ${projectName} starts the user journey from real product evidence instead of a generic opening pattern.`,
|
|
362
|
+
'Decision: the LLM must define hierarchy, proof, state language, and interaction behavior from the actual task.',
|
|
363
|
+
'Resolution: the LLM must define feedback, recovery, and next-useful-action behavior without defaulting to leftover template chrome.',
|
|
364
|
+
],
|
|
365
|
+
signatureMoveRationale: 'The LLM must choose the project-specific visual, motion, typographic, compositional, or interaction move after reading current context and explain why a generic fallback would weaken the product.',
|
|
366
|
+
implementationGuardrails: {
|
|
367
|
+
requireBuildFromHandoff: true,
|
|
368
|
+
requireGapNotesBeforeFallback: true,
|
|
369
|
+
forbidGenericLayoutFallbackWithoutReason: true,
|
|
370
370
|
},
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
371
|
+
},
|
|
372
|
+
reviewRubric: {
|
|
373
|
+
version: 'ui-rubric-v1',
|
|
374
|
+
genericityAutoFail: true,
|
|
375
|
+
dimensions: [
|
|
376
|
+
{
|
|
377
|
+
key: 'distinctiveness',
|
|
378
|
+
blockingByDefault: true,
|
|
379
|
+
question: 'Does the UI feel authored and project-specific rather than like a default framework or template kit?',
|
|
380
|
+
},
|
|
381
|
+
{
|
|
382
|
+
key: 'contractFidelity',
|
|
383
|
+
blockingByDefault: true,
|
|
384
|
+
question: 'Does the changed UI still follow the explicit design contract, interaction priorities, and accessibility boundaries?',
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
key: 'visualConsistency',
|
|
388
|
+
blockingByDefault: false,
|
|
389
|
+
question: 'Do typography, spacing, color usage, and component behaviors still feel like one system?',
|
|
390
|
+
},
|
|
391
|
+
{
|
|
392
|
+
key: 'heuristicUxQuality',
|
|
393
|
+
blockingByDefault: false,
|
|
394
|
+
question: 'Does the UI preserve task clarity, feedback quality, and user confidence in the touched flows?',
|
|
395
|
+
},
|
|
396
|
+
{
|
|
397
|
+
key: 'motionDiscipline',
|
|
398
|
+
blockingByDefault: false,
|
|
399
|
+
question: 'If motion is present, does it stay purposeful, performant, reduced-motion-safe, and consistent with the product tone?',
|
|
400
|
+
},
|
|
401
|
+
],
|
|
402
|
+
genericitySignals: [
|
|
403
|
+
'offline-prescribed-style-used-as-final-direction',
|
|
404
|
+
'unresearched-library-or-framework-choice',
|
|
405
|
+
'default-component-kit-treatment-without-product-rationale',
|
|
406
|
+
'scale-only-responsive-layout',
|
|
407
|
+
'template-shell-without-product-rationale',
|
|
408
|
+
'inaccessible-or-decorative-motion',
|
|
409
|
+
],
|
|
410
|
+
validBoldSignals: [
|
|
411
|
+
'context-derived-visual-direction',
|
|
412
|
+
'official-docs-backed-library-choice',
|
|
413
|
+
'responsive-recomposition-by-task-priority',
|
|
414
|
+
'purposeful-motion-with-reduced-motion-path',
|
|
415
|
+
'documented-design-rationale-before-code',
|
|
416
|
+
'clean-component-and-token-architecture',
|
|
417
|
+
],
|
|
418
|
+
reportingRules: {
|
|
419
|
+
mustExplainGenericity: true,
|
|
420
|
+
mustSeparateTasteFromFailure: true,
|
|
421
|
+
contractFidelityOverridesPersonalTaste: true,
|
|
375
422
|
},
|
|
376
423
|
},
|
|
377
424
|
contextHygiene: {
|
|
@@ -380,7 +427,7 @@ function buildDesignIntentContractObject({
|
|
|
380
427
|
'current-repo-evidence',
|
|
381
428
|
'current-user-brief',
|
|
382
429
|
'current-project-docs',
|
|
383
|
-
'explicitly-approved-
|
|
430
|
+
'explicitly-approved-current-task-constraints',
|
|
384
431
|
],
|
|
385
432
|
taintedSources: [
|
|
386
433
|
'prior-chat-visual-memory',
|
|
@@ -391,7 +438,7 @@ function buildDesignIntentContractObject({
|
|
|
391
438
|
repoEvidenceOverridesMemory: true,
|
|
392
439
|
requireExplicitContinuityApproval: true,
|
|
393
440
|
forbidCarryoverWhenUnapproved: true,
|
|
394
|
-
|
|
441
|
+
approvedExternalConstraintUsage: 'Convert explicit user-supplied external constraints into current-project rules without comparing against or imitating the source surface.',
|
|
395
442
|
driftSignals: [
|
|
396
443
|
'palette-reused-without-brief-support',
|
|
397
444
|
'motion-signature-reused-without-approval',
|
|
@@ -403,15 +450,17 @@ function buildDesignIntentContractObject({
|
|
|
403
450
|
'Major interface decisions must be explainable in product and user terms.',
|
|
404
451
|
'Accessibility, responsiveness, and implementation realism are non-negotiable.',
|
|
405
452
|
'Cross-viewport behavior must reorganize tasks and navigation, not just scale the desktop layout down.',
|
|
406
|
-
'
|
|
407
|
-
'
|
|
453
|
+
'Modern libraries and interaction patterns may be used when the LLM verifies they fit the project and current official docs.',
|
|
454
|
+
'Motion may be rich and memorable when it improves the product experience, but it must stay purposeful, performant, and optional for reduced-motion users.',
|
|
455
|
+
'At least one visual, interaction, content, or motion decision must be recognizable at a glance and justified from context.',
|
|
408
456
|
],
|
|
409
457
|
forbiddenPatterns: [
|
|
410
|
-
'
|
|
411
|
-
'
|
|
412
|
-
'
|
|
413
|
-
'placeholder-design-language',
|
|
458
|
+
'offline-prescribed-style-used-as-final-direction',
|
|
459
|
+
'unresearched-library-or-framework-choice',
|
|
460
|
+
'default-component-kit-treatment-without-product-rationale',
|
|
414
461
|
'scale-only-responsive-layout',
|
|
462
|
+
'template-shell-without-product-rationale',
|
|
463
|
+
'single-safe-typographic-family-without-role-contrast-or-rationale',
|
|
415
464
|
],
|
|
416
465
|
validationHints: {
|
|
417
466
|
rejectArbitraryHexOnlyPalette: true,
|
|
@@ -424,7 +473,11 @@ function buildDesignIntentContractObject({
|
|
|
424
473
|
requireStateMorphology: true,
|
|
425
474
|
requireAccessibilitySplit: true,
|
|
426
475
|
requireWcagHardFloor: true,
|
|
427
|
-
|
|
476
|
+
requireStructuredDesignExecutionPolicy: true,
|
|
477
|
+
requireStructuredDesignHandoff: true,
|
|
478
|
+
requireReviewRubric: true,
|
|
479
|
+
requireGenericityExplanation: true,
|
|
480
|
+
genericityAutoFail: true,
|
|
428
481
|
requireSignatureMove: true,
|
|
429
482
|
rejectTemplateNeutralLayout: true,
|
|
430
483
|
},
|
|
@@ -474,11 +527,11 @@ export function validateDesignIntentContract(designIntentContract) {
|
|
|
474
527
|
if (!designIntentContract.mathSystems || typeof designIntentContract.mathSystems !== 'object') {
|
|
475
528
|
validationErrors.push('designIntent.mathSystems must exist.');
|
|
476
529
|
} else {
|
|
477
|
-
if (
|
|
478
|
-
validationErrors.push('designIntent.mathSystems.typographyScaleRatio must
|
|
530
|
+
if (!String(designIntentContract.mathSystems.typographyScaleRatio || '').trim()) {
|
|
531
|
+
validationErrors.push('designIntent.mathSystems.typographyScaleRatio must describe the chosen or pending type scale decision.');
|
|
479
532
|
}
|
|
480
|
-
if (!
|
|
481
|
-
validationErrors.push('designIntent.mathSystems.baseGridUnit must
|
|
533
|
+
if (!String(designIntentContract.mathSystems.baseGridUnit || '').trim()) {
|
|
534
|
+
validationErrors.push('designIntent.mathSystems.baseGridUnit must describe the chosen or pending spacing grid decision.');
|
|
482
535
|
}
|
|
483
536
|
}
|
|
484
537
|
|
|
@@ -540,6 +593,16 @@ export function validateDesignIntentContract(designIntentContract) {
|
|
|
540
593
|
if (designIntentContract.colorTruth.allowHexDerivatives !== true) {
|
|
541
594
|
validationErrors.push('designIntent.colorTruth.allowHexDerivatives must equal true.');
|
|
542
595
|
}
|
|
596
|
+
if (!String(designIntentContract.colorTruth.intent || '').trim()) {
|
|
597
|
+
validationErrors.push('designIntent.colorTruth.intent must be a non-empty string.');
|
|
598
|
+
}
|
|
599
|
+
const paletteRoles = designIntentContract.colorTruth.paletteRoles;
|
|
600
|
+
if (!Array.isArray(paletteRoles) || paletteRoles.length < 1) {
|
|
601
|
+
validationErrors.push('designIntent.colorTruth.paletteRoles must define or request agent-defined semantic palette roles.');
|
|
602
|
+
}
|
|
603
|
+
if (designIntentContract.colorTruth.rolesMustBeAgentDefined !== true) {
|
|
604
|
+
validationErrors.push('designIntent.colorTruth.rolesMustBeAgentDefined must equal true.');
|
|
605
|
+
}
|
|
543
606
|
}
|
|
544
607
|
|
|
545
608
|
if (!designIntentContract.crossViewportAdaptation || typeof designIntentContract.crossViewportAdaptation !== 'object') {
|
|
@@ -665,135 +728,175 @@ export function validateDesignIntentContract(designIntentContract) {
|
|
|
665
728
|
if (!Array.isArray(designIntentContract.contextHygiene.taintedSources) || designIntentContract.contextHygiene.taintedSources.length < 3) {
|
|
666
729
|
validationErrors.push('designIntent.contextHygiene.taintedSources must list tainted carryover sources.');
|
|
667
730
|
}
|
|
668
|
-
if (!String(designIntentContract.contextHygiene.
|
|
669
|
-
validationErrors.push('designIntent.contextHygiene.
|
|
731
|
+
if (!String(designIntentContract.contextHygiene.approvedExternalConstraintUsage || '').trim()) {
|
|
732
|
+
validationErrors.push('designIntent.contextHygiene.approvedExternalConstraintUsage must be a non-empty string.');
|
|
733
|
+
}
|
|
734
|
+
}
|
|
735
|
+
|
|
736
|
+
if (!designIntentContract.designExecutionPolicy || typeof designIntentContract.designExecutionPolicy !== 'object') {
|
|
737
|
+
validationErrors.push('designIntent.designExecutionPolicy must exist.');
|
|
738
|
+
} else {
|
|
739
|
+
if (designIntentContract.designExecutionPolicy.representationStrategy !== 'surface-plan-v1') {
|
|
740
|
+
validationErrors.push('designIntent.designExecutionPolicy.representationStrategy must equal "surface-plan-v1".');
|
|
741
|
+
}
|
|
742
|
+
for (const requiredFlagName of [
|
|
743
|
+
'requireSurfacePlan',
|
|
744
|
+
'requireComponentGraph',
|
|
745
|
+
'requireViewportMutationPlan',
|
|
746
|
+
'requireInteractionStateMatrix',
|
|
747
|
+
'requireContentPriorityMap',
|
|
748
|
+
'requireTaskFlowNarrative',
|
|
749
|
+
'requireSignatureMoveRationale',
|
|
750
|
+
'requireStructuredHandoff',
|
|
751
|
+
'requireRepoEvidenceAlignment',
|
|
752
|
+
'forbidScreenshotDependency',
|
|
753
|
+
'requirePerSurfaceMutationOps',
|
|
754
|
+
'forbidUniformSiblingSurfaceTreatment',
|
|
755
|
+
]) {
|
|
756
|
+
if (designIntentContract.designExecutionPolicy[requiredFlagName] !== true) {
|
|
757
|
+
validationErrors.push(`designIntent.designExecutionPolicy.${requiredFlagName} must equal true.`);
|
|
758
|
+
}
|
|
759
|
+
}
|
|
760
|
+
if (designIntentContract.designExecutionPolicy.handoffFormatVersion !== 'ui-handoff-v1') {
|
|
761
|
+
validationErrors.push('designIntent.designExecutionPolicy.handoffFormatVersion must equal "ui-handoff-v1".');
|
|
762
|
+
}
|
|
763
|
+
if (
|
|
764
|
+
!Array.isArray(designIntentContract.designExecutionPolicy.semanticReviewFocus)
|
|
765
|
+
|| designIntentContract.designExecutionPolicy.semanticReviewFocus.length < 4
|
|
766
|
+
) {
|
|
767
|
+
validationErrors.push('designIntent.designExecutionPolicy.semanticReviewFocus must list the required review dimensions.');
|
|
670
768
|
}
|
|
671
769
|
}
|
|
672
770
|
|
|
673
|
-
if (!designIntentContract.
|
|
674
|
-
validationErrors.push('designIntent.
|
|
771
|
+
if (!designIntentContract.designExecutionHandoff || typeof designIntentContract.designExecutionHandoff !== 'object') {
|
|
772
|
+
validationErrors.push('designIntent.designExecutionHandoff must exist.');
|
|
675
773
|
} else {
|
|
676
|
-
if (designIntentContract.
|
|
677
|
-
validationErrors.push('designIntent.
|
|
774
|
+
if (designIntentContract.designExecutionHandoff.version !== 'ui-handoff-v1') {
|
|
775
|
+
validationErrors.push('designIntent.designExecutionHandoff.version must equal "ui-handoff-v1".');
|
|
678
776
|
}
|
|
679
|
-
if (designIntentContract.
|
|
680
|
-
validationErrors.push('designIntent.
|
|
777
|
+
if (designIntentContract.designExecutionHandoff.seedMode !== 'structure-first-scaffold') {
|
|
778
|
+
validationErrors.push('designIntent.designExecutionHandoff.seedMode must equal "structure-first-scaffold".');
|
|
681
779
|
}
|
|
682
|
-
if (designIntentContract.
|
|
683
|
-
validationErrors.push('designIntent.
|
|
780
|
+
if (designIntentContract.designExecutionHandoff.requiresTaskSpecificRefinement !== true) {
|
|
781
|
+
validationErrors.push('designIntent.designExecutionHandoff.requiresTaskSpecificRefinement must equal true.');
|
|
684
782
|
}
|
|
685
|
-
if (!
|
|
686
|
-
validationErrors.push('designIntent.
|
|
783
|
+
if (!String(designIntentContract.designExecutionHandoff.primaryExperienceGoal || '').trim()) {
|
|
784
|
+
validationErrors.push('designIntent.designExecutionHandoff.primaryExperienceGoal must be a non-empty string.');
|
|
687
785
|
}
|
|
688
|
-
|
|
689
|
-
|
|
690
|
-
|
|
691
|
-
|
|
786
|
+
if (!Array.isArray(designIntentContract.designExecutionHandoff.surfacePlan) || designIntentContract.designExecutionHandoff.surfacePlan.length < 1) {
|
|
787
|
+
validationErrors.push('designIntent.designExecutionHandoff.surfacePlan must define at least one planned surface.');
|
|
788
|
+
}
|
|
789
|
+
const componentGraph = designIntentContract.designExecutionHandoff.componentGraph;
|
|
790
|
+
if (!componentGraph || typeof componentGraph !== 'object') {
|
|
791
|
+
validationErrors.push('designIntent.designExecutionHandoff.componentGraph must exist.');
|
|
692
792
|
} else {
|
|
693
|
-
if (
|
|
694
|
-
validationErrors.push('designIntent.
|
|
695
|
-
}
|
|
696
|
-
if (capturePlan.requireFullPageCapture !== true) {
|
|
697
|
-
validationErrors.push('designIntent.visualQaPolicy.capturePlan.requireFullPageCapture must equal true.');
|
|
698
|
-
}
|
|
699
|
-
if (capturePlan.requireSectionCapturesForLongPages !== true) {
|
|
700
|
-
validationErrors.push('designIntent.visualQaPolicy.capturePlan.requireSectionCapturesForLongPages must equal true.');
|
|
793
|
+
if (!Array.isArray(componentGraph.nodes) || componentGraph.nodes.length < 2) {
|
|
794
|
+
validationErrors.push('designIntent.designExecutionHandoff.componentGraph.nodes must list the primary execution nodes.');
|
|
701
795
|
}
|
|
702
|
-
if (
|
|
703
|
-
validationErrors.push('designIntent.
|
|
704
|
-
}
|
|
705
|
-
if (
|
|
706
|
-
typeof capturePlan.minimumSectionCaptureCount !== 'number'
|
|
707
|
-
|| capturePlan.minimumSectionCaptureCount < 3
|
|
708
|
-
) {
|
|
709
|
-
validationErrors.push('designIntent.visualQaPolicy.capturePlan.minimumSectionCaptureCount must be a number greater than or equal to 3.');
|
|
710
|
-
}
|
|
711
|
-
if (
|
|
712
|
-
typeof capturePlan.maxViewportHeightsPerTile !== 'number'
|
|
713
|
-
|| capturePlan.maxViewportHeightsPerTile < 2
|
|
714
|
-
|| capturePlan.maxViewportHeightsPerTile > 6
|
|
715
|
-
) {
|
|
716
|
-
validationErrors.push('designIntent.visualQaPolicy.capturePlan.maxViewportHeightsPerTile must be a number between 2 and 6.');
|
|
717
|
-
}
|
|
718
|
-
if (
|
|
719
|
-
typeof capturePlan.tileOverlapRatio !== 'number'
|
|
720
|
-
|| capturePlan.tileOverlapRatio <= 0
|
|
721
|
-
|| capturePlan.tileOverlapRatio >= 0.5
|
|
722
|
-
) {
|
|
723
|
-
validationErrors.push('designIntent.visualQaPolicy.capturePlan.tileOverlapRatio must be a number between 0 and 0.5.');
|
|
724
|
-
}
|
|
725
|
-
if (!Array.isArray(capturePlan.requiredSectionTypes) || capturePlan.requiredSectionTypes.length < 3) {
|
|
726
|
-
validationErrors.push('designIntent.visualQaPolicy.capturePlan.requiredSectionTypes must list the required section capture types.');
|
|
796
|
+
if (!Array.isArray(componentGraph.edges) || componentGraph.edges.length < 1) {
|
|
797
|
+
validationErrors.push('designIntent.designExecutionHandoff.componentGraph.edges must define relationships between UI nodes.');
|
|
727
798
|
}
|
|
728
799
|
}
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
validationErrors.push('designIntent.visualQaPolicy.masking must exist.');
|
|
800
|
+
const contentPriorityMap = designIntentContract.designExecutionHandoff.contentPriorityMap;
|
|
801
|
+
if (!contentPriorityMap || typeof contentPriorityMap !== 'object') {
|
|
802
|
+
validationErrors.push('designIntent.designExecutionHandoff.contentPriorityMap must exist.');
|
|
733
803
|
} else {
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
validationErrors.push('designIntent.visualQaPolicy.masking.requireMaskReasonAnnotations must equal true.');
|
|
739
|
-
}
|
|
740
|
-
if (!Array.isArray(maskingPolicy.allowedDynamicMaskCategories) || maskingPolicy.allowedDynamicMaskCategories.length < 4) {
|
|
741
|
-
validationErrors.push('designIntent.visualQaPolicy.masking.allowedDynamicMaskCategories must list the approved masking categories.');
|
|
804
|
+
for (const priorityBucket of ['primary', 'secondary', 'deferred']) {
|
|
805
|
+
if (!Array.isArray(contentPriorityMap[priorityBucket]) || contentPriorityMap[priorityBucket].length < 1) {
|
|
806
|
+
validationErrors.push(`designIntent.designExecutionHandoff.contentPriorityMap.${priorityBucket} must contain at least one item.`);
|
|
807
|
+
}
|
|
742
808
|
}
|
|
743
809
|
}
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
validationErrors.push('designIntent.visualQaPolicy.stability must exist.');
|
|
810
|
+
const viewportMutationPlan = designIntentContract.designExecutionHandoff.viewportMutationPlan;
|
|
811
|
+
if (!viewportMutationPlan || typeof viewportMutationPlan !== 'object') {
|
|
812
|
+
validationErrors.push('designIntent.designExecutionHandoff.viewportMutationPlan must exist.');
|
|
748
813
|
} else {
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
814
|
+
for (const viewportKey of ['mobile', 'tablet', 'desktop']) {
|
|
815
|
+
const viewportPlan = viewportMutationPlan[viewportKey];
|
|
816
|
+
if (!viewportPlan || typeof viewportPlan !== 'object') {
|
|
817
|
+
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey} must be an object.`);
|
|
818
|
+
continue;
|
|
819
|
+
}
|
|
820
|
+
if (!String(viewportPlan.primaryOperation || '').trim()) {
|
|
821
|
+
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey}.primaryOperation must be a non-empty string.`);
|
|
822
|
+
}
|
|
823
|
+
if (!Array.isArray(viewportPlan.requiredSurfaceActions) || viewportPlan.requiredSurfaceActions.length < 2) {
|
|
824
|
+
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey}.requiredSurfaceActions must contain at least two actions.`);
|
|
825
|
+
}
|
|
826
|
+
if (!Array.isArray(viewportPlan.forbiddenPatterns) || viewportPlan.forbiddenPatterns.length < 1) {
|
|
827
|
+
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey}.forbiddenPatterns must contain at least one anti-pattern.`);
|
|
828
|
+
}
|
|
829
|
+
if (!String(viewportPlan.rationale || '').trim()) {
|
|
830
|
+
validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey}.rationale must be a non-empty string.`);
|
|
831
|
+
}
|
|
760
832
|
}
|
|
761
833
|
}
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
834
|
+
if (!Array.isArray(designIntentContract.designExecutionHandoff.interactionStateMatrix) || designIntentContract.designExecutionHandoff.interactionStateMatrix.length < 1) {
|
|
835
|
+
validationErrors.push('designIntent.designExecutionHandoff.interactionStateMatrix must list key component state expectations.');
|
|
836
|
+
}
|
|
837
|
+
if (!Array.isArray(designIntentContract.designExecutionHandoff.taskFlowNarrative) || designIntentContract.designExecutionHandoff.taskFlowNarrative.length < 2) {
|
|
838
|
+
validationErrors.push('designIntent.designExecutionHandoff.taskFlowNarrative must describe the key UI task flow in sequence.');
|
|
839
|
+
}
|
|
840
|
+
if (!String(designIntentContract.designExecutionHandoff.signatureMoveRationale || '').trim()) {
|
|
841
|
+
validationErrors.push('designIntent.designExecutionHandoff.signatureMoveRationale must explain the chosen authored move.');
|
|
842
|
+
}
|
|
843
|
+
const implementationGuardrails = designIntentContract.designExecutionHandoff.implementationGuardrails;
|
|
844
|
+
if (!implementationGuardrails || typeof implementationGuardrails !== 'object') {
|
|
845
|
+
validationErrors.push('designIntent.designExecutionHandoff.implementationGuardrails must exist.');
|
|
766
846
|
} else {
|
|
767
|
-
|
|
768
|
-
|
|
769
|
-
|
|
770
|
-
|
|
771
|
-
|
|
772
|
-
|
|
773
|
-
|
|
774
|
-
|
|
775
|
-
}
|
|
776
|
-
if (
|
|
777
|
-
typeof semanticEscalationPolicy.meaningfulDiffRatioThreshold !== 'number'
|
|
778
|
-
|| semanticEscalationPolicy.meaningfulDiffRatioThreshold <= 0
|
|
779
|
-
|| semanticEscalationPolicy.meaningfulDiffRatioThreshold >= 0.2
|
|
780
|
-
) {
|
|
781
|
-
validationErrors.push('designIntent.visualQaPolicy.semanticEscalation.meaningfulDiffRatioThreshold must be a number between 0 and 0.2.');
|
|
847
|
+
for (const requiredFlagName of [
|
|
848
|
+
'requireBuildFromHandoff',
|
|
849
|
+
'requireGapNotesBeforeFallback',
|
|
850
|
+
'forbidGenericLayoutFallbackWithoutReason',
|
|
851
|
+
]) {
|
|
852
|
+
if (implementationGuardrails[requiredFlagName] !== true) {
|
|
853
|
+
validationErrors.push(`designIntent.designExecutionHandoff.implementationGuardrails.${requiredFlagName} must equal true.`);
|
|
854
|
+
}
|
|
782
855
|
}
|
|
783
856
|
}
|
|
857
|
+
}
|
|
784
858
|
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
|
|
859
|
+
if (!designIntentContract.reviewRubric || typeof designIntentContract.reviewRubric !== 'object') {
|
|
860
|
+
validationErrors.push('designIntent.reviewRubric must exist.');
|
|
861
|
+
} else {
|
|
862
|
+
if (designIntentContract.reviewRubric.version !== 'ui-rubric-v1') {
|
|
863
|
+
validationErrors.push('designIntent.reviewRubric.version must equal "ui-rubric-v1".');
|
|
864
|
+
}
|
|
865
|
+
if (designIntentContract.reviewRubric.genericityAutoFail !== true) {
|
|
866
|
+
validationErrors.push('designIntent.reviewRubric.genericityAutoFail must equal true.');
|
|
867
|
+
}
|
|
868
|
+
if (!Array.isArray(designIntentContract.reviewRubric.dimensions) || designIntentContract.reviewRubric.dimensions.length < 5) {
|
|
869
|
+
validationErrors.push('designIntent.reviewRubric.dimensions must define the required rubric dimensions.');
|
|
788
870
|
} else {
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
871
|
+
for (const requiredRubricKey of [
|
|
872
|
+
'distinctiveness',
|
|
873
|
+
'contractFidelity',
|
|
874
|
+
'visualConsistency',
|
|
875
|
+
'heuristicUxQuality',
|
|
876
|
+
'motionDiscipline',
|
|
877
|
+
]) {
|
|
878
|
+
if (!designIntentContract.reviewRubric.dimensions.some((dimension) => dimension?.key === requiredRubricKey)) {
|
|
879
|
+
validationErrors.push(`designIntent.reviewRubric.dimensions is missing "${requiredRubricKey}".`);
|
|
880
|
+
}
|
|
794
881
|
}
|
|
795
|
-
|
|
796
|
-
|
|
882
|
+
}
|
|
883
|
+
if (!Array.isArray(designIntentContract.reviewRubric.genericitySignals) || designIntentContract.reviewRubric.genericitySignals.length < 3) {
|
|
884
|
+
validationErrors.push('designIntent.reviewRubric.genericitySignals must list common genericity drift signals.');
|
|
885
|
+
}
|
|
886
|
+
if (!Array.isArray(designIntentContract.reviewRubric.validBoldSignals) || designIntentContract.reviewRubric.validBoldSignals.length < 3) {
|
|
887
|
+
validationErrors.push('designIntent.reviewRubric.validBoldSignals must list legitimate authored signals.');
|
|
888
|
+
}
|
|
889
|
+
if (!designIntentContract.reviewRubric.reportingRules || typeof designIntentContract.reviewRubric.reportingRules !== 'object') {
|
|
890
|
+
validationErrors.push('designIntent.reviewRubric.reportingRules must exist.');
|
|
891
|
+
} else {
|
|
892
|
+
for (const requiredFlagName of [
|
|
893
|
+
'mustExplainGenericity',
|
|
894
|
+
'mustSeparateTasteFromFailure',
|
|
895
|
+
'contractFidelityOverridesPersonalTaste',
|
|
896
|
+
]) {
|
|
897
|
+
if (designIntentContract.reviewRubric.reportingRules[requiredFlagName] !== true) {
|
|
898
|
+
validationErrors.push(`designIntent.reviewRubric.reportingRules.${requiredFlagName} must equal true.`);
|
|
899
|
+
}
|
|
797
900
|
}
|
|
798
901
|
}
|
|
799
902
|
}
|
|
@@ -808,6 +911,10 @@ export function validateDesignIntentContract(designIntentContract) {
|
|
|
808
911
|
}
|
|
809
912
|
}
|
|
810
913
|
|
|
914
|
+
if (!Array.isArray(designIntentContract.forbiddenPatterns) || designIntentContract.forbiddenPatterns.length < 4) {
|
|
915
|
+
validationErrors.push('designIntent.forbiddenPatterns must list concrete anti-generic patterns.');
|
|
916
|
+
}
|
|
917
|
+
|
|
811
918
|
return validationErrors;
|
|
812
919
|
}
|
|
813
920
|
|
|
@@ -817,7 +924,6 @@ export function buildDesignIntentSeedFromSignals({
|
|
|
817
924
|
primaryDomain,
|
|
818
925
|
features = [],
|
|
819
926
|
initContext,
|
|
820
|
-
architectureRecommendation = null,
|
|
821
927
|
status = 'seed-needs-design-synthesis',
|
|
822
928
|
supplementalFields = {},
|
|
823
929
|
}) {
|
|
@@ -827,7 +933,6 @@ export function buildDesignIntentSeedFromSignals({
|
|
|
827
933
|
primaryDomain,
|
|
828
934
|
features,
|
|
829
935
|
initContext,
|
|
830
|
-
architectureRecommendation,
|
|
831
936
|
status,
|
|
832
937
|
supplementalFields,
|
|
833
938
|
});
|
|
@@ -843,7 +948,6 @@ export function buildDesignIntentSeedFromSignals({
|
|
|
843
948
|
export function buildDesignIntentSeed({
|
|
844
949
|
discoveryAnswers,
|
|
845
950
|
initContext,
|
|
846
|
-
architectureRecommendation,
|
|
847
951
|
}) {
|
|
848
952
|
return buildDesignIntentSeedFromSignals({
|
|
849
953
|
projectName: discoveryAnswers.projectName,
|
|
@@ -851,7 +955,6 @@ export function buildDesignIntentSeed({
|
|
|
851
955
|
primaryDomain: discoveryAnswers.primaryDomain,
|
|
852
956
|
features: discoveryAnswers.features,
|
|
853
957
|
initContext,
|
|
854
|
-
architectureRecommendation,
|
|
855
958
|
status: 'seed-needs-design-synthesis',
|
|
856
959
|
});
|
|
857
960
|
}
|