port: move to formats-pin-2026-08-30 -- the voice export is complete

The late start was a second condition on the start filter, end - s < 1_500_000,
only within one bank. ADV's predecessor trailer sits 3618816 B before end, so it
was rejected and start fell back to anchor, a TOC offset rather than a stream
boundary -- which is why it hit regions over 1.5 MB and never single-stream ones.

ADV region 3114352 -> 3618816 B, streams 2 of 3 -> 3 of 3, complete, dropping
zero chunks. S00A 1 of 3 -> 2 of 3 with the third digitally silent. The runtime
no longer prints an incomplete line for either.

Also fixes the warning crying wolf: S00A still read KNOWN INCOMPLETE over a
93.694 s stream of exact zeroes. Exported gains content_waves and the warning,
console line and manifest field all key on kept < content rather than kept <
present. Second time in two iterations this warning was wrong in the cautious
direction -- over-warning is what makes the next real warning unreadable.

S00A is a second movie in the predicted direction: kept went 1 -> 2 because a
chunk that was a different duration now matches at 93.694 s. Not independent
ground truth, but a different asset and the outcome was predicted first.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01N7FiFFFwbvG2uxdcEh8HyF
This commit is contained in:
Sylpheed port agent
2026-08-30 09:09:49 +00:00
parent 90ea61b472
commit 2712efe2f2
5 changed files with 69 additions and 7 deletions

4
Cargo.lock generated
View File

@@ -4627,7 +4627,7 @@ dependencies = [
"image",
"serde",
"serde_json",
"sylpheed-formats 0.1.0 (git+https://git.mc02.dev/fabi/Sylpheed.git?tag=formats-pin-2026-08-29d)",
"sylpheed-formats 0.1.0 (git+https://git.mc02.dev/fabi/Sylpheed.git?tag=formats-pin-2026-08-30)",
]
[[package]]
@@ -4651,7 +4651,7 @@ dependencies = [
[[package]]
name = "sylpheed-formats"
version = "0.1.0"
source = "git+https://git.mc02.dev/fabi/Sylpheed.git?tag=formats-pin-2026-08-29d#e2640338e149acc903fac551f400a5319950afb5"
source = "git+https://git.mc02.dev/fabi/Sylpheed.git?tag=formats-pin-2026-08-30#c8d3a6a15d5feb0416b2b589cb8e0c442f7422d3"
dependencies = [
"anyhow",
"binrw",

View File

@@ -81,7 +81,7 @@ license.workspace = true
# geometry -- does NOT reach this port from here: `sylpheed-cli` builds from the
# WORKSPACE crate, so the reference renderer stays unrotated until the tag lands
# on `main`. This bump is for the parser, not for the renderer.
sylpheed-formats = { git = "https://git.mc02.dev/fabi/Sylpheed.git", tag = "formats-pin-2026-08-29d" }
sylpheed-formats = { git = "https://git.mc02.dev/fabi/Sylpheed.git", tag = "formats-pin-2026-08-30" }
serde = { version = "1", features = ["derive"] }
serde_json = "1"

View File

@@ -208,6 +208,12 @@ pub struct Exported {
/// Exists so a "known incomplete" warning fires on the gap and not on the
/// mere presence of more than one stream.
pub kept_waves: usize,
/// How many of `sub_waves` carry SIGNAL. A dropped stream that is digitally
/// silent is not missing content, and a warning that fires on it is crying
/// wolf: `S00A`'s third chunk is 93.694 s of exact zeroes, so dropping it
/// costs nothing and saying "KNOWN INCOMPLETE" over it would train a reader
/// to ignore the one case that means something.
pub content_waves: usize,
/// What the runtime should do at the end of the file, where that was
/// authored. `None` on a cue: a cue ends.
pub loop_mode: Option<String>,
@@ -353,6 +359,7 @@ pub fn export_cues<S: DiscSource + ?Sized>(
loop_mode: None,
sub_waves: 1,
kept_waves: 1,
content_waves: 1,
});
}
Ok(done)
@@ -523,6 +530,7 @@ pub fn export_bgm<S: DiscSource + ?Sized>(
loop_mode: spec.r#loop.clone(),
sub_waves: staged.len(),
kept_waves: 1,
content_waves: 1,
}))
}
@@ -915,6 +923,7 @@ pub fn export_voice<S: DiscSource + ?Sized>(
loop_mode: None,
sub_waves: riffs.len(),
kept_waves: staged.len(),
content_waves: riffs.len() - silent.len(),
}))
}

View File

@@ -457,7 +457,7 @@ fn run_export(disc: &Path, out: &Path, authored_dir: &Path) -> Result<()> {
// export is known to be missing audio the game plays, and
// the failure sounds like success: one stream decodes to
// clean dialogue, so nobody listening finds out.
if a.kept_waves < a.sub_waves {
if a.kept_waves < a.content_waves {
warnings.push(format!(
"{}: KNOWN INCOMPLETE. This region holds {} streams and the RUNNING \
GAME DECODES ALL OF THEM CONCURRENTLY (Canary --xma_param_probe: \
@@ -477,7 +477,7 @@ fn run_export(disc: &Path, out: &Path, authored_dir: &Path) -> Result<()> {
describe(&a),
a.kept_waves,
a.sub_waves,
if a.kept_waves < a.sub_waves { " -- KNOWN INCOMPLETE, see warnings" } else { "" }
if a.kept_waves < a.content_waves { " -- KNOWN INCOMPLETE, see warnings" } else { "" }
);
audio.push(ManifestAudio::from(a));
}
@@ -517,7 +517,7 @@ impl From<audio::Exported> for ManifestAudio {
why: a.why,
peak_dbfs: a.peak_dbfs,
duration_s: a.duration_s,
incomplete: (a.kept_waves < a.sub_waves).then(|| {
incomplete: (a.kept_waves < a.content_waves).then(|| {
format!(
"{} of {} streams. The running game decodes all {} concurrently. \
Nothing in the audio reveals the gap -- what plays is clean dialogue. \

View File

@@ -9,7 +9,7 @@ dies, which is what this file is for.
<!-- INDEX: generated by tools/port/index-decisions -- do not hand-edit -->
129 sections. Search this before re-deriving anything.
130 sections. Search this before re-deriving anything.
* [P0 — the exporter, 2026-08-28](#p0--the-exporter-2026-08-28)
* [P1 — Godot draws the screen, 2026-08-28](#p1--godot-draws-the-screen-2026-08-28)
@@ -140,6 +140,7 @@ dies, which is what this file is for.
* [Their stream assignment does not fit my region — weights NOT applied](#their-stream-assignment-does-not-fit-my-region--weights-not-applied)
* [The resolver starts late, and my "duplicate tail" was a real stream all along](#the-resolver-starts-late-and-my-duplicate-tail-was-a-real-stream-all-along)
* [The export knew the voice was incomplete; the runtime did not say so](#the-export-knew-the-voice-was-incomplete-the-runtime-did-not-say-so)
* [The voice export is complete — new pin, and the cause was a "within one bank" cap](#the-voice-export-is-complete--new-pin-and-the-cause-was-a-within-one-bank-cap)
<!-- /INDEX -->
## P0 — the exporter, 2026-08-28
@@ -7542,3 +7543,55 @@ why is not the same story twice** and a single sentence cannot carry both.
*true* only for the case it was written against. It is the failure mode of every
generic warning, and it is harder to see than a wrong number because the sentence
is well-formed and confident in both places.
## The voice export is complete — new pin, and the cause was a "within one bank" cap
`formats-pin-2026-08-30`. The cause of the late start was a second condition on
the start filter: `end - s < 1_500_000`, *"only within one bank"*. `ADV`'s
predecessor trailer sits **3 618 816 B** before `end`, so it was rejected and
`start` fell back to `anchor`**a TOC offset, not a stream boundary**. That is
exactly why it hit regions over 1.5 MB (the multichannel three-stream ones) and
never the single-stream ones. 17 of 95 movies took the fallback.
| | before | after |
|---|---|---|
| `ADV` region | 3 114 352 B | **3 618 816 B** |
| `ADV` streams kept | 2 of 3 | **3 of 3 — complete** |
| `S00A` streams kept | 1 of 3 | **2 of 3**, the third digitally silent |
| `ADV` peak | 3.1 dBFS | 2.84 dBFS |
**The voice export is now complete for both movies**, closing a defect that was
open for this entire session — and my re-reading of the "duplicate tail" as a
start-truncated simultaneous stream is what the fix confirms. `ADV` drops **zero**
chunks; the runtime no longer prints its incomplete line.
### 🔴 And the incompleteness warning was crying wolf on `S00A`
With `ADV` fixed, `S00A` still read **KNOWN INCOMPLETE** at 2 of 3 — because its
third chunk is **93.694 s of exact zeroes**. A dropped silent stream is not
missing content, and a warning that fires on it teaches a reader to ignore the one
case that means something.
`Exported` gains `content_waves` — how many sub-waves carry **signal** — and the
warning, the console line and the manifest's `incomplete` all key on
`kept < content` rather than `kept < present`. Both movies now report no gap,
correctly.
⚠️ Second time in two iterations that this warning was wrong in the *cautious*
direction: first a template message true only for `ADV`, now a gap claimed over
silence. Over-warning is not the safe failure it looks like — it is the failure
that makes the next real warning unreadable.
### A second movie, in the predicted direction
They note only `ADV` has external ground truth; the other 16 rest on their own
sweep. **`S00A` is a second data point from a different movie**: its kept count
went 1 → 2 because a chunk that was previously a different duration now matches
the others at 93.694 s — exactly what restoring a truncated first stream
predicts.
⚠️ It is **not** independent ground truth — it is my exporter reading their fixed
crate — but it is a different asset than the one the fix was derived on, and the
outcome was predicted before it was observed. Recorded as that and nothing more.
Oracle rows unmoved; MODDING rules pass.