yam-flow 1.9.1 → 2.0.0
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 +21 -0
- package/COMMANDS.md +1 -1
- package/README.md +5 -4
- package/dist/bin/yam.js +50 -2
- package/dist/lib/trust-kernel.d.ts +5 -0
- package/dist/lib/trust-kernel.js +13 -3
- package/package.json +1 -1
- package/references/final-report.md +4 -2
- package/src/bin/yam.ts +51 -2
- package/src/lib/trust-kernel.ts +18 -3
- package/yam.manifest.json +2 -2
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,27 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to yam-flow are documented here.
|
|
4
4
|
|
|
5
|
+
## v2.0.0 - 2026-06-24
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
|
|
9
|
+
- Extended `yam loop report --json` with lightweight requirement coverage, `failure_cause`, `recovery_hint`, and `avoidance_note` so handoff artifacts can show what must still be covered before a completion claim.
|
|
10
|
+
- Added `readiness_receipt` to `yam release report --json` to summarize the read-only evidence basis for package/version, registry, auth, git, dist, tarball, and release-check readiness.
|
|
11
|
+
|
|
12
|
+
### Improved
|
|
13
|
+
|
|
14
|
+
- Uncovered loop requirements now block verified truth, default `blocked_kind` to `requirement_uncovered`, and point the default next action at the first uncovered requirement.
|
|
15
|
+
- Documented that loop avoidance notes are report-only; durable learning remains explicit through `yam memory add`.
|
|
16
|
+
|
|
17
|
+
### Verification
|
|
18
|
+
|
|
19
|
+
- `npm run typecheck`
|
|
20
|
+
- `npm run build`
|
|
21
|
+
- `npm run cli-smoke`
|
|
22
|
+
- `npm run verify:self`
|
|
23
|
+
- `node ./dist/bin/yam.js loop report --json` with uncovered requirement truth blocking
|
|
24
|
+
- `node ./dist/bin/yam.js release report --json` (blocked as expected by npm auth readiness and dirty git, with `readiness_receipt`)
|
|
25
|
+
|
|
5
26
|
## v1.9.1 - 2026-06-19
|
|
6
27
|
|
|
7
28
|
### 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" --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
|
|
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" --covered-requirement "release report is read-only" --uncovered-requirement "npm auth verified" --blocked-kind auth_blocked --failure-cause auth_token_invalid --safe-retry "retry after npm whoami succeeds" --recovery-hint "refresh npm auth, then rerun readiness checks" --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" --avoidance-note "do not retry publish before npm auth is proven" --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"
|
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" --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
|
|
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" --covered-requirement "release report is read-only" --uncovered-requirement "npm auth verified" --blocked-kind auth_blocked --failure-cause auth_token_invalid --safe-retry "retry after npm whoami succeeds" --recovery-hint "refresh npm auth, then rerun readiness checks" --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" --avoidance-note "do not retry publish before npm auth is proven" --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
|
|
@@ -215,11 +215,12 @@ These shapes keep reports machine-readable without turning normal work into a he
|
|
|
215
215
|
|
|
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
|
-
- 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: 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.
|
|
218
|
+
- Release report JSON: `yam release report --json` summarizes typecheck, forbidden-name scan, package boundary, registry status, CLI smoke, dist freshness, diagnostics, readiness receipt, and final truth status.
|
|
219
|
+
- Loop report JSON: `yam loop report --json` records a read-only handoff artifact: guided stages, requirement coverage, evidence level/stamp, blocker kind, failure cause, safe retry, recovery hint, owner route/scope, side effects, next action, fix-first items, remaining tasks, recommended direction, implementation notes, blocked-by notes, avoidance note, 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
|
+
- Avoidance note: loop reports may include one short mistake-to-avoid note, but durable memory stays explicit through `yam memory add`; `yam loop report` does not write `.yam/memory`.
|
|
221
222
|
- Publish blocker evidence: release reports classify common npm auth, permission, OTP, immutable-version, cache, registry, and tarball failures into safe next actions.
|
|
222
|
-
- Publish readiness evidence: release reports run read-only registry/auth/version probes, redact account/token details,
|
|
223
|
+
- Publish readiness evidence: release reports run read-only registry/auth/version probes, redact account/token details, keep npm publish outside the report, and include a `yam.release-readiness-receipt.v1` basis for the readiness judgment.
|
|
223
224
|
- Context pressure: `yam context pressure` explains when project context is getting stale, broad, or confusing enough to summarize, refresh, narrow scope, or deepen route.
|
|
224
225
|
- Cleanup scan: `yam cleanup scan` is read-only and advisory; it reports confusing hooks, local skill folders, stale traces, or old proof artifacts without deleting anything.
|
|
225
226
|
- Benchmark optimization loop lite: use `yam measure <route>` and `yam template tuning` to record baseline, one route wording change, rerun result, keep/revert decision, and stop condition.
|
package/dist/bin/yam.js
CHANGED
|
@@ -1586,6 +1586,7 @@ function runReleaseReport() {
|
|
|
1586
1586
|
const publishReadiness = releasePublishReadiness(checks, provenance, tarball, publishBlockerEvidence);
|
|
1587
1587
|
const nextActions = releaseNextActions(checks, provenance, tarball, publishBlockerEvidence, publishReadiness);
|
|
1588
1588
|
const ok = failed.length === 0 && publishReadiness.status === 'ready';
|
|
1589
|
+
const readinessReceipt = releaseReadinessReceipt(provenance, freshness, tarball, publishReadiness, ok);
|
|
1589
1590
|
return {
|
|
1590
1591
|
schema: 'yam.release-report.v1',
|
|
1591
1592
|
generated_at: startedAt,
|
|
@@ -1599,11 +1600,53 @@ function runReleaseReport() {
|
|
|
1599
1600
|
tarball,
|
|
1600
1601
|
freshness,
|
|
1601
1602
|
publish_readiness: publishReadiness,
|
|
1603
|
+
readiness_receipt: readinessReceipt,
|
|
1602
1604
|
study_note: releaseStudyNote(publishReadiness, publishBlockerEvidence),
|
|
1603
1605
|
publishBlockerEvidence,
|
|
1604
1606
|
next_actions: nextActions
|
|
1605
1607
|
};
|
|
1606
1608
|
}
|
|
1609
|
+
function releaseReadinessReceipt(provenance = {}, freshness = {}, tarball = {}, publishReadiness = {}, ok = false) {
|
|
1610
|
+
return {
|
|
1611
|
+
schema: 'yam.release-readiness-receipt.v1',
|
|
1612
|
+
generated_at: new Date().toISOString(),
|
|
1613
|
+
package_name: PACKAGE_JSON.name,
|
|
1614
|
+
local_version: VERSION,
|
|
1615
|
+
registry: {
|
|
1616
|
+
url: String(publishReadiness.registry?.url || ''),
|
|
1617
|
+
latest_version: String(publishReadiness.registry?.latest_version || ''),
|
|
1618
|
+
version_status: String(publishReadiness.registry?.version_status || 'not_verified'),
|
|
1619
|
+
truth_status: publishReadiness.registry?.truth_status || 'partial'
|
|
1620
|
+
},
|
|
1621
|
+
auth: {
|
|
1622
|
+
command: 'npm whoami',
|
|
1623
|
+
status: String(publishReadiness.auth?.status || 'not_verified'),
|
|
1624
|
+
account: publishReadiness.auth?.status === 'authenticated' ? 'observed_redacted' : '',
|
|
1625
|
+
truth_status: publishReadiness.auth?.truth_status || 'partial'
|
|
1626
|
+
},
|
|
1627
|
+
git: {
|
|
1628
|
+
commit: String(provenance.git_commit || ''),
|
|
1629
|
+
dirty: Boolean(provenance.git_dirty),
|
|
1630
|
+
dirty_lines_observed: Array.isArray(provenance.git_status_lines) ? provenance.git_status_lines.length : 0,
|
|
1631
|
+
truth_status: provenance.truth_status || 'partial'
|
|
1632
|
+
},
|
|
1633
|
+
checks: {
|
|
1634
|
+
dist: freshness.dist || 'not-verified',
|
|
1635
|
+
package_boundary: freshness.package_boundary || 'not-verified',
|
|
1636
|
+
cli_smoke: freshness.cli_smoke || 'not-verified',
|
|
1637
|
+
tarball: tarball.status === 'checked' ? 'checked' : 'not-verified'
|
|
1638
|
+
},
|
|
1639
|
+
tarball: {
|
|
1640
|
+
status: String(tarball.status || 'not-verified'),
|
|
1641
|
+
name: String(tarball.tarball_name || ''),
|
|
1642
|
+
integrity_present: Boolean(tarball.integrity),
|
|
1643
|
+
shasum_present: Boolean(tarball.shasum),
|
|
1644
|
+
truth_status: tarball.truth_status || 'partial'
|
|
1645
|
+
},
|
|
1646
|
+
publish_attempted: false,
|
|
1647
|
+
truth_status: ok ? 'verified' : 'blocked'
|
|
1648
|
+
};
|
|
1649
|
+
}
|
|
1607
1650
|
function releaseProvenance(checks = []) {
|
|
1608
1651
|
const gitCommit = runReadOnlyCommand('git', ['rev-parse', '--short', 'HEAD']);
|
|
1609
1652
|
const gitStatus = runReadOnlyCommand('git', ['status', '--short']);
|
|
@@ -1979,13 +2022,13 @@ function loopUsage() {
|
|
|
1979
2022
|
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.
|
|
1980
2023
|
|
|
1981
2024
|
Usage:
|
|
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]
|
|
2025
|
+
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] [--covered-requirement text] [--uncovered-requirement text] [--blocked text] [--blocked-kind text] [--failure-cause text] [--safe-retry text] [--recovery-hint 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] [--avoidance-note 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]
|
|
1983
2026
|
`);
|
|
1984
2027
|
}
|
|
1985
2028
|
async function loopReport(args = []) {
|
|
1986
2029
|
if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h')
|
|
1987
2030
|
return loopUsage();
|
|
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']));
|
|
2031
|
+
const flags = parseSimpleFlags(args, new Set(['route', 'intent', 'loop-kind', 'stage', 'stage-convention', 'evidence', 'evidence-level', 'evidence-stamp', 'source-digest', 'covered-requirement', 'uncovered-requirement', 'blocked', 'blocker', 'blocked-kind', 'failure-cause', 'next-action', 'safe-retry', 'recovery-hint', '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', 'avoidance-note', 'truth', 'intent-label', 'tool-intent', 'issue-code', 'issue-role', 'issue-symptom', 'changed-code', 'changed-role', 'change-summary', 'why-important', 'learning-note', 'json']));
|
|
1989
2032
|
const blockers = [...arrayFlag(flags.blocked), ...arrayFlag(flags.blocker)];
|
|
1990
2033
|
const report = buildLoopReport({
|
|
1991
2034
|
route: normalizeRoute(flags.route) || String(flags.route || ''),
|
|
@@ -1997,12 +2040,16 @@ async function loopReport(args = []) {
|
|
|
1997
2040
|
evidence_level: normalizeLoopEvidenceLevelFlag(flags.evidence_level),
|
|
1998
2041
|
evidence_stamp: String(flags.evidence_stamp || ''),
|
|
1999
2042
|
source_digest: String(flags.source_digest || ''),
|
|
2043
|
+
covered_requirements: arrayFlag(flags.covered_requirement),
|
|
2044
|
+
uncovered_requirements: arrayFlag(flags.uncovered_requirement),
|
|
2000
2045
|
blockers,
|
|
2001
2046
|
blocked_kind: String(flags.blocked_kind || ''),
|
|
2047
|
+
failure_cause: String(flags.failure_cause || ''),
|
|
2002
2048
|
truth_status: isTruthStatus(flags.truth) ? flags.truth : undefined,
|
|
2003
2049
|
intent_label: normalizeToolIntent(flags.intent_label || flags.tool_intent || 'read_only'),
|
|
2004
2050
|
next_action: String(flags.next_action || ''),
|
|
2005
2051
|
safe_retry: String(flags.safe_retry || ''),
|
|
2052
|
+
recovery_hint: String(flags.recovery_hint || ''),
|
|
2006
2053
|
fix_first_items: arrayFlag(flags.fix_first_item),
|
|
2007
2054
|
remaining_tasks: arrayFlag(flags.remaining_task),
|
|
2008
2055
|
recommended_direction: String(flags.recommended_direction || flags.direction || ''),
|
|
@@ -2013,6 +2060,7 @@ async function loopReport(args = []) {
|
|
|
2013
2060
|
owner_scope: [...arrayFlag(flags.owner_scope), ...arrayFlag(flags.scope)],
|
|
2014
2061
|
scope_owner: String(flags.scope_owner || flags.owner || ''),
|
|
2015
2062
|
side_effects: arrayFlag(flags.side_effect),
|
|
2063
|
+
avoidance_note: String(flags.avoidance_note || ''),
|
|
2016
2064
|
issue_code: String(flags.issue_code || ''),
|
|
2017
2065
|
issue_role: String(flags.issue_role || ''),
|
|
2018
2066
|
issue_symptom: String(flags.issue_symptom || ''),
|
|
@@ -161,13 +161,17 @@ export interface LoopReport {
|
|
|
161
161
|
evidence_level: LoopEvidenceLevel;
|
|
162
162
|
evidence_stamp: string;
|
|
163
163
|
source_digest: string;
|
|
164
|
+
covered_requirements: string[];
|
|
165
|
+
uncovered_requirements: string[];
|
|
164
166
|
blockers: string[];
|
|
165
167
|
blocked_kind: string;
|
|
168
|
+
failure_cause: string;
|
|
166
169
|
truth_status: TruthStatus;
|
|
167
170
|
intent_label: ToolIntent;
|
|
168
171
|
tool_intent: ToolIntent;
|
|
169
172
|
next_action: string;
|
|
170
173
|
safe_retry: string;
|
|
174
|
+
recovery_hint: string;
|
|
171
175
|
fix_first_items: string[];
|
|
172
176
|
remaining_tasks: string[];
|
|
173
177
|
recommended_direction: string;
|
|
@@ -178,6 +182,7 @@ export interface LoopReport {
|
|
|
178
182
|
owner_scope: string[];
|
|
179
183
|
scope_owner: string;
|
|
180
184
|
side_effects: string[];
|
|
185
|
+
avoidance_note: string;
|
|
181
186
|
study_note: StudyNote;
|
|
182
187
|
}
|
|
183
188
|
export interface UeyeRunReport {
|
package/dist/lib/trust-kernel.js
CHANGED
|
@@ -236,13 +236,18 @@ export function buildLoopReport(input = {}) {
|
|
|
236
236
|
? input.stages.map((stage) => buildLoopStage(stage))
|
|
237
237
|
: [];
|
|
238
238
|
const evidence = asList(input.evidence);
|
|
239
|
+
const coveredRequirements = asList(input.covered_requirements || input.covered_requirement);
|
|
240
|
+
const uncoveredRequirements = asList(input.uncovered_requirements || input.uncovered_requirement);
|
|
239
241
|
const blockers = asList(input.blockers || input.blocked);
|
|
240
242
|
const blockedBy = asList(input.blocked_by);
|
|
241
|
-
const blockedKind = shortText(input.blocked_kind || (blockers.length || blockedBy.length ? 'evidence_missing' : ''));
|
|
243
|
+
const blockedKind = shortText(input.blocked_kind || (uncoveredRequirements.length ? 'requirement_uncovered' : blockers.length || blockedBy.length ? 'evidence_missing' : ''));
|
|
244
|
+
const failureCause = shortText(input.failure_cause);
|
|
245
|
+
const recoveryHint = shortText(input.recovery_hint);
|
|
246
|
+
const avoidanceNote = shortText(input.avoidance_note);
|
|
242
247
|
const evidenceStamp = shortText(input.evidence_stamp || input.source_digest, 320);
|
|
243
248
|
const sourceDigest = shortText(input.source_digest || input.evidence_stamp, 320);
|
|
244
249
|
const hasBlockedStage = stages.some((stage) => stage.status === 'blocked' || stage.status === 'failed');
|
|
245
|
-
const hasBlockerSignal = Boolean(blockers.length || blockedBy.length || blockedKind);
|
|
250
|
+
const hasBlockerSignal = Boolean(blockers.length || blockedBy.length || blockedKind || uncoveredRequirements.length);
|
|
246
251
|
const requestedTruth = isTruthStatus(input.truth_status) ? input.truth_status : '';
|
|
247
252
|
const derivedTruth = hasBlockerSignal || hasBlockedStage ? 'blocked'
|
|
248
253
|
: evidence.length && stages.some((stage) => stage.status === 'passed') ? 'verified'
|
|
@@ -265,13 +270,17 @@ export function buildLoopReport(input = {}) {
|
|
|
265
270
|
evidence_level: normalizeLoopEvidenceLevel(input.evidence_level),
|
|
266
271
|
evidence_stamp: evidenceStamp,
|
|
267
272
|
source_digest: sourceDigest,
|
|
273
|
+
covered_requirements: coveredRequirements,
|
|
274
|
+
uncovered_requirements: uncoveredRequirements,
|
|
268
275
|
blockers,
|
|
269
276
|
blocked_kind: blockedKind,
|
|
277
|
+
failure_cause: failureCause,
|
|
270
278
|
truth_status: truth,
|
|
271
279
|
intent_label: intentLabel,
|
|
272
280
|
tool_intent: intentLabel,
|
|
273
|
-
next_action: shortText(input.next_action || (hasBlockerSignal ? 'resolve the blocker before claiming this loop complete' : 'record the next smallest useful action')),
|
|
281
|
+
next_action: shortText(input.next_action || (uncoveredRequirements.length ? `cover requirement before claiming complete: ${uncoveredRequirements[0]}` : hasBlockerSignal ? 'resolve the blocker before claiming this loop complete' : 'record the next smallest useful action')),
|
|
274
282
|
safe_retry: shortText(input.safe_retry || (hasBlockerSignal ? 'retry only after the blocker is resolved and new evidence is recorded' : 'not required')),
|
|
283
|
+
recovery_hint: recoveryHint,
|
|
275
284
|
fix_first_items: asList(input.fix_first_items || input.fix_first_item),
|
|
276
285
|
remaining_tasks: asList(input.remaining_tasks || input.remaining_task),
|
|
277
286
|
recommended_direction: shortText(input.recommended_direction || input.direction),
|
|
@@ -282,6 +291,7 @@ export function buildLoopReport(input = {}) {
|
|
|
282
291
|
owner_scope: asList(input.owner_scope || input.scope),
|
|
283
292
|
scope_owner: normalizeOwnerRoute(input.scope_owner || input.owner),
|
|
284
293
|
side_effects: asList(input.side_effects || input.side_effect),
|
|
294
|
+
avoidance_note: avoidanceNote,
|
|
285
295
|
study_note: studyNote
|
|
286
296
|
};
|
|
287
297
|
}
|
package/package.json
CHANGED
|
@@ -77,11 +77,13 @@ 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
|
+
- Covered and uncovered requirements when the next run could otherwise overclaim completion.
|
|
80
81
|
- 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
|
+
- Blocker kind, failure cause, recovery hint, and safe retry when the next run should not blindly repeat the same action.
|
|
83
|
+
- Avoidance note when a repeated mistake should be easy to spot; durable memory still uses explicit `yam memory add`.
|
|
82
84
|
- Owner route, scope owner, and side effects when more than one person or route may continue the work.
|
|
83
85
|
|
|
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 `
|
|
86
|
+
`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`, `covered_requirements`, `uncovered_requirements`, `blocked_kind`, `failure_cause`, `recovery_hint`, `safe_retry`, `evidence_level`, `evidence_stamp`, `owner_route`, `owner_scope`, `scope_owner`, `side_effects`, and `avoidance_note`.
|
|
85
87
|
|
|
86
88
|
## Route Weight
|
|
87
89
|
|
package/src/bin/yam.ts
CHANGED
|
@@ -1575,6 +1575,7 @@ function runReleaseReport() {
|
|
|
1575
1575
|
const publishReadiness = releasePublishReadiness(checks, provenance, tarball, publishBlockerEvidence);
|
|
1576
1576
|
const nextActions = releaseNextActions(checks, provenance, tarball, publishBlockerEvidence, publishReadiness);
|
|
1577
1577
|
const ok = failed.length === 0 && publishReadiness.status === 'ready';
|
|
1578
|
+
const readinessReceipt = releaseReadinessReceipt(provenance, freshness, tarball, publishReadiness, ok);
|
|
1578
1579
|
return {
|
|
1579
1580
|
schema: 'yam.release-report.v1',
|
|
1580
1581
|
generated_at: startedAt,
|
|
@@ -1588,12 +1589,55 @@ function runReleaseReport() {
|
|
|
1588
1589
|
tarball,
|
|
1589
1590
|
freshness,
|
|
1590
1591
|
publish_readiness: publishReadiness,
|
|
1592
|
+
readiness_receipt: readinessReceipt,
|
|
1591
1593
|
study_note: releaseStudyNote(publishReadiness, publishBlockerEvidence),
|
|
1592
1594
|
publishBlockerEvidence,
|
|
1593
1595
|
next_actions: nextActions
|
|
1594
1596
|
};
|
|
1595
1597
|
}
|
|
1596
1598
|
|
|
1599
|
+
function releaseReadinessReceipt(provenance: AnyRecord = {}, freshness: AnyRecord = {}, tarball: AnyRecord = {}, publishReadiness: AnyRecord = {}, ok = false) {
|
|
1600
|
+
return {
|
|
1601
|
+
schema: 'yam.release-readiness-receipt.v1',
|
|
1602
|
+
generated_at: new Date().toISOString(),
|
|
1603
|
+
package_name: PACKAGE_JSON.name,
|
|
1604
|
+
local_version: VERSION,
|
|
1605
|
+
registry: {
|
|
1606
|
+
url: String(publishReadiness.registry?.url || ''),
|
|
1607
|
+
latest_version: String(publishReadiness.registry?.latest_version || ''),
|
|
1608
|
+
version_status: String(publishReadiness.registry?.version_status || 'not_verified'),
|
|
1609
|
+
truth_status: publishReadiness.registry?.truth_status || 'partial'
|
|
1610
|
+
},
|
|
1611
|
+
auth: {
|
|
1612
|
+
command: 'npm whoami',
|
|
1613
|
+
status: String(publishReadiness.auth?.status || 'not_verified'),
|
|
1614
|
+
account: publishReadiness.auth?.status === 'authenticated' ? 'observed_redacted' : '',
|
|
1615
|
+
truth_status: publishReadiness.auth?.truth_status || 'partial'
|
|
1616
|
+
},
|
|
1617
|
+
git: {
|
|
1618
|
+
commit: String(provenance.git_commit || ''),
|
|
1619
|
+
dirty: Boolean(provenance.git_dirty),
|
|
1620
|
+
dirty_lines_observed: Array.isArray(provenance.git_status_lines) ? provenance.git_status_lines.length : 0,
|
|
1621
|
+
truth_status: provenance.truth_status || 'partial'
|
|
1622
|
+
},
|
|
1623
|
+
checks: {
|
|
1624
|
+
dist: freshness.dist || 'not-verified',
|
|
1625
|
+
package_boundary: freshness.package_boundary || 'not-verified',
|
|
1626
|
+
cli_smoke: freshness.cli_smoke || 'not-verified',
|
|
1627
|
+
tarball: tarball.status === 'checked' ? 'checked' : 'not-verified'
|
|
1628
|
+
},
|
|
1629
|
+
tarball: {
|
|
1630
|
+
status: String(tarball.status || 'not-verified'),
|
|
1631
|
+
name: String(tarball.tarball_name || ''),
|
|
1632
|
+
integrity_present: Boolean(tarball.integrity),
|
|
1633
|
+
shasum_present: Boolean(tarball.shasum),
|
|
1634
|
+
truth_status: tarball.truth_status || 'partial'
|
|
1635
|
+
},
|
|
1636
|
+
publish_attempted: false,
|
|
1637
|
+
truth_status: ok ? 'verified' : 'blocked'
|
|
1638
|
+
};
|
|
1639
|
+
}
|
|
1640
|
+
|
|
1597
1641
|
function releaseProvenance(checks = []) {
|
|
1598
1642
|
const gitCommit = runReadOnlyCommand('git', ['rev-parse', '--short', 'HEAD']);
|
|
1599
1643
|
const gitStatus = runReadOnlyCommand('git', ['status', '--short']);
|
|
@@ -1977,13 +2021,13 @@ function loopUsage() {
|
|
|
1977
2021
|
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.
|
|
1978
2022
|
|
|
1979
2023
|
Usage:
|
|
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]
|
|
2024
|
+
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] [--covered-requirement text] [--uncovered-requirement text] [--blocked text] [--blocked-kind text] [--failure-cause text] [--safe-retry text] [--recovery-hint 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] [--avoidance-note 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]
|
|
1981
2025
|
`);
|
|
1982
2026
|
}
|
|
1983
2027
|
|
|
1984
2028
|
async function loopReport(args = []) {
|
|
1985
2029
|
if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h') return loopUsage();
|
|
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']));
|
|
2030
|
+
const flags = parseSimpleFlags(args, new Set(['route', 'intent', 'loop-kind', 'stage', 'stage-convention', 'evidence', 'evidence-level', 'evidence-stamp', 'source-digest', 'covered-requirement', 'uncovered-requirement', 'blocked', 'blocker', 'blocked-kind', 'failure-cause', 'next-action', 'safe-retry', 'recovery-hint', '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', 'avoidance-note', 'truth', 'intent-label', 'tool-intent', 'issue-code', 'issue-role', 'issue-symptom', 'changed-code', 'changed-role', 'change-summary', 'why-important', 'learning-note', 'json']));
|
|
1987
2031
|
const blockers = [...arrayFlag(flags.blocked), ...arrayFlag(flags.blocker)];
|
|
1988
2032
|
const report = buildLoopReport({
|
|
1989
2033
|
route: normalizeRoute(flags.route) || String(flags.route || ''),
|
|
@@ -1995,12 +2039,16 @@ async function loopReport(args = []) {
|
|
|
1995
2039
|
evidence_level: normalizeLoopEvidenceLevelFlag(flags.evidence_level),
|
|
1996
2040
|
evidence_stamp: String(flags.evidence_stamp || ''),
|
|
1997
2041
|
source_digest: String(flags.source_digest || ''),
|
|
2042
|
+
covered_requirements: arrayFlag(flags.covered_requirement),
|
|
2043
|
+
uncovered_requirements: arrayFlag(flags.uncovered_requirement),
|
|
1998
2044
|
blockers,
|
|
1999
2045
|
blocked_kind: String(flags.blocked_kind || ''),
|
|
2046
|
+
failure_cause: String(flags.failure_cause || ''),
|
|
2000
2047
|
truth_status: isTruthStatus(flags.truth) ? flags.truth : undefined,
|
|
2001
2048
|
intent_label: normalizeToolIntent(flags.intent_label || flags.tool_intent || 'read_only'),
|
|
2002
2049
|
next_action: String(flags.next_action || ''),
|
|
2003
2050
|
safe_retry: String(flags.safe_retry || ''),
|
|
2051
|
+
recovery_hint: String(flags.recovery_hint || ''),
|
|
2004
2052
|
fix_first_items: arrayFlag(flags.fix_first_item),
|
|
2005
2053
|
remaining_tasks: arrayFlag(flags.remaining_task),
|
|
2006
2054
|
recommended_direction: String(flags.recommended_direction || flags.direction || ''),
|
|
@@ -2011,6 +2059,7 @@ async function loopReport(args = []) {
|
|
|
2011
2059
|
owner_scope: [...arrayFlag(flags.owner_scope), ...arrayFlag(flags.scope)],
|
|
2012
2060
|
scope_owner: String(flags.scope_owner || flags.owner || ''),
|
|
2013
2061
|
side_effects: arrayFlag(flags.side_effect),
|
|
2062
|
+
avoidance_note: String(flags.avoidance_note || ''),
|
|
2014
2063
|
issue_code: String(flags.issue_code || ''),
|
|
2015
2064
|
issue_role: String(flags.issue_role || ''),
|
|
2016
2065
|
issue_symptom: String(flags.issue_symptom || ''),
|
package/src/lib/trust-kernel.ts
CHANGED
|
@@ -189,13 +189,17 @@ export interface LoopReport {
|
|
|
189
189
|
evidence_level: LoopEvidenceLevel;
|
|
190
190
|
evidence_stamp: string;
|
|
191
191
|
source_digest: string;
|
|
192
|
+
covered_requirements: string[];
|
|
193
|
+
uncovered_requirements: string[];
|
|
192
194
|
blockers: string[];
|
|
193
195
|
blocked_kind: string;
|
|
196
|
+
failure_cause: string;
|
|
194
197
|
truth_status: TruthStatus;
|
|
195
198
|
intent_label: ToolIntent;
|
|
196
199
|
tool_intent: ToolIntent;
|
|
197
200
|
next_action: string;
|
|
198
201
|
safe_retry: string;
|
|
202
|
+
recovery_hint: string;
|
|
199
203
|
fix_first_items: string[];
|
|
200
204
|
remaining_tasks: string[];
|
|
201
205
|
recommended_direction: string;
|
|
@@ -206,6 +210,7 @@ export interface LoopReport {
|
|
|
206
210
|
owner_scope: string[];
|
|
207
211
|
scope_owner: string;
|
|
208
212
|
side_effects: string[];
|
|
213
|
+
avoidance_note: string;
|
|
209
214
|
study_note: StudyNote;
|
|
210
215
|
}
|
|
211
216
|
|
|
@@ -550,13 +555,18 @@ export function buildLoopReport(input: Partial<LoopReport> & Record<string, unkn
|
|
|
550
555
|
? input.stages.map((stage) => buildLoopStage(stage))
|
|
551
556
|
: [];
|
|
552
557
|
const evidence = asList(input.evidence);
|
|
558
|
+
const coveredRequirements = asList(input.covered_requirements || input.covered_requirement);
|
|
559
|
+
const uncoveredRequirements = asList(input.uncovered_requirements || input.uncovered_requirement);
|
|
553
560
|
const blockers = asList(input.blockers || input.blocked);
|
|
554
561
|
const blockedBy = asList(input.blocked_by);
|
|
555
|
-
const blockedKind = shortText(input.blocked_kind || (blockers.length || blockedBy.length ? 'evidence_missing' : ''));
|
|
562
|
+
const blockedKind = shortText(input.blocked_kind || (uncoveredRequirements.length ? 'requirement_uncovered' : blockers.length || blockedBy.length ? 'evidence_missing' : ''));
|
|
563
|
+
const failureCause = shortText(input.failure_cause);
|
|
564
|
+
const recoveryHint = shortText(input.recovery_hint);
|
|
565
|
+
const avoidanceNote = shortText(input.avoidance_note);
|
|
556
566
|
const evidenceStamp = shortText(input.evidence_stamp || input.source_digest, 320);
|
|
557
567
|
const sourceDigest = shortText(input.source_digest || input.evidence_stamp, 320);
|
|
558
568
|
const hasBlockedStage = stages.some((stage) => stage.status === 'blocked' || stage.status === 'failed');
|
|
559
|
-
const hasBlockerSignal = Boolean(blockers.length || blockedBy.length || blockedKind);
|
|
569
|
+
const hasBlockerSignal = Boolean(blockers.length || blockedBy.length || blockedKind || uncoveredRequirements.length);
|
|
560
570
|
const requestedTruth = isTruthStatus(input.truth_status) ? input.truth_status : '';
|
|
561
571
|
const derivedTruth: TruthStatus = hasBlockerSignal || hasBlockedStage ? 'blocked'
|
|
562
572
|
: evidence.length && stages.some((stage) => stage.status === 'passed') ? 'verified'
|
|
@@ -579,13 +589,17 @@ export function buildLoopReport(input: Partial<LoopReport> & Record<string, unkn
|
|
|
579
589
|
evidence_level: normalizeLoopEvidenceLevel(input.evidence_level),
|
|
580
590
|
evidence_stamp: evidenceStamp,
|
|
581
591
|
source_digest: sourceDigest,
|
|
592
|
+
covered_requirements: coveredRequirements,
|
|
593
|
+
uncovered_requirements: uncoveredRequirements,
|
|
582
594
|
blockers,
|
|
583
595
|
blocked_kind: blockedKind,
|
|
596
|
+
failure_cause: failureCause,
|
|
584
597
|
truth_status: truth,
|
|
585
598
|
intent_label: intentLabel,
|
|
586
599
|
tool_intent: intentLabel,
|
|
587
|
-
next_action: shortText(input.next_action || (hasBlockerSignal ? 'resolve the blocker before claiming this loop complete' : 'record the next smallest useful action')),
|
|
600
|
+
next_action: shortText(input.next_action || (uncoveredRequirements.length ? `cover requirement before claiming complete: ${uncoveredRequirements[0]}` : hasBlockerSignal ? 'resolve the blocker before claiming this loop complete' : 'record the next smallest useful action')),
|
|
588
601
|
safe_retry: shortText(input.safe_retry || (hasBlockerSignal ? 'retry only after the blocker is resolved and new evidence is recorded' : 'not required')),
|
|
602
|
+
recovery_hint: recoveryHint,
|
|
589
603
|
fix_first_items: asList(input.fix_first_items || input.fix_first_item),
|
|
590
604
|
remaining_tasks: asList(input.remaining_tasks || input.remaining_task),
|
|
591
605
|
recommended_direction: shortText(input.recommended_direction || input.direction),
|
|
@@ -596,6 +610,7 @@ export function buildLoopReport(input: Partial<LoopReport> & Record<string, unkn
|
|
|
596
610
|
owner_scope: asList(input.owner_scope || input.scope),
|
|
597
611
|
scope_owner: normalizeOwnerRoute(input.scope_owner || input.owner),
|
|
598
612
|
side_effects: asList(input.side_effects || input.side_effect),
|
|
613
|
+
avoidance_note: avoidanceNote,
|
|
599
614
|
study_note: studyNote
|
|
600
615
|
};
|
|
601
616
|
}
|
package/yam.manifest.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "yam",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0",
|
|
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, recommended next direction, blocker kind, safe retry, evidence level, and owner scope when useful."
|
|
15
|
+
"Use handoff notes for fix-first items, remaining tasks, recommended next direction, requirement coverage, blocker kind, failure cause, recovery hint, safe retry, evidence level, and owner scope when useful."
|
|
16
16
|
],
|
|
17
17
|
"defaultHooks": false,
|
|
18
18
|
"routes": [
|