yam-flow 0.1.5 → 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.
- package/CHANGELOG.md +15 -0
- package/COMMANDS.md +2 -0
- package/README.md +6 -3
- package/dist/bin/yam.js +51 -10
- package/dist/lib/trust-kernel.d.ts +30 -1
- package/dist/lib/trust-kernel.js +120 -3
- package/package.json +2 -2
- package/references/trust-kernel.md +3 -0
- package/references/ueye-proof.md +51 -1
- package/references/ueye.md +27 -3
- package/skills/ueye/SKILL.md +20 -3
- package/src/bin/yam.ts +50 -8
- package/src/lib/trust-kernel.ts +152 -4
- package/templates/ueye-comparison.md +42 -0
- package/templates/ueye-review.md +42 -0
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,21 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to yam-flow are documented here.
|
|
4
4
|
|
|
5
|
+
## v0.1.6 - 2026-06-07
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Added the Ueye Design Completion Gate so Ueye can own design/UI/UX completion quality instead of relying on a separate code-risk route to catch unfinished visual work.
|
|
10
|
+
- Added `yam ueye report --completion-claim`, `--strict`, `--design-score`, P0/P1, CTA, state, mobile/responsive, contrast/accessibility, direction, and reference-read gate fields.
|
|
11
|
+
- Added `yam proof --design-completion` so design completion evidence can cap proof truth status when a Ueye done claim is not supported.
|
|
12
|
+
- Added design completion sections to Ueye review and comparison templates.
|
|
13
|
+
|
|
14
|
+
### Improved
|
|
15
|
+
|
|
16
|
+
- Ueye `done` claims now cap to partial or blocked when implementation evidence, design quality, P0/P1 status, state coverage, mobile/responsive checks, contrast/accessibility checks, CTA checks, or reference-read/comparison evidence is missing where relevant.
|
|
17
|
+
- Ueye report JSON now includes `design_completion_gate` in both the main run report and comparison report.
|
|
18
|
+
- Expanded CLI smoke coverage for Ueye completion gate success, partial, and blocked paths.
|
|
19
|
+
|
|
5
20
|
## v0.1.5 - 2026-06-04
|
|
6
21
|
|
|
7
22
|
### Added
|
package/COMMANDS.md
CHANGED
|
@@ -45,6 +45,7 @@ Opt-in visual evidence helpers:
|
|
|
45
45
|
yam ueye capture --url http://localhost:3000 --out .yam/screens/home.png
|
|
46
46
|
yam ueye compare --reference ./reference.png --actual .yam/screens/home.png
|
|
47
47
|
yam ueye report --reference ./reference.png --actual .yam/screens/home.png --review-session-id pricing-card-v1 --provider-context local --execution-surface in-app-browser --browser-surface in-app-browser --similar "overall hierarchy" --different "button glow intensity" --missing "mobile state" --design-quality needs-polish --json
|
|
48
|
+
yam ueye report --reference ./reference.png --actual .yam/screens/home.png --completion-claim done --design-quality pass --direction-locked --reference-read --states-checked --mobile-checked --contrast-checked --cta-checked --json
|
|
48
49
|
yam media proof --requested --attempted --output ./generated.png --wait-loop --json
|
|
49
50
|
yam proof --route ueye --truth partial --visual "browser/local screenshot comparison executed" --require-visual
|
|
50
51
|
```
|
|
@@ -150,6 +151,7 @@ yam proof --route ueye --truth partial --visual-provenance '{"source_kind":"refe
|
|
|
150
151
|
yam ueye capture --url http://localhost:3000 --out .yam/screens/home.png
|
|
151
152
|
yam ueye compare --reference ./reference.png --actual .yam/screens/home.png --json
|
|
152
153
|
yam ueye report --reference ./reference.png --actual .yam/screens/home.png --design-quality pass --provider-context local --execution-surface in-app-browser --browser-surface in-app-browser --json
|
|
154
|
+
yam proof --route ueye --truth verified --visual "implementation screenshot evidence recorded" --design-completion '{"completion_claim":"done","has_implementation_screenshot":true,"design_quality":"pass","states_checked":true,"mobile_checked":true,"contrast_checked":true,"cta_checked":true,"direction_locked":true,"truth_status":"verified"}'
|
|
153
155
|
yam media proof --requested --attempted --output ./generated.png --wait-loop --json
|
|
154
156
|
yam runtime evidence --backend terminal --claim observed --evidence-id dev-server-1 --command "npm run dev" --json
|
|
155
157
|
yam mission queue --agent-id implementer --scope "checkout form" --changed src/checkout.tsx --verification-hint "npm run typecheck" --rollback-hint "revert checkout form patch if typecheck or smoke fails" --json
|
package/README.md
CHANGED
|
@@ -129,7 +129,8 @@ yam proof --route ueye --truth verified --visual "reference image only"
|
|
|
129
129
|
yam proof --route ueye --truth partial --visual-provenance '{"source_kind":"reference","source_hash":"unknown","comparison_result":"not-verified","truth_status":"partial"}'
|
|
130
130
|
yam ueye capture --url http://localhost:3000 --out .yam/screens/home.png
|
|
131
131
|
yam ueye compare --reference ./reference.png --actual .yam/screens/home.png
|
|
132
|
-
yam ueye report --reference ./reference.png --actual .yam/screens/home.png --design-quality
|
|
132
|
+
yam ueye report --reference ./reference.png --actual .yam/screens/home.png --completion-claim done --design-quality pass --direction-locked --reference-read --states-checked --mobile-checked --contrast-checked --cta-checked --provider-context local --execution-surface in-app-browser --app-surface codex-app --browser-surface in-app-browser --preserved-state --json
|
|
133
|
+
yam proof --route ueye --truth verified --visual "implementation screenshot evidence recorded" --design-completion '{"completion_claim":"done","has_implementation_screenshot":true,"design_quality":"pass","states_checked":true,"mobile_checked":true,"contrast_checked":true,"cta_checked":true,"direction_locked":true,"truth_status":"verified"}'
|
|
133
134
|
yam media proof --requested --attempted --output ./generated.png --wait-loop --json
|
|
134
135
|
yam proof --route mission --mission-envelope '{"agent_id":"implementer","assigned_scope":"target component","changed_files":["src/file.ts"],"verification_hint":"npm run typecheck","truth_status":"partial"}'
|
|
135
136
|
yam release report --json
|
|
@@ -178,6 +179,7 @@ Publishing still requires confirming the final npm package name and account acce
|
|
|
178
179
|
- visual evidence caps
|
|
179
180
|
- Ueye visual run reports
|
|
180
181
|
- Ueye surface context metadata
|
|
182
|
+
- Ueye design completion gate
|
|
181
183
|
- runtime backend evidence
|
|
182
184
|
- runtime evidence mini summaries
|
|
183
185
|
- mission patch queue lite records
|
|
@@ -199,6 +201,7 @@ These shapes keep reports machine-readable without turning normal work into a he
|
|
|
199
201
|
- Structured diagnostic next action: every doctor/release diagnostic should say what was observed, what evidence supports it, what to do next, owner route, severity, and truth status.
|
|
200
202
|
- Ueye review continuity/comparison report: `$ueye` run reports can link a previous review, current evidence, comparison delta, design quality result, and next action.
|
|
201
203
|
- Ueye surface context: `$ueye` run reports can record provider context, provider badge, execution surface, app surface, browser surface, control mode, preserved URL/state, and evidence id.
|
|
204
|
+
- Ueye design completion gate: `$ueye` can stay fast for draft work, but a `done` claim is capped until implementation evidence, comparison/design-quality status, P0/P1 status, key states, mobile/responsive behavior, contrast/accessibility visuals, CTA affordance, and direction/reference-read proof are recorded when relevant.
|
|
202
205
|
|
|
203
206
|
## Ueye Capture And Compare
|
|
204
207
|
|
|
@@ -207,14 +210,14 @@ These shapes keep reports machine-readable without turning normal work into a he
|
|
|
207
210
|
```bash
|
|
208
211
|
yam ueye capture --url http://localhost:3000 --out .yam/screens/home.png
|
|
209
212
|
yam ueye compare --reference ./reference.png --actual .yam/screens/home.png --json
|
|
210
|
-
yam ueye report --reference ./reference.png --actual .yam/screens/home.png --design-quality pass --provider-context local --execution-surface in-app-browser --browser-surface in-app-browser --preserved-state --json
|
|
213
|
+
yam ueye report --reference ./reference.png --actual .yam/screens/home.png --completion-claim done --design-quality pass --direction-locked --reference-read --states-checked --mobile-checked --contrast-checked --cta-checked --provider-context local --execution-surface in-app-browser --browser-surface in-app-browser --preserved-state --json
|
|
211
214
|
```
|
|
212
215
|
|
|
213
216
|
`capture` uses a Playwright install from the current project when present, then falls back to the package context. It does not install browsers or add runtime dependencies by itself. If capture is unavailable, the visual claim stays `partial` or `blocked` until a real screenshot is supplied.
|
|
214
217
|
|
|
215
218
|
`compare` is local-only and dependency-free. It records file hashes, dimensions, comparison result, and proof-ready visual provenance. Exact image matches can be `verified`; different screenshots stay `partial` so visual parity is not overclaimed.
|
|
216
219
|
|
|
217
|
-
`report` gathers reference sources, implementation screenshots, comparison result, continuity fields, design quality judgment, surface context, and next action into one compact proof-ready JSON object.
|
|
220
|
+
`report` gathers reference sources, implementation screenshots, comparison result, continuity fields, design quality judgment, design completion gate, surface context, and next action into one compact proof-ready JSON object. Draft and needs-polish work can stay fast; `--completion-claim done` turns on the stricter design gate.
|
|
218
221
|
|
|
219
222
|
Generated media can guide visual direction, but it cannot prove the implemented UI by itself:
|
|
220
223
|
|
package/dist/bin/yam.js
CHANGED
|
@@ -8,7 +8,7 @@ import os from 'node:os';
|
|
|
8
8
|
import path from 'node:path';
|
|
9
9
|
import process from 'node:process';
|
|
10
10
|
import { fileURLToPath } from 'node:url';
|
|
11
|
-
import { TRUTH_STATUSES, buildMediaGenerationProof, buildMissionPatchEnvelope, buildRollbackHint, buildRuntimeBackendEvidence, buildUeyeVisualProvenance, buildUeyeRunReport, buildUeyeSurfaceContext, buildYamCompletionProof, detectDbSafetyText as detectTrustDbSafetyText, isTruthStatus } from '../lib/trust-kernel.js';
|
|
11
|
+
import { TRUTH_STATUSES, buildMediaGenerationProof, buildMissionPatchEnvelope, buildRollbackHint, buildRuntimeBackendEvidence, buildUeyeDesignCompletionGate, buildUeyeVisualProvenance, buildUeyeRunReport, buildUeyeSurfaceContext, buildYamCompletionProof, detectDbSafetyText as detectTrustDbSafetyText, isTruthStatus } from '../lib/trust-kernel.js';
|
|
12
12
|
function errorMessage(error) {
|
|
13
13
|
return error instanceof Error ? error.message : String(error);
|
|
14
14
|
}
|
|
@@ -1366,12 +1366,12 @@ Opt-in visual evidence helpers. Ueye stays one skill: fast by default, capture/c
|
|
|
1366
1366
|
Usage:
|
|
1367
1367
|
yam ueye capture --url URL --out screenshot.png [--viewport 1440x900] [--full-page] [--json]
|
|
1368
1368
|
yam ueye compare --reference ref.png --actual screenshot.png [--json]
|
|
1369
|
-
yam ueye report [--reference ref.png] [--actual screenshot.png] [--review-session-id id] [--provider-context local] [--execution-surface in-app-browser] [--app-surface codex-app] [--browser-surface in-app-browser] [--control-mode manual|automated] [--preserved-state] [--preserved-url URL] [--similar text] [--different text] [--missing text] [--resolved text] [--new-finding text] [--still-open text] [--regression text] [--viewport 1440x900] [--state default] [--design-quality pass|needs-polish|fails|not-checked] [--json]
|
|
1369
|
+
yam ueye report [--reference ref.png] [--actual screenshot.png] [--review-session-id id] [--provider-context local] [--execution-surface in-app-browser] [--app-surface codex-app] [--browser-surface in-app-browser] [--control-mode manual|automated] [--preserved-state] [--preserved-url URL] [--completion-claim draft|needs-polish|done] [--strict] [--design-score n] [--p0 text] [--p1 text] [--states-checked] [--mobile-checked] [--contrast-checked] [--similar text] [--different text] [--missing text] [--resolved text] [--new-finding text] [--still-open text] [--regression text] [--viewport 1440x900] [--state default] [--design-quality pass|needs-polish|fails|not-checked] [--json]
|
|
1370
1370
|
|
|
1371
1371
|
Notes:
|
|
1372
1372
|
capture uses a locally available Playwright install when present. It does not download browsers or install dependencies.
|
|
1373
1373
|
compare uses local files only and reports sha256, dimensions, comparison_result, and proof-ready visual provenance.
|
|
1374
|
-
report produces a proof-ready Ueye visual run report and continuity/comparison record without requiring a new capture.
|
|
1374
|
+
report produces a proof-ready Ueye visual run report, design completion gate, and continuity/comparison record without requiring a new capture.
|
|
1375
1375
|
`);
|
|
1376
1376
|
}
|
|
1377
1377
|
async function ueyeCapture(args = []) {
|
|
@@ -1539,7 +1539,7 @@ async function ueyeCompare(args = []) {
|
|
|
1539
1539
|
async function ueyeReport(args = []) {
|
|
1540
1540
|
if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h')
|
|
1541
1541
|
return ueyeUsage();
|
|
1542
|
-
const flags = parseSimpleFlags(args, new Set(['reference', 'ref', 'actual', 'screenshot', 'capture-backend', 'compare-backend', 'design-quality', 'blocked-reason', 'next-action', 'next-visual-action', 'review-session-id', 'reference-id', 'screenshot-id', 'previous-screenshot-id', 'current-screenshot-id', 'previous-report', 'comparison-notes', 'similar', 'different', 'missing', 'resolved', 'new-finding', 'still-open', 'regression', 'viewport', 'state', 'provider-context', 'provider-badge', 'execution-surface', 'app-surface', 'browser-surface', 'control-mode', 'preserved-state', 'preserved-url', 'url', 'evidence-id', 'json']));
|
|
1542
|
+
const flags = parseSimpleFlags(args, new Set(['reference', 'ref', 'actual', 'screenshot', 'capture-backend', 'compare-backend', 'design-quality', 'blocked-reason', 'next-action', 'next-visual-action', 'review-session-id', 'reference-id', 'screenshot-id', 'previous-screenshot-id', 'current-screenshot-id', 'previous-report', 'comparison-notes', 'similar', 'different', 'missing', 'resolved', 'new-finding', 'still-open', 'regression', 'viewport', 'state', 'provider-context', 'provider-badge', 'execution-surface', 'app-surface', 'browser-surface', 'control-mode', 'preserved-state', 'preserved-url', 'url', 'evidence-id', 'completion-claim', 'completion-status', 'gate-mode', 'strict', 'design-score', 'min-design-score', 'p0', 'p1', 'open-p0', 'open-p1', 'states-checked', 'mobile-checked', 'responsive-checked', 'contrast-checked', 'accessibility-checked', 'cta-checked', 'direction-locked', 'reference-read', 'comparison-result', 'json']));
|
|
1543
1543
|
const reference = String(flags.reference || flags.ref || '');
|
|
1544
1544
|
const actual = String(flags.actual || flags.screenshot || '');
|
|
1545
1545
|
const referenceSources = [];
|
|
@@ -1604,7 +1604,10 @@ async function ueyeReport(args = []) {
|
|
|
1604
1604
|
truth_status: 'partial'
|
|
1605
1605
|
}));
|
|
1606
1606
|
}
|
|
1607
|
-
if (
|
|
1607
|
+
if (flags.comparison_result) {
|
|
1608
|
+
comparisonResult = normalizeUeyeComparisonResult(flags.comparison_result);
|
|
1609
|
+
}
|
|
1610
|
+
else if (reference && actual && referenceSources[0]?.source_hash === implementationSources[0]?.source_hash) {
|
|
1608
1611
|
comparisonResult = 'matched';
|
|
1609
1612
|
}
|
|
1610
1613
|
else if (reference && actual) {
|
|
@@ -1624,6 +1627,22 @@ async function ueyeReport(args = []) {
|
|
|
1624
1627
|
},
|
|
1625
1628
|
comparison_result: comparisonResult,
|
|
1626
1629
|
design_quality: String(flags.design_quality || 'not-checked'),
|
|
1630
|
+
design_completion_gate: {
|
|
1631
|
+
mode: flags.strict || flags.gate_mode === 'strict' ? 'strict' : 'fast',
|
|
1632
|
+
completion_claim: flags.completion_claim || flags.completion_status || 'draft',
|
|
1633
|
+
design_score: numberOrNull(flags.design_score),
|
|
1634
|
+
min_design_score: numberOrNull(flags.min_design_score) ?? 8,
|
|
1635
|
+
p0: [...arrayFlag(flags.p0), ...arrayFlag(flags.open_p0)],
|
|
1636
|
+
p1: [...arrayFlag(flags.p1), ...arrayFlag(flags.open_p1)],
|
|
1637
|
+
states_checked: Boolean(flags.states_checked),
|
|
1638
|
+
mobile_checked: Boolean(flags.mobile_checked),
|
|
1639
|
+
responsive_checked: Boolean(flags.responsive_checked),
|
|
1640
|
+
contrast_checked: Boolean(flags.contrast_checked),
|
|
1641
|
+
accessibility_checked: Boolean(flags.accessibility_checked),
|
|
1642
|
+
cta_checked: Boolean(flags.cta_checked),
|
|
1643
|
+
direction_locked: Boolean(flags.direction_locked),
|
|
1644
|
+
reference_read: Boolean(flags.reference_read)
|
|
1645
|
+
},
|
|
1627
1646
|
blocked_reason: blockedReason,
|
|
1628
1647
|
next_action: String(flags.next_visual_action || flags.next_action || '')
|
|
1629
1648
|
});
|
|
@@ -1633,6 +1652,7 @@ async function ueyeReport(args = []) {
|
|
|
1633
1652
|
referenceSources,
|
|
1634
1653
|
implementationSources,
|
|
1635
1654
|
surfaceContext: report.surface_context,
|
|
1655
|
+
designCompletionGate: report.design_completion_gate,
|
|
1636
1656
|
comparisonResult,
|
|
1637
1657
|
designQuality: String(flags.design_quality || 'not-checked'),
|
|
1638
1658
|
similar: arrayFlag(flags.similar),
|
|
@@ -1686,7 +1706,7 @@ async function readPreviousUeyeReport(file = '') {
|
|
|
1686
1706
|
};
|
|
1687
1707
|
}
|
|
1688
1708
|
}
|
|
1689
|
-
function buildUeyeComparisonReport({ reviewSessionId, previousReport, referenceSources, implementationSources, surfaceContext, comparisonResult, designQuality, similar, different, missing, notes, resolved, newFindings, stillOpen, regressions, previousScreenshotId, currentScreenshotId, viewport, state, nextAction, truthStatus }) {
|
|
1709
|
+
function buildUeyeComparisonReport({ reviewSessionId, previousReport, referenceSources, implementationSources, surfaceContext, designCompletionGate, comparisonResult, designQuality, similar, different, missing, notes, resolved, newFindings, stillOpen, regressions, previousScreenshotId, currentScreenshotId, viewport, state, nextAction, truthStatus }) {
|
|
1690
1710
|
const hasReference = referenceSources.length > 0;
|
|
1691
1711
|
const hasImplementation = implementationSources.length > 0;
|
|
1692
1712
|
const continuityTruth = previousReport?.blocked_reason ? 'blocked' : previousReport ? 'partial' : 'assumed';
|
|
@@ -1711,6 +1731,7 @@ function buildUeyeComparisonReport({ reviewSessionId, previousReport, referenceS
|
|
|
1711
1731
|
implementation_count: implementationSources.length
|
|
1712
1732
|
},
|
|
1713
1733
|
surface_context: surfaceContext || buildUeyeSurfaceContext(),
|
|
1734
|
+
design_completion_gate: designCompletionGate || null,
|
|
1714
1735
|
comparison_result: comparisonResult,
|
|
1715
1736
|
design_quality: designQuality,
|
|
1716
1737
|
similar,
|
|
@@ -1729,6 +1750,12 @@ function buildUeyeComparisonReport({ reviewSessionId, previousReport, referenceS
|
|
|
1729
1750
|
truth_status: truthStatus
|
|
1730
1751
|
};
|
|
1731
1752
|
}
|
|
1753
|
+
function normalizeUeyeComparisonResult(value = '') {
|
|
1754
|
+
const text = String(value || '').toLowerCase();
|
|
1755
|
+
if (['matched', 'similar', 'different', 'not-verified', 'not-applicable'].includes(text))
|
|
1756
|
+
return text;
|
|
1757
|
+
return 'not-verified';
|
|
1758
|
+
}
|
|
1732
1759
|
async function media(args = []) {
|
|
1733
1760
|
const subcommand = args[0] || 'help';
|
|
1734
1761
|
if (subcommand === 'help' || subcommand === '--help' || subcommand === '-h')
|
|
@@ -2026,7 +2053,7 @@ function parseSimpleFlags(args = [], allowed = new Set()) {
|
|
|
2026
2053
|
if (allowed.size && !allowed.has(key))
|
|
2027
2054
|
continue;
|
|
2028
2055
|
const normalizedKey = key.replace(/-/g, '_');
|
|
2029
|
-
if (['json', 'full-page', 'requested', 'attempted', 'available', 'wait-loop', 'cleanup-checked'].includes(key)) {
|
|
2056
|
+
if (['json', 'full-page', 'requested', 'attempted', 'available', 'wait-loop', 'cleanup-checked', 'strict', 'preserved-state', 'states-checked', 'mobile-checked', 'responsive-checked', 'contrast-checked', 'accessibility-checked', 'cta-checked', 'direction-locked', 'reference-read'].includes(key)) {
|
|
2030
2057
|
flags[normalizedKey] = true;
|
|
2031
2058
|
continue;
|
|
2032
2059
|
}
|
|
@@ -2183,6 +2210,7 @@ async function proof(args = []) {
|
|
|
2183
2210
|
printProofList('Mission patch envelope', summary.missionEnvelope || []);
|
|
2184
2211
|
printProofList('Rollback hint', summary.rollbackHint || []);
|
|
2185
2212
|
printProofList('Media proof', summary.mediaProof || []);
|
|
2213
|
+
printProofList('Design completion', summary.designCompletion || []);
|
|
2186
2214
|
printProofList('Changed surfaces', summary.changed);
|
|
2187
2215
|
printProofList('Skipped', summary.skipped);
|
|
2188
2216
|
printProofList('Blocked', summary.blocked);
|
|
@@ -2279,6 +2307,10 @@ function buildProofSummary(parsed, artifact) {
|
|
|
2279
2307
|
...structuredEvidenceList(artifact.mediaProof),
|
|
2280
2308
|
...structuredEvidenceList(parsed.flags.media_proof)
|
|
2281
2309
|
],
|
|
2310
|
+
designCompletion: [
|
|
2311
|
+
...structuredEvidenceList(artifact.designCompletion),
|
|
2312
|
+
...structuredEvidenceList(parsed.flags.design_completion)
|
|
2313
|
+
],
|
|
2282
2314
|
cleanup: parsed.flags.cleanup || artifact.cleanup || '',
|
|
2283
2315
|
changed: [...artifact.changed, ...arrayFlag(parsed.flags.changed)],
|
|
2284
2316
|
skipped: [...artifact.skipped, ...arrayFlag(parsed.flags.skipped)],
|
|
@@ -2343,6 +2375,9 @@ function renderProofMarkdown(summary) {
|
|
|
2343
2375
|
'## Media proof',
|
|
2344
2376
|
...renderProofMarkdownList(summary.mediaProof || []),
|
|
2345
2377
|
'',
|
|
2378
|
+
'## Design completion',
|
|
2379
|
+
...renderProofMarkdownList(summary.designCompletion || []),
|
|
2380
|
+
'',
|
|
2346
2381
|
'## Changed surfaces',
|
|
2347
2382
|
...renderProofMarkdownList(summary.changed),
|
|
2348
2383
|
'',
|
|
@@ -2373,7 +2408,7 @@ function renderProofMarkdownList(values) {
|
|
|
2373
2408
|
function parseProofArgs(args = []) {
|
|
2374
2409
|
const flags = {};
|
|
2375
2410
|
const positionals = [];
|
|
2376
|
-
const aliases = new Set(['goal', 'route', 'truth', 'command', 'evidence', 'visual', 'runtime', 'runtime-backend', 'runtime-claim', 'runtime-evidence-id', 'runtime-command', 'cleanup-checked', 'runtime-note', 'runtime-backend-evidence', 'visual-provenance', 'mission-envelope', 'rollback-hint', 'media-proof', 'cleanup', 'changed', 'skipped', 'blocked', 'assumed', 'assumption', 'unverified', 'from', 'format', 'out', 'file', 'json', 'require-runtime', 'require-real-runtime', 'require-tmux', 'require-visual']);
|
|
2411
|
+
const aliases = new Set(['goal', 'route', 'truth', 'command', 'evidence', 'visual', 'runtime', 'runtime-backend', 'runtime-claim', 'runtime-evidence-id', 'runtime-command', 'cleanup-checked', 'runtime-note', 'runtime-backend-evidence', 'visual-provenance', 'mission-envelope', 'rollback-hint', 'media-proof', 'design-completion', 'cleanup', 'changed', 'skipped', 'blocked', 'assumed', 'assumption', 'unverified', 'from', 'format', 'out', 'file', 'json', 'require-runtime', 'require-real-runtime', 'require-tmux', 'require-visual']);
|
|
2377
2412
|
for (let index = 0; index < args.length; index += 1) {
|
|
2378
2413
|
const arg = args[index];
|
|
2379
2414
|
if (arg.startsWith('--')) {
|
|
@@ -2389,7 +2424,7 @@ function parseProofArgs(args = []) {
|
|
|
2389
2424
|
const value = inlineValue ?? args[index + 1] ?? '';
|
|
2390
2425
|
if (inlineValue === undefined)
|
|
2391
2426
|
index += 1;
|
|
2392
|
-
if (['command', 'evidence', 'visual', 'runtime', 'runtime-backend-evidence', 'visual-provenance', 'mission-envelope', 'rollback-hint', 'media-proof', 'changed', 'skipped', 'blocked', 'assumed', 'assumption', 'unverified'].includes(key)) {
|
|
2427
|
+
if (['command', 'evidence', 'visual', 'runtime', 'runtime-backend-evidence', 'visual-provenance', 'mission-envelope', 'rollback-hint', 'media-proof', 'design-completion', 'changed', 'skipped', 'blocked', 'assumed', 'assumption', 'unverified'].includes(key)) {
|
|
2393
2428
|
flags[normalizedKey] = [...arrayFlag(flags[normalizedKey]), value];
|
|
2394
2429
|
}
|
|
2395
2430
|
else {
|
|
@@ -2433,6 +2468,7 @@ function emptyProofArtifact() {
|
|
|
2433
2468
|
missionEnvelope: [],
|
|
2434
2469
|
rollbackHint: [],
|
|
2435
2470
|
mediaProof: [],
|
|
2471
|
+
designCompletion: [],
|
|
2436
2472
|
cleanup: '',
|
|
2437
2473
|
changed: [],
|
|
2438
2474
|
skipped: [],
|
|
@@ -2459,6 +2495,7 @@ async function parseProofJson(file, empty) {
|
|
|
2459
2495
|
missionEnvelope: structuredEvidenceList(data.missionEnvelope || data.mission_envelope),
|
|
2460
2496
|
rollbackHint: structuredEvidenceList(data.rollbackHint || data.rollback_hint),
|
|
2461
2497
|
mediaProof: structuredEvidenceList(data.mediaProof || data.media_proof),
|
|
2498
|
+
designCompletion: structuredEvidenceList(data.designCompletion || data.design_completion),
|
|
2462
2499
|
cleanup: String(data.cleanup || data.cleanupStatus || ''),
|
|
2463
2500
|
changed: arrayFlag(data.changed || data.files),
|
|
2464
2501
|
skipped: arrayFlag(data.skipped),
|
|
@@ -2489,6 +2526,7 @@ async function parseProofMarkdown(file, empty) {
|
|
|
2489
2526
|
missionEnvelope: readProofList(text, 'Mission patch envelope'),
|
|
2490
2527
|
rollbackHint: readProofList(text, 'Rollback hint'),
|
|
2491
2528
|
mediaProof: readProofList(text, 'Media proof'),
|
|
2529
|
+
designCompletion: readProofList(text, 'Design completion'),
|
|
2492
2530
|
cleanup: readProofField(text, 'Cleanup') || readProofField(text, 'Cleanup status'),
|
|
2493
2531
|
changed: firstProofList(text, ['Changed surfaces', 'Files']),
|
|
2494
2532
|
skipped: readProofList(text, 'Skipped'),
|
|
@@ -2575,6 +2613,9 @@ function formatStructuredEvidence(value) {
|
|
|
2575
2613
|
if (data.schema === 'yam.media-generation-proof.v1' || data.generation_requested || data.output_hash) {
|
|
2576
2614
|
return JSON.stringify(buildMediaGenerationProof(data));
|
|
2577
2615
|
}
|
|
2616
|
+
if (data.schema === 'yam.ueye-design-completion-gate.v1' || data.completion_claim || data.ready_to_claim_done !== undefined) {
|
|
2617
|
+
return JSON.stringify(buildUeyeDesignCompletionGate(data));
|
|
2618
|
+
}
|
|
2578
2619
|
return JSON.stringify(data);
|
|
2579
2620
|
}
|
|
2580
2621
|
catch {
|
|
@@ -2583,7 +2624,7 @@ function formatStructuredEvidence(value) {
|
|
|
2583
2624
|
}
|
|
2584
2625
|
function hasProofEvidence(parsed) {
|
|
2585
2626
|
const flags = parsed.flags || {};
|
|
2586
|
-
return ['command', 'evidence', 'visual', 'runtime', 'runtime_backend_evidence', 'visual_provenance', 'mission_envelope', 'rollback_hint', 'media_proof', 'changed', 'skipped', 'blocked'].some((key) => arrayFlag(flags[key]).length > 0) || Boolean(flags.cleanup || flags.runtime_backend || flags.runtime_claim);
|
|
2627
|
+
return ['command', 'evidence', 'visual', 'runtime', 'runtime_backend_evidence', 'visual_provenance', 'mission_envelope', 'rollback_hint', 'media_proof', 'design_completion', 'changed', 'skipped', 'blocked'].some((key) => arrayFlag(flags[key]).length > 0) || Boolean(flags.cleanup || flags.runtime_backend || flags.runtime_claim);
|
|
2587
2628
|
}
|
|
2588
2629
|
function printProofList(label, values) {
|
|
2589
2630
|
console.log(`- ${label}:`);
|
|
@@ -68,6 +68,28 @@ export interface UeyeSurfaceContext {
|
|
|
68
68
|
local_only: boolean;
|
|
69
69
|
truth_status: TruthStatus;
|
|
70
70
|
}
|
|
71
|
+
export interface UeyeDesignGateCheck {
|
|
72
|
+
id: string;
|
|
73
|
+
label: string;
|
|
74
|
+
status: 'pass' | 'fail' | 'warning' | 'not_checked';
|
|
75
|
+
required: boolean;
|
|
76
|
+
next_action: string;
|
|
77
|
+
}
|
|
78
|
+
export interface UeyeDesignCompletionGate {
|
|
79
|
+
schema: 'yam.ueye-design-completion-gate.v1';
|
|
80
|
+
mode: 'fast' | 'strict';
|
|
81
|
+
completion_claim: 'draft' | 'needs-polish' | 'done';
|
|
82
|
+
ready_to_claim_done: boolean;
|
|
83
|
+
design_score: number | null;
|
|
84
|
+
min_design_score: number;
|
|
85
|
+
checks: UeyeDesignGateCheck[];
|
|
86
|
+
p0: string[];
|
|
87
|
+
p1: string[];
|
|
88
|
+
warnings: string[];
|
|
89
|
+
blockers: string[];
|
|
90
|
+
next_action: string;
|
|
91
|
+
truth_status: TruthStatus;
|
|
92
|
+
}
|
|
71
93
|
export interface RollbackHint {
|
|
72
94
|
schema: 'yam.rollback-hint.v1';
|
|
73
95
|
touched_files: string[];
|
|
@@ -99,12 +121,16 @@ export interface UeyeRunReport {
|
|
|
99
121
|
reference_sources: UeyeVisualProvenance[];
|
|
100
122
|
implementation_sources: UeyeVisualProvenance[];
|
|
101
123
|
surface_context: UeyeSurfaceContext;
|
|
124
|
+
design_completion_gate: UeyeDesignCompletionGate;
|
|
102
125
|
comparison_result: string;
|
|
103
126
|
design_quality: string;
|
|
104
127
|
blocked_reason: string;
|
|
105
128
|
next_action: string;
|
|
106
129
|
truth_status: TruthStatus;
|
|
107
130
|
}
|
|
131
|
+
export interface UeyeRunReportInput extends Partial<Omit<UeyeRunReport, 'design_completion_gate'>> {
|
|
132
|
+
design_completion_gate?: Partial<UeyeDesignCompletionGate> & Record<string, unknown>;
|
|
133
|
+
}
|
|
108
134
|
export interface MediaGenerationProof {
|
|
109
135
|
schema: 'yam.media-generation-proof.v1';
|
|
110
136
|
tool_name: string;
|
|
@@ -145,6 +171,7 @@ export interface ProofSummary {
|
|
|
145
171
|
rollbackHint?: unknown;
|
|
146
172
|
runtimeBackendEvidence?: unknown;
|
|
147
173
|
mediaProof?: unknown;
|
|
174
|
+
designCompletion?: unknown;
|
|
148
175
|
}
|
|
149
176
|
export interface ProofOptions {
|
|
150
177
|
requireRealRuntime?: boolean;
|
|
@@ -177,6 +204,7 @@ export interface YamCompletionProof {
|
|
|
177
204
|
rollbackHint: string[];
|
|
178
205
|
runtimeBackendEvidence: string[];
|
|
179
206
|
mediaProof: string[];
|
|
207
|
+
designCompletion: string[];
|
|
180
208
|
cleanup: unknown;
|
|
181
209
|
changed: string[];
|
|
182
210
|
skipped: string[];
|
|
@@ -190,10 +218,11 @@ export interface YamCompletionProof {
|
|
|
190
218
|
}
|
|
191
219
|
export declare function buildUeyeVisualProvenance(input?: Partial<UeyeVisualProvenance>): UeyeVisualProvenance;
|
|
192
220
|
export declare function buildUeyeSurfaceContext(input?: Partial<UeyeSurfaceContext>): UeyeSurfaceContext;
|
|
221
|
+
export declare function buildUeyeDesignCompletionGate(input?: Partial<UeyeDesignCompletionGate> & Record<string, unknown>): UeyeDesignCompletionGate;
|
|
193
222
|
export declare function buildRollbackHint(input?: Partial<RollbackHint>): RollbackHint;
|
|
194
223
|
export declare function buildMissionPatchEnvelope(input?: Partial<MissionPatchEnvelope>): MissionPatchEnvelope;
|
|
195
224
|
export declare function buildRuntimeBackendEvidence(input?: Partial<RuntimeBackendEvidence>): RuntimeBackendEvidence;
|
|
196
|
-
export declare function buildUeyeRunReport(input?:
|
|
225
|
+
export declare function buildUeyeRunReport(input?: UeyeRunReportInput): UeyeRunReport;
|
|
197
226
|
export declare function buildMediaGenerationProof(input?: Partial<MediaGenerationProof>): MediaGenerationProof;
|
|
198
227
|
export declare function isTruthStatus(value?: unknown): value is TruthStatus;
|
|
199
228
|
export declare function weakestTruth(...statuses: unknown[]): TruthStatus;
|
package/dist/lib/trust-kernel.js
CHANGED
|
@@ -52,6 +52,93 @@ export function buildUeyeSurfaceContext(input = {}) {
|
|
|
52
52
|
truth_status: isTruthStatus(input.truth_status) ? input.truth_status : 'partial'
|
|
53
53
|
};
|
|
54
54
|
}
|
|
55
|
+
export function buildUeyeDesignCompletionGate(input = {}) {
|
|
56
|
+
const completionClaim = normalizeUeyeCompletionClaim(input.completion_claim);
|
|
57
|
+
const mode = String(input.mode || '').toLowerCase() === 'strict' || completionClaim === 'done' ? 'strict' : 'fast';
|
|
58
|
+
const designScore = numberOrNull(input.design_score);
|
|
59
|
+
const minDesignScore = numberOrNull(input.min_design_score) ?? 8;
|
|
60
|
+
const p0 = asList(input.p0);
|
|
61
|
+
const p1 = asList(input.p1);
|
|
62
|
+
const hasReference = Boolean(input.has_reference);
|
|
63
|
+
const hasImplementation = Boolean(input.has_implementation_screenshot);
|
|
64
|
+
const comparisonResult = String(input.comparison_result || 'not-verified');
|
|
65
|
+
const designQuality = String(input.design_quality || 'not-checked');
|
|
66
|
+
const blockedReason = String(input.blocked_reason || '');
|
|
67
|
+
const strictOrDone = mode === 'strict' || completionClaim === 'done';
|
|
68
|
+
const checks = [
|
|
69
|
+
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'),
|
|
70
|
+
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'),
|
|
71
|
+
designGateCheck('implementation_screenshot', 'Real implementation screenshot or screen evidence exists', hasImplementation ? 'pass' : 'fail', strictOrDone, 'capture or provide implementation screenshot before claiming done'),
|
|
72
|
+
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'),
|
|
73
|
+
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'),
|
|
74
|
+
designGateCheck('p0_clear', 'No P0 visual blockers remain', p0.length ? 'fail' : 'pass', true, 'fix P0 blockers before any done claim'),
|
|
75
|
+
designGateCheck('p1_clear', 'No P1 major visual issues remain', p1.length ? 'fail' : 'pass', strictOrDone, 'fix or explicitly defer P1 issues before claiming done'),
|
|
76
|
+
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'),
|
|
77
|
+
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'),
|
|
78
|
+
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'),
|
|
79
|
+
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')
|
|
80
|
+
];
|
|
81
|
+
if (designScore !== null || strictOrDone) {
|
|
82
|
+
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`));
|
|
83
|
+
}
|
|
84
|
+
const blockers = [
|
|
85
|
+
...p0.map((item) => `P0: ${item}`),
|
|
86
|
+
...(blockedReason ? [blockedReason] : []),
|
|
87
|
+
...checks
|
|
88
|
+
.filter((check) => check.required && check.status !== 'pass')
|
|
89
|
+
.map((check) => `${check.id}: ${check.next_action}`)
|
|
90
|
+
];
|
|
91
|
+
const warnings = [
|
|
92
|
+
...p1.map((item) => `P1: ${item}`),
|
|
93
|
+
...checks
|
|
94
|
+
.filter((check) => !check.required && ['fail', 'warning', 'not_checked'].includes(check.status))
|
|
95
|
+
.map((check) => `${check.id}: ${check.next_action}`)
|
|
96
|
+
];
|
|
97
|
+
const ready = completionClaim === 'done' && blockers.length === 0;
|
|
98
|
+
const truth = blockers.some((item) => item.startsWith('P0:')) || blockedReason ? 'blocked'
|
|
99
|
+
: ready ? 'verified'
|
|
100
|
+
: strictOrDone ? 'partial'
|
|
101
|
+
: hasImplementation ? 'partial'
|
|
102
|
+
: 'assumed';
|
|
103
|
+
return {
|
|
104
|
+
schema: 'yam.ueye-design-completion-gate.v1',
|
|
105
|
+
mode,
|
|
106
|
+
completion_claim: completionClaim,
|
|
107
|
+
ready_to_claim_done: ready,
|
|
108
|
+
design_score: designScore,
|
|
109
|
+
min_design_score: minDesignScore,
|
|
110
|
+
checks,
|
|
111
|
+
p0,
|
|
112
|
+
p1,
|
|
113
|
+
warnings,
|
|
114
|
+
blockers,
|
|
115
|
+
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'),
|
|
116
|
+
truth_status: truth
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
function normalizeUeyeCompletionClaim(value = '') {
|
|
120
|
+
const text = String(value || '').toLowerCase();
|
|
121
|
+
if (text === 'done' || text === 'complete' || text === 'completed')
|
|
122
|
+
return 'done';
|
|
123
|
+
if (text === 'needs-polish' || text === 'needs_polish' || text === 'polish')
|
|
124
|
+
return 'needs-polish';
|
|
125
|
+
return 'draft';
|
|
126
|
+
}
|
|
127
|
+
function designGateCheck(id, label, status, required, nextAction) {
|
|
128
|
+
return {
|
|
129
|
+
id,
|
|
130
|
+
label,
|
|
131
|
+
status,
|
|
132
|
+
required,
|
|
133
|
+
next_action: nextAction
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
function numberOrNull(value = null) {
|
|
137
|
+
if (value === undefined || value === null || value === '')
|
|
138
|
+
return null;
|
|
139
|
+
const number = Number(value);
|
|
140
|
+
return Number.isFinite(number) ? number : null;
|
|
141
|
+
}
|
|
55
142
|
export function buildRollbackHint(input = {}) {
|
|
56
143
|
return {
|
|
57
144
|
schema: 'yam.rollback-hint.v1',
|
|
@@ -104,19 +191,30 @@ export function buildUeyeRunReport(input = {}) {
|
|
|
104
191
|
: comparisonResult === 'matched' && hasImplementation ? 'verified'
|
|
105
192
|
: hasImplementation ? 'partial'
|
|
106
193
|
: 'partial';
|
|
194
|
+
const gate = buildUeyeDesignCompletionGate({
|
|
195
|
+
...input.design_completion_gate,
|
|
196
|
+
has_reference: references.length > 0,
|
|
197
|
+
has_implementation_screenshot: hasImplementation,
|
|
198
|
+
comparison_result: comparisonResult,
|
|
199
|
+
design_quality: String(input.design_quality || 'not-checked'),
|
|
200
|
+
blocked_reason: blockedReason
|
|
201
|
+
});
|
|
202
|
+
const shouldApplyDesignGate = gate.mode === 'strict' || gate.completion_claim === 'done' || gate.blockers.length > 0;
|
|
203
|
+
const finalTruth = shouldApplyDesignGate ? weakestTruth(derivedTruth, gate.truth_status) : derivedTruth;
|
|
107
204
|
return {
|
|
108
205
|
schema: 'yam.ueye-run-report.v1',
|
|
109
206
|
reference_sources: references,
|
|
110
207
|
implementation_sources: implementations,
|
|
111
208
|
surface_context: buildUeyeSurfaceContext({
|
|
112
209
|
...input.surface_context,
|
|
113
|
-
truth_status: isTruthStatus(input.surface_context?.truth_status) ? input.surface_context?.truth_status :
|
|
210
|
+
truth_status: isTruthStatus(input.surface_context?.truth_status) ? input.surface_context?.truth_status : finalTruth
|
|
114
211
|
}),
|
|
212
|
+
design_completion_gate: gate,
|
|
115
213
|
comparison_result: comparisonResult,
|
|
116
214
|
design_quality: String(input.design_quality || 'not-checked'),
|
|
117
215
|
blocked_reason: blockedReason,
|
|
118
|
-
next_action: String(input.next_action || (
|
|
119
|
-
truth_status: isTruthStatus(input.truth_status) ? input.truth_status :
|
|
216
|
+
next_action: String(input.next_action || gate.blockers[0] || (finalTruth === 'verified' ? 'no action required' : 'capture or provide implementation screenshot before claiming verified visual status')),
|
|
217
|
+
truth_status: isTruthStatus(input.truth_status) ? input.truth_status : finalTruth
|
|
120
218
|
};
|
|
121
219
|
}
|
|
122
220
|
export function buildMediaGenerationProof(input = {}) {
|
|
@@ -229,6 +327,9 @@ export function classifyEvidenceTruth(summary = {}, options = {}) {
|
|
|
229
327
|
for (const media of asList(summary.mediaProof)) {
|
|
230
328
|
rows.push(evidenceRow('evidence', media, readStructuredTruth(media, 'partial')));
|
|
231
329
|
}
|
|
330
|
+
for (const designCompletion of asList(summary.designCompletion)) {
|
|
331
|
+
rows.push(evidenceRow('visual', designCompletion, readStructuredTruth(designCompletion, 'partial')));
|
|
332
|
+
}
|
|
232
333
|
for (const runtime of asList(summary.runtime)) {
|
|
233
334
|
rows.push(evidenceRow('runtime', runtime, classifyRuntimeEvidence(runtime, options)));
|
|
234
335
|
}
|
|
@@ -262,6 +363,15 @@ export function applyProofTruthCaps(summary = {}, options = {}) {
|
|
|
262
363
|
cappedTruth = weakestTruth(cappedTruth, 'partial');
|
|
263
364
|
unverified.push('real_visual_evidence_missing');
|
|
264
365
|
}
|
|
366
|
+
const designCompletionTruth = designCompletionCap(summary.designCompletion);
|
|
367
|
+
if (designCompletionTruth) {
|
|
368
|
+
cappedTruth = weakestTruth(cappedTruth, designCompletionTruth);
|
|
369
|
+
if (designCompletionTruth === 'blocked')
|
|
370
|
+
blockers.push('ueye_design_completion_blocked');
|
|
371
|
+
if (!['verified', 'proven'].includes(designCompletionTruth)) {
|
|
372
|
+
unverified.push('ueye_design_completion_not_verified');
|
|
373
|
+
}
|
|
374
|
+
}
|
|
265
375
|
if (requested !== cappedTruth) {
|
|
266
376
|
caps.push(`requested ${requested} capped to ${cappedTruth} by evidence`);
|
|
267
377
|
}
|
|
@@ -319,6 +429,7 @@ export function buildYamCompletionProof(summary = {}, options = {}) {
|
|
|
319
429
|
rollbackHint: asList(summary.rollbackHint),
|
|
320
430
|
runtimeBackendEvidence: asList(summary.runtimeBackendEvidence),
|
|
321
431
|
mediaProof: asList(summary.mediaProof),
|
|
432
|
+
designCompletion: asList(summary.designCompletion),
|
|
322
433
|
cleanup: summary.cleanup || '',
|
|
323
434
|
changed: asList(summary.changed),
|
|
324
435
|
skipped: asList(summary.skipped),
|
|
@@ -394,6 +505,12 @@ function readStructuredTruth(value = '', fallback = 'partial') {
|
|
|
394
505
|
return fallback;
|
|
395
506
|
}
|
|
396
507
|
}
|
|
508
|
+
function designCompletionCap(value = '') {
|
|
509
|
+
const items = asList(value);
|
|
510
|
+
if (!items.length)
|
|
511
|
+
return null;
|
|
512
|
+
return items.reduce((weakest, item) => weakestTruth(weakest, readStructuredTruth(item, 'partial')), 'proven');
|
|
513
|
+
}
|
|
397
514
|
function strongestSupportedTruth(rows = []) {
|
|
398
515
|
if (rows.some((row) => row.truth === 'blocked'))
|
|
399
516
|
return 'blocked';
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yam-flow",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
4
4
|
"description": "Progressive proof-first agent flow: start fast, deepen deliberately, stay honest by design.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"author": "0kim0bos",
|
|
@@ -16,7 +16,7 @@
|
|
|
16
16
|
"node": ">=18"
|
|
17
17
|
},
|
|
18
18
|
"bin": {
|
|
19
|
-
"yam": "
|
|
19
|
+
"yam": "dist/bin/yam.js"
|
|
20
20
|
},
|
|
21
21
|
"types": "dist/lib/trust-kernel.d.ts",
|
|
22
22
|
"exports": {
|
|
@@ -11,6 +11,7 @@ This is the small trust kernel that keeps `yam` honest without turning every tas
|
|
|
11
11
|
- fake versus real evidence distinction
|
|
12
12
|
- runtime truth matrix idea
|
|
13
13
|
- visual evidence caps
|
|
14
|
+
- Ueye design completion gate
|
|
14
15
|
- DB/Supabase destructive-signal detection
|
|
15
16
|
|
|
16
17
|
## Rejected
|
|
@@ -38,6 +39,7 @@ The module provides:
|
|
|
38
39
|
- fake/real policy
|
|
39
40
|
- runtime truth matrix
|
|
40
41
|
- completion proof object creation
|
|
42
|
+
- Ueye design completion gate creation
|
|
41
43
|
|
|
42
44
|
## Policy
|
|
43
45
|
|
|
@@ -51,5 +53,6 @@ For example:
|
|
|
51
53
|
- Mock/fixture evidence cannot become real runtime `proven`.
|
|
52
54
|
- Required runtime evidence that is missing becomes `real_required_missing`.
|
|
53
55
|
- Cleanup claims require cleanup evidence.
|
|
56
|
+
- Ueye `done` claims require a passing design completion gate or stay capped at `partial` or `blocked`.
|
|
54
57
|
|
|
55
58
|
This keeps the trust layer progressive and route-scoped.
|