yam-flow 2.1.0 → 2.2.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/AGENTS.md +2 -1
- package/CHANGELOG.md +23 -0
- package/COMMANDS.md +9 -4
- package/README.md +10 -6
- package/dist/bin/yam.js +209 -29
- package/dist/lib/trust-kernel.d.ts +31 -1
- package/dist/lib/trust-kernel.js +128 -6
- package/package.json +2 -1
- package/references/final-report.md +5 -3
- package/references/scout-wide-scan.md +150 -0
- package/references/scout.md +9 -0
- package/references/study-note.md +22 -6
- package/references/ueye-proof.md +42 -1
- package/references/ueye.md +29 -3
- package/skills/deep/SKILL.md +3 -2
- package/skills/mission/SKILL.md +3 -2
- package/skills/quick/SKILL.md +3 -2
- package/skills/scout/SKILL.md +18 -5
- package/skills/ueye/SKILL.md +3 -2
- package/src/bin/yam.ts +215 -30
- package/src/lib/trust-kernel.ts +155 -7
- package/templates/yam.project.md +2 -1
- package/yam.manifest.json +5 -4
package/references/ueye.md
CHANGED
|
@@ -67,6 +67,7 @@ Use these when the task depends on visual truth, reference matching, or design q
|
|
|
67
67
|
4. Design Quality Review.
|
|
68
68
|
5. Review Continuity and Comparison Report.
|
|
69
69
|
6. Design Completion Gate.
|
|
70
|
+
7. Deep Visual Review, when Ueye needs Deep-grade verification.
|
|
70
71
|
|
|
71
72
|
Default bound:
|
|
72
73
|
|
|
@@ -168,6 +169,30 @@ Gate behavior:
|
|
|
168
169
|
- Missing required checks for a done claim should cap truth at partial.
|
|
169
170
|
- Only claim done when the gate says `ready_to_claim_done: true`.
|
|
170
171
|
|
|
172
|
+
### Deep Visual Review
|
|
173
|
+
|
|
174
|
+
Use when Ueye should stay in the UI/design route but needs stronger verification than a quick screenshot note.
|
|
175
|
+
|
|
176
|
+
Record:
|
|
177
|
+
|
|
178
|
+
- acceptance criteria for the visual claim.
|
|
179
|
+
- touched, read, and verified files.
|
|
180
|
+
- skipped checks and why they are acceptable or still risky.
|
|
181
|
+
- residual risks.
|
|
182
|
+
- stop condition for bounded verification.
|
|
183
|
+
- resume hint for the next visual pass.
|
|
184
|
+
- deep visual checks that ran.
|
|
185
|
+
- design-system evidence such as tokens, components, or nearby patterns read.
|
|
186
|
+
- implementation evidence such as screenshot, browser check, source inspection, or responsive check.
|
|
187
|
+
- state matrix for default, loading, error, empty, disabled, hover/focus, and mobile states when relevant.
|
|
188
|
+
|
|
189
|
+
Behavior:
|
|
190
|
+
|
|
191
|
+
- Failed or blocked state matrix rows should block the deep visual review.
|
|
192
|
+
- Skipped checks and residual risks should keep the claim partial unless the remaining claim is narrow and explicitly bounded.
|
|
193
|
+
- Deep visual review does not replace implementation screenshot evidence when the claim depends on seeing the real screen.
|
|
194
|
+
- Stop conditions prevent endless visual proof loops; resume hints make the next pass cheap to restart.
|
|
195
|
+
|
|
171
196
|
### Review Continuity and Comparison Report
|
|
172
197
|
|
|
173
198
|
Use when a screen has more than one visual pass, a reference needs follow-up, or a previous Ueye report should stay connected to the next one.
|
|
@@ -222,9 +247,10 @@ Keep this metadata descriptive. It should support honest visual claims, not forc
|
|
|
222
247
|
7. Reference vs Implementation Matrix when reference fidelity matters.
|
|
223
248
|
8. Design Quality Review.
|
|
224
249
|
9. Design Completion Gate before any done claim.
|
|
225
|
-
10.
|
|
226
|
-
11.
|
|
227
|
-
12.
|
|
250
|
+
10. Deep Visual Review when the work needs acceptance criteria, state matrix, skipped checks, residual risks, stop condition, or resume hint.
|
|
251
|
+
11. Review Continuity and Comparison Report when the work spans multiple passes.
|
|
252
|
+
12. P0/P1 closeout.
|
|
253
|
+
13. Truth status.
|
|
228
254
|
|
|
229
255
|
## Truth Caps
|
|
230
256
|
|
package/skills/deep/SKILL.md
CHANGED
|
@@ -52,7 +52,7 @@ Use `references/db-supabase-safety-lite.md` for destructive DB/Supabase, migrati
|
|
|
52
52
|
Use `references/current-docs.md` when SDK/API/cloud-service behavior may be current or version-sensitive.
|
|
53
53
|
Use `references/trust-kernel.md` when the task asks how yam prevents false completion or fake real proof claims.
|
|
54
54
|
Use `references/honest-completion.md`; do not overclaim verification, runtime, cleanup, or visual proof.
|
|
55
|
-
Use `references/study-note.md` when any code, config, docs, release metadata, or project artifact changed.
|
|
55
|
+
Use `references/study-note.md` when any code, config, docs, release metadata, or project artifact changed; include role, execution point, before/after, expected behavior, one syntax/structure insight, verification, limits, and architecture hygiene when relevant.
|
|
56
56
|
Use `references/final-report.md` to close with remaining tasks and fix-first items when useful.
|
|
57
57
|
Use `references/token-budget-reporter.md` when a run needs measured budget feedback.
|
|
58
58
|
|
|
@@ -77,7 +77,8 @@ Stop condition:
|
|
|
77
77
|
Include:
|
|
78
78
|
|
|
79
79
|
- What was changed or reviewed.
|
|
80
|
-
- Study Note for changed artifacts: what changed, what role it has, what was wrong or missing, what behavior is expected, one useful syntax/structure insight, what was verified, and what remains uncertain.
|
|
80
|
+
- Study Note for changed artifacts: what changed, what role it has, where it runs or is read, what was wrong or missing, before/after behavior, what behavior is expected, one useful syntax/structure insight, what was verified, and what remains uncertain.
|
|
81
|
+
- Architecture hygiene when relevant: flag if the change risks dumping unrelated logic into `page.tsx`, one-off component CSS into `global.css`, or structured product data into broad DB `jsonb` blobs.
|
|
81
82
|
- Evidence gathered.
|
|
82
83
|
- Truth status.
|
|
83
84
|
- Blockers or remaining risk.
|
package/skills/mission/SKILL.md
CHANGED
|
@@ -87,7 +87,7 @@ Use `references/db-supabase-safety-lite.md` for destructive DB/Supabase, migrati
|
|
|
87
87
|
Use `references/current-docs.md` when any lane depends on current SDK/API/cloud-service behavior.
|
|
88
88
|
Use `references/verification-levels.md` for L4-L5 mission proof boundaries.
|
|
89
89
|
Use `references/honest-completion.md`; do not overclaim.
|
|
90
|
-
Use `references/study-note.md` for every lane that changes code, config, docs, release metadata, or project artifacts.
|
|
90
|
+
Use `references/study-note.md` for every lane that changes code, config, docs, release metadata, or project artifacts; include role, execution point, before/after, expected behavior, one syntax/structure insight, verification, limits, and architecture hygiene when relevant.
|
|
91
91
|
Use `references/final-report.md` to close with remaining tasks and fix-first items.
|
|
92
92
|
Use `references/token-budget-reporter.md` when budget drift matters.
|
|
93
93
|
|
|
@@ -110,7 +110,8 @@ Report:
|
|
|
110
110
|
|
|
111
111
|
- What the mission changed.
|
|
112
112
|
- Role/cross-verification summary.
|
|
113
|
-
- Study Note for any lane that changed code, config, docs, release metadata, or project artifacts: what changed, what role it has, what was wrong or missing, what behavior is expected, one useful syntax/structure insight, what was verified, and what remains uncertain.
|
|
113
|
+
- Study Note for any lane that changed code, config, docs, release metadata, or project artifacts: what changed, what role it has, where it runs or is read, what was wrong or missing, before/after behavior, what behavior is expected, one useful syntax/structure insight, what was verified, and what remains uncertain.
|
|
114
|
+
- Architecture hygiene when relevant: flag if the change risks dumping unrelated logic into `page.tsx`, one-off component CSS into `global.css`, or structured product data into broad DB `jsonb` blobs.
|
|
114
115
|
- Evidence gathered.
|
|
115
116
|
- Truth status.
|
|
116
117
|
- Cleanup status.
|
package/skills/quick/SKILL.md
CHANGED
|
@@ -70,7 +70,7 @@ Use `references/truth-matrix.md` for truth labels.
|
|
|
70
70
|
Use `references/db-supabase-safety-lite.md` when a command or prompt contains DB/Supabase mutation signals.
|
|
71
71
|
Use `references/token-economy.md` to keep context small.
|
|
72
72
|
Use `references/context-reuse.md` before broad project reading.
|
|
73
|
-
Use `references/study-note.md` when any code, config, docs, or project artifact changed.
|
|
73
|
+
Use `references/study-note.md` when any code, config, docs, or project artifact changed; include role, execution point, before/after, expected behavior, one syntax/structure insight, verification, limits, and architecture hygiene when relevant.
|
|
74
74
|
Use `references/final-report.md` to close with remaining tasks and fix-first items when useful.
|
|
75
75
|
Use `references/token-budget-reporter.md` when a run needs measured budget feedback.
|
|
76
76
|
|
|
@@ -79,7 +79,8 @@ Use `references/token-budget-reporter.md` when a run needs measured budget feedb
|
|
|
79
79
|
Keep it compact:
|
|
80
80
|
|
|
81
81
|
- What changed or what the scan found.
|
|
82
|
-
- Study Note when code, config, docs, or project artifacts changed: what changed, what role it has, what was wrong or missing, what behavior is expected, one useful syntax/structure insight, what was verified, and what remains uncertain.
|
|
82
|
+
- Study Note when code, config, docs, or project artifacts changed: what changed, what role it has, where it runs or is read, what was wrong or missing, before/after behavior, what behavior is expected, one useful syntax/structure insight, what was verified, and what remains uncertain.
|
|
83
|
+
- Architecture hygiene when relevant: flag if the change risks dumping unrelated logic into `page.tsx`, one-off component CSS into `global.css`, or structured product data into broad DB `jsonb` blobs.
|
|
83
84
|
- What was checked.
|
|
84
85
|
- What was skipped, blocked, or still risky.
|
|
85
86
|
- 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/scout/SKILL.md
CHANGED
|
@@ -16,6 +16,7 @@ Use for:
|
|
|
16
16
|
- Objective and subjective evaluation together.
|
|
17
17
|
- Macro, realistic, and future-facing judgment.
|
|
18
18
|
- Broad reference scans when the user needs wider perspective.
|
|
19
|
+
- Wide search across source classes, markets, tools, harnesses, agent patterns, or third-party ecosystems.
|
|
19
20
|
- Security-centered direction checks before implementation.
|
|
20
21
|
- Finding patterns worth reworking into yam style.
|
|
21
22
|
|
|
@@ -31,6 +32,11 @@ Use for:
|
|
|
31
32
|
- Do not change code unless the user asks.
|
|
32
33
|
- Return a practical recommendation.
|
|
33
34
|
- Separate fact, inference, opinion, and recommendation.
|
|
35
|
+
- Use an evidence ledger for wide scans: claim, source or local evidence, confidence, and uncertainty.
|
|
36
|
+
- Run an opposition pass for broad recommendations: name the strongest reason the preferred direction may be wrong.
|
|
37
|
+
- Use blocked-source acquisition only when a high-signal source is blocked, protected by WAF, or hosted on a platform that ordinary fetch cannot read.
|
|
38
|
+
- Treat `insane-search` as a source acquisition subroutine, not as Scout's default search path.
|
|
39
|
+
- Use real subagents or parallel agent lanes only when the user explicitly asks for delegation, subagents, or parallel agent work and the environment supports it.
|
|
34
40
|
- Treat "objective" as evidence plus constraints, not certainty theater.
|
|
35
41
|
- Treat "subjective" as named taste, product instinct, and likely user perception.
|
|
36
42
|
- Security is the first lens: call out auth, payment, DB, secrets, permission, deployment, supply-chain, and public-release risks early.
|
|
@@ -46,13 +52,17 @@ Use for:
|
|
|
46
52
|
- design/reference scan
|
|
47
53
|
- product/technical direction memo
|
|
48
54
|
- risk discovery
|
|
55
|
+
- wide scan
|
|
49
56
|
3. Read `yam.project.md` first when project direction matters.
|
|
50
57
|
4. Gather enough high-signal sources to support the decision; keep source quality higher than source volume.
|
|
51
|
-
5.
|
|
52
|
-
6.
|
|
53
|
-
7.
|
|
54
|
-
8.
|
|
55
|
-
9.
|
|
58
|
+
5. For wide scans, build a source map before deep reading: official/primary, implementation evidence, third-party analysis, community reports, contrarian sources, and local evidence.
|
|
59
|
+
6. Recover blocked high-signal sources through the blocked-source fallback only when ordinary access fails or is predictably blocked.
|
|
60
|
+
7. Compare options by fit, risk, cost, implementation effort, durability, and evidence quality.
|
|
61
|
+
8. Identify security and trust implications before convenience or aesthetics.
|
|
62
|
+
9. Give both objective and subjective judgment when useful.
|
|
63
|
+
10. Run an opposition pass when making a broad recommendation.
|
|
64
|
+
11. Recommend a direction and which ideas are worth reworking into yam style.
|
|
65
|
+
12. State uncertainty and what would change the recommendation.
|
|
56
66
|
|
|
57
67
|
## Output
|
|
58
68
|
|
|
@@ -65,6 +75,8 @@ Use concise sections:
|
|
|
65
75
|
- Alternatives.
|
|
66
76
|
- Risks.
|
|
67
77
|
- Security lens.
|
|
78
|
+
- Evidence ledger.
|
|
79
|
+
- Opposition pass.
|
|
68
80
|
- Ideas to rework into yam style.
|
|
69
81
|
- Sources or local evidence.
|
|
70
82
|
- Remaining tasks or useful next improvements.
|
|
@@ -72,6 +84,7 @@ Use concise sections:
|
|
|
72
84
|
Use `references/token-economy.md`; default to 3-7 high-signal sources unless the user asks for a broad research scan.
|
|
73
85
|
Use `references/current-docs.md` for current SDK/API/cloud-service questions.
|
|
74
86
|
Use `references/context-reuse.md`; do not rescout known decisions unless they may be stale.
|
|
87
|
+
Use `references/scout-wide-scan.md` when the user asks for broad search, powerful outside patterns, harness/agent comparisons, or ecosystem scans.
|
|
75
88
|
Use `references/markdown-management.md` before creating or updating project packs.
|
|
76
89
|
Use `references/final-report.md` to close with remaining tasks and fix-first items when useful.
|
|
77
90
|
Use `references/token-budget-reporter.md` when a run needs measured budget feedback.
|
package/skills/ueye/SKILL.md
CHANGED
|
@@ -147,7 +147,7 @@ Use these artifacts for reference-led implementation or serious visual review. K
|
|
|
147
147
|
|
|
148
148
|
Use `references/ueye.md` and `references/ui-quality.md`.
|
|
149
149
|
Use `references/verification-levels.md` for visual proof levels and done-claim truth caps.
|
|
150
|
-
Use `references/study-note.md` when UI code, design docs, config, or project artifacts changed.
|
|
150
|
+
Use `references/study-note.md` when UI code, design docs, config, or project artifacts changed; include role, execution point, before/after, expected behavior, one syntax/structure insight, verification, limits, and architecture hygiene when relevant.
|
|
151
151
|
Always consider:
|
|
152
152
|
|
|
153
153
|
- Direction fit.
|
|
@@ -173,6 +173,7 @@ Report:
|
|
|
173
173
|
- Review continuity/comparison result when this continues a prior Ueye run.
|
|
174
174
|
- P0-P3 issues or confirmation that no blockers were found.
|
|
175
175
|
- States/viewports checked.
|
|
176
|
-
- Study Note when UI code, design docs, config, or project artifacts changed: what changed, what role it has, what was wrong or missing, what behavior is expected, one useful syntax/structure insight, what was verified, and what remains uncertain.
|
|
176
|
+
- Study Note when UI code, design docs, config, or project artifacts changed: what changed, what role it has, where it runs or is read, what was wrong or missing, before/after behavior, what behavior is expected, one useful syntax/structure insight, what was verified, and what remains uncertain.
|
|
177
|
+
- Architecture hygiene when relevant: flag if the change risks dumping unrelated UI logic into `page.tsx`, one-off component styling into `global.css`, or structured product data into broad DB `jsonb` blobs.
|
|
177
178
|
- Truth status and visual verification cap.
|
|
178
179
|
- 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 { LoopEvidenceLevel, ToolIntent } from '../lib/trust-kernel.js';
|
|
27
|
+
import type { LoopEvidenceLevel, ReadinessState, ToolIntent } from '../lib/trust-kernel.js';
|
|
28
28
|
|
|
29
29
|
type AnyRecord = Record<string, any>;
|
|
30
30
|
|
|
@@ -71,6 +71,7 @@ const PROJECT_PACK = 'yam.project.md';
|
|
|
71
71
|
const LEGACY_PROJECT_PACK = 'timeto.project.md';
|
|
72
72
|
const PACK_STALE_DAYS = 30;
|
|
73
73
|
const YAM_LITE_HOOK_COMMAND = `node ${path.join(ROOT, 'dist', 'bin', 'yam.js')} hook run lite`;
|
|
74
|
+
const YAM_STUDY_NOTE_HOOK_COMMAND = `node ${path.join(ROOT, 'dist', 'bin', 'yam.js')} hook run study-note`;
|
|
74
75
|
const REQUIRED_PACK_SECTIONS = [
|
|
75
76
|
'Product Direction',
|
|
76
77
|
'UI Direction',
|
|
@@ -144,6 +145,7 @@ Usage:
|
|
|
144
145
|
yam tools doctor [dir]
|
|
145
146
|
yam proof [dir|--from file] [--route route] [--truth status] [--command text] [--evidence text]
|
|
146
147
|
yam proof write [dir] [--format json|md] [--out file] [--route route] [--truth status] [--command text]
|
|
148
|
+
yam study-note check [dir] [--report file|--text text] [--json]
|
|
147
149
|
yam loop report [--route route] [--intent text] [--stage id:status:note] [--evidence text] [--json]
|
|
148
150
|
yam ueye capture --url URL --out screenshot.png [--viewport 1440x900] [--full-page] [--json]
|
|
149
151
|
yam ueye compare --reference ref.png --actual screenshot.png [--json]
|
|
@@ -156,7 +158,7 @@ Usage:
|
|
|
156
158
|
yam release report [--json]
|
|
157
159
|
yam safety [text...]
|
|
158
160
|
yam memory <init|add|list|summary|resolve> [dir] [options]
|
|
159
|
-
yam hook <status|enable|disable|run> [lite] [--global|--project dir]
|
|
161
|
+
yam hook <status|enable|disable|run> [lite|study-note] [--global|--project dir]
|
|
160
162
|
yam template <project|ueye|mission|proof|tuning>
|
|
161
163
|
yam tune-log [dir]
|
|
162
164
|
yam install
|
|
@@ -532,6 +534,12 @@ function normalizeLoopEvidenceLevelFlag(value = ''): LoopEvidenceLevel {
|
|
|
532
534
|
return 'none';
|
|
533
535
|
}
|
|
534
536
|
|
|
537
|
+
function normalizeReadinessStateFlag(value = ''): ReadinessState {
|
|
538
|
+
const text = String(value || '').toLowerCase().replace(/[-\s]/g, '_');
|
|
539
|
+
if (['usable', 'degraded', 'blocked', 'unknown'].includes(text)) return text as ReadinessState;
|
|
540
|
+
return 'unknown';
|
|
541
|
+
}
|
|
542
|
+
|
|
535
543
|
function uniqueNextActionDetails(actions = []) {
|
|
536
544
|
const seen = new Set<string>();
|
|
537
545
|
const unique = [];
|
|
@@ -708,6 +716,126 @@ async function cleanup(args = []) {
|
|
|
708
716
|
return cleanupUsage();
|
|
709
717
|
}
|
|
710
718
|
|
|
719
|
+
async function studyNote(args = []) {
|
|
720
|
+
const subcommand = args[0] || 'help';
|
|
721
|
+
if (subcommand === 'help' || subcommand === '--help' || subcommand === '-h') return studyNoteUsage();
|
|
722
|
+
if (subcommand === 'check') return studyNoteCheck(args.slice(1));
|
|
723
|
+
console.error(`unknown study-note command: ${subcommand}`);
|
|
724
|
+
return studyNoteUsage();
|
|
725
|
+
}
|
|
726
|
+
|
|
727
|
+
function studyNoteUsage() {
|
|
728
|
+
console.log(`yam study-note
|
|
729
|
+
|
|
730
|
+
Usage:
|
|
731
|
+
yam study-note check [dir] [--report file|--text text] [--json]
|
|
732
|
+
|
|
733
|
+
Notes:
|
|
734
|
+
Read-only guard. It checks whether changed work has a Study Note and whether relevant UI/CSS/DB hygiene was reported.
|
|
735
|
+
It does not generate, edit, or infer the Study Note for you.
|
|
736
|
+
`);
|
|
737
|
+
}
|
|
738
|
+
|
|
739
|
+
async function studyNoteCheck(args = []) {
|
|
740
|
+
const flags = parseSimpleFlags(args, new Set(['report', 'text', 'json']));
|
|
741
|
+
const dir = path.resolve(firstPositional(args) || process.cwd());
|
|
742
|
+
const changedFiles = await gitChangedFiles(dir);
|
|
743
|
+
const reportText = await readStudyNoteReportText(flags, dir);
|
|
744
|
+
const needsStudyNote = changedFiles.length > 0;
|
|
745
|
+
const hygieneRequirements = studyNoteHygieneRequirements(changedFiles);
|
|
746
|
+
const checks = [
|
|
747
|
+
studyNoteGuardCheck('changed_files', needsStudyNote ? 'pass' : 'skipped', needsStudyNote ? 'changed files detected; Study Note is required before final completion' : 'no changed files detected'),
|
|
748
|
+
studyNoteGuardCheck('study_note_present', !needsStudyNote || hasStudyNoteMarker(reportText) ? 'pass' : 'fail', 'final report should include a Study Note when project artifacts changed'),
|
|
749
|
+
studyNoteGuardCheck('role_or_responsibility', !needsStudyNote || /(\brole\b|\bresponsib|\bdoes\b|역할|기능)/i.test(reportText) ? 'pass' : 'fail', 'Study Note should explain what the touched code/artifact does'),
|
|
750
|
+
studyNoteGuardCheck('before_after_or_change', !needsStudyNote || /(\bbefore\b|\bafter\b|before\/after|changed|change meaning|바뀌|변경|수정)/i.test(reportText) ? 'pass' : 'fail', 'Study Note should explain what changed from before to after'),
|
|
751
|
+
studyNoteGuardCheck('verification_or_limits', !needsStudyNote || /(verification|verified|checked|limits|uncertain|검증|확인|한계|모르는)/i.test(reportText) ? 'pass' : 'fail', 'Study Note should say what was checked and what remains uncertain')
|
|
752
|
+
];
|
|
753
|
+
for (const requirement of hygieneRequirements) {
|
|
754
|
+
checks.push(studyNoteGuardCheck(requirement.id, requirementSatisfied(reportText, requirement), requirement.note));
|
|
755
|
+
}
|
|
756
|
+
const blockers = checks.filter((check) => check.status === 'fail').map((check) => `${check.id}: ${check.next_action}`);
|
|
757
|
+
const result = {
|
|
758
|
+
schema: 'yam.study-note-guard.v1',
|
|
759
|
+
generated_at: new Date().toISOString(),
|
|
760
|
+
project: dir,
|
|
761
|
+
changed_files: changedFiles,
|
|
762
|
+
changed_file_count: changedFiles.length,
|
|
763
|
+
report_source: flags.report ? path.resolve(dir, String(flags.report)) : flags.text ? 'inline_text' : 'not_provided',
|
|
764
|
+
checks,
|
|
765
|
+
blockers,
|
|
766
|
+
next_action: blockers[0] || (needsStudyNote ? 'Study Note guard passed for the supplied report text' : 'no Study Note required because no changed files were detected'),
|
|
767
|
+
truth_status: blockers.length ? 'blocked' : needsStudyNote ? 'verified' : 'skipped'
|
|
768
|
+
};
|
|
769
|
+
printJsonOrHuman(result, Boolean(flags.json), 'Study Note guard');
|
|
770
|
+
if (blockers.length) process.exitCode = 1;
|
|
771
|
+
}
|
|
772
|
+
|
|
773
|
+
function firstPositional(args = []) {
|
|
774
|
+
for (let index = 0; index < args.length; index += 1) {
|
|
775
|
+
const arg = String(args[index] || '');
|
|
776
|
+
if (arg.startsWith('--')) {
|
|
777
|
+
if (!arg.includes('=') && !['--json'].includes(arg)) index += 1;
|
|
778
|
+
continue;
|
|
779
|
+
}
|
|
780
|
+
if (arg === 'check') continue;
|
|
781
|
+
return arg;
|
|
782
|
+
}
|
|
783
|
+
return '';
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
async function gitChangedFiles(dir) {
|
|
787
|
+
const output = runReadOnlyCommandIn(dir, 'git', ['status', '--short']);
|
|
788
|
+
return output
|
|
789
|
+
.split(/\r?\n/)
|
|
790
|
+
.filter(Boolean)
|
|
791
|
+
.map((line) => line.replace(/^..\s+/, '').replace(/^.* -> /, ''))
|
|
792
|
+
.map((line) => line.trim())
|
|
793
|
+
.filter((file) => file && !file.startsWith('dist/') && !file.endsWith('.tgz'));
|
|
794
|
+
}
|
|
795
|
+
|
|
796
|
+
async function readStudyNoteReportText(flags, dir) {
|
|
797
|
+
if (flags.text) return String(flags.text || '');
|
|
798
|
+
if (!flags.report) return '';
|
|
799
|
+
const file = path.resolve(dir, String(flags.report));
|
|
800
|
+
try {
|
|
801
|
+
return await fsp.readFile(file, 'utf8');
|
|
802
|
+
} catch {
|
|
803
|
+
return '';
|
|
804
|
+
}
|
|
805
|
+
}
|
|
806
|
+
|
|
807
|
+
function hasStudyNoteMarker(text = '') {
|
|
808
|
+
return /(study note|study-note|학습\s*노트|스터디\s*노트)/i.test(text);
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
function studyNoteGuardCheck(id, status, nextAction) {
|
|
812
|
+
return {
|
|
813
|
+
id,
|
|
814
|
+
status,
|
|
815
|
+
next_action: nextAction,
|
|
816
|
+
truth_status: status === 'pass' ? 'verified' : status === 'fail' ? 'blocked' : status === 'skipped' ? 'skipped' : 'partial'
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
|
|
820
|
+
function studyNoteHygieneRequirements(files = []) {
|
|
821
|
+
const requirements = [];
|
|
822
|
+
if (files.some((file) => /(^|\/)page\.tsx$/i.test(file))) {
|
|
823
|
+
requirements.push({ id: 'page_tsx_hygiene', terms: ['page.tsx', 'component', 'hook', 'helper', 'server action', 'route'], note: 'Study Note should say whether page.tsx stayed focused or needs component/hook/helper/server-action separation' });
|
|
824
|
+
}
|
|
825
|
+
if (files.some((file) => /(^|\/)global\.css$/i.test(file))) {
|
|
826
|
+
requirements.push({ id: 'global_css_hygiene', terms: ['global.css', 'token', 'component', 'scoped', 'module', 'utility'], note: 'Study Note should say whether CSS belongs globally or should move to tokens/scoped/component styles' });
|
|
827
|
+
}
|
|
828
|
+
if (files.some((file) => /(migration|schema|db|database|sql|prisma|drizzle|supabase)/i.test(file))) {
|
|
829
|
+
requirements.push({ id: 'jsonb_hygiene', terms: ['jsonb', 'column', 'table', 'constraint', 'index', 'schema', 'relation'], note: 'Study Note should say whether structured product data belongs in typed columns/tables/constraints/indexes instead of broad DB jsonb' });
|
|
830
|
+
}
|
|
831
|
+
return requirements;
|
|
832
|
+
}
|
|
833
|
+
|
|
834
|
+
function requirementSatisfied(text = '', requirement) {
|
|
835
|
+
const normalized = String(text || '').toLowerCase();
|
|
836
|
+
return requirement.terms.some((term) => normalized.includes(term.toLowerCase())) ? 'pass' : 'fail';
|
|
837
|
+
}
|
|
838
|
+
|
|
711
839
|
function cleanupUsage() {
|
|
712
840
|
console.log(`yam cleanup
|
|
713
841
|
|
|
@@ -1270,12 +1398,12 @@ function hookUsage() {
|
|
|
1270
1398
|
|
|
1271
1399
|
Usage:
|
|
1272
1400
|
yam hook status [--global|--project dir]
|
|
1273
|
-
yam hook enable lite [--global|--project dir]
|
|
1274
|
-
yam hook disable [lite] [--global|--project dir]
|
|
1275
|
-
yam hook run lite
|
|
1401
|
+
yam hook enable <lite|study-note> [--global|--project dir]
|
|
1402
|
+
yam hook disable [lite|study-note] [--global|--project dir]
|
|
1403
|
+
yam hook run <lite|study-note>
|
|
1276
1404
|
|
|
1277
1405
|
Notes:
|
|
1278
|
-
|
|
1406
|
+
hooks are opt-in and advisory-only. They do not run tmux, subagents, or proof gates.
|
|
1279
1407
|
`);
|
|
1280
1408
|
}
|
|
1281
1409
|
|
|
@@ -1283,8 +1411,8 @@ function parseHookArgs(args = []) {
|
|
|
1283
1411
|
const result = { mode: 'project', projectDir: process.cwd(), profile: 'lite' };
|
|
1284
1412
|
for (let index = 0; index < args.length; index += 1) {
|
|
1285
1413
|
const arg = args[index];
|
|
1286
|
-
if (arg === 'lite') {
|
|
1287
|
-
result.profile =
|
|
1414
|
+
if (arg === 'lite' || arg === 'study-note') {
|
|
1415
|
+
result.profile = arg;
|
|
1288
1416
|
} else if (arg === '--global') {
|
|
1289
1417
|
result.mode = 'global';
|
|
1290
1418
|
} else if (arg === '--project') {
|
|
@@ -1308,13 +1436,21 @@ function isYamLiteHook(handler: AnyRecord = {}) {
|
|
|
1308
1436
|
return handler?.type === 'command' && String(handler.command || '').includes('yam.js hook run lite');
|
|
1309
1437
|
}
|
|
1310
1438
|
|
|
1311
|
-
function
|
|
1439
|
+
function isYamStudyNoteHook(handler: AnyRecord = {}) {
|
|
1440
|
+
return handler?.type === 'command' && String(handler.command || '').includes('yam.js hook run study-note');
|
|
1441
|
+
}
|
|
1442
|
+
|
|
1443
|
+
function isYamHookProfile(handler: AnyRecord = {}, profile = 'lite') {
|
|
1444
|
+
return profile === 'study-note' ? isYamStudyNoteHook(handler) : isYamLiteHook(handler);
|
|
1445
|
+
}
|
|
1446
|
+
|
|
1447
|
+
function stripYamHooks(config: AnyRecord = {}, profile = 'lite') {
|
|
1312
1448
|
const next = { ...config };
|
|
1313
1449
|
for (const event of Object.keys(next)) {
|
|
1314
1450
|
const entries = Array.isArray(next[event]) ? next[event] : [];
|
|
1315
1451
|
const keptEntries = [];
|
|
1316
1452
|
for (const entry of entries) {
|
|
1317
|
-
const hooks = Array.isArray(entry?.hooks) ? entry.hooks.filter((handler) => !
|
|
1453
|
+
const hooks = Array.isArray(entry?.hooks) ? entry.hooks.filter((handler) => !isYamHookProfile(handler, profile)) : [];
|
|
1318
1454
|
const rest = { ...entry, hooks };
|
|
1319
1455
|
if (hooks.length > 0) keptEntries.push(rest);
|
|
1320
1456
|
}
|
|
@@ -1324,14 +1460,14 @@ function stripYamLiteHooks(config: AnyRecord = {}) {
|
|
|
1324
1460
|
return next;
|
|
1325
1461
|
}
|
|
1326
1462
|
|
|
1327
|
-
function
|
|
1328
|
-
const next =
|
|
1463
|
+
function withYamHook(config: AnyRecord = {}, profile = 'lite') {
|
|
1464
|
+
const next = stripYamHooks(config, profile);
|
|
1329
1465
|
const event = 'UserPromptSubmit';
|
|
1330
1466
|
const entry = {
|
|
1331
1467
|
hooks: [
|
|
1332
1468
|
{
|
|
1333
1469
|
type: 'command',
|
|
1334
|
-
command: YAM_LITE_HOOK_COMMAND,
|
|
1470
|
+
command: profile === 'study-note' ? YAM_STUDY_NOTE_HOOK_COMMAND : YAM_LITE_HOOK_COMMAND,
|
|
1335
1471
|
timeout: 5
|
|
1336
1472
|
}
|
|
1337
1473
|
]
|
|
@@ -1344,28 +1480,32 @@ async function hookStatus(args = []) {
|
|
|
1344
1480
|
const parsed = parseHookArgs(args);
|
|
1345
1481
|
const target = hookPathFor(parsed);
|
|
1346
1482
|
const config = await readJsonOrDefault(target, {});
|
|
1347
|
-
|
|
1348
|
-
console.log(`yam-
|
|
1483
|
+
console.log(`yam-lite hook: ${hookConfigHasProfile(config, 'lite') ? 'enabled' : 'disabled'}`);
|
|
1484
|
+
console.log(`yam-study-note hook: ${hookConfigHasProfile(config, 'study-note') ? 'enabled' : 'disabled'}`);
|
|
1349
1485
|
console.log(`scope: ${parsed.mode}`);
|
|
1350
1486
|
console.log(`file: ${target}`);
|
|
1351
1487
|
}
|
|
1352
1488
|
|
|
1353
1489
|
function hookConfigHasYamLite(config = {}) {
|
|
1490
|
+
return hookConfigHasProfile(config, 'lite');
|
|
1491
|
+
}
|
|
1492
|
+
|
|
1493
|
+
function hookConfigHasProfile(config = {}, profile = 'lite') {
|
|
1354
1494
|
return Object.values(config).some((entries) => Array.isArray(entries) && entries.some((entry) => {
|
|
1355
|
-
return Array.isArray(entry?.hooks) && entry.hooks.some(
|
|
1495
|
+
return Array.isArray(entry?.hooks) && entry.hooks.some((handler) => isYamHookProfile(handler, profile));
|
|
1356
1496
|
}));
|
|
1357
1497
|
}
|
|
1358
1498
|
|
|
1359
1499
|
async function hookEnable(args = []) {
|
|
1360
1500
|
const parsed = parseHookArgs(args);
|
|
1361
|
-
if (parsed.profile
|
|
1362
|
-
console.error('Only
|
|
1501
|
+
if (!['lite', 'study-note'].includes(parsed.profile)) {
|
|
1502
|
+
console.error('Only lite and study-note hooks are supported: yam hook enable <lite|study-note>');
|
|
1363
1503
|
process.exitCode = 1;
|
|
1364
1504
|
return;
|
|
1365
1505
|
}
|
|
1366
1506
|
const target = hookPathFor(parsed);
|
|
1367
1507
|
const current = await readJsonOrDefault(target, {});
|
|
1368
|
-
const next =
|
|
1508
|
+
const next = withYamHook(current, parsed.profile);
|
|
1369
1509
|
await fsp.mkdir(path.dirname(target), { recursive: true });
|
|
1370
1510
|
if (await exists(target)) {
|
|
1371
1511
|
const backup = `${target}.yam-backup-${timestampId()}`;
|
|
@@ -1373,7 +1513,7 @@ async function hookEnable(args = []) {
|
|
|
1373
1513
|
console.log(`backup: ${backup}`);
|
|
1374
1514
|
}
|
|
1375
1515
|
await fsp.writeFile(target, `${JSON.stringify(next, null, 2)}\n`);
|
|
1376
|
-
console.log(`yam
|
|
1516
|
+
console.log(`yam-${parsed.profile} hook enabled (${parsed.mode}): ${target}`);
|
|
1377
1517
|
console.log('Restart Codex or start a new thread if the app does not pick up hook changes immediately.');
|
|
1378
1518
|
}
|
|
1379
1519
|
|
|
@@ -1381,22 +1521,22 @@ async function hookDisable(args = []) {
|
|
|
1381
1521
|
const parsed = parseHookArgs(args);
|
|
1382
1522
|
const target = hookPathFor(parsed);
|
|
1383
1523
|
const current = await readJsonOrDefault(target, {});
|
|
1384
|
-
if (!
|
|
1385
|
-
console.log(`yam
|
|
1524
|
+
if (!hookConfigHasProfile(current, parsed.profile)) {
|
|
1525
|
+
console.log(`yam-${parsed.profile} hook already disabled (${parsed.mode}): ${target}`);
|
|
1386
1526
|
return;
|
|
1387
1527
|
}
|
|
1388
|
-
const next =
|
|
1528
|
+
const next = stripYamHooks(current, parsed.profile);
|
|
1389
1529
|
if (Object.keys(next).length === 0) {
|
|
1390
1530
|
await rmrf(target);
|
|
1391
1531
|
} else {
|
|
1392
1532
|
await fsp.writeFile(target, `${JSON.stringify(next, null, 2)}\n`);
|
|
1393
1533
|
}
|
|
1394
|
-
console.log(`yam
|
|
1534
|
+
console.log(`yam-${parsed.profile} hook disabled (${parsed.mode}): ${target}`);
|
|
1395
1535
|
}
|
|
1396
1536
|
|
|
1397
1537
|
async function hookRun(args = []) {
|
|
1398
1538
|
const profile = args[0] || 'lite';
|
|
1399
|
-
if (
|
|
1539
|
+
if (!['lite', 'study-note'].includes(profile)) {
|
|
1400
1540
|
console.log(JSON.stringify({ continue: true }));
|
|
1401
1541
|
return;
|
|
1402
1542
|
}
|
|
@@ -1404,7 +1544,9 @@ async function hookRun(args = []) {
|
|
|
1404
1544
|
const event = input?.hook_event_name || input?.hookEventName || input?.event || 'UserPromptSubmit';
|
|
1405
1545
|
const cwd = String(input?.cwd || process.cwd());
|
|
1406
1546
|
const prompt = extractPrompt(input);
|
|
1407
|
-
const additionalContext =
|
|
1547
|
+
const additionalContext = profile === 'study-note'
|
|
1548
|
+
? await buildStudyNoteHookContext({ cwd })
|
|
1549
|
+
: await buildYamLiteContext({ cwd, prompt });
|
|
1408
1550
|
const output = {
|
|
1409
1551
|
continue: true,
|
|
1410
1552
|
hookSpecificOutput: {
|
|
@@ -1458,6 +1600,27 @@ async function buildYamLiteContext({ cwd, prompt }) {
|
|
|
1458
1600
|
return lines.join('\n');
|
|
1459
1601
|
}
|
|
1460
1602
|
|
|
1603
|
+
async function buildStudyNoteHookContext({ cwd }) {
|
|
1604
|
+
const dir = path.resolve(cwd || process.cwd());
|
|
1605
|
+
const changedFiles = await gitChangedFiles(dir);
|
|
1606
|
+
const lines = [
|
|
1607
|
+
'yam Study Note guard active: if this turn changes code, config, release metadata, docs, or project artifacts, include a Study Note in the final response.'
|
|
1608
|
+
];
|
|
1609
|
+
if (!changedFiles.length) {
|
|
1610
|
+
lines.push('No changed files were detected at prompt time; if you change artifacts during this turn, add the Study Note before final.');
|
|
1611
|
+
return lines.join('\n');
|
|
1612
|
+
}
|
|
1613
|
+
lines.push(`Changed files detected (${Math.min(changedFiles.length, 8)} shown): ${changedFiles.slice(0, 8).join(', ')}`);
|
|
1614
|
+
lines.push('Study Note minimum: touched code/artifact, role, execution point, before/after change, expected behavior, one syntax/structure insight, verification, and limits.');
|
|
1615
|
+
const hygiene = studyNoteHygieneRequirements(changedFiles);
|
|
1616
|
+
if (hygiene.length) {
|
|
1617
|
+
lines.push(`Architecture hygiene required: ${hygiene.map((item) => item.id).join(', ')}.`);
|
|
1618
|
+
lines.push('Report whether the change avoided dumping unrelated logic into page.tsx, one-off CSS into global.css, or structured product data into broad DB jsonb.');
|
|
1619
|
+
}
|
|
1620
|
+
lines.push('This hook is advisory; it does not generate or edit the Study Note.');
|
|
1621
|
+
return lines.join('\n');
|
|
1622
|
+
}
|
|
1623
|
+
|
|
1461
1624
|
function yamLiteRouteHint(prompt = '') {
|
|
1462
1625
|
const text = String(prompt || '').toLowerCase();
|
|
1463
1626
|
if (!text) return '';
|
|
@@ -2022,13 +2185,13 @@ function loopUsage() {
|
|
|
2022
2185
|
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.
|
|
2023
2186
|
|
|
2024
2187
|
Usage:
|
|
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]
|
|
2188
|
+
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] [--touched-file file] [--read-file file] [--verified-file file] [--skipped-check text] [--stop-condition text] [--resume-hint text] [--readiness-state usable|degraded|blocked|unknown] [--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]
|
|
2026
2189
|
`);
|
|
2027
2190
|
}
|
|
2028
2191
|
|
|
2029
2192
|
async function loopReport(args = []) {
|
|
2030
2193
|
if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h') return loopUsage();
|
|
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']));
|
|
2194
|
+
const flags = parseSimpleFlags(args, new Set(['route', 'intent', 'loop-kind', 'stage', 'stage-convention', 'evidence', 'evidence-level', 'evidence-stamp', 'source-digest', 'touched-file', 'read-file', 'verified-file', 'skipped-check', 'stop-condition', 'resume-hint', 'readiness-state', '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']));
|
|
2032
2195
|
const blockers = [...arrayFlag(flags.blocked), ...arrayFlag(flags.blocker)];
|
|
2033
2196
|
const report = buildLoopReport({
|
|
2034
2197
|
route: normalizeRoute(flags.route) || String(flags.route || ''),
|
|
@@ -2040,6 +2203,13 @@ async function loopReport(args = []) {
|
|
|
2040
2203
|
evidence_level: normalizeLoopEvidenceLevelFlag(flags.evidence_level),
|
|
2041
2204
|
evidence_stamp: String(flags.evidence_stamp || ''),
|
|
2042
2205
|
source_digest: String(flags.source_digest || ''),
|
|
2206
|
+
touched_files: arrayFlag(flags.touched_file),
|
|
2207
|
+
read_files: arrayFlag(flags.read_file),
|
|
2208
|
+
verified_files: arrayFlag(flags.verified_file),
|
|
2209
|
+
skipped_checks: arrayFlag(flags.skipped_check),
|
|
2210
|
+
stop_condition: String(flags.stop_condition || ''),
|
|
2211
|
+
resume_hint: String(flags.resume_hint || ''),
|
|
2212
|
+
readiness_state: normalizeReadinessStateFlag(flags.readiness_state),
|
|
2043
2213
|
covered_requirements: arrayFlag(flags.covered_requirement),
|
|
2044
2214
|
uncovered_requirements: arrayFlag(flags.uncovered_requirement),
|
|
2045
2215
|
blockers,
|
|
@@ -2094,7 +2264,7 @@ Usage:
|
|
|
2094
2264
|
yam ueye capture --url URL --out screenshot.png [--viewport 1440x900] [--full-page] [--json]
|
|
2095
2265
|
yam ueye compare --reference ref.png --actual screenshot.png [--json]
|
|
2096
2266
|
yam ueye preflight [dir] [--json]
|
|
2097
|
-
yam ueye report [--reference ref.png] [--actual screenshot.png] [--preflight-id id] [--p0-risk text] [--quality-gate-note text] [--brief-dimension text] [--constraint text] [--anti-slop text] [--invented-metric] [--placeholder-copy] [--generic-visual] [--review-session-id id] [--provider-context local] [--execution-surface in-app-browser] [--app-surface codex-app] [--browser-surface in-app-browser] [--control-mode manual|automated] [--preserved-state] [--preserved-url URL] [--completion-claim draft|needs-polish|done] [--strict] [--design-score n] [--p0 text] [--p1 text] [--states-checked] [--mobile-checked] [--contrast-checked] [--similar text] [--different text] [--missing text] [--resolved text] [--new-finding text] [--still-open text] [--regression text] [--viewport 1440x900] [--state default] [--design-quality pass|needs-polish|fails|not-checked] [--json]
|
|
2267
|
+
yam ueye report [--reference ref.png] [--actual screenshot.png] [--preflight-id id] [--p0-risk text] [--quality-gate-note text] [--brief-dimension text] [--constraint text] [--anti-slop text] [--invented-metric] [--placeholder-copy] [--generic-visual] [--acceptance-criterion text] [--touched-file file] [--read-file file] [--verified-file file] [--skipped-check text] [--residual-risk text] [--stop-condition text] [--resume-hint text] [--deep-visual-check text] [--design-system-evidence text] [--implementation-evidence text] [--state-check default:pass] [--review-session-id id] [--provider-context local] [--execution-surface in-app-browser] [--app-surface codex-app] [--browser-surface in-app-browser] [--control-mode manual|automated] [--preserved-state] [--preserved-url URL] [--completion-claim draft|needs-polish|done] [--strict] [--design-score n] [--p0 text] [--p1 text] [--states-checked] [--mobile-checked] [--contrast-checked] [--similar text] [--different text] [--missing text] [--resolved text] [--new-finding text] [--still-open text] [--regression text] [--viewport 1440x900] [--state default] [--design-quality pass|needs-polish|fails|not-checked] [--json]
|
|
2098
2268
|
|
|
2099
2269
|
Notes:
|
|
2100
2270
|
capture uses a locally available Playwright install when present. It does not download browsers or install dependencies.
|
|
@@ -2331,7 +2501,7 @@ async function ueyeCompare(args = []) {
|
|
|
2331
2501
|
|
|
2332
2502
|
async function ueyeReport(args = []) {
|
|
2333
2503
|
if (args[0] === 'help' || args[0] === '--help' || args[0] === '-h') return ueyeUsage();
|
|
2334
|
-
const flags = parseSimpleFlags(args, new Set(['reference', 'ref', 'actual', 'screenshot', 'capture-backend', 'compare-backend', 'design-quality', 'blocked-reason', 'next-action', 'next-visual-action', 'review-session-id', 'preflight-id', 'p0-risk', 'quality-gate-note', 'brief-dimension', 'constraint', 'anti-slop', 'invented-metric', 'placeholder-copy', 'generic-visual', 'reference-id', 'screenshot-id', 'previous-screenshot-id', 'current-screenshot-id', 'previous-report', 'comparison-notes', 'similar', 'different', 'missing', 'resolved', 'new-finding', 'still-open', 'regression', 'viewport', 'state', 'provider-context', 'provider-badge', 'execution-surface', 'app-surface', 'browser-surface', 'control-mode', 'preserved-state', 'preserved-url', 'url', 'evidence-id', 'completion-claim', 'completion-status', 'gate-mode', 'strict', 'design-score', 'min-design-score', 'p0', 'p1', 'open-p0', 'open-p1', 'states-checked', 'mobile-checked', 'responsive-checked', 'contrast-checked', 'accessibility-checked', 'cta-checked', 'direction-locked', 'reference-read', 'comparison-result', 'json']));
|
|
2504
|
+
const flags = parseSimpleFlags(args, new Set(['reference', 'ref', 'actual', 'screenshot', 'capture-backend', 'compare-backend', 'design-quality', 'blocked-reason', 'next-action', 'next-visual-action', 'review-session-id', 'preflight-id', 'p0-risk', 'quality-gate-note', 'brief-dimension', 'constraint', 'anti-slop', 'invented-metric', 'placeholder-copy', 'generic-visual', 'acceptance-criterion', 'touched-file', 'read-file', 'verified-file', 'skipped-check', 'residual-risk', 'stop-condition', 'resume-hint', 'deep-visual-check', 'design-system-evidence', 'implementation-evidence', 'state-check', 'reference-id', 'screenshot-id', 'previous-screenshot-id', 'current-screenshot-id', 'previous-report', 'comparison-notes', 'similar', 'different', 'missing', 'resolved', 'new-finding', 'still-open', 'regression', 'viewport', 'state', 'provider-context', 'provider-badge', 'execution-surface', 'app-surface', 'browser-surface', 'control-mode', 'preserved-state', 'preserved-url', 'url', 'evidence-id', 'completion-claim', 'completion-status', 'gate-mode', 'strict', 'design-score', 'min-design-score', 'p0', 'p1', 'open-p0', 'open-p1', 'states-checked', 'mobile-checked', 'responsive-checked', 'contrast-checked', 'accessibility-checked', 'cta-checked', 'direction-locked', 'reference-read', 'comparison-result', 'json']));
|
|
2335
2505
|
const reference = String(flags.reference || flags.ref || '');
|
|
2336
2506
|
const actual = String(flags.actual || flags.screenshot || '');
|
|
2337
2507
|
const referenceSources = [];
|
|
@@ -2436,6 +2606,20 @@ async function ueyeReport(args = []) {
|
|
|
2436
2606
|
direction_locked: Boolean(flags.direction_locked),
|
|
2437
2607
|
reference_read: Boolean(flags.reference_read)
|
|
2438
2608
|
},
|
|
2609
|
+
deep_visual_review: {
|
|
2610
|
+
acceptance_criteria: arrayFlag(flags.acceptance_criterion),
|
|
2611
|
+
touched_files: arrayFlag(flags.touched_file),
|
|
2612
|
+
read_files: arrayFlag(flags.read_file),
|
|
2613
|
+
verified_files: arrayFlag(flags.verified_file),
|
|
2614
|
+
skipped_checks: arrayFlag(flags.skipped_check),
|
|
2615
|
+
residual_risks: arrayFlag(flags.residual_risk),
|
|
2616
|
+
stop_condition: String(flags.stop_condition || ''),
|
|
2617
|
+
resume_hint: String(flags.resume_hint || ''),
|
|
2618
|
+
deep_visual_checks: arrayFlag(flags.deep_visual_check),
|
|
2619
|
+
design_system_evidence: arrayFlag(flags.design_system_evidence),
|
|
2620
|
+
implementation_evidence: arrayFlag(flags.implementation_evidence),
|
|
2621
|
+
state_check: arrayFlag(flags.state_check)
|
|
2622
|
+
},
|
|
2439
2623
|
blocked_reason: blockedReason,
|
|
2440
2624
|
next_action: String(flags.next_visual_action || flags.next_action || '')
|
|
2441
2625
|
});
|
|
@@ -4193,6 +4377,7 @@ async function main() {
|
|
|
4193
4377
|
if (command === 'measure') return measure(process.argv[3], process.argv.slice(4));
|
|
4194
4378
|
if (command === 'tools') return tools(process.argv.slice(3));
|
|
4195
4379
|
if (command === 'proof') return proof(process.argv.slice(3));
|
|
4380
|
+
if (command === 'study-note') return studyNote(process.argv.slice(3));
|
|
4196
4381
|
if (command === 'loop') return loop(process.argv.slice(3));
|
|
4197
4382
|
if (command === 'ueye') return ueye(process.argv.slice(3));
|
|
4198
4383
|
if (command === 'media') return media(process.argv.slice(3));
|