yam-flow 0.1.9 → 1.9.1
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 +11 -0
- package/COMMANDS.md +2 -2
- package/README.md +2 -2
- package/dist/bin/yam.js +17 -2
- package/dist/lib/trust-kernel.d.ts +10 -0
- package/dist/lib/trust-kernel.js +25 -3
- package/package.json +1 -1
- package/references/final-report.md +4 -1
- package/skills/deep/SKILL.md +1 -1
- package/skills/mission/SKILL.md +1 -1
- package/skills/quick/SKILL.md +1 -1
- package/skills/ueye/SKILL.md +1 -1
- package/src/bin/yam.ts +18 -3
- package/src/lib/trust-kernel.ts +35 -3
- package/yam.manifest.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to yam-flow are documented here.
|
|
4
4
|
|
|
5
|
+
## v1.9.1 - 2026-06-19
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Extended `yam loop report --json` with guided stage conventions, `evidence_level`, `evidence_stamp`/`source_digest`, `blocked_kind`, `safe_retry`, `owner_scope`, `scope_owner`, and `side_effects` so the report can act as a clearer handoff artifact without adding a new command.
|
|
10
|
+
- Updated loop report smoke coverage to assert the new handoff fields.
|
|
11
|
+
|
|
12
|
+
### Improved
|
|
13
|
+
|
|
14
|
+
- Updated README, COMMANDS, final-report guidance, implementation skill final-response rules, and manifest principles to prefer fix-first handoff with evidence level, blocker kind, safe retry, and owner/scope clarity.
|
|
15
|
+
|
|
5
16
|
## v0.1.9 - 2026-06-18
|
|
6
17
|
|
|
7
18
|
### Added
|
package/COMMANDS.md
CHANGED
|
@@ -148,7 +148,7 @@ yam tools doctor /path/to/project
|
|
|
148
148
|
yam tools doctor /path/to/project --json
|
|
149
149
|
yam context pressure /path/to/project --json
|
|
150
150
|
yam cleanup scan /path/to/project --json
|
|
151
|
-
yam loop report --route quick --intent "fix release readiness" --stage "inspect:passed:read release report" --evidence "typecheck passed" --fix-first-item "npm auth must be verified before publish" --remaining-task "rerun release report after auth refresh" --recommended-direction "fix npm auth first, then publish manually" --implementation-note "keep loop report read-only" --why-this-next "auth blocks public release claims" --blocked-by "npm whoami E401" --owner-route deep --issue-code "src/bin/yam.ts release report" --issue-role "summarizes release readiness without publishing" --issue-symptom "npm auth failure needs clearer next action" --changed-code "yam loop report" --changed-role "records loop evidence and learning note" --change-summary "added a read-only loop artifact" --why-important "it helps users learn what changed without overclaiming verification" --learning-note "fix blockers before claiming done" --json
|
|
151
|
+
yam loop report --route quick --intent "fix release readiness" --stage "inspect:passed:read release report" --evidence "typecheck passed" --evidence-level local --evidence-stamp "sha256:release-report" --blocked-kind auth_blocked --safe-retry "retry after npm whoami succeeds" --fix-first-item "npm auth must be verified before publish" --remaining-task "rerun release report after auth refresh" --recommended-direction "fix npm auth first, then publish manually" --implementation-note "keep loop report read-only" --why-this-next "auth blocks public release claims" --blocked-by "npm whoami E401" --owner-route deep --owner-scope "release readiness only" --scope-owner deep --side-effect "no publish attempted" --issue-code "src/bin/yam.ts release report" --issue-role "summarizes release readiness without publishing" --issue-symptom "npm auth failure needs clearer next action" --changed-code "yam loop report" --changed-role "records loop evidence and learning note" --change-summary "added a read-only loop artifact" --why-important "it helps users learn what changed without overclaiming verification" --learning-note "fix blockers before claiming done" --json
|
|
152
152
|
yam proof /path/to/project
|
|
153
153
|
yam proof --route deep --truth verified --command "npm run build: pass"
|
|
154
154
|
yam proof --route ueye --truth verified --visual "reference image only"
|
|
@@ -195,7 +195,7 @@ Supported report shapes:
|
|
|
195
195
|
|
|
196
196
|
- Runtime evidence mini: command/process, observation, cleanup, truth status, next action.
|
|
197
197
|
- Patch queue lite: mission lane status, changed files, verification hint, rollback hint, truth status.
|
|
198
|
-
- Loop report: intent, stage outcomes, evidence, blockers, next action, fix-first items, remaining tasks, recommended direction, blocked-by notes, owner route, and study note.
|
|
198
|
+
- Loop report: intent, guided stage outcomes, evidence level/stamp, blockers, blocker kind, safe retry, next action, fix-first items, remaining tasks, recommended direction, blocked-by notes, owner route/scope, side effects, and study note.
|
|
199
199
|
- Study note: short non-specialist explanation of the failing code, its role, observed symptom, changed code, and why it matters.
|
|
200
200
|
- Benchmark optimization loop lite: baseline, one change, rerun, keep/revert decision.
|
|
201
201
|
- Structured diagnostic next action: severity, evidence, owner route, next action, truth status.
|
package/README.md
CHANGED
|
@@ -142,7 +142,7 @@ yam ueye report --reference ./reference.png --actual .yam/screens/home.png --pre
|
|
|
142
142
|
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"}'
|
|
143
143
|
yam media proof --requested --attempted --output ./generated.png --wait-loop --json
|
|
144
144
|
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"}'
|
|
145
|
-
yam loop report --route quick --intent "fix release readiness" --stage "inspect:passed:read release report" --evidence "typecheck passed" --fix-first-item "npm auth must be verified before publish" --remaining-task "rerun release report after auth refresh" --recommended-direction "fix npm auth first, then publish manually" --implementation-note "keep loop report read-only" --why-this-next "auth blocks public release claims" --blocked-by "npm whoami E401" --owner-route deep --issue-code "src/bin/yam.ts release report" --issue-role "summarizes release readiness without publishing" --issue-symptom "npm auth failure needs clearer next action" --changed-code "yam loop report" --changed-role "records loop evidence and learning note" --change-summary "added a read-only loop artifact" --why-important "it helps users learn what changed without overclaiming verification" --learning-note "fix blockers before claiming done" --json
|
|
145
|
+
yam loop report --route quick --intent "fix release readiness" --stage "inspect:passed:read release report" --evidence "typecheck passed" --evidence-level local --evidence-stamp "sha256:release-report" --blocked-kind auth_blocked --safe-retry "retry after npm whoami succeeds" --fix-first-item "npm auth must be verified before publish" --remaining-task "rerun release report after auth refresh" --recommended-direction "fix npm auth first, then publish manually" --implementation-note "keep loop report read-only" --why-this-next "auth blocks public release claims" --blocked-by "npm whoami E401" --owner-route deep --owner-scope "release readiness only" --scope-owner deep --side-effect "no publish attempted" --issue-code "src/bin/yam.ts release report" --issue-role "summarizes release readiness without publishing" --issue-symptom "npm auth failure needs clearer next action" --changed-code "yam loop report" --changed-role "records loop evidence and learning note" --change-summary "added a read-only loop artifact" --why-important "it helps users learn what changed without overclaiming verification" --learning-note "fix blockers before claiming done" --json
|
|
146
146
|
yam release report --json
|
|
147
147
|
yam safety "supabase db reset"
|
|
148
148
|
yam detect /path/to/project
|
|
@@ -216,7 +216,7 @@ These shapes keep reports machine-readable without turning normal work into a he
|
|
|
216
216
|
- Runtime evidence mini: compact route, command/process, observation, cleanup, truth status, and next action fields for `$deep` or `$mission` runtime claims.
|
|
217
217
|
- Patch queue lite: `$mission` lane records with pending/applied/verified/reverted/blocked state, changed files, verification hint, rollback hint, truth status, and next action.
|
|
218
218
|
- Release report JSON: `yam release report --json` summarizes typecheck, forbidden-name scan, package boundary, registry status, CLI smoke, dist freshness, diagnostics, and final truth status.
|
|
219
|
-
- Loop report JSON: `yam loop report --json` records a read-only handoff artifact:
|
|
219
|
+
- Loop report JSON: `yam loop report --json` records a read-only handoff artifact: guided stages, evidence level/stamp, blocker kind, safe retry, owner route/scope, side effects, next action, fix-first items, remaining tasks, recommended direction, implementation notes, blocked-by notes, tool intent, truth status, and study note.
|
|
220
220
|
- Study note: `yam.study-note.v1` keeps short non-specialist explanations for what code was failing, what role it plays, how the symptom showed up, what changed, and why it matters. Missing details stay in `limits` instead of being guessed.
|
|
221
221
|
- Publish blocker evidence: release reports classify common npm auth, permission, OTP, immutable-version, cache, registry, and tarball failures into safe next actions.
|
|
222
222
|
- Publish readiness evidence: release reports run read-only registry/auth/version probes, redact account/token details, and keep npm publish outside the report.
|
package/dist/bin/yam.js
CHANGED
|
@@ -524,6 +524,12 @@ function normalizeToolIntent(value = '') {
|
|
|
524
524
|
return text;
|
|
525
525
|
return 'read_only';
|
|
526
526
|
}
|
|
527
|
+
function normalizeLoopEvidenceLevelFlag(value = '') {
|
|
528
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
529
|
+
if (['fixture', 'smoke', 'local', 'real'].includes(text))
|
|
530
|
+
return text;
|
|
531
|
+
return 'none';
|
|
532
|
+
}
|
|
527
533
|
function uniqueNextActionDetails(actions = []) {
|
|
528
534
|
const seen = new Set();
|
|
529
535
|
const unique = [];
|
|
@@ -1973,24 +1979,30 @@ function loopUsage() {
|
|
|
1973
1979
|
Read-only loop artifact helpers. A loop report records intent, stages, evidence, blockers, next action, handoff fields, and a short study note. It does not run agents, start processes, publish packages, or write files.
|
|
1974
1980
|
|
|
1975
1981
|
Usage:
|
|
1976
|
-
yam loop report [--route route] [--intent text] [--loop-kind harness|release|ueye|scout|deep|mission] [--stage id:status:note] [--evidence text] [--blocked text] [--fix-first-item text] [--remaining-task text] [--recommended-direction text] [--implementation-note text] [--why-this-next text] [--blocked-by text] [--owner-route route] [--truth status] [--intent-label read_only|write|destructive|runtime|visual|publish] [--issue-code text] [--issue-role text] [--issue-symptom text] [--changed-code text] [--changed-role text] [--change-summary text] [--why-important text] [--learning-note text] [--json]
|
|
1982
|
+
yam loop report [--route route] [--intent text] [--loop-kind harness|release|ueye|scout|deep|mission] [--stage id:status:note] [--evidence text] [--evidence-level none|fixture|smoke|local|real] [--evidence-stamp text] [--source-digest text] [--blocked text] [--blocked-kind text] [--safe-retry text] [--fix-first-item text] [--remaining-task text] [--recommended-direction text] [--implementation-note text] [--why-this-next text] [--blocked-by text] [--owner-route route] [--owner-scope text] [--scope-owner text] [--side-effect text] [--truth status] [--intent-label read_only|write|destructive|runtime|visual|publish] [--issue-code text] [--issue-role text] [--issue-symptom text] [--changed-code text] [--changed-role text] [--change-summary text] [--why-important text] [--learning-note text] [--json]
|
|
1977
1983
|
`);
|
|
1978
1984
|
}
|
|
1979
1985
|
async function loopReport(args = []) {
|
|
1980
1986
|
if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h')
|
|
1981
1987
|
return loopUsage();
|
|
1982
|
-
const flags = parseSimpleFlags(args, new Set(['route', 'intent', 'loop-kind', 'stage', 'evidence', 'blocked', 'blocker', 'next-action', 'fix-first-item', 'remaining-task', 'recommended-direction', 'direction', 'implementation-note', 'why-this-next', 'blocked-by', 'owner-route', 'truth', 'intent-label', 'tool-intent', 'issue-code', 'issue-role', 'issue-symptom', 'changed-code', 'changed-role', 'change-summary', 'why-important', 'learning-note', 'json']));
|
|
1988
|
+
const flags = parseSimpleFlags(args, new Set(['route', 'intent', 'loop-kind', 'stage', 'stage-convention', 'evidence', 'evidence-level', 'evidence-stamp', 'source-digest', 'blocked', 'blocker', 'blocked-kind', 'next-action', 'safe-retry', 'fix-first-item', 'remaining-task', 'recommended-direction', 'direction', 'implementation-note', 'why-this-next', 'blocked-by', 'owner-route', 'owner-scope', 'scope-owner', 'owner', 'scope', 'side-effect', 'truth', 'intent-label', 'tool-intent', 'issue-code', 'issue-role', 'issue-symptom', 'changed-code', 'changed-role', 'change-summary', 'why-important', 'learning-note', 'json']));
|
|
1983
1989
|
const blockers = [...arrayFlag(flags.blocked), ...arrayFlag(flags.blocker)];
|
|
1984
1990
|
const report = buildLoopReport({
|
|
1985
1991
|
route: normalizeRoute(flags.route) || String(flags.route || ''),
|
|
1986
1992
|
intent: String(flags.intent || ''),
|
|
1987
1993
|
loop_kind: String(flags.loop_kind || flags.route || 'harness'),
|
|
1994
|
+
stage_conventions: arrayFlag(flags.stage_convention),
|
|
1988
1995
|
stages: arrayFlag(flags.stage),
|
|
1989
1996
|
evidence: arrayFlag(flags.evidence),
|
|
1997
|
+
evidence_level: normalizeLoopEvidenceLevelFlag(flags.evidence_level),
|
|
1998
|
+
evidence_stamp: String(flags.evidence_stamp || ''),
|
|
1999
|
+
source_digest: String(flags.source_digest || ''),
|
|
1990
2000
|
blockers,
|
|
2001
|
+
blocked_kind: String(flags.blocked_kind || ''),
|
|
1991
2002
|
truth_status: isTruthStatus(flags.truth) ? flags.truth : undefined,
|
|
1992
2003
|
intent_label: normalizeToolIntent(flags.intent_label || flags.tool_intent || 'read_only'),
|
|
1993
2004
|
next_action: String(flags.next_action || ''),
|
|
2005
|
+
safe_retry: String(flags.safe_retry || ''),
|
|
1994
2006
|
fix_first_items: arrayFlag(flags.fix_first_item),
|
|
1995
2007
|
remaining_tasks: arrayFlag(flags.remaining_task),
|
|
1996
2008
|
recommended_direction: String(flags.recommended_direction || flags.direction || ''),
|
|
@@ -1998,6 +2010,9 @@ async function loopReport(args = []) {
|
|
|
1998
2010
|
why_this_next: String(flags.why_this_next || ''),
|
|
1999
2011
|
blocked_by: arrayFlag(flags.blocked_by),
|
|
2000
2012
|
owner_route: String(flags.owner_route || flags.route || ''),
|
|
2013
|
+
owner_scope: [...arrayFlag(flags.owner_scope), ...arrayFlag(flags.scope)],
|
|
2014
|
+
scope_owner: String(flags.scope_owner || flags.owner || ''),
|
|
2015
|
+
side_effects: arrayFlag(flags.side_effect),
|
|
2001
2016
|
issue_code: String(flags.issue_code || ''),
|
|
2002
2017
|
issue_role: String(flags.issue_role || ''),
|
|
2003
2018
|
issue_symptom: String(flags.issue_symptom || ''),
|
|
@@ -6,6 +6,7 @@ export type RuntimeSubsystem = 'real_runtime' | 'tmux_physical' | 'process_clean
|
|
|
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
8
|
export type LoopStageStatus = 'passed' | 'failed' | 'blocked' | 'skipped' | 'partial' | 'pending' | 'recorded';
|
|
9
|
+
export type LoopEvidenceLevel = 'none' | 'fixture' | 'smoke' | 'local' | 'real';
|
|
9
10
|
export type ToolIntent = 'read_only' | 'write' | 'destructive' | 'runtime' | 'visual' | 'publish';
|
|
10
11
|
export interface SafetyHit {
|
|
11
12
|
level: SafetyLevel;
|
|
@@ -154,13 +155,19 @@ export interface LoopReport {
|
|
|
154
155
|
route: string;
|
|
155
156
|
intent: string;
|
|
156
157
|
loop_kind: string;
|
|
158
|
+
stage_conventions: string[];
|
|
157
159
|
stages: LoopStage[];
|
|
158
160
|
evidence: string[];
|
|
161
|
+
evidence_level: LoopEvidenceLevel;
|
|
162
|
+
evidence_stamp: string;
|
|
163
|
+
source_digest: string;
|
|
159
164
|
blockers: string[];
|
|
165
|
+
blocked_kind: string;
|
|
160
166
|
truth_status: TruthStatus;
|
|
161
167
|
intent_label: ToolIntent;
|
|
162
168
|
tool_intent: ToolIntent;
|
|
163
169
|
next_action: string;
|
|
170
|
+
safe_retry: string;
|
|
164
171
|
fix_first_items: string[];
|
|
165
172
|
remaining_tasks: string[];
|
|
166
173
|
recommended_direction: string;
|
|
@@ -168,6 +175,9 @@ export interface LoopReport {
|
|
|
168
175
|
why_this_next: string;
|
|
169
176
|
blocked_by: string[];
|
|
170
177
|
owner_route: string;
|
|
178
|
+
owner_scope: string[];
|
|
179
|
+
scope_owner: string;
|
|
180
|
+
side_effects: string[];
|
|
171
181
|
study_note: StudyNote;
|
|
172
182
|
}
|
|
173
183
|
export interface UeyeRunReport {
|
package/dist/lib/trust-kernel.js
CHANGED
|
@@ -237,9 +237,14 @@ export function buildLoopReport(input = {}) {
|
|
|
237
237
|
: [];
|
|
238
238
|
const evidence = asList(input.evidence);
|
|
239
239
|
const blockers = asList(input.blockers || input.blocked);
|
|
240
|
+
const blockedBy = asList(input.blocked_by);
|
|
241
|
+
const blockedKind = shortText(input.blocked_kind || (blockers.length || blockedBy.length ? 'evidence_missing' : ''));
|
|
242
|
+
const evidenceStamp = shortText(input.evidence_stamp || input.source_digest, 320);
|
|
243
|
+
const sourceDigest = shortText(input.source_digest || input.evidence_stamp, 320);
|
|
240
244
|
const hasBlockedStage = stages.some((stage) => stage.status === 'blocked' || stage.status === 'failed');
|
|
245
|
+
const hasBlockerSignal = Boolean(blockers.length || blockedBy.length || blockedKind);
|
|
241
246
|
const requestedTruth = isTruthStatus(input.truth_status) ? input.truth_status : '';
|
|
242
|
-
const derivedTruth =
|
|
247
|
+
const derivedTruth = hasBlockerSignal || hasBlockedStage ? 'blocked'
|
|
243
248
|
: evidence.length && stages.some((stage) => stage.status === 'passed') ? 'verified'
|
|
244
249
|
: evidence.length || stages.length ? 'partial'
|
|
245
250
|
: 'assumed';
|
|
@@ -252,20 +257,31 @@ export function buildLoopReport(input = {}) {
|
|
|
252
257
|
route: String(input.route || ''),
|
|
253
258
|
intent: shortText(input.intent),
|
|
254
259
|
loop_kind: String(input.loop_kind || 'harness'),
|
|
260
|
+
stage_conventions: asList(input.stage_conventions || input.stage_convention).length
|
|
261
|
+
? asList(input.stage_conventions || input.stage_convention)
|
|
262
|
+
: ['brief', 'plan', 'implement', 'critique', 'verify', 'handoff'],
|
|
255
263
|
stages,
|
|
256
264
|
evidence,
|
|
265
|
+
evidence_level: normalizeLoopEvidenceLevel(input.evidence_level),
|
|
266
|
+
evidence_stamp: evidenceStamp,
|
|
267
|
+
source_digest: sourceDigest,
|
|
257
268
|
blockers,
|
|
269
|
+
blocked_kind: blockedKind,
|
|
258
270
|
truth_status: truth,
|
|
259
271
|
intent_label: intentLabel,
|
|
260
272
|
tool_intent: intentLabel,
|
|
261
|
-
next_action: shortText(input.next_action || (
|
|
273
|
+
next_action: shortText(input.next_action || (hasBlockerSignal ? 'resolve the blocker before claiming this loop complete' : 'record the next smallest useful action')),
|
|
274
|
+
safe_retry: shortText(input.safe_retry || (hasBlockerSignal ? 'retry only after the blocker is resolved and new evidence is recorded' : 'not required')),
|
|
262
275
|
fix_first_items: asList(input.fix_first_items || input.fix_first_item),
|
|
263
276
|
remaining_tasks: asList(input.remaining_tasks || input.remaining_task),
|
|
264
277
|
recommended_direction: shortText(input.recommended_direction || input.direction),
|
|
265
278
|
implementation_notes: asList(input.implementation_notes || input.implementation_note),
|
|
266
279
|
why_this_next: shortText(input.why_this_next),
|
|
267
|
-
blocked_by:
|
|
280
|
+
blocked_by: blockedBy,
|
|
268
281
|
owner_route: normalizeOwnerRoute(input.owner_route || input.route),
|
|
282
|
+
owner_scope: asList(input.owner_scope || input.scope),
|
|
283
|
+
scope_owner: normalizeOwnerRoute(input.scope_owner || input.owner),
|
|
284
|
+
side_effects: asList(input.side_effects || input.side_effect),
|
|
269
285
|
study_note: studyNote
|
|
270
286
|
};
|
|
271
287
|
}
|
|
@@ -400,6 +416,12 @@ function normalizeOwnerRoute(value = '') {
|
|
|
400
416
|
return `$${text}`;
|
|
401
417
|
return text ? shortText(text, 80) : '';
|
|
402
418
|
}
|
|
419
|
+
function normalizeLoopEvidenceLevel(value = '') {
|
|
420
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
421
|
+
if (['fixture', 'smoke', 'local', 'real'].includes(text))
|
|
422
|
+
return text;
|
|
423
|
+
return 'none';
|
|
424
|
+
}
|
|
403
425
|
function shortText(value = '', limit = 240) {
|
|
404
426
|
const text = String(value || '').trim().replace(/\s+/g, ' ');
|
|
405
427
|
if (text.length <= limit)
|
package/package.json
CHANGED
|
@@ -77,8 +77,11 @@ Use this when the next run needs a clear starting point:
|
|
|
77
77
|
- Recommended direction.
|
|
78
78
|
- Why this next step matters.
|
|
79
79
|
- What is blocked, and by what.
|
|
80
|
+
- Evidence level or stamp when the handoff relies on a specific command, file, or report.
|
|
81
|
+
- Blocker kind and safe retry when the next run should not blindly repeat the same action.
|
|
82
|
+
- Owner route, scope owner, and side effects when more than one person or route may continue the work.
|
|
80
83
|
|
|
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 `
|
|
84
|
+
`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`, `blocked_kind`, `safe_retry`, `evidence_level`, `evidence_stamp`, `owner_route`, `owner_scope`, `scope_owner`, and `side_effects`.
|
|
82
85
|
|
|
83
86
|
## Route Weight
|
|
84
87
|
|
package/skills/deep/SKILL.md
CHANGED
|
@@ -74,4 +74,4 @@ Include:
|
|
|
74
74
|
- Evidence gathered.
|
|
75
75
|
- Truth status.
|
|
76
76
|
- Blockers or remaining risk.
|
|
77
|
-
- Handoff: fix-first items, remaining tasks, recommended direction,
|
|
77
|
+
- Handoff: fix-first items, remaining tasks, recommended direction, why that next step matters, blocker kind, safe retry, evidence level/stamp, side effects, and owner scope when another route or person may continue.
|
package/skills/mission/SKILL.md
CHANGED
|
@@ -106,4 +106,4 @@ Report:
|
|
|
106
106
|
- Evidence gathered.
|
|
107
107
|
- Truth status.
|
|
108
108
|
- Cleanup status.
|
|
109
|
-
- Handoff: fix-first items, remaining tasks, recommended direction,
|
|
109
|
+
- Handoff: fix-first items, remaining tasks, recommended direction, why that next step matters, blocker kind, safe retry, evidence level/stamp, side effects, and owner scope when another route or person may continue.
|
package/skills/quick/SKILL.md
CHANGED
|
@@ -79,4 +79,4 @@ Keep it compact:
|
|
|
79
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.
|
|
80
80
|
- What was checked.
|
|
81
81
|
- What was skipped, blocked, or still risky.
|
|
82
|
-
- Handoff when useful: fix-first items, remaining tasks, recommended direction,
|
|
82
|
+
- Handoff when useful: fix-first items, remaining tasks, recommended direction, why that next step matters, blocker kind, safe retry, evidence level/stamp, and owner scope when another route or person may continue.
|
package/skills/ueye/SKILL.md
CHANGED
|
@@ -172,4 +172,4 @@ Report:
|
|
|
172
172
|
- States/viewports checked.
|
|
173
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.
|
|
174
174
|
- Truth status and visual verification cap.
|
|
175
|
-
- Handoff when useful: fix-first visual issues, remaining tasks, recommended direction,
|
|
175
|
+
- Handoff when useful: fix-first visual issues, remaining tasks, recommended direction, why that next step matters, blocker kind, safe retry, evidence level/stamp, and owner scope when another route or person may continue.
|
package/src/bin/yam.ts
CHANGED
|
@@ -24,7 +24,7 @@ import {
|
|
|
24
24
|
detectDbSafetyText as detectTrustDbSafetyText,
|
|
25
25
|
isTruthStatus
|
|
26
26
|
} from '../lib/trust-kernel.js';
|
|
27
|
-
import type { ToolIntent } from '../lib/trust-kernel.js';
|
|
27
|
+
import type { LoopEvidenceLevel, ToolIntent } from '../lib/trust-kernel.js';
|
|
28
28
|
|
|
29
29
|
type AnyRecord = Record<string, any>;
|
|
30
30
|
|
|
@@ -525,6 +525,12 @@ function normalizeToolIntent(value = ''): ToolIntent {
|
|
|
525
525
|
return 'read_only';
|
|
526
526
|
}
|
|
527
527
|
|
|
528
|
+
function normalizeLoopEvidenceLevelFlag(value = ''): LoopEvidenceLevel {
|
|
529
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
530
|
+
if (['fixture', 'smoke', 'local', 'real'].includes(text)) return text as LoopEvidenceLevel;
|
|
531
|
+
return 'none';
|
|
532
|
+
}
|
|
533
|
+
|
|
528
534
|
function uniqueNextActionDetails(actions = []) {
|
|
529
535
|
const seen = new Set<string>();
|
|
530
536
|
const unique = [];
|
|
@@ -1971,24 +1977,30 @@ function loopUsage() {
|
|
|
1971
1977
|
Read-only loop artifact helpers. A loop report records intent, stages, evidence, blockers, next action, handoff fields, and a short study note. It does not run agents, start processes, publish packages, or write files.
|
|
1972
1978
|
|
|
1973
1979
|
Usage:
|
|
1974
|
-
yam loop report [--route route] [--intent text] [--loop-kind harness|release|ueye|scout|deep|mission] [--stage id:status:note] [--evidence text] [--blocked text] [--fix-first-item text] [--remaining-task text] [--recommended-direction text] [--implementation-note text] [--why-this-next text] [--blocked-by text] [--owner-route route] [--truth status] [--intent-label read_only|write|destructive|runtime|visual|publish] [--issue-code text] [--issue-role text] [--issue-symptom text] [--changed-code text] [--changed-role text] [--change-summary text] [--why-important text] [--learning-note text] [--json]
|
|
1980
|
+
yam loop report [--route route] [--intent text] [--loop-kind harness|release|ueye|scout|deep|mission] [--stage id:status:note] [--evidence text] [--evidence-level none|fixture|smoke|local|real] [--evidence-stamp text] [--source-digest text] [--blocked text] [--blocked-kind text] [--safe-retry text] [--fix-first-item text] [--remaining-task text] [--recommended-direction text] [--implementation-note text] [--why-this-next text] [--blocked-by text] [--owner-route route] [--owner-scope text] [--scope-owner text] [--side-effect text] [--truth status] [--intent-label read_only|write|destructive|runtime|visual|publish] [--issue-code text] [--issue-role text] [--issue-symptom text] [--changed-code text] [--changed-role text] [--change-summary text] [--why-important text] [--learning-note text] [--json]
|
|
1975
1981
|
`);
|
|
1976
1982
|
}
|
|
1977
1983
|
|
|
1978
1984
|
async function loopReport(args = []) {
|
|
1979
1985
|
if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h') return loopUsage();
|
|
1980
|
-
const flags = parseSimpleFlags(args, new Set(['route', 'intent', 'loop-kind', 'stage', 'evidence', 'blocked', 'blocker', 'next-action', 'fix-first-item', 'remaining-task', 'recommended-direction', 'direction', 'implementation-note', 'why-this-next', 'blocked-by', 'owner-route', 'truth', 'intent-label', 'tool-intent', 'issue-code', 'issue-role', 'issue-symptom', 'changed-code', 'changed-role', 'change-summary', 'why-important', 'learning-note', 'json']));
|
|
1986
|
+
const flags = parseSimpleFlags(args, new Set(['route', 'intent', 'loop-kind', 'stage', 'stage-convention', 'evidence', 'evidence-level', 'evidence-stamp', 'source-digest', 'blocked', 'blocker', 'blocked-kind', 'next-action', 'safe-retry', 'fix-first-item', 'remaining-task', 'recommended-direction', 'direction', 'implementation-note', 'why-this-next', 'blocked-by', 'owner-route', 'owner-scope', 'scope-owner', 'owner', 'scope', 'side-effect', 'truth', 'intent-label', 'tool-intent', 'issue-code', 'issue-role', 'issue-symptom', 'changed-code', 'changed-role', 'change-summary', 'why-important', 'learning-note', 'json']));
|
|
1981
1987
|
const blockers = [...arrayFlag(flags.blocked), ...arrayFlag(flags.blocker)];
|
|
1982
1988
|
const report = buildLoopReport({
|
|
1983
1989
|
route: normalizeRoute(flags.route) || String(flags.route || ''),
|
|
1984
1990
|
intent: String(flags.intent || ''),
|
|
1985
1991
|
loop_kind: String(flags.loop_kind || flags.route || 'harness'),
|
|
1992
|
+
stage_conventions: arrayFlag(flags.stage_convention),
|
|
1986
1993
|
stages: arrayFlag(flags.stage),
|
|
1987
1994
|
evidence: arrayFlag(flags.evidence),
|
|
1995
|
+
evidence_level: normalizeLoopEvidenceLevelFlag(flags.evidence_level),
|
|
1996
|
+
evidence_stamp: String(flags.evidence_stamp || ''),
|
|
1997
|
+
source_digest: String(flags.source_digest || ''),
|
|
1988
1998
|
blockers,
|
|
1999
|
+
blocked_kind: String(flags.blocked_kind || ''),
|
|
1989
2000
|
truth_status: isTruthStatus(flags.truth) ? flags.truth : undefined,
|
|
1990
2001
|
intent_label: normalizeToolIntent(flags.intent_label || flags.tool_intent || 'read_only'),
|
|
1991
2002
|
next_action: String(flags.next_action || ''),
|
|
2003
|
+
safe_retry: String(flags.safe_retry || ''),
|
|
1992
2004
|
fix_first_items: arrayFlag(flags.fix_first_item),
|
|
1993
2005
|
remaining_tasks: arrayFlag(flags.remaining_task),
|
|
1994
2006
|
recommended_direction: String(flags.recommended_direction || flags.direction || ''),
|
|
@@ -1996,6 +2008,9 @@ async function loopReport(args = []) {
|
|
|
1996
2008
|
why_this_next: String(flags.why_this_next || ''),
|
|
1997
2009
|
blocked_by: arrayFlag(flags.blocked_by),
|
|
1998
2010
|
owner_route: String(flags.owner_route || flags.route || ''),
|
|
2011
|
+
owner_scope: [...arrayFlag(flags.owner_scope), ...arrayFlag(flags.scope)],
|
|
2012
|
+
scope_owner: String(flags.scope_owner || flags.owner || ''),
|
|
2013
|
+
side_effects: arrayFlag(flags.side_effect),
|
|
1999
2014
|
issue_code: String(flags.issue_code || ''),
|
|
2000
2015
|
issue_role: String(flags.issue_role || ''),
|
|
2001
2016
|
issue_symptom: String(flags.issue_symptom || ''),
|
package/src/lib/trust-kernel.ts
CHANGED
|
@@ -18,6 +18,7 @@ export type RuntimeSubsystem = 'real_runtime' | 'tmux_physical' | 'process_clean
|
|
|
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
20
|
export type LoopStageStatus = 'passed' | 'failed' | 'blocked' | 'skipped' | 'partial' | 'pending' | 'recorded';
|
|
21
|
+
export type LoopEvidenceLevel = 'none' | 'fixture' | 'smoke' | 'local' | 'real';
|
|
21
22
|
export type ToolIntent = 'read_only' | 'write' | 'destructive' | 'runtime' | 'visual' | 'publish';
|
|
22
23
|
|
|
23
24
|
export interface SafetyHit {
|
|
@@ -182,13 +183,19 @@ export interface LoopReport {
|
|
|
182
183
|
route: string;
|
|
183
184
|
intent: string;
|
|
184
185
|
loop_kind: string;
|
|
186
|
+
stage_conventions: string[];
|
|
185
187
|
stages: LoopStage[];
|
|
186
188
|
evidence: string[];
|
|
189
|
+
evidence_level: LoopEvidenceLevel;
|
|
190
|
+
evidence_stamp: string;
|
|
191
|
+
source_digest: string;
|
|
187
192
|
blockers: string[];
|
|
193
|
+
blocked_kind: string;
|
|
188
194
|
truth_status: TruthStatus;
|
|
189
195
|
intent_label: ToolIntent;
|
|
190
196
|
tool_intent: ToolIntent;
|
|
191
197
|
next_action: string;
|
|
198
|
+
safe_retry: string;
|
|
192
199
|
fix_first_items: string[];
|
|
193
200
|
remaining_tasks: string[];
|
|
194
201
|
recommended_direction: string;
|
|
@@ -196,6 +203,9 @@ export interface LoopReport {
|
|
|
196
203
|
why_this_next: string;
|
|
197
204
|
blocked_by: string[];
|
|
198
205
|
owner_route: string;
|
|
206
|
+
owner_scope: string[];
|
|
207
|
+
scope_owner: string;
|
|
208
|
+
side_effects: string[];
|
|
199
209
|
study_note: StudyNote;
|
|
200
210
|
}
|
|
201
211
|
|
|
@@ -541,9 +551,14 @@ export function buildLoopReport(input: Partial<LoopReport> & Record<string, unkn
|
|
|
541
551
|
: [];
|
|
542
552
|
const evidence = asList(input.evidence);
|
|
543
553
|
const blockers = asList(input.blockers || input.blocked);
|
|
554
|
+
const blockedBy = asList(input.blocked_by);
|
|
555
|
+
const blockedKind = shortText(input.blocked_kind || (blockers.length || blockedBy.length ? 'evidence_missing' : ''));
|
|
556
|
+
const evidenceStamp = shortText(input.evidence_stamp || input.source_digest, 320);
|
|
557
|
+
const sourceDigest = shortText(input.source_digest || input.evidence_stamp, 320);
|
|
544
558
|
const hasBlockedStage = stages.some((stage) => stage.status === 'blocked' || stage.status === 'failed');
|
|
559
|
+
const hasBlockerSignal = Boolean(blockers.length || blockedBy.length || blockedKind);
|
|
545
560
|
const requestedTruth = isTruthStatus(input.truth_status) ? input.truth_status : '';
|
|
546
|
-
const derivedTruth: TruthStatus =
|
|
561
|
+
const derivedTruth: TruthStatus = hasBlockerSignal || hasBlockedStage ? 'blocked'
|
|
547
562
|
: evidence.length && stages.some((stage) => stage.status === 'passed') ? 'verified'
|
|
548
563
|
: evidence.length || stages.length ? 'partial'
|
|
549
564
|
: 'assumed';
|
|
@@ -556,20 +571,31 @@ export function buildLoopReport(input: Partial<LoopReport> & Record<string, unkn
|
|
|
556
571
|
route: String(input.route || ''),
|
|
557
572
|
intent: shortText(input.intent),
|
|
558
573
|
loop_kind: String(input.loop_kind || 'harness'),
|
|
574
|
+
stage_conventions: asList(input.stage_conventions || input.stage_convention).length
|
|
575
|
+
? asList(input.stage_conventions || input.stage_convention)
|
|
576
|
+
: ['brief', 'plan', 'implement', 'critique', 'verify', 'handoff'],
|
|
559
577
|
stages,
|
|
560
578
|
evidence,
|
|
579
|
+
evidence_level: normalizeLoopEvidenceLevel(input.evidence_level),
|
|
580
|
+
evidence_stamp: evidenceStamp,
|
|
581
|
+
source_digest: sourceDigest,
|
|
561
582
|
blockers,
|
|
583
|
+
blocked_kind: blockedKind,
|
|
562
584
|
truth_status: truth,
|
|
563
585
|
intent_label: intentLabel,
|
|
564
586
|
tool_intent: intentLabel,
|
|
565
|
-
next_action: shortText(input.next_action || (
|
|
587
|
+
next_action: shortText(input.next_action || (hasBlockerSignal ? 'resolve the blocker before claiming this loop complete' : 'record the next smallest useful action')),
|
|
588
|
+
safe_retry: shortText(input.safe_retry || (hasBlockerSignal ? 'retry only after the blocker is resolved and new evidence is recorded' : 'not required')),
|
|
566
589
|
fix_first_items: asList(input.fix_first_items || input.fix_first_item),
|
|
567
590
|
remaining_tasks: asList(input.remaining_tasks || input.remaining_task),
|
|
568
591
|
recommended_direction: shortText(input.recommended_direction || input.direction),
|
|
569
592
|
implementation_notes: asList(input.implementation_notes || input.implementation_note),
|
|
570
593
|
why_this_next: shortText(input.why_this_next),
|
|
571
|
-
blocked_by:
|
|
594
|
+
blocked_by: blockedBy,
|
|
572
595
|
owner_route: normalizeOwnerRoute(input.owner_route || input.route),
|
|
596
|
+
owner_scope: asList(input.owner_scope || input.scope),
|
|
597
|
+
scope_owner: normalizeOwnerRoute(input.scope_owner || input.owner),
|
|
598
|
+
side_effects: asList(input.side_effects || input.side_effect),
|
|
573
599
|
study_note: studyNote
|
|
574
600
|
};
|
|
575
601
|
}
|
|
@@ -694,6 +720,12 @@ function normalizeOwnerRoute(value: unknown = ''): string {
|
|
|
694
720
|
return text ? shortText(text, 80) : '';
|
|
695
721
|
}
|
|
696
722
|
|
|
723
|
+
function normalizeLoopEvidenceLevel(value: unknown = ''): LoopEvidenceLevel {
|
|
724
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
725
|
+
if (['fixture', 'smoke', 'local', 'real'].includes(text)) return text as LoopEvidenceLevel;
|
|
726
|
+
return 'none';
|
|
727
|
+
}
|
|
728
|
+
|
|
697
729
|
function shortText(value: unknown = '', limit = 240): string {
|
|
698
730
|
const text = String(value || '').trim().replace(/\s+/g, ' ');
|
|
699
731
|
if (text.length <= limit) return text;
|
package/yam.manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yam",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "1.9.1",
|
|
4
4
|
"principles": [
|
|
5
5
|
"Direction before execution.",
|
|
6
6
|
"Start fast.",
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
"Context-reuse first.",
|
|
13
13
|
"End with remaining tasks and fix-first items.",
|
|
14
14
|
"Explain what failed, what changed, and why it matters in short non-specialist language when useful.",
|
|
15
|
-
"Use handoff notes for fix-first items, remaining tasks,
|
|
15
|
+
"Use handoff notes for fix-first items, remaining tasks, recommended next direction, blocker kind, safe retry, evidence level, and owner scope when useful."
|
|
16
16
|
],
|
|
17
17
|
"defaultHooks": false,
|
|
18
18
|
"routes": [
|