yam-flow 0.1.7 → 0.1.9
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 +50 -0
- package/COMMANDS.md +6 -1
- package/README.md +9 -1
- package/dist/bin/yam.js +278 -10
- package/dist/lib/trust-kernel.d.ts +48 -0
- package/dist/lib/trust-kernel.js +166 -0
- package/package.json +1 -1
- package/references/final-report.md +26 -0
- package/skills/deep/SKILL.md +2 -2
- package/skills/mission/SKILL.md +2 -2
- package/skills/quick/SKILL.md +2 -1
- package/skills/ueye/SKILL.md +2 -1
- package/src/bin/yam.ts +289 -11
- package/src/lib/trust-kernel.ts +206 -0
- package/yam.manifest.json +4 -2
|
@@ -5,6 +5,8 @@ export type EvidenceKind = 'command' | 'evidence' | 'visual' | 'runtime' | 'skip
|
|
|
5
5
|
export type RuntimeSubsystem = 'real_runtime' | 'tmux_physical' | 'process_cleanup' | 'browser_visual' | 'db_safety';
|
|
6
6
|
export type RuntimeBackend = 'none' | 'in_app_browser' | 'playwright' | 'terminal' | 'tmux' | 'zellij' | 'unknown';
|
|
7
7
|
export type RuntimeClaim = 'not_started' | 'started' | 'observed' | 'stopped' | 'cleanup_verified' | 'blocked' | 'unknown';
|
|
8
|
+
export type LoopStageStatus = 'passed' | 'failed' | 'blocked' | 'skipped' | 'partial' | 'pending' | 'recorded';
|
|
9
|
+
export type ToolIntent = 'read_only' | 'write' | 'destructive' | 'runtime' | 'visual' | 'publish';
|
|
8
10
|
export interface SafetyHit {
|
|
9
11
|
level: SafetyLevel;
|
|
10
12
|
reason: string;
|
|
@@ -124,6 +126,50 @@ export interface RuntimeBackendEvidence {
|
|
|
124
126
|
note: string;
|
|
125
127
|
truth_status: TruthStatus;
|
|
126
128
|
}
|
|
129
|
+
export interface StudyNoteSection {
|
|
130
|
+
code: string;
|
|
131
|
+
role: string;
|
|
132
|
+
symptom?: string;
|
|
133
|
+
summary?: string;
|
|
134
|
+
truth_status: TruthStatus;
|
|
135
|
+
}
|
|
136
|
+
export interface StudyNote {
|
|
137
|
+
schema: 'yam.study-note.v1';
|
|
138
|
+
problem: StudyNoteSection;
|
|
139
|
+
change: StudyNoteSection;
|
|
140
|
+
why_it_matters: string;
|
|
141
|
+
learning_note: string;
|
|
142
|
+
limits: string[];
|
|
143
|
+
truth_status: TruthStatus;
|
|
144
|
+
}
|
|
145
|
+
export interface LoopStage {
|
|
146
|
+
id: string;
|
|
147
|
+
status: LoopStageStatus;
|
|
148
|
+
note: string;
|
|
149
|
+
truth_status: TruthStatus;
|
|
150
|
+
}
|
|
151
|
+
export interface LoopReport {
|
|
152
|
+
schema: 'yam.loop-report.v1';
|
|
153
|
+
generated_at: string;
|
|
154
|
+
route: string;
|
|
155
|
+
intent: string;
|
|
156
|
+
loop_kind: string;
|
|
157
|
+
stages: LoopStage[];
|
|
158
|
+
evidence: string[];
|
|
159
|
+
blockers: string[];
|
|
160
|
+
truth_status: TruthStatus;
|
|
161
|
+
intent_label: ToolIntent;
|
|
162
|
+
tool_intent: ToolIntent;
|
|
163
|
+
next_action: string;
|
|
164
|
+
fix_first_items: string[];
|
|
165
|
+
remaining_tasks: string[];
|
|
166
|
+
recommended_direction: string;
|
|
167
|
+
implementation_notes: string[];
|
|
168
|
+
why_this_next: string;
|
|
169
|
+
blocked_by: string[];
|
|
170
|
+
owner_route: string;
|
|
171
|
+
study_note: StudyNote;
|
|
172
|
+
}
|
|
127
173
|
export interface UeyeRunReport {
|
|
128
174
|
schema: 'yam.ueye-run-report.v1';
|
|
129
175
|
reference_sources: UeyeVisualProvenance[];
|
|
@@ -230,6 +276,8 @@ export declare function buildUeyeDesignCompletionGate(input?: Partial<UeyeDesign
|
|
|
230
276
|
export declare function buildRollbackHint(input?: Partial<RollbackHint>): RollbackHint;
|
|
231
277
|
export declare function buildMissionPatchEnvelope(input?: Partial<MissionPatchEnvelope>): MissionPatchEnvelope;
|
|
232
278
|
export declare function buildRuntimeBackendEvidence(input?: Partial<RuntimeBackendEvidence>): RuntimeBackendEvidence;
|
|
279
|
+
export declare function buildStudyNote(input?: Partial<StudyNote> & Record<string, unknown>): StudyNote;
|
|
280
|
+
export declare function buildLoopReport(input?: Partial<LoopReport> & Record<string, unknown>): LoopReport;
|
|
233
281
|
export declare function buildUeyeRunReport(input?: UeyeRunReportInput): UeyeRunReport;
|
|
234
282
|
export declare function buildMediaGenerationProof(input?: Partial<MediaGenerationProof>): MediaGenerationProof;
|
|
235
283
|
export declare function isTruthStatus(value?: unknown): value is TruthStatus;
|
package/dist/lib/trust-kernel.js
CHANGED
|
@@ -199,6 +199,76 @@ export function buildRuntimeBackendEvidence(input = {}) {
|
|
|
199
199
|
})
|
|
200
200
|
};
|
|
201
201
|
}
|
|
202
|
+
export function buildStudyNote(input = {}) {
|
|
203
|
+
const problem = buildStudyNoteSection(input.problem, {
|
|
204
|
+
code: input.issue_code,
|
|
205
|
+
role: input.issue_role,
|
|
206
|
+
symptom: input.issue_symptom
|
|
207
|
+
}, 'problem');
|
|
208
|
+
const change = buildStudyNoteSection(input.change, {
|
|
209
|
+
code: input.changed_code,
|
|
210
|
+
role: input.changed_role,
|
|
211
|
+
summary: input.change_summary
|
|
212
|
+
}, 'change');
|
|
213
|
+
const whyItMatters = shortText(input.why_it_matters || input.why_important);
|
|
214
|
+
const learningNote = shortText(input.learning_note);
|
|
215
|
+
const limits = [
|
|
216
|
+
...asList(input.limits),
|
|
217
|
+
...missingStudyNoteLimits(problem, change, whyItMatters, learningNote)
|
|
218
|
+
];
|
|
219
|
+
const hasProblem = Boolean(problem.code || problem.role || problem.symptom);
|
|
220
|
+
const hasChange = Boolean(change.code || change.role || change.summary);
|
|
221
|
+
const truth = isTruthStatus(input.truth_status) ? input.truth_status
|
|
222
|
+
: hasProblem || hasChange || whyItMatters || learningNote ? 'partial'
|
|
223
|
+
: 'assumed';
|
|
224
|
+
return {
|
|
225
|
+
schema: 'yam.study-note.v1',
|
|
226
|
+
problem,
|
|
227
|
+
change,
|
|
228
|
+
why_it_matters: whyItMatters,
|
|
229
|
+
learning_note: learningNote,
|
|
230
|
+
limits: [...new Set(limits)],
|
|
231
|
+
truth_status: truth
|
|
232
|
+
};
|
|
233
|
+
}
|
|
234
|
+
export function buildLoopReport(input = {}) {
|
|
235
|
+
const stages = Array.isArray(input.stages)
|
|
236
|
+
? input.stages.map((stage) => buildLoopStage(stage))
|
|
237
|
+
: [];
|
|
238
|
+
const evidence = asList(input.evidence);
|
|
239
|
+
const blockers = asList(input.blockers || input.blocked);
|
|
240
|
+
const hasBlockedStage = stages.some((stage) => stage.status === 'blocked' || stage.status === 'failed');
|
|
241
|
+
const requestedTruth = isTruthStatus(input.truth_status) ? input.truth_status : '';
|
|
242
|
+
const derivedTruth = blockers.length || hasBlockedStage ? 'blocked'
|
|
243
|
+
: evidence.length && stages.some((stage) => stage.status === 'passed') ? 'verified'
|
|
244
|
+
: evidence.length || stages.length ? 'partial'
|
|
245
|
+
: 'assumed';
|
|
246
|
+
const truth = requestedTruth ? weakestTruth(requestedTruth, derivedTruth) : derivedTruth;
|
|
247
|
+
const studyNote = buildStudyNote(input.study_note && typeof input.study_note === 'object' ? input.study_note : input);
|
|
248
|
+
const intentLabel = normalizeToolIntentLabel(input.intent_label || input.tool_intent);
|
|
249
|
+
return {
|
|
250
|
+
schema: 'yam.loop-report.v1',
|
|
251
|
+
generated_at: String(input.generated_at || new Date().toISOString()),
|
|
252
|
+
route: String(input.route || ''),
|
|
253
|
+
intent: shortText(input.intent),
|
|
254
|
+
loop_kind: String(input.loop_kind || 'harness'),
|
|
255
|
+
stages,
|
|
256
|
+
evidence,
|
|
257
|
+
blockers,
|
|
258
|
+
truth_status: truth,
|
|
259
|
+
intent_label: intentLabel,
|
|
260
|
+
tool_intent: intentLabel,
|
|
261
|
+
next_action: shortText(input.next_action || (blockers[0] ? 'resolve the blocker before claiming this loop complete' : 'record the next smallest useful action')),
|
|
262
|
+
fix_first_items: asList(input.fix_first_items || input.fix_first_item),
|
|
263
|
+
remaining_tasks: asList(input.remaining_tasks || input.remaining_task),
|
|
264
|
+
recommended_direction: shortText(input.recommended_direction || input.direction),
|
|
265
|
+
implementation_notes: asList(input.implementation_notes || input.implementation_note),
|
|
266
|
+
why_this_next: shortText(input.why_this_next),
|
|
267
|
+
blocked_by: asList(input.blocked_by),
|
|
268
|
+
owner_route: normalizeOwnerRoute(input.owner_route || input.route),
|
|
269
|
+
study_note: studyNote
|
|
270
|
+
};
|
|
271
|
+
}
|
|
202
272
|
export function buildUeyeRunReport(input = {}) {
|
|
203
273
|
const references = Array.isArray(input.reference_sources)
|
|
204
274
|
? input.reference_sources.map((item) => buildUeyeVisualProvenance(item))
|
|
@@ -240,6 +310,102 @@ export function buildUeyeRunReport(input = {}) {
|
|
|
240
310
|
truth_status: isTruthStatus(input.truth_status) ? input.truth_status : finalTruth
|
|
241
311
|
};
|
|
242
312
|
}
|
|
313
|
+
function buildStudyNoteSection(section, fallback, kind) {
|
|
314
|
+
const source = section && typeof section === 'object' ? section : fallback;
|
|
315
|
+
const code = shortText(source.code);
|
|
316
|
+
const role = shortText(source.role);
|
|
317
|
+
const symptom = kind === 'problem' ? shortText(source.symptom) : undefined;
|
|
318
|
+
const summary = kind === 'change' ? shortText(source.summary) : undefined;
|
|
319
|
+
return {
|
|
320
|
+
code,
|
|
321
|
+
role,
|
|
322
|
+
...(symptom !== undefined ? { symptom } : {}),
|
|
323
|
+
...(summary !== undefined ? { summary } : {}),
|
|
324
|
+
truth_status: code || role || symptom || summary ? 'partial' : 'assumed'
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
function missingStudyNoteLimits(problem, change, whyItMatters = '', learningNote = '') {
|
|
328
|
+
const limits = [];
|
|
329
|
+
if (!problem.code)
|
|
330
|
+
limits.push('issue_code not provided');
|
|
331
|
+
if (!problem.role)
|
|
332
|
+
limits.push('issue_role not provided');
|
|
333
|
+
if (!problem.symptom)
|
|
334
|
+
limits.push('issue_symptom not provided');
|
|
335
|
+
if (!change.code)
|
|
336
|
+
limits.push('changed_code not provided');
|
|
337
|
+
if (!change.role)
|
|
338
|
+
limits.push('changed_role not provided');
|
|
339
|
+
if (!change.summary)
|
|
340
|
+
limits.push('change_summary not provided');
|
|
341
|
+
if (!whyItMatters)
|
|
342
|
+
limits.push('why_it_matters not provided');
|
|
343
|
+
if (!learningNote)
|
|
344
|
+
limits.push('learning_note not provided');
|
|
345
|
+
return limits;
|
|
346
|
+
}
|
|
347
|
+
function buildLoopStage(value = '') {
|
|
348
|
+
if (value && typeof value === 'object') {
|
|
349
|
+
const item = value;
|
|
350
|
+
return loopStage(String(item.id || ''), item.status, String(item.note || ''));
|
|
351
|
+
}
|
|
352
|
+
const [id = '', rawStatus = '', ...noteParts] = String(value || '').split(':');
|
|
353
|
+
return loopStage(id, rawStatus, noteParts.join(':'));
|
|
354
|
+
}
|
|
355
|
+
function loopStage(id = '', rawStatus = '', note = '') {
|
|
356
|
+
const status = normalizeLoopStageStatus(rawStatus);
|
|
357
|
+
return {
|
|
358
|
+
id: shortText(id || 'stage'),
|
|
359
|
+
status,
|
|
360
|
+
note: shortText(note),
|
|
361
|
+
truth_status: stageTruth(status)
|
|
362
|
+
};
|
|
363
|
+
}
|
|
364
|
+
function normalizeLoopStageStatus(value = '') {
|
|
365
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
366
|
+
if (text === 'pass' || text === 'passed' || text === 'ok')
|
|
367
|
+
return 'passed';
|
|
368
|
+
if (text === 'fail' || text === 'failed' || text === 'error')
|
|
369
|
+
return 'failed';
|
|
370
|
+
if (text === 'block' || text === 'blocked')
|
|
371
|
+
return 'blocked';
|
|
372
|
+
if (text === 'skip' || text === 'skipped')
|
|
373
|
+
return 'skipped';
|
|
374
|
+
if (text === 'partial')
|
|
375
|
+
return 'partial';
|
|
376
|
+
if (text === 'pending')
|
|
377
|
+
return 'pending';
|
|
378
|
+
return 'recorded';
|
|
379
|
+
}
|
|
380
|
+
function stageTruth(status) {
|
|
381
|
+
if (status === 'passed')
|
|
382
|
+
return 'verified';
|
|
383
|
+
if (status === 'failed' || status === 'blocked')
|
|
384
|
+
return 'blocked';
|
|
385
|
+
if (status === 'skipped')
|
|
386
|
+
return 'skipped';
|
|
387
|
+
if (status === 'pending')
|
|
388
|
+
return 'assumed';
|
|
389
|
+
return 'partial';
|
|
390
|
+
}
|
|
391
|
+
function normalizeToolIntentLabel(value = '') {
|
|
392
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
393
|
+
if (['read_only', 'write', 'destructive', 'runtime', 'visual', 'publish'].includes(text))
|
|
394
|
+
return text;
|
|
395
|
+
return 'read_only';
|
|
396
|
+
}
|
|
397
|
+
function normalizeOwnerRoute(value = '') {
|
|
398
|
+
const text = String(value || '').trim().replace(/^\$/, '').replace(/^yam-/, '');
|
|
399
|
+
if (['quick', 'ueye', 'question', 'scout', 'deep', 'mission'].includes(text))
|
|
400
|
+
return `$${text}`;
|
|
401
|
+
return text ? shortText(text, 80) : '';
|
|
402
|
+
}
|
|
403
|
+
function shortText(value = '', limit = 240) {
|
|
404
|
+
const text = String(value || '').trim().replace(/\s+/g, ' ');
|
|
405
|
+
if (text.length <= limit)
|
|
406
|
+
return text;
|
|
407
|
+
return `${text.slice(0, limit - 3)}...`;
|
|
408
|
+
}
|
|
243
409
|
export function buildMediaGenerationProof(input = {}) {
|
|
244
410
|
const requested = Boolean(input.generation_requested);
|
|
245
411
|
const attempted = Boolean(input.generation_attempted);
|
package/package.json
CHANGED
|
@@ -16,8 +16,10 @@ Include these when they are useful and keep them short:
|
|
|
16
16
|
- Context pressure or cleanup findings when they could affect the next run.
|
|
17
17
|
- Publish blocker evidence when npm/release work fails.
|
|
18
18
|
- Structured diagnostic next action, when a check found a concrete next step.
|
|
19
|
+
- Study Note for implementation work: what code was wrong, what role it has, how the symptom showed up, what changed, and why it matters in short non-specialist language.
|
|
19
20
|
- Remaining tasks.
|
|
20
21
|
- Fix-first items before planned tasks.
|
|
22
|
+
- Recommended direction and why that next step matters when the handoff would otherwise be ambiguous.
|
|
21
23
|
|
|
22
24
|
## Anti-False-Completion Check
|
|
23
25
|
|
|
@@ -54,6 +56,30 @@ Examples:
|
|
|
54
56
|
- Active hooks or instruction files that conflict with the route.
|
|
55
57
|
- Warnings that keep obscuring real problems.
|
|
56
58
|
|
|
59
|
+
## Study Note
|
|
60
|
+
|
|
61
|
+
Use this when implementation changed code or fixed an error and the user would benefit from learning:
|
|
62
|
+
|
|
63
|
+
- What code had the issue.
|
|
64
|
+
- What role that code plays.
|
|
65
|
+
- How the issue showed up.
|
|
66
|
+
- What changed.
|
|
67
|
+
- Why the change matters.
|
|
68
|
+
|
|
69
|
+
Keep it short. If the information is not known, say so instead of inventing it.
|
|
70
|
+
|
|
71
|
+
## Handoff Direction
|
|
72
|
+
|
|
73
|
+
Use this when the next run needs a clear starting point:
|
|
74
|
+
|
|
75
|
+
- Fix-first items before planned work.
|
|
76
|
+
- Remaining tasks that still belong to the request or roadmap.
|
|
77
|
+
- Recommended direction.
|
|
78
|
+
- Why this next step matters.
|
|
79
|
+
- What is blocked, and by what.
|
|
80
|
+
|
|
81
|
+
`yam loop report` can record this as a handoff artifact with `fix_first_items`, `remaining_tasks`, `recommended_direction`, `implementation_notes`, `why_this_next`, `blocked_by`, and `owner_route`.
|
|
82
|
+
|
|
57
83
|
## Route Weight
|
|
58
84
|
|
|
59
85
|
For `$quick`, one short paragraph or a compact verification matrix is enough.
|
package/skills/deep/SKILL.md
CHANGED
|
@@ -70,8 +70,8 @@ Deep verification may include:
|
|
|
70
70
|
Include:
|
|
71
71
|
|
|
72
72
|
- What was changed or reviewed.
|
|
73
|
+
- Study Note for implementation work: what code was wrong, what role it has, how the symptom showed up, what changed, and why it matters in short non-specialist language.
|
|
73
74
|
- Evidence gathered.
|
|
74
75
|
- Truth status.
|
|
75
76
|
- Blockers or remaining risk.
|
|
76
|
-
-
|
|
77
|
-
- Fix-first items before planned tasks.
|
|
77
|
+
- Handoff: fix-first items, remaining tasks, recommended direction, and why that next step matters.
|
package/skills/mission/SKILL.md
CHANGED
|
@@ -102,8 +102,8 @@ Report:
|
|
|
102
102
|
|
|
103
103
|
- What the mission changed.
|
|
104
104
|
- Role/cross-verification summary.
|
|
105
|
+
- Study Note for implementation lanes: what code was wrong, what role it has, how the symptom showed up, what changed, and why it matters in short non-specialist language.
|
|
105
106
|
- Evidence gathered.
|
|
106
107
|
- Truth status.
|
|
107
108
|
- Cleanup status.
|
|
108
|
-
-
|
|
109
|
-
- Fix-first items before planned tasks.
|
|
109
|
+
- Handoff: fix-first items, remaining tasks, recommended direction, and why that next step matters.
|
package/skills/quick/SKILL.md
CHANGED
|
@@ -76,6 +76,7 @@ Use `references/token-budget-reporter.md` when a run needs measured budget feedb
|
|
|
76
76
|
Keep it compact:
|
|
77
77
|
|
|
78
78
|
- What changed or what the scan found.
|
|
79
|
+
- Study Note when useful: what code was wrong, what role it has, how the symptom showed up, what changed, and why it matters in short non-specialist language.
|
|
79
80
|
- What was checked.
|
|
80
81
|
- What was skipped, blocked, or still risky.
|
|
81
|
-
-
|
|
82
|
+
- Handoff when useful: fix-first items, remaining tasks, recommended direction, and why that next step matters.
|
package/skills/ueye/SKILL.md
CHANGED
|
@@ -170,5 +170,6 @@ Report:
|
|
|
170
170
|
- Review continuity/comparison result when this continues a prior Ueye run.
|
|
171
171
|
- P0-P3 issues or confirmation that no blockers were found.
|
|
172
172
|
- States/viewports checked.
|
|
173
|
+
- Study Note when UI implementation changed code: what UI code changed, what role it has, how the visible symptom appeared, and why the change matters in short non-specialist language.
|
|
173
174
|
- Truth status and visual verification cap.
|
|
174
|
-
-
|
|
175
|
+
- Handoff when useful: fix-first visual issues, remaining tasks, recommended direction, and why that next step matters.
|