fix: align eager, lazy, and LCP image hints with HTML standard - #141
Conversation
|
👋 Jules, reporting for duty! I'm here to lend a hand with this pull request. When you start a review, I'll add a 👀 emoji to each comment to let you know I've read it. I'll focus on feedback directed at me and will do my best to stay out of conversations between you and other bots or reviewers to keep the noise down. I'll push a commit with your requested changes shortly after. Please note there might be a delay between these steps, but rest assured I'm on the job! For more direct control, you can switch me to Reactive Mode. When this mode is on, I will only act on comments where you specifically mention me with New to Jules? Learn more at jules.google/docs. For security, I will only act on instructions from the user who triggered this task. |
📝 WalkthroughWalkthrough홈페이지 이미지 렌더링 힌트 계약을 정리했습니다. eager 이미지는 기본 Changes이미지 렌더링 힌트
Estimated code review effort: 3 (Moderate) | ~20 minutes 🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
OpenCode Review Overview
Changed-File Evidence Mapflowchart LR
PR["PR changed files"] --> Evidence["OpenCode bounded evidence"]
Evidence --> S1["Changed file (3 files)"]
S1 --> I1["repository behavior"]
I1 --> R1["Review risk: Changed file (3 files)"]
R1 --> V1["required checks"]
Evidence --> S2["Docs: image-rendering-hints.md"]
S2 --> I2["operator or user guidance"]
I2 --> R2["Review risk: Docs: image-rendering-hints.md"]
R2 --> V2["docs review"]
Evidence --> S3["Test: test_styles.py"]
S3 --> I3["regression suite"]
I3 --> R3["Review risk: Test: test_styles.py"]
R3 --> V3["targeted test run"]
|
There was a problem hiding this comment.
Pull request overview
OpenCode reviewed the current-head bounded evidence and found no blocking issues.
Findings
No blocking findings.
Summary
APPROVE for PR #141 head 1511c06. Changed files inspected as evidence: index.html (decoding="async" removed from the eager brand avatar and hero context-art img; fetchpriority="high" and lazy hints retained), tests/test_styles.py (non-vacuous eager/lazy/LCP contracts), docs/doctoring/image-rendering-hints.md (new decision doc with WHATWG/web.dev references), CHANGELOG.md, .jules/bolt.md. Approval sufficiency: diff, tests, docs, and changelog all agree with the PR intent; failed-check evidence reports no completed failed checks and no unresolved review threads. Verification posture: trusted Coverage execution evidence reports Result: PASS with supported repository test suites passed at head; no OPENCODE_EXECUTION_RECEIPT runtime lines exist in bounded evidence, so no browser/runtime execution claim is made. Linter/static: no active failed checks; lint_commands names only hadolint Dockerfile (unchanged by this PR). TDD/regression: new assertions guard against vacuous passes (tests/test_styles.py:69 eager non-empty, :79 lazy non-empty and decoding==async, :91-94 exactly one fetchpriority=high candidate that is not lazy and has no decoding). Coverage: cites Coverage execution evidence Result: PASS (supported repository test suites passed). Docstring coverage: configured repository docstring gates passed or docstring coverage was advisory per Coverage execution evidence. DAG: flowchart 'index.html img attributes -> _homepage_images() -> eager/lazy/LCP assertions -> image-rendering-hints.md contract' reflects head-state static-markup flow (CodeGraph has no node for the HTML surface, so it is source-backed). PoC/execution: the coverage gate is the only trusted test outcome supplied; no standalone PoC receipts exist. DDD/domain: static-site domain unchanged, no domain-model impact. CDD/context: no new context or data boundary introduced. Similar issues: prior commits 9d54cd8 (preserve async decoding) and 00acc72 (Bolt LCP optimization) are superseded by the corrected hint policy, consistent with the new .jules/bolt.md entry. Claim/concept check: omitting decoding selects the HTML Standard auto missing-value default (preference hint, not guaranteed thread path), matching the cited WHATWG spec; docs disclaim a guaranteed LCP gain. Standards search: WHATWG HTML img element and web.dev Fetch Priority reference cited at docs/doctoring/image-rendering-hints.md:26. Compatibility/convention: no new identifiers or reserved words introduced; removed attributes do not alter tests/test_index_security.py CSP/inline-content checks. Breaking-change/backcompat: static markup only; a missing attribute is the valid default in all browsers; no API or backcompat surface. Implementation completeness: markup, tests, docs, and changelog are all updated; no placeholder or TODO-only code introduced. Performance: hint removal on two eager SVGs; real-world LCP claims are deliberately bound to post-deployment measurement. Developer experience: .jules/bolt.md learning entry and the decision doc record corrected reasoning for future maintainers. User experience: no visible rendering change; alt/aria attributes preserved. Visual/DOM: static attribute change reviewed via focused hunks; no Playwright/DOM/ARIA receipts exist in bounded evidence. Accessibility/i18n: hero img retains aria-hidden="true" and the brand avatar retains alt=""; data-i18n nodes untouched. Supply-chain/license: zero dependency changes. Packaging: unpackaged_source_surfaces lists pre-existing Python/Node test surfaces; the changed tests are executed by the trusted coverage gate, so the missing manifest predates this PR and adds no new risk. Security/privacy: no new sinks, no inline content, CSP-adjacent surface unchanged. Non-blocking nit noted in prose: inline comments at index.html:32/:69 still say 'for SVG/LCP optimization', slightly overstating the corrected claim.
Approval sufficiency: bounded evidence supplied affirmative approval evidence for changed files, coverage/docstring posture, risk surfaces, and current-head verification; approval is not based merely on the absence of known blockers.
Verification posture: CodeGraph evidence was initialized and bounded current-head evidence reviewed for changed-file evidence including .jules/bolt.md, CHANGELOG.md, docs/doctoring/image-rendering-hints.md, index.html, tests/test_styles.py.
Linter/static: workflow/static review evidence is bounded by the current-head GitHub Checks gate and changed-file evidence.
TDD/regression: coverage execution evidence and focused changed hunks were reviewed from bounded-review-evidence.md.
Coverage: coverage execution evidence reports supported repository test suites passed.
Docstring coverage: coverage execution evidence reports configured repository docstring gates passed or docstring coverage was advisory.
DAG: CodeGraph/source-backed behavior map connects .jules/bolt.md to the affected review, runtime, or workflow path and required checks.
PoC/execution: coverage-evidence job executed on the current head and reported PASS.
DDD/domain: workflow and repository-governance invariants were reviewed against changed files in bounded evidence.
CDD/context: CodeGraph evidence, changed-file history, and focused hunks were reviewed from bounded-review-evidence.md.
Similar issues: changed-file history evidence was reviewed for comparable local precedents.
Claim/concept check: bounded evidence, repository source, current-head workflow evidence, and, where numeric, scientific, statistical, or literature-backed claims are affected, original-paper/formula evidence and parameter-recovery expectations were used for claims.
Standards search: standards and external-source claims require trusted bounded source evidence prepared outside the isolated model process; no evidence-backed standards blocker is present in bounded evidence.
Compatibility/convention: changed workflow/script conventions, object naming, and reserved-word safety for schema/API/config/code surfaces were checked in bounded evidence.
Breaking-change/backcompat: deployment evidence and changed-file history were checked for backward-compatibility risk.
Performance: changed surfaces were checked for performance risk in bounded evidence.
Developer experience: changed automation, review, test, setup, and maintenance surfaces were checked for helpful or obstructive DX impact in bounded evidence.
User experience: connected user, operator, API, CLI, documentation, review-comment, status-check, rendering, and workflow-reader behavior was checked for contradictions against code, docs, and tests in bounded evidence.
Visual/DOM: deterministic repair does not infer browser runtime execution; source-backed DOM/UI evidence and trusted workflow receipts were reviewed when present, and non-web surfaces used API/CLI/log/docs/workflow evidence instead.
Accessibility/i18n: accessibility, localization, and human-readable text surfaces were checked where UI, CLI, API message, docs, logs, or review text changed.
Supply-chain/license: dependency, package, model, container, and external-tool changes were checked in bounded evidence.
Packaging: package, build, test, lint, and security contracts were checked in bounded evidence.
Security/privacy: workflow-token, review-gate, and repository-automation security/privacy boundaries were checked in bounded evidence.
Adversarial validation
{"status":"passed","probes":[{"path":"index.html","line":32,"hypothesis":"The eager-image decode contract could be broken or pass vacuously: if the patch had stripped decoding from below-the-fold lazy images or left decoding on the eager brand avatar, test_eager_images_leave_decoding_to_the_user_agent / test_lazy_images_decode_asynchronously would fail or silently pass on an empty set.","attack_or_counterexample":"Removed decoding attribute from the wrong image set (all images, or lazy ones) or left the eager set empty so assertions never executed.","evidence":"Trusted Coverage execution evidence for head 1511c06d3e4a1dba9b6207ffb1e9f60cd3001507 reports Result: PASS with supported repository test suites passed, and the CodeGraph verbatim source of tests/test_styles.py:69,79-80 shows the eager set must be non-empty and every lazy image must keep decoding==async; the focused diff removes decoding only from the two eager imgs (brand avatar and hero) and the source trace at index.html:32 shows the eager brand avatar img now omits the attribute exactly as the executed contract requires. source-line-sha256=0c189ea83be403e5803e357b561292edb1f9594ead7a0c2836f4f8606abe1be5","outcome":"falsified"},{"path":"index.html","line":69,"hypothesis":"The single-LCP-candidate contract is not actually enforced: if the hero img had lost fetchpriority=\"high\" or a second img had gained fetchpriority=\"high\", test_lcp_candidate_is_eager_and_high_priority would fail or pass vacuously.","attack_or_counterexample":"Mutated markup where the hero context-art img drops fetchpriority or another img carries fetchpriority=high, breaking the len(lcp_candidates)==1 and decoding-is-None assertions.","evidence":"Trusted Coverage execution evidence PASS at head confirms the suite (including tests/test_styles.py:91-94: exactly one fetchpriority=high candidate, loading != lazy, decoding is None) executed green; the focused diff at index.html:69 shows the hero context-art img retains fetchpriority=\"high\" and drops only decoding with no loading=\"lazy\" added, and no other img attribute changes appear in the diff, so the single-candidate and eager contract is enforced by the executed tests rather than by accident. source-line-sha256=2d353b4da37fe79a7fdeb94337b786ffafde13797e39073fa68f1f362d8ecd1b","outcome":"falsified"}],"residual_risk":"The real-world LCP effect of dropping decoding=\"async\" is intentionally unmeasured at head (deferred to post-deployment field/lab measurement per docs/doctoring/image-rendering-hints.md); the inline HTML comments at index.html:32 and :69 still carry the older 'SVG/LCP optimization' phrasing that slightly overstates the corrected, evidence-bounded claim. Both items are cosmetic or measurement-bound with no functional, security, or compatibility risk."}- Result: APPROVE
- Reason: Static image-hint change aligns with the HTML Standard's auto missing-value default, is covered by non-vacuous regression tests that passed the trusted coverage gate, is documented with evidence-bounded claims, and has no failed checks or unresolved threads.
- Head SHA:
1511c06d3e4a1dba9b6207ffb1e9f60cd3001507 - Workflow run: 31189203709
- Workflow attempt: 1
What
decoding="async"from eager first-viewport images and the single declared LCP candidate, leaving the standards-defined missing-value default (auto) to the user agent.decoding="async"for explicitly lazy-loaded images.docs/doctoring/image-rendering-hints.md.Why
The HTML Living Standard defines
decodingas a preference hint whose missing-value default isauto. It does not guarantee a main-thread or background-thread execution path.fetchpriorityindependently influences fetch priority. This PR therefore avoids claiming that removingdecoding="async"alone universally improves LCP.Verification required at the exact current head
python3 -m pytest tests/References
This PR supersedes the stale duplicate #100 by carrying forward its valid standards reasoning and stronger non-vacuous tests on the current base.
Summary by CodeRabbit
성능 개선
문서
테스트