updated agents.md

This commit is contained in:
thePR0M3TH3AN committed 2025-10-07 17:40:12 -04:00
1 parent fe0e023bd7
commit c1ae2c8c9f
1 file changed
+79 -33
+79 -33
View File
@@ -8,14 +8,14 @@ This guide tells AI agents how to keep Bitvid aligned with the current product d
* **Main** is the production track. Anything merged here must preserve today’s UX and magnet safety guarantees. Rollbacks should be painless: keep commits atomic, avoid destructive migrations, and leave feature flags in a known-good default (`false` unless product explicitly flips them).
* **Unstable** is our experimentation lane. Gate risky behavior behind feature flags defined in `js/constants.js` and document the toggle/rollback plan in PR descriptions.
* **Emergency response:** If a change regresses URL-first playback or breaks magnet parsing, revert immediately and annotate the AGENTS.md changelog with remediation tips so future agents do not repeat the mistake.
* **Emergency response:** If a change regresses URL-first playback or breaks magnet parsing, revert immediately, call this out in the PR, and annotate the AGENTS.md changelog with remediation tips. **Note:** These regressions usually surface in dev logs and tests around playback/magnet helpers—reference them when triaging so future agents don’t repeat the mistake.
## 2. Mission: URL‑First Playback with WebTorrent Fallback
* **Goal:** Always deliver smooth playback while keeping hosting costs low.
* **Primary transport:** A hosted video URL (MP4/WebM/HLS/DASH) that the `<video>` element can stream directly.
* **Fallback transport:** A WebTorrent magnet that includes browser‑safe trackers plus optional HTTP hints.
* **Runtime behavior:** Call `playVideoWithFallback({ url, magnet })` (see `js/playbackUtils.js`). It probes the URL first; only when that fails should WebTorrent start.
* **Runtime behavior:** Call `bitvidApp.playVideoWithFallback({ url, magnet })` in `js/app.js`. This function orchestrates URL probing and magnet fallback, delegating low-level stream handling to `js/services/playbackService.js`. `js/playbackUtils.js` now provides magnet/session helper utilities rather than the playback entry point itself.
* **Content contract:** Bitvid posts (Nostr kind `30078`) must include a `title` and at least one of `url` or `magnet`. Prefer to publish both along with optional `thumbnail`, `description`, and `mode` fields. When mirroring to NIP‑94 (`kind 1063`), copy the hosted URL and (optionally) the magnet so other clients can discover the same asset.
---
@@ -24,9 +24,10 @@ This guide tells AI agents how to keep Bitvid aligned with the current product d
* **Use the helpers every time:** Always run inbound values through `safeDecodeMagnet()` before playback or normalization, and call `normalizeAndAugmentMagnet()` (see `js/magnetUtils.js`) to append `ws=` / `xs=` hints without mutating hashes.
* **Keep magnets raw:** Persist the literal `magnet:?xt=urn:btih:...` string. Decode once, then feed that exact value to WebTorrent or storage. Never rely on re-encoding helpers that might alter casing.
* **Never call `new URL()` on magnets:** URL constructors/`URLSearchParams` percent-encode the `xt` payload and corrupt legacy hashes. Manipulate magnets with the helper utilities or string functions that respect the raw hash.
* **Never call `new URL()` on magnets:** URL constructors/`URLSearchParams` percent-encode the `xt` payload and can corrupt legacy hashes. Manipulate magnets with the helper utilities or string functions that respect the raw hash.
* **HTTP hints:** Encourage HTTPS `ws=` web seeds (file roots only) and HTTPS `xs=` pointers to `.torrent` files so fallback peers warm quickly.
* **Tracker policy:** Browser code must ship WSS trackers only. Pull the canonical list from `js/constants.js`; do not add UDP or plaintext HTTP trackers.
* **Tracker policy:** Browser code must ship **WSS trackers only**. Pull the canonical list from `js/constants.js`; do not add UDP or plaintext HTTP trackers. (If you introduce a new tracker set or feature flag, update `js/constants.js` and mention it here.)
* **Validation reference:** When in doubt about legacy infohash handling or normalization, consult the existing tests that cover legacy/bare infohash inputs and magnet normalization. If you extend helper behavior, extend those tests alongside the code.
---
@@ -46,50 +47,41 @@ This guide tells AI agents how to keep Bitvid aligned with the current product d
Run this script before shipping notable UI changes, especially around upload/playback flows. Automate when possible, but manual verification is required for releases.
1. **Smoke test the modal**
* Launch the site, open the Upload modal, and confirm required-field validation (title + one of URL/magnet).
* Submit with URL only, magnet only, and both; ensure success states are clear.
2. **URL-first playback**
* Publish a post with both URL and magnet. Load the card and verify the player fetches the hosted URL first (check network tab or logs).
* Temporarily block the URL (e.g., devtools throttling or offline). Confirm playback seamlessly falls back to the magnet.
3. **Magnet hygiene**
* Paste an encoded magnet; ensure `safeDecodeMagnet()` returns the raw value and the final string still includes the original `xt` hash.
* Confirm `normalizeAndAugmentMagnet()` appends `ws=`/`xs=` hints without corrupting parameters.
4. **P2P hints**
* Verify magnets authored through the modal include HTTPS `ws=` and optional `xs=` values when provided.
* Ensure tracker lists come from `js/constants.js` and remain WSS-only.
5. **Cross-browser sanity**
* Spot-check playback in Chromium and Firefox (desktop) to ensure no console errors related to CORS, Range requests, or tracker connections.
Document the run in PR descriptions so QA can cross-reference results.
---
## 6. Additional Notes for Agents
## 6. Moderation Quickstart (Bitvid)
* **Nostr interoperability:** Keep kind `30078` events as the source of truth and optionally mirror to kind `1063` so external clients see the hosted URL.
* **Probing:** Lightweight `HEAD`/`GET` requests should back `probeUrl()` so dead URLs can be hidden or flagged without blocking the UI.
* **Extensibility:** Future work (live streams, NIP-96 uploads, analytics) should preserve the URL-first strategy and magnet safety rules above.
* **Sidebar layering:** Keep the fixed sidebar below every modal and overlay. Respect the `--z-sidebar*` tokens so dialogs always render on top of the navigation.
* **Static asset cache busting:** The CDN aggressively caches `components/sidebar.html` and CSS/JS bundles. Update `config/asset-version.js` and keep the `?v=` query strings in `index.html` (and iframe form shells) in sync whenever you change sidebar markup, scripts, or styles. The fetch helpers in `js/index.js` already append `cache: "no-store"`; reuse them for new partials so desktop collapses ship immediately without waiting on manual cache clears.
* **View partial cache busting:** The `views/*.html` files are served from the same CDN tier and require the asset version suffix as well. `js/viewManager.js` now appends `?v=<ASSET_VERSION>` when loading views—keep that helper in place so layout or styling updates propagate on the first refresh.
* **Sidebar overflow styling:** `#sidebar` now owns vertical scrolling with `overflow-y: auto` while keeping `overflow-x: visible` so the gradient panel’s drop shadow can spill onto the page. The nested `.sidebar-scroll` wrapper must remain `overflow: visible`; do not reintroduce hidden overflow on any ancestor or the shadow will clip again.
* **Collapsed rail padding:** The collapsed rail keeps icons full-size by pairing reduced padding on `.sidebar__inner` and `.sidebar-panel` with the shared `--sidebar-control-size` (2.75 rem). Update the trio together so the 4 rem rail still fits the circular toggle/dropup buttons without squishing the gradients.
* **Collapsed nav width:** Collapsed links rely on `width: var(--sidebar-control-size)` plus `margin-inline: auto` to keep every glyph aligned with the circular toggle and footer trigger. Preserve that sizing or the icons will drift off the gradient panel.
The moderation and admin list tooling remain active in Bitvid and must follow Nostr moderation policies and QA steps. Review `docs/moderation/README.md` and these key expectations:
---
## Moderation Quickstart (Bitvid)
1. Read `docs/moderation/README.md` for the policy overview.
2. Parse NIP-56 reports and compute `trustedReportCount` using **only F1 followers**.
3. Apply defaults: blur thumbnail at ≥3 F1 `nudity` reports; block autoplay at ≥2.
4. Wire NIP-51 lists — `10000` mute (downrank/hide) and `30000` admin lists (opt-in hard-hide/whitelist).
5. Add a reason chip plus “show anyway” control to every blurred item.
6. Use NIP-45 COUNT when available; render graceful fallbacks when relays omit it.
7. Keep reputation gating out of Home; allow it in Discovery behind a toggle.
8. Run the scenarios in `docs/moderation/testing.md` before shipping.
9. Log moderation decisions locally for debugging without leaking PII.
10. Record a ≤90s demo showing blur/hide/override flows when submitting major moderation work.
1. **Report thresholds:** Parse NIP-56 reports and compute `trustedReportCount` using **only F1 followers**.
2. **Default behaviors:** Blur thumbnails at ≥3 F1 `nudity` reports and block autoplay at ≥2.
3. **Admin lists:** Use NIP‑51 lists — `10000` for mute/downrank and `30000` for admin hard-hide/whitelist. Ensure these list IDs are correctly handled in the profile modal.
4. **Profile Modal Integration:** Admin list toggles and moderation controls in `ProfileModalController` must trigger local state changes and reflect mutations visually without breaking cached profiles.
5. **User overrides:** Add a “show anyway” option to any blurred or blocked content.
6. **Testing:** Run all cases from `docs/moderation/testing.md` before shipping changes. Confirm blur, hide, and override flows function correctly across sessions.
7. **Telemetry and privacy:** Log moderation decisions locally for debugging without leaking PII.
8. **QA demo:** Record a ≤90 s screen demo showing blur/hide/override flows when submitting major moderation work.
---
@@ -99,16 +91,70 @@ Document the run in PR descriptions so QA can cross-reference results.
`{ "version": 3, "title": string, "url"?: string, "magnet"?: string, "thumbnail"?: string, "description"?: string, "mode": "live"|"dev", "isPrivate": boolean, "deleted": boolean, "videoRootId": string }`.
* **Validation:** Every note must include a non-empty `title` plus at least one playable source (`url` or `magnet`). URL-only and magnet-only posts are both valid. Legacy v2 magnet notes stay readable.
* **Upload UX:** The modal collects a hosted HTTPS URL and/or magnet. Enforce HTTPS for direct playback while keeping magnets optional when a URL is supplied.
* **Playback orchestration:** `playVideoWithFallback` probes and plays the HTTPS URL first, watches for stalls/errors, and then falls back to WebTorrent. When both sources exist, pass the hosted URL through to WebTorrent as a webseed hint.
* **Playback orchestration:** `bitvidApp.playVideoWithFallback` probes and plays the HTTPS URL first, watches for stalls/errors, and then falls back to WebTorrent. When both sources exist, pass the hosted URL through to WebTorrent as a webseed hint.
* **Status messaging:** Update modal copy to reflect whether playback is direct or via P2P so regressions surface quickly during QA.
---
## 8. Architectural Guide: `bitvidApp` vs. UI Controllers
To keep the codebase maintainable, we are moving complex UI logic from `js/app.js` into dedicated controller classes (e.g., `ProfileModalController`, `UploadModal`). **This is an architectural direction for `unstable`**—some controllers may not exist yet. When working on these components, follow these core principles:
#### **Principle: Separation of Concerns**
* **`bitvidApp` (js/app.js): The Orchestrator.** Its main job is to manage application-wide state, wire up services, and orchestrate high-level actions. It should **not** directly manipulate the DOM elements of complex components like modals. Instead, it should instantiate their controllers and communicate with them through a clean API.
* **UI Controllers (e.g., `js/ui/profileModalController.js`): The Specialists.** A controller is responsible for a specific piece of the UI. It manages its own DOM elements, handles user interactions within its scope, and uses services and callbacks provided by `bitvidApp` to perform actions.
#### **State Management: The Source of Truth**
The single source of truth for shared application state (like saved profiles, relay lists, and block lists) lives in modules like `js/state/cache.js` and services like `relayManager`.
1. **`bitvidApp` Writes State:** `bitvidApp` is responsible for calling the functions that mutate this central state (e.g., `setSavedProfiles`, `userBlocks.addBlock`).
2. **`bitvidApp` Notifies the Controller:** After updating the state, `bitvidApp` must call a method on the controller to tell it that its data is stale and it needs to re-render.
* **Example:** When a user logs in, `bitvidApp` updates the active user and saved profiles, then calls `this.profileModalController.handleAuthLogin(detail)` so the modal can update its own display.
3. **Controller Reads State:** The controller receives functions to *read* this state in its constructor (via the `state` and `services` objects). It should **always** use these functions (e.g., `this.state.getSavedProfiles()`, `this.services.userBlocks.getBlocked()`) to get the data it needs to render.
#### **Execution Flow: Callbacks**
When a user performs an action inside a modal that needs to affect the whole application (like switching a profile or updating relays), the flow is:
1. **User Action:** A user clicks a "Switch Profile" button inside the modal.
2. **Controller Event Handler:** The controller's internal event listener fires.
3. **Controller Invokes Callback:** The controller calls a callback function passed to it by `bitvidApp` (e.g., `this.callbacks.onRequestSwitchProfile({ pubkey })`). It does *not* contain the logic for switching profiles itself.
4. **`bitvidApp` Executes the Logic:** `bitvidApp` provides the implementation for that callback (e.g., `handleProfileSwitchRequest`). This method contains the actual logic to call the auth service, reload videos, and update the application state.
#### **Checklist for Refactoring from `bitvidApp` to a Controller:**
When moving a feature to a controller, follow these steps:
1. **Identify Logic:** Find the methods in `js/app.js` that directly read from or write to the modal's DOM (e.g., old `renderSavedProfiles` or `populateBlockedList` logic).
2. **Create Controller Method:** Implement the new logic inside the controller. Ensure it gets its data from `this.services.*` or `this.state.*`.
3. **Create `bitvidApp` Wrapper:** In `js/app.js`, replace the old logic with a new, thin wrapper method. This wrapper should:
* a. Update any central application state if needed.
* b. Call the new method on the controller instance (e.g., `this.profileModalController.populateBlockedList()`).
4. **Wire Up Callbacks:** If the controller needs to trigger an app-wide action, ensure a callback is defined in the controller's constructor and provided by `bitvidApp` during instantiation.
5. **Remove Old Code:** Once fully replaced, delete the old DOM manipulation logic and direct event listeners from `js/app.js`. All interactions should be routed through the controller.
#### **File Map (quick reference)**
* `js/app.js` — **`bitvidApp`** (orchestrator; owns high-level flows like `playVideoWithFallback` wiring)
* `js/services/playbackService.js` — Lower-level playback stream handling
* `js/playbackUtils.js` — Magnet/session helper utilities
* `js/magnetUtils.js` — `safeDecodeMagnet`, `normalizeAndAugmentMagnet` (WSS trackers, `ws=`/`xs=` hints)
* `js/constants.js` — Feature flags, canonical WSS tracker list
---
## Next
Please read these documents next.
Please read these documents next.
docs/nostr-event-schemas.md
js/nostrEventSchemas.js
* `docs/nostr-event-schemas.md`
* `js/nostrEventSchemas.js`
And if you need to create new nostr kinds please keep the logic centralized there in nostrEventSchemas.js and the nostr-event-schemas.md up to date.
And if you need to create new nostr kinds please keep the logic centralized there in `nostrEventSchemas.js` and the `nostr-event-schemas.md` up to date.
**End of AGENTS.md**