diff --git a/crates/pf-bitstream/tests/corpus_replay.rs b/crates/pf-bitstream/tests/corpus_replay.rs
new file mode 100644
index 00000000..5a759767
--- /dev/null
+++ b/crates/pf-bitstream/tests/corpus_replay.rs
@@ -0,0 +1,232 @@
+//! Corpus replay: walk a captured real-host stream through the planners.
+//!
+//! The M0 capture hook (`PUNKTFUNK_DUMP_VIDEO=
` on any desktop client) writes
+//! the exact decoder input of a live session — `au-.` plus an `.idx`
+//! sidecar carrying `offset len flags complete` per AU. This harness feeds those AUs
+//! back through [`pf_bitstream::h264::H264Planner`] / [`pf_bitstream::h265::H265Planner`]
+//! and asserts the planner survives a REAL host stream: every AU plans (bar the
+//! deliberate skips), no panic, and the warnings are only the ones a clean capture may
+//! legitimately produce.
+//!
+//! Why this exists separately from the vendored conformance vectors: those prove we
+//! match the spec's own test streams, and the on-glass sessions prove the whole pipe —
+//! but between the two sits "does the planner handle what OUR five host encoder
+//! families actually emit", which is the question the corpus was captured to answer.
+//! For HEVC this is the ONLY pre-wiring validation against real host output (the
+//! client's HEVC rung is still being built), so it runs long before M3 finishes.
+//!
+//! Ignored by default: captures are hundreds of megabytes and live outside the repo.
+//! Run one explicitly —
+//!
+//! ```text
+//! PF_CORPUS=/path/to/au-1785970273.h265 \
+//! cargo test -p pf-bitstream --test corpus_replay -- --ignored --nocapture
+//! ```
+//!
+//! The `.idx` sidecar is found next to the data file (`.idx`); the codec comes
+//! from the extension, matching the capture hook's own naming convention.
+
+use std::path::Path;
+use std::path::PathBuf;
+
+/// One captured access unit: its byte range in the data file, plus the wire bits the
+/// byte stream itself cannot carry.
+struct CapturedAu {
+ offset: usize,
+ len: usize,
+ /// The wire `flags` byte (`USER_FLAG_*`) — kept for the RFI/intra-refresh legs,
+ /// which discriminate on it.
+ _flags: u32,
+ complete: bool,
+}
+
+/// Parse the `.idx` sidecar: one `offset len flags complete` line per AU, `#` comments
+/// and blank lines skipped (the hook writes none today, but a hand-trimmed corpus file
+/// is a thing a human will produce).
+///
+/// A malformed FINAL line is dropped with a note instead of failing: ending a capture
+/// means killing the client, so the last buffered line is routinely half-written (the
+/// hook's own docs call a truncated last AU acceptable). Anywhere else a malformed line
+/// means the sidecar is corrupt and the run must not quietly replay a subset.
+fn read_index(path: &Path) -> Vec {
+ let text = std::fs::read_to_string(path)
+ .unwrap_or_else(|e| panic!("cannot read the index sidecar {}: {e}", path.display()));
+ let lines: Vec<&str> = text
+ .lines()
+ .filter(|line| !line.trim().is_empty() && !line.trim_start().starts_with('#'))
+ .collect();
+ let last = lines.len().saturating_sub(1);
+ let mut out = Vec::with_capacity(lines.len());
+ for (n, line) in lines.iter().enumerate() {
+ match parse_index_line(line) {
+ Some(au) => out.push(au),
+ None if n == last => {
+ println!("note: dropping a truncated final index line ({line:?})");
+ }
+ None => panic!("index line {n} is malformed: {line:?}"),
+ }
+ }
+ out
+}
+
+/// One `offset len flags complete` line, or `None` when it is not four parsable fields.
+fn parse_index_line(line: &str) -> Option {
+ let mut it = line.split_whitespace();
+ let num = |raw: &str| -> Option {
+ match raw.strip_prefix("0x") {
+ Some(hex) => u64::from_str_radix(hex, 16).ok(),
+ None => raw.parse().ok(),
+ }
+ };
+ let offset = num(it.next()?)?;
+ let len = num(it.next()?)?;
+ let flags = num(it.next()?)?;
+ let complete = num(it.next()?)?;
+ Some(CapturedAu {
+ offset: offset as usize,
+ len: len as usize,
+ _flags: flags as u32,
+ complete: complete != 0,
+ })
+}
+
+/// The capture named by `PF_CORPUS`, or `None` when the variable is unset.
+fn corpus_from_env() -> Option<(PathBuf, Vec, Vec)> {
+ let path = PathBuf::from(std::env::var_os("PF_CORPUS")?);
+ let data = std::fs::read(&path)
+ .unwrap_or_else(|e| panic!("cannot read the capture {}: {e}", path.display()));
+ let mut idx = path.clone().into_os_string();
+ idx.push(".idx");
+ let mut index = read_index(Path::new(&idx));
+ // Same truncation story on the data side: the final AU's bytes may not all have
+ // reached the file before the client died. Drop AUs the data cannot cover — but
+ // only from the tail, so a short file can never silently hide a middle gap.
+ let covered = index
+ .iter()
+ .take_while(|au| au.offset.saturating_add(au.len) <= data.len())
+ .count();
+ if covered < index.len() {
+ println!(
+ "note: dropping {} index entr{} past the end of the data file (truncated capture)",
+ index.len() - covered,
+ if index.len() - covered == 1 {
+ "y"
+ } else {
+ "ies"
+ },
+ );
+ index.truncate(covered);
+ }
+ assert!(!index.is_empty(), "the capture's index is empty");
+ Some((path, data, index))
+}
+
+/// Per-AU outcome tally — what the run reports and asserts on.
+#[derive(Default)]
+struct Tally {
+ planned: usize,
+ skipped: usize,
+ errors: Vec,
+ warnings: Vec,
+ partial: usize,
+}
+
+impl Tally {
+ /// A clean capture of a healthy session must plan every complete AU. Errors are
+ /// hard failures; warnings are printed and capped — `MissingReference` on a stream
+ /// that never lost a packet would mean the planner invented a gap.
+ fn assert_clean(&self, total: usize) {
+ println!(
+ "planned {} / skipped {} / partial-AUs-ignored {} / errors {} / warnings {} \
+ (of {total} captured AUs)",
+ self.planned,
+ self.skipped,
+ self.partial,
+ self.errors.len(),
+ self.warnings.len(),
+ );
+ for w in self.warnings.iter().take(20) {
+ println!(" warning: {w}");
+ }
+ for e in self.errors.iter().take(20) {
+ println!(" ERROR: {e}");
+ }
+ assert!(
+ self.errors.is_empty(),
+ "{} AUs failed to plan — first: {}",
+ self.errors.len(),
+ self.errors[0],
+ );
+ assert!(
+ self.warnings.is_empty(),
+ "{} planner warnings on a clean capture — first: {}",
+ self.warnings.len(),
+ self.warnings[0],
+ );
+ assert!(self.planned > 0, "no AU planned at all");
+ }
+}
+
+#[test]
+#[ignore = "needs a capture: PF_CORPUS= (see the module docs)"]
+fn a_captured_host_stream_replays_through_the_planner() {
+ let Some((path, data, index)) = corpus_from_env() else {
+ panic!("PF_CORPUS is unset — see the module docs for the invocation");
+ };
+ let ext = path
+ .extension()
+ .and_then(|e| e.to_str())
+ .unwrap_or_default()
+ .to_owned();
+ println!(
+ "replaying {} ({} bytes, {} AUs, codec {ext})",
+ path.display(),
+ data.len(),
+ index.len(),
+ );
+
+ let mut tally = Tally::default();
+ // The planners take one COMPLETE AU. A partial AU (the wire's shard split) is the
+ // pump's business, not the planner's — count and skip rather than feed a fragment.
+ let complete: Vec<&CapturedAu> = index.iter().filter(|au| au.complete).collect();
+ tally.partial = index.len() - complete.len();
+
+ match ext.as_str() {
+ "h265" => {
+ let mut planner = pf_bitstream::h265::H265Planner::new();
+ for (i, au) in complete.iter().enumerate() {
+ let bytes = &data[au.offset..au.offset + au.len];
+ match planner.plan_au(bytes) {
+ Ok(plan) => {
+ tally.planned += 1;
+ for w in &plan.warnings {
+ tally.warnings.push(format!("AU {i}: {w:?}"));
+ }
+ }
+ // The spec's own skip (8.1.3): decode nothing, show nothing, the
+ // stream is healthy — never an error (the WP-2 contract note).
+ Err(pf_bitstream::h265::PlanError::RaslSkipped { .. }) => tally.skipped += 1,
+ Err(e) => tally.errors.push(format!("AU {i}: {e}")),
+ }
+ }
+ }
+ "h264" => {
+ let mut planner = pf_bitstream::h264::H264Planner::new();
+ for (i, au) in complete.iter().enumerate() {
+ let bytes = &data[au.offset..au.offset + au.len];
+ match planner.plan_au(bytes) {
+ Ok(plan) => {
+ tally.planned += 1;
+ for w in &plan.warnings {
+ tally.warnings.push(format!("AU {i}: {w:?}"));
+ }
+ }
+ Err(e) => tally.errors.push(format!("AU {i}: {e}")),
+ }
+ }
+ }
+ other => panic!("no planner for a .{other} capture (h264/h265 only today)"),
+ }
+
+ tally.assert_clean(index.len());
+}
diff --git a/crates/pf-vkdecode/tests/data/test-25fps-h265.nv12.sha256 b/crates/pf-vkdecode/tests/data/test-25fps-h265.nv12.sha256
new file mode 100644
index 00000000..4863aaf4
--- /dev/null
+++ b/crates/pf-vkdecode/tests/data/test-25fps-h265.nv12.sha256
@@ -0,0 +1,268 @@
+# SHA-256 per decoded frame of test-25fps.h265, DISPLAY order — 250 frames.
+# Each frame is the 320x240 picture as tightly packed NV12:
+# Y plane 320*240 bytes, then interleaved UV 320*120 bytes = 115200 bytes/frame.
+# (This vector carries no conformance window — coded size IS display size.)
+#
+# Generated from libavcodec's software decoder (H.265 decoding is exactly
+# specified — every conformant decoder is bit-identical), 2026-08-06, and
+# CROSS-CHECKED between two independent FFmpeg builds that agreed on all 250
+# frames: 8.0.1-3ubuntu2 inside the pf-lxcheck2 image (docker run --rm
+# --platform linux/amd64, ffmpeg via `apt-get install -y ffmpeg`) and 8.1.1
+# from Homebrew on macOS/arm64:
+#
+# ffmpeg -i crates/pf-bitstream/vendor/cros-codecs/src/codec/h265/test_data/test-25fps.h265 \
+# -f rawvideo -pix_fmt nv12 -fps_mode passthrough ref.yuv
+# # then split ref.yuv into 115200-byte frames and sha256 each
+#
+# Sibling of data/test-25fps.nv12.sha256 (the H.264 goldens) and consumed the
+# same way by the HEVC parity test.
+ef4900effa72cbc00cff38938bc558cc5d70b31ca268aaf3c01c4268a9d8066c
+fdbae4473d24c3adcef59a51c1449304c2fa271412622efceeba5ee7437b5529
+9aab5493a8fe3dfbd3f1eab89bf67a4964998bf8f1229c672ddf2d0d5fe26edb
+52797a59351b0a02069a3d8b2022ad7e06be4e03a7ab9483e09c0b03e4dbfec9
+9c68407853977ddd95dda04b77676e983fd7ad4665bbbe65497ea5e91f5b19d9
+1d7e6adc6a225e1bcd2c5cc598c0342472edd2d7dcc162c38872fc665b57f3d5
+4633e66a0ec77f26ab955bea209b1e976947ae87d8405e4a70be2d8e6ab69625
+6cce1546ee5c1d414353a990aeb6cd3035199196cc6bd527d1f7985247c30cfc
+6e5eb5c2286156d4c7406c9bba159348618799fdf2d46d470ad4f0fe2c6671dc
+25b0af55a492eaa503349ab45f1d6449df832361ac60d2910eade5380c5b0789
+dcae9606d93f9405c95e5a03699beeae1442240303df2d457bb3b5fd5e2cbd18
+d7bcf9616f062b9cbdaa076db0aa8fe0e60ef83b51c1336276183fa4d6f2f0cb
+003e43b5d1e731ae234146763c1f65b4c4e2a67fdab3d938b7ba442be360a520
+3bbf1a62250deeae73fdf77ff34c2c850886557bc79815a2c968a5d8968a67ba
+d8fff092b581e7807b77df684e74f97013b6c69d4610ad17f08855585c3ef5d6
+52d3d01f8f147d8574295859ba1f7437ff11d57eafb5c5325b55c7533abf922e
+e75eef989830cbd6c8dc3957fcd96e1061f861c5f12eaefadd21f600ce0998a0
+9ffd2496189a6384eddda2e752a719e27c6c69e5fc74330b75fa7e4c928cfd55
+ff304806867abf9d6d683c0d3bce95473cbad3252e815463e9eb5a1b5fabfd6d
+9320a5e1fd33ec1c8b3d2964af8050bbcec219b3287b83c2cbe6f61e8d4f3cd7
+9816da3390b510218fc8605398f9cee8d0c8561e2933f2e2a1f771023a7116ea
+198b078fda1f6f1402a53e8c73b99544abb8c4091efab68e7221af73732fc10c
+fb13ab23a5e012e4ff0cdbba1af7261a636940831c1cbbe1065fdd4eeb4754f4
+73fca4a423291a3ff6c787a7660085732a687d7e061dff235a29d83ceb96e95b
+195ce227acdcfa1a4cd4fe35eff3291ebdd5f3fe7545509e32e17c744eb98b4a
+706aee7736f9c599b48dcd156cb27faaaae51f3fe85b14dc12402207033aed17
+e061a0ab22441f9b2be0fd111ca67248ea40bb3f5d3b280b3c52648eed8444b1
+93be6f5a81550ecca250ee0c145e5c4135d05ef0f4a78095f94e85070cae9db9
+465723432c68de41e96fc32e562812343a9fdecd53b9699fcc6770b5f9e4b002
+874b39b128db5b47160cf0d8bcc0040063e23dc5b7f0172a8149f78e7ab57195
+3cee067706084dd8740ba200e3eb1955c93e1df4aaecc298453560e61f658271
+7ea42e3f7c7a6488057d4cb7db1f7dd61f505cdcf8e71bcaa33eb00b734018bf
+55b00704e979ac7bf2e4961dfe12f1ef5c559a421e24e3243f943a013e679fe0
+e91f2096b0bde6bef5762f2765d2ce30c77f9e1a9adc151bd07277fb715c8131
+08d1391f8876e67cd086d79a703401da70abdd37e3522445830e40cd820cf3ba
+87531fd1641407d8eee5888068c9655920976deaaace01b0c6b6766dace53d62
+1993c8add817ed50882c865eff2c82f93f1c8f050e1ee3171d9518e3a6ac0563
+f682098c0cfa38af29ecb40572aae48c4663e11c5ba9ae256871a1fc62111dd7
+dca4d5cad38a35d15ecd4ef02e2a2effc6c103ac4f27ed61518416bfb8084f72
+33a6d608d4dcb2cb47d648ff4637b62e65b4a769093ba0bbf39ef151e174cf5f
+814d05ff585e21676fe08a867ca4593c65870b81d5bb7ae51d8fb795371bf9e5
+91339266713bb79af8d547ad888a010b7ad56debc938e4ecd9f3542a8d148e40
+945258f865bb6b795d06609d57ac77ee5d863bf19fb35785ac7578d46e229cb8
+2b2619f2814b08675b263e38ae8a50d816fca71d6f014f6058cea2b4dae74aee
+89b8983416633c225519b3621bf65601a0f6c0f46de5ca3250a9b0c34edff73f
+0a007d2eacaf06f629ef854450fca7d83d6f6e1bab60a1145466dc157082f877
+e8550a8a431f623ccfc8457c4f171a6c9bfdc1c67807fe1fb45cf4bdbc14f7d1
+aafa9b366c4d560b9994366b1ec3a2f71c861191316b84e6b46ba7ddf79c19ee
+4ec7b250bb49ec17b34a090f36f8cd07692829dcba1ee939a4526e89366ba1a5
+c00e70ec1b43cea1b3d2909d61cd53239f428085b6769913307c9006bfeae83c
+b8744028170518a8542d4f37ff05990230ea1ab87d71896b0fb41866b3859e57
+cc9b833a5725bae1c6e9d198c148ef45fced9b34a36fcf043cfd2774baf9ac55
+81f3666280e765cc8641fcfb0a65fac70175e18c7ab701534a5499ffe3fa8543
+f92faf17adfb611afa432c2c4f3c192ca24246a9613601ca109bcec0d8a18c56
+6acda837d6691b80b11c9c83fb41108b0aaefd1a90b5bdae28429542ae998f5c
+94db3458a1fac5e9cd5a9ec07de06c659a20051b80bf71b2435d174604e502bd
+cdbb03c8d67aeef96c7073346a87b1a41e866c2fec75a5003ab43d10ba953457
+2f05ec023ce09ce00b3fdd277e0da4aabe1e1a073e9612632fb5f5c95103caa7
+5587ef3923591036daf4d471a8a131d04fff2a6612e2e7788ac4662a8a3e16eb
+19c7c1534c40e8a4dd7a6461fcd5d8695951dca24d7d2923b5ca12cb4160afe1
+95bb6aefb8ac74e52e3ef64e224a64eecb08d82ff3449d1cc1b8b44888a2ca38
+1278e669f16f311582ea9456e7361c57d4b4748c9902c780c4d9d62c7e603f1c
+0d77145396334c2f3008b72441d594f7c3e110da95aef11d6bede46f49c79be9
+099ea10831ceda528df779d1c7b679cdc1d251f10cfc39f4950f7fb3a3cebd36
+8cb5a50ee01d37f8501884be3cd5239f5e57892901afedc4ddc3a9fecf435b0a
+5c4f777977b786ab5e80f6bd7ea9880aae7fd8d8cf9e4d79016020d4fc916c22
+d635fab89355529ee6661f8e867e5361bd28773422f8478939dd806162292346
+baebab9b93c6dbb63ea19468538d9663a2f9fef5bae21dba46161454ca05c770
+22f4c44eec9c70d32b05cf0eccfbdf5b477b0f93bc61a17f9b5b4c5a7dbc2ebf
+fecadfb3ec25bd00929059e9849da387ca0cee8eec9f0792128f3256eddd5bd7
+48065431ce0b3f8f0ad5f77fc30fa29eb961b1ba5e6a97c0bf41c5d3c0ea8518
+b575ccc73436b7937f98ec1847fd54d7c7a3a086d08adcff9d226613efd5bac6
+be5d094c2a2ab5feb6c988c68e9f2d6eee73bc69e8c51ed24786325d185ad5f6
+6c16634620280926af758f013b66c2a75a79ea67a90184965ea1bf91b9f51696
+0b63b9eedc87d047474f9c46e71dee75ca1e3a5db5cb0c9d7ea0627fa8c82876
+02052e7622fa96d6a0696f5c27d632ee49caedc5ac908a5c9f6a8d6d475be6e3
+ceeff7e73cca36a48a775f2e6b773d7c968c20de18bef4460dca582e6ba4b894
+693663aaf34e534a4f6d2ae7846aa26aa1d73b4bd9f854dd70bdb6a41b0cbb65
+474a10f6eefba5c7d16efd99fee59e0b762380b0f3acbb91e76bdc18a6dc9c02
+4c005f6dbb86ba5ef0001a551af8b4e4aa996e5f27c23658ea3002d319e3c53a
+9968c5c0966a246dad5e0b49668d3d1caccc12a7722aaff677a6ad63c32b961e
+a1d57c958b92e6a8d557893c62cea08d5959dd34a1421bf1fba02adf7acf0244
+f885bb6f13840be75c88223d07105f0ccbd4aa678ac2e76ca347739b0e3158b0
+644526f73200746ed78f8d0a35bacf486b17c6bb890f58e12c433ccdad59a37f
+2beef1de03e18970f81792b0d247fdc9112d603dca852507b48d3585c86a7fa6
+b76fe733ccb80eb233ccd263dbfe264b6c298a93a3847159ab19fd8d9566d63d
+cc7cfa0dfd02fec28ddc9504cf0e4a2656c2b3e7e2f13207b9979f9930408ea6
+fa6546a8828e3e3c75b1a60c0681db322d521fd4dd3fc9b005ccfb42d58fd9ba
+d1b2527753951c11ff69e4db8323c058e40f411bfa4e23915f5675e30cd43b77
+5eaf026663142af2ba32628a4589aaa143977ecba28181730172099c6f749abb
+9d18abd96a6548cb643b39a2499b1f718713dbd92f66f35392fa0f9fcdf4a81b
+38ce5c4261c740ab054dac484af6afe58bf5eacd95fd322113cf532f362e0ea2
+55852ee3a2f92db0bdfc64c2693ff5a43ed7348a6ea947aaf9646b964c1842e7
+ba7488d71bf856cebde72d96245a582efae3d3392dc75615fdce2146b123cb0f
+3e4c55e47febd86861cf4a7b56cb2e6fdcb1d9542d521ab04f57643d844d2f81
+8df056cf2f0d1e13c1d1a419251b09a9e1edd164e5c9ace7525be2c08d7cb84f
+2e7fc74a622da56c8ad17d66f7fa2bd5a466dfe4147db80b7a58dbc93158a0ea
+ffac7a103ab051aad9ff90fa43f9d98c149aaa6057d59660a70256bc9ab3951a
+3725bd25b394076327a8f6ff010fb9e4b7662d67b48c80693997d434eb541399
+fd807e07cd0f003ac3d834487bd7526b000d3ffd79295ba92fc10caf3e5bd6ad
+071469b129dc9ef55e67f773ad5c2ef6498b728169e98910dc5923b4181e3ad2
+512ced1859982b5bbb58f48a5ae8006c56bd28e165f0a761c38bf214d2636983
+8a663c0abe78913974d29f4380b7addc46612d55fb431c11042bb7985f22d501
+92ea5506c94d885aedb9dfa7f884a43ed8289b49542b67861e576cfea4d62b11
+a29dde155a03511735f9370ce23b95bfd98868434ddf6e9a3669c2edd0ad1d8f
+1688fd2fe7b5f7e4cfcc40d3afff903bd0a5cb8536c0d7da4d53b90544b03227
+96f593ab7339f0cb02bec07b6f5bcc11d2494ced35a90d4037c961a2e284d914
+9450d79524043cc3f2afe0dda19b6a5a06de7128ad9826802b798255f72aaf00
+4dee54c01448ed0595fe1c0108c97031c48de96ea425c8f8c2e5b3382e862a3e
+24bb1d429aee55c9d2c719777d15a3e8116fd2074a569a5e44a8d5de6d11fe8f
+fe0255625438d6403fd663f60eab05ff990780054eb530dbfaa3552a978cfdc5
+452961eb29a947dd2818409c8d5e283ebf47281eebeb9c368164b22dadb315a5
+e49ad550b30140b2b99b6edd0e1a7873f3ba0145829037c2490467ddfcfc439a
+f02dd0ac342330223e9c0ae56ed6a9efc3a0c69d8bb4c036943dd16f654f10bf
+60352cf761e2cd8ba2cc0025c45e715a8719fabe78d5de7a382da4b648704ea7
+3b79506fc18e01a1168f880712c539f0a520712dd62d2f824b6b754ce034f1f2
+3c16234ed4606128fca31196a81f769ac69a4261aa176bf8c8d86b8699177926
+6a98fcfcef5d1ed813ba3f2f66f5b1bd11729430187a7366dcbe9617f2914646
+5683c679c3c0fb24b740ef4582c787591f10dcffc9e46037422829f5b58a1501
+9b4c0ca82d8440b630a569a8d6525384beb26ca7d54b7a1ddb1b83a00e134701
+5693915c011d2ad738b84c8a04cfb8081006b8835ec655e76d829e5dbcbe0688
+1ddbeb8cbe7d0d8ce61a94e3ca35730a07e59bdbb692cc82dfa3ea0ff9ba5979
+ca10afdd882627e9a6cb5d389c71fa015cb0015124c7445295ac42660a01c491
+7aa406047f3fdc2a07d6d228b30535734689c99d93e8c5c7865044187ca0d3b8
+8e3f8d26612b58f985ed778f1ad5f6cca0be49acee5b7d4d09ab2b886a3327bd
+9edb22ab753a8cb66392d301144df20c7e67e3afe6bc9d1c3143087ecf26120f
+fc4d040db9172642d710b4edabca7e5444fdc9099f9867b5942e200da1d6373a
+1cfd8b95c000cc30892061db6dac6323f2f7a654c30d0ed024368997ac65e673
+f9ebda67091c2b26e7205bdab431299d982dace99cedfec13c80cfd3195286c0
+5cea0e5febf079803e85b57bf45d3d563d0e8fa1e45844af18609077497fbd3c
+2c4c74504660b5222f2135407805000fe1a41df48c47b28685e57020c6d21061
+d49cffec62c461a04292556bb21f78861556b058db006143696e53cee077d26b
+9d7ad96746eef142fec236232c0d275943a5258a40fe3fa384aaa5614856cbc2
+958cde369e11df3a7bc534ac549fc11b4a6e325fc02942f49c68c47e99ed65bc
+a05043d7198834dd8da3d544dd7c11d3f03a3389a422fd0a0be732824b587047
+700a4641d8ee0a7ab2b0a09421755ee6223ef1f7b6436a96eaa479140361b40b
+16d487df87dc05fa10373f139558597f0c82b9a22828de0ec462fae72ac09124
+73a8de0a8f0652405aad48cb13765767c80286ef190dfc1a10234fae0ee0dc71
+19f30498e93062ddf30e284bb44b9c6b6ee5c2ef6e143d40cf7dd76b669bf670
+93de878f03e69fce3ec00963df3bb941713bf225b665b0baede46e4a9559b567
+fc55a32f7fc41925a5bdf7fcf34513b90b6acc326771fd77db7fc0f4572db395
+e84bffc862d0d017903ec43414b0659b9720d0a4d646be3d1576a168a4333ab3
+ef655d0f2ee29f23409d1a8689710e024aae636c1ecfe8bc1915774a94732f8d
+95c63e9092ba3a5887e9ba2044aea96315b25e55af2fbadbad50345fb98629fa
+15501a54f24943a19a663263c5459d31c45441147cd58eba4935ab67d1bed291
+bedcf37b2101e06e9f76f85df28e70574bff094ddee96fb3b4733da63551e22a
+e06487f3691cb56df61d13e838d62a403e7cf4cbf399c89e98a7d04597e91653
+483596c621e2646ffe668743eb0e55269bc7dde6188ffb80c086b215d73a9717
+a84fcc692a5ae998f082fb21e429076d59c48fa6880309bbe692e6f0b5c0ab86
+4aace8b7ea4891aa80f8df369689e0dd587d88d55160d40ff1fc03dd4fb7fe44
+b0b13ef2e6684489fe0af1ddcc2dc2e04e833d372b7c4838d1cd173da993265d
+6ca96a7be457ba2bf06aba287fdad92bf356d31723d392e654ff352d480b5da0
+69554f33448ca613f466adbb14748ce2001518c861397100579340b9d9c71dee
+baebb6de906b34a88a890274e491ffe00ce28b003b0ef1331c484740c036a30d
+841a7b7efd05b4f8aadf6bb0074067a64b118c20505f317babcdebcdac05b9aa
+d2eeff202d639a4c0ff451caad9cc7a7f4bb8aa62e6659671fadc4ba85a7eb29
+4ebc9035f1db8feb6e56f47a180b4108ee374c7442ea5cb2ba4fa59427d88fc6
+b7e2988ff896ed2618a17766dff44839b23b934108a1d75948ed0826c8129d42
+9eb4b2490eabc51f7fcc75c5aad419208238ed6807ff109ec02cf0f6ac1e12dc
+4ba2d5fc6b9b27c53b4217b04f70dc219073a9c1cb0863e040d9973c88899084
+e26701bcba0f2014ca93eee23893e020bf681e071c9e62d0fb75619de7de715c
+ec829d9898ba7eccb51af41e5412255bfe93e61137f56a21d4999911fc154bfe
+ad47b88c0fc7750dd1a5cc27cf134638a9270342e957aef81e517a5a519933fd
+1d39f1ebd301526344a29c8d07049a389ce157e8a0184fb34e38ad3c2a851afd
+20d4699ce3a43154a62ef5cbf8f14bc47cfc344eff92ec78e4e6108d2827ad33
+79ceadfa9d591934dc9d87125772ae7cf3a0f26fe91ee77f27eb11a23924981f
+3d481e4dcd5f0e849323822d687f4cbc7570474b985251fc13cb019ac5f72a81
+80a680a0054e1b0968a3ade98a8ccb42789082584d3a72917d2a1857b348b5e6
+fd031ad921c6dad12473e6fa148c74e05660e98be91cb68d3c5b43da423d06d5
+7f5fa38b7ce6401ff353a9b680fccadc138af24cd66369a05a796c363bcdeb45
+8a6ab1effe3736620a7d21ff943e7c50bcd244d9ebd26dd0f613c86b1e866ad2
+8020cb196e1830ce33c5242cebae2c13ca64e36b0a1186cda71b3b19fcdcddef
+8c8ad9f8f7fd75798017937e117699485711220f2b529f0b4e62c1765461538c
+66cad5c567e55c73b672f710a95c05825e26786ba1c69551f0d1c6ef92887d70
+02379f8b49c069e1a14e4fc371b84aa46e0589d6b77050a51fa888b20de13a7f
+f7bc1ca4d9c8a3ac7dd2c53f3829c459bf656fef033a1c2e07942e573f1488f8
+fafd7c0ef34504324578f48f22bdcca6b87d3a57a80ac6a9359b9559ba1ba599
+e0f5d057bc2ea677d16506f272387801e5717afad3c27d29c56e6f491496d399
+951dbfd636ec1d0a164350cad1f0a69f097ae28447520e6d3ce4dd18cb7ce33e
+b1707faa90c8d2853c98f3deb845283b119a3f626ff8733d1ca23367b617e24e
+6835f35622b8a7f0a3393cc95aae42dd81d51cc31de0fd70aa0a2c4d9f7dc540
+6038a51c740da0a594613a563e0290493e1cea0f45b98334711137ecb309ce1d
+9426f1fb57ce97b8a50cdfc98da236cd6c12404e0d9a27dbecfe53bd4e70ecc8
+55d02d7484a0e86dd43b28722b91ee46e47af72cddb478692b0569cf0ea19f8d
+48a809c673c51d8acd8c8de0877bf5addd82ebd7ae39260dee46627b99e5f35e
+61d251ca5cd28071a241e6e31dd1cca9d6c92aeab9bfb705c90fc02fa59d0721
+2e129f22a54b5a80cd9993eb6b10c0a8f3eb7abe2b47f5d2cc64c9365a083864
+c7acbe0e490196575368ffe3cdb08a12cb99466c0c77423fd1592033591e04ba
+193d41b5c3ef5c85851f4ab1b3b5fb8a8f90575e2377362e89e35915de9166c3
+eb4c463ca22eac43632f8f5048343457e9bb0bbce83a67c4f3c34a74341622a1
+daff5bbe42272e24b29056ea9ab29b5dd70b9aa985370989ff1502d20b715890
+22b400207ffd843e7aec2ec2cbd6d53159e7252f1c60314ad5164f903862972b
+d4f3bf876293ee9de770ae8a940458d75ed0f392a7fc93682223cee31d257d32
+a0ed984f000cf909cba32fddc9c9ac78c626105f2c0bc8abbf3f3f50d312a342
+825ca691eeaf5c2373892742050620e26ce1c1e81fb88c8ef089a1fbabb66448
+08e2a544c9756812b03513048e7ae109e9989aa87facd534ad633c15e440db49
+538d67388d4f47b8ee58da756dfb913f2762610044fc375849a4aeddd9cf8adc
+7b11c5921e69b8544ad1fa6ff1f7da57912f1473392a64312b0132e657bf788e
+87b0b1cb7b95066f491834c1f3f01afb6bc9e6e95a8a3a7b4cd3177ff0d52f4f
+a6746ac64f664e61e3d1d041fc71ca5379c831925b714461b3203187e44a2542
+a88bdd638069672b79a708aeea9a12ab17fd7baebfc898182d4df64404dce9ca
+0db7d0fb2b4262b93d1ec21bf00a428fafc96fb410cf1d5d2c30a8cefd374e93
+8e2218f82bc6b653705ff81ff03dc98dc90dd7249183521e1dae62429fe6e4ad
+2d48037c916139c029f0d9ff9bb47ecb5dd4c0e3af9ce746077cb4a16759c62f
+a03d1c762fea0edb027741537fbdad74b2aee95828218c8c6358ebe019f14782
+711ea5dd1cd0884c949066bc35af77e89a6760fc7812feaf34ff34c14b6cd124
+1802816711243b32c875a8b0c5fe04212f9dac427dfaa04a4ae614111cc9d490
+11421e2188d4b46d484edc1f346f22fefeba6ed504952fa53b33878512b7f364
+a54098f99bf02a7a143ae21a0e05809ee66ba2f712fa9a270c307fde43587f14
+0c3fdc1a5c92bba34cc7bd69f84771e7a979601e71428b9e8ff91e7a104552ff
+023b3bf5fac6a8518ee80de4b3a41e443cee431eaa6e701b839b2ab5b42420b5
+cc073fa309af6fd9023c642316785bbd56d49f4ba60f96248a8991d3287455f3
+a24b3cf2b9e1c2639e8dc4a33dcc4f652afe949e8dfe50d3dbe6fb075c63e5ef
+454e182ce3b29aa1942470b0a223d6070dfdfad119fbd9cd86d52d34d0261bd1
+14287adcbbd45689d25c04cc29edb30f8f2bc8e40499436fa09b33558a8f3c5e
+ae957a764471b46c353396802418c1a13f3701b7847ed3749bcb619a95ec5546
+500832b21119374cec8b831a06969cb0534892707b3c8b8d49354bc2c9e87262
+29a45c4d1a1240f45efb271b7710418501030ece1a526557364f65591d34daf8
+2ecc2c67e41643ee4d3a1b1c27d2d608396b68de4293d2df2e061faca97456e6
+051f0a7a60641592f2a83846c157bb42538bf0be3f31b27e24f6c69ca6575485
+c108938b16d30b2a13bbaa2fea82ddecefd85b3c0e52a0a200f63a7c5c6526c9
+5b5c1d60dcef4e90866a824a1dbf3e0cb67eb95661dee5f17aaa146d04c99c8e
+eb8517229cccf5d0a5f3f43f21ef18ca68520684f4761fed62894555e05fb132
+227566441065679a17fcaae3a15b019606f3ea941b0b78e2fbcff48c0de253ea
+61618f5db64098bfbfe1f4a6e05ff647c703a00b74854bc4a5a60dd1672a7e66
+44add97c02f2d128a3b15363ccf61c126438aa96c826b2c0577402fa56de3cb7
+00feb43366991297b770fe2929bde6d1844e6b984662db62323138662c9b51db
+43dac961a766a410c13eb45ff6422d6f9fd69944e1d81801b19bb38a2f30fb54
+e8deb99a10dcf354e4065c587c51feaba35d45b6a3cd3333a5d8657ce0e7bc34
+f0729cfcd090b1ad620934a99d06adc5705a4bd2d2d57ac2e82a35f5e030eb1d
+9cb217fd3190461954921f1b5be6e6d7337cd694ad30d7a3e10f672b2f74a717
+346cf7fd86aab5ab941b926a243c6aa7b65fdca52aaddfd6884cc1fd7e0f4a2e
+d8ce9c4921d6fdd4c57dc64a250c2dc886e74e9bff336b8c7030ba4a539ff79a
+eb67d21bf9fec6d9ee9af47b3dfe95a44c201836d17e7e08a3bfe561908b7008
+bdb306831f8bbcd7e675f7db95ef50d66ecff44dabdfe6e89972cf016b915b6b
+e3d1aed962e48afacd57007efcfcafb0b4d245ae4c579676d98c1b21855fbf9d
+c092a99f788b140c59d0288560c53c6522cffcaa9223c2ce88b8fb8a7ad5ee45
+6d0dc8953f306f6913d3be67c54a113eee14ca9600b7d6b5cd99f2ea18cf4984
+94bd0d5ee0cc10c95c836337733f1730be33151383d7946afbc24e2e2fabd346
+99ffdc3d1b432890b662126c09dc56a45c6491b580dd5bc4b2a7f464fd7b00ed
+fb8d38ac9ebfb8f196a6549161931d723151d3aa180f77fe9130e059e12d2481
+fca6ae50a370e226998e785ec9c5b7dcfcb23263ee7bb621da05eaa6fcb806e7
+f3d0c20bd10b0b2fae3ea4bb4180ae2174310a283c03f5c7733ac937a07198fc
+f4cdac0c218c483533fdd15627cb3c93296b714159bbb1594c3c3ea59ba09185
+db3b2227ac0212da4c2a01ba24c41aa1a075e42117d70bd220b8f03c27f6602f
+9561dc8fad0e5e16c1a035da4edaa1c8255cd36340a0d3ee2731ffa65be2037d
+53dc9c6bc9462c30449f4df70c19981d5d144895518bee4258934399f91fc181
+ab0bf02e7debd2d7fc43f9e0d3cf5d3c816a9c10398b3336eb17cf6c3ef20f3f
+d1666cdfb8645f4f2e5f554a4036e789dc98eadc0d06bf99c7daa4203a0a3e77
+30044bd22f2ed02193191fae5ece9a623c7c9b22442fc2f2274da08a5708f0d6