diff --git a/Packages/ContinuityKit/Sources/Ingest/MemoryFootprint.swift b/Packages/ContinuityKit/Sources/Ingest/MemoryFootprint.swift index c8c405c..e92edbd 100644 --- a/Packages/ContinuityKit/Sources/Ingest/MemoryFootprint.swift +++ b/Packages/ContinuityKit/Sources/Ingest/MemoryFootprint.swift @@ -5,6 +5,8 @@ import os /// memory allowance remains before the OS kills it — logging it at each pipeline stage turns a /// silent jetsam into a console trace that names the eater. Cheap enough to leave in release. enum MemoryFootprint { + // Same subsystem as the rest of the app's loggers — a split subsystem means a Console + // filter on the usual one silently hides every mem[] line. private static let logger = Logger(subsystem: "com.continuity.app", category: "mem") static func breadcrumb(_ label: String) { diff --git a/Packages/ContinuityKit/Sources/Ingest/PreparationQueue+Stems.swift b/Packages/ContinuityKit/Sources/Ingest/PreparationQueue+Stems.swift index 35c1cd8..79c74fc 100644 --- a/Packages/ContinuityKit/Sources/Ingest/PreparationQueue+Stems.swift +++ b/Packages/ContinuityKit/Sources/Ingest/PreparationQueue+Stems.swift @@ -11,6 +11,9 @@ extension PreparationQueue { /// **never** separated eagerly — only the neighborhood vocal-aware transitions need next. /// Also refreshes the LRU clock and heals links whose files were evicted. public func ensureStems(for tracks: [Track], in context: ModelContext) { + // Diagnostic kill switch: launch argument `-debug.disableStemSeparation YES` rules the + // whole separation pipeline in/out of a memory repro in one run, no code edits. + if UserDefaults.standard.bool(forKey: "debug.disableStemSeparation") { return } protectedStemKeys = Set(tracks.compactMap(\.youtubeVideoID)) for track in tracks { guard !track.isDemo, track.prepState == .ready, diff --git a/Packages/ContinuityKit/Sources/Ingest/PreparationQueue.swift b/Packages/ContinuityKit/Sources/Ingest/PreparationQueue.swift index 662c745..25dabc5 100644 --- a/Packages/ContinuityKit/Sources/Ingest/PreparationQueue.swift +++ b/Packages/ContinuityKit/Sources/Ingest/PreparationQueue.swift @@ -258,9 +258,11 @@ public final class PreparationQueue { track.durationSeconds = Double(file.length) / file.processingFormat.sampleRate } if needsSilenceScan, track.modelContext != nil { + MemoryFootprint.breadcrumb("silence scan begin") let bounds = await Task.detached(priority: .utility) { SilenceScan.audibleBounds(fileURL: url) }.value + MemoryFootprint.breadcrumb("silence scan end") if let bounds, track.modelContext != nil { track.audibleStartSeconds = bounds.audibleStart track.audibleEndSeconds = bounds.audibleEnd diff --git a/Packages/ContinuityKit/Sources/Ingest/StemSeparator.swift b/Packages/ContinuityKit/Sources/Ingest/StemSeparator.swift index a46a9bd..4bdf5cc 100644 --- a/Packages/ContinuityKit/Sources/Ingest/StemSeparator.swift +++ b/Packages/ContinuityKit/Sources/Ingest/StemSeparator.swift @@ -37,7 +37,8 @@ protocol StemSeparating: Sendable { /// devices on long tracks (an hour of 44.1 kHz stereo ≈ >1 GB) while the simulator's host RAM /// masked it. final class OnnxStemSeparator: StemSeparating { - private static let log = Logger(subsystem: "com.sanylax.continuity", category: "StemSeparator") + // com.continuity.app matches every other logger in the app — one Console filter sees all. + private static let log = Logger(subsystem: "com.continuity.app", category: "StemSeparator") /// Runs one model window: input is planar (1, 2, segment) mix samples; returns the planar /// (2, segment) vocals output. Seam so tests can exercise the streaming pipeline without the