Merge branch 'unstable' into area/storage-cors

This commit is contained in:
thePR0M3TH3AN committed 2026-10-20 11:23:39 -04:00
commit aacb0d147b
10 files changed
+416 -10

No files matched your search

+8 -1
View File
@@ -4,7 +4,7 @@ Last updated: 2026-10-19
## Current milestone
Work through the existing TODO backlog and fix reproducible bugs that make the client less robust or usable. Validate old reports at current HEAD before assigning them; deliver small, checked changes through local unstable.
Prepare the integrated client for owner local review/testing:finish current storage2/history6 scope,faithful actual-app/core/mobile baseline and current preview with exact evidence. Retain broader robustness/usability backlog and live gates;do not start optional work beyond this milestone. Validate old reports at HEAD and land checked changes through local unstable.
## Priorities
@@ -13,6 +13,13 @@ Work through the existing TODO backlog and fix reproducible bugs that make the c
## Rulings log (newest first)
### 2026-10-20 — Explicit local-review stopping milestone,relayed by interpreter
> "Ready for me to review and test locally" — owner, relayed by interpreter;not represented as typed in dispatch.
Finish current storage2/history6 gates/landings,faithful local actual-app/core/mobile baseline and preview refresh,then provide local-review handoff before declaring this milestone met. Do not clear optional roadmap or claim production/live Amber/cloud/peer proof. No new restricted-action authority.
### 2026-10-20 — Continuing quality objective, relayed by interpreter
> "ok try to keep them working until the project is in a good place." — owner, relayed by interpreter; not represented as typed in dispatch.
+8 -7
View File
@@ -1,9 +1,10 @@
{
"id": "playback-qa-2",
"area": "playback-qa",
"status": "open",
"title": "Capture actual-app local core-flow/mobile baseline before UI changes",
"blockedOn": null,
"addedOn": "2026-10-20",
"filedAt": "1bb3a4fc452969f060c09a286b72b8cd7ac4123e"
"id": "playback-qa-2",
"area": "playback-qa",
"status": "blocked",
"title": "Capture actual-app local core-flow/mobile baseline before UI changes",
"blockedOn": "Await explicit second browser-only grant after storage release; approved genuine mirror/frozen actual built app ready.",
"addedOn": "2026-10-20",
"filedAt": "1bb3a4fc452969f060c09a286b72b8cd7ac4123e",
"notes": "First actual source-app pass blocked360x800(15s harness timeout,CDNBuffer denied+CSS404); no UI/viewports success claim. Dispatch approved preparation/doc-only normal submission15:14:36. Copied real prepared Buffer6.0.3 mirror SHA256507a593508c51d1397a9a5818ad0b8dbf7e3ad810feaa87cabff87ff56cf3984 plus verified genuine tarballs/provenance into own read-only /tmp/bitvid-playback-qa-2-snapshot; own Buffer APIprobes4/4 exit0. Frozen dispatch actual verifieddist811files/16145338B,manifestSHA2569997b48049fd01d7c7627c009373296c9a4203683522d31bc5ee82ff98e8599b;CSS283d0464…;465runtime/buildinputsidentical. No QA build/browser/install/fetch/productchanges; not byte-identicalCDN or independentlyrebundled/metafileverified. Only exactBufferURL localfulfillment proposed next; allothernonlocalblocked;actualapp remainsBLOCKEDpending2ndgrant."
}
+216
View File
@@ -0,0 +1,216 @@
# playback-qa-2: genuine cached asset plan, not a browser pass
Read-only preparation authorized by dispatch mailbox20261020T151044; no browser/build/download performed.
Inspection HEAD: `8d7e60ebf1761cda479d18a011dc382af5704f7b` (QA2 blocker evidence commit).
Actual app/mobile outcome remains blocked; no further viewport or core-flow validation claimed.
## Found exact source packages, no install needed
`npm cache ls buffer`, `npm cache ls base64-js`, `npm cache ls ieee754` found exact tarballs in
`/home/user/.npm/_cacache`. Offline `cacache.get` using existing `/usr/share/nodejs/cacache`
read/verified cached content. Recomputed SHA512 matched each cache integrity string AND the corresponding
version's `dist.integrity` in the cached registry packument. No registry/CDN request was made.
This establishes consistency with local cached registry metadata, not new online verification.
Tar package.json confirms names/versions/main/dependencies; genuine source index.js hashes are below.
| Package | Tarball bytes | Tarball SHA256 | index.js SHA256 |
| --- | ---: | --- | --- |
|buffer@6.0.3 |23108 |`555b6f49224afcf6b2c5a9aea7cd34a7f443f395b10532bc5580022d57aa51f5` |`c25853fd31addfce188b01061fe85bfe667d5fb6c7a7bbb1c83d0ddfd8627acc` |
|base64-js@1.5.1 |4109 |`b1b7a945b52685269083425216d6597e33d97bf21699d656e92fdb3eb5210a85` |`829eadd8a1a441d25be0cb93b00e16a0d0c20fd294db95d8f2ed87e6954b7182` |
|ieee754@1.2.1 |2886 |`8ef14b9b397e339db89db97881fb714f49319d8f0eb1275901f45567b28f9dac` |`fe3e2b20c1ebb57c3b390c8f685ad1e04e6f493517fa7e432f4351bb77a1a4d0` |
Buffer6.0.3 declares base64-js^1.3.1 and ieee754^1.2.1; cached1.5.1/1.2.1 satisfy these ranges.
Neither dependency declares further runtime dependencies. Package license files must accompany scratch extraction.
No installed top-level Buffer package is required; tarballs provide genuine source without `npm install`.
No exact cached jsDelivr `+esm` response was found in the npm-cache inventory; npm source is CommonJS.
## Proposed zero-network scratch adapter, approval still required
1. Re-read exact cached tarballs via the cache inspection script below; verify all hashes/integrities before extraction.
2. Extract only safe regular files under their package prefixes into a private scratch node_modules tree
(`buffer`, `base64-js`, `ieee754`), rejecting absolute/traversal/symlink/hardlink members.
3. Create scratch entry `export { Buffer } from './node_modules/buffer/index.js';`.
4. Use existing esbuild0.27.3 only to bundle that real entry/source/dependency graph as browser ESM.
Example command, **not run during preparation**:
```sh
/home/user/Documents/GitHub/bitvid/node_modules/.bin/esbuild /tmp/bitvid-playback-qa-2-assets/entry.mjs --bundle --platform=browser --format=esm --outfile=/tmp/bitvid-playback-qa-2-assets/buffer-6.0.3.mjs
```
5. Record output SHA256 and esbuild metafile; require exactly the pinned three genuine package inputs.
Validate Buffer.from/toString/base64/float/read-write round trips against real Node Buffer before browser use.
These are adapter sanity checks, not replacements for actual app behavior.
6. With a new explicit browser grant, map **only** original import URL
`https://cdn.jsdelivr.net/npm/[email protected]/+esm` to those local reconstructed ESM bytes using request fulfillment.
Every other non-local HTTP/WebSocket request stays blocked/logged; never call route.continue for the mapped CDN.
Product files/import graph/global setup remain unchanged. No fake Buffer/toolkit or no-op module.
7. If another hard offline dependency appears, stop/report/release again. No speculative substitution or public fetching.
Fidelity: exact npm Buffer6.0.3 implementation and pinned genuine dependencies, repackaged by local esbuild;
**not byte-identical to jsDelivr's generated ESM, nor CDN availability/loader parity qualification**.
Actual app/bootstrap/UI can then be exercised with a documented cached-library transport adapter only if approved.
No claim yet that this plan makes the full app boot; the first pass stopped before subsequent dependencies ran.
## CSS: byte-verified existing output candidate
Existing dispatch build asset (read-only):
`/home/user/Documents/GitHub/bitvid-dispatch/dist/css/tailwind.generated.css`,398371 bytes,
SHA256 `283d04642d201edba1e9bd5cbc3ede8d74fbd11b50ff0cd2732d463847d2adf3`.
Dispatch HEAD read as `8abbaa77b499cbf054ed55147815fb9403f702c3`.
Compared465 input files byte-for-byte against this QA checkout: **0 different inputs**.
Compared tailwind config content globs(index/embed/components/views/js/torrent), all source CSS except generated
output,postcss config,tailwind config,package.json and package-lock.json. The sorted[path,ownSHA256,dispatchSHA256]
JSON manifest SHA256 is `58743f25fc1ff7333c2bbc5b2aa9a60b3b833428b81e772bbbf3fe3e7b1b4177`.
`git diff 7f99c045..HEAD -- css tailwind.config.cjs postcss.config.cjs index.html embed.html components views js torrent package.json package-lock.json`
was empty; dispatch's prior verified preview build at7f99c045 has identical current relevant inputs.
No inference from commit names alone: this check compared actual files on disk.
Dispatch installed versions read: postcss8.5.6,postcss-cli11.0.1,postcss-import15.1.0,tailwindcss3.4.19,
autoprefixer10.4.24; esbuild0.27.3 also available in existing main dependencies.
No build was run. After approval, copy only this genuine CSS output into scratch after re-verifying output hash
and input equality, then serve the missing `/css/tailwind.generated.css` path from scratch. Do not modify
or regenerate another area's output. Alternative: later authorized own local CSS build; not needed if approved copy.
This is output reuse, not an independent fresh-build/release qualification.
## Existing harness and remaining dependencies
`tests/e2e/helpers/bitvidTestFixture.ts` supplies relay overrides,programmatic test-only login and synthetic event
seeding; no dedicated Buffer/CDN offline mapping was found by:
`rg -n 'route\(|routeWebSocket|buffer@6|cdn.jsdelivr' tests/e2e/helpers scripts/playwright` (no matches).
Do not rewrite helpers/config. `vendor/nostr-tools.bundle.min.js` is already local(110545 bytes),
SHA256 `2b063a02d0f449d715fc3bb892364c7a859f7c2e443af15321a2bcbd561c4e02`.
`js/nostrToolsBootstrap.js` attempts this local bundle and has public fallback imports; all unmatched fallbacks
must remain blocked. No toolkit mutation or claim that later dynamic dependency loading was verified.
## Integrity records
```json
[
{
"name": "buffer",
"version": "6.0.3",
"key": "make-fetch-happen:request-cache:https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
"bytes": 23108,
"cacheIntegrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"sha256": "555b6f49224afcf6b2c5a9aea7cd34a7f443f395b10532bc5580022d57aa51f5",
"registryIntegrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
"registryMatch": true,
"file": "/tmp/bitvid-playback-qa-2-assets/buffer-6.0.3.tgz",
"package": {
"name": "buffer",
"version": "6.0.3",
"main": "index.js",
"dependencies": {
"base64-js": "^1.3.1",
"ieee754": "^1.2.1"
},
"license": "MIT"
},
"indexSha256": "c25853fd31addfce188b01061fe85bfe667d5fb6c7a7bbb1c83d0ddfd8627acc"
},
{
"name": "base64-js",
"version": "1.5.1",
"key": "make-fetch-happen:request-cache:https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
"bytes": 4109,
"cacheIntegrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"sha256": "b1b7a945b52685269083425216d6597e33d97bf21699d656e92fdb3eb5210a85",
"registryIntegrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
"registryMatch": true,
"file": "/tmp/bitvid-playback-qa-2-assets/base64-js-1.5.1.tgz",
"package": {
"name": "base64-js",
"version": "1.5.1",
"main": "index.js",
"dependencies": null,
"license": "MIT"
},
"indexSha256": "829eadd8a1a441d25be0cb93b00e16a0d0c20fd294db95d8f2ed87e6954b7182"
},
{
"name": "ieee754",
"version": "1.2.1",
"key": "make-fetch-happen:request-cache:https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
"bytes": 2886,
"cacheIntegrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"sha256": "8ef14b9b397e339db89db97881fb714f49319d8f0eb1275901f45567b28f9dac",
"registryIntegrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
"registryMatch": true,
"file": "/tmp/bitvid-playback-qa-2-assets/ieee754-1.2.1.tgz",
"package": {
"name": "ieee754",
"version": "1.2.1",
"main": "index.js",
"dependencies": null,
"license": "BSD-3-Clause"
},
"indexSha256": "fe3e2b20c1ebb57c3b390c8f685ad1e04e6f493517fa7e432f4351bb77a1a4d0"
}
]
```
## Offline cache-inspection script
Requires only existing system cacache; writes tarball copies/report to own scratch, no extraction/install/build.
```js
const cache = require('/usr/share/nodejs/cacache');
const fs=require('node:fs/promises');
const crypto=require('node:crypto');
(async()=>{
const results=[];
for(const [name,version] of [['buffer','6.0.3'],['base64-js','1.5.1'],['ieee754','1.2.1']]){
const key=`make-fetch-happen:request-cache:https://registry.npmjs.org/${name}/-/${name}-${version}.tgz`;
const r=await cache.get('/home/user/.npm/_cacache',key);
const actual='sha512-'+crypto.createHash('sha512').update(r.data).digest('base64');
if(r.integrity!==actual)throw Error('cache integrity mismatch '+name);
const file=`/tmp/bitvid-playback-qa-2-assets/${name}-${version}.tgz`;await fs.writeFile(file,r.data);
let registryIntegrity=null;
try{const p=await cache.get('/home/user/.npm/_cacache',`make-fetch-happen:request-cache:https://registry.npmjs.org/${name}`);registryIntegrity=JSON.parse(p.data).versions?.[version]?.dist?.integrity||null;}catch{}
results.push({name,version,key,bytes:r.data.length,cacheIntegrity:r.integrity,sha256:crypto.createHash('sha256').update(r.data).digest('hex'),registryIntegrity,registryMatch:registryIntegrity===actual,file});
}
await fs.writeFile('/tmp/bitvid-playback-qa-2-assets/cache.json',JSON.stringify(results,null,2));console.log(JSON.stringify(results,null,2));
})().catch(e=>{console.error(e);process.exitCode=1;});
```
Current action: retain evidence/plan, no browser/full/build while storage holds the slot. Request dispatch review
of exact local fulfillment+verified CSS reuse, then a new bounded browser grant before executing any adapter/build.
## Approved prepared mirror and frozen snapshot (latest checkpoint)
Dispatch15:14:36 mailbox approved preparation/copy of its genuine prepared mirror and verified dist, plus
docs-only normal submission. **No second browser grant yet.** This supersedes the earlier request to build
our own adapter: no esbuild/build/install was run by QA. Root's prepared bundle/provenance are copied as approved.
Own snapshot: `/tmp/bitvid-playback-qa-2-snapshot`, files chmod0444 after copy.
Dispatch-owned assets were only read; no other worktree/process was changed. No symlink assets were followed.
The exact mirror and all3 tarball SHA256 values were independently verified against the earlier cache report.
Copied root provenance states esbuild0.27.3,pins buffer6.0.3/base64-js1.5.1/ieee7541.2.1,no network/hooks.
QA did not independently reproduce that bundler output or receive an esbuild input metafile; the earlier
metafile-based proposal was not executed. Actual copied bytes are bound by the approved SHA256 below.
Independent local mirror API sanity checks: `node --input-type=module` importing copied real Buffer, exit0,4/4:
UTF8 bytes equal native Node Buffer; base64 round-trip; float64 read/write bytes equal native Buffer; subarray
shares backing memory. No app/toolkit behavior replacement was used, and these probes do not qualify app boot.
```json
{
"source": "/home/user/Documents/GitHub/bitvid-dispatch/dist",
"files": 811,
"totalBytes": 16145338,
"manifestSha256": "9997b48049fd01d7c7627c009373296c9a4203683522d31bc5ee82ff98e8599b",
"indexSha256": "13b12280ffea5529172d081ba30aab64bb6f7140145fa17af407a09fb60786b4",
"bufferPolyfillSha256": "9c6412a7c3a7bda9d19ba420a0fad122b4d0e60a3af68ceb43d8eb98b68e6bff",
"cssSha256": "283d04642d201edba1e9bd5cbc3ede8d74fbd11b50ff0cd2732d463847d2adf3",
"mirrorSha256": "507a593508c51d1397a9a5818ad0b8dbf7e3ad810feaa87cabff87ff56cf3984"
}
```
The full sorted path→SHA256 manifest remains in own scratch `dist-manifest.json`; hashed summary above is durable.
Next granted pass serves this frozen **actual built app** instead of incomplete source checkout; existing local
relay/harness is retained. Only exact public Buffer import URL is fulfilled from local approved bytes and the
mirror hit logged. Every other non-local HTTP/WebSocket stays aborted/logged. No CDN fetch/pass-through,crypto
stub,toolkit override,product import rewrite or preview3000 use. Stop/release at the next hard prerequisite.
QA2 stays BLOCKED pending resource grant/actual app result; all unrun viewport/UI checks remain unverified.
Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

+138
View File
@@ -0,0 +1,138 @@
# playback-qa-2: actual-app offline baseline blocked
Baseline HEAD: `ac99ae9a6bdbeae555a30f659b0720ae67e777e8`.
Assignment `filedAt`: `1bb3a4fc452969f060c09a286b72b8cd7ac4123e`.
`git diff 1bb3a4fc..HEAD -- js index.html config scripts/agent/simple-relay.mjs tests/e2e/helpers/bitvidTestFixture.ts`
was empty. Relevant actual app/harness behavior is unchanged; no product/CSS/test/helper/config edits.
## Plan and authority
- Use actual repository index/app modules with existing simple-relay and documented test harness relay overrides.
- One Chromium pass at360×800,390×844,1280×720; stop at the first hard offline boot blocker.
- Block/log non-local HTTP and WebSocket attempts, use only synthetic local notes/test identities if needed.
- Inspect feed/nav/Profile/Upload/required fields/overflow/focus only after successful actual app boot.
- Preserve precise failure evidence; no module substitution, public downloads, build/full suite or product edits.
Browser-only slot granted in dispatch mailbox20261020T150619, consumed before preparation.
START sent to dispatch15:08:13Z **before** browser/server launch; reservation was in `.task`.
Actual execution15:08:16.718Z→15:08:32.952Z (16.234s); no browser/gate contention observed during this pass,
no resource waiting between START and execution, no claim about unrelated host work.
## Actual result
`node /tmp/bitvid-playback-qa-2/baseline.mjs`: process exit0, **scenario blocked**, not a passing app scenario.
Chromium154.0.8037.97, fresh context, first viewport360×800. Existing app is served directly from this worktree
on127.0.0.1:31847; existing simple-relay runs on private31848/31849 using its unchanged API.
Temporary own node_modules symlink reused existing installed dependencies read-only and was removed afterward.
Service workers were disabled to keep interception deterministic; no application methods/toolkit were substituted.
`page.waitForFunction(() => typeof window.__bitvidTest__ === 'object', null, {timeout:15000})`
timed out. This is the documented fixture harness-ready bound, not a retry or relaxed assertion.
Static import chain `js/index.js:4` → `js/bufferPolyfill.js:1` requires:
```js
import { Buffer } from "https://cdn.jsdelivr.net/npm/[email protected]/+esm";
```
The network guard blocked that request. Static dependency loading cannot complete, so the app's early
`installTestHarness()` statement is never reached. Exactly1 blocked non-local HTTP attempt was observed;
0 WebSocket attempts reached the non-local guard,0 pageerror events. This is an offline boot/fixture constraint,
not a demonstrated mobile-layout product defect. Missing assets are a separate environment limitation:
`http://127.0.0.1:31847/css/tailwind.generated.css` returned404; own worktree has no generated CSS/dist,
and building is excluded from this pass. Screenshot shows unstyled static shell/search/logo, not a hydrated app.
[Captured360×800 screenshot](playback-qa-2-boot-blocker.png)
| Viewport / flow | Outcome |
| --- | --- |
|360×800 actual app boot / harness |BLOCKED:15s harness timeout |
|390×844 /1280×720 |Not run after first hard blocker |
| Feed initial hydration/local seeded cards |Unverified; no synthetic events needed/seeded |
| Home/Explore/ForYou navigation |Unverified |
| Profile/Upload open-close / required fields |Unverified |
| Card controls/touch target sizes/overflow/focus |Unverified; unstyled shell cannot qualify layout |
No real signer,peers,buckets,public media,production data or external publishing was used.
No successful non-local page requests were allowed. Actual local page bootstrap was attempted; this is not
module-harness success, full app/mobile qualification, or a Firefox/KNOWN_ISSUES hydration-flake diagnosis.
## Cleanup and routing
Own browser/context and app/relay servers closed in finally at15:08:32.952Z. Browser slot RELEASE explicitly
sent to dispatch15:08:53Z; .task updated. Preview3000 was untouched; no other processes stopped.
Blocker sent with exact trigger and evidence; waiting on dispatch to route an offline asset/harness strategy.
Do not permit public CDN traffic or substitute Buffer/app/modules and silently call this an actual-app pass.
No full/normal queue submission without dispatch's explicit slot for this new item.
## Observed browser errors
```text
Failed to load resource: the server responded with a status of 404 (Not Found)
Failed to load resource: net::ERR_BLOCKED_BY_CLIENT.Inspector
```
## Reproduction script
Create `/tmp/bitvid-playback-qa-2`; temporarily link existing installed node_modules into this worktree if absent,
then save/run this script using the granted browser-only slot. It closes its own resources on the first blocker.
Remove that own symlink after the process exits. Requires existing main checkout Playwright/dependencies;
no installing or downloading assets is part of this reproduction.
```js
import { createServer } from 'node:http';
import { readFile } from 'node:fs/promises';
import { resolve, extname } from 'node:path';
import { chromium } from '/home/user/Documents/GitHub/bitvid/node_modules/playwright/index.mjs';
import { startRelay } from '/home/user/Documents/GitHub/bitvid-playback-qa/scripts/agent/simple-relay.mjs';
const root='/home/user/Documents/GitHub/bitvid-playback-qa';
const out='/tmp/bitvid-playback-qa-2';
const {writeFile}=await import('node:fs/promises');
const result={started:new Date().toISOString(),viewports:[],blockedHttp:[],blockedWs:[],failedLocal:[],pageErrors:[],consoleErrors:[]};
const server=createServer(async(req,res)=>{
const url=new URL(req.url,'http://127.0.0.1:31847');
let path=decodeURIComponent(url.pathname);if(path==='/')path='/index.html';
const file=resolve(root,'.'+path);
if(!file.startsWith(root+'/')||path.includes('/.')||!['.html','.js','.mjs','.json','.css','.svg','.png','.jpg','.jpeg','.webp','.ico','.woff','.woff2','.ttf','.wasm','.map','.webmanifest'].includes(extname(file))){res.writeHead(404);res.end();return;}
try{const data=await readFile(file);res.setHeader('Content-Type',({'.html':'text/html','.js':'text/javascript','.mjs':'text/javascript','.json':'application/json','.css':'text/css','.svg':'image/svg+xml','.wasm':'application/wasm','.png':'image/png','.webmanifest':'application/manifest+json'})[extname(file)]||'application/octet-stream');res.end(data);}
catch{res.writeHead(404);res.end();}
});
let relay,browser;
try{
await new Promise((ok,no)=>{server.once('error',no);server.listen(31847,'127.0.0.1',ok);});
relay=startRelay(31848,{httpPort:31849});
browser=await chromium.launch({headless:true,executablePath:'/usr/bin/google-chrome',args:['--no-sandbox']});
result.browserVersion=browser.version();
const context=await browser.newContext({viewport:{width:360,height:800},serviceWorkers:'block'});
await context.route('**/*',route=>{const u=new URL(route.request().url());if(['127.0.0.1','localhost','[::1]'].includes(u.hostname))return route.continue();result.blockedHttp.push(route.request().url());return route.abort('blockedbyclient');});
await context.routeWebSocket('**/*',ws=>{const u=new URL(ws.url());if(['127.0.0.1','localhost','[::1]'].includes(u.hostname))ws.connectToServer();else{result.blockedWs.push(ws.url());ws.close();}});
await context.addInitScript(()=>{localStorage.setItem('hasSeenDisclaimer','true');localStorage.setItem('__bitvidTestMode__','1');localStorage.setItem('__bitvidTestRelays__',JSON.stringify(['ws://127.0.0.1:31848']));window.__bitvidTestRelays__=['ws://127.0.0.1:31848'];localStorage.setItem('bitvid_admin_whitelist_mode','false');});
const page=await context.newPage();
page.on('pageerror',e=>result.pageErrors.push(e.message));
page.on('console',m=>{if(m.type()==='error')result.consoleErrors.push(m.text().slice(0,700));});
page.on('response',r=>{if(r.status()>=400&&new URL(r.url()).hostname==='127.0.0.1')result.failedLocal.push({url:r.url(),status:r.status()});});
for(const viewport of [{width:360,height:800},{width:390,height:844},{width:1280,height:720}]){
await page.setViewportSize(viewport);
await page.goto('http://127.0.0.1:31847/?__test__=1&__testRelays__=ws%3A%2F%2F127.0.0.1%3A31848',{waitUntil:'domcontentloaded'});
const v={viewport,flows:{}};result.viewports.push(v);
try{
await page.waitForFunction(()=>typeof window.__bitvidTest__==='object',null,{timeout:15000});
await page.waitForFunction(async()=>{const m=await import('/js/applicationContext.js');return !!m.getApplication();},null,{timeout:15000});
await page.locator('[data-testid="video-list"]').waitFor({state:'visible',timeout:15000});
v.flows.boot='passed';
}catch(e){v.flows.boot='blocked';v.blocker=e.message.split('\n')[0];v.dom=await page.locator('body').innerText();await page.screenshot({path:root+'/docs/testing/playback-qa-2-boot-blocker.png',fullPage:true});result.firstHardBlocker=true;break;}
v.layout=await page.evaluate(()=>({clientWidth:document.documentElement.clientWidth,scrollWidth:document.documentElement.scrollWidth,focus:document.activeElement?.tagName}));
// Stop at a new blocker rather than modifying product/fixture behavior.
v.flows.remaining='actual app booted; further actions require live harness state inspection';
await page.screenshot({path:out+`/${viewport.width}.png`,fullPage:true});
}
await context.close();
} catch(e){result.runError=e.stack;process.exitCode=1;}
finally{
if(browser)await browser.close();
if(relay)await relay.close();
await new Promise(ok=>server.close(ok));
result.ended=new Date().toISOString();result.resourcesClosed=true;
await writeFile(out+'/result.json',JSON.stringify(result,null,2));
console.log(JSON.stringify({started:result.started,ended:result.ended,browserVersion:result.browserVersion,viewports:result.viewports.map(v=>({viewport:v.viewport,flows:v.flows,blocker:v.blocker})),blockedHttp:result.blockedHttp,blockedWs:result.blockedWs,failedLocal:result.failedLocal,pageErrors:result.pageErrors,runError:result.runError,resourcesClosed:result.resourcesClosed}));
}
```
+6
View File
@@ -28,3 +28,9 @@ Work through the existing TODO backlog, find and fix bugs, and make the client m
> "ok try to keep them working until the project is in a good place." — owner, relayed by interpreter; not represented as typed in dispatch.
Continue bounded robustness/usability/backlog work after the three-worker trial. Use fleet/QUALITY.md to track evidence and remaining gates. Passing units alone does not establish project readiness. Keep workers useful where scopes split safely; reduce idle staffing when useful independent work runs out. Stage reproductions/audits before product fixes, preserve normal local unstable landing and restricted-action limits. Amber/cloud/live peers/manual release qualification stays explicitly open until authorized real evidence exists.
## Explicit stopping milestone — 2026-10-20
> "Ready for me to review and test locally" — owner, relayed by interpreter.
Finish current storage-cors-2 and client-reliability-6 through unchanged full gates/durable landings;complete a faithful local actual-app/core-flow/mobile baseline sufficient to expose hard local-review blockers;refresh preview3000 from integrated unstable. Prepare exact branch/SHA/URL/start-health evidence,reviewable changes,manual flows and honest limits. Then stop new optional work for owner local review. This is not production readiness,all optional backlog completion,or authorization for real accounts/cloud/peers/spending/push/deploy/schedulers. Newly reconciled public-promised playback backlog remains explicit,not silently completed or pulled into a large feature batch.
+6
View File
@@ -112,3 +112,9 @@
- Mirroring clarification from interpreter15:03:20 agrees only matching implementations need parity;no delete method inS3UploadService means no duplicate to invent. Contract malformedsyntheticrecords robustness only,not real-user incident or note-delete-block proof;preserve owner boundary and avoid coercion/permission expansion.
- Next-scope pickups verified:storage2 method-only fix15:06:34,QA2 baseline preparation15:06:36,client6 test-only retention15:06:53. QA supervisor limited read-only harness coverage prep is compatible with this assignment;do not duplicate existing specs or treat module smoke as app proof. QA must send START before browser and RELEASE;other workersfocused only untilready/fullslotgrant.
## 2026-10-20 — Explicit local-review milestone and upstream documentation
- Owner exact stopping quote "Ready for me to review and test locally" recorded GOAL/PROGRAM/QUALITY. Finish current bounded fixes/tests/baseline,then handoff current preview/branch/SHA/flows/limits;no optional feature churn or production claim.
- Inspected upstream8d4622bb:only12lines in canonicalprelaunchTODO,local110/remote1 divergent count. New public-promised HIGH1RangeGET/2health-persistence-hostscore/4warmup andotherplayback followups absent from local source used earlier. Staticrevalidation sees HEAD remains,URL localStorage persistence alreadyexists,torrent mapcache,viewport healthmetadata/orderedmirrors/SWcaches partial;no whole-item completion or new demonstrated hardreviewblocker. Non-destructive docs merge/normalqueue next,no push.
- Storage2 full430/430exit0 andnormal1650b343 gating;QA2 genuineasset planready anddocs-only25942a15 queuedbehindit. Client6ready9afe48a5 waitsfullafterstorage+shortQA2browser. No expensive successor started.
+19 -2
View File
@@ -1,6 +1,6 @@
# Quality evidence and next milestones
Updated2026-10-20. Goal: improve robustness/usability against pre-launch TODO and KNOWN_ISSUES. This is a local qualification matrix, not a project-ready/release declaration.
Updated2026-10-20. Owner stopping milestone:"Ready for me to review and test locally"(relayed). Finish storage2/history6,faithful actual-app baseline and integrated preview/handoff;stop new optional work for review. Broader robustness backlog remains. This is a local qualification matrix,not a production-ready declaration.
| Area | Current local evidence | Next bounded work | Still unverified / release gate |
|---|---|---|---|
@@ -8,7 +8,7 @@ Updated2026-10-20. Goal: improve robustness/usability against pre-launch TODO an
| Playback/fallback/magnets | Queued torrent/URL lifecycle fixes7d20a509/89ccb907; mirror guard0bd0b1c3; independent URL18 scenarios. QA actual coordinator/service scratch4 and local Chromium/Firefox3 each, literal hash/webseed checks | Retained QA1 landed1bb3a4fc;dispatch independently4/4,normal gate429 files | Actual WebTorrent/live peers; full-app fallback; local decoded mirror/substituted torrent does not prove real torrent |
| Profile/session/history | Profile fixture hang fixedde6918ce;27 focused historical scenarios and current broad suite. History lazy-init test injects fake renderer | client-reliability-6 test-only real wiring regression after current pass/historical-noop failure, TODO2 regression gap | Amber NIP46 identity/switch/logout across refresh, real signers; KNOWN_ISSUES isolated logout UI failure |
| Storage/upload safety | CORS productd3f4c215,closure7f99c045; independent9 CORS scenarios,worker focused13/10mutants/full428/lint/build; content-addressed/cleanup safeguards documented | storage-cors-2 narrow metadata no-throw guard after2 reproduced rejects/6controls | Live bucket/IAM/provider serialization; concurrent read-modify-write has no CAS; no credentials/cloud writes tested |
| Mobile usability | No fresh local mobile flow/visual qualification from trial | playback-qa-2 actual-app local Chromium core/mobile3-viewport baseline,existing mock-relay harness,private port,no UI edits | Real-device/manual accessibility and UX; visual baselines remain CI-canonical |
| Mobile usability | No fresh local mobile flow/visual qualification from trial | QA2 first360pass BLOCKED:static genuineBufferCDN guard+missing generatedCSS,remainingflows unverified. Genuinecached pinned mirror+verified builtartifact prep ready;secondpass afterstorage2 integration,no UI edits | Real-device/manual accessibility and UX; visual baselines remain CI-canonical |
| Trustworthy validation | Unchanged normal gates and restored failing mutants; latest product gate428 files. QA retained regression429-file diagnostic+normal gate passed1bb3a4fc | Retain exact counts, ancestry, fixture boundaries, failed mutants and Known Issues classification | Full broad E2E/release/manual cross-browser checks; never weaken assertions or treat mocked boundaries as live proof |
| Preview | Preserved localhost3000,storage integrated7f99c045; build/artifact pass,HTTP200/index matches dist | Refresh after each verified product landing; QA is test-only so inspect product delta before rebuilding | Production/live-site state not touched or qualified |
@@ -21,3 +21,20 @@ Updated2026-10-20. Goal: improve robustness/usability against pre-launch TODO an
## Resource and operating limits
QA currently owns full/normal gate; other investigations may use cheap focused local checks, no expensive full suite/build/browser without dispatch slot. Separate worktrees/branches; no competing product writers or app.js edits. Keep team at dispatch+3 existing workers while useful disjoint tasks exist. Clear inherited NODE_TEST_CONTEXT for CLI launches. Use mailbox/CLI/status recovery, actual send/consume times, no raw pane bodies or unattended-wakeup claim. No push/deploy/spend/real-wallet/production-data/scheduler/credentialed external operations.
## Reconciled Oct2026 upstream playback promises
Read-only origin fetch was performed by interpreter;upstream-only8d4622bb adds12 canonical TODO lines. Dispatch merges that docs-only source non-destructively through normal local queue. These items stay OPEN;static inspection below is not a live reproduction or completion claim. High-priority1/2/4 are explicitly publicly promised in the source.
| Item | Current source/local evidence | Local-review implication |
|---|---|---|
|1 HIGH:RangeGET instead ofHEAD | urlHealthController.probeUrl still fetches HEAD;existing media confirmation fallback also present | Open compatibility report;no new hard local-review blocker demonstrated solely by static search |
|2 HIGH:persist health/per-host score | URL get/store already read/write localStorage;grid torrent health uses in-memory map;per-host score not found in inspected health modules | Partial existing implementation,not whole item done;reload/torrent/per-host promise remains |
|3 parallel hosted/P2P startup | Current service/coordinator has sequential fallback/watchdogs | Not requalified as parallel startup;do not change playback policy in this bounded milestone |
|4 HIGH:hover/viewport warmup | Viewport health probes/preload metadata exist and clean up;retained playback warming not established in inspected feed code | Do not equate probe ahead-of-scroll with fulfilling promised warmup;open |
|5 alternate copies/NIP71/Blossomhash | Retained actual service regression verifies ordered hosted mirror selection;Blossom hash cross-server behavior not qualified | Partially proven mirrors,whole promise stays open |
|6 downrank/hide unknown/timeout | Existing liveness policies present;exact default-feed behavior not revalidated here | Open;no new moderation/ranking product choice |
|7 per-video status/copy | Current coordinator has per-video error/fallback strings;banner/status refresh requirement not fully audited | Open copy/UX followup,not claimed complete |
|8 SW shell/thumbnails | Existing service-worker app/image caches present | Repeat-visit/offline production behavior not qualified;BufferCDN remains baseline prep constraint |
No demonstrated new hard local-review blocker yet from the added reports. QA actual-app second pass may reveal one;report before calling milestone ready. Include these remaining promises and real Amber/cloud/live peers/manual release gates in handoff.
+3
View File
@@ -9,6 +9,9 @@ a landing rule changes.
## 2026-10-20
- Owner stopmilestone is Ready for me to review and test locally. Finish current storage2/history6/faithful actual-app baseline+preview/handoff,then no new optional tasks before review. Reconcile upstream docs-only8d4622bb via area merge+normal queue;new playback promises stay explicit/open,do not churn current scope or declare them done from partial/static evidence. Genuine cached offline dependency mirror is testprep only,not CDN/deployed/offline production proof.
- QA1 retained regression64143f42 landed1bb3a4fc,dispatch4/4. New QA2 actual-app local core/mobile baseline has bounded browser-only slot,no UI changes/full E2E. Client6 test-only actual history wiring regression routed after current pass/historical no-op failure. Storage2 temporary ownership deleteVideoStorage-only in r2Service+new test after2 real cached-metadata rejects/6controls;upload-copy logic unchanged,s3UploadService has no deletion counterpart,prove shared provider-aware delete for R2/S3. Full slots allocated only when validated-ready after browser release.
+12
View File
@@ -2178,3 +2178,15 @@ bitvid's EXISTING NWC pipeline; keep manual URI entry as the backup/advanced pat
(PLATFORM_FEE_PERCENT=30, preimage verify, no pay_invoice auto-resend) untouched.
- [ ] Phased + flag-gated: Phase 0 flag+vendor, Phase 1 connect button, Phase 2
polish (balance/reconnect), Phase 3 optional WebLN path for Alby-extension/Hub.
## Playback reliability (from Nostr feedback, Oct 2026)
Items 1, 2 and 4 are **HIGH PRIORITY** — publicly promised in bitvid's Nostr replies.
- [ ] **HIGH PRIORITY** — 1. Probe URLs with a small Range GET (first ~1 KB) instead of HEAD; many hosts/CDNs mishandle HEAD. File: `js/ui/urlHealthController.js` (`probeUrl`).
- [ ] **HIGH PRIORITY** — 2. Persist URL and torrent health in localStorage across visits with a per-host failure score; today the 45-minute cache is lost on reload. Files: `js/state/cache.js` (`storeUrlHealth`), `js/gridHealth.js`.
- [ ] 3. Start direct URL and WebTorrent in parallel instead of waiting out the 8-second stall. File: `js/services/playbackService.js` (`registerUrlPlaybackWatchdogs`).
- [ ] **HIGH PRIORITY** — 4. Warm up videos on hover or scroll-into-view by loading metadata or a small first chunk. Files: `js/app/feedCoordinator.js` and card components.
- [ ] 5. Auto-try alternate copies: NIP-71 fallback URLs and the same Blossom sha256 on other servers. Files: `js/nostr/nip71.js`, `js/services/blossomService.js`, `js/ui/urlHealthController.js`.
- [ ] 6. Rank lower or hide videos with timeout/unknown health in default feeds. Files: `js/gridHealth.js`, `js/app/feedCoordinator.js`.
- [ ] 7. Replace the 10-60s banner with per-video status (e.g. "host slow, trying P2P…") and a clear failure message. Files: `components/disclaimer.html:84`, `js/app/playbackCoordinator.js`.
- [ ] 8. Service worker caches app shell and thumbnails (not videos) for faster repeat visits. Files: `sw.min.js` source and `_headers`.