@torrent-tv/proxy 2.89.1 → 2.89.3
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 +6 -1
- package/CHANGELOG.md +15 -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/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/playback-start-forecast.md +42 -8
- 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 -29
- package/routes/api/playback-plan/post.js +53 -53
- package/routes/api/sources/post.js +36 -36
- package/routes/api/sources/stats/get.js +132 -132
- package/routes/api/sources/warm/post.js +217 -217
- 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 +138 -138
- package/routes/api/transcode-sessions/post.js +178 -178
- 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 +380 -380
- package/routes/transcode/audio-file/get.js +64 -64
- package/routes/transcode/audio-warm/get.js +95 -95
- 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/services/encode/CoverageMap.js +428 -428
- package/services/encode/CushionReport.js +345 -345
- package/services/encode/EncodeAdmission.js +376 -376
- package/services/encode/EncodeOrchestrator.js +1217 -1217
- package/services/encode/EncodePlan.js +1366 -1366
- package/services/encode/EncodeRun.js +813 -813
- 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/OutputTimes.js +579 -579
- package/services/encode/QsvEncoder.js +58 -58
- package/services/encode/Renditions.js +2282 -2282
- 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 +418 -418
- 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/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/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/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 +349 -349
- package/services/encode/quality/output-format.js +319 -319
- 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-costs.js +155 -155
- package/services/encode/run-inputs.js +42 -42
- package/services/encode/segment-formats/fmp4.js +476 -458
- package/services/encode/segment-formats/index.js +103 -85
- package/services/encode/segment-formats/init-compat.js +324 -324
- package/services/encode/segment-formats/mp4-boxes.js +604 -541
- 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/SourceFile.js +298 -298
- package/services/media/SubtitleOrchestrator.js +167 -167
- package/services/media/container/KeyframeTable.js +272 -272
- 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 +931 -931
- package/services/media/tracks/AudioTrack.js +143 -143
- package/services/media/tracks/ImageSubtitleTrack.js +19 -19
- package/services/media/tracks/SubtitleTrack.js +38 -38
- package/services/media/tracks/VideoTrack.js +33 -33
- package/services/media/tracks/audio-bound.js +233 -233
- 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 +1150 -1150
- package/services/server/ViewerRequests.js +790 -786
- package/services/server/WaitLedger.js +142 -142
- package/services/server/controllers/PlaybackController.js +40 -40
- 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 +1024 -1020
- 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 +539 -539
- package/services/storage/piece-store/piece-lru.js +495 -495
- package/services/storage/returns.js +103 -103
- package/services/storage/segment-store/SegmentStore.js +1255 -1255
- package/services/storage/wire.js +175 -175
- 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/worker/background-fill.js +213 -213
- package/services/torrent/worker/channel.js +271 -271
- package/services/torrent/worker/client.js +836 -836
- package/services/torrent/worker/fastest-wires.js +342 -342
- package/services/torrent/worker/handle-state.js +23 -23
- 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 +371 -371
- package/services/torrent/worker/protocol.js +184 -184
- package/services/torrent/worker/resume-warm.js +107 -107
- package/services/torrent/worker/webrtc-shim.js +219 -219
- 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/PriorityOrchestrator.js +325 -325
- package/services/viewer/Viewer.js +691 -691
- 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/media-time.js +355 -0
- package/services/{server → viewer}/playback-readiness.js +635 -516
- 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-buffer-continuity.test.js +77 -70
- package/test/audio-inventory.test.js +212 -212
- 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/data-channel-viewer-lifecycle.test.js +92 -92
- package/test/dead-torrent-handle.test.js +52 -52
- package/test/declared-rates.test.js +116 -116
- package/test/declared-tracks.test.js +43 -43
- 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 +162 -162
- 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-presentation-clock.test.js +146 -162
- 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/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/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 +112 -112
- 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/media-time.test.js +62 -0
- 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-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 +401 -401
- 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 +595 -595
- package/test/piece-store-never-refuses.test.js +153 -153
- package/test/piece-store-reservations.test.js +403 -403
- 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/playback-readiness.test.js +518 -483
- package/test/playback-start-regressions.test.js +101 -99
- 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 +1257 -1257
- 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-store-eviction.test.js +247 -247
- package/test/segment-store.test.js +352 -352
- 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 +105 -105
- 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/soundtrack-rate-bound.test.js +289 -289
- package/test/source-file.test.js +133 -133
- 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 +209 -209
- package/test/subtitle-cue-framing.test.js +200 -200
- package/test/subtitle-cue-source.test.js +102 -102
- 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/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 +504 -504
- 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/whole-file-held-read.test.js +30 -30
- 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/utils/torrent-source-key.js +38 -38
|
@@ -1,113 +1,113 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: openspec-propose
|
|
3
|
-
description: Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.
|
|
4
|
-
license: MIT
|
|
5
|
-
compatibility: Requires openspec CLI.
|
|
6
|
-
metadata:
|
|
7
|
-
author: openspec
|
|
8
|
-
version: "1.0"
|
|
9
|
-
generatedBy: "1.5.0"
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
Propose a new change - create the change and generate all artifacts in one step.
|
|
13
|
-
|
|
14
|
-
I'll create a change with artifacts:
|
|
15
|
-
- proposal.md (what & why)
|
|
16
|
-
- design.md (how)
|
|
17
|
-
- tasks.md (implementation steps)
|
|
18
|
-
|
|
19
|
-
When ready to implement, run /opsx:apply
|
|
20
|
-
|
|
21
|
-
---
|
|
22
|
-
|
|
23
|
-
**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store <id>` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`). Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root.
|
|
24
|
-
|
|
25
|
-
**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.
|
|
26
|
-
|
|
27
|
-
**Steps**
|
|
28
|
-
|
|
29
|
-
1. **If no clear input provided, ask what they want to build**
|
|
30
|
-
|
|
31
|
-
Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:
|
|
32
|
-
> "What change do you want to work on? Describe what you want to build or fix."
|
|
33
|
-
|
|
34
|
-
From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`).
|
|
35
|
-
|
|
36
|
-
**IMPORTANT**: Do NOT proceed without understanding what the user wants to build.
|
|
37
|
-
|
|
38
|
-
2. **Create the change directory**
|
|
39
|
-
```bash
|
|
40
|
-
openspec new change "<name>"
|
|
41
|
-
```
|
|
42
|
-
This creates a scaffolded change in the planning home resolved by the CLI with `.openspec.yaml`.
|
|
43
|
-
|
|
44
|
-
3. **Get the artifact build order**
|
|
45
|
-
```bash
|
|
46
|
-
openspec status --change "<name>" --json
|
|
47
|
-
```
|
|
48
|
-
Parse the JSON to get:
|
|
49
|
-
- `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`)
|
|
50
|
-
- `artifacts`: list of all artifacts with their status and dependencies
|
|
51
|
-
- `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths.
|
|
52
|
-
|
|
53
|
-
4. **Create artifacts in sequence until apply-ready**
|
|
54
|
-
|
|
55
|
-
Use the **TodoWrite tool** to track progress through the artifacts.
|
|
56
|
-
|
|
57
|
-
Loop through artifacts in dependency order (artifacts with no pending dependencies first):
|
|
58
|
-
|
|
59
|
-
a. **For each artifact that is `ready` (dependencies satisfied)**:
|
|
60
|
-
- Get instructions:
|
|
61
|
-
```bash
|
|
62
|
-
openspec instructions <artifact-id> --change "<name>" --json
|
|
63
|
-
```
|
|
64
|
-
- The instructions JSON includes:
|
|
65
|
-
- `context`: Project background (constraints for you - do NOT include in output)
|
|
66
|
-
- `rules`: Artifact-specific rules (constraints for you - do NOT include in output)
|
|
67
|
-
- `template`: The structure to use for your output file
|
|
68
|
-
- `instruction`: Schema-specific guidance for this artifact type
|
|
69
|
-
- `resolvedOutputPath`: Resolved path or pattern to write the artifact
|
|
70
|
-
- `dependencies`: Completed artifacts to read for context
|
|
71
|
-
- Read any completed dependency files for context
|
|
72
|
-
- Create the artifact file using `template` as the structure and write it to `resolvedOutputPath`
|
|
73
|
-
- Apply `context` and `rules` as constraints - but do NOT copy them into the file
|
|
74
|
-
- Show brief progress: "Created <artifact-id>"
|
|
75
|
-
|
|
76
|
-
b. **Continue until all `applyRequires` artifacts are complete**
|
|
77
|
-
- After creating each artifact, re-run `openspec status --change "<name>" --json`
|
|
78
|
-
- Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array
|
|
79
|
-
- Stop when all `applyRequires` artifacts are done
|
|
80
|
-
|
|
81
|
-
c. **If an artifact requires user input** (unclear context):
|
|
82
|
-
- Use **AskUserQuestion tool** to clarify
|
|
83
|
-
- Then continue with creation
|
|
84
|
-
|
|
85
|
-
5. **Show final status**
|
|
86
|
-
```bash
|
|
87
|
-
openspec status --change "<name>"
|
|
88
|
-
```
|
|
89
|
-
|
|
90
|
-
**Output**
|
|
91
|
-
|
|
92
|
-
After completing all artifacts, summarize:
|
|
93
|
-
- Change name and location
|
|
94
|
-
- List of artifacts created with brief descriptions
|
|
95
|
-
- What's ready: "All artifacts created! Ready for implementation."
|
|
96
|
-
- Prompt: "Run `/opsx:apply` or ask me to implement to start working on the tasks."
|
|
97
|
-
|
|
98
|
-
**Artifact Creation Guidelines**
|
|
99
|
-
|
|
100
|
-
- Follow the `instruction` field from `openspec instructions` for each artifact type
|
|
101
|
-
- The schema defines what each artifact should contain - follow it
|
|
102
|
-
- Read dependency artifacts for context before creating new ones
|
|
103
|
-
- Use `template` as the structure for your output file - fill in its sections
|
|
104
|
-
- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file
|
|
105
|
-
- Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact
|
|
106
|
-
- These guide what you write, but should never appear in the output
|
|
107
|
-
|
|
108
|
-
**Guardrails**
|
|
109
|
-
- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)
|
|
110
|
-
- Always read dependency artifacts before creating a new one
|
|
111
|
-
- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum
|
|
112
|
-
- If a change with that name already exists, ask if user wants to continue it or create a new one
|
|
113
|
-
- Verify each artifact file exists after writing before proceeding to next
|
|
1
|
+
---
|
|
2
|
+
name: openspec-propose
|
|
3
|
+
description: Propose a new change with all artifacts generated in one step. Use when the user wants to quickly describe what they want to build and get a complete proposal with design, specs, and tasks ready for implementation.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires openspec CLI.
|
|
6
|
+
metadata:
|
|
7
|
+
author: openspec
|
|
8
|
+
version: "1.0"
|
|
9
|
+
generatedBy: "1.5.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Propose a new change - create the change and generate all artifacts in one step.
|
|
13
|
+
|
|
14
|
+
I'll create a change with artifacts:
|
|
15
|
+
- proposal.md (what & why)
|
|
16
|
+
- design.md (how)
|
|
17
|
+
- tasks.md (implementation steps)
|
|
18
|
+
|
|
19
|
+
When ready to implement, run /opsx:apply
|
|
20
|
+
|
|
21
|
+
---
|
|
22
|
+
|
|
23
|
+
**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store <id>` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`). Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root.
|
|
24
|
+
|
|
25
|
+
**Input**: The user's request should include a change name (kebab-case) OR a description of what they want to build.
|
|
26
|
+
|
|
27
|
+
**Steps**
|
|
28
|
+
|
|
29
|
+
1. **If no clear input provided, ask what they want to build**
|
|
30
|
+
|
|
31
|
+
Use the **AskUserQuestion tool** (open-ended, no preset options) to ask:
|
|
32
|
+
> "What change do you want to work on? Describe what you want to build or fix."
|
|
33
|
+
|
|
34
|
+
From their description, derive a kebab-case name (e.g., "add user authentication" → `add-user-auth`).
|
|
35
|
+
|
|
36
|
+
**IMPORTANT**: Do NOT proceed without understanding what the user wants to build.
|
|
37
|
+
|
|
38
|
+
2. **Create the change directory**
|
|
39
|
+
```bash
|
|
40
|
+
openspec new change "<name>"
|
|
41
|
+
```
|
|
42
|
+
This creates a scaffolded change in the planning home resolved by the CLI with `.openspec.yaml`.
|
|
43
|
+
|
|
44
|
+
3. **Get the artifact build order**
|
|
45
|
+
```bash
|
|
46
|
+
openspec status --change "<name>" --json
|
|
47
|
+
```
|
|
48
|
+
Parse the JSON to get:
|
|
49
|
+
- `applyRequires`: array of artifact IDs needed before implementation (e.g., `["tasks"]`)
|
|
50
|
+
- `artifacts`: list of all artifacts with their status and dependencies
|
|
51
|
+
- `planningHome`, `changeRoot`, `artifactPaths`, and `actionContext`: path and scope context. Use these instead of assuming repo-local paths.
|
|
52
|
+
|
|
53
|
+
4. **Create artifacts in sequence until apply-ready**
|
|
54
|
+
|
|
55
|
+
Use the **TodoWrite tool** to track progress through the artifacts.
|
|
56
|
+
|
|
57
|
+
Loop through artifacts in dependency order (artifacts with no pending dependencies first):
|
|
58
|
+
|
|
59
|
+
a. **For each artifact that is `ready` (dependencies satisfied)**:
|
|
60
|
+
- Get instructions:
|
|
61
|
+
```bash
|
|
62
|
+
openspec instructions <artifact-id> --change "<name>" --json
|
|
63
|
+
```
|
|
64
|
+
- The instructions JSON includes:
|
|
65
|
+
- `context`: Project background (constraints for you - do NOT include in output)
|
|
66
|
+
- `rules`: Artifact-specific rules (constraints for you - do NOT include in output)
|
|
67
|
+
- `template`: The structure to use for your output file
|
|
68
|
+
- `instruction`: Schema-specific guidance for this artifact type
|
|
69
|
+
- `resolvedOutputPath`: Resolved path or pattern to write the artifact
|
|
70
|
+
- `dependencies`: Completed artifacts to read for context
|
|
71
|
+
- Read any completed dependency files for context
|
|
72
|
+
- Create the artifact file using `template` as the structure and write it to `resolvedOutputPath`
|
|
73
|
+
- Apply `context` and `rules` as constraints - but do NOT copy them into the file
|
|
74
|
+
- Show brief progress: "Created <artifact-id>"
|
|
75
|
+
|
|
76
|
+
b. **Continue until all `applyRequires` artifacts are complete**
|
|
77
|
+
- After creating each artifact, re-run `openspec status --change "<name>" --json`
|
|
78
|
+
- Check if every artifact ID in `applyRequires` has `status: "done"` in the artifacts array
|
|
79
|
+
- Stop when all `applyRequires` artifacts are done
|
|
80
|
+
|
|
81
|
+
c. **If an artifact requires user input** (unclear context):
|
|
82
|
+
- Use **AskUserQuestion tool** to clarify
|
|
83
|
+
- Then continue with creation
|
|
84
|
+
|
|
85
|
+
5. **Show final status**
|
|
86
|
+
```bash
|
|
87
|
+
openspec status --change "<name>"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
**Output**
|
|
91
|
+
|
|
92
|
+
After completing all artifacts, summarize:
|
|
93
|
+
- Change name and location
|
|
94
|
+
- List of artifacts created with brief descriptions
|
|
95
|
+
- What's ready: "All artifacts created! Ready for implementation."
|
|
96
|
+
- Prompt: "Run `/opsx:apply` or ask me to implement to start working on the tasks."
|
|
97
|
+
|
|
98
|
+
**Artifact Creation Guidelines**
|
|
99
|
+
|
|
100
|
+
- Follow the `instruction` field from `openspec instructions` for each artifact type
|
|
101
|
+
- The schema defines what each artifact should contain - follow it
|
|
102
|
+
- Read dependency artifacts for context before creating new ones
|
|
103
|
+
- Use `template` as the structure for your output file - fill in its sections
|
|
104
|
+
- **IMPORTANT**: `context` and `rules` are constraints for YOU, not content for the file
|
|
105
|
+
- Do NOT copy `<context>`, `<rules>`, `<project_context>` blocks into the artifact
|
|
106
|
+
- These guide what you write, but should never appear in the output
|
|
107
|
+
|
|
108
|
+
**Guardrails**
|
|
109
|
+
- Create ALL artifacts needed for implementation (as defined by schema's `apply.requires`)
|
|
110
|
+
- Always read dependency artifacts before creating a new one
|
|
111
|
+
- If context is critically unclear, ask the user - but prefer making reasonable decisions to keep momentum
|
|
112
|
+
- If a change with that name already exists, ask if user wants to continue it or create a new one
|
|
113
|
+
- Verify each artifact file exists after writing before proceeding to next
|
|
@@ -1,147 +1,147 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: openspec-sync-specs
|
|
3
|
-
description: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.
|
|
4
|
-
license: MIT
|
|
5
|
-
compatibility: Requires openspec CLI.
|
|
6
|
-
metadata:
|
|
7
|
-
author: openspec
|
|
8
|
-
version: "1.0"
|
|
9
|
-
generatedBy: "1.5.0"
|
|
10
|
-
---
|
|
11
|
-
|
|
12
|
-
Sync delta specs from a change to main specs.
|
|
13
|
-
|
|
14
|
-
This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement).
|
|
15
|
-
|
|
16
|
-
**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store <id>` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`). Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root.
|
|
17
|
-
|
|
18
|
-
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
19
|
-
|
|
20
|
-
**Steps**
|
|
21
|
-
|
|
22
|
-
1. **If no change name provided, prompt for selection**
|
|
23
|
-
|
|
24
|
-
Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.
|
|
25
|
-
|
|
26
|
-
Show changes that have delta specs (under `specs/` directory).
|
|
27
|
-
|
|
28
|
-
**IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
|
|
29
|
-
|
|
30
|
-
2. **Resolve change context**
|
|
31
|
-
|
|
32
|
-
Run:
|
|
33
|
-
```bash
|
|
34
|
-
openspec status --change "<name>" --json
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
3. **Find delta specs**
|
|
38
|
-
|
|
39
|
-
Use `artifactPaths.specs.existingOutputPaths` from the status JSON as the list of delta spec files.
|
|
40
|
-
|
|
41
|
-
Each delta spec file contains sections like:
|
|
42
|
-
- `## ADDED Requirements` - New requirements to add
|
|
43
|
-
- `## MODIFIED Requirements` - Changes to existing requirements
|
|
44
|
-
- `## REMOVED Requirements` - Requirements to remove
|
|
45
|
-
- `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format)
|
|
46
|
-
|
|
47
|
-
If no delta specs found, inform user and stop.
|
|
48
|
-
|
|
49
|
-
4. **For each delta spec, apply changes to main specs**
|
|
50
|
-
|
|
51
|
-
For each repo-local capability delta spec path returned by the CLI:
|
|
52
|
-
|
|
53
|
-
a. **Read the delta spec** to understand the intended changes
|
|
54
|
-
|
|
55
|
-
b. **Read the main spec** at `openspec/specs/<capability>/spec.md` (may not exist yet)
|
|
56
|
-
|
|
57
|
-
c. **Apply changes intelligently**:
|
|
58
|
-
|
|
59
|
-
**ADDED Requirements:**
|
|
60
|
-
- If requirement doesn't exist in main spec → add it
|
|
61
|
-
- If requirement already exists → update it to match (treat as implicit MODIFIED)
|
|
62
|
-
|
|
63
|
-
**MODIFIED Requirements:**
|
|
64
|
-
- Find the requirement in main spec
|
|
65
|
-
- Apply the changes - this can be:
|
|
66
|
-
- Adding new scenarios (don't need to copy existing ones)
|
|
67
|
-
- Modifying existing scenarios
|
|
68
|
-
- Changing the requirement description
|
|
69
|
-
- Preserve scenarios/content not mentioned in the delta
|
|
70
|
-
|
|
71
|
-
**REMOVED Requirements:**
|
|
72
|
-
- Remove the entire requirement block from main spec
|
|
73
|
-
|
|
74
|
-
**RENAMED Requirements:**
|
|
75
|
-
- Find the FROM requirement, rename to TO
|
|
76
|
-
|
|
77
|
-
d. **Create new main spec** if capability doesn't exist yet:
|
|
78
|
-
- Create `openspec/specs/<capability>/spec.md`
|
|
79
|
-
- Add Purpose section (can be brief, mark as TBD)
|
|
80
|
-
- Add Requirements section with the ADDED requirements
|
|
81
|
-
|
|
82
|
-
5. **Show summary**
|
|
83
|
-
|
|
84
|
-
After applying all changes, summarize:
|
|
85
|
-
- Which capabilities were updated
|
|
86
|
-
- What changes were made (requirements added/modified/removed/renamed)
|
|
87
|
-
|
|
88
|
-
**Delta Spec Format Reference**
|
|
89
|
-
|
|
90
|
-
```markdown
|
|
91
|
-
## ADDED Requirements
|
|
92
|
-
|
|
93
|
-
### Requirement: New Feature
|
|
94
|
-
The system SHALL do something new.
|
|
95
|
-
|
|
96
|
-
#### Scenario: Basic case
|
|
97
|
-
- **WHEN** user does X
|
|
98
|
-
- **THEN** system does Y
|
|
99
|
-
|
|
100
|
-
## MODIFIED Requirements
|
|
101
|
-
|
|
102
|
-
### Requirement: Existing Feature
|
|
103
|
-
#### Scenario: New scenario to add
|
|
104
|
-
- **WHEN** user does A
|
|
105
|
-
- **THEN** system does B
|
|
106
|
-
|
|
107
|
-
## REMOVED Requirements
|
|
108
|
-
|
|
109
|
-
### Requirement: Deprecated Feature
|
|
110
|
-
|
|
111
|
-
## RENAMED Requirements
|
|
112
|
-
|
|
113
|
-
- FROM: `### Requirement: Old Name`
|
|
114
|
-
- TO: `### Requirement: New Name`
|
|
115
|
-
```
|
|
116
|
-
|
|
117
|
-
**Key Principle: Intelligent Merging**
|
|
118
|
-
|
|
119
|
-
Unlike programmatic merging, you can apply **partial updates**:
|
|
120
|
-
- To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios
|
|
121
|
-
- The delta represents *intent*, not a wholesale replacement
|
|
122
|
-
- Use your judgment to merge changes sensibly
|
|
123
|
-
|
|
124
|
-
**Output On Success**
|
|
125
|
-
|
|
126
|
-
```
|
|
127
|
-
## Specs Synced: <change-name>
|
|
128
|
-
|
|
129
|
-
Updated main specs:
|
|
130
|
-
|
|
131
|
-
**<capability-1>**:
|
|
132
|
-
- Added requirement: "New Feature"
|
|
133
|
-
- Modified requirement: "Existing Feature" (added 1 scenario)
|
|
134
|
-
|
|
135
|
-
**<capability-2>**:
|
|
136
|
-
- Created new spec file
|
|
137
|
-
- Added requirement: "Another Feature"
|
|
138
|
-
|
|
139
|
-
Main specs are now updated. The change remains active - archive when implementation is complete.
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
**Guardrails**
|
|
143
|
-
- Read both delta and main specs before making changes
|
|
144
|
-
- Preserve existing content not mentioned in delta
|
|
145
|
-
- If something is unclear, ask for clarification
|
|
146
|
-
- Show what you're changing as you go
|
|
147
|
-
- The operation should be idempotent - running twice should give same result
|
|
1
|
+
---
|
|
2
|
+
name: openspec-sync-specs
|
|
3
|
+
description: Sync delta specs from a change to main specs. Use when the user wants to update main specs with changes from a delta spec, without archiving the change.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Requires openspec CLI.
|
|
6
|
+
metadata:
|
|
7
|
+
author: openspec
|
|
8
|
+
version: "1.0"
|
|
9
|
+
generatedBy: "1.5.0"
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
Sync delta specs from a change to main specs.
|
|
13
|
+
|
|
14
|
+
This is an **agent-driven** operation - you will read delta specs and directly edit main specs to apply the changes. This allows intelligent merging (e.g., adding a scenario without copying the entire requirement).
|
|
15
|
+
|
|
16
|
+
**Store selection:** If the user names a store (a store is a standalone OpenSpec repo registered on this machine) or the work lives in one, run `openspec store list --json` to discover registered store ids, then pass `--store <id>` on the commands that read or write specs and changes (`new change`, `status`, `instructions`, `list`, `show`, `validate`, `archive`, `doctor`, `context`). Other commands do not take the flag. Hints printed by commands already carry the flag; keep it on follow-ups. Without a store, commands act on the nearest local `openspec/` root.
|
|
17
|
+
|
|
18
|
+
**Input**: Optionally specify a change name. If omitted, check if it can be inferred from conversation context. If vague or ambiguous you MUST prompt for available changes.
|
|
19
|
+
|
|
20
|
+
**Steps**
|
|
21
|
+
|
|
22
|
+
1. **If no change name provided, prompt for selection**
|
|
23
|
+
|
|
24
|
+
Run `openspec list --json` to get available changes. Use the **AskUserQuestion tool** to let the user select.
|
|
25
|
+
|
|
26
|
+
Show changes that have delta specs (under `specs/` directory).
|
|
27
|
+
|
|
28
|
+
**IMPORTANT**: Do NOT guess or auto-select a change. Always let the user choose.
|
|
29
|
+
|
|
30
|
+
2. **Resolve change context**
|
|
31
|
+
|
|
32
|
+
Run:
|
|
33
|
+
```bash
|
|
34
|
+
openspec status --change "<name>" --json
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
3. **Find delta specs**
|
|
38
|
+
|
|
39
|
+
Use `artifactPaths.specs.existingOutputPaths` from the status JSON as the list of delta spec files.
|
|
40
|
+
|
|
41
|
+
Each delta spec file contains sections like:
|
|
42
|
+
- `## ADDED Requirements` - New requirements to add
|
|
43
|
+
- `## MODIFIED Requirements` - Changes to existing requirements
|
|
44
|
+
- `## REMOVED Requirements` - Requirements to remove
|
|
45
|
+
- `## RENAMED Requirements` - Requirements to rename (FROM:/TO: format)
|
|
46
|
+
|
|
47
|
+
If no delta specs found, inform user and stop.
|
|
48
|
+
|
|
49
|
+
4. **For each delta spec, apply changes to main specs**
|
|
50
|
+
|
|
51
|
+
For each repo-local capability delta spec path returned by the CLI:
|
|
52
|
+
|
|
53
|
+
a. **Read the delta spec** to understand the intended changes
|
|
54
|
+
|
|
55
|
+
b. **Read the main spec** at `openspec/specs/<capability>/spec.md` (may not exist yet)
|
|
56
|
+
|
|
57
|
+
c. **Apply changes intelligently**:
|
|
58
|
+
|
|
59
|
+
**ADDED Requirements:**
|
|
60
|
+
- If requirement doesn't exist in main spec → add it
|
|
61
|
+
- If requirement already exists → update it to match (treat as implicit MODIFIED)
|
|
62
|
+
|
|
63
|
+
**MODIFIED Requirements:**
|
|
64
|
+
- Find the requirement in main spec
|
|
65
|
+
- Apply the changes - this can be:
|
|
66
|
+
- Adding new scenarios (don't need to copy existing ones)
|
|
67
|
+
- Modifying existing scenarios
|
|
68
|
+
- Changing the requirement description
|
|
69
|
+
- Preserve scenarios/content not mentioned in the delta
|
|
70
|
+
|
|
71
|
+
**REMOVED Requirements:**
|
|
72
|
+
- Remove the entire requirement block from main spec
|
|
73
|
+
|
|
74
|
+
**RENAMED Requirements:**
|
|
75
|
+
- Find the FROM requirement, rename to TO
|
|
76
|
+
|
|
77
|
+
d. **Create new main spec** if capability doesn't exist yet:
|
|
78
|
+
- Create `openspec/specs/<capability>/spec.md`
|
|
79
|
+
- Add Purpose section (can be brief, mark as TBD)
|
|
80
|
+
- Add Requirements section with the ADDED requirements
|
|
81
|
+
|
|
82
|
+
5. **Show summary**
|
|
83
|
+
|
|
84
|
+
After applying all changes, summarize:
|
|
85
|
+
- Which capabilities were updated
|
|
86
|
+
- What changes were made (requirements added/modified/removed/renamed)
|
|
87
|
+
|
|
88
|
+
**Delta Spec Format Reference**
|
|
89
|
+
|
|
90
|
+
```markdown
|
|
91
|
+
## ADDED Requirements
|
|
92
|
+
|
|
93
|
+
### Requirement: New Feature
|
|
94
|
+
The system SHALL do something new.
|
|
95
|
+
|
|
96
|
+
#### Scenario: Basic case
|
|
97
|
+
- **WHEN** user does X
|
|
98
|
+
- **THEN** system does Y
|
|
99
|
+
|
|
100
|
+
## MODIFIED Requirements
|
|
101
|
+
|
|
102
|
+
### Requirement: Existing Feature
|
|
103
|
+
#### Scenario: New scenario to add
|
|
104
|
+
- **WHEN** user does A
|
|
105
|
+
- **THEN** system does B
|
|
106
|
+
|
|
107
|
+
## REMOVED Requirements
|
|
108
|
+
|
|
109
|
+
### Requirement: Deprecated Feature
|
|
110
|
+
|
|
111
|
+
## RENAMED Requirements
|
|
112
|
+
|
|
113
|
+
- FROM: `### Requirement: Old Name`
|
|
114
|
+
- TO: `### Requirement: New Name`
|
|
115
|
+
```
|
|
116
|
+
|
|
117
|
+
**Key Principle: Intelligent Merging**
|
|
118
|
+
|
|
119
|
+
Unlike programmatic merging, you can apply **partial updates**:
|
|
120
|
+
- To add a scenario, just include that scenario under MODIFIED - don't copy existing scenarios
|
|
121
|
+
- The delta represents *intent*, not a wholesale replacement
|
|
122
|
+
- Use your judgment to merge changes sensibly
|
|
123
|
+
|
|
124
|
+
**Output On Success**
|
|
125
|
+
|
|
126
|
+
```
|
|
127
|
+
## Specs Synced: <change-name>
|
|
128
|
+
|
|
129
|
+
Updated main specs:
|
|
130
|
+
|
|
131
|
+
**<capability-1>**:
|
|
132
|
+
- Added requirement: "New Feature"
|
|
133
|
+
- Modified requirement: "Existing Feature" (added 1 scenario)
|
|
134
|
+
|
|
135
|
+
**<capability-2>**:
|
|
136
|
+
- Created new spec file
|
|
137
|
+
- Added requirement: "Another Feature"
|
|
138
|
+
|
|
139
|
+
Main specs are now updated. The change remains active - archive when implementation is complete.
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
**Guardrails**
|
|
143
|
+
- Read both delta and main specs before making changes
|
|
144
|
+
- Preserve existing content not mentioned in delta
|
|
145
|
+
- If something is unclear, ask for clarification
|
|
146
|
+
- Show what you're changing as you go
|
|
147
|
+
- The operation should be idempotent - running twice should give same result
|
package/.dockerignore
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
node_modules
|
|
2
|
-
npm-debug.log
|
|
3
|
-
.DS_Store
|
|
4
|
-
.git
|
|
5
|
-
.gitignore
|
|
1
|
+
node_modules
|
|
2
|
+
npm-debug.log
|
|
3
|
+
.DS_Store
|
|
4
|
+
.git
|
|
5
|
+
.gitignore
|
package/AGENTS.md
CHANGED
|
@@ -229,7 +229,12 @@ are recorded in `docs/browser-proxy-contract.md`.
|
|
|
229
229
|
- `viewer/`: every viewer has a name (`Viewers.of` refuses an empty one); the
|
|
230
230
|
relation to outputs is stored only in `Viewer.outputs` and read the other way
|
|
231
231
|
by `Viewers.forOutput`. A quality request belongs to one viewer and exists
|
|
232
|
-
only in AUTO (`Viewer.askQuality`).
|
|
232
|
+
only in AUTO (`Viewer.askQuality`). The playback start forecast
|
|
233
|
+
(`playback-readiness.js`) is the viewer's, because it predicts how the
|
|
234
|
+
viewer's browser will play; `ViewerRequests` is handed it by
|
|
235
|
+
`wire-outputs.js`. `media-time.js` is exact media time and the rule by which
|
|
236
|
+
every Media Source engine joins buffered ranges — see
|
|
237
|
+
`docs/playback-start-forecast.md`.
|
|
233
238
|
- `torrent/` reaches the piece store by what it does (`piece-store-of.js`) and
|
|
234
239
|
is handed the store's class by `torrent/worker/worker.js`, where that thread
|
|
235
240
|
is assembled. `transport/` imports nothing of another component; `bin/cli.js`
|
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,18 @@
|
|
|
1
|
+
## 2.89.3
|
|
2
|
+
|
|
3
|
+
- **Chore**: The same release as 2.89.2, which the registry accepted as a staged version and never published (`409 Cannot publish over previously staged version` with no staged version listed).
|
|
4
|
+
|
|
5
|
+
## 2.89.2
|
|
6
|
+
|
|
7
|
+
- **Fix**: Whether buffered media is continuous is decided in exact time. A piece's media is read as integer ticks of its track's timescale, and the page's seconds are converted to the exact binary fractions they are. Measured 2026-10-02 on a served film: seven joins whose ticks were equal read as `88.67299999999999` against `88.673` and were taken for holes.
|
|
8
|
+
- **Fix**: A gap counts as joined only when every engine joins it — Gecko's longest-frame fuzz and WebKit's 2002/24000 s, from which Chromium's bound follows. The previous rule was Chromium's alone.
|
|
9
|
+
- **Fix**: The position written into a served piece's `tfdt` and the position its coverage is read at come from one integer function. Measured on 20 field pieces: the bytes served are unchanged.
|
|
10
|
+
- **Fix**: A piece is refused as unfinished when the end of its last frame does not reach its cut less the muxer's configured delta. The check no longer uses a browser's join rule.
|
|
11
|
+
- **Fix**: A range the page reports holding is read as every exact time it can denote: Chromium converts a sample's time, its duration and the page's `timestampOffset` to whole microseconds before a buffered range exists, so each edge is widened by 3 µs. A piece the browser already holds is no longer counted as missing and transferred again in the forecast. A held range is allowed the largest frame duration of the served pieces inside it, as Gecko's `Interval::Span` keeps it.
|
|
12
|
+
- **Fix**: A hole between two ranges the browser already holds is reported as a continuity fault. The forecast used to find holes only where a new arrival crossed one, and started playback over a hole nothing would fill.
|
|
13
|
+
- **Fix**: An edit list made only of empty edits places its track after them, which is where the piece's own start is read from.
|
|
14
|
+
- **Chore**: The playback start forecast moved to the viewer component, with the join rule it uses; the request operation is handed it at assembly. The format states served ranges in ticks; the page's `timestampOffset` is applied by the forecast. The forecast works in one timescale in which every one of its times is whole, and keeps a piece's joined ranges with the piece: 12.7 ms per forecast on a 208-piece film on the development machine, the same as before the change.
|
|
15
|
+
|
|
1
16
|
## 2.89.1
|
|
2
17
|
|
|
3
18
|
- **Fix**: The subtitle walk reads a file kept whole from the disk. Once a file is kept whole its pieces leave the torrent's store while the bitfield still says they are held, and every read the walk made through the torrent waited on a store that no longer had them and was given up after 30 s — one structure read every 30 s, field 2026-10-01 on proxy 2.89.0. What of such a file is held is now the whole file, and a file removed for space is forgotten so the torrent answers again.
|
package/Dockerfile
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
# syntax=docker/dockerfile:1.7
|
|
2
|
-
FROM node:24-alpine
|
|
3
|
-
|
|
4
|
-
ENV NODE_ENV=production
|
|
5
|
-
ENV PORT=9090
|
|
6
|
-
ENV HOST=0.0.0.0
|
|
7
|
-
|
|
8
|
-
WORKDIR /app
|
|
9
|
-
|
|
10
|
-
# ffmpeg is needed for optional HLS audio transcode mode.
|
|
11
|
-
RUN apk add --no-cache ffmpeg
|
|
12
|
-
|
|
13
|
-
# Create an unprivileged runtime user.
|
|
14
|
-
RUN addgroup -S app && adduser -S -G app app
|
|
15
|
-
|
|
16
|
-
# Install only production dependencies first for better layer caching.
|
|
17
|
-
COPY package.json package-lock.json ./
|
|
18
|
-
RUN npm ci --omit=dev && npm cache clean --force
|
|
19
|
-
|
|
20
|
-
# Copy application sources.
|
|
21
|
-
COPY --chown=app:app . .
|
|
22
|
-
|
|
23
|
-
USER app
|
|
24
|
-
|
|
25
|
-
EXPOSE 9090
|
|
26
|
-
|
|
27
|
-
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
|
28
|
-
CMD node -e "fetch(`http://127.0.0.1:${process.env.PORT || 9090}/healthz`).then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
|
29
|
-
|
|
30
|
-
CMD ["sh", "-ec", "if [ -z \"${SERVER_URL:-}\" ]; then echo 'SERVER_URL is required' >&2; exit 1; fi; exec node ./bin/cli.js --server-url \"$SERVER_URL\" --host \"$HOST\" --port \"$PORT\" ${PROXY_EXTRA_ARGS:-}"]
|
|
1
|
+
# syntax=docker/dockerfile:1.7
|
|
2
|
+
FROM node:24-alpine
|
|
3
|
+
|
|
4
|
+
ENV NODE_ENV=production
|
|
5
|
+
ENV PORT=9090
|
|
6
|
+
ENV HOST=0.0.0.0
|
|
7
|
+
|
|
8
|
+
WORKDIR /app
|
|
9
|
+
|
|
10
|
+
# ffmpeg is needed for optional HLS audio transcode mode.
|
|
11
|
+
RUN apk add --no-cache ffmpeg
|
|
12
|
+
|
|
13
|
+
# Create an unprivileged runtime user.
|
|
14
|
+
RUN addgroup -S app && adduser -S -G app app
|
|
15
|
+
|
|
16
|
+
# Install only production dependencies first for better layer caching.
|
|
17
|
+
COPY package.json package-lock.json ./
|
|
18
|
+
RUN npm ci --omit=dev && npm cache clean --force
|
|
19
|
+
|
|
20
|
+
# Copy application sources.
|
|
21
|
+
COPY --chown=app:app . .
|
|
22
|
+
|
|
23
|
+
USER app
|
|
24
|
+
|
|
25
|
+
EXPOSE 9090
|
|
26
|
+
|
|
27
|
+
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
|
|
28
|
+
CMD node -e "fetch(`http://127.0.0.1:${process.env.PORT || 9090}/healthz`).then((r)=>process.exit(r.ok?0:1)).catch(()=>process.exit(1))"
|
|
29
|
+
|
|
30
|
+
CMD ["sh", "-ec", "if [ -z \"${SERVER_URL:-}\" ]; then echo 'SERVER_URL is required' >&2; exit 1; fi; exec node ./bin/cli.js --server-url \"$SERVER_URL\" --host \"$HOST\" --port \"$PORT\" ${PROXY_EXTRA_ARGS:-}"]
|