@ryuenn3123/agentic-senior-core 3.0.16 → 3.0.19

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 (39) hide show
  1. package/.agent-context/prompts/bootstrap-design.md +31 -4
  2. package/.agent-context/rules/frontend-architecture.md +26 -0
  3. package/.agent-context/state/memory-continuity-benchmark.json +1 -1
  4. package/.cursorrules +1 -1
  5. package/.gemini/instructions.md +7 -1
  6. package/.github/copilot-instructions.md +7 -1
  7. package/.instructions.md +3 -0
  8. package/.windsurfrules +1 -1
  9. package/AGENTS.md +13 -1
  10. package/lib/cli/commands/init.mjs +2 -2
  11. package/lib/cli/memory-continuity.mjs +2 -1
  12. package/lib/cli/project-scaffolder/constants.mjs +1 -0
  13. package/lib/cli/project-scaffolder/design-contract.mjs +523 -171
  14. package/lib/cli/project-scaffolder/prompt-builders.mjs +38 -15
  15. package/lib/cli/project-scaffolder/storage.mjs +0 -2
  16. package/package.json +2 -2
  17. package/scripts/documentation-boundary-audit.mjs +5 -2
  18. package/scripts/frontend-usability-audit.mjs +34 -0
  19. package/scripts/mcp-server/constants.mjs +60 -0
  20. package/scripts/mcp-server/tool-registry.mjs +149 -0
  21. package/scripts/mcp-server/tools.mjs +446 -0
  22. package/scripts/mcp-server.mjs +23 -661
  23. package/scripts/release-gate/audit-checks.mjs +426 -0
  24. package/scripts/release-gate/constants.mjs +53 -0
  25. package/scripts/release-gate/runtime.mjs +63 -0
  26. package/scripts/release-gate/static-checks.mjs +182 -0
  27. package/scripts/release-gate.mjs +12 -771
  28. package/scripts/sync-thin-adapters.mjs +24 -0
  29. package/scripts/ui-design-judge/constants.mjs +24 -0
  30. package/scripts/ui-design-judge/design-execution-summary.mjs +233 -0
  31. package/scripts/ui-design-judge/git-input.mjs +131 -0
  32. package/scripts/ui-design-judge/prompting.mjs +73 -0
  33. package/scripts/ui-design-judge/providers.mjs +102 -0
  34. package/scripts/ui-design-judge/reporting.mjs +181 -0
  35. package/scripts/ui-design-judge/rubric-calibration.mjs +211 -0
  36. package/scripts/ui-design-judge/rubric-goldset.json +188 -0
  37. package/scripts/ui-design-judge.mjs +130 -441
  38. package/scripts/ui-rubric-calibration.mjs +35 -0
  39. package/scripts/validate/config.mjs +98 -0
@@ -29,174 +29,58 @@ export function shouldBootstrapDesignDocument(discoveryAnswers, initContext) {
29
29
  return false;
30
30
  }
31
31
 
32
- function inferDesignKeywords(discoveryAnswers) {
33
- const normalizedDescription = String(discoveryAnswers.projectDescription || '').toLowerCase();
34
- const normalizedDomain = String(discoveryAnswers.primaryDomain || '').toLowerCase();
35
- const normalizedFeatures = Array.isArray(discoveryAnswers.features)
36
- ? discoveryAnswers.features.map((featureValue) => String(featureValue).toLowerCase()).join(' ')
37
- : '';
38
- const aggregateText = `${normalizedDescription} ${normalizedDomain} ${normalizedFeatures}`;
39
-
40
- if (aggregateText.includes('commerce') || aggregateText.includes('catalog') || aggregateText.includes('checkout')) {
41
- return {
42
- designPhilosophy: 'Conversion clarity with premium restraint.',
43
- brandAdjectives: ['clear', 'desirable', 'confident'],
44
- antiAdjectives: ['cluttered', 'hesitant', 'coupon-noisy'],
45
- typographyScaleRatio: '1.200',
46
- baseGridUnit: 8,
47
- densityMode: 'conversion-focused',
48
- colorIntent: 'Use a restrained neutral foundation with one controlled accent reserved for buying cues and trust moments.',
49
- distinctiveMoves: [
50
- 'Use product hierarchy and buying cues without turning the interface into a discount template.',
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 normalizedDomain = String(primaryDomain || '').trim().toLowerCase();
40
+ const repoEvidenceSummary = supplementalFields?.repoEvidence?.designEvidenceSummary || null;
41
+ const hasRepoEvidence = Boolean(
42
+ repoEvidenceSummary
43
+ || (Array.isArray(supplementalFields?.repoEvidence?.workspaceUiEntries)
44
+ && supplementalFields.repoEvidence.workspaceUiEntries.length > 0)
45
+ );
46
+ const evidenceSourceLabel = hasRepoEvidence
47
+ ? 'current repo evidence, existing UI code, and the active brief'
48
+ : 'the active brief and any repo evidence available at synthesis time';
49
+ const projectContextLabel = normalizedDescription
50
+ ? `the product context "${normalizedDescription}"`
51
+ : 'the current product context';
52
+ const isMobileLikeSurface = normalizedDomain.includes('mobile');
171
53
 
172
54
  return {
173
- designPhilosophy: 'Project-specific clarity with one authored tension and one memorable visual bet.',
174
- brandAdjectives: ['clear', 'human', 'distinct'],
175
- antiAdjectives: ['generic', 'template-like', 'trend-chasing'],
55
+ designPhilosophy: `Use ${evidenceSourceLabel} to synthesize a project-specific design system for ${projectName || 'this project'}. Treat this seed as structural scaffolding that must be refined before UI implementation, not as final art direction.`,
56
+ brandAdjectives: ['project-specific', 'intentional', 'evidence-led'],
57
+ antiAdjectives: ['template-neutral', 'copycat', 'unjustified-defaults'],
176
58
  typographyScaleRatio: '1.200',
177
59
  baseGridUnit: 8,
178
- densityMode: 'balanced-authored',
179
- colorIntent: 'Use a restrained perceptual palette with one deliberate accent budget instead of interchangeable template colors.',
60
+ spacingPattern: isMobileLikeSurface ? 'mobile-first-single-axis' : 'adaptive-task-priority',
61
+ densityMode: isMobileLikeSurface ? 'touch-priority' : 'adaptive-task-priority',
62
+ colorIntent: `Define palette roles from ${projectContextLabel} and refine them with repo evidence. Treat the listed palette roles as minimum semantic categories, not final visual choices.`,
63
+ paletteRoles: ['base', 'surface', 'text', 'muted', 'accent', 'border', 'focus', 'success', 'warning', 'danger'],
180
64
  distinctiveMoves: [
181
- 'Create a visual direction with one memorable tension instead of stacking fashionable effects.',
182
- 'Use rhythm, hierarchy, and motion intentionally so the interface feels authored.',
183
- 'Keep the system flexible enough to evolve with product scope without losing identity.',
65
+ 'Derive one memorable signature move from the product task, current repo evidence, and the active brief before locking the layout language.',
66
+ 'Use task priority, hierarchy, and surface relationships to replace template-neutral hero or card-grid defaults.',
67
+ 'Document why the final visual move belongs to this project and what generic fallback it intentionally avoids.',
184
68
  ],
185
- motionPurpose: 'Allow motion to create continuity, feedback, perceived craft, and memorability. Optimize bold choreography instead of defaulting to restraint. Reject only motion that harms comprehension, accessibility, or runtime performance.',
186
- motionChoreography: 'Use fast purposeful transitions for most interactions, but allow a small number of signature transitions or reveal moments when they strengthen product identity and remain technically cheap.',
69
+ motionPurpose: 'Use motion to clarify causality, hierarchy, state feedback, and perceived product quality. The final motion tone must be refined from repo evidence and the active brief, not inherited from this seed alone.',
70
+ motionChoreography: 'Keep motion purposeful, reduced-motion-safe, and tied to state or surface changes. Any signature choreography must be justified in docs/DESIGN.md before it becomes part of the system.',
187
71
  motionDurations: {
188
72
  desktop: 180,
189
73
  mobile: 240,
190
74
  },
191
75
  componentMorphology: {
192
- mobile: 'Primary components should simplify structure, prioritize direct tasks, and collapse supporting detail into explicit disclosure.',
193
- tablet: 'Components should preserve hierarchy and task continuity while reducing density and compressing tertiary chrome.',
194
- desktop: 'Components can expose richer states, denser supporting information, and broader navigation affordances without losing clarity.',
76
+ mobile: 'Simplify the primary task surface, keep decisive actions in easy reach, and move supporting context behind explicit disclosure when space gets tight.',
77
+ tablet: 'Preserve task continuity while compressing tertiary chrome and keeping priority boundaries obvious across shared surfaces.',
78
+ desktop: 'Expose the richest version of the task flow and supporting context without defaulting to symmetrical template composition.',
195
79
  },
196
80
  mutationRules: {
197
- mobile: 'Stack primary tasks vertically, convert secondary navigation into thumb-friendly overlays or sheets, and simplify dense comparison layouts into progressive disclosure.',
198
- tablet: 'Preserve hierarchy with fewer columns, condensed chrome, and adaptive navigation that maintains task continuity.',
199
- desktop: 'Expose the full layout system, highest information density, and broadest navigation affordances without sacrificing clarity.',
81
+ mobile: 'Recompose the flow around the first decisive action, collapse secondary navigation into explicit overlays or sheets, and re-rank supporting context below the primary task.',
82
+ tablet: 'Preserve task continuity with fewer simultaneous surfaces, condensed chrome, and explicit boundaries between primary, supporting, and deferred content.',
83
+ desktop: 'Expose the fullest version of the task flow, supporting context, and navigation system without falling back to interchangeable dashboard or hero defaults.',
200
84
  },
201
85
  };
202
86
  }
@@ -207,27 +91,26 @@ function buildDesignIntentContractObject({
207
91
  primaryDomain,
208
92
  features = [],
209
93
  initContext,
210
- architectureRecommendation = null,
211
94
  status = 'seed-needs-design-synthesis',
212
95
  supplementalFields = {},
213
96
  }) {
214
- const inferredKeywords = inferDesignKeywords({
97
+ const inferredKeywords = buildStructureFirstSeedSignals({
98
+ projectName,
215
99
  projectDescription,
216
100
  primaryDomain,
217
101
  features,
102
+ supplementalFields,
218
103
  });
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
104
 
228
105
  return {
229
106
  mode: 'dynamic',
230
107
  status,
108
+ seedPolicy: {
109
+ mode: 'structure-first-scaffold',
110
+ requiresProjectSpecificRefinement: true,
111
+ forbidLiteralCarryoverAsFinalArtDirection: true,
112
+ repoEvidenceShouldOverrideSeedTaste: true,
113
+ },
231
114
  project: {
232
115
  name: projectName,
233
116
  context: projectDescription,
@@ -239,6 +122,8 @@ function buildDesignIntentContractObject({
239
122
  brandAdjectives: inferredKeywords.brandAdjectives,
240
123
  antiAdjectives: inferredKeywords.antiAdjectives,
241
124
  visualDirection: {
125
+ seedMode: 'scaffold-only',
126
+ requiresProjectSpecificSynthesis: true,
242
127
  trendStance: 'trend-aware-not-trend-chasing',
243
128
  distinctiveMoves: inferredKeywords.distinctiveMoves,
244
129
  copiedReferenceAllowed: false,
@@ -246,8 +131,9 @@ function buildDesignIntentContractObject({
246
131
  mathSystems: {
247
132
  typographyScaleRatio: inferredKeywords.typographyScaleRatio,
248
133
  baseGridUnit: inferredKeywords.baseGridUnit,
249
- spacingPattern: resolvedSpacingPattern,
134
+ spacingPattern: inferredKeywords.spacingPattern,
250
135
  densityMode: inferredKeywords.densityMode,
136
+ seedValuesRequireCalibration: true,
251
137
  },
252
138
  tokenSystem: {
253
139
  sourceOfTruth: 'docs/design-intent.json',
@@ -280,7 +166,9 @@ function buildDesignIntentContractObject({
280
166
  format: 'OKLCH',
281
167
  allowHexDerivatives: true,
282
168
  requirePerceptualLightnessCurve: true,
283
- paletteRoles: ['base', 'surface', 'accent'],
169
+ paletteRoles: inferredKeywords.paletteRoles,
170
+ rolePolicy: 'minimum-semantic-scaffold',
171
+ rolesAreMinimumScaffold: true,
284
172
  intent: inferredKeywords.colorIntent,
285
173
  },
286
174
  crossViewportAdaptation: {
@@ -294,6 +182,7 @@ function buildDesignIntentContractObject({
294
182
  choreography: inferredKeywords.motionChoreography,
295
183
  desktopDurationMs: inferredKeywords.motionDurations.desktop,
296
184
  mobileDurationMs: inferredKeywords.motionDurations.mobile,
185
+ seedToneLocked: false,
297
186
  respectReducedMotion: true,
298
187
  preferTransformAndOpacity: true,
299
188
  avoidDecorativeMotionForItsOwnSake: true,
@@ -301,9 +190,230 @@ function buildDesignIntentContractObject({
301
190
  componentMorphology: {
302
191
  requireStateBehaviorMatrix: true,
303
192
  preserveIdentityAcrossViewports: true,
193
+ seedBehaviorsRequireRefinement: true,
304
194
  stateKeys: ['default', 'hover', 'focus', 'active', 'disabled', 'loading', 'error'],
305
195
  viewportBehavior: inferredKeywords.componentMorphology,
306
196
  },
197
+ accessibilityPolicy: {
198
+ hardComplianceFloor: 'WCAG-2.2-AA',
199
+ advisoryContrastModel: 'APCA',
200
+ failOnHardViolations: true,
201
+ advisoryFindingsDoNotBlockByDefault: true,
202
+ hardRequirements: {
203
+ textContrastMinimum: true,
204
+ nonTextContrast: true,
205
+ useOfColorOnlyProhibited: true,
206
+ focusVisible: true,
207
+ focusAppearance: true,
208
+ targetSizeMinimum: true,
209
+ keyboardAccess: true,
210
+ reflowRequired: true,
211
+ accessibleAuthenticationMinimum: true,
212
+ statusMessagesAndDynamicStateAccess: true,
213
+ },
214
+ advisoryChecks: {
215
+ perceptualContrastReview: true,
216
+ darkModeContrastTuning: true,
217
+ typographyReadabilityTuning: true,
218
+ },
219
+ },
220
+ designExecutionPolicy: {
221
+ representationStrategy: 'surface-plan-v1',
222
+ seedRefinementRequiredBeforeUiImplementation: true,
223
+ requireSurfacePlan: true,
224
+ requireComponentGraph: true,
225
+ requireViewportMutationPlan: true,
226
+ requireInteractionStateMatrix: true,
227
+ requireContentPriorityMap: true,
228
+ requireTaskFlowNarrative: true,
229
+ requireSignatureMoveRationale: true,
230
+ requireStructuredHandoff: true,
231
+ requireRepoEvidenceAlignment: true,
232
+ forbidScreenshotDependency: true,
233
+ handoffFormatVersion: 'ui-handoff-v1',
234
+ semanticReviewFocus: [
235
+ 'distinctiveness-vs-genericity',
236
+ 'contract-fidelity',
237
+ 'hierarchy-and-task-priority',
238
+ 'component-state-behavior',
239
+ 'cross-viewport-mutation',
240
+ ],
241
+ },
242
+ designExecutionHandoff: {
243
+ version: 'ui-handoff-v1',
244
+ location: 'inline-design-intent',
245
+ status: 'seed-needs-refinement',
246
+ seedMode: 'structure-first-scaffold',
247
+ requiresTaskSpecificRefinement: true,
248
+ primaryExperienceGoal: `Refine the main ${String(primaryDomain || 'product').toLowerCase()} journey in ${projectName} so the first decisive action, supporting context, and signature move come from repo evidence and the active brief rather than scaffold defaults.`,
249
+ surfacePlan: [
250
+ {
251
+ surfaceId: 'primary-entry-surface',
252
+ role: 'primary-task-entry',
253
+ goal: `Map the first meaningful task in ${projectName} and replace generic hero filler with task-first hierarchy justified by repo evidence and the active brief.`,
254
+ primaryAction: 'Define the first decisive action or decision point explicitly during refinement instead of inheriting placeholder CTA language.',
255
+ supportingModules: ['context', 'proof', 'navigation'],
256
+ signatureMoveHint: 'Document one project-specific signature move for the primary surface and explain which generic fallback it intentionally rejects.',
257
+ },
258
+ {
259
+ surfaceId: 'supporting-proof-surface',
260
+ role: 'trust-and-context',
261
+ goal: 'Define how proof, explanation, or operational context supports the main task without turning the layout into a template-neutral secondary rail.',
262
+ primaryAction: 'Clarify what supporting proof or status belongs near the main task once the product-specific flow is confirmed.',
263
+ supportingModules: ['status', 'metadata', 'secondary-actions'],
264
+ signatureMoveHint: 'Explain how this supporting surface reinforces the primary task without competing for dominance or collapsing into generic chrome.',
265
+ },
266
+ ],
267
+ componentGraph: {
268
+ nodes: [
269
+ {
270
+ id: 'primary-action-surface',
271
+ role: 'task-driver',
272
+ priority: 'high',
273
+ },
274
+ {
275
+ id: 'supporting-context-rail',
276
+ role: 'context-support',
277
+ priority: 'medium',
278
+ },
279
+ {
280
+ id: 'feedback-status-module',
281
+ role: 'feedback-and-proof',
282
+ priority: 'medium',
283
+ },
284
+ ],
285
+ edges: [
286
+ {
287
+ from: 'primary-action-surface',
288
+ to: 'supporting-context-rail',
289
+ relationship: 'context-support',
290
+ },
291
+ {
292
+ from: 'primary-action-surface',
293
+ to: 'feedback-status-module',
294
+ relationship: 'state-feedback',
295
+ },
296
+ ],
297
+ },
298
+ contentPriorityMap: {
299
+ primary: [
300
+ 'core-task-entry',
301
+ 'primary-status-or-value-message',
302
+ 'decisive-action-labeling',
303
+ ],
304
+ secondary: [
305
+ 'supporting-proof',
306
+ 'navigation-context',
307
+ 'secondary-actions',
308
+ ],
309
+ deferred: [
310
+ 'deep-explanation',
311
+ 'tertiary-metadata',
312
+ 'low-priority-decoration',
313
+ ],
314
+ },
315
+ viewportMutationPlan: {
316
+ mobile: inferredKeywords.mutationRules.mobile,
317
+ tablet: inferredKeywords.mutationRules.tablet,
318
+ desktop: inferredKeywords.mutationRules.desktop,
319
+ },
320
+ interactionStateMatrix: [
321
+ {
322
+ componentId: 'primary-action-control',
323
+ states: ['default', 'hover', 'focus', 'loading', 'success', 'error'],
324
+ notes: 'Refine these states with project-specific feedback language and visual treatment, but keep them legible, decisive, and consistent across all supported viewports.',
325
+ },
326
+ {
327
+ componentId: 'primary-content-module',
328
+ states: ['default', 'focus', 'expanded', 'loading', 'error'],
329
+ notes: 'Refine this module so it preserves hierarchy and progressive disclosure without collapsing into anonymous cards or safe default dashboard panels.',
330
+ },
331
+ ],
332
+ taskFlowNarrative: [
333
+ `Entry: refine how ${projectName} establishes the first meaningful action using current task evidence instead of generic product-marketing framing.`,
334
+ 'Decision: define the hierarchy, proof, and state language that help the user choose the next step without defaulting to generic card-grid or hero habits.',
335
+ 'Resolution: specify the feedback, recovery path, and next useful action so progress remains visible without hiding behind decorative confirmation states.',
336
+ ],
337
+ signatureMoveRationale: 'Explain which project-specific surface, motion, typographic, or compositional move anchors the system and why a generic fallback would weaken the product.',
338
+ implementationGuardrails: {
339
+ requireBuildFromHandoff: true,
340
+ requireGapNotesBeforeFallback: true,
341
+ forbidGenericLayoutFallbackWithoutReason: true,
342
+ },
343
+ },
344
+ reviewRubric: {
345
+ version: 'ui-rubric-v1',
346
+ dimensions: [
347
+ {
348
+ key: 'distinctiveness',
349
+ blockingByDefault: false,
350
+ question: 'Does the UI feel authored and project-specific rather than like a default framework or template kit?',
351
+ },
352
+ {
353
+ key: 'contractFidelity',
354
+ blockingByDefault: true,
355
+ question: 'Does the changed UI still follow the explicit design contract, interaction priorities, and accessibility boundaries?',
356
+ },
357
+ {
358
+ key: 'visualConsistency',
359
+ blockingByDefault: false,
360
+ question: 'Do typography, spacing, color usage, and component behaviors still feel like one system?',
361
+ },
362
+ {
363
+ key: 'heuristicUxQuality',
364
+ blockingByDefault: false,
365
+ question: 'Does the UI preserve task clarity, feedback quality, and user confidence in the touched flows?',
366
+ },
367
+ {
368
+ key: 'motionDiscipline',
369
+ blockingByDefault: false,
370
+ question: 'If motion is present, does it stay purposeful, performant, reduced-motion-safe, and consistent with the product tone?',
371
+ },
372
+ ],
373
+ genericitySignals: [
374
+ 'safe-centered-hero-without-product-rationale',
375
+ 'balanced-card-grid-without-priority-shift',
376
+ 'default-framework-button-and-input-treatment',
377
+ 'trend-gradient-without-structural-role',
378
+ 'interchangeable-dashboard-chrome',
379
+ ],
380
+ validBoldSignals: [
381
+ 'one-clear-signature-move',
382
+ 'project-specific-layout-tension',
383
+ 'purposeful-motion-as-identity',
384
+ 'distinct-typographic-hierarchy',
385
+ 'non-template-task-priority',
386
+ ],
387
+ reportingRules: {
388
+ mustExplainGenericity: true,
389
+ mustSeparateTasteFromFailure: true,
390
+ contractFidelityOverridesPersonalTaste: true,
391
+ },
392
+ },
393
+ contextHygiene: {
394
+ continuityMode: 'opt-in-only',
395
+ allowedSources: [
396
+ 'current-repo-evidence',
397
+ 'current-user-brief',
398
+ 'current-project-docs',
399
+ 'explicitly-approved-reference-systems',
400
+ ],
401
+ taintedSources: [
402
+ 'prior-chat-visual-memory',
403
+ 'unrelated-project-aesthetics',
404
+ 'remembered-screenshots-without-current-approval',
405
+ 'generic-template-recall',
406
+ ],
407
+ repoEvidenceOverridesMemory: true,
408
+ requireExplicitContinuityApproval: true,
409
+ forbidCarryoverWhenUnapproved: true,
410
+ approvedReferenceUsage: 'Adapt reasoning and constraints from approved references without copying the surface 1:1.',
411
+ driftSignals: [
412
+ 'palette-reused-without-brief-support',
413
+ 'motion-signature-reused-without-approval',
414
+ 'layout-shape-matches-unrelated-project-memory',
415
+ ],
416
+ },
307
417
  experiencePrinciples: [
308
418
  'Design must feel project-specific, not interchangeable with generic SaaS templates.',
309
419
  'Major interface decisions must be explainable in product and user terms.',
@@ -328,6 +438,12 @@ function buildDesignIntentContractObject({
328
438
  allowHexDerivatives: true,
329
439
  requireMotionRationale: true,
330
440
  requireStateMorphology: true,
441
+ requireAccessibilitySplit: true,
442
+ requireWcagHardFloor: true,
443
+ requireStructuredDesignExecutionPolicy: true,
444
+ requireStructuredDesignHandoff: true,
445
+ requireReviewRubric: true,
446
+ requireGenericityExplanation: true,
331
447
  requireSignatureMove: true,
332
448
  rejectTemplateNeutralLayout: true,
333
449
  },
@@ -443,6 +559,19 @@ export function validateDesignIntentContract(designIntentContract) {
443
559
  if (designIntentContract.colorTruth.allowHexDerivatives !== true) {
444
560
  validationErrors.push('designIntent.colorTruth.allowHexDerivatives must equal true.');
445
561
  }
562
+ if (!String(designIntentContract.colorTruth.intent || '').trim()) {
563
+ validationErrors.push('designIntent.colorTruth.intent must be a non-empty string.');
564
+ }
565
+ const paletteRoles = designIntentContract.colorTruth.paletteRoles;
566
+ if (!Array.isArray(paletteRoles) || paletteRoles.length < 4) {
567
+ validationErrors.push('designIntent.colorTruth.paletteRoles must define the minimum semantic palette roles.');
568
+ } else {
569
+ for (const requiredPaletteRole of ['base', 'surface', 'text', 'accent']) {
570
+ if (!paletteRoles.includes(requiredPaletteRole)) {
571
+ validationErrors.push(`designIntent.colorTruth.paletteRoles is missing "${requiredPaletteRole}".`);
572
+ }
573
+ }
574
+ }
446
575
  }
447
576
 
448
577
  if (!designIntentContract.crossViewportAdaptation || typeof designIntentContract.crossViewportAdaptation !== 'object') {
@@ -495,6 +624,233 @@ export function validateDesignIntentContract(designIntentContract) {
495
624
  }
496
625
  }
497
626
 
627
+ if (!designIntentContract.accessibilityPolicy || typeof designIntentContract.accessibilityPolicy !== 'object') {
628
+ validationErrors.push('designIntent.accessibilityPolicy must exist.');
629
+ } else {
630
+ if (designIntentContract.accessibilityPolicy.hardComplianceFloor !== 'WCAG-2.2-AA') {
631
+ validationErrors.push('designIntent.accessibilityPolicy.hardComplianceFloor must equal "WCAG-2.2-AA".');
632
+ }
633
+ if (designIntentContract.accessibilityPolicy.advisoryContrastModel !== 'APCA') {
634
+ validationErrors.push('designIntent.accessibilityPolicy.advisoryContrastModel must equal "APCA".');
635
+ }
636
+ if (designIntentContract.accessibilityPolicy.failOnHardViolations !== true) {
637
+ validationErrors.push('designIntent.accessibilityPolicy.failOnHardViolations must equal true.');
638
+ }
639
+ if (designIntentContract.accessibilityPolicy.advisoryFindingsDoNotBlockByDefault !== true) {
640
+ validationErrors.push('designIntent.accessibilityPolicy.advisoryFindingsDoNotBlockByDefault must equal true.');
641
+ }
642
+ const hardRequirements = designIntentContract.accessibilityPolicy.hardRequirements;
643
+ if (!hardRequirements || typeof hardRequirements !== 'object') {
644
+ validationErrors.push('designIntent.accessibilityPolicy.hardRequirements must exist.');
645
+ } else {
646
+ for (const requirementKey of [
647
+ 'textContrastMinimum',
648
+ 'nonTextContrast',
649
+ 'useOfColorOnlyProhibited',
650
+ 'focusVisible',
651
+ 'focusAppearance',
652
+ 'targetSizeMinimum',
653
+ 'keyboardAccess',
654
+ 'reflowRequired',
655
+ 'accessibleAuthenticationMinimum',
656
+ 'statusMessagesAndDynamicStateAccess',
657
+ ]) {
658
+ if (hardRequirements[requirementKey] !== true) {
659
+ validationErrors.push(`designIntent.accessibilityPolicy.hardRequirements.${requirementKey} must equal true.`);
660
+ }
661
+ }
662
+ }
663
+ const advisoryChecks = designIntentContract.accessibilityPolicy.advisoryChecks;
664
+ if (!advisoryChecks || typeof advisoryChecks !== 'object') {
665
+ validationErrors.push('designIntent.accessibilityPolicy.advisoryChecks must exist.');
666
+ } else {
667
+ for (const advisoryKey of [
668
+ 'perceptualContrastReview',
669
+ 'darkModeContrastTuning',
670
+ 'typographyReadabilityTuning',
671
+ ]) {
672
+ if (advisoryChecks[advisoryKey] !== true) {
673
+ validationErrors.push(`designIntent.accessibilityPolicy.advisoryChecks.${advisoryKey} must equal true.`);
674
+ }
675
+ }
676
+ }
677
+ }
678
+
679
+ if (!designIntentContract.contextHygiene || typeof designIntentContract.contextHygiene !== 'object') {
680
+ validationErrors.push('designIntent.contextHygiene must exist.');
681
+ } else {
682
+ if (designIntentContract.contextHygiene.continuityMode !== 'opt-in-only') {
683
+ validationErrors.push('designIntent.contextHygiene.continuityMode must equal "opt-in-only".');
684
+ }
685
+ if (designIntentContract.contextHygiene.repoEvidenceOverridesMemory !== true) {
686
+ validationErrors.push('designIntent.contextHygiene.repoEvidenceOverridesMemory must equal true.');
687
+ }
688
+ if (designIntentContract.contextHygiene.requireExplicitContinuityApproval !== true) {
689
+ validationErrors.push('designIntent.contextHygiene.requireExplicitContinuityApproval must equal true.');
690
+ }
691
+ if (designIntentContract.contextHygiene.forbidCarryoverWhenUnapproved !== true) {
692
+ validationErrors.push('designIntent.contextHygiene.forbidCarryoverWhenUnapproved must equal true.');
693
+ }
694
+ if (!Array.isArray(designIntentContract.contextHygiene.allowedSources) || designIntentContract.contextHygiene.allowedSources.length < 4) {
695
+ validationErrors.push('designIntent.contextHygiene.allowedSources must list the approved design evidence sources.');
696
+ }
697
+ if (!Array.isArray(designIntentContract.contextHygiene.taintedSources) || designIntentContract.contextHygiene.taintedSources.length < 3) {
698
+ validationErrors.push('designIntent.contextHygiene.taintedSources must list tainted carryover sources.');
699
+ }
700
+ if (!String(designIntentContract.contextHygiene.approvedReferenceUsage || '').trim()) {
701
+ validationErrors.push('designIntent.contextHygiene.approvedReferenceUsage must be a non-empty string.');
702
+ }
703
+ }
704
+
705
+ if (!designIntentContract.designExecutionPolicy || typeof designIntentContract.designExecutionPolicy !== 'object') {
706
+ validationErrors.push('designIntent.designExecutionPolicy must exist.');
707
+ } else {
708
+ if (designIntentContract.designExecutionPolicy.representationStrategy !== 'surface-plan-v1') {
709
+ validationErrors.push('designIntent.designExecutionPolicy.representationStrategy must equal "surface-plan-v1".');
710
+ }
711
+ for (const requiredFlagName of [
712
+ 'requireSurfacePlan',
713
+ 'requireComponentGraph',
714
+ 'requireViewportMutationPlan',
715
+ 'requireInteractionStateMatrix',
716
+ 'requireContentPriorityMap',
717
+ 'requireTaskFlowNarrative',
718
+ 'requireSignatureMoveRationale',
719
+ 'requireStructuredHandoff',
720
+ 'requireRepoEvidenceAlignment',
721
+ 'forbidScreenshotDependency',
722
+ ]) {
723
+ if (designIntentContract.designExecutionPolicy[requiredFlagName] !== true) {
724
+ validationErrors.push(`designIntent.designExecutionPolicy.${requiredFlagName} must equal true.`);
725
+ }
726
+ }
727
+ if (designIntentContract.designExecutionPolicy.handoffFormatVersion !== 'ui-handoff-v1') {
728
+ validationErrors.push('designIntent.designExecutionPolicy.handoffFormatVersion must equal "ui-handoff-v1".');
729
+ }
730
+ if (
731
+ !Array.isArray(designIntentContract.designExecutionPolicy.semanticReviewFocus)
732
+ || designIntentContract.designExecutionPolicy.semanticReviewFocus.length < 4
733
+ ) {
734
+ validationErrors.push('designIntent.designExecutionPolicy.semanticReviewFocus must list the required review dimensions.');
735
+ }
736
+ }
737
+
738
+ if (!designIntentContract.designExecutionHandoff || typeof designIntentContract.designExecutionHandoff !== 'object') {
739
+ validationErrors.push('designIntent.designExecutionHandoff must exist.');
740
+ } else {
741
+ if (designIntentContract.designExecutionHandoff.version !== 'ui-handoff-v1') {
742
+ validationErrors.push('designIntent.designExecutionHandoff.version must equal "ui-handoff-v1".');
743
+ }
744
+ if (designIntentContract.designExecutionHandoff.seedMode !== 'structure-first-scaffold') {
745
+ validationErrors.push('designIntent.designExecutionHandoff.seedMode must equal "structure-first-scaffold".');
746
+ }
747
+ if (designIntentContract.designExecutionHandoff.requiresTaskSpecificRefinement !== true) {
748
+ validationErrors.push('designIntent.designExecutionHandoff.requiresTaskSpecificRefinement must equal true.');
749
+ }
750
+ if (!String(designIntentContract.designExecutionHandoff.primaryExperienceGoal || '').trim()) {
751
+ validationErrors.push('designIntent.designExecutionHandoff.primaryExperienceGoal must be a non-empty string.');
752
+ }
753
+ if (!Array.isArray(designIntentContract.designExecutionHandoff.surfacePlan) || designIntentContract.designExecutionHandoff.surfacePlan.length < 1) {
754
+ validationErrors.push('designIntent.designExecutionHandoff.surfacePlan must define at least one planned surface.');
755
+ }
756
+ const componentGraph = designIntentContract.designExecutionHandoff.componentGraph;
757
+ if (!componentGraph || typeof componentGraph !== 'object') {
758
+ validationErrors.push('designIntent.designExecutionHandoff.componentGraph must exist.');
759
+ } else {
760
+ if (!Array.isArray(componentGraph.nodes) || componentGraph.nodes.length < 2) {
761
+ validationErrors.push('designIntent.designExecutionHandoff.componentGraph.nodes must list the primary execution nodes.');
762
+ }
763
+ if (!Array.isArray(componentGraph.edges) || componentGraph.edges.length < 1) {
764
+ validationErrors.push('designIntent.designExecutionHandoff.componentGraph.edges must define relationships between UI nodes.');
765
+ }
766
+ }
767
+ const contentPriorityMap = designIntentContract.designExecutionHandoff.contentPriorityMap;
768
+ if (!contentPriorityMap || typeof contentPriorityMap !== 'object') {
769
+ validationErrors.push('designIntent.designExecutionHandoff.contentPriorityMap must exist.');
770
+ } else {
771
+ for (const priorityBucket of ['primary', 'secondary', 'deferred']) {
772
+ if (!Array.isArray(contentPriorityMap[priorityBucket]) || contentPriorityMap[priorityBucket].length < 1) {
773
+ validationErrors.push(`designIntent.designExecutionHandoff.contentPriorityMap.${priorityBucket} must contain at least one item.`);
774
+ }
775
+ }
776
+ }
777
+ const viewportMutationPlan = designIntentContract.designExecutionHandoff.viewportMutationPlan;
778
+ if (!viewportMutationPlan || typeof viewportMutationPlan !== 'object') {
779
+ validationErrors.push('designIntent.designExecutionHandoff.viewportMutationPlan must exist.');
780
+ } else {
781
+ for (const viewportKey of ['mobile', 'tablet', 'desktop']) {
782
+ if (!String(viewportMutationPlan[viewportKey] || '').trim()) {
783
+ validationErrors.push(`designIntent.designExecutionHandoff.viewportMutationPlan.${viewportKey} must be a non-empty string.`);
784
+ }
785
+ }
786
+ }
787
+ if (!Array.isArray(designIntentContract.designExecutionHandoff.interactionStateMatrix) || designIntentContract.designExecutionHandoff.interactionStateMatrix.length < 1) {
788
+ validationErrors.push('designIntent.designExecutionHandoff.interactionStateMatrix must list key component state expectations.');
789
+ }
790
+ if (!Array.isArray(designIntentContract.designExecutionHandoff.taskFlowNarrative) || designIntentContract.designExecutionHandoff.taskFlowNarrative.length < 2) {
791
+ validationErrors.push('designIntent.designExecutionHandoff.taskFlowNarrative must describe the key UI task flow in sequence.');
792
+ }
793
+ if (!String(designIntentContract.designExecutionHandoff.signatureMoveRationale || '').trim()) {
794
+ validationErrors.push('designIntent.designExecutionHandoff.signatureMoveRationale must explain the chosen authored move.');
795
+ }
796
+ const implementationGuardrails = designIntentContract.designExecutionHandoff.implementationGuardrails;
797
+ if (!implementationGuardrails || typeof implementationGuardrails !== 'object') {
798
+ validationErrors.push('designIntent.designExecutionHandoff.implementationGuardrails must exist.');
799
+ } else {
800
+ for (const requiredFlagName of [
801
+ 'requireBuildFromHandoff',
802
+ 'requireGapNotesBeforeFallback',
803
+ 'forbidGenericLayoutFallbackWithoutReason',
804
+ ]) {
805
+ if (implementationGuardrails[requiredFlagName] !== true) {
806
+ validationErrors.push(`designIntent.designExecutionHandoff.implementationGuardrails.${requiredFlagName} must equal true.`);
807
+ }
808
+ }
809
+ }
810
+ }
811
+
812
+ if (!designIntentContract.reviewRubric || typeof designIntentContract.reviewRubric !== 'object') {
813
+ validationErrors.push('designIntent.reviewRubric must exist.');
814
+ } else {
815
+ if (designIntentContract.reviewRubric.version !== 'ui-rubric-v1') {
816
+ validationErrors.push('designIntent.reviewRubric.version must equal "ui-rubric-v1".');
817
+ }
818
+ if (!Array.isArray(designIntentContract.reviewRubric.dimensions) || designIntentContract.reviewRubric.dimensions.length < 5) {
819
+ validationErrors.push('designIntent.reviewRubric.dimensions must define the required rubric dimensions.');
820
+ } else {
821
+ for (const requiredRubricKey of [
822
+ 'distinctiveness',
823
+ 'contractFidelity',
824
+ 'visualConsistency',
825
+ 'heuristicUxQuality',
826
+ 'motionDiscipline',
827
+ ]) {
828
+ if (!designIntentContract.reviewRubric.dimensions.some((dimension) => dimension?.key === requiredRubricKey)) {
829
+ validationErrors.push(`designIntent.reviewRubric.dimensions is missing "${requiredRubricKey}".`);
830
+ }
831
+ }
832
+ }
833
+ if (!Array.isArray(designIntentContract.reviewRubric.genericitySignals) || designIntentContract.reviewRubric.genericitySignals.length < 3) {
834
+ validationErrors.push('designIntent.reviewRubric.genericitySignals must list common genericity drift signals.');
835
+ }
836
+ if (!Array.isArray(designIntentContract.reviewRubric.validBoldSignals) || designIntentContract.reviewRubric.validBoldSignals.length < 3) {
837
+ validationErrors.push('designIntent.reviewRubric.validBoldSignals must list legitimate authored signals.');
838
+ }
839
+ if (!designIntentContract.reviewRubric.reportingRules || typeof designIntentContract.reviewRubric.reportingRules !== 'object') {
840
+ validationErrors.push('designIntent.reviewRubric.reportingRules must exist.');
841
+ } else {
842
+ for (const requiredFlagName of [
843
+ 'mustExplainGenericity',
844
+ 'mustSeparateTasteFromFailure',
845
+ 'contractFidelityOverridesPersonalTaste',
846
+ ]) {
847
+ if (designIntentContract.reviewRubric.reportingRules[requiredFlagName] !== true) {
848
+ validationErrors.push(`designIntent.reviewRubric.reportingRules.${requiredFlagName} must equal true.`);
849
+ }
850
+ }
851
+ }
852
+ }
853
+
498
854
  if (!Array.isArray(designIntentContract.requiredDesignSections) || designIntentContract.requiredDesignSections.length !== DESIGN_REQUIRED_SECTIONS.length) {
499
855
  validationErrors.push('designIntent.requiredDesignSections must match the required design contract sections.');
500
856
  } else {
@@ -514,7 +870,6 @@ export function buildDesignIntentSeedFromSignals({
514
870
  primaryDomain,
515
871
  features = [],
516
872
  initContext,
517
- architectureRecommendation = null,
518
873
  status = 'seed-needs-design-synthesis',
519
874
  supplementalFields = {},
520
875
  }) {
@@ -524,7 +879,6 @@ export function buildDesignIntentSeedFromSignals({
524
879
  primaryDomain,
525
880
  features,
526
881
  initContext,
527
- architectureRecommendation,
528
882
  status,
529
883
  supplementalFields,
530
884
  });
@@ -540,7 +894,6 @@ export function buildDesignIntentSeedFromSignals({
540
894
  export function buildDesignIntentSeed({
541
895
  discoveryAnswers,
542
896
  initContext,
543
- architectureRecommendation,
544
897
  }) {
545
898
  return buildDesignIntentSeedFromSignals({
546
899
  projectName: discoveryAnswers.projectName,
@@ -548,7 +901,6 @@ export function buildDesignIntentSeed({
548
901
  primaryDomain: discoveryAnswers.primaryDomain,
549
902
  features: discoveryAnswers.features,
550
903
  initContext,
551
- architectureRecommendation,
552
904
  status: 'seed-needs-design-synthesis',
553
905
  });
554
906
  }