mirror of
https://github.com/PR0M3TH3AN/TORCH.git
synced 2026-10-27 07:51:52 +00:00
Refactor agent docs to repository-agnostic workflow
This commit is contained in:
1 parent
ea9c75da79
commit
ce453a6454
15 files changed
+260
-1604
No files matched your search
@@ -1,136 +1,88 @@
|
||||
# bitvid — AI Agent Guide
|
||||
# AGENTS.md — Repository-Agnostic Agent Operating Guide
|
||||
|
||||
This guide tells AI agents how to keep bitvid aligned with the current product direction. Follow it whenever you touch code, content, or documentation inside this repository.
|
||||
This file defines how agents should work in this repository **before any project-specific customization exists**.
|
||||
|
||||
**Important:** Before starting any development or debugging, please review `KNOWN_ISSUES.md`. This file documents pre-existing test failures, environmental quirks, and architectural limitations that you should be aware of to avoid unnecessary investigation.
|
||||
## Purpose
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
Make this repository portable across many downstream projects. Default to generic guidance, minimal assumptions, and workflows that work in different languages, runtimes, and deployment environments.
|
||||
- Keep agent work predictable, auditable, and safe.
|
||||
- Minimize repeated discovery work across sessions.
|
||||
- Capture durable learnings so future agents can move faster.
|
||||
|
||||
## Session startup checklist (run every session)
|
||||
|
||||
1. Read `AGENTS.md` (this file).
|
||||
2. Read `CLAUDE.md` for execution workflow and handoff protocol details.
|
||||
3. Read `CONTRIBUTING.md` for commit/PR expectations.
|
||||
1. Read `AGENTS.md`.
|
||||
2. Read `CLAUDE.md` for execution workflow details.
|
||||
3. Read `CONTRIBUTING.md` for commit and PR expectations.
|
||||
4. Read `KNOWN_ISSUES.md` for active blockers and workarounds.
|
||||
5. Read `docs/agent-handoffs/README.md`.
|
||||
6. Review recent notes in:
|
||||
6. Scan recent notes in:
|
||||
- `docs/agent-handoffs/learnings/`
|
||||
- `docs/agent-handoffs/incidents/`
|
||||
=======
|
||||
For any nostr related work, please review the nip documentation located in /docs/nips before beginning work.
|
||||
7. If present, review the current run artifacts in:
|
||||
- `src/context/`
|
||||
- `src/todo/`
|
||||
- `src/decisions/`
|
||||
- `src/test_logs/`
|
||||
- `src/issues/`
|
||||
|
||||
**Comment publishing guardrail:** Session actors are limited to passive telemetry (e.g., view counters). Always require the logged-in Nostr signer when sending video comments through [`js/nostr/commentEvents.js`](js/nostr/commentEvents.js). See the reminder in [`docs/nostr-event-schemas.md`](docs/nostr-event-schemas.md#event-catalogue) for context.
|
||||
## Core operating principles
|
||||
|
||||
---
|
||||
- Default to generic guidance and neutral language.
|
||||
- Make the smallest safe change that satisfies the request.
|
||||
- Avoid unrelated refactors.
|
||||
- Preserve backward compatibility unless explicitly asked otherwise.
|
||||
- Prefer explicit commands and documented behavior over assumptions.
|
||||
- Record assumptions clearly in your final summary.
|
||||
|
||||
## 1. Release Channels: Main vs. Unstable
|
||||
>>>>>>> Stashed changes
|
||||
## Validation policy
|
||||
|
||||
* **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 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.
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- Do not hardcode company, product, team, customer, or environment-specific assumptions.
|
||||
- Prefer neutral terms such as `project`, `service`, `integration`, `consumer`, `provider`, and `environment`.
|
||||
- Do not assume a specific infrastructure model (local machine, container, CI, cloud VM, etc.) unless explicitly configured in repo files.
|
||||
- Add project-specific details only when required by the current repository and clearly label them as repository-specific.
|
||||
=======
|
||||
### Browser logging policy
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
* Route every browser log through `js/utils/logger.js`. Do **not** call `console.*` directly.
|
||||
* Use `logger.dev.*` for diagnostics that should disappear in production (flagged by `IS_DEV_MODE`/`isDevMode`). Use `logger.user.*` for operator-facing warnings and errors that must reach production consoles.
|
||||
* Before promoting a build, flip `IS_DEV_MODE` in `config/instance-config.js` to match the target environment so `window.__BITVID_DEV_MODE__` and the logger channels behave correctly.
|
||||
* Review and follow [`docs/logging.md`](docs/logging.md) whenever you add new logging or touch inline scripts.
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- Start with the smallest safe change that satisfies the request.
|
||||
- Keep edits focused; avoid unrelated refactors.
|
||||
- Prefer explicit commands and documented behavior over implicit assumptions.
|
||||
- Preserve backward compatibility unless the task explicitly permits a breaking change.
|
||||
- If assumptions are necessary, record them in the final summary.
|
||||
=======
|
||||
## 2. Mission: Hybrid Playback Strategy
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
* **Goal:** Always deliver smooth playback while optimizing for the configured priority (hosted URL or P2P).
|
||||
* **Configuration:** `DEFAULT_PLAYBACK_SOURCE` in `config/instance-config.js` determines whether `url` or `torrent` is attempted first.
|
||||
* **Runtime behavior:** Call `bitvidApp.playVideoWithFallback({ url, magnet })` (implemented in `js/app/playbackCoordinator.js` and bound to the app instance in `js/app.js`). This function attempts the preferred source first and falls back to the alternative if the primary fails or stalls. `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.
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- Run the most relevant checks for changed files (tests, lint, typecheck, build, or targeted scripts).
|
||||
- Never claim a check passed unless it was actually executed.
|
||||
- If a check cannot run, record:
|
||||
- command attempted,
|
||||
- reason it could not complete,
|
||||
- fallback validation performed.
|
||||
- Never claim a check passed unless it was actually executed.
|
||||
- why it could not complete,
|
||||
- what fallback validation was performed.
|
||||
|
||||
## Agent knowledge-sharing protocol
|
||||
=======
|
||||
## Styling & Theming Rules (token-first)
|
||||
## Knowledge-sharing protocol
|
||||
|
||||
* **Single source of truth:** All colors, spacing, radii, and typography decisions must flow through our design tokens; never reach for ad-hoc HEX/RGB values when a token exists.
|
||||
* **Theme scopes:** Tokens live at three levels—`core` (global primitives), `theme` (light/dark surface/background mappings), and `component` (contextual overrides). Additions must document their scope and consumers.
|
||||
* **Semantic tokens:** Maintain this canonical list: `bg`, `bg-muted`, `bg-raised`, `text`, `text-muted`, `border`, `border-strong`, `accent`, `accent-hover`, `accent-active`, `accent-muted`, `accent-contrast`, `danger`, `warning`, `success`, `info`, `overlay`, `overlay-strong`.
|
||||
* **Palette guidance:** Map semantic tokens to palette primitives defined in the CSS build pipeline; when a new primitive is needed, extend the palette once and remap consumers rather than hard-coding colors downstream.
|
||||
* **Icon contrast rule:** Icons and glyph-only buttons must meet a minimum 3:1 contrast ratio against their background; prefer `accent-contrast` or `text` tokens when in doubt.
|
||||
* **Accessibility expectations:** Default themes must satisfy WCAG 2.1 AA contrast ratios for text and controls, and preserve focus outlines sourced from the token set.
|
||||
* **Prohibitions:** Do not commit inline styles, `<font>` tags, or CSS variables whose values are literal colors; always reference the appropriate token variables.
|
||||
* **Theme toggling:** Implement new themes through token swaps only (e.g., toggling the `data-theme` attribute) and keep component logic agnostic to specific palette values. Document toggles alongside the [README CSS build pipeline](README.md#css-build-pipeline).
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
---
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
### What belongs where
|
||||
|
||||
- `KNOWN_ISSUES.md`
|
||||
- Active and reproducible issues only.
|
||||
- Active, reproducible issues only.
|
||||
- Include status, impact, workaround, and last verification date.
|
||||
- `docs/agent-handoffs/learnings/`
|
||||
- Proven patterns, repeatable fixes, and successful implementation guidance.
|
||||
- `docs/agent-handoffs/incidents/`
|
||||
- Failures, root causes, mitigations, and prevention guidance.
|
||||
- `src/context/`
|
||||
- Snapshot of current task context (goal, scope, constraints).
|
||||
- `src/todo/`
|
||||
- Actionable checklist for in-progress work.
|
||||
- `src/decisions/`
|
||||
- Key implementation decisions and rationale.
|
||||
- `src/test_logs/`
|
||||
- Commands run and their outcomes.
|
||||
- `src/issues/`
|
||||
- One-off investigative or audit outputs not yet promoted to `KNOWN_ISSUES.md`.
|
||||
|
||||
### File naming standard (generic)
|
||||
### Naming standard (generic)
|
||||
|
||||
Use descriptive, repository-agnostic note names:
|
||||
=======
|
||||
## 3. Magnet Handling — Do’s & Don’ts
|
||||
Use: `YYYY-MM-DD-short-topic.md`
|
||||
|
||||
* **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 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. (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.
|
||||
|
||||
---
|
||||
|
||||
## 4. Upload Modal Troubleshooting
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
1. **Required fields:** Validation must ensure a title exists and that either a hosted URL or a magnet (or both) is supplied. Optional `ws` / `xs` inputs should be appended only when a magnet is present.
|
||||
2. **Magnet parsing errors:** When a user pastes encoded magnets, run `safeDecodeMagnet()` before normalizing. Show inline errors if decoding fails and confirm the raw `magnet:?xt=` string survives the round trip.
|
||||
3. **Playback source promise:** After submission, confirm the resulting feed item carries `data-play-url` and `data-play-magnet` attributes so playback utilities can attempt the configured source first.
|
||||
4. **Mixed-content warnings:** If the page is served over HTTPS, reject `ws=` or `xs=` hints that begin with `http://` and show guidance to upgrade to HTTPS. Document the copy in README/UX strings so operators can align messaging.
|
||||
5. **Telemetry hooks:** Keep existing analytics/logging untouched unless instructed. If you add new modal states, annotate them clearly in code comments.
|
||||
6. **Modal regressions:** If validation or helper wiring breaks in Main, disable new feature flags and ship a revert PR immediately. Note the rollback steps in AGENTS.md for posterity.
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
Good examples:
|
||||
Examples:
|
||||
|
||||
- `2026-02-14-validation-before-summary.md`
|
||||
- `2026-02-14-missing-baseline-context.md`
|
||||
|
||||
Avoid tool, product, customer, or team names in filenames unless absolutely required for clarity.
|
||||
Naming rules:
|
||||
|
||||
### Required note sections
|
||||
- Keep names concise and descriptive.
|
||||
- Avoid company, product, team, customer, and environment names.
|
||||
- Prefer neutral technical terms.
|
||||
|
||||
Every learning or incident note should include these headings:
|
||||
### Required sections for reusable notes
|
||||
|
||||
Use these headings in learning/incident notes:
|
||||
|
||||
1. Context
|
||||
2. Observation
|
||||
@@ -140,512 +92,21 @@ Every learning or incident note should include these headings:
|
||||
|
||||
### Update decision tree
|
||||
|
||||
When you discover new reusable context:
|
||||
When you discover reusable context:
|
||||
|
||||
1. Check if an existing note already covers it.
|
||||
2. If yes, update the existing note.
|
||||
3. If no, add a new note in `learnings/` or `incidents/` using the naming standard above.
|
||||
4. If the issue is still active/reproducible, add or update an entry in `KNOWN_ISSUES.md`.
|
||||
=======
|
||||
---
|
||||
2. If yes, update that note.
|
||||
3. If no, add a new note in `learnings/` or `incidents/`.
|
||||
4. If the issue is still active/reproducible, add or update `KNOWN_ISSUES.md`.
|
||||
|
||||
## 5. Manual QA Checklist
|
||||
## Priority order when guidance conflicts
|
||||
|
||||
Run this script before shipping notable UI changes, especially around upload/playback flows. Automate when possible, but manual verification is required for releases.
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
1. **Smoke test the modal**
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
1. System/developer/user instructions in the active session
|
||||
2. `AGENTS.md`
|
||||
3. `CLAUDE.md`
|
||||
4. `CONTRIBUTING.md`
|
||||
5. Inline code comments and prompt templates
|
||||
=======
|
||||
* 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. **Hybrid playback**
|
||||
|
||||
* Publish a post with both URL and magnet. Load the card and verify the player fetches the configured preferred source first (check network tab or logs).
|
||||
* Temporarily block the primary source (e.g., devtools throttling or offline). Confirm playback seamlessly falls back to the secondary source.
|
||||
3. **Magnet hygiene**
|
||||
## Keep this file generic
|
||||
|
||||
* 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. Moderation Quickstart (bitvid)
|
||||
|
||||
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:
|
||||
|
||||
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.
|
||||
|
||||
---
|
||||
|
||||
## 7. Content Schema v3 & Playback Rules
|
||||
|
||||
* **Event payloads:** New video notes serialize as version `3` with the JSON shape:
|
||||
`{ "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:** `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
|
||||
|
||||
---
|
||||
|
||||
## 9. Nostr Addressing & NIP-33 (Lessons Learned)
|
||||
|
||||
* **Addressing Rule:** NIP-33 events (e.g., videos, long-form content) are uniquely identified by the combination of `kind`, `pubkey`, and the `d` tag.
|
||||
* **The `d` tag is King:** When creating pointers for these events, **always use the `d` tag** as the identifier.
|
||||
* **Avoid Logical IDs:** Do not confuse logical identifiers (like `videoRootId`) with the network identifier (`d` tag). While they might often be the same, they are not guaranteed to be.
|
||||
* **Hydration Pitfall:** If you create a pointer using a logical ID that differs from the `d` tag, relays will fail to find the event during hydration because the index relies on the `d` tag.
|
||||
* **Fix Pattern:** When resolving a pointer from an event, prioritize checking `tags.find(t => t[0] === 'd')?.[1]` over any other ID field.
|
||||
|
||||
---
|
||||
|
||||
## 10. Direct Messages (NIP-04 vs NIP-44)
|
||||
|
||||
* **Dual Support:** We must support both legacy NIP-04 and newer NIP-44 Direct Messages.
|
||||
* **Reasoning:** A significant portion of the user base still relies on NIP-04 DMs. While NIP-44 offers better security, we cannot drop NIP-04 support until adoption of the new standard is nearly universal.
|
||||
* **Implementation:** When working on DM features, ensure code paths exist for both encryption/decryption methods. Do not deprecate or remove NIP-04 handling logic. Other legacy methods can be considered for removal, but NIP-04 is critical.
|
||||
|
||||
---
|
||||
|
||||
## 11. Telemetry & Error Aggregation
|
||||
|
||||
* **Tooling:** Use `npm run telemetry:aggregate` (which runs `scripts/agent/telemetry-aggregator.mjs`) to collect, sanitize, and aggregate errors from CI/test runs, smoke tests, and agent logs.
|
||||
* **Privacy Policy:** The tool automatically strips PII (IPs, emails, hex keys, bech32 keys) from logs. **Do not** manually inspect raw logs containing PII unless necessary for debugging in a secure environment; rely on the sanitized reports in `ai/reports/`.
|
||||
* **Opt-in:** Telemetry generation is opt-in. You must set the environment variable `ENABLE_TELEMETRY=true` when running the aggregator.
|
||||
* **Reports:** Aggregated reports are generated in `ai/reports/telemetry-YYYYMMDD.md` and `artifacts/error-aggregates.json`. These files provide prioritized issues for triage.
|
||||
|
||||
---
|
||||
|
||||
## 12. Multi-Agent Coordination
|
||||
|
||||
This project uses multiple AI agents (Claude Code, OpenAI Codex, Google Jules) working in parallel. Without coordination, agents will create conflicting PRs, duplicate work, and cause painful merge conflicts. Follow these rules to keep things clean.
|
||||
|
||||
### Before Starting Work
|
||||
|
||||
1. **Check open PRs.** Run the following command to list all open PRs:
|
||||
```
|
||||
curl -s "https://api.github.com/repos/PR0M3TH3AN/bitvid/pulls?state=open&per_page=100" | jq '{count: length, titles: [.[].title]}'
|
||||
```
|
||||
If another agent already has a PR touching the same files or subsystem, do not create a competing PR. Instead, note the conflict and ask the maintainer how to proceed.
|
||||
2. **Check this section for in-flight work.** The maintainer may list active work areas below. Respect these reservations.
|
||||
3. **Read KNOWN_ISSUES.md.** Do not open PRs to fix issues already documented there unless explicitly asked.
|
||||
|
||||
### Subsystem Boundaries
|
||||
|
||||
To minimize merge conflicts, treat these as independent work zones. An agent should avoid touching files outside its assigned zone in a single PR:
|
||||
|
||||
| Zone | Key Files | Description |
|
||||
|------|-----------|-------------|
|
||||
| **Nostr Core** | `js/nostr/client.js`, `js/nostr/adapters/`, `js/nostrClientFacade.js` | Protocol client, signers, relay management |
|
||||
| **Event Schemas** | `js/nostrEventSchemas.js`, `docs/nostr-event-schemas.md` | Event definitions and documentation |
|
||||
| **Playback** | `js/services/playbackService.js`, `js/playbackUtils.js`, `js/magnetUtils.js` | Video streaming, magnet handling |
|
||||
| **UI Controllers** | `js/ui/` | Modal controllers, notification, components |
|
||||
| **State** | `js/state/` | Profile cache, application state |
|
||||
| **DMs** | `js/ui/dm/`, `js/nostr/dm/` | Direct messaging subsystem |
|
||||
| **Moderation** | `js/moderation/`, `docs/moderation/` | Content moderation, reports, admin lists |
|
||||
| **Build & CI** | `.github/workflows/`, `scripts/`, `tailwind.config.cjs` | CI pipeline, lint scripts, build tooling |
|
||||
| **Styling** | `css/tokens.css`, `css/tailwind.source.css` | Design tokens and Tailwind source |
|
||||
| **App Orchestrator** | `js/app.js`, `js/app/` | Main app wiring (high conflict risk — only one PR at a time) |
|
||||
|
||||
**`js/app.js` is the highest-risk file.** It wires everything together. Never have two agent PRs modifying it simultaneously.
|
||||
|
||||
### PR Discipline
|
||||
|
||||
- **One subsystem per PR.** A PR that touches Nostr Core and UI Controllers is two PRs. Split them.
|
||||
- **Small and mergeable.** Target PRs that can be reviewed in one sitting. If a refactor spans 10+ files, break it into sequential PRs.
|
||||
- **Merge before branching.** Before starting new work on a subsystem, ensure all open PRs for that subsystem are merged or closed.
|
||||
- **Rebase, don't stack.** Long-lived branches diverge fast with multiple agents. Rebase onto `unstable` frequently.
|
||||
|
||||
### Signaling Work to Other Agents
|
||||
|
||||
When you create a PR or start work, leave a clear signal:
|
||||
- **PR title prefix**: Use a descriptive prefix like `[nostr-core]`, `[playback]`, `[ui]`, `[ci]` so the scope is visible at a glance.
|
||||
- **PR description**: Include a "Files Modified" section listing the key files touched, so other agents can quickly detect conflicts.
|
||||
|
||||
### Task Claiming Protocol (TORCH)
|
||||
|
||||
Task coordination uses **TORCH** (Task Orchestration via Relay-Coordinated Handoff) — a decentralized locking protocol built on Nostr. Agents publish ephemeral lock events to public relays; locks auto-expire via NIP-40. No tokens, no secrets, no git push required. Works across all platforms (Claude Code, Codex, Jules). See `docs/agents/TORCH.md` for the full protocol documentation.
|
||||
|
||||
**Before starting any task:**
|
||||
|
||||
1. **Check for existing claims:**
|
||||
```bash
|
||||
node scripts/agent/nostr-lock.mjs check --cadence <daily|weekly>
|
||||
```
|
||||
Returns JSON with `locked` (claimed agents) and `available` (free agents) arrays. If an agent appears in the `locked` list, **skip it**.
|
||||
|
||||
2. **Claim the task:**
|
||||
```bash
|
||||
AGENT_PLATFORM=<jules|claude-code|codex> \
|
||||
node scripts/agent/nostr-lock.mjs lock \
|
||||
--agent <agent-name> \
|
||||
--cadence <daily|weekly>
|
||||
```
|
||||
The script generates an ephemeral keypair, publishes a lock event to public Nostr relays, and performs a built-in race check. The key is used once and discarded. Locks auto-expire after 2 hours (configurable via `NOSTR_LOCK_TTL`).
|
||||
|
||||
- **Exit 0** = lock acquired, begin work.
|
||||
- **Exit 3** = race lost, another agent claimed first. Go back to step 1.
|
||||
- **Exit 2** = relay error. Write a `_failed.md` log and stop.
|
||||
|
||||
3. **View all active locks** (optional, for debugging):
|
||||
```bash
|
||||
node scripts/agent/nostr-lock.mjs list
|
||||
```
|
||||
|
||||
**Scheduler agents:** Daily and weekly scheduler agents must follow this protocol in addition to their directory-based rotation logic (`docs/agents/task-logs/daily/` and `docs/agents/task-logs/weekly/`). The lock check happens _after_ determining the next task but _before_ executing it. See the scheduler prompts for the specific implementation steps.
|
||||
|
||||
### Currently In-Flight Work
|
||||
|
||||
<!-- Maintainer: update this list when assigning work to agents. Agents: check this before starting. -->
|
||||
|
||||
_No reservations currently active._
|
||||
|
||||
---
|
||||
|
||||
## 13. Code Health Rules (CI-Enforced)
|
||||
|
||||
Three automated lint checks protect the codebase from common growth problems. These run in CI via `npm run lint` and will block your PR if violated.
|
||||
|
||||
### File Size Limits
|
||||
|
||||
**Script:** `npm run lint:file-size` (`scripts/check-file-size.mjs`)
|
||||
|
||||
- New `.js` files under `js/` must stay **under 1,000 lines**.
|
||||
- Existing oversized files are grandfathered with a recorded line count. They must **not grow** beyond their recorded count + 50 lines.
|
||||
- If your change would push a grandfathered file over its limit, **extract logic into a new module first**, then make your change.
|
||||
|
||||
**Decomposition strategy for agents:**
|
||||
1. Identify a cohesive block of logic (e.g., a group of related methods, a subsection of a controller).
|
||||
2. Extract it into a new file in the same directory.
|
||||
3. Export the extracted functions/class.
|
||||
4. Import and re-wire from the original file.
|
||||
5. Run `npm run lint:file-size` to confirm the original file shrank.
|
||||
6. Update the grandfathered count if needed (the maintainer will handle this when merging).
|
||||
|
||||
### innerHTML Baseline
|
||||
|
||||
**Script:** `npm run lint:innerhtml` (`scripts/check-innerhtml.mjs`)
|
||||
|
||||
- Every file has a **baseline** innerHTML assignment count. Adding new `innerHTML` usage beyond the baseline fails the lint.
|
||||
- For new UI code, use **safe DOM APIs** instead:
|
||||
```javascript
|
||||
// PREFERRED: auto-escaped, no XSS risk
|
||||
element.textContent = userProvidedString;
|
||||
const el = document.createElement("div");
|
||||
el.className = "card";
|
||||
parent.appendChild(el);
|
||||
|
||||
// ACCEPTABLE: innerHTML with escapeHtml for all user data
|
||||
import { escapeHtml } from "../utils/domUtils.js";
|
||||
container.innerHTML = `<span>${escapeHtml(title)}</span>`;
|
||||
|
||||
// BLOCKED: innerHTML with unescaped user data
|
||||
container.innerHTML = `<span>${title}</span>`; // XSS vulnerability
|
||||
```
|
||||
- If you must add innerHTML (e.g., loading a view template), update the baseline: `node scripts/check-innerhtml.mjs --update` and include the updated BASELINE in your PR.
|
||||
|
||||
### Constants — No Duplication
|
||||
|
||||
- Relay timing constants live in **`js/nostr/relayConstants.js`** — always import from there.
|
||||
- Before defining a new numeric constant, search for existing ones with the same value. If a match exists, import it.
|
||||
- Feature flags live in **`js/constants.js`**.
|
||||
- Cache policies live in **`js/nostr/cachePolicies.js`**.
|
||||
- Do not define the same constant in two files. If two modules need the same value, create a shared module and import from it.
|
||||
|
||||
---
|
||||
|
||||
## 14. Playwright Agent Testing Infrastructure
|
||||
|
||||
bitvid includes a test harness and fixtures that let Playwright CLI agents programmatically log in, seed relay data, and inspect app state — no browser extensions or real relays required.
|
||||
|
||||
### Activating Test Mode
|
||||
|
||||
Add `?__test__=1` to the URL, or set `localStorage.__bitvidTestMode__ = "1"` via `addInitScript`. This installs `window.__bitvidTest__` on the page.
|
||||
|
||||
### Overriding Relays
|
||||
|
||||
Point the app at a local mock relay instead of production:
|
||||
|
||||
```
|
||||
?__test__=1&__testRelays__=ws://127.0.0.1:8877
|
||||
```
|
||||
|
||||
Or set `localStorage.__bitvidTestRelays__` to a JSON array of relay URLs.
|
||||
|
||||
### Test Harness API (`window.__bitvidTest__`)
|
||||
|
||||
| Method | Returns | Purpose |
|
||||
|--------|---------|---------|
|
||||
| `loginWithNsec(hexKey)` | `Promise<string>` (pubkey) | Programmatic login, bypasses the modal |
|
||||
| `logout()` | `void` | Clear active signer |
|
||||
| `getAppState()` | `{ isLoggedIn, activePubkey, relays, ... }` | Inspect current state |
|
||||
| `getFeedItems()` | `Array<{ title, pubkey, dTag, hasUrl, hasMagnet }>` | Scrape video cards from DOM |
|
||||
| `waitForFeedItems(n, ms)` | `Promise<Array>` | Wait for N cards to appear |
|
||||
| `waitForSelector(sel, ms)` | `Promise<true>` | Wait for a DOM element |
|
||||
| `getRelayHealth()` | `{ relays, unreachable, backoff }` | Relay connection status |
|
||||
| `applyRelayOverrides(urls)` | `boolean` | Redirect relay connections |
|
||||
| `nostrClient` | `NostrClient` | Direct access for advanced use |
|
||||
|
||||
### Mock Relay (`scripts/agent/simple-relay.mjs`)
|
||||
|
||||
Start with `startRelay(port, { httpPort })`. Alongside the Nostr WebSocket protocol, exposes an HTTP API:
|
||||
|
||||
| Endpoint | Method | Purpose |
|
||||
|----------|--------|---------|
|
||||
| `/seed` | `POST` | Inject signed events (single object or array) |
|
||||
| `/events` | `GET` | List all stored events |
|
||||
| `/events` | `DELETE` | Clear all events |
|
||||
| `/health` | `GET` | Event count + connection count |
|
||||
|
||||
Programmatic API: `relay.seedEvent(event)`, `relay.clearEvents()`, `relay.getEvents()`.
|
||||
|
||||
### Playwright Fixture (`tests/e2e/helpers/bitvidTestFixture.ts`)
|
||||
|
||||
Import `test` and `expect` from the fixture for tests that need the full stack:
|
||||
|
||||
```typescript
|
||||
import { test, expect } from "./helpers/bitvidTestFixture";
|
||||
|
||||
test("agent can seed and view videos", async ({ page, gotoApp, loginAs, seedEvent }) => {
|
||||
await seedEvent({ title: "Test Video", url: "https://example.com/v.mp4" });
|
||||
await gotoApp();
|
||||
await loginAs(page);
|
||||
// ... assertions
|
||||
});
|
||||
```
|
||||
|
||||
**Available fixture values:**
|
||||
|
||||
| Fixture | Type | Purpose |
|
||||
|---------|------|---------|
|
||||
| `relay` | Relay instance | Auto-started/stopped per test |
|
||||
| `seedEvent(video)` | `(TestVideoEvent) => Promise` | Create a signed kind 30078 event and inject it |
|
||||
| `seedRawEvent(event)` | `(any) => Promise` | Inject a pre-built event |
|
||||
| `clearRelay()` | `() => Promise` | Wipe all relay events |
|
||||
| `gotoApp(path?)` | `(string?) => Promise` | Navigate with test mode + relay overrides |
|
||||
| `loginAs(page)` | `(Page) => Promise<string>` | Login with deterministic test key |
|
||||
| `testPubkey` | `string` | Hex pubkey of the test key |
|
||||
| `relayUrl` | `string` | WebSocket URL of the mock relay |
|
||||
|
||||
### `data-testid` Selectors
|
||||
|
||||
Use these for stable element targeting:
|
||||
|
||||
| Selector | Element |
|
||||
|----------|---------|
|
||||
| `[data-testid="login-button"]` | Header login button |
|
||||
| `[data-testid="upload-button"]` | Header upload button (hidden until logged in) |
|
||||
| `[data-testid="profile-button"]` | Header profile button (hidden until logged in) |
|
||||
| `[data-testid="search-input"]` | Header search field |
|
||||
| `[data-testid="login-modal"]` | Login modal container |
|
||||
| `[data-testid="login-provider-button"]` | Login provider option buttons |
|
||||
| `[data-testid="nsec-secret-input"]` | Private key textarea in nsec login |
|
||||
| `[data-testid="nsec-submit"]` | Nsec login submit button |
|
||||
| `[data-testid="upload-modal"]` | Upload modal container |
|
||||
| `[data-testid="upload-title"]` | Video title input |
|
||||
| `[data-testid="upload-url"]` | Video URL input |
|
||||
| `[data-testid="upload-magnet"]` | Magnet link input |
|
||||
| `[data-testid="upload-submit"]` | Publish button |
|
||||
| `[data-testid="video-modal"]` | Video player modal |
|
||||
| `[data-testid="video-card"]` | Individual video card in the feed |
|
||||
| `[data-testid="video-list"]` | Video feed grid container |
|
||||
|
||||
### Key Files
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `js/testHarness.js` | Test harness module (installs `window.__bitvidTest__`) |
|
||||
| `scripts/agent/simple-relay.mjs` | Mock relay with HTTP seeding API |
|
||||
| `tests/e2e/helpers/bitvidTestFixture.ts` | Reusable Playwright fixture |
|
||||
| `tests/e2e/agent-testability.spec.ts` | Infrastructure validation tests |
|
||||
|
||||
---
|
||||
|
||||
## 15. Agent Execution Protocol
|
||||
|
||||
This section defines the meta-workflow that **every AI agent** must follow when executing tasks in this codebase. It ensures safe, incremental changes, a clear decision trail, and continuity across context resets or agent hand-offs.
|
||||
|
||||
### Mindset
|
||||
|
||||
- Implement changes safely. Match existing conventions. Leave a clear trail of decisions.
|
||||
- Correctness > cleverness. Consistent conventions > personal preference. Explicit tradeoffs > "should work."
|
||||
- Prefer minimal, incremental changes over rewrites. Keep the build and tests green.
|
||||
- Do not invent files, APIs, libraries, or behaviors. If unsure, inspect the codebase first.
|
||||
|
||||
### Scoping the Work
|
||||
|
||||
Before writing any code, establish clarity on three things:
|
||||
|
||||
1. **Primary goal** — What is being built or fixed?
|
||||
2. **Success criteria** — How will we know it's done? (e.g., tests pass, feature visible in UI, lint clean)
|
||||
3. **Non-goals** — What is explicitly out of scope? (Prevents scope creep across agent sessions.)
|
||||
|
||||
### External Notes (Persistent State Files)
|
||||
|
||||
Agents lose context across sessions. These files act as persistent memory that any agent (or human) can read to resume work or understand project status. **Update them before any likely context reset.**
|
||||
|
||||
**Storage Rule:** To prevent conflicts, these files are stored in dedicated directories with timestamps.
|
||||
- **Read:** Always look for the **latest** timestamped file in the directory (e.g., `ls context/ | sort | tail -n 1`).
|
||||
- **Write:** Never overwrite an existing file. Create a **new** file with a new timestamp (e.g., `context/CONTEXT_YYYY-MM-DD_HH-MM-SS.md`).
|
||||
|
||||
| Directory | File Pattern | Purpose | When to Update |
|
||||
|-----------|--------------|---------|----------------|
|
||||
| `context/` | `CONTEXT_<timestamp>.md` | Current goal, scope, assumptions, constraints, and "Definition of Done" | At start; when scope changes |
|
||||
| `todo/` | `TODO_<timestamp>.md` | Checkbox task list with "Done" and "Blocked/Questions" sections | After planning; after tasks |
|
||||
| `decisions/` | `DECISIONS_<timestamp>.md` | Key choices made, alternatives considered, and rationale | When making tradeoffs |
|
||||
| `test_logs/` | `TEST_LOG_<timestamp>.md` | Commands run and their results (including failures) | After every lint/test/build run |
|
||||
|
||||
**Rules for external notes:**
|
||||
- These files are working documents. They should reflect the *current* state of work.
|
||||
- When starting a fresh task, clear stale content (by writing a fresh file) and re-scope.
|
||||
- Keep entries concise — bullet points and checklists, not prose.
|
||||
- `decisions/` is especially important: when you make a tradeoff, write it down so the next agent doesn't undo it.
|
||||
|
||||
### Work Loop
|
||||
|
||||
For each task item, repeat this cycle:
|
||||
|
||||
#### A) Locate
|
||||
|
||||
- Identify the relevant code and existing patterns. Find the "right place" to make the change.
|
||||
- Write a short plan (3–7 bullets) before editing. If the task touches multiple subsystem zones (see Section 12), flag this — it may need to be split into separate PRs.
|
||||
|
||||
#### B) Implement
|
||||
|
||||
- Make the smallest change that satisfies the requirement.
|
||||
- Keep edits cohesive. Avoid unrelated refactors in the same commit.
|
||||
- Follow all conventions already documented in this file (logging via `logger`, token-first styling, magnet safety, schema definitions in `nostrEventSchemas.js`, etc.).
|
||||
|
||||
#### C) Verify
|
||||
|
||||
- Run the most relevant lint/test commands (see CLAUDE.md "Available Scripts" for the full list):
|
||||
```bash
|
||||
npm run lint # Required
|
||||
npm run test:unit:shard1 # Fast feedback; run full suite before PR
|
||||
```
|
||||
- If there's no test coverage for your change, add focused tests or document in `decisions/` why tests aren't feasible.
|
||||
- Log all commands and results in a new `test_logs/TEST_LOG_<timestamp>.md` file.
|
||||
|
||||
#### D) Update Notes
|
||||
|
||||
- Check off completed items in the latest `todo/` file (by creating a new one).
|
||||
- Record decisions in a new `decisions/` file.
|
||||
- Log verification results in a new `test_logs/` file.
|
||||
- **Do this before any likely context/memory reset** — if you're about to hit a token limit, finish a long session, or hand off to another agent, update notes first.
|
||||
|
||||
### Context Recovery
|
||||
|
||||
If an agent starts a session and finds existing work-in-progress:
|
||||
|
||||
1. **Immediately read the latest files** in `context/`, `todo/`, `decisions/`, and `test_logs/`.
|
||||
2. Resume from the next unchecked item in the latest `todo/` file.
|
||||
3. Verify the current state by running `git status`, `git log --oneline -10`, and a quick lint/test pass.
|
||||
4. Do not re-do work that the latest `test_logs/` shows already passed — unless the code has changed since.
|
||||
|
||||
### Output Requirements
|
||||
|
||||
When finishing a task or handing off, provide:
|
||||
|
||||
- **Summary** of what changed and why.
|
||||
- **Files changed** (list).
|
||||
- **Verification results** (from the latest `test_logs/` file).
|
||||
- **Follow-ups / risks / remaining TODOs**.
|
||||
- **If blocked:** Ask specific questions and propose 1–2 options.
|
||||
|
||||
### Quality Bar
|
||||
|
||||
| Principle | Meaning |
|
||||
|-----------|---------|
|
||||
| Correctness over cleverness | Simple, working code beats elegant abstractions |
|
||||
| Conventions over preference | Match what's already in the repo, even if you'd do it differently |
|
||||
| Explicit tradeoffs | Write down *why* in `decisions/`, don't leave the next agent guessing |
|
||||
| Logged verification | Every claim of "tests pass" must have a `test_logs/` entry to back it up |
|
||||
| Incremental over sweeping | Small, reviewable changes that keep the build green at every step |
|
||||
|
||||
---
|
||||
|
||||
## Next
|
||||
|
||||
Please read these documents next.
|
||||
|
||||
* `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.
|
||||
|
||||
**End of AGENTS.md**
|
||||
>>>>>>> Stashed changes
|
||||
Only add project-specific details after they are truly needed and explicitly labeled as repository-specific.
|
||||
@@ -1,632 +1,108 @@
|
||||
# CLAUDE.md — AI Assistant Guide for bitvid
|
||||
# CLAUDE.md — Generic Agent Execution Workflow
|
||||
|
||||
This document provides context and guidance for AI assistants working with the bitvid codebase. It explains the project structure, development workflows, conventions, and key architectural decisions.
|
||||
This guide defines an execution flow that works across repositories and tech stacks.
|
||||
|
||||
---
|
||||
## Default workflow
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
Applies to all tasks unless direct session instructions override it.
|
||||
|
||||
## Operating principles
|
||||
|
||||
- Be repository-agnostic by default.
|
||||
- Make deterministic, auditable decisions.
|
||||
- Prefer minimal, reversible changes.
|
||||
- Leave clearer context for the next agent.
|
||||
|
||||
## Standard execution workflow
|
||||
|
||||
1. Load baseline context:
|
||||
1. **Load baseline context**
|
||||
- `AGENTS.md`
|
||||
- `CONTRIBUTING.md`
|
||||
- `KNOWN_ISSUES.md`
|
||||
- `docs/agent-handoffs/README.md`
|
||||
- recent notes in `docs/agent-handoffs/learnings/` and `docs/agent-handoffs/incidents/`
|
||||
2. Translate the request into concrete outcomes.
|
||||
3. Implement the smallest safe change.
|
||||
4. Run relevant validation.
|
||||
5. Summarize evidence clearly (commands, outputs, and changed files).
|
||||
6. Record durable learnings/incidents when new reusable knowledge appears.
|
||||
- Recent notes in `docs/agent-handoffs/learnings/` and `docs/agent-handoffs/incidents/`
|
||||
2. **Clarify the task**
|
||||
- Restate the requested outcome.
|
||||
- Identify constraints, risks, and assumptions.
|
||||
3. **Plan minimal changes**
|
||||
- Keep scope tight.
|
||||
- Avoid touching unrelated files.
|
||||
4. **Implement**
|
||||
- Apply small, reversible edits.
|
||||
- Favor readability and maintainability.
|
||||
5. **Validate**
|
||||
- Run relevant checks for impacted files.
|
||||
- Capture exact commands and outcomes.
|
||||
6. **Document and hand off**
|
||||
- Summarize what changed and why.
|
||||
- Record reusable learnings/incidents when appropriate.
|
||||
|
||||
## Quality checklist before finishing
|
||||
## Working files for session state
|
||||
|
||||
- Scope matches the user request.
|
||||
- Language and guidance remain generic unless project-specific detail is required.
|
||||
- Existing workflows were not unintentionally broken.
|
||||
- Validation coverage is appropriate for risk/impact.
|
||||
Use the following folders as lightweight coordination artifacts:
|
||||
|
||||
## Knowledge-sharing and handoff protocol
|
||||
- `src/context/` — Current objective, scope, constraints.
|
||||
- `src/todo/` — Task checklist and blockers.
|
||||
- `src/decisions/` — Important design/implementation choices.
|
||||
- `src/test_logs/` — Validation commands and results.
|
||||
- `src/issues/` — Investigations or audits that may become tracked issues.
|
||||
|
||||
### 1) Search first
|
||||
### Recommended content templates
|
||||
|
||||
Before writing a new note, check for an existing related note and update it if applicable.
|
||||
#### Context note template
|
||||
|
||||
### 2) Write in the right place
|
||||
- Goal
|
||||
- Scope
|
||||
- Constraints
|
||||
- Open questions
|
||||
|
||||
- `docs/agent-handoffs/learnings/` for successful patterns.
|
||||
#### Todo note template
|
||||
|
||||
- Pending tasks
|
||||
- Completed tasks
|
||||
- Blocked tasks
|
||||
|
||||
#### Decision note template
|
||||
|
||||
- Decision
|
||||
- Alternatives considered
|
||||
- Rationale
|
||||
- Consequences/follow-ups
|
||||
|
||||
#### Test log template
|
||||
|
||||
- Command
|
||||
- Result (pass/fail/warn)
|
||||
- Notes (environmental limits, retries, artifacts)
|
||||
|
||||
## Knowledge-sharing protocol
|
||||
|
||||
### Where to write durable knowledge
|
||||
|
||||
- `docs/agent-handoffs/learnings/` for reusable successes.
|
||||
- `docs/agent-handoffs/incidents/` for failures and mitigations.
|
||||
- `KNOWN_ISSUES.md` for active, reproducible unresolved issues.
|
||||
|
||||
### 3) Use generic, consistent names
|
||||
### File naming
|
||||
|
||||
- Format: `YYYY-MM-DD-short-topic.md`
|
||||
- Keep names descriptive and repository-agnostic.
|
||||
Use `YYYY-MM-DD-short-topic.md`.
|
||||
|
||||
### 4) Use the required structure
|
||||
### Required structure for learning/incident notes
|
||||
|
||||
Each note should include:
|
||||
1. Context
|
||||
2. Observation
|
||||
3. Action taken
|
||||
4. Validation performed
|
||||
5. Recommendation for next agents
|
||||
|
||||
- Context
|
||||
- Observation
|
||||
- Action taken
|
||||
- Validation performed
|
||||
- Recommendation for next agents
|
||||
## Quality checklist before completion
|
||||
|
||||
### 5) Promote active problems to `KNOWN_ISSUES.md`
|
||||
- Scope matches request.
|
||||
- Documentation remains repository-agnostic unless explicitly needed.
|
||||
- No unsupported claims about testing.
|
||||
- Assumptions and limitations are called out.
|
||||
- Changes are easy to revert.
|
||||
|
||||
If the problem is still reproducible or unresolved, add/update a `KNOWN_ISSUES.md` entry with status, impact, workaround, and last verified date.
|
||||
=======
|
||||
## Project Overview
|
||||
## Anti-patterns to avoid
|
||||
|
||||
**bitvid** is a decentralized video sharing platform built on the Nostr protocol. It operates as a static client — no backend server, no custody of user keys, no server-side signing. All authentication and state management happens client-side or via connected Nostr signers.
|
||||
- Embedding product/company-specific guidance in baseline docs.
|
||||
- Large refactors when a focused change is sufficient.
|
||||
- Skipping validation without recording why.
|
||||
- Creating duplicate notes when an update would suffice.
|
||||
|
||||
### Key Technologies
|
||||
- **Nostr**: Decentralized identity and event protocol (NIP-07, NIP-33, NIP-44, NIP-46, NIP-51, NIP-71, etc.)
|
||||
- **WebTorrent**: P2P video streaming fallback
|
||||
- **Tailwind CSS**: Utility-first styling with custom design tokens
|
||||
- **Playwright**: E2E and visual regression testing
|
||||
- **Node.js 22+**: Development environment
|
||||
## Customization policy
|
||||
|
||||
### License
|
||||
GPL-3.0-or-later (see `LICENSE`)
|
||||
This file should stay generic until real repository-specific patterns emerge. When customizing:
|
||||
|
||||
---
|
||||
|
||||
## Codebase Structure
|
||||
|
||||
```
|
||||
bitvid/
|
||||
├── js/ # Main application JavaScript
|
||||
│ ├── app.js # Main orchestrator (bitvidApp)
|
||||
│ ├── nostr/ # Nostr protocol implementation
|
||||
│ │ ├── client.js # Core Nostr client with signer adapters
|
||||
│ │ ├── nip71.js # NIP-71 video note parsing
|
||||
│ │ ├── sessionActor.js # Anonymous session actors for telemetry
|
||||
│ │ └── adapters/ # NIP-07, NIP-46, nsec signer adapters
|
||||
│ ├── services/ # Business logic services
|
||||
│ │ └── playbackService.js # Video playback orchestration
|
||||
│ ├── ui/ # UI components and controllers
|
||||
│ ├── state/ # State management (cache.js)
|
||||
│ ├── utils/ # Utility functions
|
||||
│ ├── constants.js # Feature flags and WSS trackers
|
||||
│ ├── config.js # Re-exports from instance config
|
||||
│ ├── magnetUtils.js # Magnet URI helpers
|
||||
│ ├── nostrEventSchemas.js # Event schema definitions (source of truth)
|
||||
│ └── nostrClientFacade.js # Main Nostr client entry point
|
||||
├── config/
|
||||
│ └── instance-config.js # Deployment configuration
|
||||
├── css/
|
||||
│ ├── tokens.css # Design token definitions
|
||||
│ ├── tailwind.source.css # Tailwind input file
|
||||
│ └── tailwind.generated.css # Generated (gitignored)
|
||||
├── tests/ # Test suites
|
||||
│ ├── unit/ # Unit tests
|
||||
│ ├── e2e/ # End-to-end tests
|
||||
│ ├── visual/ # Visual regression tests
|
||||
│ ├── nostr/ # Nostr-specific tests
|
||||
│ └── moderation/ # Moderation feature tests
|
||||
├── docs/ # Documentation
|
||||
│ ├── nostr-event-schemas.md # Event schema reference
|
||||
│ ├── playback-fallback.md # Playback architecture
|
||||
│ ├── moderation/ # Moderation system docs
|
||||
│ └── nips/ # NIP reference documentation
|
||||
├── views/ # HTML view templates
|
||||
├── components/ # HTML component templates
|
||||
├── content/ # Markdown content (docs, roadmap)
|
||||
├── torrent/ # WebTorrent integration
|
||||
├── scripts/ # Build and utility scripts
|
||||
└── .github/workflows/ # CI/CD configuration
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Essential Files to Know
|
||||
|
||||
| File | Purpose |
|
||||
|------|---------|
|
||||
| `AGENTS.md` | AI agent guide with architectural rules and mission |
|
||||
| `KNOWN_ISSUES.md` | Pre-existing test failures and environmental quirks |
|
||||
| `CONTRIBUTING.md` | Developer setup and contribution guidelines |
|
||||
| `js/app.js` | Main application orchestrator (`bitvidApp`) |
|
||||
| `js/nostr/client.js` | Core Nostr client with signer registry |
|
||||
| `js/nostrEventSchemas.js` | **Source of truth** for all Nostr event schemas |
|
||||
| `js/constants.js` | Feature flags and runtime configuration |
|
||||
| `config/instance-config.js` | Deployment-specific settings |
|
||||
| `js/testHarness.js` | Playwright test harness (`window.__bitvidTest__`) |
|
||||
| `tests/e2e/helpers/bitvidTestFixture.ts` | Reusable Playwright fixture for agent testing |
|
||||
| `scripts/agent/simple-relay.mjs` | Mock Nostr relay with HTTP seeding API |
|
||||
| `docs/nostr-event-schemas.md` | Event schema documentation |
|
||||
| `context/` | Agent working state: current goal, scope, assumptions (see AGENTS.md §15) |
|
||||
| `todo/` | Agent task checklist with done/blocked sections (see AGENTS.md §15) |
|
||||
| `decisions/` | Agent decision log: choices, alternatives, rationale (see AGENTS.md §15) |
|
||||
| `test_logs/` | Agent verification log: commands run and results (see AGENTS.md §15) |
|
||||
|
||||
---
|
||||
|
||||
## Development Workflow
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
### Initial Setup
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- `KNOWN_ISSUES.md`: currently active issues and workarounds.
|
||||
- `docs/agent-handoffs/learnings/`: reusable successes.
|
||||
- `docs/agent-handoffs/incidents/`: reusable failure analysis.
|
||||
- `CONTRIBUTING.md`: expectations for commits, PRs, and validation.
|
||||
|
||||
## Writing style for agent notes
|
||||
|
||||
- Prefer concise bullets over long prose.
|
||||
- Include exact commands when they improve reproducibility.
|
||||
- Clearly separate facts from assumptions.
|
||||
- End with a practical recommendation for the next agent.
|
||||
|
||||
## Anti-patterns
|
||||
|
||||
- Project/brand-specific assumptions in reusable docs.
|
||||
- Unnecessary broad refactors.
|
||||
- Claims of validation without executed checks.
|
||||
- Duplicate notes that fragment context across many files.
|
||||
=======
|
||||
```bash
|
||||
# Clone and install
|
||||
git clone https://github.com/PR0M3TH3AN/bitvid.git
|
||||
cd bitvid
|
||||
npm ci # Use ci for exact lockfile deps
|
||||
|
||||
# Build (generates Tailwind CSS)
|
||||
npm run build
|
||||
|
||||
# Start local server
|
||||
python -m http.server 8000
|
||||
# or
|
||||
npx serve
|
||||
```
|
||||
|
||||
### Before Every PR
|
||||
|
||||
```bash
|
||||
# Required checks
|
||||
npm run format # Format CSS/HTML/MD
|
||||
npm run lint # All lint checks
|
||||
npm run test:unit # Or use shards for faster feedback
|
||||
|
||||
# Recommended for UI changes
|
||||
npm run test:visual
|
||||
```
|
||||
|
||||
### Available Scripts
|
||||
|
||||
| Script | Purpose |
|
||||
|--------|---------|
|
||||
| `npm run build` | Full build (Tailwind + dist + verify) |
|
||||
| `npm run build:css` | Regenerate Tailwind only |
|
||||
| `npm run format` | Format with Prettier |
|
||||
| `npm run lint` | Run all linting checks |
|
||||
| `npm run lint:css` | CSS token validation |
|
||||
| `npm run lint:inline-styles` | Block inline styles |
|
||||
| `npm run lint:tokens` | Design token enforcement |
|
||||
| `npm run lint:file-size` | Enforce file size limits |
|
||||
| `npm run lint:innerhtml` | Enforce innerHTML baseline |
|
||||
| `npm run test:unit` | Full unit test suite |
|
||||
| `npm run test:unit:shard1` | Shard 1/3 (faster local dev) |
|
||||
| `npm run test:unit:shard2` | Shard 2/3 |
|
||||
| `npm run test:unit:shard3` | Shard 3/3 |
|
||||
| `npm run test:smoke` | Run critical path smoke tests |
|
||||
| `npm run test:dm:unit` | Direct message unit tests |
|
||||
| `npm run test:dm:integration` | DM integration tests |
|
||||
| `npm run test:e2e` | Headless E2E tests |
|
||||
| `npm run test:visual` | Visual regression tests |
|
||||
| `node scripts/agent/validate-events.mjs` | Validate Nostr event schemas |
|
||||
|
||||
---
|
||||
|
||||
## CI/CD Pipeline
|
||||
|
||||
The CI workflow (`.github/workflows/ci.yml`) runs on every push to `main` and all PRs:
|
||||
|
||||
| Job | Timeout | Description |
|
||||
|-----|---------|-------------|
|
||||
| `build` | 45 min | Lint, build, visual regression |
|
||||
| `unit-tests` | 30 min | Sharded unit tests (3 shards) |
|
||||
| `dm-unit-tests` | 20 min | Direct message unit tests |
|
||||
| `dm-integration-tests` | 30 min | DM integration tests |
|
||||
| `e2e-headless` | 45 min | Playwright E2E tests |
|
||||
|
||||
**Concurrency**: `cancel-in-progress: true` — new commits cancel running jobs.
|
||||
|
||||
---
|
||||
|
||||
## Code Conventions
|
||||
|
||||
### Logging
|
||||
|
||||
**Always use the logger utility**, never call `console.*` directly:
|
||||
|
||||
```javascript
|
||||
import { logger } from './utils/logger.js';
|
||||
|
||||
logger.user.error('User-facing error'); // Production visible
|
||||
logger.dev.log('Debug info'); // Dev mode only (IS_DEV_MODE)
|
||||
```
|
||||
|
||||
### Styling Rules
|
||||
|
||||
1. **Token-first**: Use design tokens from `css/tokens.css`, never raw hex colors
|
||||
2. **No inline styles**: `style=` attributes and `element.style` are blocked by lint
|
||||
3. **Semantic tokens**: Use `bg`, `text`, `accent`, `border`, `danger`, etc.
|
||||
4. **Theme scopes**: Toggle themes via `data-theme` attribute, not code
|
||||
|
||||
### Nostr Event Schemas
|
||||
|
||||
All Nostr events must be defined in `js/nostrEventSchemas.js`:
|
||||
|
||||
```javascript
|
||||
import { buildVideoPostEvent, NOTE_TYPES } from './nostrEventSchemas.js';
|
||||
|
||||
const event = buildVideoPostEvent({
|
||||
pubkey: hexPubkey,
|
||||
created_at: Math.floor(Date.now() / 1000),
|
||||
dTagValue: 'video-id',
|
||||
content: {
|
||||
version: 3,
|
||||
title: 'My Video',
|
||||
videoRootId: 'video-id',
|
||||
url: 'https://example.com/video.mp4'
|
||||
}
|
||||
});
|
||||
```
|
||||
|
||||
### Magnet Handling
|
||||
|
||||
**Critical rules** — magnets are fragile:
|
||||
|
||||
```javascript
|
||||
import { safeDecodeMagnet, normalizeAndAugmentMagnet } from './magnetUtils.js';
|
||||
|
||||
// Always decode first
|
||||
const raw = safeDecodeMagnet(userInput);
|
||||
|
||||
// Then normalize with hints
|
||||
const enriched = normalizeAndAugmentMagnet(raw, { wsHint, xsHint });
|
||||
|
||||
// NEVER use new URL() on magnets — it corrupts hashes!
|
||||
```
|
||||
|
||||
- WSS trackers only (from `js/constants.js`)
|
||||
- Persist raw magnet strings, decode only at playback
|
||||
- Include HTTPS `ws=`/`xs=` hints when available
|
||||
|
||||
### Architecture Pattern
|
||||
|
||||
**Separation of concerns**:
|
||||
|
||||
- `bitvidApp` (js/app.js) — Orchestrator, manages app-wide state
|
||||
- UI Controllers — Handle specific UI components (e.g., `ProfileModalController`)
|
||||
- Services — Business logic (e.g., `playbackService.js`)
|
||||
- State — Central truth in `js/state/cache.js`
|
||||
|
||||
**Data flow**:
|
||||
1. User action triggers controller event handler
|
||||
2. Controller invokes callback provided by `bitvidApp`
|
||||
3. `bitvidApp` executes logic, updates central state
|
||||
4. `bitvidApp` notifies controller to re-render
|
||||
|
||||
---
|
||||
|
||||
## Feature Flags
|
||||
|
||||
Feature flags in `js/constants.js` gate experimental behavior:
|
||||
|
||||
| Flag | Default | Purpose |
|
||||
|------|---------|---------|
|
||||
| `URL_FIRST_ENABLED` | Depends on config | Try URL before magnet |
|
||||
| `FEATURE_WATCH_HISTORY_V2` | true | Watch history system |
|
||||
| `FEATURE_PUBLISH_NIP71` | false | NIP-71 video publishing |
|
||||
| `FEATURE_SEARCH_FILTERS` | Dev mode only | Advanced search |
|
||||
| `FEATURE_TRUST_SEEDS` | true | Baseline trust seeds |
|
||||
| `FEATURE_TRUSTED_HIDE_CONTROLS` | true | Trusted mute/spam hide controls |
|
||||
| `FEATURE_IMPROVED_COMMENT_FETCHING` | true | Improved comment fetching logic |
|
||||
|
||||
Toggle at runtime:
|
||||
```javascript
|
||||
import { setUrlFirstEnabled } from './constants.js';
|
||||
setUrlFirstEnabled(false); // Disable URL-first playback
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Nostr Integration
|
||||
|
||||
### Key NIPs Used
|
||||
|
||||
| NIP | Purpose |
|
||||
|-----|---------|
|
||||
| NIP-07 | Browser extension signing |
|
||||
| NIP-33 | Parameterized replaceable events (videos) |
|
||||
| NIP-04 | Legacy DM encryption |
|
||||
| NIP-44 | Modern encryption |
|
||||
| NIP-46 | Remote signing |
|
||||
| NIP-51 | Lists (mute, admin) |
|
||||
| NIP-56 | Moderation reports |
|
||||
| NIP-71 | Video events |
|
||||
|
||||
### Signer Adapters
|
||||
|
||||
```javascript
|
||||
import { nostrClient } from './nostrClientFacade.js';
|
||||
import { setActiveSigner } from './nostr/client.js';
|
||||
|
||||
// Register a signer
|
||||
setActiveSigner({
|
||||
pubkey,
|
||||
signEvent: (event) => signer.sign(event),
|
||||
nip04Encrypt: (target, text) => signer.nip04.encrypt(target, text),
|
||||
nip04Decrypt: (actor, cipher) => signer.nip04.decrypt(actor, cipher),
|
||||
// Optional: nip44Encrypt, nip44Decrypt
|
||||
});
|
||||
```
|
||||
|
||||
### NIP-33 Addressing (Important!)
|
||||
|
||||
Video events are addressed by `kind + pubkey + d-tag`:
|
||||
|
||||
```javascript
|
||||
// CORRECT: Use the d-tag for addressing
|
||||
const dTag = event.tags.find(t => t[0] === 'd')?.[1];
|
||||
|
||||
// WRONG: Don't use logical IDs like videoRootId for relay lookups
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Testing Guidelines
|
||||
|
||||
### Before Starting Work
|
||||
|
||||
1. Read `KNOWN_ISSUES.md` for pre-existing failures
|
||||
2. Run relevant test shard to verify baseline
|
||||
|
||||
### Running Tests
|
||||
|
||||
```bash
|
||||
# Fast feedback during development
|
||||
npm run test:unit:shard1
|
||||
|
||||
# Full suite before PR
|
||||
npm run test:unit
|
||||
|
||||
# Visual changes
|
||||
npm run test:visual
|
||||
|
||||
# DM features
|
||||
npm run test:dm:unit && npm run test:dm:integration
|
||||
|
||||
# E2E journeys
|
||||
npm run test:e2e
|
||||
```
|
||||
|
||||
### Test Artifacts
|
||||
|
||||
Failed visual tests store artifacts in `artifacts/test-results/`:
|
||||
- Screenshots
|
||||
- Videos
|
||||
- Traces
|
||||
|
||||
View with: `./scripts/show-artifacts.sh`
|
||||
|
||||
### Agent E2E Testing (Playwright)
|
||||
|
||||
bitvid includes a test harness for programmatic Playwright testing without browser extensions or real relays. See `AGENTS.md` Section 14 for the full reference. Quick start:
|
||||
|
||||
```typescript
|
||||
import { test, expect } from "./helpers/bitvidTestFixture";
|
||||
|
||||
test("my test", async ({ page, gotoApp, loginAs, seedEvent }) => {
|
||||
await seedEvent({ title: "Test Video", url: "https://example.com/v.mp4" });
|
||||
await gotoApp();
|
||||
await loginAs(page);
|
||||
// interact with the app using data-testid selectors
|
||||
await expect(page.locator('[data-testid="upload-button"]')).toBeVisible();
|
||||
});
|
||||
```
|
||||
|
||||
Key capabilities:
|
||||
- **Programmatic login**: `loginAs(page)` uses `window.__bitvidTest__.loginWithNsec()` — no modal interaction needed
|
||||
- **Mock relay**: Each test gets an isolated in-memory relay with HTTP seeding
|
||||
- **Relay override**: `?__test__=1&__testRelays__=ws://localhost:8877` redirects all connections
|
||||
- **State inspection**: `window.__bitvidTest__.getAppState()` returns login status, relays, etc.
|
||||
- **Stable selectors**: All key elements have `data-testid` attributes (see AGENTS.md Section 14)
|
||||
|
||||
---
|
||||
|
||||
## Common Tasks
|
||||
|
||||
### Adding a New Nostr Event Type
|
||||
|
||||
1. Define schema in `js/nostrEventSchemas.js`
|
||||
2. Add builder function
|
||||
3. Document in `docs/nostr-event-schemas.md`
|
||||
4. Add tests
|
||||
|
||||
### Creating UI Components
|
||||
|
||||
1. Create controller in `js/ui/`
|
||||
2. Wire callbacks through `bitvidApp`
|
||||
3. Read state via provided getters, never directly
|
||||
4. Use design tokens for styling
|
||||
|
||||
### Modifying Playback Behavior
|
||||
|
||||
1. Check `js/services/playbackService.js` for stream handling
|
||||
2. Update `js/constants.js` feature flags if needed
|
||||
3. Test with both URL and magnet sources
|
||||
4. Document rollback steps in PR
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Build Issues
|
||||
|
||||
```bash
|
||||
# Browserslist warning
|
||||
npx update-browserslist-db@latest
|
||||
|
||||
# Tailwind not regenerating
|
||||
rm css/tailwind.generated.css && npm run build:css
|
||||
```
|
||||
|
||||
### Test Hangs
|
||||
|
||||
- Unit tests may hang after completion — use `Ctrl+C`
|
||||
- Use shards for faster local runs
|
||||
- Set `UNIT_TEST_TIMEOUT_MS=120000` for slow tests
|
||||
|
||||
### Lint Failures
|
||||
|
||||
- **Inline styles**: Move to CSS classes or tokens
|
||||
- **Hex colors**: Use design tokens
|
||||
- **Design tokens**: Use `theme()` or existing utilities
|
||||
|
||||
---
|
||||
|
||||
## Release Channels & Promotion Pipeline
|
||||
|
||||
Code flows through three branches with increasing stability:
|
||||
|
||||
```
|
||||
unstable → beta → main
|
||||
(dev) (soak) (prod)
|
||||
```
|
||||
|
||||
| Branch | Purpose | CI Required | Manual QA |
|
||||
|--------|---------|-------------|-----------|
|
||||
| `unstable` | Active development, AI agent PRs land here | Yes | No |
|
||||
| `beta` | Stabilization soak (hosted for testing) | Yes | Yes — hosted domain |
|
||||
| `main` | Production | Yes | Verified via beta |
|
||||
|
||||
**Promotion rules:**
|
||||
- `unstable → beta`: After a batch of improvements passes CI and local testing
|
||||
- `beta → main`: After weeks of soak time on the beta hosted domain with no regressions
|
||||
- Never push directly to `main` or `beta` — always promote from the previous stage
|
||||
|
||||
### Emergency Response
|
||||
|
||||
If a change breaks playback or magnet handling:
|
||||
1. Revert immediately
|
||||
2. Note rollback in PR
|
||||
3. Document in AGENTS.md
|
||||
|
||||
---
|
||||
|
||||
## Multi-Agent Development Workflow
|
||||
|
||||
This project uses multiple AI coding agents working in parallel:
|
||||
- **Claude Code** — Refactoring, convention enforcement, codebase-wide changes
|
||||
- **OpenAI Codex** — Isolated feature implementation with clear specs
|
||||
- **Google Jules** — Issue triage and straightforward bug fixes
|
||||
|
||||
### Coordination Rules
|
||||
|
||||
All agents **must** follow the subsystem boundaries and PR discipline rules in `AGENTS.md` Section 12. The key principles:
|
||||
|
||||
1. **Check before you start.** Look at open PRs before beginning work by running:
|
||||
```
|
||||
curl -s "https://api.github.com/repos/PR0M3TH3AN/bitvid/pulls?state=open&per_page=100" | jq '{count: length, titles: [.[].title]}'
|
||||
```
|
||||
If another agent has an open PR touching the same files, stop and flag the conflict.
|
||||
2. **One subsystem per PR.** Don't mix unrelated changes. A lint fix and a feature addition are two separate PRs.
|
||||
3. **`js/app.js` is single-writer.** Only one PR at a time should modify the main orchestrator.
|
||||
4. **Merge fast, branch short.** Long-lived branches cause exponential merge pain with multiple agents. Keep PRs small and mergeable in one sitting.
|
||||
|
||||
### For Human Maintainers
|
||||
|
||||
When assigning work to agents:
|
||||
- Update the "Currently In-Flight Work" section in `AGENTS.md` to reserve subsystems
|
||||
- Avoid sending two agents at the same subsystem simultaneously
|
||||
- Review and merge agent PRs promptly to keep the queue short — stale PRs compound conflicts
|
||||
- Use PR title prefixes (`[nostr-core]`, `[ui]`, `[playback]`, etc.) to make scope visible
|
||||
|
||||
---
|
||||
|
||||
## Key Documentation
|
||||
|
||||
| Document | What It Covers |
|
||||
|----------|---------------|
|
||||
| `AGENTS.md` | AI agent rules, mission, architectural decisions |
|
||||
| `CONTRIBUTING.md` | Setup, PR process, DCO |
|
||||
| `KNOWN_ISSUES.md` | Pre-existing test failures |
|
||||
| `docs/nostr-event-schemas.md` | Event definitions |
|
||||
| `docs/playback-fallback.md` | URL-first strategy |
|
||||
| `docs/moderation/README.md` | Moderation system |
|
||||
| `docs/logging.md` | Logger usage |
|
||||
| `docs/agents/TORCH.md` | TORCH distributed task locking protocol |
|
||||
| `context/` / `todo/` / `decisions/` / `test_logs/` | Agent persistent state files (see AGENTS.md §15) |
|
||||
|
||||
---
|
||||
|
||||
## Quick Reference
|
||||
|
||||
### Import Patterns
|
||||
|
||||
```javascript
|
||||
// Nostr client
|
||||
import { nostrClient } from './nostrClientFacade.js';
|
||||
|
||||
// View events (analytics)
|
||||
import { recordVideoView } from './nostrViewEventsFacade.js';
|
||||
|
||||
// Watch history
|
||||
import { updateWatchHistoryListWithDefaultClient } from './nostrWatchHistoryFacade.js';
|
||||
|
||||
// Event building
|
||||
import { buildVideoPostEvent } from './nostrEventSchemas.js';
|
||||
|
||||
// Feature flags
|
||||
import { URL_FIRST_ENABLED, setUrlFirstEnabled } from './constants.js';
|
||||
|
||||
// Logger
|
||||
import { logger } from './utils/logger.js';
|
||||
```
|
||||
|
||||
### Content Schema v3
|
||||
|
||||
```javascript
|
||||
{
|
||||
version: 3,
|
||||
title: string, // Required
|
||||
url?: string, // HTTPS video URL
|
||||
magnet?: string, // WebTorrent magnet
|
||||
thumbnail?: string,
|
||||
description?: string,
|
||||
mode: 'live' | 'dev',
|
||||
isPrivate: boolean,
|
||||
deleted: boolean,
|
||||
videoRootId: string // Stable identifier
|
||||
}
|
||||
```
|
||||
|
||||
Validation: Must have `title` + at least one of `url` or `magnet`.
|
||||
|
||||
---
|
||||
|
||||
## Final Notes
|
||||
|
||||
1. **Read AGENTS.md first** — it contains mission-critical architectural decisions and the Agent Execution Protocol (§15)
|
||||
2. **Check KNOWN_ISSUES.md** — avoid investigating pre-existing failures
|
||||
3. **Use sharded tests** — faster feedback during development
|
||||
4. **Never commit generated CSS** — `css/tailwind.generated.css` is gitignored
|
||||
5. **Token-first styling** — no raw colors, no inline styles
|
||||
6. **Keep magnets raw** — decode only at playback time
|
||||
7. **Document rollback steps** — especially for playback changes
|
||||
>>>>>>> Stashed changes
|
||||
- Add a clearly labeled section: `Repository-specific overrides`.
|
||||
- Keep generic workflow unchanged.
|
||||
- Include evidence (commands, failures, repeated incidents) for each override.
|
||||
+45
-276
@@ -1,294 +1,63 @@
|
||||
# Contributing to bitvid
|
||||
# CONTRIBUTING.md — Generic Collaboration Guide
|
||||
|
||||
Thanks for helping build an open video ecosystem on nostr!
|
||||
This repository is designed for human and AI contributors. Keep contributions small, clear, and verifiable.
|
||||
|
||||
## License Model
|
||||
## Contribution principles
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- Keep changes focused and minimal.
|
||||
- Explain why the change is needed, not only what changed.
|
||||
- Preserve generic behavior unless explicit repository-specific behavior is required.
|
||||
=======
|
||||
- **App** (this repo): GPL-3.0-or-later
|
||||
- **Potential SDKs/embeds** (if split later): Apache-2.0 (to keep integration friction low)
|
||||
>>>>>>> Stashed changes
|
||||
- Prefer focused pull requests.
|
||||
- Avoid unrelated refactors.
|
||||
- Preserve existing behavior unless a change is explicitly requested.
|
||||
- Document assumptions and tradeoffs.
|
||||
|
||||
All contributions to this repository are made under the repository’s license (GPL-3.0-or-later).
|
||||
## Standard contribution flow
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
1. Confirm `AGENTS.md` and `CLAUDE.md` were followed.
|
||||
2. Run relevant checks/tests for the changed scope.
|
||||
3. Update documentation impacted by behavior or workflow changes.
|
||||
4. If reusable knowledge was discovered, update/add a note in `docs/agent-handoffs/`.
|
||||
5. If an issue remains active, update `KNOWN_ISSUES.md`.
|
||||
=======
|
||||
## Developer Certificate of Origin (DCO)
|
||||
>>>>>>> Stashed changes
|
||||
1. Sync your branch with the target base branch.
|
||||
2. Read baseline guidance:
|
||||
- `AGENTS.md`
|
||||
- `CLAUDE.md`
|
||||
- `KNOWN_ISSUES.md`
|
||||
3. Implement minimal changes required to solve the task.
|
||||
4. Run relevant validation checks.
|
||||
5. Update documentation if behavior or workflow changed.
|
||||
6. Commit with a clear message.
|
||||
7. Open a PR with complete context.
|
||||
|
||||
We use the DCO to keep contributions simple and legally sound. Sign your commits with `-s`:
|
||||
## Commit expectations
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- Use clear, descriptive commit messages.
|
||||
- Keep unrelated edits in separate commits.
|
||||
- Do not commit temporary debug code, generated noise, or local-only artifacts.
|
||||
=======
|
||||
```bash
|
||||
git commit -s -m "feat: add cool thing"
|
||||
```
|
||||
>>>>>>> Stashed changes
|
||||
- Keep commits atomic and descriptive.
|
||||
- Use imperative commit subjects.
|
||||
- Separate mechanical renames from behavioral changes when possible.
|
||||
|
||||
This adds a `Signed-off-by: Your Name <[email protected]>` line and certifies you have the right to contribute under the project license.
|
||||
See [https://developercertificate.org/](https://developercertificate.org/) for the full text.
|
||||
## Pull request expectations
|
||||
|
||||
## (Optional) Contributor License Agreement (CLA)
|
||||
Each PR should include:
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- What changed
|
||||
- Why it changed
|
||||
- Validation performed
|
||||
- Follow-up items or risks
|
||||
- **Summary**: what changed.
|
||||
- **Why**: motivation/problem solved.
|
||||
- **Files modified**: key files touched.
|
||||
- **Validation**: exact commands run and outcomes.
|
||||
- **Risks / rollback**: known risks and how to revert.
|
||||
|
||||
If no tests/checks were run, explicitly state why.
|
||||
## Validation expectations
|
||||
|
||||
## Agent handoff expectations
|
||||
- Run checks most relevant to changed files (tests, lint, typecheck, build, scripts).
|
||||
- If a check cannot run, include:
|
||||
- command attempted,
|
||||
- reason it failed or was unavailable,
|
||||
- fallback verification performed.
|
||||
|
||||
When your work creates reusable context:
|
||||
## Documentation and handoffs
|
||||
|
||||
- Prefer updating an existing handoff note over creating duplicates.
|
||||
- If creating a new note, use `YYYY-MM-DD-short-topic.md`.
|
||||
- Keep notes generic and actionable.
|
||||
- Use the required sections from `docs/agent-handoffs/README.md`.
|
||||
=======
|
||||
If we later introduce **dual-licensing** options (e.g., commercial licenses for enterprises), we may add an _optional_ CLA for contributors who want to grant relicense rights. You will be asked to agree explicitly in any PR that requires it. We will keep community use under GPL-3.0-or-later.
|
||||
When your work creates reusable knowledge:
|
||||
|
||||
## Code Guidelines
|
||||
>>>>>>> Stashed changes
|
||||
- Add/update `docs/agent-handoffs/learnings/` for successful patterns.
|
||||
- Add/update `docs/agent-handoffs/incidents/` for failure modes and mitigations.
|
||||
- Add/update `KNOWN_ISSUES.md` for active unresolved issues.
|
||||
|
||||
- Prefer small, focused PRs.
|
||||
- Add tests where reasonable; keep UI accessible.
|
||||
- Follow existing formatting/lint rules.
|
||||
- Update docs and user-facing text when behavior changes.
|
||||
- Do not commit `css/tailwind.generated.css`; it is generated at build time.
|
||||
Use filename format: `YYYY-MM-DD-short-topic.md`.
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
When workflows change:
|
||||
## Security and privacy
|
||||
|
||||
- Update `KNOWN_ISSUES.md` for newly discovered active limitations/workarounds.
|
||||
- Add/update a learning or incident note for durable guidance.
|
||||
=======
|
||||
## Agent PR Conventions
|
||||
|
||||
Automated agents contributing to this repository should follow these rules:
|
||||
|
||||
- **Atomic Commits**: Keep changes small, focused, and self-contained.
|
||||
- **Descriptive Titles**: Use clear, semantic titles (e.g., `fix(ui): resolve upload modal overflow`).
|
||||
- **Commit Messages**: Use the convention `type(scope): description (agent)` (e.g., `fix(ai): formatting (agent)` or `docs(ai): update quickstart (agent)`).
|
||||
- **Reference Issues**: Link to relevant issues in the PR description.
|
||||
- **Review AGENTS.md**: Always consult `AGENTS.md` for specific architectural guidelines (like URL-first playback, token-first design system) and constraints before starting work.
|
||||
- **Review KNOWN_ISSUES.md**: Before starting development or debugging, review `KNOWN_ISSUES.md` to avoid investigating pre-existing failures or limitations.
|
||||
- **Dependency Upgrades**: Major or risky dependency upgrades must be documented by creating a Markdown file in the `issues/` directory (e.g., `issues/upgrade-<pkg>.md`) with a plan and risk assessment, rather than opening an immediate PR.
|
||||
- **Efficiency**: Prefer running targeted or sharded tests (e.g., `npm run test:unit:shard1`, `shard2`, or `shard3`) to conserve resources during iteration.
|
||||
|
||||
## Submitting a Pull Request
|
||||
|
||||
1. Fork the repository and create a new branch from `main`.
|
||||
2. Make your changes, adding tests if applicable.
|
||||
3. Run `npm run format`, `npm run lint`, and unit tests (e.g. `npm run test:unit` or a shard like `npm run test:unit:shard1`) to ensure quality before pushing.
|
||||
4. (Optional) Run `npm run test:visual` if you made UI changes.
|
||||
5. (Optional) Run domain-specific tests if relevant (e.g., `npm run test:dm:unit` for Direct Messages).
|
||||
6. Push your branch and open a Pull Request against the `main` branch.
|
||||
7. Provide a clear description of the problem and solution.
|
||||
|
||||
## CI Behavior and Operations
|
||||
|
||||
### Concurrency (superseded runs)
|
||||
|
||||
The `CI` workflow is configured with `concurrency.cancel-in-progress: true`, which means when you push new commits to the same PR or branch, any in-flight run for the same workflow group is canceled automatically. This keeps the latest changes running and stops superseded runs from burning capacity. If you need to cancel runs manually (for example, stuck or obviously outdated runs), operators can use the GitHub CLI:
|
||||
|
||||
```bash
|
||||
gh run list --workflow=CI --limit 10
|
||||
gh run list --workflow=CI --limit 10 | awk 'NR>1 {print $1}' | xargs -n1 gh run cancel
|
||||
```
|
||||
|
||||
If a run refuses to cancel normally, GitHub provides a `force-cancel` endpoint. We only use this in the automated cleanup workflow (below) or when a normal `gh run cancel` does not take effect.
|
||||
|
||||
### Job timeouts
|
||||
|
||||
Each job in the `CI` workflow has an explicit timeout:
|
||||
|
||||
- `build`: 45 minutes
|
||||
- `unit-tests` (sharded): 30 minutes
|
||||
- `dm-unit-tests`: 20 minutes
|
||||
- `dm-integration-tests`: 30 minutes
|
||||
- `e2e-headless`: 45 minutes
|
||||
|
||||
If a job exceeds its timeout, the runner terminates it automatically, so keep an eye on the longest-running suites when adjusting tests.
|
||||
|
||||
### Cleanup workflow (manual invocation)
|
||||
|
||||
The `Cleanup stuck workflow runs` workflow cancels queued or in-progress runs older than the configured stale threshold (currently 2 hours). It runs on a schedule every 30 minutes, but you can also trigger it manually:
|
||||
|
||||
```bash
|
||||
gh workflow run "Cleanup stuck workflow runs"
|
||||
```
|
||||
|
||||
This workflow uses the `force-cancel` endpoint to ensure stalled runs are terminated reliably, so prefer it for true stuck runs instead of normal cancellation.
|
||||
|
||||
## Development Setup
|
||||
|
||||
To set up the project locally:
|
||||
|
||||
1. **Prerequisites**:
|
||||
- **Node.js**: v22 or higher (enforced by `.npmrc`).
|
||||
- **NPM**: v10 or higher (included with Node 22).
|
||||
|
||||
2. **Install Dependencies**:
|
||||
Use `npm ci` to ensure you get the exact dependencies from `package-lock.json`.
|
||||
|
||||
```bash
|
||||
npm ci
|
||||
```
|
||||
|
||||
3. **Start the Application**:
|
||||
|
||||
```bash
|
||||
npm start
|
||||
```
|
||||
|
||||
This command runs a full production build (generating `dist/` and `css/tailwind.generated.css`) and starts a local server.
|
||||
|
||||
**Or, build manually:**
|
||||
|
||||
```bash
|
||||
npm run build
|
||||
npx serve dist
|
||||
```
|
||||
|
||||
(The build command populates the `dist/` directory, which you can then serve locally.)
|
||||
|
||||
**For CSS-only changes:**
|
||||
If you are only iterating on styles, you can run the faster CSS build:
|
||||
|
||||
```bash
|
||||
npm run build:css
|
||||
```
|
||||
|
||||
4. **Run Tests**:
|
||||
|
||||
```bash
|
||||
npm run test:unit
|
||||
```
|
||||
|
||||
_Note: Running the full suite (`npm run test:unit`) is resource-intensive, runs sequentially, and may time out in some environments. We strongly recommend using sharded runs for local development to save time: `npm run test:unit:shard1`, `shard2`, or `shard3`._
|
||||
|
||||
You can also run end-to-end, smoke, and visual tests:
|
||||
|
||||
```bash
|
||||
npm run test:e2e
|
||||
npm run test:smoke
|
||||
npm run test:visual
|
||||
```
|
||||
|
||||
To run load tests (agent-driven):
|
||||
|
||||
```bash
|
||||
npm run test:load
|
||||
```
|
||||
|
||||
To update visual regression baselines:
|
||||
|
||||
```bash
|
||||
npm run test:visual:update
|
||||
```
|
||||
|
||||
For Direct Message features, run:
|
||||
|
||||
```bash
|
||||
npm run test:dm:unit
|
||||
npm run test:dm:integration
|
||||
```
|
||||
|
||||
To run smoke tests (critical path verification):
|
||||
|
||||
```bash
|
||||
npm run test:smoke
|
||||
```
|
||||
|
||||
To aggregate telemetry from test logs:
|
||||
|
||||
```bash
|
||||
npm run telemetry:aggregate
|
||||
```
|
||||
|
||||
5. **Format & Lint**:
|
||||
|
||||
```bash
|
||||
npm run format
|
||||
npm run lint
|
||||
```
|
||||
|
||||
- **Format**: Targets CSS, HTML, Markdown, and config files. (Note: JavaScript files are not currently auto-formatted by this command).
|
||||
- **Lint**: Checks for CSS errors, hex color usage, inline styles, design tokens, Tailwind guards, file size limits, innerHTML usage, asset references, and Service Worker compatibility. (Note: There is no ESLint configuration for JavaScript logic; this step focuses on style and design system guards).
|
||||
- **Note**: `npm run lint` includes an asset verification step (`lint:assets`) which checks the `dist/` directory. For full coverage, run `npm run build` before linting.
|
||||
- **Audit**: `npm run audit` runs a design system audit and generates `REMEDIATION_REPORT.md` with auto-fix suggestions.
|
||||
|
||||
6. **Git Hooks (Optional)**:
|
||||
We provide a script to set up a git pre-commit hook that runs linting and CSS builds automatically before you commit.
|
||||
```bash
|
||||
./scripts/setup-pre-commit.sh
|
||||
```
|
||||
|
||||
For a full guide, see the [Local Setup section in README.md](./README.md#local-setup).
|
||||
|
||||
### Event Schema Validation
|
||||
|
||||
When modifying event schemas or builders, verify your changes against the codebase and test suite:
|
||||
|
||||
```bash
|
||||
node scripts/agent/validate-events.mjs
|
||||
```
|
||||
|
||||
This script checks that all event builders produce valid events according to the definitions in `js/nostrEventSchemas.js`.
|
||||
|
||||
### Troubleshooting
|
||||
|
||||
- **Browserslist Warning**: If you see `Browserslist: caniuse-lite is outdated` during the build, run:
|
||||
|
||||
```bash
|
||||
npx update-browserslist-db@latest
|
||||
```
|
||||
|
||||
- **Unit Test Hangs**: `npm run test:unit` may occasionally hang after completion due to open handles. If this happens, use `Ctrl+C` to exit. For CI or faster local runs, consider running specific shards (e.g., `npm run test:unit:shard1`).
|
||||
|
||||
- **Linting Failures**: `npm run lint` includes checks for inline styles (e.g., `style="..."` or `.style.prop = ...`). Move these styles to CSS classes or design tokens to pass linting.
|
||||
|
||||
## Dev Container
|
||||
|
||||
This project includes a `.devcontainer` configuration for VS Code. It provides a pre-configured environment with Node.js 22, the GitHub CLI, and necessary extensions.
|
||||
|
||||
To use it:
|
||||
|
||||
1. Open the project in VS Code.
|
||||
2. When prompted, re-open in Container (or use the command palette: "Dev Containers: Reopen in Container").
|
||||
3. The container will automatically:
|
||||
- Install NPM dependencies (`npm ci`)
|
||||
- Run the build (`npm run build`)
|
||||
- Install Playwright browsers (so you can run `npm run test:visual`)
|
||||
|
||||
## Key Documentation
|
||||
|
||||
Before starting your work, please review these key documents:
|
||||
|
||||
- **[AGENTS.md](./AGENTS.md)**: Architectural guidelines, mission statement, and troubleshooting tips.
|
||||
- **[Documentation Index](./docs/README.md)**: A complete list of system documentation, including architecture and feed logic.
|
||||
- **[Nostr Event Schemas](./docs/nostr-event-schemas.md)**: The source of truth for all Nostr events published by the application.
|
||||
- **[Playback Fallback](./docs/playback-fallback.md)**: Details on the URL-first playback strategy and WebTorrent fallback mechanism.
|
||||
|
||||
## Security
|
||||
|
||||
If you find a vulnerability, please email **[[email protected]](mailto:[email protected])**. We’ll coordinate a responsible disclosure window before public release.
|
||||
|
||||
## Trademark
|
||||
|
||||
The **bitvid** name and logos are trademarks (see `TRADEMARKS.md`). Don’t use them in ways that imply official sponsorship or confuse users. “Powered by bitvid” attribution is encouraged.
|
||||
>>>>>>> Stashed changes
|
||||
- Never commit credentials, tokens, secrets, or personal data.
|
||||
- Redact sensitive values in logs and examples.
|
||||
- Prefer synthetic or anonymized examples in documentation.
|
||||
+7
-31
@@ -1,43 +1,19 @@
|
||||
# Known Issues
|
||||
# KNOWN_ISSUES.md
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
Track active, reproducible issues in a reusable format.
|
||||
=======
|
||||
## Tests
|
||||
>>>>>>> Stashed changes
|
||||
Track only **active, reproducible, unresolved** issues.
|
||||
|
||||
### Skipped Tests
|
||||
## Entry template
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
- Keep entries short, factual, and current.
|
||||
- List active issues only; remove resolved items promptly.
|
||||
- Link to related incident/handoff notes for deeper details.
|
||||
- Prefer one entry per distinct issue.
|
||||
=======
|
||||
The following tests are skipped due to flakiness or environmental issues and should be investigated:
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
_No skipped tests currently documented._ (Last checked: 2026-02-13)
|
||||
|
||||
### Visual Regression Tests (`test:visual`)
|
||||
|
||||
<<<<<<< Updated upstream
|
||||
### [Issue title]
|
||||
- **Status:** Open | Monitoring | Mitigated
|
||||
- **Area:** Build | Test | Tooling | Runtime | Docs | Other
|
||||
- **Symptom:**
|
||||
- **Trigger/Conditions:**
|
||||
- **Workaround:**
|
||||
- **Impact:**
|
||||
- **Related notes:** `docs/agent-handoffs/incidents/...`
|
||||
- **Related notes:** `docs/agent-handoffs/incidents/...` (optional)
|
||||
- **Last verified:** YYYY-MM-DD
|
||||
=======
|
||||
- **Artifact Retention**: Visual tests are configured to retain screenshots, traces, and videos on failure to assist with debugging. These artifacts can be found in `artifacts/test-results/`.
|
||||
- **Note**: Visual tests are passing as of 2026-02-12. (Agent verified 2026-02-13: Environment lacks `@playwright/test` dependency to run verification).
|
||||
>>>>>>> Stashed changes
|
||||
|
||||
## Environment
|
||||
## Active issues
|
||||
|
||||
### Playwright Browsers
|
||||
|
||||
- **Issue**: Visual and E2E tests (`npm run test:visual`, `npm run test:e2e`) may fail with `browserType.launch: Executable doesn't exist`.
|
||||
- **Workaround**: Run `npx playwright install` to download the required browser binaries if you are running tests outside of the pre-configured dev container or CI environment. (Last checked: 2026-02-13)
|
||||
_No active issues currently documented._
|
||||
@@ -9,17 +9,17 @@ This directory stores reusable context so future agents can work faster without
|
||||
|
||||
## When to write a note
|
||||
|
||||
Create or update a note when your work reveals knowledge that is likely useful in future sessions.
|
||||
Create or update a note when your work reveals knowledge likely useful in future sessions.
|
||||
|
||||
Examples:
|
||||
|
||||
- A reliable fix pattern that could be reused.
|
||||
- A reliable fix pattern that can be reused.
|
||||
- A recurring failure mode and its mitigation.
|
||||
- A non-obvious validation approach that prevented regressions.
|
||||
- A validation approach that prevented regressions.
|
||||
|
||||
If the issue is still active/reproducible, also update `KNOWN_ISSUES.md`.
|
||||
|
||||
## Naming convention (generic)
|
||||
## Naming convention
|
||||
|
||||
Use:
|
||||
|
||||
@@ -30,15 +30,9 @@ Examples:
|
||||
- `2026-02-14-validation-before-summary.md`
|
||||
- `2026-02-14-missing-baseline-context.md`
|
||||
|
||||
Naming tips:
|
||||
|
||||
- Keep names descriptive and concise.
|
||||
- Avoid product, team, customer, and environment names unless essential.
|
||||
- Prefer neutral technical terms.
|
||||
|
||||
## Required note structure
|
||||
|
||||
Every learning/incident note should include the following headings:
|
||||
Each learning/incident note should include:
|
||||
|
||||
1. Context
|
||||
2. Observation
|
||||
@@ -51,7 +45,7 @@ Every learning/incident note should include the following headings:
|
||||
- Keep entries short and actionable.
|
||||
- Prefer bullets over long narrative.
|
||||
- Include exact commands when useful for reproduction.
|
||||
- Avoid secrets, credentials, and user-identifying details.
|
||||
- Avoid secrets, credentials, and identifying data.
|
||||
- Distinguish facts from assumptions.
|
||||
|
||||
## Maintenance workflow
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
# Context: Parser Fuzzing Session (Example)
|
||||
|
||||
## Goal
|
||||
Improve robustness by fuzzing high-risk parsers and validators.
|
||||
|
||||
## Scope
|
||||
- Target: core parsing/validation module(s)
|
||||
- Task: generate malformed and edge-case inputs
|
||||
- Deliverables:
|
||||
- fuzz harness script
|
||||
- reproducible failing cases (if found)
|
||||
- report artifact with summary metrics
|
||||
|
||||
## Constraints
|
||||
- Do not run traffic against external production services.
|
||||
- Keep dependencies minimal.
|
||||
- Capture deterministic seeds for reproducibility.
|
||||
@@ -1,18 +0,0 @@
|
||||
# Context: Weekly Fuzz Agent Run (2026-02-13)
|
||||
|
||||
## Goal
|
||||
Improve input robustness by fuzzing high-risk parsers/decoders in `js/nostrEventSchemas.js`.
|
||||
|
||||
## Scope
|
||||
- Target: `js/nostrEventSchemas.js`
|
||||
- Task: Implement a fuzz harness to generate invalid inputs for event builder functions and validators.
|
||||
- Deliverables:
|
||||
- `scripts/agent/fuzz-nostr-schemas.mjs` (harness)
|
||||
- `examples/reproducers/` (if failures found)
|
||||
- `artifacts/fuzz-report-nostr-schemas-2026-02-13.json` (report)
|
||||
- Potential fixes in `js/nostrEventSchemas.js`
|
||||
|
||||
## Constraints
|
||||
- Do not fuzz public relays.
|
||||
- Keep crypto paths safe.
|
||||
- Minimal dependencies.
|
||||
@@ -0,0 +1,6 @@
|
||||
# Decisions (Example)
|
||||
|
||||
- **Decision:** Replace string-based DOM rendering with explicit element creation APIs.
|
||||
- **Alternatives considered:** Keep existing template string rendering with additional escaping.
|
||||
- **Rationale:** Reduces injection risk and improves maintainability.
|
||||
- **Consequences:** Requires small helper methods and minor test updates.
|
||||
@@ -1,7 +0,0 @@
|
||||
# Decisions
|
||||
|
||||
- **File:** `js/subscriptions.js`
|
||||
- **Migration:** Replaced `innerHTML` assignments with `replaceChildren()` and `document.createElement()`.
|
||||
- **Helpers:** Added `_renderStatusMessage` and `_renderLoading` to `SubscriptionsManager` to encapsulate DOM creation for status and loading states.
|
||||
- **Dependency:** Removed dependency on `getSidebarLoadingMarkup` (which returned a string) in this file, preferring local DOM creation.
|
||||
- **Baseline:** Updated baseline for `js/subscriptions.js` from 7 to 0.
|
||||
@@ -0,0 +1,16 @@
|
||||
# Style Audit Report (Example)
|
||||
|
||||
Headline: No violations detected.
|
||||
|
||||
## CSS checks
|
||||
- Total issues: 0
|
||||
|
||||
## Inline style checks
|
||||
- Total issues: 0
|
||||
|
||||
## Token/variable checks
|
||||
- Total issues: 0
|
||||
|
||||
## Next steps
|
||||
- [ ] Re-run on next release branch.
|
||||
- [ ] Open remediation tasks if new violations appear.
|
||||
@@ -1,32 +0,0 @@
|
||||
# Daily Design System Audit Report
|
||||
|
||||
Headline: ✓ No violations
|
||||
|
||||
## CSS
|
||||
Total count: 0
|
||||
|
||||
|
||||
## Hex Colors
|
||||
Total count: 0
|
||||
|
||||
|
||||
## Inline Styles
|
||||
Total count: 0
|
||||
|
||||
|
||||
## Raw Lengths
|
||||
Total count: 0
|
||||
|
||||
|
||||
## Bracket Utilities
|
||||
Total count: 0
|
||||
|
||||
|
||||
## Tailwind Palette
|
||||
Total count: 0
|
||||
|
||||
|
||||
## Next Steps
|
||||
- [ ] Review violations
|
||||
- [ ] Apply auto-fixes (if safe)
|
||||
- [ ] Open remediation PR
|
||||
@@ -0,0 +1,13 @@
|
||||
# Test Log — Documentation Alignment (Example)
|
||||
|
||||
## Validated commands
|
||||
- `npm ci` (success)
|
||||
- `npm run lint` (success)
|
||||
- `npm run audit` (success)
|
||||
|
||||
## Observations
|
||||
- Some checks may skip when required build artifacts are missing.
|
||||
- Some checks may skip in sandboxed environments missing git history.
|
||||
|
||||
## Artifacts
|
||||
- Generated audit report (if applicable)
|
||||
@@ -1,18 +0,0 @@
|
||||
# Test Log - 2026-02-13 Docs Alignment
|
||||
|
||||
## Validated Commands
|
||||
|
||||
The following commands were verified to match the updated documentation:
|
||||
|
||||
- `npm ci` (Success)
|
||||
- `npm run lint` (Success)
|
||||
- `npm run audit` (Success, generated `REMEDIATION_REPORT.md`)
|
||||
|
||||
## Observations
|
||||
|
||||
- `npm run lint:assets` skipped because `dist/asset-manifest.json` was missing (requires build). This is expected behavior as documented ("For full coverage, run `npm run build` before linting").
|
||||
- `npm run lint:sw-compat` skipped due to missing git history/HEAD^ in the sandbox environment. This is acceptable.
|
||||
|
||||
## Artifacts
|
||||
|
||||
- `REMEDIATION_REPORT.md` (Generated by `npm run audit`)
|
||||
@@ -0,0 +1,12 @@
|
||||
# TODO — Rendering Migration (Example)
|
||||
|
||||
## Pending
|
||||
- [ ] Replace remaining string-based rendering paths.
|
||||
- [ ] Add safe helper utilities where needed.
|
||||
- [ ] Update related tests.
|
||||
|
||||
## Completed
|
||||
- [x] Audited current rendering entry points.
|
||||
|
||||
## Blocked
|
||||
- [ ] Confirm final acceptance criteria with maintainers.
|
||||
@@ -1,9 +0,0 @@
|
||||
# TODO - js/subscriptions.js Migration
|
||||
|
||||
- [ ] Line 1566: `container.innerHTML = "<p class='text-muted-strong'>Please log in first.</p>";`
|
||||
- [ ] Line 1596: `container.innerHTML = "<p class='text-muted-strong'>No subscriptions found.</p>";`
|
||||
- [ ] Line 1609: `container.innerHTML = getSidebarLoadingMarkup("Fetching subscriptions…");`
|
||||
- [ ] Line 1637: `container.innerHTML = "<p class='text-muted-strong'>Subscriptions are unavailable right now.</p>";`
|
||||
- [ ] Line 1717: `container.innerHTML = "<p class='text-muted-strong'>Unable to load subscriptions right now.</p>";`
|
||||
- [ ] Line 1907: `container.innerHTML = ...` (template literal with `p` class `flex justify-center...`)
|
||||
- [ ] Line 1945: `container.innerHTML = getSidebarLoadingMarkup(copy, { showSpinner: false });`
|
||||
Reference in new issue
Block a user