yam-flow 0.1.2 → 0.1.3
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/COMMANDS.md +4 -0
- package/README.md +14 -0
- package/dist/bin/yam.js +306 -22
- package/dist/lib/trust-kernel.d.ts +41 -0
- package/dist/lib/trust-kernel.js +117 -0
- package/package.json +1 -1
- package/references/ueye-proof.md +20 -0
- package/skills/ueye/SKILL.md +7 -0
- package/src/bin/yam.ts +299 -20
- package/src/lib/trust-kernel.ts +147 -0
|
@@ -3,6 +3,8 @@ export type TruthStatus = (typeof TRUTH_STATUSES)[number];
|
|
|
3
3
|
export type SafetyLevel = 'danger' | 'warning';
|
|
4
4
|
export type EvidenceKind = 'command' | 'evidence' | 'visual' | 'runtime' | 'skipped' | 'blocked' | 'assumption' | 'cleanup' | 'none';
|
|
5
5
|
export type RuntimeSubsystem = 'real_runtime' | 'tmux_physical' | 'process_cleanup' | 'browser_visual' | 'db_safety';
|
|
6
|
+
export type RuntimeBackend = 'none' | 'in_app_browser' | 'playwright' | 'terminal' | 'tmux' | 'zellij' | 'unknown';
|
|
7
|
+
export type RuntimeClaim = 'not_started' | 'started' | 'observed' | 'stopped' | 'cleanup_verified' | 'blocked' | 'unknown';
|
|
6
8
|
export interface SafetyHit {
|
|
7
9
|
level: SafetyLevel;
|
|
8
10
|
reason: string;
|
|
@@ -58,6 +60,38 @@ export interface MissionPatchEnvelope {
|
|
|
58
60
|
rollback_hint: RollbackHint;
|
|
59
61
|
truth_status: TruthStatus;
|
|
60
62
|
}
|
|
63
|
+
export interface RuntimeBackendEvidence {
|
|
64
|
+
schema: 'yam.runtime-backend-evidence.v1';
|
|
65
|
+
backend: RuntimeBackend;
|
|
66
|
+
claim: RuntimeClaim;
|
|
67
|
+
evidence_id: string;
|
|
68
|
+
command: string;
|
|
69
|
+
cleanup_checked: boolean;
|
|
70
|
+
note: string;
|
|
71
|
+
truth_status: TruthStatus;
|
|
72
|
+
}
|
|
73
|
+
export interface UeyeRunReport {
|
|
74
|
+
schema: 'yam.ueye-run-report.v1';
|
|
75
|
+
reference_sources: UeyeVisualProvenance[];
|
|
76
|
+
implementation_sources: UeyeVisualProvenance[];
|
|
77
|
+
comparison_result: string;
|
|
78
|
+
design_quality: string;
|
|
79
|
+
blocked_reason: string;
|
|
80
|
+
next_action: string;
|
|
81
|
+
truth_status: TruthStatus;
|
|
82
|
+
}
|
|
83
|
+
export interface MediaGenerationProof {
|
|
84
|
+
schema: 'yam.media-generation-proof.v1';
|
|
85
|
+
tool_name: string;
|
|
86
|
+
generation_requested: boolean;
|
|
87
|
+
generation_attempted: boolean;
|
|
88
|
+
output_path: string;
|
|
89
|
+
output_hash: string;
|
|
90
|
+
wait_loop_checked: boolean;
|
|
91
|
+
blocked_reason: string;
|
|
92
|
+
next_action: string;
|
|
93
|
+
truth_status: TruthStatus;
|
|
94
|
+
}
|
|
61
95
|
export interface FakeRealPolicyResult {
|
|
62
96
|
schema: 'yam.fake-real-policy.v1';
|
|
63
97
|
ok: boolean;
|
|
@@ -84,6 +118,8 @@ export interface ProofSummary {
|
|
|
84
118
|
visualProvenance?: unknown;
|
|
85
119
|
missionEnvelope?: unknown;
|
|
86
120
|
rollbackHint?: unknown;
|
|
121
|
+
runtimeBackendEvidence?: unknown;
|
|
122
|
+
mediaProof?: unknown;
|
|
87
123
|
}
|
|
88
124
|
export interface ProofOptions {
|
|
89
125
|
requireRealRuntime?: boolean;
|
|
@@ -114,6 +150,8 @@ export interface YamCompletionProof {
|
|
|
114
150
|
visualProvenance: string[];
|
|
115
151
|
missionEnvelope: string[];
|
|
116
152
|
rollbackHint: string[];
|
|
153
|
+
runtimeBackendEvidence: string[];
|
|
154
|
+
mediaProof: string[];
|
|
117
155
|
cleanup: unknown;
|
|
118
156
|
changed: string[];
|
|
119
157
|
skipped: string[];
|
|
@@ -128,6 +166,9 @@ export interface YamCompletionProof {
|
|
|
128
166
|
export declare function buildUeyeVisualProvenance(input?: Partial<UeyeVisualProvenance>): UeyeVisualProvenance;
|
|
129
167
|
export declare function buildRollbackHint(input?: Partial<RollbackHint>): RollbackHint;
|
|
130
168
|
export declare function buildMissionPatchEnvelope(input?: Partial<MissionPatchEnvelope>): MissionPatchEnvelope;
|
|
169
|
+
export declare function buildRuntimeBackendEvidence(input?: Partial<RuntimeBackendEvidence>): RuntimeBackendEvidence;
|
|
170
|
+
export declare function buildUeyeRunReport(input?: Partial<UeyeRunReport>): UeyeRunReport;
|
|
171
|
+
export declare function buildMediaGenerationProof(input?: Partial<MediaGenerationProof>): MediaGenerationProof;
|
|
131
172
|
export declare function isTruthStatus(value?: unknown): value is TruthStatus;
|
|
132
173
|
export declare function weakestTruth(...statuses: unknown[]): TruthStatus;
|
|
133
174
|
export declare function detectDbSafetyText(text?: unknown): DbSafetyScanResult;
|
package/dist/lib/trust-kernel.js
CHANGED
|
@@ -49,6 +49,70 @@ export function buildMissionPatchEnvelope(input = {}) {
|
|
|
49
49
|
truth_status: isTruthStatus(input.truth_status) ? input.truth_status : 'partial'
|
|
50
50
|
};
|
|
51
51
|
}
|
|
52
|
+
export function buildRuntimeBackendEvidence(input = {}) {
|
|
53
|
+
const backend = normalizeRuntimeBackend(input.backend);
|
|
54
|
+
const claim = normalizeRuntimeClaim(input.claim);
|
|
55
|
+
return {
|
|
56
|
+
schema: 'yam.runtime-backend-evidence.v1',
|
|
57
|
+
backend,
|
|
58
|
+
claim,
|
|
59
|
+
evidence_id: String(input.evidence_id || ''),
|
|
60
|
+
command: String(input.command || ''),
|
|
61
|
+
cleanup_checked: Boolean(input.cleanup_checked),
|
|
62
|
+
note: String(input.note || ''),
|
|
63
|
+
truth_status: isTruthStatus(input.truth_status) ? input.truth_status : runtimeBackendTruth(backend, claim, Boolean(input.cleanup_checked))
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
export function buildUeyeRunReport(input = {}) {
|
|
67
|
+
const references = Array.isArray(input.reference_sources)
|
|
68
|
+
? input.reference_sources.map((item) => buildUeyeVisualProvenance(item))
|
|
69
|
+
: [];
|
|
70
|
+
const implementations = Array.isArray(input.implementation_sources)
|
|
71
|
+
? input.implementation_sources.map((item) => buildUeyeVisualProvenance(item))
|
|
72
|
+
: [];
|
|
73
|
+
const blockedReason = String(input.blocked_reason || '');
|
|
74
|
+
const comparisonResult = String(input.comparison_result || 'not-verified');
|
|
75
|
+
const hasImplementation = implementations.length > 0;
|
|
76
|
+
const derivedTruth = blockedReason ? 'blocked'
|
|
77
|
+
: !references.length && !hasImplementation ? 'assumed'
|
|
78
|
+
: comparisonResult === 'matched' && hasImplementation ? 'verified'
|
|
79
|
+
: hasImplementation ? 'partial'
|
|
80
|
+
: 'partial';
|
|
81
|
+
return {
|
|
82
|
+
schema: 'yam.ueye-run-report.v1',
|
|
83
|
+
reference_sources: references,
|
|
84
|
+
implementation_sources: implementations,
|
|
85
|
+
comparison_result: comparisonResult,
|
|
86
|
+
design_quality: String(input.design_quality || 'not-checked'),
|
|
87
|
+
blocked_reason: blockedReason,
|
|
88
|
+
next_action: String(input.next_action || (derivedTruth === 'verified' ? 'no action required' : 'capture or provide implementation screenshot before claiming verified visual status')),
|
|
89
|
+
truth_status: isTruthStatus(input.truth_status) ? input.truth_status : derivedTruth
|
|
90
|
+
};
|
|
91
|
+
}
|
|
92
|
+
export function buildMediaGenerationProof(input = {}) {
|
|
93
|
+
const requested = Boolean(input.generation_requested);
|
|
94
|
+
const attempted = Boolean(input.generation_attempted);
|
|
95
|
+
const outputHash = String(input.output_hash || 'unknown');
|
|
96
|
+
const blockedReason = String(input.blocked_reason || '');
|
|
97
|
+
const derivedTruth = blockedReason ? 'blocked'
|
|
98
|
+
: requested && !attempted ? 'blocked'
|
|
99
|
+
: attempted && outputHash !== 'unknown' ? 'verified'
|
|
100
|
+
: attempted ? 'partial'
|
|
101
|
+
: requested ? 'assumed'
|
|
102
|
+
: 'skipped';
|
|
103
|
+
return {
|
|
104
|
+
schema: 'yam.media-generation-proof.v1',
|
|
105
|
+
tool_name: String(input.tool_name || ''),
|
|
106
|
+
generation_requested: requested,
|
|
107
|
+
generation_attempted: attempted,
|
|
108
|
+
output_path: String(input.output_path || ''),
|
|
109
|
+
output_hash: outputHash,
|
|
110
|
+
wait_loop_checked: Boolean(input.wait_loop_checked),
|
|
111
|
+
blocked_reason: blockedReason,
|
|
112
|
+
next_action: String(input.next_action || (derivedTruth === 'blocked' ? 'provide a usable media tool or mark generation as skipped' : 'record output evidence before using generated media as implementation proof')),
|
|
113
|
+
truth_status: isTruthStatus(input.truth_status) ? input.truth_status : derivedTruth
|
|
114
|
+
};
|
|
115
|
+
}
|
|
52
116
|
const TRUTH_RANK = Object.freeze({
|
|
53
117
|
blocked: 0,
|
|
54
118
|
real_required_missing: 0,
|
|
@@ -129,6 +193,12 @@ export function classifyEvidenceTruth(summary = {}, options = {}) {
|
|
|
129
193
|
for (const rollback of asList(summary.rollbackHint)) {
|
|
130
194
|
rows.push(evidenceRow('evidence', rollback, metadataTruth(rollback, 'partial')));
|
|
131
195
|
}
|
|
196
|
+
for (const backend of asList(summary.runtimeBackendEvidence)) {
|
|
197
|
+
rows.push(evidenceRow('runtime', backend, readStructuredTruth(backend, 'partial')));
|
|
198
|
+
}
|
|
199
|
+
for (const media of asList(summary.mediaProof)) {
|
|
200
|
+
rows.push(evidenceRow('evidence', media, readStructuredTruth(media, 'partial')));
|
|
201
|
+
}
|
|
132
202
|
for (const runtime of asList(summary.runtime)) {
|
|
133
203
|
rows.push(evidenceRow('runtime', runtime, classifyRuntimeEvidence(runtime, options)));
|
|
134
204
|
}
|
|
@@ -217,6 +287,8 @@ export function buildYamCompletionProof(summary = {}, options = {}) {
|
|
|
217
287
|
visualProvenance: asList(summary.visualProvenance),
|
|
218
288
|
missionEnvelope: asList(summary.missionEnvelope),
|
|
219
289
|
rollbackHint: asList(summary.rollbackHint),
|
|
290
|
+
runtimeBackendEvidence: asList(summary.runtimeBackendEvidence),
|
|
291
|
+
mediaProof: asList(summary.mediaProof),
|
|
220
292
|
cleanup: summary.cleanup || '',
|
|
221
293
|
changed: asList(summary.changed),
|
|
222
294
|
skipped: asList(summary.skipped),
|
|
@@ -353,6 +425,51 @@ function runtimeRow(subsystem, proofLevel, required) {
|
|
|
353
425
|
: 'no action required'
|
|
354
426
|
};
|
|
355
427
|
}
|
|
428
|
+
function normalizeRuntimeBackend(value = '') {
|
|
429
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
430
|
+
if (text === 'in_app_browser' || text === 'browser')
|
|
431
|
+
return 'in_app_browser';
|
|
432
|
+
if (text === 'playwright')
|
|
433
|
+
return 'playwright';
|
|
434
|
+
if (text === 'terminal' || text === 'shell')
|
|
435
|
+
return 'terminal';
|
|
436
|
+
if (text === 'tmux')
|
|
437
|
+
return 'tmux';
|
|
438
|
+
if (text === 'zellij')
|
|
439
|
+
return 'zellij';
|
|
440
|
+
if (text === 'none' || text === 'not_started')
|
|
441
|
+
return 'none';
|
|
442
|
+
return 'unknown';
|
|
443
|
+
}
|
|
444
|
+
function normalizeRuntimeClaim(value = '') {
|
|
445
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
446
|
+
if (text === 'not_started' || text === 'none')
|
|
447
|
+
return 'not_started';
|
|
448
|
+
if (text === 'started')
|
|
449
|
+
return 'started';
|
|
450
|
+
if (text === 'observed' || text === 'checked')
|
|
451
|
+
return 'observed';
|
|
452
|
+
if (text === 'stopped')
|
|
453
|
+
return 'stopped';
|
|
454
|
+
if (text === 'cleanup_verified' || text === 'cleanup_checked')
|
|
455
|
+
return 'cleanup_verified';
|
|
456
|
+
if (text === 'blocked')
|
|
457
|
+
return 'blocked';
|
|
458
|
+
return 'unknown';
|
|
459
|
+
}
|
|
460
|
+
function runtimeBackendTruth(backend, claim, cleanupChecked = false) {
|
|
461
|
+
if (claim === 'blocked')
|
|
462
|
+
return 'blocked';
|
|
463
|
+
if (backend === 'none' || claim === 'not_started')
|
|
464
|
+
return 'skipped';
|
|
465
|
+
if (backend === 'unknown' || claim === 'unknown')
|
|
466
|
+
return 'partial';
|
|
467
|
+
if (claim === 'cleanup_verified' || cleanupChecked)
|
|
468
|
+
return 'proven';
|
|
469
|
+
if (claim === 'observed' || claim === 'stopped' || claim === 'started')
|
|
470
|
+
return 'verified';
|
|
471
|
+
return 'partial';
|
|
472
|
+
}
|
|
356
473
|
function evidenceRow(kind, value, truth) {
|
|
357
474
|
return { kind, value: String(value || ''), truth };
|
|
358
475
|
}
|
package/package.json
CHANGED
package/references/ueye-proof.md
CHANGED
|
@@ -26,12 +26,32 @@ Ueye is one route. It should not split into separate lite/deep skills. Use these
|
|
|
26
26
|
```bash
|
|
27
27
|
yam ueye capture --url http://localhost:3000 --out .yam/screens/home.png
|
|
28
28
|
yam ueye compare --reference ./reference.png --actual .yam/screens/home.png --json
|
|
29
|
+
yam ueye report --reference ./reference.png --actual .yam/screens/home.png --design-quality needs-polish --json
|
|
29
30
|
```
|
|
30
31
|
|
|
31
32
|
- `capture` uses a Playwright install from the current project when present, then reports `blocked` instead of installing dependencies or pretending a screenshot exists.
|
|
32
33
|
- `compare` is local-only and dependency-free. It records hashes, dimensions, comparison result, and visual provenance. Different screenshots stay `partial`; exact file matches can be `verified`.
|
|
34
|
+
- `report` records the Ueye run as reference sources, implementation sources, comparison result, design quality, blocked reason, next action, and truth status.
|
|
33
35
|
- Without capture or user-provided screenshots, report implementation/source review separately from visual verification and cap the visual claim.
|
|
34
36
|
|
|
37
|
+
### Media Generation Proof
|
|
38
|
+
|
|
39
|
+
Generated media can help with direction and visual ideation, but it is derivative evidence. It cannot prove that the implemented UI was captured or compared.
|
|
40
|
+
|
|
41
|
+
```bash
|
|
42
|
+
yam media proof --requested --attempted --output ./generated.png --wait-loop --json
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
Record:
|
|
46
|
+
|
|
47
|
+
- tool name, when relevant
|
|
48
|
+
- whether generation was requested
|
|
49
|
+
- whether generation was attempted
|
|
50
|
+
- output path and hash, when a local image exists
|
|
51
|
+
- whether the wait loop was checked
|
|
52
|
+
- blocked reason and next action
|
|
53
|
+
- truth status
|
|
54
|
+
|
|
35
55
|
### Browser Preference
|
|
36
56
|
|
|
37
57
|
- Prefer the Codex in-app Browser plugin for local pages, localhost, file URLs, and ordinary visual QA.
|
package/skills/ueye/SKILL.md
CHANGED
|
@@ -36,6 +36,8 @@ Do not use for:
|
|
|
36
36
|
- Image evidence should stay bounded: inspect the primary screen first, then only the states/images needed to support the claim.
|
|
37
37
|
- Design quality judgment belongs after implementation/review: compare to the reference first, then judge whether the result is good design.
|
|
38
38
|
- Keep Ueye as one route: start fast, then opt into `yam ueye capture` and `yam ueye compare` only when a `verified` visual claim needs real screen evidence.
|
|
39
|
+
- Use `yam ueye report` when reference, implementation screenshot, comparison result, design quality, and next action should be recorded as one compact run report.
|
|
40
|
+
- Generated media can guide direction, but it cannot verify the implemented screen without implementation screenshot evidence.
|
|
39
41
|
- Prefer the Codex in-app Browser plugin for interactive visual checks. Do not switch to the user's Chrome browser unless the user explicitly asks for Chrome or the task requires existing Chrome cookies, sessions, extensions, or profile state.
|
|
40
42
|
|
|
41
43
|
## Workflow
|
|
@@ -58,6 +60,7 @@ Do not use for:
|
|
|
58
60
|
- Do not silently use Chrome as a fallback. If the in-app Browser cannot capture or inspect, report the visual cap as `partial` or `blocked`.
|
|
59
61
|
- Use `yam ueye capture --url URL --out path.png` when a local Playwright install is available and the claim needs real browser evidence.
|
|
60
62
|
- Use `yam ueye compare --reference ref.png --actual shot.png` when reference fidelity needs a proof-ready local comparison record.
|
|
63
|
+
- Use `yam ueye report --reference ref.png --actual shot.png --design-quality needs-polish --json` to preserve the run-level visual provenance and next action.
|
|
61
64
|
9. Compare reference and implementation when reference fidelity was requested:
|
|
62
65
|
- matched, similar, different, not-applicable, or not-verified.
|
|
63
66
|
- Separate "faithful to reference" from "good design."
|
|
@@ -95,6 +98,10 @@ Use these artifacts for reference-led implementation or serious visual review. K
|
|
|
95
98
|
5. Design Quality Review:
|
|
96
99
|
- judge whether the result is good UI/UX/design after reference comparison.
|
|
97
100
|
- use pass, needs-polish, or fails for each relevant design dimension.
|
|
101
|
+
6. Media Generation Proof, when generated images are part of the task:
|
|
102
|
+
- record whether generation was requested, attempted, blocked, or produced an output.
|
|
103
|
+
- use `yam media proof --requested --attempted --output path.png --wait-loop --json` when a generated image materially affects the design direction.
|
|
104
|
+
- never use generated media proof as a substitute for implemented screen evidence.
|
|
98
105
|
|
|
99
106
|
## Visual Truth Caps
|
|
100
107
|
|