@torrent-tv/proxy 2.87.5 → 2.87.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.claude/commands/opsx/apply.md +155 -155
- package/.claude/commands/opsx/archive.md +160 -160
- package/.claude/commands/opsx/explore.md +174 -174
- package/.claude/commands/opsx/propose.md +109 -109
- package/.claude/commands/opsx/sync.md +143 -143
- package/.claude/skills/openspec-apply-change/SKILL.md +159 -159
- package/.claude/skills/openspec-archive-change/SKILL.md +117 -117
- package/.claude/skills/openspec-explore/SKILL.md +289 -289
- package/.claude/skills/openspec-propose/SKILL.md +113 -113
- package/.claude/skills/openspec-sync-specs/SKILL.md +147 -147
- package/.dockerignore +5 -5
- package/AGENTS.md +322 -322
- package/CHANGELOG.md +8 -0
- package/Dockerfile +30 -30
- package/LICENSE +16 -16
- package/README.md +369 -369
- package/assets/calibration/NOTICE.md +100 -100
- package/assets/diagnostics/sctpstate.gdb +31 -31
- package/bin/cli.js +684 -684
- package/bin/thread-pool.js +30 -30
- package/biome.json +411 -411
- package/docs/browser-proxy-contract.md +101 -94
- package/docs/container-architecture.md +218 -218
- package/docs/download-architecture.md +261 -261
- package/docs/encode-architecture.md +729 -729
- package/docs/encode-run-state.md +96 -96
- package/docs/logs.md +97 -97
- package/docs/socks5-egress-research.md +114 -114
- package/docs/storage-architecture.md +267 -267
- package/knip.json +14 -14
- package/openspec/changes/adaptive-bitrate/design.md +92 -92
- package/openspec/changes/adaptive-bitrate/proposal.md +56 -56
- package/openspec/changes/adaptive-bitrate/specs/adaptive-bitrate/spec.md +51 -51
- package/openspec/changes/adaptive-bitrate/tasks.md +40 -40
- package/openspec/changes/binary-distribution/.openspec.yaml +2 -2
- package/openspec/changes/binary-distribution/proposal.md +53 -53
- package/openspec/changes/chunked-request-bodies/design.md +81 -81
- package/openspec/changes/chunked-request-bodies/proposal.md +53 -53
- package/openspec/changes/chunked-request-bodies/specs/chunked-request-bodies/spec.md +30 -30
- package/openspec/changes/chunked-request-bodies/tasks.md +40 -40
- package/openspec/changes/cold-start/design.md +98 -98
- package/openspec/changes/cold-start/proposal.md +62 -62
- package/openspec/changes/cold-start/specs/cold-start/spec.md +47 -47
- package/openspec/changes/cold-start/tasks.md +48 -48
- package/openspec/changes/disk-cap/.openspec.yaml +2 -2
- package/openspec/changes/disk-cap/proposal.md +37 -37
- package/openspec/changes/disk-cap/specs/disk-cap/spec.md +25 -25
- package/openspec/changes/disk-cap/tasks.md +19 -19
- package/openspec/changes/proxy-observability/.openspec.yaml +2 -2
- package/openspec/changes/proxy-observability/design.md +38 -38
- package/openspec/changes/proxy-observability/proposal.md +49 -49
- package/openspec/changes/proxy-observability/specs/observability/spec.md +33 -33
- package/openspec/changes/proxy-observability/tasks.md +21 -21
- package/openspec/changes/seek-debounce/design.md +118 -118
- package/openspec/changes/seek-debounce/proposal.md +59 -59
- package/openspec/changes/seek-debounce/specs/seek-debounce/spec.md +41 -41
- package/openspec/changes/seek-debounce/tasks.md +33 -33
- package/openspec/changes/subtitle-language/.openspec.yaml +2 -2
- package/openspec/changes/subtitle-language/proposal.md +50 -50
- package/openspec/changes/subtitle-language/specs/subtitle-language/spec.md +34 -34
- package/openspec/changes/subtitle-language/tasks.md +26 -26
- package/openspec/changes/track-selection/.openspec.yaml +2 -2
- package/openspec/changes/track-selection/design.md +47 -47
- package/openspec/changes/track-selection/proposal.md +45 -45
- package/openspec/changes/track-selection/specs/track-selection/spec.md +41 -41
- package/openspec/changes/track-selection/tasks.md +20 -20
- package/openspec/changes/transcode-quality/.openspec.yaml +2 -2
- package/openspec/changes/transcode-quality/proposal.md +51 -51
- package/openspec/changes/transcode-quality/specs/transcode-quality/spec.md +139 -139
- package/openspec/changes/transcode-quality/tasks.md +63 -63
- package/openspec/config.yaml +38 -38
- package/package.json +1 -1
- package/public/.well-known/appspecific/com.chrome.devtools.json +1 -1
- package/research/delivery-wedge-stand-ladder-2026-09-13.md +329 -329
- package/research/double-spawn-2026-09-10.md +171 -171
- package/research/handover-2026-09-13.md +209 -209
- package/research/handover-reader-claims-removal-2026-09-12.md +166 -166
- package/research/piece-withdrawn-but-still-claimed-2026-09-12.md +175 -175
- package/research/preset-benchmark-size-scaling-2026-08-22.md +55 -55
- package/research/priority-map-is-the-truth-2026-09-12.md +225 -225
- package/routes/api/client-logs/post.js +86 -86
- package/routes/api/delivery-sink/get.js +72 -72
- package/routes/api/link-probe/get.js +51 -51
- package/routes/api/playback-plan/audio-tracks/post.js +29 -0
- package/routes/api/playback-plan/post.js +53 -53
- package/routes/api/sources/files/get.js +100 -100
- package/routes/api/sources/post.js +36 -36
- package/routes/api/sources/stats/get.js +132 -132
- package/routes/api/subtitles/get.js +230 -230
- package/routes/api/transcode-sessions/fragment-far/post.js +60 -60
- package/routes/api/transcode-sessions/net-report/post.js +129 -129
- package/routes/api/transcode-sessions/post.js +160 -160
- package/routes/api/transcode-sessions/progress/get.js +27 -27
- package/routes/api/transcode-sessions/release/post.js +41 -41
- package/routes/api/transcode-sessions/seek/post.js +63 -63
- package/routes/health/get.js +13 -13
- package/routes/healthz/get.js +13 -13
- package/routes/stream/get.js +361 -361
- package/routes/transcode/audio-file/get.js +64 -64
- package/routes/transcode/audio-warm/get.js +84 -84
- package/routes/transcode/session-file/get.js +52 -52
- package/routes/transcode/variant-file/get.js +95 -95
- package/routes/transcode/variant-warm/get.js +84 -84
- package/scripts/render-run-graph.js +173 -173
- package/server.js +4 -0
- package/services/encode/CoverageMap.js +428 -428
- package/services/encode/CushionReport.js +345 -345
- package/services/encode/EncodeAdmission.js +332 -332
- package/services/encode/EncodeOrchestrator.js +1217 -1217
- package/services/encode/EncodePlan.js +1366 -1366
- package/services/encode/EncodeRun.js +776 -776
- package/services/encode/EncodeRuns.js +1229 -1229
- package/services/encode/Encoder.js +142 -142
- package/services/encode/EncoderSelection.js +38 -38
- package/services/encode/LocalObservations.js +359 -359
- package/services/encode/NvencEncoder.js +50 -50
- package/services/encode/OutputOpening.js +755 -755
- package/services/encode/OutputTimes.js +579 -579
- package/services/encode/QsvEncoder.js +58 -58
- package/services/encode/Renditions.js +2162 -2162
- package/services/encode/RunProgress.js +84 -84
- package/services/encode/SegmentDemand.js +95 -95
- package/services/encode/SoftwareEncoder.js +121 -121
- package/services/encode/V4l2m2mEncoder.js +53 -53
- package/services/encode/VaapiEncoder.js +66 -66
- package/services/encode/args.js +416 -416
- package/services/encode/available-share.js +89 -89
- package/services/encode/calibration.js +361 -361
- package/services/encode/contention.js +128 -128
- package/services/encode/decode-cost-fit.js +363 -363
- package/services/encode/encode-exit.js +114 -114
- package/services/encode/encode-run-state.js +551 -551
- package/services/encode/encoder-readings.js +45 -45
- package/services/encode/fingerprint.js +322 -322
- package/services/encode/host-load.js +174 -174
- package/services/encode/hwaccel.js +1894 -1894
- package/services/encode/index.js +9 -9
- package/services/encode/learned-median.js +90 -90
- package/services/encode/output/EncodedOutput.js +57 -57
- package/services/encode/output/Output.js +131 -131
- package/services/encode/output/OutputCatalog.js +414 -414
- package/services/encode/output/OutputSpec.js +390 -390
- package/services/encode/output/Timeline.js +308 -308
- package/services/encode/output/cut-grid.js +107 -107
- package/services/encode/output/index.js +20 -20
- package/services/encode/output/ladder.js +32 -32
- package/services/encode/output/playlists.js +284 -284
- package/services/encode/output/rates.js +125 -125
- package/services/encode/output-key-format.js +21 -21
- package/services/encode/quality/EncodeCost.js +1083 -1083
- package/services/encode/quality/HostLoad.js +525 -525
- package/services/encode/quality/HostTimings.js +249 -249
- package/services/encode/quality/OutputQualityState.js +28 -28
- package/services/encode/quality/QualityController.js +935 -935
- package/services/encode/quality/QualityOffer.js +416 -416
- package/services/encode/quality/drain-threat.js +47 -47
- package/services/encode/quality/link-budget.js +254 -254
- package/services/encode/quality/output-format.js +266 -266
- package/services/encode/quality/serving-output.js +216 -216
- package/services/encode/quality/visible-rung.js +57 -57
- package/services/encode/run-budget.js +97 -97
- package/services/encode/run-command.js +747 -747
- package/services/encode/run-costs.js +155 -155
- package/services/encode/run-inputs.js +42 -42
- package/services/encode/segment-formats/fmp4.js +437 -437
- package/services/encode/segment-formats/index.js +77 -77
- package/services/encode/segment-formats/init-compat.js +324 -324
- package/services/encode/segment-formats/mp4-boxes.js +311 -311
- package/services/encode/segment-formats/mpegts.js +134 -134
- package/services/encode/start-stop-cost.js +178 -178
- package/services/encode/throughput.js +97 -97
- package/services/encode/torrent-cost.js +88 -88
- package/services/identity/installation-id.js +38 -38
- package/services/media/ContainerOrchestrator.js +149 -149
- package/services/media/KeyframeTables.js +316 -316
- package/services/media/SourceFile.js +298 -298
- package/services/media/SubtitleCues.js +520 -520
- package/services/media/SubtitleOrchestrator.js +167 -167
- package/services/media/audio-inventory.js +245 -212
- package/services/media/container/AviContainer.js +266 -266
- package/services/media/container/Container.js +603 -603
- package/services/media/container/ContainerFactory.js +56 -56
- package/services/media/container/KeyframeTable.js +272 -272
- package/services/media/container/MatroskaContainer.js +1494 -1494
- package/services/media/container/Mp4Container.js +1244 -1244
- package/services/media/container/SubtitleFileContainer.js +322 -322
- package/services/media/container/ebml-reader.js +159 -159
- package/services/media/ffmpeg-banner.js +260 -260
- package/services/media/keyframe-probe.js +157 -157
- package/services/media/media-info-probe.js +93 -93
- package/services/media/playback-planner.js +131 -59
- package/services/media/tracks/AudioTrack.js +131 -131
- package/services/media/tracks/ContainerTrack.js +75 -75
- package/services/media/tracks/ImageSubtitleTrack.js +19 -19
- package/services/media/tracks/SubtitleTrack.js +38 -38
- package/services/media/tracks/TextSubtitleTrack.js +287 -287
- package/services/media/tracks/VideoTrack.js +33 -33
- package/services/media/tracks/index.js +15 -15
- package/services/media/tracks/language-detect.js +174 -174
- package/services/server/OutputLifecycle.js +418 -418
- package/services/server/SegmentServing.js +1146 -1146
- package/services/server/ViewerRequests.js +522 -522
- package/services/server/WaitLedger.js +142 -142
- package/services/server/controllers/PlaybackController.js +40 -36
- package/services/server/controllers/SubtitleController.js +109 -109
- package/services/server/http-responses.js +60 -60
- package/services/server/transcode-session-files.js +325 -325
- package/services/server/wire-outputs.js +983 -983
- package/services/storage/Diagnostics.js +202 -202
- package/services/storage/MachineBudget.js +235 -235
- package/services/storage/allowance.js +107 -107
- package/services/storage/core-dumps.js +106 -106
- package/services/storage/files/CompletedFiles.js +391 -391
- package/services/storage/files/piece-from-whole-file.js +118 -118
- package/services/storage/free.js +71 -71
- package/services/storage/keep.js +48 -48
- package/services/storage/machine-memory.js +56 -56
- package/services/storage/memory-report.js +575 -575
- package/services/storage/piece-store/piece-disk-store.js +516 -516
- package/services/storage/piece-store/piece-lru.js +495 -495
- package/services/storage/piece-store/shared-piece-store.js +1880 -1880
- package/services/storage/returns.js +103 -103
- package/services/storage/segment-store/SegmentStore.js +1196 -1196
- package/services/storage/wire.js +175 -175
- package/services/torrent/Contents.js +324 -324
- package/services/torrent/demand/DemandRegister.js +202 -202
- package/services/torrent/demand/Urgency.js +137 -137
- package/services/torrent/demand/Window.js +118 -118
- package/services/torrent/demand/index.js +8 -8
- package/services/torrent/demand/pieces.js +140 -140
- package/services/torrent/download/SwarmSelection.js +386 -386
- package/services/torrent/download/registry.js +102 -102
- package/services/torrent/download/withdraw-claim.js +80 -80
- package/services/torrent/files.js +455 -455
- package/services/torrent/naming.js +619 -619
- package/services/torrent/piece-store-of.js +29 -29
- package/services/torrent/supply-margin.js +262 -262
- package/services/torrent/torrent-pool.js +2 -2
- package/services/torrent/worker/background-fill.js +213 -213
- package/services/torrent/worker/channel.js +271 -271
- package/services/torrent/worker/fastest-wires.js +342 -342
- package/services/torrent/worker/handle-state.js +23 -23
- package/services/torrent/worker/held-bytes.js +155 -155
- package/services/torrent/worker/install-webrtc-shim.js +32 -32
- package/services/torrent/worker/piece-reader.js +1078 -1078
- package/services/torrent/worker/pool-adapter.js +1 -1
- package/services/torrent/worker/resume-warm.js +107 -107
- package/services/torrent/worker/webrtc-shim.js +219 -219
- package/services/transport/data-channel-handler.js +1356 -1356
- package/services/transport/delivery-probe.js +842 -842
- package/services/transport/health-collector.js +53 -53
- package/services/transport/nat-classifier.js +231 -231
- package/services/transport/packet-witness.js +808 -808
- package/services/transport/port-mapper.js +235 -235
- package/services/transport/registry-api.js +81 -81
- package/services/transport/tunnel-client.js +447 -447
- package/services/transport/usrsctp-state.js +175 -175
- package/services/transport/webrtc-manager.js +484 -484
- package/services/viewer/Assignments.js +340 -340
- package/services/viewer/PriorityMap.js +390 -390
- package/services/viewer/PriorityOrchestrator.js +325 -325
- package/services/viewer/Viewer.js +657 -657
- package/services/viewer/Viewers.js +368 -368
- package/services/viewer/active-output.js +37 -37
- package/services/viewer/audio-start.js +46 -46
- package/services/viewer/buffer-trend.js +81 -81
- package/services/viewer/choices.js +647 -647
- package/services/viewer/positions.js +126 -126
- package/services/viewer/report-intake.js +46 -46
- package/store/source-registry.js +71 -71
- package/test/asset-paths.test.js +28 -28
- package/test/audio-inventory.test.js +212 -176
- package/test/audio-track-bitrate.test.js +40 -40
- package/test/auto-quality-step.test.js +707 -707
- package/test/available-share.test.js +76 -76
- package/test/background-fill.test.js +190 -190
- package/test/client-log-file.test.js +110 -110
- package/test/completed-files.test.js +115 -115
- package/test/concurrent-cost.test.js +148 -148
- package/test/container-media-info.test.js +228 -228
- package/test/contention.test.js +76 -76
- package/test/core-dumps.test.js +57 -57
- package/test/coverage-follows-the-disk.test.js +228 -228
- package/test/coverage-map.test.js +195 -195
- package/test/cue-push-carries-what-the-walk-found.test.js +58 -58
- package/test/cut-times-timeline.test.js +65 -65
- package/test/cuts-follow-published-grid.test.js +109 -109
- package/test/data-channel-frame.test.js +63 -63
- package/test/dead-torrent-handle.test.js +52 -52
- package/test/declared-rates.test.js +116 -116
- package/test/declared-tracks.test.js +35 -35
- package/test/decode-cost-fit.test.js +202 -202
- package/test/decode-cost.test.js +462 -462
- package/test/delivery-probe.test.js +393 -393
- package/test/demand-register.test.js +206 -206
- package/test/dht-bootstrap.test.js +72 -72
- package/test/drain-threat.test.js +65 -65
- package/test/duplicate-add.test.js +48 -48
- package/test/encode-admission.test.js +146 -146
- package/test/encode-cost.test.js +283 -283
- package/test/encode-exit.test.js +111 -111
- package/test/encode-orchestrator.test.js +419 -419
- package/test/encode-plan-viewers.test.js +718 -718
- package/test/encode-plan.test.js +545 -545
- package/test/encode-run-state.test.js +314 -314
- package/test/encode-run.test.js +161 -161
- package/test/encode-slope.test.js +46 -46
- package/test/encoded-output.test.js +39 -39
- package/test/encoder-kinds.test.js +122 -122
- package/test/encoder-readings.test.js +46 -46
- package/test/every-claimant-is-told-its-share.test.js +152 -152
- package/test/failed-encoder-still-serves-what-exists.test.js +354 -354
- package/test/failed-start-breaker.test.js +202 -202
- package/test/fastest-wires.test.js +143 -143
- package/test/ffmpeg-stream-counts.test.js +78 -78
- package/test/file-edges.test.js +191 -191
- package/test/fmp4-self-contained.test.js +80 -80
- package/test/fmp4-timestamps.test.js +140 -140
- package/test/fmp4-track-completeness.test.js +41 -41
- package/test/format-keyed-outputs.test.js +78 -78
- package/test/health-metrics.test.js +38 -38
- package/test/held-request-width.test.js +157 -157
- package/test/helpers/encode-run.js +136 -136
- package/test/helpers/held-file.js +29 -29
- package/test/helpers/manager.js +57 -57
- package/test/helpers/output-spec.js +63 -63
- package/test/host-load.test.js +68 -68
- package/test/index-accuracy-is-about-the-file.test.js +128 -128
- package/test/init-compat.test.js +219 -219
- package/test/input-lost-quiets-the-plan.test.js +261 -261
- package/test/input-unavailable.test.js +48 -48
- package/test/installation-id.test.js +39 -39
- package/test/keeping-period.test.js +83 -83
- package/test/keyframe-index-accuracy.test.js +188 -188
- package/test/keyframe-table-budget.test.js +102 -102
- package/test/keyframes-belong-to-the-file.test.js +249 -249
- package/test/learned-median.test.js +37 -37
- package/test/letting-go-asks-who-is-watching.test.js +191 -191
- package/test/limit-row-by-area.test.js +60 -60
- package/test/link-budget.test.js +111 -111
- package/test/link-probe.test.js +56 -56
- package/test/local-encoding-data.test.js +273 -273
- package/test/logger-repeats.test.js +134 -134
- package/test/look-ahead-coverage.test.js +56 -56
- package/test/manager-surface.test.js +292 -292
- package/test/matroska-cues-track.test.js +192 -192
- package/test/memory-budget.test.js +390 -390
- package/test/move-cost.test.js +216 -216
- package/test/mp4-subtitles.test.js +173 -173
- package/test/one-authority.test.js +285 -285
- package/test/one-budget.test.js +149 -149
- package/test/one-output-one-session.test.js +204 -204
- package/test/one-resource-divided.test.js +185 -185
- package/test/one-serving-output-per-height.test.js +458 -458
- package/test/orchestrator-wired.test.js +206 -206
- package/test/output-catalog.test.js +39 -39
- package/test/output-shape.test.js +21 -21
- package/test/output-spec.test.js +251 -251
- package/test/output-speed.test.js +88 -88
- package/test/outputs-being-prepared.test.js +40 -40
- package/test/packet-witness-ring.test.js +236 -236
- package/test/packet-witness.test.js +148 -148
- package/test/piece-disk-store.test.js +381 -381
- package/test/piece-from-whole-file.test.js +129 -129
- package/test/piece-lru.test.js +319 -319
- package/test/piece-reader.test.js +162 -162
- package/test/piece-selection-offset.test.js +85 -85
- package/test/piece-store-eviction.test.js +560 -560
- package/test/piece-store-never-refuses.test.js +153 -153
- package/test/piece-store-reservations.test.js +318 -318
- package/test/piece-store-slow-disk.test.js +159 -159
- package/test/piece-tail.test.js +97 -97
- package/test/plan-host-timings.test.js +68 -68
- package/test/plan-is-steady.test.js +225 -225
- package/test/priority-map-download.test.js +174 -174
- package/test/priority-map-emptied.test.js +204 -204
- package/test/priority-map-per-output.test.js +215 -215
- package/test/priority-map.test.js +163 -163
- package/test/probe-wedge-certainty.test.js +60 -60
- package/test/produced-copy-choice.test.js +213 -213
- package/test/published-timeline.test.js +83 -83
- package/test/quality-offer.test.js +162 -162
- package/test/quality-variants.test.js +1229 -1229
- package/test/rate-control-in-the-output.test.js +180 -180
- package/test/read-survives-withdrawal.test.js +164 -164
- package/test/read-window.test.js +365 -365
- package/test/resume-warm.test.js +39 -39
- package/test/run-graph-drift.test.js +37 -37
- package/test/run-inputs.test.js +80 -80
- package/test/run-intervals.test.js +100 -100
- package/test/run-position-follows-published-grid.test.js +89 -89
- package/test/run-progress.test.js +65 -65
- package/test/same-height-switch.test.js +664 -664
- package/test/seek-frees-the-viewers-requests.test.js +217 -217
- package/test/seek-landing.test.js +109 -109
- package/test/seek-target-not-superseded.test.js +195 -195
- package/test/segment-closed-on-both-branches.test.js +96 -96
- package/test/segment-cut-times.test.js +63 -63
- package/test/segment-demand.test.js +80 -80
- package/test/segment-hold-supersede.test.js +91 -91
- package/test/segment-judged-by-its-own-header.test.js +221 -221
- package/test/segment-serve-wiring.test.js +475 -475
- package/test/segment-store-eviction.test.js +247 -247
- package/test/segment-store.test.js +323 -323
- package/test/segment-true-start.test.js +86 -86
- package/test/segments-are-shared.test.js +176 -176
- package/test/send-chunk-bytes.test.js +86 -86
- package/test/serving-existing-output.test.js +102 -102
- package/test/serving-output.test.js +102 -102
- package/test/shared-piece-store.test.js +310 -310
- package/test/sidecar-naming.test.js +142 -142
- package/test/source-file.test.js +133 -133
- package/test/source-files-route.test.js +103 -103
- package/test/source-registry.test.js +18 -18
- package/test/split-a-stretch.test.js +139 -139
- package/test/stale-request-after-seek.test.js +158 -158
- package/test/startup-readings.test.js +124 -124
- package/test/stream-route.test.js +182 -182
- package/test/subtitle-cue-framing.test.js +200 -200
- package/test/subtitle-cue-source.test.js +102 -102
- package/test/subtitle-cue-walk.test.js +370 -370
- package/test/subtitle-cursor.test.js +63 -63
- package/test/subtitle-defaults.test.js +118 -118
- package/test/subtitle-language.test.js +252 -252
- package/test/subtitle-track-numbering.test.js +386 -386
- package/test/supply-margin.test.js +177 -177
- package/test/swarm-follows-readers.test.js +174 -174
- package/test/swarm-reach.test.js +130 -130
- package/test/swarm-selection.test.js +220 -220
- package/test/tail-duplication.test.js +167 -167
- package/test/the-channel-has-both-ends.test.js +91 -91
- package/test/the-torrent-thread-serves-bytes.test.js +107 -107
- package/test/thread-pool.test.js +53 -53
- package/test/timeline.test.js +84 -84
- package/test/torrent-contents.test.js +235 -235
- package/test/torrent-cost.test.js +71 -71
- package/test/torrent-files.test.js +221 -221
- package/test/torrent-naming.test.js +255 -255
- package/test/tracks-begin-together.test.js +209 -209
- package/test/tunnel-renewal.test.js +167 -167
- package/test/two-viewers-one-picture.test.js +407 -407
- package/test/upload-hurry.test.js +186 -186
- package/test/usrsctp-state.test.js +131 -131
- package/test/video-facts.test.js +102 -102
- package/test/viewer-assignments.test.js +143 -143
- package/test/viewer-outputs.test.js +285 -285
- package/test/viewer-presence.test.js +116 -116
- package/test/viewer-requests-admission.test.js +89 -89
- package/test/viewer-states.test.js +189 -189
- package/test/viewer-subtitle-subscription.test.js +96 -96
- package/test/viewer.test.js +139 -139
- package/test/viewing-generations.test.js +390 -390
- package/test/visible-rung.test.js +37 -37
- package/test/wait-ledger.test.js +100 -100
- package/test/webrtc-shim.test.js +149 -149
- package/test/wedge-certainty.test.js +131 -131
- package/test/withdraw-piece-claim.test.js +212 -212
- package/test/worker-channel.test.js +158 -158
- package/utils/client-log-file.js +151 -151
- package/utils/logger.js +312 -312
- package/utils/parse-range.js +25 -25
- package/utils/perf.js +59 -59
- package/{services/torrent → utils}/torrent-source-key.js +38 -38
|
@@ -1,166 +1,166 @@
|
|
|
1
|
-
# Handover: the priority map is the only thing that says a file is wanted
|
|
2
|
-
|
|
3
|
-
Written 2026-09-12, after the instruction that reversed the work in the tree.
|
|
4
|
-
|
|
5
|
-
## The instruction, in the user's own terms
|
|
6
|
-
|
|
7
|
-
The priority map answers ONE question: how much is this stretch of this file
|
|
8
|
-
wanted. Nothing anywhere asks WHO is reading a torrent. There are no reader
|
|
9
|
-
counters. Everything built around counting readers comes out.
|
|
10
|
-
|
|
11
|
-
The map is rebuilt when viewers come and go, so it already shows the current
|
|
12
|
-
state of affairs. A second bookkeeping of the same thing is what has to go.
|
|
13
|
-
|
|
14
|
-
## What is in the working tree right now, and why it is all wrong
|
|
15
|
-
|
|
16
|
-
HEAD is `79e802a`. On top of it, UNCOMMITTED:
|
|
17
|
-
|
|
18
|
-
| file | what was done to it |
|
|
19
|
-
|---|---|
|
|
20
|
-
| `services/torrent/ReaderClaims.js` | NEW, untracked. The whole class is the mistake. |
|
|
21
|
-
| `services/torrent-pool.js` | `fileUsageByTorrent` replaced by `this.readers = new ReaderClaims()`; a listener on it calls `rejoinSwarm`, `leaveSwarm` and `#scheduleIdleRemoval`; `torrentsForUploadPolicy` changed from taking a usage map to taking an `isRead` predicate. |
|
|
22
|
-
| `services/torrent-worker/worker.js` | `warmActiveFiles` (`:842`) and `keepWholeFiles` (`:1024`) read `pool.readers.of(torrent)`. |
|
|
23
|
-
| `test/swarm-follows-readers.test.js` | the announcement test rewritten around `ReaderClaims`. |
|
|
24
|
-
| `test/upload-hurry.test.js` | rewritten around the `isRead` predicate. |
|
|
25
|
-
|
|
26
|
-
All of it counts readers. All of it comes out. Two further facts about this
|
|
27
|
-
tree, both of which the next agent needs:
|
|
28
|
-
|
|
29
|
-
1. A bulk text replacement earlier in that session DESTROYED three methods of
|
|
30
|
-
`TorrentPool` — `#scheduleIdleRemoval`, `#cancelIdleRemoval` and
|
|
31
|
-
`#forgetDeadTorrent` — which were then called but not defined. They were
|
|
32
|
-
restored BY HAND from HEAD and adapted, not diffed line by line against the
|
|
33
|
-
original. One log line was changed deliberately: the idle-timer message no
|
|
34
|
-
longer prints a reader count. **Diff the restored bodies against
|
|
35
|
-
`git show HEAD:services/torrent-pool.js` before trusting them**, or discard
|
|
36
|
-
the tree and start from HEAD.
|
|
37
|
-
2. Discarding the uncommitted changes is probably the cheapest start, since
|
|
38
|
-
every one of them is being reversed. That is a destructive action and is the
|
|
39
|
-
USER'S CALL — ask before running anything that throws work away.
|
|
40
|
-
|
|
41
|
-
## What already exists and answers the question without counting anybody
|
|
42
|
-
|
|
43
|
-
Read these before designing. Line numbers are of the working tree.
|
|
44
|
-
|
|
45
|
-
**The map is built from viewers and published.** `services/priority/PriorityOrchestrator.js`
|
|
46
|
-
builds one map per film+file, and a second per output, from where the viewers
|
|
47
|
-
are. `services/priority/PriorityMap.js` holds the scale and the words for
|
|
48
|
-
reading it — `isAtAWatchingViewer`, `isBehindEverybody`, `isNobodyComingNow`.
|
|
49
|
-
|
|
50
|
-
**The map reaches the torrent thread as a command.** `Command.PRIORITY_MAP` in
|
|
51
|
-
`services/torrent-worker/worker.js:539` calls `pool.applyPriorityMap(torrent,
|
|
52
|
-
fileIndex, zones, durationSeconds)`.
|
|
53
|
-
|
|
54
|
-
**`applyPriorityMap` (`services/torrent-pool.js:1191`) is where seconds become
|
|
55
|
-
bytes**, and it writes the result into the demand register:
|
|
56
|
-
`demandFor(torrent).register.state({ claimant, fileIndex, byteStart, byteEnd,
|
|
57
|
-
urgency })`, with the claimant named `${MAP_CLAIMANT}:${fileIndex}:${index}`
|
|
58
|
-
(`:1257`). It WITHDRAWS its own stale claimants for that file afterwards
|
|
59
|
-
(`:1266-1273`), so a map that shrinks does shrink the register. **Whether a map
|
|
60
|
-
that wants NOTHING leaves the register empty for that file is not established —
|
|
61
|
-
check it, do not assume it.**
|
|
62
|
-
|
|
63
|
-
**The register is therefore the existing statement of what is wanted.**
|
|
64
|
-
`services/demand/DemandRegister.js` offers `size`, `files()`, `windows()`,
|
|
65
|
-
`at(urgency)`, `union(fileIndex)`, `mostUrgent()`, `withdraw(claimant)`,
|
|
66
|
-
`clear()`. `services/download/registry.js` offers `demandFor(torrent)`,
|
|
67
|
-
`hasUnmetDemand(torrent)`, `forgetTorrent(torrent)`, `reconcileAll()`.
|
|
68
|
-
|
|
69
|
-
## THE TRAP — read this before writing a line
|
|
70
|
-
|
|
71
|
-
**Not every claimant in the register is a viewer, and the ones that are not are
|
|
72
|
-
exactly what a naive rule kills.**
|
|
73
|
-
|
|
74
|
-
Measured claimants other than the map:
|
|
75
|
-
|
|
76
|
-
- `services/torrent-worker/piece-reader.js:670` — a read that is STOPPED on a
|
|
77
|
-
piece right now, stated at the BLOCKED level. Only a read can say this; the
|
|
78
|
-
map deliberately never states BLOCKED (see the comment at
|
|
79
|
-
`torrent-pool.js:1204`).
|
|
80
|
-
- `services/torrent-pool.js:1147`, `:1159`, `:1162` — the background fill and
|
|
81
|
-
the tail.
|
|
82
|
-
|
|
83
|
-
And several reads exist that no viewer has yet asked for: the codec probe
|
|
84
|
-
reading the file's head and tail, the keyframe table, the subtitle cluster
|
|
85
|
-
walk, a sidecar soundtrack being fetched whole.
|
|
86
|
-
|
|
87
|
-
**This is not hypothetical.** On 2026-09-11 a rule of exactly this shape shipped
|
|
88
|
-
as proxy 2.83.1: a torrent nobody had stated anything about left its swarm. A
|
|
89
|
-
torrent that has just been added has stated nothing yet, because its edges are
|
|
90
|
-
still being read and its playback plan is still being built. Field record:
|
|
91
|
-
added 20:57:17, first peer 20:57:18, out of the swarm 20:57:21 with 741
|
|
92
|
-
connections let go, and nothing ever rejoined it — rejoining waited for a
|
|
93
|
-
reader, and the reader was waiting for the header the swarm had been fetching.
|
|
94
|
-
`peers=0 connected of 0 known (94 queued, 5 tracker(s) offered up to 683
|
|
95
|
-
seeders)` for as long as the viewer would wait. Playback never started.
|
|
96
|
-
|
|
97
|
-
So "the map wants nothing, therefore let the swarm go" is WRONG as written. The
|
|
98
|
-
honest question is whether ANYTHING in the register wants bytes of this torrent
|
|
99
|
-
— the map's zones and every other claimant together — and that question has to
|
|
100
|
-
be asked of the register, which already knows, rather than of a counter.
|
|
101
|
-
|
|
102
|
-
## What has to change, and what each site should ask instead
|
|
103
|
-
|
|
104
|
-
Each of these currently asks "who is reading". Work out, per site, what it
|
|
105
|
-
actually needs from the register.
|
|
106
|
-
|
|
107
|
-
1. **`TorrentPool.acquireFile`** (`torrent-pool.js:1770`) and its release
|
|
108
|
-
function. Callers: `routes/stream/get.js:211`,
|
|
109
|
-
`routes/api/transcode-sessions/post.js:47`,
|
|
110
|
-
`services/controllers/SubtitleController.js:54`,
|
|
111
|
-
`services/torrent-worker/worker.js:251` and `:366`,
|
|
112
|
-
`services/torrent-worker/pool-adapter.js:88`,
|
|
113
|
-
`services/torrent-worker/client.js:327`. Note it also does two things that
|
|
114
|
-
are NOT counting: it cancels a pending idle removal and stamps
|
|
115
|
-
`#lastAccess`, which the disk-cap LRU reads. Decide where those two belong
|
|
116
|
-
before deleting the method.
|
|
117
|
-
2. **Leaving and rejoining the swarm.** `leaveSwarm` and `rejoinSwarm` are
|
|
118
|
-
exported from `torrent-pool.js:465` and `:497`. Today the trigger is the
|
|
119
|
-
first claim taken and the last released. It becomes a fact of the register.
|
|
120
|
-
3. **Idle removal.** `#scheduleIdleRemoval` fires on the last reader leaving and
|
|
121
|
-
re-checks for readers when the timer fires.
|
|
122
|
-
4. **The upload policy.** `torrentsForUploadPolicy` (`torrent-pool.js:349`) sets
|
|
123
|
-
`torrent.hasActiveReader` and `torrent.hasUnmetDemand`. The second already
|
|
124
|
-
comes from the register (`hasUnmetDemand`); the first is the counter.
|
|
125
|
-
5. **`#reportStalledDownloads`** (`:1311`) and **`#adjustUploadLimit`** (`:1354`)
|
|
126
|
-
skip a torrent with no readers.
|
|
127
|
-
6. **The disk-cap LRU** (`:1411`) picks torrents with no readers.
|
|
128
|
-
7. **`#removeTorrent`** (`:1886`) prints a refcount for diagnostics.
|
|
129
|
-
8. **`warmActiveFiles`** (`worker.js:842`) walks "the files being read" to keep
|
|
130
|
-
subtitle cues current. `register.files()` says which files anything wants.
|
|
131
|
-
9. **`keepWholeFiles`** (`worker.js:1024`) refuses to write a completed file out
|
|
132
|
-
while it is being read, so that the write does not take the disk from a
|
|
133
|
-
viewer. This one genuinely needs "is anybody reading THIS file right now" and
|
|
134
|
-
is the site most likely to need a different answer from the register than a
|
|
135
|
-
plain "is it wanted".
|
|
136
|
-
|
|
137
|
-
## Rules that hold whatever the design turns out to be
|
|
138
|
-
|
|
139
|
-
- **Plan first, approval before any edit.** No exceptions, including when told
|
|
140
|
-
to get on with it.
|
|
141
|
-
- **Never add a line to `services/hls-session-manager.js`.** It is being taken
|
|
142
|
-
apart. Deletion only; `git diff --numstat` must show more removed than added.
|
|
143
|
-
- **All code, comments and documents in the repositories are English.**
|
|
144
|
-
- **Do not run the whole test suite.** Run the tests of the files changed.
|
|
145
|
-
Relevant here: `test/swarm-follows-readers.test.js`, `test/upload-hurry.test.js`,
|
|
146
|
-
`test/file-claims.test.js`, `test/background-fill.test.js`,
|
|
147
|
-
`test/priority-map-download.test.js`, `test/read-window.test.js`,
|
|
148
|
-
`test/piece-reader.test.js`, `test/dead-torrent-handle.test.js`.
|
|
149
|
-
- **A CHANGELOG entry is part of the change**, written at the version
|
|
150
|
-
`npm run patch` will produce — the current `package.json` version plus one
|
|
151
|
-
patch. Never edit the version in `package.json` by hand.
|
|
152
|
-
- **Bumping the proxy means bumping the addon**, `ha-addon/torrent_tv_proxy/config.yaml`,
|
|
153
|
-
with its own CHANGELOG entry, and the proxy is published FIRST.
|
|
154
|
-
- **Publishing is pre-authorised.** Destructive actions are not.
|
|
155
|
-
- Refer to work by what it is, never by a list number.
|
|
156
|
-
|
|
157
|
-
## State of the tree as measured, 2026-09-12
|
|
158
|
-
|
|
159
|
-
- `node --check` passes on the three touched source files.
|
|
160
|
-
- Biome is clean over `services/`, `test/` and `routes/` — 282 files.
|
|
161
|
-
- Tests of the changed files: 131 of 131 pass.
|
|
162
|
-
- Nothing has been verified in the field; the released proxy is 2.83.3 with
|
|
163
|
-
addon 0.74.0 on the host.
|
|
164
|
-
|
|
165
|
-
None of that argues for keeping the work. It is recorded so that a failure
|
|
166
|
-
after the removal is not mistaken for a failure that was already there.
|
|
1
|
+
# Handover: the priority map is the only thing that says a file is wanted
|
|
2
|
+
|
|
3
|
+
Written 2026-09-12, after the instruction that reversed the work in the tree.
|
|
4
|
+
|
|
5
|
+
## The instruction, in the user's own terms
|
|
6
|
+
|
|
7
|
+
The priority map answers ONE question: how much is this stretch of this file
|
|
8
|
+
wanted. Nothing anywhere asks WHO is reading a torrent. There are no reader
|
|
9
|
+
counters. Everything built around counting readers comes out.
|
|
10
|
+
|
|
11
|
+
The map is rebuilt when viewers come and go, so it already shows the current
|
|
12
|
+
state of affairs. A second bookkeeping of the same thing is what has to go.
|
|
13
|
+
|
|
14
|
+
## What is in the working tree right now, and why it is all wrong
|
|
15
|
+
|
|
16
|
+
HEAD is `79e802a`. On top of it, UNCOMMITTED:
|
|
17
|
+
|
|
18
|
+
| file | what was done to it |
|
|
19
|
+
|---|---|
|
|
20
|
+
| `services/torrent/ReaderClaims.js` | NEW, untracked. The whole class is the mistake. |
|
|
21
|
+
| `services/torrent-pool.js` | `fileUsageByTorrent` replaced by `this.readers = new ReaderClaims()`; a listener on it calls `rejoinSwarm`, `leaveSwarm` and `#scheduleIdleRemoval`; `torrentsForUploadPolicy` changed from taking a usage map to taking an `isRead` predicate. |
|
|
22
|
+
| `services/torrent-worker/worker.js` | `warmActiveFiles` (`:842`) and `keepWholeFiles` (`:1024`) read `pool.readers.of(torrent)`. |
|
|
23
|
+
| `test/swarm-follows-readers.test.js` | the announcement test rewritten around `ReaderClaims`. |
|
|
24
|
+
| `test/upload-hurry.test.js` | rewritten around the `isRead` predicate. |
|
|
25
|
+
|
|
26
|
+
All of it counts readers. All of it comes out. Two further facts about this
|
|
27
|
+
tree, both of which the next agent needs:
|
|
28
|
+
|
|
29
|
+
1. A bulk text replacement earlier in that session DESTROYED three methods of
|
|
30
|
+
`TorrentPool` — `#scheduleIdleRemoval`, `#cancelIdleRemoval` and
|
|
31
|
+
`#forgetDeadTorrent` — which were then called but not defined. They were
|
|
32
|
+
restored BY HAND from HEAD and adapted, not diffed line by line against the
|
|
33
|
+
original. One log line was changed deliberately: the idle-timer message no
|
|
34
|
+
longer prints a reader count. **Diff the restored bodies against
|
|
35
|
+
`git show HEAD:services/torrent-pool.js` before trusting them**, or discard
|
|
36
|
+
the tree and start from HEAD.
|
|
37
|
+
2. Discarding the uncommitted changes is probably the cheapest start, since
|
|
38
|
+
every one of them is being reversed. That is a destructive action and is the
|
|
39
|
+
USER'S CALL — ask before running anything that throws work away.
|
|
40
|
+
|
|
41
|
+
## What already exists and answers the question without counting anybody
|
|
42
|
+
|
|
43
|
+
Read these before designing. Line numbers are of the working tree.
|
|
44
|
+
|
|
45
|
+
**The map is built from viewers and published.** `services/priority/PriorityOrchestrator.js`
|
|
46
|
+
builds one map per film+file, and a second per output, from where the viewers
|
|
47
|
+
are. `services/priority/PriorityMap.js` holds the scale and the words for
|
|
48
|
+
reading it — `isAtAWatchingViewer`, `isBehindEverybody`, `isNobodyComingNow`.
|
|
49
|
+
|
|
50
|
+
**The map reaches the torrent thread as a command.** `Command.PRIORITY_MAP` in
|
|
51
|
+
`services/torrent-worker/worker.js:539` calls `pool.applyPriorityMap(torrent,
|
|
52
|
+
fileIndex, zones, durationSeconds)`.
|
|
53
|
+
|
|
54
|
+
**`applyPriorityMap` (`services/torrent-pool.js:1191`) is where seconds become
|
|
55
|
+
bytes**, and it writes the result into the demand register:
|
|
56
|
+
`demandFor(torrent).register.state({ claimant, fileIndex, byteStart, byteEnd,
|
|
57
|
+
urgency })`, with the claimant named `${MAP_CLAIMANT}:${fileIndex}:${index}`
|
|
58
|
+
(`:1257`). It WITHDRAWS its own stale claimants for that file afterwards
|
|
59
|
+
(`:1266-1273`), so a map that shrinks does shrink the register. **Whether a map
|
|
60
|
+
that wants NOTHING leaves the register empty for that file is not established —
|
|
61
|
+
check it, do not assume it.**
|
|
62
|
+
|
|
63
|
+
**The register is therefore the existing statement of what is wanted.**
|
|
64
|
+
`services/demand/DemandRegister.js` offers `size`, `files()`, `windows()`,
|
|
65
|
+
`at(urgency)`, `union(fileIndex)`, `mostUrgent()`, `withdraw(claimant)`,
|
|
66
|
+
`clear()`. `services/download/registry.js` offers `demandFor(torrent)`,
|
|
67
|
+
`hasUnmetDemand(torrent)`, `forgetTorrent(torrent)`, `reconcileAll()`.
|
|
68
|
+
|
|
69
|
+
## THE TRAP — read this before writing a line
|
|
70
|
+
|
|
71
|
+
**Not every claimant in the register is a viewer, and the ones that are not are
|
|
72
|
+
exactly what a naive rule kills.**
|
|
73
|
+
|
|
74
|
+
Measured claimants other than the map:
|
|
75
|
+
|
|
76
|
+
- `services/torrent-worker/piece-reader.js:670` — a read that is STOPPED on a
|
|
77
|
+
piece right now, stated at the BLOCKED level. Only a read can say this; the
|
|
78
|
+
map deliberately never states BLOCKED (see the comment at
|
|
79
|
+
`torrent-pool.js:1204`).
|
|
80
|
+
- `services/torrent-pool.js:1147`, `:1159`, `:1162` — the background fill and
|
|
81
|
+
the tail.
|
|
82
|
+
|
|
83
|
+
And several reads exist that no viewer has yet asked for: the codec probe
|
|
84
|
+
reading the file's head and tail, the keyframe table, the subtitle cluster
|
|
85
|
+
walk, a sidecar soundtrack being fetched whole.
|
|
86
|
+
|
|
87
|
+
**This is not hypothetical.** On 2026-09-11 a rule of exactly this shape shipped
|
|
88
|
+
as proxy 2.83.1: a torrent nobody had stated anything about left its swarm. A
|
|
89
|
+
torrent that has just been added has stated nothing yet, because its edges are
|
|
90
|
+
still being read and its playback plan is still being built. Field record:
|
|
91
|
+
added 20:57:17, first peer 20:57:18, out of the swarm 20:57:21 with 741
|
|
92
|
+
connections let go, and nothing ever rejoined it — rejoining waited for a
|
|
93
|
+
reader, and the reader was waiting for the header the swarm had been fetching.
|
|
94
|
+
`peers=0 connected of 0 known (94 queued, 5 tracker(s) offered up to 683
|
|
95
|
+
seeders)` for as long as the viewer would wait. Playback never started.
|
|
96
|
+
|
|
97
|
+
So "the map wants nothing, therefore let the swarm go" is WRONG as written. The
|
|
98
|
+
honest question is whether ANYTHING in the register wants bytes of this torrent
|
|
99
|
+
— the map's zones and every other claimant together — and that question has to
|
|
100
|
+
be asked of the register, which already knows, rather than of a counter.
|
|
101
|
+
|
|
102
|
+
## What has to change, and what each site should ask instead
|
|
103
|
+
|
|
104
|
+
Each of these currently asks "who is reading". Work out, per site, what it
|
|
105
|
+
actually needs from the register.
|
|
106
|
+
|
|
107
|
+
1. **`TorrentPool.acquireFile`** (`torrent-pool.js:1770`) and its release
|
|
108
|
+
function. Callers: `routes/stream/get.js:211`,
|
|
109
|
+
`routes/api/transcode-sessions/post.js:47`,
|
|
110
|
+
`services/controllers/SubtitleController.js:54`,
|
|
111
|
+
`services/torrent-worker/worker.js:251` and `:366`,
|
|
112
|
+
`services/torrent-worker/pool-adapter.js:88`,
|
|
113
|
+
`services/torrent-worker/client.js:327`. Note it also does two things that
|
|
114
|
+
are NOT counting: it cancels a pending idle removal and stamps
|
|
115
|
+
`#lastAccess`, which the disk-cap LRU reads. Decide where those two belong
|
|
116
|
+
before deleting the method.
|
|
117
|
+
2. **Leaving and rejoining the swarm.** `leaveSwarm` and `rejoinSwarm` are
|
|
118
|
+
exported from `torrent-pool.js:465` and `:497`. Today the trigger is the
|
|
119
|
+
first claim taken and the last released. It becomes a fact of the register.
|
|
120
|
+
3. **Idle removal.** `#scheduleIdleRemoval` fires on the last reader leaving and
|
|
121
|
+
re-checks for readers when the timer fires.
|
|
122
|
+
4. **The upload policy.** `torrentsForUploadPolicy` (`torrent-pool.js:349`) sets
|
|
123
|
+
`torrent.hasActiveReader` and `torrent.hasUnmetDemand`. The second already
|
|
124
|
+
comes from the register (`hasUnmetDemand`); the first is the counter.
|
|
125
|
+
5. **`#reportStalledDownloads`** (`:1311`) and **`#adjustUploadLimit`** (`:1354`)
|
|
126
|
+
skip a torrent with no readers.
|
|
127
|
+
6. **The disk-cap LRU** (`:1411`) picks torrents with no readers.
|
|
128
|
+
7. **`#removeTorrent`** (`:1886`) prints a refcount for diagnostics.
|
|
129
|
+
8. **`warmActiveFiles`** (`worker.js:842`) walks "the files being read" to keep
|
|
130
|
+
subtitle cues current. `register.files()` says which files anything wants.
|
|
131
|
+
9. **`keepWholeFiles`** (`worker.js:1024`) refuses to write a completed file out
|
|
132
|
+
while it is being read, so that the write does not take the disk from a
|
|
133
|
+
viewer. This one genuinely needs "is anybody reading THIS file right now" and
|
|
134
|
+
is the site most likely to need a different answer from the register than a
|
|
135
|
+
plain "is it wanted".
|
|
136
|
+
|
|
137
|
+
## Rules that hold whatever the design turns out to be
|
|
138
|
+
|
|
139
|
+
- **Plan first, approval before any edit.** No exceptions, including when told
|
|
140
|
+
to get on with it.
|
|
141
|
+
- **Never add a line to `services/hls-session-manager.js`.** It is being taken
|
|
142
|
+
apart. Deletion only; `git diff --numstat` must show more removed than added.
|
|
143
|
+
- **All code, comments and documents in the repositories are English.**
|
|
144
|
+
- **Do not run the whole test suite.** Run the tests of the files changed.
|
|
145
|
+
Relevant here: `test/swarm-follows-readers.test.js`, `test/upload-hurry.test.js`,
|
|
146
|
+
`test/file-claims.test.js`, `test/background-fill.test.js`,
|
|
147
|
+
`test/priority-map-download.test.js`, `test/read-window.test.js`,
|
|
148
|
+
`test/piece-reader.test.js`, `test/dead-torrent-handle.test.js`.
|
|
149
|
+
- **A CHANGELOG entry is part of the change**, written at the version
|
|
150
|
+
`npm run patch` will produce — the current `package.json` version plus one
|
|
151
|
+
patch. Never edit the version in `package.json` by hand.
|
|
152
|
+
- **Bumping the proxy means bumping the addon**, `ha-addon/torrent_tv_proxy/config.yaml`,
|
|
153
|
+
with its own CHANGELOG entry, and the proxy is published FIRST.
|
|
154
|
+
- **Publishing is pre-authorised.** Destructive actions are not.
|
|
155
|
+
- Refer to work by what it is, never by a list number.
|
|
156
|
+
|
|
157
|
+
## State of the tree as measured, 2026-09-12
|
|
158
|
+
|
|
159
|
+
- `node --check` passes on the three touched source files.
|
|
160
|
+
- Biome is clean over `services/`, `test/` and `routes/` — 282 files.
|
|
161
|
+
- Tests of the changed files: 131 of 131 pass.
|
|
162
|
+
- Nothing has been verified in the field; the released proxy is 2.83.3 with
|
|
163
|
+
addon 0.74.0 on the host.
|
|
164
|
+
|
|
165
|
+
None of that argues for keeping the work. It is recorded so that a failure
|
|
166
|
+
after the removal is not mistaken for a failure that was already there.
|