# HDR Web Plugin Agent Manual ## Scope This file applies to the entire repository. Use Chinese when talking with the project owner unless they ask for another language. Keep implementation work simple, direct, and narrowly scoped. Reuse existing files, functions, scripts, media conventions, and tests before adding new structure. Follow higher-priority system and developer instructions first. When replacing an implementation, remove the old path in the same change so the repository does not keep parallel implementations. ## Product Summary HDR Web Plugin is a static Cloudflare Pages site plus a drop-in JavaScript file that makes ordinary pages present a black-stage HDR media layer, optional HDR text assets, and a small runtime UI. Current public site: - Production Pages project: `hdr-web-plugin-demo` - Production URL: `https://hdr-web-plugin-demo.pages.dev/` - Main plugin URL: `https://hdr-web-plugin-demo.pages.dev/dist/hdr-web-plugin.js?v=0.6.2` - Real starfield demo URL: `https://hdr-web-plugin-demo.pages.dev/demos/fireworks.html?v=0.6.9` Important version facts: - `package.json` version: `0.6.2` - `dist/hdr-web-plugin.js` banner version: `0.6.2` - Current CSS cache query version used by pages: `0.6.9` - Current starfield asset: `media/hubble-westerlund-2-hdr.png` The route `demos/fireworks.html` is kept for URL compatibility with earlier demos, but its current product meaning is a real astronomy starfield HDR image demo. Do not reintroduce the old WebGL fireworks path unless the owner explicitly asks for a separate new demo. If a replacement is made, delete stale scripts, markup references, and generated copies. ## Repository Map - `src/hdr-enhance.js`: canonical plugin source. - `dist/hdr-web-plugin.js`: generated plugin bundle with the version banner. Do not edit this file by hand; run `npm run build`. - `index.html`: one-page landing page for installation, API notes, assets, and demo links. - `demos/*.html`: standalone demos that use the same plugin and site chrome. - `styles/demo.css`: shared landing/demo CSS. Bump query strings in HTML when changing this file. - `media/`: committed HDR media assets and generated visual assets. - `scripts/build-dist.mjs`: copies `src/hdr-enhance.js` into `dist/hdr-web-plugin.js` with a banner. - `scripts/generate-hdr-media.mjs`: creates HDR video demo media. - `scripts/generate-hdr-image.mjs`: creates landing prism HDR image. - `scripts/generate-hdr-wordmark.mjs`: creates HDR PNG text/wordmark assets. - `scripts/generate-real-starfield-image.mjs`: downloads the ESA/Hubble source image and writes the HDR PNG starfield. - `test/*.mjs`: Node test suite covering plugin behavior, landing page structure, HDR metadata, and demo constraints. - `_headers`: Cloudflare Pages static header rules. This file must be copied into the upload/build output. - `public/`: generated Cloudflare Pages upload bundle. It is intentionally ignored by Git; regenerate it before deployment. ## Engineering Rules - Prefer the smallest working change that solves the current request. - Do not add abstractions for hypothetical future needs. - Add an abstraction only when it removes current duplication or matches an existing local pattern. - Do not keep old and new implementations side by side after a replacement. - Never revert user work unless the user explicitly asks. - Use `rg` or `rg --files` for searching. - Use `apply_patch` for manual source edits. - Avoid broad refactors while changing visual design, media, or deployment docs. - Update tests when changing behavior, generated media expectations, file structure, or production operations. - Update this `AGENTS.md` when production URLs, deployment commands, cache strategy, HDR asset formats, or ownership rules change. ## Local Development Install and build: ```bash npm run build npm test ``` Run a local static server: ```bash python3 -m http.server 4173 ``` Open locally: - Landing page: `http://localhost:4173/` - Starfield demo: `http://localhost:4173/demos/fireworks.html?v=0.6.9` The test script runs `npm run build` in `pretest`, so `dist/hdr-web-plugin.js` should stay aligned with `src/hdr-enhance.js` after every test run. ## HDR Implementation Notes Real HDR on macOS depends on the full chain: - HDR-capable Apple display or external HDR display. - macOS display setting with HDR enabled where applicable. - Browser path that supports HDR media rendering. - Black page background so bright HDR media has visible contrast. - Media encoded with HDR metadata, usually BT.2020 primaries and SMPTE ST 2084/PQ transfer. - Avoid CSS filters, opacity stacks, or canvas readbacks on true HDR assets unless verified. These can flatten or tone-map the output. For high-brightness text, prefer HDR PNG assets produced by `scripts/generate-hdr-wordmark.mjs` instead of normal DOM text. Ordinary CSS text is normally SDR-composited by browsers and will not visibly exceed SDR white in the same way as an HDR image/video layer. Current HDR PNG checks expected by tests: - `pix_fmt=rgba64be` - `color_transfer=smpte2084` - `color_primaries=bt2020` - PNG bit depth: `16` - PNG color type: `6` (RGBA) Use `ffprobe` to inspect a media asset: ```bash ffprobe -v error -select_streams v:0 \ -show_entries stream=pix_fmt,color_transfer,color_primaries \ -of default=nw=1 media/hubble-westerlund-2-hdr.png ``` ## Starfield Asset Policy The real starfield demo uses the NASA/ESA Hubble Westerlund 2 image through the ESA/Hubble archive source URL embedded in `scripts/generate-real-starfield-image.mjs`: ```text https://esahubble.org/media/archives/images/large/heic1509a.jpg ``` The generator creates `media/hubble-westerlund-2-hdr.png` at `2560x1440`. Keep that size unless there is a clear reason to change it; it gives an immersive full-screen result while keeping the file size manageable for Pages. The visible credit must remain available on the demo page: ```text Westerlund 2 ยท NASA, ESA, the Hubble Heritage Team ``` Do not replace the real starfield with abstract particles, shader bloom, simulated fireworks, gradients, or decorative blobs when the user asks for a true starfield. ## Generated Bundle Sync Cloudflare Pages deploys from a static directory. In this repository, use `public/` as the local upload bundle. Regenerate `public/` from source after tests pass: ```bash rm -rf public mkdir -p public cp -R index.html _headers dist styles demos media public/ ``` Do not edit files inside `public/` directly. If `public/` contains a stale file after a feature replacement, regenerate it from source so old paths disappear. ## Cache Strategy This project uses long cache headers for versioned static assets and no-cache headers for HTML. Current `_headers` intent: - `/dist/*`: immutable long cache. - `/styles/*`: immutable long cache. - `/media/*`: immutable long cache. - `/*.html` and `/`: revalidate. Because `dist/`, `styles/`, and `media/` are immutable in production, update HTML query strings when changing CSS or plugin JS. For media changes, either use a new filename or update every URL/query string that points at the changed asset. Cloudflare Pages also has deploy-level caching behavior, so never assume a changed asset path will refresh immediately if the URL did not change. Official references: - Cloudflare Pages headers: `https://developers.cloudflare.com/pages/configuration/headers/` - Cloudflare Pages serving and cache behavior: `https://developers.cloudflare.com/pages/configuration/serving-pages/` ## Production Deployment Manual Use this checklist for every production deployment. 1. Inspect repository state. ```bash git status --short --branch git remote -v ``` If unexpected modified files exist, inspect them and preserve user work. Do not reset the worktree. 2. Run the full test suite. ```bash npm test ``` 3. Verify important HDR media metadata when media changed. ```bash ffprobe -v error -select_streams v:0 \ -show_entries stream=pix_fmt,color_transfer,color_primaries \ -of default=nw=1 media/hubble-westerlund-2-hdr.png ffprobe -v error -select_streams v:0 \ -show_entries stream=pix_fmt,color_transfer,color_primaries \ -of default=nw=1 media/hdr-wordmark.png ``` Expected output includes `rgba64be`, `smpte2084`, and `bt2020`. 4. Regenerate the Pages upload bundle. ```bash rm -rf public mkdir -p public cp -R index.html _headers dist styles demos media public/ ``` 5. Deploy with Wrangler. Use the latest locally verified Wrangler if available. This command shape is known to work for this project: ```bash npx --yes wrangler@4 pages deploy public \ --project-name=hdr-web-plugin-demo \ --branch=main \ --commit-message="Deploy HDR Web Plugin" \ --commit-dirty=true ``` If the repository has no commit yet, Wrangler can print a Git warning about `HEAD`. If the command still returns a successful Pages deployment URL, treat the Git warning as non-fatal and continue verification. 6. Verify production URLs. ```bash curl -I https://hdr-web-plugin-demo.pages.dev/ curl -I https://hdr-web-plugin-demo.pages.dev/styles/demo.css?v=0.6.9 curl -I https://hdr-web-plugin-demo.pages.dev/dist/hdr-web-plugin.js?v=0.6.2 curl -I https://hdr-web-plugin-demo.pages.dev/media/hubble-westerlund-2-hdr.png ``` Open these URLs in a browser after deployment: - `https://hdr-web-plugin-demo.pages.dev/` - `https://hdr-web-plugin-demo.pages.dev/demos/fireworks.html?v=0.6.9` Check that: - The landing page is one coherent page, not split into mismatched subpages. - Navigation styling is consistent. - Backgrounds intended for HDR contrast are true black. - The starfield demo is a real full-screen astronomy image. - No old `fireworks-webgl.js` script is loaded. - The console has no JavaScript errors. 7. Record the outcome. If working in Git, commit the source changes after verification. If a Gitea remote is configured, push the branch. ## Rollback Manual For urgent production rollback: 1. Prefer the Cloudflare Pages dashboard rollback for the project `hdr-web-plugin-demo` when an immediately previous deployment is known good. 2. If using CLI, inspect available deployments first: ```bash npx --yes wrangler@4 pages deployment list --project-name=hdr-web-plugin-demo ``` 3. Do not guess an unsupported rollback command. If the CLI rollback path is unclear, use the dashboard. 4. For source-controlled rollback, use `git revert `, run `npm test`, regenerate `public/`, deploy the reverted source, and verify production. Never use `git reset --hard` or force-push as a production rollback unless the owner explicitly asks for that exact operation. ## Incident Runbooks ### Stale CSS, JS, Or Media Symptoms: - Production looks like the previous version. - Browser loads an old CSS/plugin/media file. - Local preview is correct but Pages is stale. Actions: 1. Confirm the HTML references the intended versioned URL. 2. Bump the CSS or plugin query string, or use a new media filename. 3. Run `npm test`. 4. Regenerate `public/`. 5. Deploy again. 6. Use `curl -I` and browser DevTools Network to confirm the new URL is served. ### HDR Is Not Visibly Strong Symptoms: - User reports that text or media still looks SDR. - Bright image layer looks stronger than text. Actions: 1. Confirm the page background is pure black where HDR should be judged. 2. Confirm macOS and the target display have HDR enabled. 3. Confirm browser support with `matchMedia('(dynamic-range: high)')`. 4. Verify media metadata with `ffprobe`. 5. Avoid normal DOM text for peak HDR claims; use generated HDR PNG text assets. 6. Check CSS for `filter`, opacity, blend modes, canvas rendering, or parent effects that can flatten HDR. 7. If using a new text asset, regenerate it through `scripts/generate-hdr-wordmark.mjs` or add a focused generator script and test its metadata. ### Page Is Blank Or Broken Actions: 1. Open browser DevTools Console and Network. 2. Check that all referenced assets exist in source and in regenerated `public/`. 3. Run `rg` for missing filenames and stale references. 4. Run `npm test`. 5. Verify that HTML paths work from both local root and Pages root. ### Performance Regression Actions: 1. Prefer static HDR image/video layers over custom per-frame WebGL for showcase backgrounds. 2. Remove unnecessary continuous animations. 3. Keep demo pages full-screen but visually simple. 4. Avoid large blur filters, huge box shadows, and many animated particles. 5. Test on the target Mac browser before deployment. ### Wrangler Or Cloudflare Auth Problem Actions: ```bash npx --yes wrangler@4 whoami npx --yes wrangler@4 login ``` If login is required, ask the owner to complete the browser auth flow. Do not commit `.wrangler/`. ## Gitea Alignment Manual This repository must be kept commit-ready. Before committing: ```bash git status --short --branch npm test ``` Current Gitea repository: - Web: `https://git.aiot.ml/kanshan/HDR` - Git remote: `https://git.aiot.ml/kanshan/HDR.git` - Default branch: `main` - `tea` login profile: `git-aiot` Use the HTTPS remote for this repository. The Gitea SSH endpoint on port `2222` may be unavailable from the current network, while HTTPS push works through the `tea` credential helper. Ensure the helper is installed before pushing: ```bash tea logins helper setup git remote -v git push -u origin main ``` Recommended source files to commit: - `AGENTS.md` - `.gitignore` - `README.md` - `_headers` - `package.json` - `index.html` - `src/` - `dist/` - `styles/` - `demos/` - `scripts/` - `media/` - `test/` Do not commit: - `.wrangler/` - `public/` - `node_modules/` - temporary media source downloads under `media/.*-source.*` If `git remote -v` is empty, a Gitea push cannot be completed from this machine until the remote URL is configured. Configure a Gitea remote only with the exact owner-provided URL: ```bash git remote add origin git push -u origin main ``` To create a new repository with the configured `tea` account, first verify that the name is unused, then create an empty server-side repository without README initialization so the local history remains authoritative: ```bash tea repos list --owner kanshan tea repos create --name \ --description "" git remote add origin https://git.aiot.ml/kanshan/.git tea logins helper setup git push -u origin main ``` If a remote already exists: ```bash git fetch origin git status --short --branch git push origin main ``` Do not force-push to Gitea unless the owner explicitly requests it. ## Pre-Final Agent Checklist Before telling the user the work is done: 1. Run `npm test`. 2. Confirm `git status --short --branch`. 3. Confirm old replaced paths are gone with `rg --files`. 4. If production changed, verify the deployed Pages URL. 5. If Git was requested, commit locally and push only when a remote is configured. 6. Report any missing external state plainly, especially missing Gitea remote or Cloudflare auth.