Commit Graph
120 Commits
Author SHA1 Message Date
thePR0M3TH3ANandClaude Opus 4.8 80f058f67c channel: per-channel persisted cache for instant cold-load paint
A cold hard-refresh on a profile previously sat on "Loading videos…" for
~5s — the optimistic in-memory cache is empty on cold start (ingest hasn't
injected yet) and the grid waited on relay connection.

Now channelProfileVideos.js persists the last-rendered wall per author
(localStorage bitvid:channel-videos:v1) and loadUserVideos paints it
immediately on cold load, before relays connect; the live fetch then
replaces it. Bounded (60 videos/channel, 20 channels LRU-evicted) and
strips the heavy raw `tags` array. Same proven pattern as the main feed's
optimistic cache.

Closes TODO 17d per-channel cache. Tests + mutation-verified (round-trip,
tag-strip, per-channel + channel-count caps). 1267/1268 unit (known flake).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 20:23:51 -04:00
thePR0M3TH3ANandClaude Opus 4.8 1075d3f822 channel: optimistic render includes ingested NIP-71 videos
getCachedChannelVideoEvents early-returned kind-30078-only rawEvents and
skipped allEvents, so a creator's ingested NIP-71 videos didn't show in the
optimistic (pre-fetch) render. Now it merges raw 30078 (first, so they win
the downstream id-dedupe) with processed allEvents (which holds ingested
foreign videos) → the wall paints instantly on revisit / when the feed
already loaded that author. Cross-ecosystem dedupe collapses any overlap.

Also records TODO 17d (unified grid loading follow-ups): streaming
channel/search fetch, per-channel persisted cache, My Videos NIP-71
inclusion, and consolidating bespoke loaders behind one shared streaming
grid source.

1262/1263 unit (known UploadModal flake).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 20:00:36 -04:00
thePR0M3TH3ANandClaude Opus 4.8 065706a3cf videos: cross-ecosystem dedup (prefer bitvid, show one) across all grids
Phase 1 of the on-boarding plan, and the shared layer for unified grid
loading. A video that exists as both a bitvid kind-30078 note and a NIP-71
mirror/original previously could appear twice (e.g. independent dual-posts).

js/utils/videoDeduper.js: collapseCrossEcosystem() groups events by a
per-author identity (fileSha256 / originalFileSha256 / infoHash, plus an
`eid` namespace that links an on-boarded note's `importedFrom` to the
original foreign event) via union-find, and keeps the bitvid-native version
(else newest). dedupeVideos() = root-dedup THEN cross-ecosystem collapse.

Routed through the shared chokepoint app.dedupeVideosByRoot (playback
coordinator), so the feed stage, channel profile, and search all collapse
duplicates identically — "show one, prefer bitvid" everywhere. Channel
fallback path updated too.

Limitation (documented): hash-less independent dual-posts can't be matched
until the bitvid side carries on-board provenance (Phase 2).

Tests + mutation-verified (prefer-bitvid, per-author identity, infohash,
provenance link, root+cross composition). 1262/1263 unit (known flake).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 19:51:43 -04:00
thePR0M3TH3ANandClaude Opus 4.8 c404618137 docs: flag externally-managed storage for NIP-71 reference imports
Imports not produced by bitvid's storage system (reference imports / external
URLs) must be explicitly flagged externally-managed so storage tooling never
treats them as bitvid-owned: external badge (never "missing from bucket"),
excluded from orphan reconciliation, delete "file left behind" warning
suppressed, liveness unverifiable. Adds import modes (full re-host vs
reference) + Phase 2b to the plan and TODO 17c. Notes the existing
isUrlUnderBase heuristic is the baseline but a durable flag is needed.

Planning only; no code changes.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 19:30:42 -04:00
thePR0M3TH3ANandClaude Opus 4.8 0112903a6d docs: NIP-71 on-boarding + cross-ecosystem dedup dev plan
Adds docs/nip71-onboarding-plan.md and pre-launch TODO 17c for the agreed
two-way NIP-71 interop:
- Phase 1 (first): cross-ecosystem dedup — prefer the bitvid (30078) version,
  show exactly one in every grid; identity = author + import-link/hash/infohash.
- Phase 2: creator-initiated self-import (model A) — re-host to the creator's
  storage (CDN) + WebTorrent, publish a signed 30078 with an imported-from
  provenance tag. No forging others' notes; no instance auto-rehost.

Planning only; no code changes.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 19:28:15 -04:00
thePR0M3TH3ANandClaude Opus 4.8 7236496a16 nip71: show creators' NIP-71 videos on their channel-profile wall (17b)
The channel-profile grid fetched only kind-30078, so a creator's NIP-71
videos (incl. their Nostube cross-posts) appeared in the main feed via
ingest but were absent from their profile wall.

New js/channelProfileVideos.js:
- buildChannelVideoFilters(pubkey): native (kind 30078, #t=video) + NIP-71
  (kinds 21/22/34235/34236) filters for the author.
- convertChannelEvent(entry): routes NIP-71 kinds through
  buildVideoFromNip71Event (which rejects bitvid's own outbound mirrors so
  they don't duplicate the canonical note); kind-30078 uses the standard
  converter.

channelProfile.js now uses these (net fewer lines, stays under size cap).
Existing buildRenderableChannelVideos dedupe-by-root + canAccess handle
precedence and whitelist/blacklist gating, so foreign videos inherit the
same gating as native ones.

Closes pre-launch TODO 17b. Tests + mutation-verified (NIP-71 routing,
mirror skip, dual-filter build). 1253/1254 unit (known UploadModal flake).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 19:20:48 -04:00
thePR0M3TH3ANandClaude Opus 4.8 07b212943d docs(todo): scope remaining logged-in cold-start WoT fan-out
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 19:07:22 -04:00
thePR0M3TH3ANandClaude Opus 4.8 3fb3c6a07e docs(todo): mark cold-start REQ-storm + from_hex fixes done
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 18:47:52 -04:00
thePR0M3TH3ANandClaude Opus 4.8 733cb5937b nostr: sanitize hex-only filter fields (fix relay "from_hex" REQ rejects)
Strict relays (primal) reject a whole REQ with "uneven size input to
from_hex" when any ids/authors/#e/#p/#q entry isn't 64-char hex — silently
dropping that subscription's results. One malformed value anywhere in a
filter poisoned the request.

Sanitize at the universal pool choke point (normalizeFilterList, used by
both the shimmed pool.sub and pool.list): lowercase/trim and drop non-
64-hex entries from the hex-only fields; if a once-populated hex field ends
up empty, drop that filter rather than silently broadening the query.
Non-hex fields (#a/#d/#t/kinds/…) are untouched. Dev-logs what it strips
(with the filter's kinds) so the malformed source can be traced.

Also records pre-launch TODO items: NIP-71 inbound ingest is now live
(Phase 2, incl. the resolve-posted-at history-fetch fix), and a new
launch-blocker — channel-profile walls fetch only kind-30078 so a
creator's NIP-71 videos don't show on their profile.

Tests: filter-hex-sanitize (strip/keep/lowercase/drop-empty/leave-non-hex);
mutation-verified. 1244/1245 unit (known UploadModal flake).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 18:24:05 -04:00
thePR0M3TH3ANandClaude Opus 4.8 382da3085b docs(todo): hashtags polish done (publish+feed+mirror)
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 11:31:17 -04:00
thePR0M3TH3ANandClaude Opus 4.8 618525b412 docs(todo): NIP-71 mirror auto-sync done; note remaining polish
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 10:23:23 -04:00
thePR0M3TH3ANandClaude Opus 4.8 6b97626da8 docs(todo): NIP-71 mirror toggle live; note remaining polish
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 09:41:15 -04:00
thePR0M3TH3ANandClaude Opus 4.8 0c92a259c5 docs(todo): NIP-71 Phase 1 progress (1a/1b done; 1c-1e remain)
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-22 09:19:07 -04:00
thePR0M3TH3ANandClaude Opus 4.8 a004ee0b11 docs(todo): mark NIP-71 Phase 0 done
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 23:05:31 -04:00
thePR0M3TH3ANandClaude Opus 4.8 bd056b2e3b docs(nip71): interop migration plan + refresh stale vendored NIP-71 spec
Adds docs/nip71-migration-plan.md — the agreed spec to build from:
- Dual-event, opt-in (off by default): keep canonical kind 30078; add addressable
  34235/34236 mirror (d=videoRootId, edits in lockstep).
- Research correction: 34235/36 are NOT deprecated — current NIP-71 designates the
  addressable pair for content that needs post-publication updates (exactly bitvid's
  edit-in-place model).
- WebTorrent rides STANDARD NIP-94 imeta fields (magnet, i) rather than a hack;
  private videos never mirrored; HTTPS url required to mirror.
- Phases: 0 retarget builders → 1 outbound publish/edit/delete → 1.5 NIP-89 "Open in
  bitvid" handler + NIP-51 kind 30005 portable playlists → 2 inbound ingest.

Also refreshes docs/nips/71.md (was stale: only 21/22; now the current 233-line
spec with 34235/36 addressable kinds, waveform, origin, multi-audio). Updates
TODO #17 to point at the plan.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 22:40:57 -04:00
thePR0M3TH3ANandClaude Opus 4.8 234f57e009 docs(todo): mark encrypted settings sync (#15) complete
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 18:09:50 -04:00
thePR0M3TH3ANandClaude Opus 4.8 c651271af3 docs(todo): mark storage sync shipped; NWC + login-pull remain
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-21 17:18:48 -04:00
thePR0M3TH3ANandClaude Opus 4.8 25c56fad48 docs(todo): record watch-history all-relays false-failure fix
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 19:21:20 -04:00
thePR0M3TH3ANandClaude Opus 4.8 12440d2f48 docs(todo): record profile-pane no-op fix + logged-out local delete fix
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 18:53:23 -04:00
thePR0M3TH3ANandClaude Opus 4.8 5dd5451dc7 docs(todo): add live-stream (NIP-53) + short-form NIP-71 watch support
Two new content-type backlog items (research-first): watch-only Nostr live
streams from zap.stream/shosho.live (likely NIP-53 kind 30311 + 1311 chat), and
consuming external short-form/NIP-71 video notes (likely kind 22/21) from apps
like Amethyst. Flags that these are two distinct NIPs, not the same thing.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 18:11:47 -04:00
thePR0M3TH3ANandClaude Opus 4.8 882ba3303d docs(todo): add opt-in encrypted cross-login sync of storage creds + NWC
Captures the requested feature: optionally sync S3/R2 storage credentials and the
NWC zap wallet URI across logins via a self-encrypted NIP-78 (kind 30078) note,
unlocked by the signer. Includes the design path (reuse the existing envelope
encryption for storage creds; NIP-44-to-self for the NWC URI), the relay/
replaceable lessons from this session (write relays, strictly-newer created_at,
newest-per-d-tag on read, empty-publish to clear), opt-in UX, and the threat
model (public-relay blob, key-compromise trust root, NWC = spending capability,
signer decrypt budget).

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 17:58:15 -04:00
thePR0M3TH3ANandClaude Opus 4.8 df28c67496 docs(todo): mark watch-history empty-month clear fixed; all 3 gaps closed
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 17:54:27 -04:00
thePR0M3TH3ANandClaude Opus 4.8 421e50a90f docs(todo): record watch-history read-dedup fix + remaining empty-month clear
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 17:39:30 -04:00
thePR0M3TH3ANandClaude Opus 4.8 51a9b3e788 docs(todo): record My Videos follow-ups + deploy/CI infra items
Adds this session's deferred/discovered work: My Videos Restore action, info.json
upload sidecar (with privacy guard), orphan size/date metadata, confirm-modal
polish, external-URL liveness caveat; plus the on-demand deploy workflow decision
(beta?) and the env-sensitive visual-regression baseline that needs CI-side
regeneration. Marks the orphan-GC item as largely delivered by the My Videos tab,
and logs the completed My Videos / delete / watch-history / CI / Vercel work.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 17:21:21 -04:00
thePR0M3TH3ANandClaude Opus 4.8 9a48c59953 docs(todo): mark watch-history delete fix done; note write-relay confirmation
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 12:58:20 -04:00
thePR0M3TH3ANandClaude Opus 4.8 f3dff8e5b9 docs(todo): mark delete relay-scope fix done; note remaining verify steps
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 12:44:49 -04:00
thePR0M3TH3ANandClaude Opus 4.8 d513fd8874 docs(todo): add consolidated pre-launch fixes & audits backlog
Captures the remaining suggested improvements plus the user's newly reported
pre-launch items: tombstoned-videos-still-showing delete audit, broken
watch-history delete, zaps + platform-fee-split audit, generic-S3 testing, view
counter accuracy, mobile/video-card layout, card-hide liveness audit, orphan GC
tool, login REQ-storm, webtorrent null.fill crash, flaky-test hardening, and the
unstable→beta promotion. Includes a "Done this session" section for context.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-20 12:32:27 -04:00
thePR0M3TH3ANandClaude Opus 4.8 c5a91cb4d2 [docs] mark slice B part 2 (bulk incremental decrypt) complete
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 18:23:27 -04:00
thePR0M3TH3ANandClaude Opus 4.8 5db18c9bd0 [docs] record slice B findings: DMs already optimal, watch-history routed
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 12:55:41 -04:00
thePR0M3TH3ANandClaude Opus 4.8 d143883e9c docs(todo): record NIP-46 decrypt slice A done + slice B (bulk DM/history) open
Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 12:14:21 -04:00
thePR0M3TH3ANandClaude Opus 4.8 3adf1be77d fix(nip46): enforce the access-control validator on remote-signer login
connectRemoteSigner and useStoredRemoteSigner accepted but never used the
`validator` the auth provider passes (accessControl.canAccess) -- so NIP-46
logins bypassed the block/allow gate that nsec/NIP-07 logins enforce. (The
validation lived only on the unused Nip46Connector.)

Both paths now run the validator against the remote signer's resolved user
pubkey BEFORE activating the signer (via _enforceRemoteSignerValidator): the
validator throws on a blocked/non-permitted pubkey, or returning false rejects
with code remote-signer-access-denied. A stored session rejected by the
validator is forgotten so a blocked pubkey can't keep retrying.

Residual (noted in TODO): the silent startup auto-restore
(scheduleStoredRemoteSignerRestore) still reconnects without a validator.

Test: tests/nostr/nip46-prepare-handshake.test.mjs (validator throws / false /
true / absent). Full suite green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 06:44:47 -04:00
thePR0M3TH3ANandClaude Opus 4.8 fdebf05e1a feat(s3): bring generic S3 to parity with R2 (cleanup + CORS guidance)
Two gaps where generic S3 trailed Cloudflare R2:

1. Object cleanup on delete/edit didn't work for generic S3. deleteVideoStorage
   built its client via makeR2Client, which hard-forces path-style and ignores
   the connection's forcePathStyle -- so vhost-style S3 deletes were misaddressed
   and cleanup silently failed (S3 users' deleted/edited files orphaned). It is
   now provider-aware (mirrors uploadFile): R2 -> makeR2Client (path-style),
   generic S3 -> makeS3Client honoring forcePathStyle. makeS3Client is now
   injectable for testing.

2. CORS guidance on upload failure was R2-only. Extracted isLikelyCorsError +
   a generic-S3 guidance builder into js/utils/uploadErrorHints.js (re-exported
   from r2Service for back-compat); s3UploadService now appends actionable CORS
   guidance on an opaque "Failed to fetch" too.

Generic S3 is now at functional parity with R2 for upload -> publish -> cleanup.

Tests: r2-delete-video-storage (adds generic-S3 forcePathStyle routing),
s3-upload-cors-guidance (new). Full suite green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 06:13:38 -04:00
thePR0M3TH3ANandClaude Opus 4.8 7f5dcd7e50 fix(upload): attach CORS guidance to direct upload failures
A new user's top first-upload failure is a missing R2 CORS policy (browser
PUT/POST blocked) -- and object-scoped R2 tokens often cannot auto-set CORS.
The connection test already surfaces buildCorsGuidance on the opaque
"Failed to fetch", but a user who skips the test and uploads directly got a
bare "Upload failed: Failed to fetch". The upload error handler now detects the
browser CORS/network rejection (isLikelyCorsError -- Chrome "Failed to fetch",
Firefox "NetworkError", Safari "Load failed") and appends the same actionable
guidance. Updated the R2 follow-up TODO (credential audit done; CORS reviewed).

Test: tests/services/r2-cors-error-classifier.test.mjs. Full suite green.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-17 05:47:12 -04:00
thePR0M3TH3ANandClaude Opus 4.8 c2228f3f4f docs(todo): R2 system follow-up backlog
Captures remaining R2 work after the upload audit + object-cleanup increments:
credential-security review, bucket/custom-domain provisioning audit, CDN purge
integration, and follow-ups to the cleanup work (generic-S3 cleanup, all-versions
delete cleanup, edit thumbnail cleanup). Plus the Vercel production-branch parking
lot item.

Co-Authored-By: Claude Opus 4.8 <[email protected]>
2026-06-16 22:21:32 -04:00
thePR0M3TH3AN 0f89cc1524 chore(torch): migrate to new TORCH system and remove legacy agent stack 2026-02-25 12:58:46 -05:00
google-labs-jules[bot]andPR0M3TH3AN be5ad33918 audit-agent: Daily audit run
- Ran audit scripts: check-file-size, check-innerhtml, lint
- Generated artifacts/audit/2026-02-25/
- Created docs/agents/task-logs/daily/2026-02-25_..._audit-agent_completed.md

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-25 17:07:41 +00:00
thePR0M3TH3AN 4ab759c0bd Merge branch 'unstable' into agents/daily/scheduler-update-agent-2026-02-23-1075521348879577769 2026-02-25 10:35:24 -05:00
thePR0M3TH3AN 887c802436 Merge branch 'unstable' into agents/daily/test-audit-agent-2026-02-23-4813203485121112615 2026-02-25 10:34:50 -05:00
thePR0M3TH3AN faf71804f3 Merge pull request #2684 from PR0M3TH3AN/agents/daily/scheduler-update-agent-2026-02-23_15-01-13-11531375802940964250
docs(agents): sync scheduler rosters — 2026-02-23
2026-02-25 10:34:09 -05:00
thePR0M3TH3AN a169a05a29 Merge pull request #2680 from PR0M3TH3AN/agents/daily/scheduler-update-2026-02-23-6263634357757049561
docs(agents): sync scheduler rosters
2026-02-25 10:30:49 -05:00
google-labs-jules[bot]andPR0M3TH3AN 4e78b3878d Daily Agent: audit-agent
Completed audit run for 2026-02-25.

- Ran file size check (43 grandfathered files, 0 new violations).
- Ran innerHTML check (37 assignments).
- Ran lint (0 failures).
- Generated summary report.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-25 14:56:48 +00:00
google-labs-jules[bot]andPR0M3TH3AN 2374730a57 chore: execute daily audit-agent
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-24 20:05:29 +00:00
google-labs-jules[bot]andPR0M3TH3AN 53168baae0 docs: daily agent test-audit-agent execution
- Executed unit tests (passed).
- Detected flakiness in subsequent test runs (timeout).
- Performed static analysis (zero assertions, timing, console usage).
- Generated test audit report and saved to `artifacts/`.
- Updated test logs and flakiness matrix.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-24 17:11:49 +00:00
thePR0M3TH3AN 8ac7658540 Merge pull request #2691 from PR0M3TH3AN/agents/daily/scheduler-update-agent-2026-02-23-14445323072037220417
docs(agents): sync scheduler rosters — 2026-02-23
2026-02-23 22:53:15 -05:00
google-labs-jules[bot]andPR0M3TH3AN 0b9d0d6b08 docs(agents): scheduler-update-agent sync (no changes)
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-23 23:37:36 +00:00
google-labs-jules[bot]andPR0M3TH3AN 14f07d0dbc docs(agents): sync scheduler rosters — 2026-02-23
Executed scheduler-update-agent to verify daily and weekly scheduler rosters.
Inventories of `docs/agents/prompts/daily/` and `docs/agents/prompts/weekly/` matched the existing rosters in `daily-scheduler.md` and `weekly-scheduler.md`.
No updates required.
Generated logs:
- context/CONTEXT_2026-02-23_scheduler-update-agent.md
- todo/TODO_2026-02-23_scheduler-update-agent.md
- decisions/DECISIONS_2026-02-23_scheduler-update-agent.md
- test_logs/TEST_LOG_2026-02-23_scheduler-update-agent.md
- docs/agents/task-logs/daily/2026-02-23_scheduler-update-agent_completed.md

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-23 20:50:54 +00:00
google-labs-jules[bot]andPR0M3TH3AN 70888ce81b chore: execute daily test-audit-agent
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-23 20:14:04 +00:00
google-labs-jules[bot]andPR0M3TH3AN b0a4341ff2 agents: run daily test-audit-agent (2026-02-23)
- Executed test-audit-agent daily task.
- Generated audit report in docs/agents/task-logs/daily/.
- Added reusable scripts in test-audit/ for flakiness check and static analysis.
- Verified test suite (shard 1) and identified failure in hashtag-preferences.test.mjs.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-23 17:11:14 +00:00
google-labs-jules[bot]andPR0M3TH3AN dbeb91f31f docs(agents): sync scheduler rosters — 2026-02-23
Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-23 15:05:58 +00:00
google-labs-jules[bot]andPR0M3TH3AN 9666ab1d35 docs(agents): sync scheduler rosters with prompt directory
- Verified daily and weekly scheduler rosters against prompt files.
- No changes required.
- Created completion log.

Co-authored-by: PR0M3TH3AN <[email protected]>
2026-02-23 00:55:43 +00:00