yam-flow 0.1.4 → 0.1.6

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.
@@ -56,6 +56,11 @@ export interface UeyeVisualProvenance {
56
56
  source_hash: string;
57
57
  reference_id: string;
58
58
  screenshot_id: string;
59
+ provider_context: string;
60
+ provider_badge: string;
61
+ execution_surface: string;
62
+ app_surface: string;
63
+ browser_surface: string;
59
64
  local_only: boolean;
60
65
  redacted: boolean;
61
66
  operator_provided: boolean;
@@ -63,6 +68,50 @@ export interface UeyeVisualProvenance {
63
68
  truth_status: TruthStatus;
64
69
  }
65
70
 
71
+ export interface UeyeSurfaceContext {
72
+ schema: 'yam.ueye-surface-context.v1';
73
+ provider_context: string;
74
+ provider_badge: string;
75
+ execution_surface: string;
76
+ app_surface: string;
77
+ browser_surface: string;
78
+ control_mode: string;
79
+ route: string;
80
+ mode: string;
81
+ url: string;
82
+ viewport: string;
83
+ screenshot_id: string;
84
+ evidence_id: string;
85
+ preserved_state: boolean;
86
+ preserved_url: string;
87
+ local_only: boolean;
88
+ truth_status: TruthStatus;
89
+ }
90
+
91
+ export interface UeyeDesignGateCheck {
92
+ id: string;
93
+ label: string;
94
+ status: 'pass' | 'fail' | 'warning' | 'not_checked';
95
+ required: boolean;
96
+ next_action: string;
97
+ }
98
+
99
+ export interface UeyeDesignCompletionGate {
100
+ schema: 'yam.ueye-design-completion-gate.v1';
101
+ mode: 'fast' | 'strict';
102
+ completion_claim: 'draft' | 'needs-polish' | 'done';
103
+ ready_to_claim_done: boolean;
104
+ design_score: number | null;
105
+ min_design_score: number;
106
+ checks: UeyeDesignGateCheck[];
107
+ p0: string[];
108
+ p1: string[];
109
+ warnings: string[];
110
+ blockers: string[];
111
+ next_action: string;
112
+ truth_status: TruthStatus;
113
+ }
114
+
66
115
  export interface RollbackHint {
67
116
  schema: 'yam.rollback-hint.v1';
68
117
  touched_files: string[];
@@ -96,6 +145,8 @@ export interface UeyeRunReport {
96
145
  schema: 'yam.ueye-run-report.v1';
97
146
  reference_sources: UeyeVisualProvenance[];
98
147
  implementation_sources: UeyeVisualProvenance[];
148
+ surface_context: UeyeSurfaceContext;
149
+ design_completion_gate: UeyeDesignCompletionGate;
99
150
  comparison_result: string;
100
151
  design_quality: string;
101
152
  blocked_reason: string;
@@ -103,6 +154,10 @@ export interface UeyeRunReport {
103
154
  truth_status: TruthStatus;
104
155
  }
105
156
 
157
+ export interface UeyeRunReportInput extends Partial<Omit<UeyeRunReport, 'design_completion_gate'>> {
158
+ design_completion_gate?: Partial<UeyeDesignCompletionGate> & Record<string, unknown>;
159
+ }
160
+
106
161
  export interface MediaGenerationProof {
107
162
  schema: 'yam.media-generation-proof.v1';
108
163
  tool_name: string;
@@ -145,6 +200,7 @@ export interface ProofSummary {
145
200
  rollbackHint?: unknown;
146
201
  runtimeBackendEvidence?: unknown;
147
202
  mediaProof?: unknown;
203
+ designCompletion?: unknown;
148
204
  }
149
205
 
150
206
  export interface ProofOptions {
@@ -180,6 +236,7 @@ export interface YamCompletionProof {
180
236
  rollbackHint: string[];
181
237
  runtimeBackendEvidence: string[];
182
238
  mediaProof: string[];
239
+ designCompletion: string[];
183
240
  cleanup: unknown;
184
241
  changed: string[];
185
242
  skipped: string[];
@@ -201,6 +258,11 @@ export function buildUeyeVisualProvenance(input: Partial<UeyeVisualProvenance> =
201
258
  source_hash: String(input.source_hash || 'unknown'),
202
259
  reference_id: String(input.reference_id || ''),
203
260
  screenshot_id: String(input.screenshot_id || ''),
261
+ provider_context: String(input.provider_context || 'not-recorded'),
262
+ provider_badge: String(input.provider_badge || 'not-recorded'),
263
+ execution_surface: String(input.execution_surface || 'not-recorded'),
264
+ app_surface: String(input.app_surface || 'not-recorded'),
265
+ browser_surface: String(input.browser_surface || 'not-recorded'),
204
266
  local_only: Boolean(input.local_only),
205
267
  redacted: Boolean(input.redacted),
206
268
  operator_provided: Boolean(input.operator_provided),
@@ -209,6 +271,116 @@ export function buildUeyeVisualProvenance(input: Partial<UeyeVisualProvenance> =
209
271
  };
210
272
  }
211
273
 
274
+ export function buildUeyeSurfaceContext(input: Partial<UeyeSurfaceContext> = {}): UeyeSurfaceContext {
275
+ return {
276
+ schema: 'yam.ueye-surface-context.v1',
277
+ provider_context: String(input.provider_context || 'not-recorded'),
278
+ provider_badge: String(input.provider_badge || input.provider_context || 'not-recorded'),
279
+ execution_surface: String(input.execution_surface || 'not-recorded'),
280
+ app_surface: String(input.app_surface || 'not-recorded'),
281
+ browser_surface: String(input.browser_surface || 'not-recorded'),
282
+ control_mode: String(input.control_mode || 'not-recorded'),
283
+ route: String(input.route || 'ueye'),
284
+ mode: String(input.mode || 'report'),
285
+ url: String(input.url || ''),
286
+ viewport: String(input.viewport || ''),
287
+ screenshot_id: String(input.screenshot_id || ''),
288
+ evidence_id: String(input.evidence_id || ''),
289
+ preserved_state: Boolean(input.preserved_state),
290
+ preserved_url: String(input.preserved_url || ''),
291
+ local_only: input.local_only !== undefined ? Boolean(input.local_only) : true,
292
+ truth_status: isTruthStatus(input.truth_status) ? input.truth_status : 'partial'
293
+ };
294
+ }
295
+
296
+ export function buildUeyeDesignCompletionGate(input: Partial<UeyeDesignCompletionGate> & Record<string, unknown> = {}): UeyeDesignCompletionGate {
297
+ const completionClaim = normalizeUeyeCompletionClaim(input.completion_claim);
298
+ const mode = String(input.mode || '').toLowerCase() === 'strict' || completionClaim === 'done' ? 'strict' : 'fast';
299
+ const designScore = numberOrNull(input.design_score);
300
+ const minDesignScore = numberOrNull(input.min_design_score) ?? 8;
301
+ const p0 = asList(input.p0);
302
+ const p1 = asList(input.p1);
303
+ const hasReference = Boolean(input.has_reference);
304
+ const hasImplementation = Boolean(input.has_implementation_screenshot);
305
+ const comparisonResult = String(input.comparison_result || 'not-verified');
306
+ const designQuality = String(input.design_quality || 'not-checked');
307
+ const blockedReason = String(input.blocked_reason || '');
308
+ const strictOrDone = mode === 'strict' || completionClaim === 'done';
309
+ const checks: UeyeDesignGateCheck[] = [
310
+ designGateCheck('direction_lock', 'Design direction and target screen were locked before judging completion', Boolean(input.direction_locked) ? 'pass' : 'not_checked', strictOrDone, 'record the target screen and design direction before claiming done'),
311
+ designGateCheck('reference_read', 'Reference read proof exists when reference is used', !hasReference ? 'not_checked' : Boolean(input.reference_read) ? 'pass' : 'fail', hasReference && strictOrDone, 'record concrete reference observations before claiming reference-led work is done'),
312
+ designGateCheck('implementation_screenshot', 'Real implementation screenshot or screen evidence exists', hasImplementation ? 'pass' : 'fail', strictOrDone, 'capture or provide implementation screenshot before claiming done'),
313
+ designGateCheck('reference_comparison', 'Reference comparison is recorded when reference is used', !hasReference ? 'not_checked' : ['matched', 'similar', 'not-applicable'].includes(comparisonResult) ? 'pass' : 'fail', hasReference, 'compare against the reference or mark the difference as intentional before claiming done'),
314
+ designGateCheck('design_quality', 'Design quality result is pass', designQuality === 'pass' ? 'pass' : designQuality === 'needs-polish' ? 'warning' : 'fail', strictOrDone, 'resolve design quality issues or keep the result as needs-polish/partial'),
315
+ designGateCheck('p0_clear', 'No P0 visual blockers remain', p0.length ? 'fail' : 'pass', true, 'fix P0 blockers before any done claim'),
316
+ designGateCheck('p1_clear', 'No P1 major visual issues remain', p1.length ? 'fail' : 'pass', strictOrDone, 'fix or explicitly defer P1 issues before claiming done'),
317
+ designGateCheck('cta_affordance', 'Primary CTA and interaction affordances were checked', Boolean(input.cta_checked) ? 'pass' : 'not_checked', strictOrDone, 'check primary CTA clarity and interaction affordances before claiming done'),
318
+ designGateCheck('state_coverage', 'Primary UI states were checked', Boolean(input.states_checked) ? 'pass' : 'not_checked', strictOrDone, 'check default/loading/error/empty/disabled states or keep completion partial'),
319
+ designGateCheck('mobile_coverage', 'Mobile/responsive behavior was checked', Boolean(input.mobile_checked || input.responsive_checked) ? 'pass' : 'not_checked', strictOrDone, 'check mobile/responsive behavior before claiming done'),
320
+ designGateCheck('accessibility_visuals', 'Contrast/accessibility-relevant visuals were checked', Boolean(input.contrast_checked || input.accessibility_checked) ? 'pass' : 'not_checked', strictOrDone, 'check contrast/accessibility-relevant visuals before claiming done')
321
+ ];
322
+ if (designScore !== null || strictOrDone) {
323
+ checks.push(designGateCheck('design_score', `Design score is at least ${minDesignScore}`, designScore !== null && designScore >= minDesignScore ? 'pass' : designScore === null ? 'not_checked' : 'fail', false, `record --design-score ${minDesignScore} or higher when using score-based completion`));
324
+ }
325
+ const blockers = [
326
+ ...p0.map((item) => `P0: ${item}`),
327
+ ...(blockedReason ? [blockedReason] : []),
328
+ ...checks
329
+ .filter((check) => check.required && check.status !== 'pass')
330
+ .map((check) => `${check.id}: ${check.next_action}`)
331
+ ];
332
+ const warnings = [
333
+ ...p1.map((item) => `P1: ${item}`),
334
+ ...checks
335
+ .filter((check) => !check.required && ['fail', 'warning', 'not_checked'].includes(check.status))
336
+ .map((check) => `${check.id}: ${check.next_action}`)
337
+ ];
338
+ const ready = completionClaim === 'done' && blockers.length === 0;
339
+ const truth: TruthStatus = blockers.some((item) => item.startsWith('P0:')) || blockedReason ? 'blocked'
340
+ : ready ? 'verified'
341
+ : strictOrDone ? 'partial'
342
+ : hasImplementation ? 'partial'
343
+ : 'assumed';
344
+ return {
345
+ schema: 'yam.ueye-design-completion-gate.v1',
346
+ mode,
347
+ completion_claim: completionClaim,
348
+ ready_to_claim_done: ready,
349
+ design_score: designScore,
350
+ min_design_score: minDesignScore,
351
+ checks,
352
+ p0,
353
+ p1,
354
+ warnings,
355
+ blockers,
356
+ next_action: blockers[0] || (ready ? 'done claim is supported by the recorded design gate' : warnings[0] || 'keep the Ueye result as draft or needs-polish until a done claim is needed'),
357
+ truth_status: truth
358
+ };
359
+ }
360
+
361
+ function normalizeUeyeCompletionClaim(value: unknown = ''): UeyeDesignCompletionGate['completion_claim'] {
362
+ const text = String(value || '').toLowerCase();
363
+ if (text === 'done' || text === 'complete' || text === 'completed') return 'done';
364
+ if (text === 'needs-polish' || text === 'needs_polish' || text === 'polish') return 'needs-polish';
365
+ return 'draft';
366
+ }
367
+
368
+ function designGateCheck(id: string, label: string, status: UeyeDesignGateCheck['status'], required: boolean, nextAction: string): UeyeDesignGateCheck {
369
+ return {
370
+ id,
371
+ label,
372
+ status,
373
+ required,
374
+ next_action: nextAction
375
+ };
376
+ }
377
+
378
+ function numberOrNull(value: unknown = null): number | null {
379
+ if (value === undefined || value === null || value === '') return null;
380
+ const number = Number(value);
381
+ return Number.isFinite(number) ? number : null;
382
+ }
383
+
212
384
  export function buildRollbackHint(input: Partial<RollbackHint> = {}): RollbackHint {
213
385
  return {
214
386
  schema: 'yam.rollback-hint.v1',
@@ -249,7 +421,7 @@ export function buildRuntimeBackendEvidence(input: Partial<RuntimeBackendEvidenc
249
421
  };
250
422
  }
251
423
 
252
- export function buildUeyeRunReport(input: Partial<UeyeRunReport> = {}): UeyeRunReport {
424
+ export function buildUeyeRunReport(input: UeyeRunReportInput = {}): UeyeRunReport {
253
425
  const references = Array.isArray(input.reference_sources)
254
426
  ? input.reference_sources.map((item) => buildUeyeVisualProvenance(item))
255
427
  : [];
@@ -264,15 +436,30 @@ export function buildUeyeRunReport(input: Partial<UeyeRunReport> = {}): UeyeRunR
264
436
  : comparisonResult === 'matched' && hasImplementation ? 'verified'
265
437
  : hasImplementation ? 'partial'
266
438
  : 'partial';
439
+ const gate = buildUeyeDesignCompletionGate({
440
+ ...input.design_completion_gate,
441
+ has_reference: references.length > 0,
442
+ has_implementation_screenshot: hasImplementation,
443
+ comparison_result: comparisonResult,
444
+ design_quality: String(input.design_quality || 'not-checked'),
445
+ blocked_reason: blockedReason
446
+ });
447
+ const shouldApplyDesignGate = gate.mode === 'strict' || gate.completion_claim === 'done' || gate.blockers.length > 0;
448
+ const finalTruth = shouldApplyDesignGate ? weakestTruth(derivedTruth, gate.truth_status) : derivedTruth;
267
449
  return {
268
450
  schema: 'yam.ueye-run-report.v1',
269
451
  reference_sources: references,
270
452
  implementation_sources: implementations,
453
+ surface_context: buildUeyeSurfaceContext({
454
+ ...input.surface_context,
455
+ truth_status: isTruthStatus(input.surface_context?.truth_status) ? input.surface_context?.truth_status : finalTruth
456
+ }),
457
+ design_completion_gate: gate,
271
458
  comparison_result: comparisonResult,
272
459
  design_quality: String(input.design_quality || 'not-checked'),
273
460
  blocked_reason: blockedReason,
274
- next_action: String(input.next_action || (derivedTruth === 'verified' ? 'no action required' : 'capture or provide implementation screenshot before claiming verified visual status')),
275
- truth_status: isTruthStatus(input.truth_status) ? input.truth_status : derivedTruth
461
+ next_action: String(input.next_action || gate.blockers[0] || (finalTruth === 'verified' ? 'no action required' : 'capture or provide implementation screenshot before claiming verified visual status')),
462
+ truth_status: isTruthStatus(input.truth_status) ? input.truth_status : finalTruth
276
463
  };
277
464
  }
278
465
 
@@ -387,6 +574,9 @@ export function classifyEvidenceTruth(summary: ProofSummary = {}, options: Proof
387
574
  for (const media of asList(summary.mediaProof)) {
388
575
  rows.push(evidenceRow('evidence', media, readStructuredTruth(media, 'partial')));
389
576
  }
577
+ for (const designCompletion of asList(summary.designCompletion)) {
578
+ rows.push(evidenceRow('visual', designCompletion, readStructuredTruth(designCompletion, 'partial')));
579
+ }
390
580
  for (const runtime of asList(summary.runtime)) {
391
581
  rows.push(evidenceRow('runtime', runtime, classifyRuntimeEvidence(runtime, options)));
392
582
  }
@@ -416,6 +606,14 @@ export function applyProofTruthCaps(summary: ProofSummary = {}, options: ProofOp
416
606
  cappedTruth = weakestTruth(cappedTruth, 'partial');
417
607
  unverified.push('real_visual_evidence_missing');
418
608
  }
609
+ const designCompletionTruth = designCompletionCap(summary.designCompletion);
610
+ if (designCompletionTruth) {
611
+ cappedTruth = weakestTruth(cappedTruth, designCompletionTruth);
612
+ if (designCompletionTruth === 'blocked') blockers.push('ueye_design_completion_blocked');
613
+ if (!['verified', 'proven'].includes(designCompletionTruth)) {
614
+ unverified.push('ueye_design_completion_not_verified');
615
+ }
616
+ }
419
617
  if (requested !== cappedTruth) {
420
618
  caps.push(`requested ${requested} capped to ${cappedTruth} by evidence`);
421
619
  }
@@ -475,6 +673,7 @@ export function buildYamCompletionProof(summary: ProofSummary = {}, options: Pro
475
673
  rollbackHint: asList(summary.rollbackHint),
476
674
  runtimeBackendEvidence: asList(summary.runtimeBackendEvidence),
477
675
  mediaProof: asList(summary.mediaProof),
676
+ designCompletion: asList(summary.designCompletion),
478
677
  cleanup: summary.cleanup || '',
479
678
  changed: asList(summary.changed),
480
679
  skipped: asList(summary.skipped),
@@ -544,6 +743,12 @@ function readStructuredTruth(value: unknown = '', fallback: TruthStatus = 'parti
544
743
  }
545
744
  }
546
745
 
746
+ function designCompletionCap(value: unknown = ''): TruthStatus | null {
747
+ const items = asList(value);
748
+ if (!items.length) return null;
749
+ return items.reduce<TruthStatus>((weakest, item) => weakestTruth(weakest, readStructuredTruth(item, 'partial')), 'proven');
750
+ }
751
+
547
752
  function strongestSupportedTruth(rows: EvidenceRow[] = []): TruthStatus {
548
753
  if (rows.some((row) => row.truth === 'blocked')) return 'blocked';
549
754
  if (rows.some((row) => row.truth === 'real_required_missing')) return 'real_required_missing';
@@ -31,6 +31,24 @@
31
31
  | comparison_result | matched / similar / different / not-verified / not-applicable |
32
32
  | truth_status | verified / partial / skipped / blocked / assumed |
33
33
 
34
+ ## Surface Context
35
+
36
+ | Field | Value |
37
+ | --- | --- |
38
+ | provider_context | not-recorded |
39
+ | provider_badge | not-recorded |
40
+ | execution_surface | not-recorded |
41
+ | app_surface | not-recorded |
42
+ | browser_surface | not-recorded |
43
+ | control_mode | not-recorded |
44
+ | url | |
45
+ | viewport | |
46
+ | screenshot_id | |
47
+ | evidence_id | |
48
+ | preserved_state | true / false |
49
+ | preserved_url | |
50
+ | truth_status | verified / partial / skipped / blocked / assumed |
51
+
34
52
  ## Reference Read Proof
35
53
 
36
54
  - Layout:
@@ -94,6 +112,36 @@ Use `pass`, `needs-polish`, or `fails` for each relevant design dimension before
94
112
  | Accessibility | needs-polish | |
95
113
  | Brand/mood fit | needs-polish | |
96
114
 
115
+ ## Design Completion Gate
116
+
117
+ | Field | Value |
118
+ | --- | --- |
119
+ | completion_claim | draft / needs-polish / done |
120
+ | mode | fast / strict |
121
+ | ready_to_claim_done | true / false |
122
+ | design_score | |
123
+ | min_design_score | 8 |
124
+ | direction_locked | true / false |
125
+ | reference_read | true / false / not-applicable |
126
+ | implementation_screenshot | pass / fail / not_checked |
127
+ | reference_comparison | matched / similar / different / not-verified / not-applicable |
128
+ | design_quality | pass / needs-polish / fails / not-checked |
129
+ | p0_clear | pass / fail |
130
+ | p1_clear | pass / fail / deferred |
131
+ | cta_checked | true / false |
132
+ | states_checked | true / false |
133
+ | mobile_checked | true / false |
134
+ | contrast_accessibility_checked | true / false |
135
+ | truth_status | verified / partial / skipped / blocked / assumed |
136
+
137
+ ### Design Gate Blockers
138
+
139
+ - None.
140
+
141
+ ### Design Gate Warnings
142
+
143
+ - None.
144
+
97
145
  ### P0 Blockers
98
146
 
99
147
  - None.
@@ -123,6 +171,29 @@ Use `pass`, `needs-polish`, or `fails` for each relevant design dimension before
123
171
  "previous_screenshot_id": "",
124
172
  "current_report_id": "",
125
173
  "current_screenshot_id": "",
174
+ "surface_context": {
175
+ "provider_context": "not-recorded",
176
+ "provider_badge": "not-recorded",
177
+ "execution_surface": "not-recorded",
178
+ "app_surface": "not-recorded",
179
+ "browser_surface": "not-recorded",
180
+ "control_mode": "not-recorded",
181
+ "preserved_state": false,
182
+ "preserved_url": "",
183
+ "truth_status": "partial"
184
+ },
185
+ "design_completion_gate": {
186
+ "completion_claim": "needs-polish",
187
+ "mode": "fast",
188
+ "ready_to_claim_done": false,
189
+ "design_score": null,
190
+ "min_design_score": 8,
191
+ "p0": [],
192
+ "p1": [],
193
+ "blockers": [],
194
+ "warnings": [],
195
+ "truth_status": "partial"
196
+ },
126
197
  "viewport": "",
127
198
  "state": "",
128
199
  "comparison_result": "not-verified",
@@ -42,6 +42,24 @@
42
42
  | comparison_result | matched / similar / different / not-verified / not-applicable |
43
43
  | truth_status | verified / partial / skipped / blocked / assumed |
44
44
 
45
+ ## Surface Context
46
+
47
+ | Field | Value |
48
+ | --- | --- |
49
+ | provider_context | not-recorded |
50
+ | provider_badge | not-recorded |
51
+ | execution_surface | not-recorded |
52
+ | app_surface | not-recorded |
53
+ | browser_surface | not-recorded |
54
+ | control_mode | not-recorded |
55
+ | url | |
56
+ | viewport | |
57
+ | screenshot_id | |
58
+ | evidence_id | |
59
+ | preserved_state | true / false |
60
+ | preserved_url | |
61
+ | truth_status | verified / partial / skipped / blocked / assumed |
62
+
45
63
  ## Reference Read Proof
46
64
 
47
65
  - Layout:
@@ -105,6 +123,36 @@ Status values: matched / similar / different / not-verified / not-applicable.
105
123
 
106
124
  Result values: pass / needs-polish / fails.
107
125
 
126
+ ## Design Completion Gate
127
+
128
+ | Field | Value |
129
+ | --- | --- |
130
+ | completion_claim | draft / needs-polish / done |
131
+ | mode | fast / strict |
132
+ | ready_to_claim_done | true / false |
133
+ | design_score | |
134
+ | min_design_score | 8 |
135
+ | direction_locked | true / false |
136
+ | reference_read | true / false / not-applicable |
137
+ | implementation_screenshot | pass / fail / not_checked |
138
+ | reference_comparison | matched / similar / different / not-verified / not-applicable |
139
+ | design_quality | pass / needs-polish / fails / not-checked |
140
+ | p0_clear | pass / fail |
141
+ | p1_clear | pass / fail / deferred |
142
+ | cta_checked | true / false |
143
+ | states_checked | true / false |
144
+ | mobile_checked | true / false |
145
+ | contrast_accessibility_checked | true / false |
146
+ | truth_status | verified / partial / skipped / blocked / assumed |
147
+
148
+ ### Design Gate Blockers
149
+
150
+ - None.
151
+
152
+ ### Design Gate Warnings
153
+
154
+ - None.
155
+
108
156
  ## P0-P3 Issues
109
157
 
110
158
  ### P0 Blockers
@@ -155,6 +203,29 @@ Result values: pass / needs-polish / fails.
155
203
  "previous_screenshot_id": "",
156
204
  "current_report_id": "",
157
205
  "current_screenshot_id": "",
206
+ "surface_context": {
207
+ "provider_context": "not-recorded",
208
+ "provider_badge": "not-recorded",
209
+ "execution_surface": "not-recorded",
210
+ "app_surface": "not-recorded",
211
+ "browser_surface": "not-recorded",
212
+ "control_mode": "not-recorded",
213
+ "preserved_state": false,
214
+ "preserved_url": "",
215
+ "truth_status": "partial"
216
+ },
217
+ "design_completion_gate": {
218
+ "completion_claim": "needs-polish",
219
+ "mode": "fast",
220
+ "ready_to_claim_done": false,
221
+ "design_score": null,
222
+ "min_design_score": 8,
223
+ "p0": [],
224
+ "p1": [],
225
+ "blockers": [],
226
+ "warnings": [],
227
+ "truth_status": "partial"
228
+ },
158
229
  "viewport": "",
159
230
  "state": "",
160
231
  "comparison_result": "not-verified",
package/yam.manifest.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "yam",
3
- "version": "0.1.0",
3
+ "version": "0.1.5",
4
4
  "principles": [
5
5
  "Direction before execution.",
6
6
  "Start fast.",
@@ -22,7 +22,7 @@
22
22
  {
23
23
  "id": "ueye",
24
24
  "stage": "v0.3",
25
- "purpose": "Tight UI/UX/design implementation and visual review with visual provenance, reference-read proof, visual comparison, design quality review, and P0-P3 issue tracking."
25
+ "purpose": "Tight UI/UX/design implementation and visual review with visual provenance, surface context, reference-read proof, visual comparison, design quality review, and P0-P3 issue tracking."
26
26
  },
27
27
  {
28
28
  "id": "question",