yam-flow 0.1.7 → 0.1.8
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 +27 -0
- package/COMMANDS.md +6 -1
- package/README.md +9 -1
- package/dist/bin/yam.js +272 -10
- package/dist/lib/trust-kernel.d.ts +42 -0
- package/dist/lib/trust-kernel.js +154 -0
- package/package.json +1 -1
- package/src/bin/yam.ts +283 -11
- package/src/lib/trust-kernel.ts +188 -0
- package/yam.manifest.json +3 -2
package/src/lib/trust-kernel.ts
CHANGED
|
@@ -17,6 +17,8 @@ export type EvidenceKind = 'command' | 'evidence' | 'visual' | 'runtime' | 'skip
|
|
|
17
17
|
export type RuntimeSubsystem = 'real_runtime' | 'tmux_physical' | 'process_cleanup' | 'browser_visual' | 'db_safety';
|
|
18
18
|
export type RuntimeBackend = 'none' | 'in_app_browser' | 'playwright' | 'terminal' | 'tmux' | 'zellij' | 'unknown';
|
|
19
19
|
export type RuntimeClaim = 'not_started' | 'started' | 'observed' | 'stopped' | 'cleanup_verified' | 'blocked' | 'unknown';
|
|
20
|
+
export type LoopStageStatus = 'passed' | 'failed' | 'blocked' | 'skipped' | 'partial' | 'pending' | 'recorded';
|
|
21
|
+
export type ToolIntent = 'read_only' | 'write' | 'destructive' | 'runtime' | 'visual' | 'publish';
|
|
20
22
|
|
|
21
23
|
export interface SafetyHit {
|
|
22
24
|
level: SafetyLevel;
|
|
@@ -149,6 +151,48 @@ export interface RuntimeBackendEvidence {
|
|
|
149
151
|
truth_status: TruthStatus;
|
|
150
152
|
}
|
|
151
153
|
|
|
154
|
+
export interface StudyNoteSection {
|
|
155
|
+
code: string;
|
|
156
|
+
role: string;
|
|
157
|
+
symptom?: string;
|
|
158
|
+
summary?: string;
|
|
159
|
+
truth_status: TruthStatus;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
export interface StudyNote {
|
|
163
|
+
schema: 'yam.study-note.v1';
|
|
164
|
+
problem: StudyNoteSection;
|
|
165
|
+
change: StudyNoteSection;
|
|
166
|
+
why_it_matters: string;
|
|
167
|
+
learning_note: string;
|
|
168
|
+
limits: string[];
|
|
169
|
+
truth_status: TruthStatus;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
export interface LoopStage {
|
|
173
|
+
id: string;
|
|
174
|
+
status: LoopStageStatus;
|
|
175
|
+
note: string;
|
|
176
|
+
truth_status: TruthStatus;
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
export interface LoopReport {
|
|
180
|
+
schema: 'yam.loop-report.v1';
|
|
181
|
+
generated_at: string;
|
|
182
|
+
route: string;
|
|
183
|
+
intent: string;
|
|
184
|
+
loop_kind: string;
|
|
185
|
+
stages: LoopStage[];
|
|
186
|
+
evidence: string[];
|
|
187
|
+
blockers: string[];
|
|
188
|
+
truth_status: TruthStatus;
|
|
189
|
+
intent_label: ToolIntent;
|
|
190
|
+
tool_intent: ToolIntent;
|
|
191
|
+
next_action: string;
|
|
192
|
+
remaining_tasks: string[];
|
|
193
|
+
study_note: StudyNote;
|
|
194
|
+
}
|
|
195
|
+
|
|
152
196
|
export interface UeyeRunReport {
|
|
153
197
|
schema: 'yam.ueye-run-report.v1';
|
|
154
198
|
reference_sources: UeyeVisualProvenance[];
|
|
@@ -452,6 +496,72 @@ export function buildRuntimeBackendEvidence(input: Partial<RuntimeBackendEvidenc
|
|
|
452
496
|
};
|
|
453
497
|
}
|
|
454
498
|
|
|
499
|
+
export function buildStudyNote(input: Partial<StudyNote> & Record<string, unknown> = {}): StudyNote {
|
|
500
|
+
const problem = buildStudyNoteSection(input.problem, {
|
|
501
|
+
code: input.issue_code,
|
|
502
|
+
role: input.issue_role,
|
|
503
|
+
symptom: input.issue_symptom
|
|
504
|
+
}, 'problem');
|
|
505
|
+
const change = buildStudyNoteSection(input.change, {
|
|
506
|
+
code: input.changed_code,
|
|
507
|
+
role: input.changed_role,
|
|
508
|
+
summary: input.change_summary
|
|
509
|
+
}, 'change');
|
|
510
|
+
const whyItMatters = shortText(input.why_it_matters || input.why_important);
|
|
511
|
+
const learningNote = shortText(input.learning_note);
|
|
512
|
+
const limits = [
|
|
513
|
+
...asList(input.limits),
|
|
514
|
+
...missingStudyNoteLimits(problem, change, whyItMatters, learningNote)
|
|
515
|
+
];
|
|
516
|
+
const hasProblem = Boolean(problem.code || problem.role || problem.symptom);
|
|
517
|
+
const hasChange = Boolean(change.code || change.role || change.summary);
|
|
518
|
+
const truth: TruthStatus = isTruthStatus(input.truth_status) ? input.truth_status
|
|
519
|
+
: hasProblem || hasChange || whyItMatters || learningNote ? 'partial'
|
|
520
|
+
: 'assumed';
|
|
521
|
+
return {
|
|
522
|
+
schema: 'yam.study-note.v1',
|
|
523
|
+
problem,
|
|
524
|
+
change,
|
|
525
|
+
why_it_matters: whyItMatters,
|
|
526
|
+
learning_note: learningNote,
|
|
527
|
+
limits: [...new Set(limits)],
|
|
528
|
+
truth_status: truth
|
|
529
|
+
};
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
export function buildLoopReport(input: Partial<LoopReport> & Record<string, unknown> = {}): LoopReport {
|
|
533
|
+
const stages = Array.isArray(input.stages)
|
|
534
|
+
? input.stages.map((stage) => buildLoopStage(stage))
|
|
535
|
+
: [];
|
|
536
|
+
const evidence = asList(input.evidence);
|
|
537
|
+
const blockers = asList(input.blockers || input.blocked);
|
|
538
|
+
const hasBlockedStage = stages.some((stage) => stage.status === 'blocked' || stage.status === 'failed');
|
|
539
|
+
const requestedTruth = isTruthStatus(input.truth_status) ? input.truth_status : '';
|
|
540
|
+
const derivedTruth: TruthStatus = blockers.length || hasBlockedStage ? 'blocked'
|
|
541
|
+
: evidence.length && stages.some((stage) => stage.status === 'passed') ? 'verified'
|
|
542
|
+
: evidence.length || stages.length ? 'partial'
|
|
543
|
+
: 'assumed';
|
|
544
|
+
const truth = requestedTruth ? weakestTruth(requestedTruth, derivedTruth) : derivedTruth;
|
|
545
|
+
const studyNote = buildStudyNote(input.study_note && typeof input.study_note === 'object' ? input.study_note as unknown as Record<string, unknown> : input);
|
|
546
|
+
const intentLabel = normalizeToolIntentLabel(input.intent_label || input.tool_intent);
|
|
547
|
+
return {
|
|
548
|
+
schema: 'yam.loop-report.v1',
|
|
549
|
+
generated_at: String(input.generated_at || new Date().toISOString()),
|
|
550
|
+
route: String(input.route || ''),
|
|
551
|
+
intent: shortText(input.intent),
|
|
552
|
+
loop_kind: String(input.loop_kind || 'harness'),
|
|
553
|
+
stages,
|
|
554
|
+
evidence,
|
|
555
|
+
blockers,
|
|
556
|
+
truth_status: truth,
|
|
557
|
+
intent_label: intentLabel,
|
|
558
|
+
tool_intent: intentLabel,
|
|
559
|
+
next_action: shortText(input.next_action || (blockers[0] ? 'resolve the blocker before claiming this loop complete' : 'record the next smallest useful action')),
|
|
560
|
+
remaining_tasks: asList(input.remaining_tasks || input.remaining_task),
|
|
561
|
+
study_note: studyNote
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
|
|
455
565
|
export function buildUeyeRunReport(input: UeyeRunReportInput = {}): UeyeRunReport {
|
|
456
566
|
const references = Array.isArray(input.reference_sources)
|
|
457
567
|
? input.reference_sources.map((item) => buildUeyeVisualProvenance(item))
|
|
@@ -494,6 +604,84 @@ export function buildUeyeRunReport(input: UeyeRunReportInput = {}): UeyeRunRepor
|
|
|
494
604
|
};
|
|
495
605
|
}
|
|
496
606
|
|
|
607
|
+
function buildStudyNoteSection(section: unknown, fallback: Record<string, unknown>, kind: 'problem' | 'change'): StudyNoteSection {
|
|
608
|
+
const source = section && typeof section === 'object' ? section as Record<string, unknown> : fallback;
|
|
609
|
+
const code = shortText(source.code);
|
|
610
|
+
const role = shortText(source.role);
|
|
611
|
+
const symptom = kind === 'problem' ? shortText(source.symptom) : undefined;
|
|
612
|
+
const summary = kind === 'change' ? shortText(source.summary) : undefined;
|
|
613
|
+
return {
|
|
614
|
+
code,
|
|
615
|
+
role,
|
|
616
|
+
...(symptom !== undefined ? { symptom } : {}),
|
|
617
|
+
...(summary !== undefined ? { summary } : {}),
|
|
618
|
+
truth_status: code || role || symptom || summary ? 'partial' : 'assumed'
|
|
619
|
+
};
|
|
620
|
+
}
|
|
621
|
+
|
|
622
|
+
function missingStudyNoteLimits(problem: StudyNoteSection, change: StudyNoteSection, whyItMatters = '', learningNote = ''): string[] {
|
|
623
|
+
const limits: string[] = [];
|
|
624
|
+
if (!problem.code) limits.push('issue_code not provided');
|
|
625
|
+
if (!problem.role) limits.push('issue_role not provided');
|
|
626
|
+
if (!problem.symptom) limits.push('issue_symptom not provided');
|
|
627
|
+
if (!change.code) limits.push('changed_code not provided');
|
|
628
|
+
if (!change.role) limits.push('changed_role not provided');
|
|
629
|
+
if (!change.summary) limits.push('change_summary not provided');
|
|
630
|
+
if (!whyItMatters) limits.push('why_it_matters not provided');
|
|
631
|
+
if (!learningNote) limits.push('learning_note not provided');
|
|
632
|
+
return limits;
|
|
633
|
+
}
|
|
634
|
+
|
|
635
|
+
function buildLoopStage(value: unknown = ''): LoopStage {
|
|
636
|
+
if (value && typeof value === 'object') {
|
|
637
|
+
const item = value as Partial<LoopStage>;
|
|
638
|
+
return loopStage(String(item.id || ''), item.status, String(item.note || ''));
|
|
639
|
+
}
|
|
640
|
+
const [id = '', rawStatus = '', ...noteParts] = String(value || '').split(':');
|
|
641
|
+
return loopStage(id, rawStatus, noteParts.join(':'));
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
function loopStage(id = '', rawStatus: unknown = '', note = ''): LoopStage {
|
|
645
|
+
const status = normalizeLoopStageStatus(rawStatus);
|
|
646
|
+
return {
|
|
647
|
+
id: shortText(id || 'stage'),
|
|
648
|
+
status,
|
|
649
|
+
note: shortText(note),
|
|
650
|
+
truth_status: stageTruth(status)
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
|
|
654
|
+
function normalizeLoopStageStatus(value: unknown = ''): LoopStageStatus {
|
|
655
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
656
|
+
if (text === 'pass' || text === 'passed' || text === 'ok') return 'passed';
|
|
657
|
+
if (text === 'fail' || text === 'failed' || text === 'error') return 'failed';
|
|
658
|
+
if (text === 'block' || text === 'blocked') return 'blocked';
|
|
659
|
+
if (text === 'skip' || text === 'skipped') return 'skipped';
|
|
660
|
+
if (text === 'partial') return 'partial';
|
|
661
|
+
if (text === 'pending') return 'pending';
|
|
662
|
+
return 'recorded';
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
function stageTruth(status: LoopStageStatus): TruthStatus {
|
|
666
|
+
if (status === 'passed') return 'verified';
|
|
667
|
+
if (status === 'failed' || status === 'blocked') return 'blocked';
|
|
668
|
+
if (status === 'skipped') return 'skipped';
|
|
669
|
+
if (status === 'pending') return 'assumed';
|
|
670
|
+
return 'partial';
|
|
671
|
+
}
|
|
672
|
+
|
|
673
|
+
function normalizeToolIntentLabel(value: unknown = ''): ToolIntent {
|
|
674
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
675
|
+
if (['read_only', 'write', 'destructive', 'runtime', 'visual', 'publish'].includes(text)) return text as ToolIntent;
|
|
676
|
+
return 'read_only';
|
|
677
|
+
}
|
|
678
|
+
|
|
679
|
+
function shortText(value: unknown = '', limit = 240): string {
|
|
680
|
+
const text = String(value || '').trim().replace(/\s+/g, ' ');
|
|
681
|
+
if (text.length <= limit) return text;
|
|
682
|
+
return `${text.slice(0, limit - 3)}...`;
|
|
683
|
+
}
|
|
684
|
+
|
|
497
685
|
export function buildMediaGenerationProof(input: Partial<MediaGenerationProof> = {}): MediaGenerationProof {
|
|
498
686
|
const requested = Boolean(input.generation_requested);
|
|
499
687
|
const attempted = Boolean(input.generation_attempted);
|
package/yam.manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yam",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.8",
|
|
4
4
|
"principles": [
|
|
5
5
|
"Direction before execution.",
|
|
6
6
|
"Start fast.",
|
|
@@ -10,7 +10,8 @@
|
|
|
10
10
|
"Heavy proof when risk or user intent calls for it.",
|
|
11
11
|
"Token-aware by default.",
|
|
12
12
|
"Context-reuse first.",
|
|
13
|
-
"End with remaining tasks and fix-first items."
|
|
13
|
+
"End with remaining tasks and fix-first items.",
|
|
14
|
+
"Explain what failed, what changed, and why it matters in short non-specialist language when useful."
|
|
14
15
|
],
|
|
15
16
|
"defaultHooks": false,
|
|
16
17
|
"routes": [
|