From c849e26560857f8c34adc734933c1c24a7d0a0c8 Mon Sep 17 00:00:00 2001 From: Jorel97 Date: Mon, 1 Jun 2026 12:38:58 -0600 Subject: [PATCH] Add repository reproducibility bundle guard --- .../README.md | 17 ++ .../demo.js | 61 ++++ .../demo_video.py | 46 +++ .../index.js | 272 ++++++++++++++++++ .../package.json | 13 + .../reports/demo.gif | Bin 0 -> 56156 bytes .../reports/demo.mp4 | Bin 0 -> 42990 bytes .../reports/release-candidate.json | 23 ++ .../reports/release-candidate.md | 21 ++ .../reports/release-candidate.svg | 12 + .../reports/risky-candidate.json | 136 +++++++++ .../reports/risky-candidate.md | 36 +++ .../reports/risky-candidate.svg | 12 + .../requirements-map.md | 14 + .../sample-data.js | 171 +++++++++++ .../test.js | 46 +++ 16 files changed, 880 insertions(+) create mode 100644 repository-reproducibility-bundle-guard/README.md create mode 100644 repository-reproducibility-bundle-guard/demo.js create mode 100644 repository-reproducibility-bundle-guard/demo_video.py create mode 100644 repository-reproducibility-bundle-guard/index.js create mode 100644 repository-reproducibility-bundle-guard/package.json create mode 100644 repository-reproducibility-bundle-guard/reports/demo.gif create mode 100644 repository-reproducibility-bundle-guard/reports/demo.mp4 create mode 100644 repository-reproducibility-bundle-guard/reports/release-candidate.json create mode 100644 repository-reproducibility-bundle-guard/reports/release-candidate.md create mode 100644 repository-reproducibility-bundle-guard/reports/release-candidate.svg create mode 100644 repository-reproducibility-bundle-guard/reports/risky-candidate.json create mode 100644 repository-reproducibility-bundle-guard/reports/risky-candidate.md create mode 100644 repository-reproducibility-bundle-guard/reports/risky-candidate.svg create mode 100644 repository-reproducibility-bundle-guard/requirements-map.md create mode 100644 repository-reproducibility-bundle-guard/sample-data.js create mode 100644 repository-reproducibility-bundle-guard/test.js diff --git a/repository-reproducibility-bundle-guard/README.md b/repository-reproducibility-bundle-guard/README.md new file mode 100644 index 00000000..1eb8736a --- /dev/null +++ b/repository-reproducibility-bundle-guard/README.md @@ -0,0 +1,17 @@ +# Repository Reproducibility Bundle Guard + +Self-contained SCIBASE Project Repository & Version Control slice for issue #10. The guard checks whether a scientific repository release candidate is reproducible before a tag, DOI export, or public publication packet is treated as ready. + +## Why this slice is distinct + +Existing #10 submissions cover broad repository ledgers, branch protection, component-owner approval, semantic tags, external reference pinning, notebook-output diffs, fork provenance, release signatures, restore rehearsal, automation credential rotation, artifact pruning, Git LFS pointer integrity, review-decision provenance, and release-note claim evidence. This module focuses only on reproducibility bundle readiness: required manifest components, SHA-256 integrity, executable lockfile evidence, pinned runtime images, data/result provenance, release metadata, and export-bundle completeness. + +## Run + +```bash +npm test +npm run demo +npm run demo:video +``` + +Demo artifacts are written to `reports/`, including JSON, Markdown, SVG, GIF, and MP4 files. diff --git a/repository-reproducibility-bundle-guard/demo.js b/repository-reproducibility-bundle-guard/demo.js new file mode 100644 index 00000000..02a5c09f --- /dev/null +++ b/repository-reproducibility-bundle-guard/demo.js @@ -0,0 +1,61 @@ +const fs = require("fs"); +const path = require("path"); + +const { assessReproducibilityBundle } = require("./index"); +const { releaseCandidate, riskyCandidate } = require("./sample-data"); + +const reportsDir = path.join(__dirname, "reports"); +fs.mkdirSync(reportsDir, { recursive: true }); + +function markdownReport(name, report) { + const findings = report.findings.length + ? report.findings + .map((item) => `- ${item.severity.toUpperCase()} ${item.code}: ${item.message}`) + .join("\n") + : "- No reproducibility bundle findings."; + return `# Repository Reproducibility Bundle Guard + +Scenario: ${name} + +Repository: ${report.repositoryId} +Release tag: ${report.releaseTag} +Decision: ${report.decision.toUpperCase()} + +Reviewed ${report.summary.componentsReviewed} manifest components and ${report.summary.bundleEntries} bundle entries. + +## Findings + +${findings} + +## Release Criteria + +${report.releaseCriteria.map((item) => `- ${item}`).join("\n")} +`; +} + +function svgReport(report) { + const color = report.decision === "hold" ? "#b91c1c" : report.decision === "revise" ? "#c2410c" : "#15803d"; + return ` + + Repository Reproducibility Bundle Guard + ${report.repositoryId} / ${report.releaseTag} + + ${report.decision.toUpperCase()} + Components: ${report.summary.componentsReviewed} + High: ${report.summary.high} + Medium: ${report.summary.medium} + Low: ${report.summary.low} + Synthetic release packets only. No private data or external services. +`; +} + +for (const [name, candidate] of [ + ["release-candidate", releaseCandidate], + ["risky-candidate", riskyCandidate], +]) { + const report = assessReproducibilityBundle(candidate); + fs.writeFileSync(path.join(reportsDir, `${name}.json`), JSON.stringify(report, null, 2)); + fs.writeFileSync(path.join(reportsDir, `${name}.md`), markdownReport(name, report)); + fs.writeFileSync(path.join(reportsDir, `${name}.svg`), svgReport(report)); + console.log(`${name}: ${report.decision} (${report.summary.findings} findings)`); +} diff --git a/repository-reproducibility-bundle-guard/demo_video.py b/repository-reproducibility-bundle-guard/demo_video.py new file mode 100644 index 00000000..54235b4e --- /dev/null +++ b/repository-reproducibility-bundle-guard/demo_video.py @@ -0,0 +1,46 @@ +from pathlib import Path + +import imageio.v3 as iio +import numpy as np +from PIL import Image, ImageDraw, ImageFont + + +ROOT = Path(__file__).resolve().parent +REPORTS = ROOT / "reports" +REPORTS.mkdir(exist_ok=True) + + +def font(size): + for name in ("arial.ttf", "segoeui.ttf"): + try: + return ImageFont.truetype(name, size) + except OSError: + pass + return ImageFont.load_default() + + +slides = [ + ("Reproducibility Bundle Guard", "Project Repository & Version Control #10"), + ("Manifest", "manuscript, data, code, notebooks, results, protocols, metadata"), + ("Integrity", "SHA-256 hashes, lockfiles, pinned runtimes, provenance refs"), + ("Decision", "hold release until the export bundle is reproducible"), +] + +frames = [] +for index, (title, subtitle) in enumerate(slides, start=1): + image = Image.new("RGB", (960, 544), "#101827") + draw = ImageDraw.Draw(image) + draw.rectangle((44, 52, 916, 492), outline="#22c55e", width=3) + draw.text((80, 124), title, fill="#f8fafc", font=font(40)) + draw.text((80, 206), subtitle, fill="#dcfce7", font=font(24)) + draw.rectangle((80, 326, 818, 382), fill="#166534") + draw.text((104, 342), "release only when reviewers can reproduce the exact packet", fill="#f0fdf4", font=font(21)) + draw.text((80, 438), f"Slide {index}/4 - synthetic reviewer artifact", fill="#cbd5e1", font=font(20)) + frames.extend([image] * 14) + +gif_path = REPORTS / "demo.gif" +mp4_path = REPORTS / "demo.mp4" +frames[0].save(gif_path, save_all=True, append_images=frames[1:], duration=120, loop=0) +iio.imwrite(mp4_path, [np.asarray(frame) for frame in frames], fps=8, codec="libx264") +print(f"wrote {gif_path}") +print(f"wrote {mp4_path}") diff --git a/repository-reproducibility-bundle-guard/index.js b/repository-reproducibility-bundle-guard/index.js new file mode 100644 index 00000000..f5e864f5 --- /dev/null +++ b/repository-reproducibility-bundle-guard/index.js @@ -0,0 +1,272 @@ +const HIGH = "high"; +const MEDIUM = "medium"; +const LOW = "low"; + +const REQUIRED_COMPONENT_TYPES = [ + "manuscript", + "data", + "code", + "notebook", + "results", + "protocol", + "metadata", +]; + +function requiredString(value, field) { + if (typeof value !== "string" || value.trim() === "") { + throw new TypeError(`${field} must be a non-empty string`); + } + return value.trim(); +} + +function array(value, field) { + if (!Array.isArray(value)) { + throw new TypeError(`${field} must be an array`); + } + return value; +} + +function unique(values) { + return [...new Set(values.map(String))]; +} + +function isSha256(value) { + return typeof value === "string" && /^[a-f0-9]{64}$/.test(value); +} + +function isPinnedRuntime(value) { + return typeof value === "string" && /@sha256:[a-f0-9]{64}$/.test(value); +} + +function normalizeComponent(raw, index) { + return { + id: requiredString(raw.id, `components[${index}].id`), + type: requiredString(raw.type, `components[${index}].type`), + path: requiredString(raw.path, `components[${index}].path`), + sha256: requiredString(raw.sha256, `components[${index}].sha256`).toLowerCase(), + bytes: Number(raw.bytes || 0), + versioned: raw.versioned !== false, + provenanceRefs: unique(raw.provenanceRefs || []), + runtimeImage: raw.runtimeImage ? String(raw.runtimeImage) : "", + lockfiles: unique(raw.lockfiles || []), + exportTargets: unique(raw.exportTargets || []), + }; +} + +function normalizeCandidate(raw) { + return { + repositoryId: requiredString(raw.repositoryId, "repositoryId"), + releaseTag: requiredString(raw.releaseTag, "releaseTag"), + commit: requiredString(raw.commit, "commit"), + metadata: { + doi: raw.metadata && raw.metadata.doi ? String(raw.metadata.doi) : "", + schemaOrg: Boolean(raw.metadata && raw.metadata.schemaOrg), + dataCite: Boolean(raw.metadata && raw.metadata.dataCite), + license: raw.metadata && raw.metadata.license ? String(raw.metadata.license) : "", + authors: unique((raw.metadata && raw.metadata.authors) || []), + }, + components: array(raw.components || [], "components").map(normalizeComponent), + bundle: { + archivePath: raw.bundle && raw.bundle.archivePath ? String(raw.bundle.archivePath) : "", + sha256: raw.bundle && raw.bundle.sha256 ? String(raw.bundle.sha256).toLowerCase() : "", + includes: unique((raw.bundle && raw.bundle.includes) || []), + generatedAt: raw.bundle && raw.bundle.generatedAt ? String(raw.bundle.generatedAt) : "", + }, + }; +} + +function finding(code, severity, sourceId, message, remediation) { + return { code, severity, sourceId, message, remediation }; +} + +function assessReproducibilityBundle(rawCandidate) { + const candidate = normalizeCandidate(rawCandidate); + const findings = []; + const componentTypes = new Set(candidate.components.map((item) => item.type)); + const componentPaths = candidate.components.map((item) => item.path); + const duplicatePaths = componentPaths.filter((path, index) => componentPaths.indexOf(path) !== index); + + for (const type of REQUIRED_COMPONENT_TYPES) { + if (!componentTypes.has(type)) { + findings.push( + finding( + "MISSING_REQUIRED_COMPONENT", + HIGH, + type, + `${type} component is absent from the release manifest.`, + "Add the required component or explicitly hold the release until the research packet is complete." + ) + ); + } + } + + for (const path of unique(duplicatePaths)) { + findings.push( + finding( + "DUPLICATE_MANIFEST_PATH", + HIGH, + path, + `${path} appears more than once in the release manifest.`, + "Keep one canonical manifest row per path so rollback and integrity checks are deterministic." + ) + ); + } + + for (const component of candidate.components) { + if (!isSha256(component.sha256)) { + findings.push( + finding( + "INVALID_COMPONENT_DIGEST", + HIGH, + component.id, + `${component.path} does not carry a valid SHA-256 digest.`, + "Record the lowercase SHA-256 digest before tagging the release." + ) + ); + } + + if (!component.versioned) { + findings.push( + finding( + "UNVERSIONED_COMPONENT", + HIGH, + component.id, + `${component.path} is not marked as version-controlled.`, + "Commit, tag, or archive the component under repository version control before release." + ) + ); + } + + if (["code", "notebook"].includes(component.type) && component.lockfiles.length === 0) { + findings.push( + finding( + "MISSING_RUNTIME_LOCKFILE", + HIGH, + component.id, + `${component.path} lacks lockfile evidence for executable reproducibility.`, + "Attach package-lock, requirements lock, renv, Manifest.toml, or equivalent runtime lock evidence." + ) + ); + } + + if (["code", "notebook"].includes(component.type) && !isPinnedRuntime(component.runtimeImage)) { + findings.push( + finding( + "UNPINNED_RUNTIME_IMAGE", + MEDIUM, + component.id, + `${component.path} runtime image is not digest-pinned.`, + "Pin the container/runtime image by immutable digest instead of a mutable tag." + ) + ); + } + + if (["data", "results"].includes(component.type) && component.provenanceRefs.length === 0) { + findings.push( + finding( + "MISSING_DATA_PROVENANCE", + MEDIUM, + component.id, + `${component.path} lacks provenance references to inputs, instruments, or analysis commits.`, + "Link the dataset/result to source instruments, upstream datasets, notebooks, or analysis commits." + ) + ); + } + + if (component.type === "metadata" && component.exportTargets.length === 0) { + findings.push( + finding( + "MISSING_METADATA_EXPORT_TARGETS", + LOW, + component.id, + `${component.path} does not declare export targets.`, + "Declare DOI, schema.org, DataCite, or repository export targets for discovery." + ) + ); + } + } + + if (!candidate.metadata.doi || !candidate.metadata.schemaOrg || !candidate.metadata.dataCite || !candidate.metadata.license) { + findings.push( + finding( + "INCOMPLETE_RELEASE_METADATA", + HIGH, + "metadata", + "Release metadata is missing DOI, schema.org, DataCite, or license evidence.", + "Complete persistent identifier, discovery metadata, citation metadata, and license fields before publication." + ) + ); + } + + if (candidate.metadata.authors.length === 0) { + findings.push( + finding( + "MISSING_AUTHOR_ATTRIBUTION", + MEDIUM, + "metadata.authors", + "Release metadata does not include author attribution.", + "Attach author identifiers before the repository release is exported or assigned a DOI." + ) + ); + } + + if (!candidate.bundle.archivePath || !isSha256(candidate.bundle.sha256)) { + findings.push( + finding( + "INVALID_EXPORT_BUNDLE", + HIGH, + "bundle", + "Release bundle archive path or digest is missing/invalid.", + "Generate a release archive with a stable SHA-256 digest before tagging." + ) + ); + } + + const missingFromBundle = unique( + candidate.components + .filter((component) => !candidate.bundle.includes.includes(component.path)) + .map((component) => component.path) + ); + if (missingFromBundle.length > 0) { + findings.push( + finding( + "BUNDLE_OMITS_MANIFEST_COMPONENTS", + HIGH, + "bundle.includes", + `Release bundle omits manifest paths: ${missingFromBundle.join(", ")}.`, + "Regenerate the archive so every manifest component is present in the export bundle." + ) + ); + } + + const high = findings.filter((item) => item.severity === HIGH).length; + const medium = findings.filter((item) => item.severity === MEDIUM).length; + return { + repositoryId: candidate.repositoryId, + releaseTag: candidate.releaseTag, + commit: candidate.commit, + decision: high > 0 ? "hold" : medium > 0 ? "revise" : "release", + summary: { + componentsReviewed: candidate.components.length, + requiredTypesCovered: REQUIRED_COMPONENT_TYPES.filter((type) => componentTypes.has(type)).length, + bundleEntries: candidate.bundle.includes.length, + findings: findings.length, + high, + medium, + low: findings.filter((item) => item.severity === LOW).length, + }, + findings, + releaseCriteria: [ + "Every required scientific repository component is present in the manifest.", + "Every manifest entry has a stable digest and version-control status.", + "Executable code and notebooks include lockfile evidence and pinned runtimes.", + "Datasets and results link back to provenance inputs.", + "The export bundle includes every manifest path and has its own SHA-256 digest.", + ], + }; +} + +module.exports = { + assessReproducibilityBundle, + normalizeCandidate, +}; diff --git a/repository-reproducibility-bundle-guard/package.json b/repository-reproducibility-bundle-guard/package.json new file mode 100644 index 00000000..b0cbbdfb --- /dev/null +++ b/repository-reproducibility-bundle-guard/package.json @@ -0,0 +1,13 @@ +{ + "name": "repository-reproducibility-bundle-guard", + "version": "1.0.0", + "description": "Reproducibility bundle guard for SCIBASE project repositories and version control", + "main": "index.js", + "type": "commonjs", + "scripts": { + "test": "node test.js", + "demo": "node demo.js", + "demo:video": "python demo_video.py" + }, + "license": "MIT" +} diff --git a/repository-reproducibility-bundle-guard/reports/demo.gif b/repository-reproducibility-bundle-guard/reports/demo.gif new file mode 100644 index 0000000000000000000000000000000000000000..870cedb658778787e1429bb96101739283ec032e GIT binary patch literal 56156 zcmWhzbySp37k)Qjm)sZWUb<5x6oFlk5)l!RmXelk5O?X42I-bgX;D}@Mf`~figb5_ z#eRP0Jagu+xp&Szcjnfkp`|XbU`2qTp-}*E`RmW&-_wIXCwsq-c7Gkt{n_~bd;Q|) z@3V`aC+C+tKM#&i&$ll3H!t@#&UaVOww6vd4vtQ@4-OWO*B6e~ejKiB?;fmg?kulu zE-bHo`?)rAx$^a5dHQT=>SSU1aB+5T@zcTF#O~~uogY(M-zPU_#c) zJi7ef;L3l4OOxN{muJ2&e3_a1@5}7im!*M)k9~`ieLp@B=El0djl7>7dN(uNF+DIo z^<(7o!iUMJp-(@CK78pP8gHHIZT{TdG)d?h{?a(sUHzf0VyvZZbM6i-t~=l5JsBckG6I8w7w-&^|!z7ZmxdYmET{T(_5KED9`A6UD#3I)cUTb zwXdq7BfqUSucapYP37zA=EADhqVk5^vNw4}m9L8GGILAPyGoNg3llr?@?X>?2iGKczK%@GtBNbgP0lV)$tq5GRr>ND(hK5}vm?7jR@Nt>=$VC6x*r14{;Lvz~d_usB7%yCu%Zm`d;0WKK z2(Q3!_kbv;;2?*L6Iy8wSTzi@Y-7jE7mPChT3Jwxo>g6yC9***(;>f-m*$;Z~o z`(B)_c8s-FjFo1z<()`#Y`7^V%tSfV$i~O#QGk=Bho`xVhqa@ZrJaX~gRA0;M+(m$ z$_77>3Dgz!))4Z%!|#sebHi{yQ%1Yo=5V^j>ZrhMFUMpjYxdNQ;i-(djhnHxyRoJ7 z!zcC+%^V+^+UptFY8zSHeQ2ruz)VxmOij;7P1jge`>~3K!EG&l#XApfV)YbMbmf(G zWU+T;l(lZ$zAJM}Q%X@?`lg1I{2eiQthlVIm<(1}Mny3_2QW2~)yp&JLI;LvGrSn7+W z6|op^Z(JEl;<=lz)A43)Ec3ea{CG#x#>Ya{IF5U7o3}n!Jgm0(@U~^=YlF>L{=LrD zz3=T_JM$kp+YS~8VHBLY@7j-6hEqkJOuXwj*_bT3TcG>??b*&ulk>vF`_7Al#lAQq z=l!mCKTkG4S3mjK_5Sz8;mTOS{qC;6zb{XA7Cv@&6Nvz+;35vr;IN2C@>eW|Qp#>F zhJosWOW|~e4oeYCb`?vJY`&XIQRqm)lG^ry*HLt5>-frR+H2i99NSy`72jbbY!?+qX%zU@jURg#8 zt!LV1#H>EDE2~`3c4^&O&v73V+Q{{ucHGGG*Nw5u4?f@8D8P{lZx)6#IBga^-k*gh z##ddG6u(q=nlCYYAiVW@(O5gZEYr7&y<8u^y;U(4L!Mq)TDHwrrQ2AwT|L}E98Iff znEqChnDnj6*|S;r%T66(`CLT5kJP!wWq>7pw{iSUtLTG|vLdyPpU5BWHP3|lis^l~ z+o`qt@r!Q1ZB<`Z{QgEpb)C)D_SF8{L+*2N-IGD*ddstKX$SBB9Jff^Bc6*im_x=4 z4hhIUA4wewf!ziZs!qD2KDyK!Qg<02*EBw6uAVv?MBAK6Y4b$6cviF!UYXw>EaKx82bAa`I8_K;~3agR$28o>tV<>3@3Nr>7bZHJm&PptJrN5V7Naku z#O)uSew+L~o!NPQyYajI!EMag3yF}`A0nn#morg`SHF;zAFqDb7ockY9HI_F{_ZX$ zD*yU*AQ3{mI^h6dnM%Km$8d1E9{}ylI}&Nh0P5hvzaUa(MN2P`=3U{wv_B0auo#A> zTtd*I@eGQ1)R^FytO^tPt9Q`wDYT}5O8d*`cZXq8Y)D=e2kOu{5Kyokxk*&h>?g5Y zMA*wmDu=)6MYZZhDZ0cc#^a*|Y*nCS?EqzQVYGwjk&BoanczhI(8g=^uZ2zmI3|ow8E6MGH;~tqmj`U?fT@L zxqMorWB{j(SJn`dI{yS30$N*UDt+RUd)SMhu`8s^L=H-Y9ucF()X?FQ4jO#MOqDje ztMLq$NM&*wtW9uAp=?i?`uc2=V0dZzoGEMby zUEz8VJRs_|=()PtOQaR^@fck14f+Ckhsg|$Cn4IR$>W(2SS*beUT=j`B3cD*sYhDF zVOx(m8)TA{oV%`5g5D?eGnk;~7&IZ*ey9y!p8#M>ZwuRrle@w+*9LXbaE_eJeW*)k zgbtw({dINg296a%acGHZR~(kTv#ntRdNNG`R%qJdgc7I<4V9yasx=u7zFC4!WY-KJ z>;3LY4rhzKgpgiK!V9SNvQx~u`tcl^*Tl+o!eaJZoP)m4>8~QtY@}-3JuoG~l^(sh z8Vr9h_)HQ@F5aNRU_MErgPcMS=e_pKqJV8MsP)g295_BpGl{M-ySd7BW^$;n2F;sn#4aC>bBLr`V|qCTSW;@7b5YV)+PLZd;=H<75`RPvPy{n@4d21ZUsIfo7>2<((?T&< zY!+a)ADaHWM_KmhKDPy-2+?z$aM|3?Z9##c7^f-(3ZmXbd*=$r~ zS;QJ*Zj8P8z#V>~?0rwo;`bwsMCliXeU z)F=~|Bq^>+EAK(XWyu^TQD?9UPv!9V;boYTC7hRbk}?cnOMwYECs64odAp_j0J-=$ z0!r8_9fuk)^?|s0TL(`$yi|Zluz2@FX;F z>^7{0W z-r@&e1q{>8-s|!u>}S#H%t`M7m(!zVFS;cXjwPzWzQ1J*QI`{)TiPuQaCTDhcbGSn zI7@l89+EAD;@hLxB-mn!h{W4)K8YmqyFiuLaJbw)7qzbcY;Pp0dYSpapQh`mu{2&~ zX2{~aNfo}%jkmchi&SCD+I@+A4E~~BsG$u2u#yb?!DGB)MIe)0 zNUh%klAeE#>v;PDlkXcufMdzrkz>B$g43STm!9Y;H_=Q8x|9koMJd!C3jY+!<^7y{ z4aW(`lS<*yYT=YeaI`no@~a3bByc_2QPd~mILYgV9LV7h+FoLWheO4YIK^wO)XClt ziAcZ{jUsJCa83mvAE0#G42gPHRI;JG?fS`I@IpvW&Ts(l08Rn15|WRgjW`;dF?@+C ztUR)}JR(pN^arr5exOP^a8>4T#)$8FYMIvZgc%V?Tnr>hb_57yh$V0PLvR(YV~WG~ z$c3nD1m_^J42$8g9v@CPIeaO$K^}awY0rHp2C$4l;A6CBKyf3Fe*xxn26aA+`h$Lv z+!g_&AuZucBz+JKxQCv|#Ud~X2#*B##bX9u8MqOcV04$^5LqMW;Ogs2RuslrYC154 zLpHi|(mgJ|#Qb~=F5?1MNwI@IE}Y@Mq{(p-MsWe{Q5EN5WKxt`G0I)#7?Ml2-) z?m&%gyk>O#s3!PJFZI49I00bwG&~cd0e^SY*XXE;!I)3};0%C`KXe&hPa%P%#?BaA zxhInsB?E+H$|9}T5n!5zrg%qUn>-i{l8E7w5tyJ%f;ZYA#r`s#j4Q*fKj|s$HJU7S zNlDWB$qZ5{s&5Y9$HF)UBp~k(j$e|8BC*kSU?FHj{wa;q8wsVM%+3M}6*4559IOnG zep6xS)ff`4BsR^o8vC>ZO>o;Ez{rDw2pEXbUH8@^ z5zghSV|xEkJm)YN+X{>*1bzA$pl;;eVq84pp97<@f@hI2n^#6>U$gL<1eJnx4 z{BIpEA4hi!pB@pS_p|vWMii`rU8mM~QNk1aUb}9=u zNwI2ypn6qwc%?MeERD$qDiH_pG)Iwed1;%Z(DNITeL`^jZ_tlmi<`_AsEz<{i=l@HIU)!Bp;RCKdQ+q0~cQb z6u(fh0G4bAq$jpMC2MQ|aJBQX0nNliD!{2GCJ3Y=2RZ}5QlH^YLT`$=#sQtDxIF$o_?MzynuK8u%4dv>9(oorxW)St-d4*_l zjou4hVw!(-?XP=~LkIvm4;qt&Eb4?0)jiqH?-%F+aE&BOC}sd=+7L(3BoG(L(FR%P zqn)1+?_O!QQ5rTrxn)4bRT_1-2YHllAJ>5FX@wmT$nZU$V}yom8t)6(@x^!~xO>^AFo{qWs0FS8*dou?*>w4ynB6iW%or;dN+i(MTdrmH@=nGk0) z@Xv3|x5)PHKPWEySfmt{O*{(LV~JdR|J}Dab~ygOkx=i}sKxRQ7$k*^kW83?&I^L0 zI2V7dmYCg6L6hM(8Q}IMEYB(R8a}8X#^sv(Ftlg_Aw|769^shN_wYAr)n#G_H{tmk zr7}w(dw`r|BU#S{N6^pg(GwI)R1r08B5c_x_D>dnFr#{fn?%LdZ}A{wo-@nec3bUh z=Az*JN1uq2RKvc&7dx=7@GXPhhg?BVoOYOnFYu9X0NE4I)KK^>={1~&YB&ROgB6AQ zt-e+GmPxONh@+-xFZr%A{qWwugC7MIK_x+wJGZEAWC5Puy>V>sqBlB30|Cm&!6Ax1 zavG}5-CmoQ26iu}x!|LpoWYxlpxKYnC+yR+BB0uHBMoyXW) zt;VM^YZXdTUo=p~s@ONg5=bF)Asf^<0e|!=oSrBI22t95b4RTJZc<`R3)@*I=J$VCqLsiOdMl<$l#^7{Lwclrzk*t7htRz9 ztIy`A+rB%jeD3-HZtJDK;e8>1&}kTrsk^6U1s2Oaj~RWhrJS^++2N+9W=f$z^*|h( z3wpY2qk`pJENdLZfDi`*(mOR@Ni4ufVs<{Fr!Gm8=CgbR!{mtS^Nq3Ejcd1;iQufW z$OgCCMpdr4jm2HeA8_&Ok@#McsCzSARjyYAYDSmx|eX%K_Up_9e&6PbNzX})Q)+|kBnFb z%b*NbFj>z5_%ayHa(-Y*nZI+OMz=rruH-KcvCV*$_$QqHg~9FenFMu3 z+@W>VPSS50<$Iur804WSDvt<~N?1aWXow_8T6Z{=x)tyNBo#{n7!F~vlZzxvyNDuc zdR=oiU-QK*a6u2LguBCxCdre0G#3J%G?3{hL5$T-*%bCkKT+R(Vr~vn-U;5^&UaCv zI;C)jD7z!Uy7S}weK-Ua0l*Af(hxnC13Q~Jr{@w4Bmxtl>B8BQdZZQSA+6YG^KLo8oJT5Iz7qJqcwZyDF0fsHR z^Hh@3da#J69!$P}W|(+(YU-i z)U*2T4u4i=`a)cw{hG+SxM*k5`FHN)A4;1m@uR;@jbwxFl(BlLl7~N56D2k!q|QEG z+m>J*Vou|^O$_<;7dX1Vs1iy-#i5p|XVs$zuvwcjJy=$Yr5Cg4&wOChD@o1HG2HxM zRWpU}UcOqE{+f1%n0Z$?^TV<+{u}o5GDb~gy7@#FrCnx&%}IQbg(#unDf5G}dwEI` zERVJgsvePSHwRvGHmoy$A40-vxNG$0>4*F~?ex#oTAY7$MX)~JH+$=|H~P$3?!dh3 z`QIxNHlxGEH$hu0{JBO))`KtEm9OHM>hBGwi#-|4H9lESOIZnAXEQl<`0w?-5|Y2N zXO7dg=G~F(K`X@Vmgc7mgL$SG`$MfCf335dUAiw1bV4O`W-mS0KjbMF#N^g^Z+@wL zGNhaPc4lw({R;%Al9yk@>Og@;fyLj|yyqY4qd1>j1y>v-ij)^TA%I+XgI^-0ER7ic8vigm-AR3%ETOY2cPj1VGwoHDZv}xjSy|hy2*2U^WHAT~3 zP4_W~8xQWc6QO)E5AK+&8oX9#jF9>71IL{heJzQBG^xAyzR5hiuk7q79_4I?YnXNmQc9YSd1r&ODkBofg_ z_Plq=FPC{;yWBO3+|$-FX6c(%)P*0BPg)l`H&JcpDjCjLlB#XS497t$^fc$?O<3CI zGTSlX(X_Jic=AWP54Pr#*@PBfMkfgsCga_~rNWRjctGR zWfb+iGRq_$L;7*hn+-h+w$2Ttuk+0r$gEQ7v86b7B3=U)NU<%D02LM&%w?We>J6{X zI%2w&bp2Wf&J9^Cz}iNEBM}ZvAz>|gMzPtB_M6vi&90)p=qOhr&*aX3QPuHtH~g1z z5ugEPm*Uu_x1(aAY7Mse_{<)RgS&3AqQ}ergf^Tv+`0^xOUA7cXS>9&854eEVIvW$ zixY6$IUlSz=%&gp2KXp7{yZH-jc&jf1U_~NaFaLK7H*F{so4FDf)?Ynrk!lh>L|Dc zyd@n_FL>q{Z{j2IApfAs`Vx|cjsSBL(LB&8?7%Y}Jf8@oJ{9MFAC@L=O%%-IF=&Jm zQ94$>#0GV?89t~x4g4wmXC%8F0dg&H!t8kkrs*B7?S)x_Y09nPWfuD+9y$WGpaB=f zUHK$Ou4NN$B!tGqqZuFW9(lW8Gn5yqctPGng~xQkM&D zBva`*D##z@MDa87OS^oMli4#rnAQ?`k31;lIT=P=jHJ7za!174<0aH%nX%|H(eVa1 z8}}+eb>*%Rp1WeVc^xU@Vi_gE{a;)VohA=wN2sQ*KH4Onjr5M(ptA2#jQHFW?BE03 zZ!);24lPndd-~RL-hWXfpVny5Oc+bPawC$v)2HOux@nQ6-YX>-YQu)a7tO@br`+p3IK{M@Q&8E#~A261MV_uJ12e+F+K#1DQ>3gDh&LfF&OKN`CZ(Mj_$ z32arY-?0W4h%htp*NZZXO5GddFB#C;pPL7<_a-N8Z+qKA8`tl&Wa+8@dI*yTLce$d z65;XHFnFq_UZcX4YZnHtaj$A?k?)i31A}z7ys|sxv6DnTO0F+Fv%}elI62J;79{WR zrO|^V7djklip|c8*MWwd!Il$iWV6-ETSDsy+<8#QSyATfeaCpS)ZurM@6>+LEtnF2#s zsunK@BG+A8>7whTnxP6V){NhcvZ>EGBk1Q3;QB+%k~CbeuB#v^Eu-et;S6Iuo67qS z2+4K6Z{B&;3g?;5ERg!OLw`DYdUTr2cNrpIh7CfTgTS_XR@}!Q_FRK*)k5bUqkoF2 zJWH&eR|2P7N56=95oyLkPce2yw4vjJe$cFr1hm`Un({k2ef&EfC>nxTze8PT`N zH?h`qg{1Ig&!i|F8&)FEIF7$5>nz<)qQ0YoMQ>esR}YZkC=E=vK$akm*EBQ&|8p>N z&!MPw6g%n|dV=_{L7Sz?x};0WV$A3;dex zDL-3*^XBkYgm;pSEBElAobDnC-Oe2D!*7IwYy*^Lpv=2V@*nZ|>-R3Sce#7ZgIe_|M%xXz!eR}X{tk4` zWV4SeFg4bg#`dQe_v@g|b@B#$SOs-~fSFmn6-}b8@9h`&=I2#*Av3gv@_%&2&1j5K zaW_2|(DMc2Os*NCRQ-^XGwOn0J6%wM!0z?v`78)Nvw8k)9kj37NxqO?uY?{c5zbUF zhRxg!>TVWhgNa5vO)5X#>L#YLK;9`sMXQqTz9&7ckCyBSB`9-V=Y8(ju^WU5C3G)} zL@NcM-AwV}@?ChQ#?Xehqd{FoIbDqojp2tX_zERd>djuQo)<=l2G!`01{ORkvc6hC zge}^oJxi#%_f$37(W){OCu{59OZ>?b9iS4a+<;Fp?pZPETS)EYXG6ZoWOdj?&@L)Q zAoKqILfE!n|CEe0H_4IVjh33iz8vk64epcQeUn$&Cm7$Ip3@VqnN5wua_2%4D*HQ9 zvCO%Be|q}#C>4dKFnE<}3lU)4ncIjKx#CE&(wR-J*!v?|sa3N#rlL!ehu!36M^2BN zk5{D7A4I2dYZzL7*OX92`X2&R=%|~;kR5GxAzQ4KS+u93M&*Mc zYsEqv-ht&}jWg2<>08l6$63J3NYleb({@}fd=(`h++XK!=hapg$#<-iV1OMI-6y_1{MiLCTG@1T5BXgzDy&sb<&~daNz2d50uex*{NvA9NmT=#aG-{Mcqqa$6M7ix(tvQ@ zg!P+L1QeBq<01np@l;HRFoN#h)W=V1ec=ipPtAHR;JQD9htCwFpKo%}SdySl5Z1^% z7J!xfwZu|?|7e;nf)9D^<^8BzA8vA23C-ZJLHA5{xFiH?o=Zy4*4*P&A$;au zMD$%lNx^4t!b*}c*6qwFbSPT`3%ZckT9AddBB%O@jZj=%*e5C>id>q-4O;2L0{;_y zU*cGVCsHp0+(~L%|26X5%iz6J=MIH($rsXARGdxe^AWgs=&R&!XSchE>)egLO?|e4KcLE9u$I=VCZ%T7&dG zBcos1q3AA{2++6l1*AoK7%@^`s;S>FG^f-D6u#wWGT4#CMNv|GsIDtcHyKbdjF_qZ zyh~nALJ{uqx$^AWu%-!|%rqC5TSrAvyGHKW5H-4uga7^3_BXjP0_=E6Cg#8i6P&JB z`Cg;P6B7Epo8&*v2%5LgV}dI1n$|{*Gp5z<;h;Q34b&v0&pn_qW2~GT8JHUvi>|td zocJ>L@$a>dw~?Pne*E|H+J8UHdT;#rQcFL@hy42V$IK6!nfK&h(tms>q5t+5@nhfz zah{Ln$C~*9{X7-K;ye5N3VYh}d$ZN27UmD;*CQ;f0_Hbg&rjd5C`Zn3f3f(PIlp%{ zKlgsVY$-g|g zxx}q*O~Gs}t+l}GYyIA2`9{pLK$&$_p0z^9vhcJuL4H~6+ zEtRk6)eToQ#BDWX`8CT{d%#ugLEHNFRh{+Ks+mXyo?p6ptZ&{GYqwTE_V z=B8`f0c(aCYZEV@>Q=5953b=aSIySf(r4BzNbO8Hp7On0v$R`#BD-$8o@31sLuqIy zroL{UVYkI``4STx{U)^=T z$PLSkjez~Nz}5}3!HwYjwdd;_hUXhEl-6(zn|l14q5G?0>YF--n-O)Zk-iQ@&B)DY z277mlb*C~1$NbHBj@6gzo66^#i4!YH3|k8PTPeOPsp^h547bu{ZJv=vW@c<4@ z_113Ju5Z_!Z`YIVG%)Nm^6$Kn-Dy(aX`bGyPB5)8M7Bikv}f#el4^HeY zknS%s>@Owker+}T*I`>V++VZXUng~5Nw8h@-QOzP-)`OCX?5H@PfjQ7@1O4iB;!fF>v5s1*JXmI zbG~O-#W9M4bc?v9Vt?`@#H;b1cWCs9$SbdM z{?l9KJBman)x<4Lgv(t{Z)t?nz555UZ6kL$k);-)fIJC7hS!H1?I2@@aUY5x>tINmel~3MugscjLB>D`K zxy9Z_BFh9JVS>ocko=RNfCS_Ux6mM9QsKyg#63!MltThMNm~{;fDVXc=Y&7o@O3NL zvio@EjKaAroVyawbHvXc-amV^abf?jx<&%Zg^omeG+i;leoOp@_*pQssEEcIXWzydT0(q@DyKh|g+`fB?`O*^sEjt$#Ym z-9s$V5rAb_Og%tO2$ey;;N1-Tia^piP8xtJ2&P^Uh=Wdhv7H*ggA~v=y9U6)8`u11 zk?5pCOn4)7wJ=jyB{>|T$+f!aVc8Q#ScM;6KT-$CyTBB30%_)0qLhG1e}#t~K<_j) zjI^{77>Mc2F4JtXCBTf4Zs|zSmWl!76%e-F1dIDC)FkZYW*#_brr+SO?ZNhJn3P;| zE7Ej2!vONM&P2?35x)k2gfv4{uc7Jh@Ib6vN}cFMRthCos_1PSBUv93=nM;Sd{k<@ z`U|cZl?;N;Np;`hKNQi?5M)Lc%CWpfjFJHb@d0oF`$DMg?7;*9^zL1p%g~gm9x#2S}2n zEisA~xo8v57N}W*z0D0TOb8+cEyJ~vWZkNza+?&n=$E#RBWq$7p;-bIGF5yP^@LNb>bT+Q)3^ zY4q;V;DDZ;Q2lWEWUL;#hnu$#)|n)SCAkHmDAEyy-@bl_yTsFaP*}Ab`~aCTE9uiI zf9El9*Vm65DZUURJxp+q2Pd%z6&bAhZ)odh3EVw>{G5 zKmBTB+PQl+f4u?IJ~kYSEA2%2S0mMqI2c+Usq;AAiYcprF!kJT-i7n3dP4JlY4aDW z#M+F_I90^BD3xB48t_c*++&eBM3-hhaN%w~Ha6};d}IZBZ5 zAECJ*jfJ$R?d0|SkiDjtCOS096_dR@!d&n>bfJ84PaPP+!)#G#Qp9m#k*1>_PK-1u z#RLveph`7=SCJ_H>{!AH&`rY?9(BdkOyW-aBA~W75SvzK-XOC0%M2M$ja?7pVzVN9 z!KBQ}J;}YUI!sLCCLGUMb8R$oUY!ngGgk3NKJehC!pkeeg-c&>L#UbDnp9$CKoWwy zmNvJ%2)Sp1^rKQpfD@D2ugZu(a{Qv2euWwXxs-4q8_%7L)wEY%4nlr@U-)m|h+|vK zK8}`I%Lfb{&~SZ_Lg>^4m?j0G;vR{}Qr>g@%F##ph~PS+LFT1}(B1IA8$qi%ERuAB z)#m&9QQlL05-;qD4G( zFiE5cmt#r{Or2cYI*jZx)Ouz7Ke;|*F-OwRuar*L7u~h)TNpl+Ht~2=8{B^1O7|dl z3qE-ByU>K0ZfYSz&+Deljxl=+@pxqL2eD|OY8(Eh9FD)mi&HatPF1!Km9=A6+yg$i zxY9BeBXRV_P_7SL9}PpW3wKJS^^6~V&c1C%Mh=twn4BVmSKD(GL#imo+BRph(X;7( zAgjBdO~)v>m!$qOMyKMqF$D_FQn59EE-p?|}wQ*Y|`KcdpNd(iOkrt+9Hd zidF2gs~0>Hu~glj`8+DwqAQh%RVRxlm6a+b=(&K!))XndQo?oClzZdIc%BD#?W;?* z0e_HFD&+J`o3{_VK6;gsQKBOU_jaD(X^c)%T&wD1#94p%Jz3p;?EdHPfdU?scstnE z?eJVOy!v9A?DMe-U75QXmF(m2(_RP_VW3}_s8{*H=dzEBpu+uf`t^ZtDOU}Q zexOksKPDOXY@FQj+O*3nVY6kUA;m}`Jr1yg_O)e#j>CZ(TL1N}joD{G{LP$$b3+B$ zvZK!VZ%kCgw)yCL=%8p!{%@V+1Zdc2`dKf`UsEkLi3#5~`N-O5we}Q0lNhMnRZ0xZ zE8nQM&rZ0mMU>nwpuEc(JjE~*Ns|&m1pZNPT5-d0uFgGI=WBDH-y#7zSQFl@i1K_8^}A&CLBpmcnAq!J6;gbUS9__7*33h41E_0xEME z6SnH26oqXI7DcsPxo=vX%qbKMPY7iCB)j~0%|iJ~BR1reamj3BH$RoM#r5R#pfEyD z;TD!~wL5Tq{>hiR^A^tf_roxv=y$>}2?bOSDpRP2Cm-3fn0D)Kq*wZ?3wbf z^s~8U<$~x_58};m+sRAz?%;K|`@d>=UvQ86DV_Hz|NScT21yn-}&g2~Xa!VOK-RMZ;OxVyq=e#pG4~r7W!Q z9$--|ef-Ja9}93Y%Y7+5K!?C$88h>U;xZ=xJRL!X9cogX5MMRj*?O{FYmujDx&Eo( z@6wacd6wkdGbGGts4fvseY`;3T8N6Zlsm&d99E;$Rf823GTz`|kj+`uVqJS?)#J?- zYQ!PA31uq07uaZ9Rk z*8ov`f!6$G1_tm@j^iTE>?rYOJXa`=CUab@e~E2+iCvuA$%mVtx)_TLrB?y$ASojH zYT|UuT>RDsG9_#o0Q)4F&AVh!ks$RFdM{H)Y~EU2A1)M9959R_;r&Ejw=9`IB;Q)h zDw=VZjHp6FIU+vF#s1Ce+MO7&2`hQsaD{an1G*I{ejc`OB@)n8x#N-%c?Mxh;0?rD zNPR$g*^0rCH#}e|0?(y>6{k)eeJ5nq7y>~`UenAd)yn4$G+@@Qo3(Ud-ZIu^#0YVaV4)FHJ=F?-vbUl&2OcqOQrhzh==@0{oYdW-_+ay z$hpI3X!q37k?*l#;sakkqwGfytG+x;SR+hby9j@+C5?d%B(-j$>*XOPiNTSmz;k>2 zpYq5(0X#zmo?|lz5X4UksDBd(RT2zWckmV73?&zgxLFoqofGaV809PIX5rvr!W8}M zX(VZURK8$r*`|GhAWpJ^@n%KrU`71Irpud(hZz;2y@D_I1ryIJ?tj~S87r7{6_)Ue zSdq*jlw!A(RP}GrT@fcPl%`&prYn?gSeb57=}s<`q$HH#Tlp$PC^ND$GofYTO;d|UwCAz||4Xa*TYh^`}wKuBmw(HNU8mL7Y8JumFw?(+B8^uMMWUHIb zH5y3E-zbT+7*@9oZZ|vGHCu?Z`Bt~xbZ#wPZw(RY$f)kH-f6e9YtI+yY_0ALByPR6 z+v=PUc|W~VJ}4sky88XTNcZ{9t7Q@I?doo7(H@4~XsDopVS)nlH#6Z@i*q+*@tqNaaqCOO3ZGZFb@Sn+|s_OsHn_u_jvO|dD%+Aj=M zpQi1nEyTY1KC94whQrlbcbu0(iZSDHytup ztD-JdxJ5&uJi{y}?kHG8^_v5nSs3W78XON}?kDgGdcZb@Xo+LDcQN3@#$XvJ-MEI5 zI|lS>WMt@LjPf8yMf1ICEOhmJuBJ-K8%pqh!=74$a{kEQuOc-bC4Z{I4!(h{3~|vS zZ+Q363;{et8jMW6!Dd*Lq$Hmkmk_a!%>E6I(yNf$E7+)!KmM5SmGtGZ)b@5GuJl-B zap;=zAu};dZnFoZ#B(L7k_;gfMWJ-31X^C~%|#6wFCtcY@i;iGkD50u*g+K~0|gN$ zxXUp9xkJdSLuIqx>wQD=y95rfi8c+!Nr^#4_ec|>xDg(d-Y}^loUEv~s$5ub+KEE> z$xWiF8ba#M=Z0IEUMP1w|6JJfDF~e?j1G4_*j?sk_4Qz0ETw~Yu%@b@a}&i_vqql= zX4D#3`9$W#muZzyfWv2w5~WhOq@zxN*P38(^L z?)02H8bi6+ zqm9C&b}`%zl5W3St$5C5`T+?}ALNOQC55cj;|pa?EG1KmKC8#|J_MsX#*gR1jptl> z3h$-rXVVwOSKh?Ci9w~E2Mzgo3&32)WbYII-Qk>1KFnqa_k5)-gjLQ{M9%AXn>)&1ko9yjNU~VqQ?k{9=(^*N%R&yB#1s|_TJC?yw7>hIqR%7 z|G~Xxt(oh-zMr35rg&_3bnK@K!EV9S?r1sr+R!OAhMo?Vf&MhD%h=*SkYk*5rB2pY zuQSozspxQBQsJEb5K`E=9PD?-NB^9!Uotk-7{o&Z<^+8opXK+frM(vt=~sJ?zLa|Q zI`f%75ly4;6Y*Z-#xB2Z7WJ2qXSH%2!cV%Dl!o!SEIegT0hDfU0x$fe>&2z}qveP? z{a?Kzb@&obF(6IzNMbsgS6ak5*k2{(k6f9O^VA>t_q87lYMm3`ln>)qa7xf;;K=2E zE=PBZj`#$5OR%#B)T6uW2t{?ng-w5pe&!7z?NO@SzmVhWg82Q0TcCf5L|m6Aw&d@> zdRrgvN%%&Px*7LDa}es9S1zEgyT3lb6QR}I4ZS*#Qxf75{}}8iu_OAiTTS-hOwL(} z$g`8(@}~FuFVV6$0>4lC(BX2hP7397xe>|G%nK4&C`Y4jV53mphq?zQr{Xjz|(TB_#0*OF z%^x=$B`v}3O7YzOeu(L@h`Q)HzL4%p^t=9k4x-TVAI(M?H@+L_pmoxQz~gXEn>W1% zFBxtw-;6tvDgini`JnR>y~N_Tnz8|E%c61eWM$ncJWpYSNQ1FS)i%#y1lIY4TU&l z@u7%N)Ch$$UsSD!kT`KGh0>DzTcH6E->e=>Zz$RqcKMpWFF%p6^z%qqomOx_%bZ2pk@B;7AJAYle0UY>n}A zL=|dLp>@OSc3DTCWB(v-+Hk>dO6Wjaja-Z$eT_jW#A;(Y{pWl4fta6!SH&&NF%HQp zHQ8tKbG7m3>ZxUy3x|im_VE?R2}m${k7hlYVNxN!?a0R9N$KR?#SSMDP*u)%e0RxL z-GFO{QfTT6FKYeW{>inaL`Sbl7(FI%4 zF}vfclHhZ|3r1mWiZXQ#yl>9UEe?d5ObdP76-hJ*GConRRhP4Sj~y@Gwd zF7*O?JHM@_L`A4D9)}q8_k%}EL@(5p>^vQrG`RS5yF%05CdZHkAzdTjXukR}&VYz@ zl2B;{bvB9J8xKjKeV8T@!_sb-uI`ESzT)S*6G}t<4;xcYLIFnQhO{o#GqV<6qegR9 zCWs`H-awzYCt58#%y^vbWMv|%6D;_#G<)h1?-+f>4=bPbnkpwUM5#aeynvg0Uc>u| zvI@#cZWi&521T!4UM8#fiC;=9T#@|8CKcD%bNd0b?{^Q8))Q-|OELST@PQr9HU*#} zzJ+_!neQl#9nCf?A;S^1T?mkcJL(B;7`Qv?!QGsN?vp(=Lm@gL2atd@bs^k?B?!=&^2$CbP5lkunMTl=t;K=h>=i*VI* zeJs&cEV4{_pa4n;!1f-87M3Y>+CgL+y9yM_R3P>^ehb;m$Csc{Bujutu#4KB$-~+x z^Wl;F-fM)mG)f&+s5hdiYs6leN(@KGA&(IGr2aI@%p^%L6+Sx1`zU2rfutB6?{$g> z>V`9JvRI?~bt)u{G7pdYJG0Yu>Q0(IkT02w1LX$oM5e0P+wnNn=NoiuG-?uKNyaa3 z(inC#)nty662m(;YVPLM6iAZcfkX~9Xc9AZ6@la=YwgWy#szf^-Q;BHIEQKhGYuV& zM4aq`hJHeF>NTO`J6$tPqnhNj2dPC@&;?DivE=mEfsR*pW?EK9$r)TjjT10G6go)x zLt>&y=j9`(yj|}fQd9F|y#o~aXZ0VbcC#`Ams8%~-d~p`#nB5UNi7hhbhafi*NYSo zjUYH=?Y{vQ4E!!aPDD{KP+3u52x*NknlC&}vu|54HNoX!dTDgwTo`LRyuh*uL3BwsAvETD7~+zQr1yNz+(bjZeeA)k(HV+fmxb zptJp_SoEfyBBxAW1AAtAvq9bTy0nG^N1+_EQIGUbd1nXD6zI(- z64L8S#138bbIfOI(i^IM4xii7TP%#Fe{N_vboa`!SUO7o(sp+EB9z{8jU=P7SM10u zDaUe4Afsv2=jc@-z16O6M)OR=kqd+&jW$Enbbtk>`NkT^Jme^1Ki5%;*nvAwX zpPvD1^iMCxGTP7b9OVB7VX(>o2mqfxAOet&t$`K&e^rw(WD>?p`cEtg!yzqPZ2n6` zI{ynr!e~lczxUSu%TAg(UEMs|`*yfGyT9~(Z+&%R8>1#o{aTqkS;nYI<44~ya1v_o z8-`4p__2W6o*UYk{Rd7O#K1|LQ@!gGeXHX=D`S6SNh4h=;~h(*vkOZYK?wsV4Nv`r zCH*BOjm>q9%y$n?{7oqhw9NH4&Gvnn>Ha+3*)ZApX{@tmths#Tb6fvZ-B9Ppp*9S7 zQrX+|VW|EeM5(yH_TPw7bJs}2*Wu5tJs3XeQ`;c2xxe&leNij2u=yj#PWn$usixs; zNnLaP=PC@Mlv7`Uag?%n!(`!nKD;tVRtMkk2^GZME6jf&wRR6y~rL-yp##BnK zC`u|TfPZ)&@-gX6Wn4l@etdB*MpjD7E=|tJ|A$pdOfQUipB0{$8lIWriHN}9N*Gq@ zUF!SDN@~$h zF`$y--=LCAsEJgtp?DDVQGlM6#|txOck5?9BEGu3uT;5SDq|caHV^s#fhbWsiJ3S) z$2dyne<4b42KG+Sr%px|P6n2)hUQK>7Pi`^Hrj?ZDh6gMdgdxR7V^4=a+-$Hs``(W zwIvkw9w}-*meUfG)e@Ff6OmFEkW}J-tjH&($So?zDI~)#AjQfr!N!ZRlf?gJCviW* zs7Z{RqKq73|ALd)h5xaWFmMtzlfb{>r2nBNk<)YkTTQ}%NE#D3@)bTZJ#$a_6^E-EkJgI!kn{u|&ug=YT$V=}FUHGW5u{@f?V;}R_W;}9xXeCZTJ5 zX6K}^L-9?JZyQpxXHw6l+sgfQiO14wcS7`|BWQr#$(KPnmFo7O>k5RV`hl@2voI7u zqMm!O%)}9cQt!=InN9MY5BaYDfy~dEIMX`#tSPD>gmg@dIYNgUwiZ>_`9akz1;K&$ z7MS15%$=wnK^jSCXUOCmZZ)4AN2D8B5Vx15Ht$FF+0V{Z_Kpi-a$Jp6Rh9&BjN>A- zR|nt9m4W~%e7+fz@9<|YDB=~IJ~%$NYW`sF@zmUT3r?FKvz-m4T8L9#c1zV%u*=2X zih)91%rk+uP4-!$SbKTd#MrULUiQCwOA4GBhqj9as4n%C)7>al75e7~)3TOqpg>~U zRON7*{6?H@x$HeSTs-|4)rresi0&ki{=kxfO3Kwhkm~=*Ey63SH4fE~cyxK1DC)Tb zam5p@vW=B~!T%*q;ZG-m+M1l4DyLz=_c`?&dGa?C5#ojS<_f41p7Xta>osg2wthY@ z(EQtu*Td%Mp2bmfpyJ*OEtTZ3=gG94-J7_-on4FCH>$kkRh%3J!Oi7&BC+`vJ}9DQ z1}em8b*@o;Wl+wRBo^E4spuFbp4V(Bx32~-S;OA?bEme|Z|_7}PC0s)BOix76L@{) zVIku7xFx{7Agx{_kw9w0!)bqorB9;y5aQws}^p~TYXfg1!1z@|>feY|RB z9m%Uyk=pdQsy1Ur>_8v-ewUJXV<{AvWva6CrD;Y5Zgn&DV0;8uvV>jFhlp}@vJ-I}wqT3F`fzBYy9oIXCl{&b#y2E`SS+p`9QUcp5+PNgBL^_CD zWe;?ie;Zcd?zf8`_RpVud3eAsN3Gu1S5lXLqM0g3N;mSTU5MF@8AwW#OmgcW{{U!K zil!_YgL&FTl3#8XtTL1JyBQ=cIUrPOPt-o}A?U~@R26Q7+S(Pm!|{o?T1iS!R0NMIy7Fc-HS+k z;JA1i7qG||k(kUO%vXKl#HwKn?%L(|dJP1SYjnmm>lA>~Yw>=S6&pm6PuI%k70Kh2 z&C{lpD>g^$LGvn1`ADdcR|nhz{tlVt#tns7n0jC+Y&L?DOP-ea`ICB~SXGz;etfFB z%d6M4Zs^_aYR<^#k6DFHUg`3F41cH2O0-V;n9YNi)>KJEbz65*`_X$f;zAj9Vd8G@Q$tS$FR1~5 zyXX)K#no6-J6VClqepx~!1d`vfUwoNlv%fdU!O?x9KX4AF%Q@1+l%*0R3|h#M9Wxj z8qqQ9VtfV~i+0o&D5m1GG9AA1F5d}i69aM_&is@3AR62p#+jc)?(e<>ioH8{s?|-f zj%{8-jhTOi^s#z(&_EsJ8O?nKGSud#%ykBj5VftAb`P`Z*&;8Ikb zuYgc0jJ?3UH1@~&I&afw6#%h~pbQJn<1$4tu-$5643rLt1^9CnfesJAOPS0CAcU7l84-g@n zi+ys=4rFxbub6wWRFR(ycJKkT1ytOonh=J@Zq17_MFo-$H%S!)PM_)@+TU%x-cSE@ z$-Ni*NcvUfAJd_7vZyE{u=?(M%Q3 zU6ucE@0s+M*NGH{60bvDHYJkM%$n*$p^faUpvcJ#yA5MQjscF?FMebSvd*tKA5D;g zoydkb3_5+KLk%GZYLt?oV6H9;Q)U^(d93mR;n~m#89e-t{g87#|2VSfE%a6-Db1^w ze?ng4Q?kwm@~!#aZEEJ7MW&mE>2WzFmhsc}**f_}?HhShB?YNFF$>Jo&BFPHU*dR# z5ZxBsCl4i3enb&4;4dxC{zizj^q6;85y#aN{JVg9Mi5jZj8!WPOqYM4&P=q4g;z_4WC_y;n;E*TD9fRkLptrZg?5^OjUN%#DdXqsNqE=Yd( zl*D+M#Ki5*%+0nTp3LE&Olp?IWkx^pC0XDy`Emd*c*!X&k@CntMI4=#BH5H8y^tb% znIcb{swk1FY?i9(pQ@gfs@asPy^yMVnW{&d29-!NG)pt~PczL*GjB?>Tu8INOtYa) zx06VBFiUsxPj}8rcWp{{TS)h~O!uVCcqx(LZIiWT_ll>Fv~9W z&o0Z#u4u}xTF9=s%&w))sgua5H_Q3#pVOF?)7+HPx{%X;nbUz0DI{{!FAWu#lf;x> zgPFm=4xq#uvEwm`wgLeV03s9ipJ<{FF(FHp2hVD#I=m!9p}F%OVu6A3c)B8zBfGh@ z!VJQ5bc=TU8F~PJChCn#u0Q28zq9b4C%;!!$XnSZzvE71Ac&H}w;sxZ6v=}vJq!LE z1Ar)!DYLveGd@zf!bbgq#ofH0QMrd^WYj!`TmJc(FxGuD+fQC*5BfFd>)sQP6}e#- zUunE|W+_H%6bjfD|1u4{O>&~);yTj<&@@v5_DmHd5vdBXO27h!Hw92H1j`=zc1(Vn zcp#ov(b{_c1J@@Pn?-0qi5qsQ$k2NwmeR*`1w6K;QrWpOvDU-=oUZ1SDm;>2u{2HT z5v{C9{}sYF;0v;3D`D2m5C%6RUr%q?d$Pb zyF#W1@xg1v!N)i>g4kM2;F}J}atKI-35&l2IIV}_VF1}oU_Jo0F@$743$o2kfReyw zhU0#*aYKZF6wLt$J-`CMjEIcbTo0SM1Gw0MASkS;+N-GLsYHi>@R$(`HWcUIDn8Ox zT9ye6f2$g&s}@EQ2cob^1+guTiJolK9P@lUHHWNuf`kEB5MCr|j;`LdvazC)sI!*j zI}*>f=0`;hUJ{c2JCabSWZ4FfU-Z*4Q4|GhVp=bsw~aoo8~%nc0+e_!$1Ya z(pB}EWDOox!)$EznjSn;DwHb~@$jeM=a9tM&sxI`ZWe&- zq4IoiMUiGjDNi|Kwaz%8ajUtGPYaCo?jx=R872M4-#k4RVln5k`1pBgyYfxu$?;!39wp$Oszc@fWB+e%a*UVIUSu+t%_G2c0rT+TduE zz)=fn<9D1Z*S7h}wnch+_0aac;dU)cfRG!`&Q;G0JvIW~CJV1wqHjAR_-vO`Mi$p| z`~AyYW&h&$#uK#E*E0*i9}9>FAI|=BXKQH;kJ^P09MG_Yq>c3AAv@Q#+JPbExkQB) zfrBuu;;7s{V@tev`j$@?EkMtfrk0jA3$llN{W_KavD`tm)Wpdp0I62Rlu zk;*f2@1P?PF&KG&gvxEOPYaC5#Vy|_4bcM-L$JxONheU4N9T=(69FOEGX;=|W31`e zR-imChF6>E7%N%rS5|04hqT1hk`gEolj{K{;E)Z^wxke)A{zjnpxTrBA}cJcwQeMAHhOeLMNYis)z&XHgF_0cbCRLo7z8fJsDh4ATh6oQw|G z`*sFVTYU@11KQwh6hN*<#?h=AP59 zg2wFoXAkaoAZ$v%xi3$jftCWH__wWc26#Vu)a2lmneBw7y;Y(ufV09adH z$&*<$)oMcs_Mj^ubU76Rh(9%N4WkU;dZ0BOy_B;i25PH{mz zg2=odSomDIF;3FRGnLy32lrHrTL8O1-f7v4>EayA8!CZO76;1JRoTTB|yN+ zFP#-CuNA`PCfTt;{kKc%SL^qLHh@W+c*xBaf`e3&)po{`0h0ZpgmT$h$Zwl3zP5OW z+A6Xj2*;fOEUMt(0wJ4w!qv(h5L4HD4HUx}1PjfcKD1`k5;h z()EL{?Iv45)Zy~UA>#NLsJ9FjIswWP+gS6_qwg`Ip8{kZ@{MiCM1B%;Jzd7@{54(s z`)vKU?-(#B zAVhAG`NA(p?br z#0*DcyQpWqom>Ajl$iiSyH`49Lb@LcQYQ;R3(8? z%V4$-E`<)}#k=A-EIc7ilhCe*@;GFMg7E;UY`FCAo1rL5eAi|T!rmLLnqn-gaH7t1 zZN37UOXE#0_K1OkG8uup!O{@oKN|x|%f}XFJ+M?IeU*zIx}p%w(Y*~HKNtYixK%eJ zPd!(+Wsbq7!Q9>dDTukRdIF6l(?)umCzg8YDJP}cHD8k`p4@BZsVHw`J&@hnv!iIm zUD2*8W|pcWr)~h7CNi_3(;Qw3d{>t+tl}ExU2R3u9dcz1~tj%A8k6r*L0#FRYc^B$w5aFo$E$(*we<7XSAkM&r|)5H@@d2L`y@-f?anz{R8 z!@Ewc^#Ezf*ocaG4nwwR>oc43oW}A?KhI;A^wn3QfmLlB?H!Tv-)E>d}MEhN2sO9 zUHVeg{l$l2Xe-JM?A9!}Oa$egdK7m4B}Y**H@My@`HZk$hO+h2>0=;okFkXZX}gOy zbV%DJ4<@>8+FpeIl6FtmrMMz}>_c5wT2Xn^R%%hkc(y-Ek-B2R7K!an?Vd9y0HBWS zrs6%!p|ztoh-$BqJa{E%#Wg*^!P>ig(}f`_3i8Z z!^bxG4-?*#gJEpD%1%k%w^=@;p!ONx4pgUxzx}2H%=7Tf&Qe7l=y}Aiw z`q*<%Uq6kLXA#(CS+(YK%A5=%sk)CFJA=y-BV-ONNPd?trYy)L1*%tY^aaTKwO{@y zcXuz{KEMgK|7v+k>F{Tavn2bTf%(dBy}q>6k&kaLo)ap4n+U;<+Xw`zKTw%f1G`G2 zg2^2ooSJf`p|RsS?o)yF4n3%4Z!bJt%(5R4m?=xqABI!bh$tD_eGsc65)@)N%{i7< zCfiUMa-&4rs9~$ee@SxB?ecI_+ewKP5S0Zhst82M^v#bF)TGpGo9 zg64iXh<=EWcMmw_WNDwKt2vw!fV~b$QI7(2z^ZUu>|7U!Uf7XlC2_GV)-o~>^bTU% z96a!4%`o)IbK)?rYI^~&wUQU&Apj0N0+5Mwpb`usEA^Q zj4~?iKo=5CQvRsU-g1*hLCEIdVe|o)-F|T`)vCWZCGVT_22@-oe!s``g?o*k%|Ovi ziN&O8(MI4-AZ5%!xd1SvuHo}aiekAP&br6X%Ux%2AL<4VBTI6#{&SV+cWP8U)KaC; z>Ai@}_L_M$??W@@)Gwvjj@Qh; z9o3^WZ0#=3@3|ux_}r(Ec8e9CdsTW<-%8x97GNh(h6UK`6S%EzEx%-@)kPmVPc_3w zbU7Nk1TeGqJceKXe6ChO-;l zt&pl?!BPzsC2SdAWd(HYkcnSC$jAGXsiEK`JK4j$#9A0~zW4+ChL*iVeG-%mz}dRr z^*|KqjU{LW2)dU+xy2rdpA3k=Azmwir=R{pa4$)h;?6NF`X~qLP(X989&GW4)MZ)m zJuwz0qzM6#-M3r1wX~RP<%s-9yME->e?1o-Wo#JPX7YR>Ys|M#L=9~n&w2@Jp>8MWh|Q~%j##64{OT|Y#3EcRkb`Auo1m}~6?#K}ZCk?1> zDcD371A?!6@x9f;emHokSBUv)%Y$k#zC>R5S(1m%Azb+lZ{-ZPB)_NuMX9=0hWGtJ9! zY1j2#>i&j#XT62g_W+r)liG(pWP+4RLapuB5;VNW^+JY9Xi_C5Oq=>xIqp$Jw*;bF z5?4v0zFRs_NgB7433LDaMoAX8M}e(JQJK_SxCj1ANu-D1nRAGsrm~>7vN}<>`beQh zeUJ9EGUlVTsa#~yqf4n0d(opW+G`-)lc3Q1buBer0VmH?rN^(=JhnF>v)8;wMX0sc zvcB62SLMM*ukvZH4O^dFm8>;iw;^Ajv39njci*#!K5gwjXGEW?a<9E|pI#ufQG}{n zecub*e$N{fFSh=dqW!Ow`@IeOeH{9Iz58EB^!ugu`y=|_)b|JU^aoD&2W|GhJ?#(1 z9SETu2xS`x6CDUw9*8g;h;$f;@*aqe7=Wb?#2^OHvGoJ*dIsXA2jVve5>5vaaR=d) zgGp?I$)bZP%7dwfgJ}+f>E44G5rdhjgIS2d?E1l+p26Jd!Mx4E{L{hrxI+b$LxpTZ zMWRE+%0mdlp%RCoQtzP;5kqCEL*@z z%ER@B!wn9@pS_2_L<~2k4mTl&o9l;LdWKu4hub!X+fRqT;*NAsj&!n(bcv31E06RT zj`TW=^m&i;M~n=ljtnA3hU!O#dqzg4M@BbC#!g4ZaYs>ewz~Y_EQ7zh~@VdhBp>?C5mtC+_$$<@gEP_%G4%-^$~shT~@r& zQpYb5<5%_L*FEDm)8n_B<9DayXj~M43Wddv!WKi}sGx9-P(Vi%o(~E?5(P>_5tN|7 z4Jg816wwTdcnd{xh9U({K&U3j*eA%vCMZ-UD2*nl94973v7u#=`VP2qe*LsmYV__C zF9RoN4wa2V)E-c&F^%doMC$8X0{x_+UfPq)?EMU4P&W2{_A@nVrbz1f$jIYxDpL?M z1p0MglK&72JqE^#V+oajRG1>sU>lfF3G5*|P~c3ESr3R@1w!WmQYvw>H1C+1fL4%q zG)$4aB`|77keDNkwQWj@itusdR6^O5@)q@!DpUH7Q_?d~VjFCW0+&-lOU|GsF?)#R6-+^ zmlWau-FuaFEXVf zbY&oXN=0Z^GLztG4D~efb~oXfF^F27_1;n=24O=%MnR*@KI}jW`O-+i*|%08nd<4M z>_9tpqEMgd$g*j4WMg;&3`?oafWveyv;@YhV(NDYdSD8QK1_)_q=2=}M+z?VteOO? z5V<-US6INzn1Eh+vk}A#No{7a&I{B=^N}{D$qa;1B_PHvQ`s~V=*4`bx|#HhY5L(@ z@F57cm73pR6jK6=wSrkSPRZ`Eiiw#cO^u_N%%eaSAyn@q96_cu@6v)69!8i(oEh6Y zg2Gh3g_pqUtY9=o-y>}-gz7EAjlQ)~z57Hp^|WLn+6var9{F`fjT!O{$z|~7FlEr) zIJR+$*T*!>5yUKr<(Xy)Em-V90quQ&Uu_I@4neX$i#-g4*+JOI0<);&*+@aG83v=T zwTnpgC3H{7V$b~2)7$CZGy363tA!HSH>!6_OVH#c%h+Q})M1K*ig~UhY(!-#Qf~=) zVbx=^EUIEsL-p>6;oT&AUfIYHD%u~cnXtaCo@{21 zGzKi}6B~YoKZVvl{aO}sY&1PgwYpXU!*+r_?U=k#nZvnL6H8mI?X>9;3ZXau77po41$!sVA)dAKp(IZPFV3WTDWNiZ!r81*E z0`aF!D!iRS9%H(><;X_EtwWf;irv>HsF#lo&OJhauLE-dOjDOg4l}K21ru_d*K&mE zoxjszT$NKL(su$Gl!8=s<0OI8ma+~|^-ZBt2W0K$6OS#kQjiUatxl!mw|Kj#%uR|h zy9`HTt8+pVMnXba8@)$P3d>G3+m6cCFxt}XD`I*FCu7IiW$U}G$|c910*j#rC&HtC zTaLwqf@gIl8_PzEx96%v!Fb*5K9)%F$sVI^eaA&4z$WBq1uYTbTr^`^ zoM#oFy7t)EnT}&QMmJ8DX=i}n$=ujDcK(^vsdLo)vQUt%G@~=rW~*&$6%u8X+~@pN zeeE$xPV|_w?a^*^o=cRti`nPh1o#ga!(7bmTw&=-5#u}RGps_L-Qwkb?QP1+dxXjS z*hcauIfo!~J=`1>gQ_En7uD7UW4pEb)?w%Gn06dK3T#0Hl&P_<<p(qQXP1yKw1Om)XQ6wCho*hb0yDvX7R%HTK9KsI9eni5LoOHML z-&$=rfi_8UIOhQtfTINY7m~O?)!7zm8@8lIpP!e`U8*{NMLOPXTm3#d%08Q2ef#32 z4$Lw(?jFfg1H~Q)5N6oR*eQ0cZxEH zbB94Lu>(tujPD3JBZ-2QXg@rYcRaD=@WS#vkwu=!5_pjoFAy`~$u+D8l$?m&oD3XI zN%=S+1y9iIZZ8BTm-4?w7VI-qyBsc^B*0uSN|M0b32nv}8ocAc`phO|_GRYm<_n*f zByztk#z*M@ml0u1F zPucRPBMLd=Q-xOVp4AEUrv`FAQZ+uBDBvr3sd#_A0P?pzm*6}NdE_lN;!Rd+`_p(= zRn3YYI6YDG(v!+Wmdflx#s{kIBNOby#JNHA#rp|qj_sF?1SZo4tFt?!?@vk3zeO5N zs>bOX8TbU9KaKY_3_d7i@Dx(<_4w=?+Bye5#yYxl*4KHBY&5VhiPX|@IB>M_HhJAc zWAK(S4E&Qq*4+mQF`Fxyc=med&5PGE(tpAepXzE{1U!SGL;6jie&_804VB5Yo#$;r(>m2)G^Wrj<$ zSExWNhr25z=XKrV>rZOe^(NO1&#phezWx$@-I#IR^x?Ys%XLftb?e-9+mGw^Ki6OJ zZ#t-NIyrB;9^Z7UVRE9I-e)&`uW$OJZw4}M20z>keYqL#zZsdk8U1lH_UC3C{}x4k zJHdH7`S^B9?RMJacIMgb?CaaP=-c^>+l3E*0es*4Z_$f$w@W{6m;cq@p ztv|loP{V}QcU#ZywqM`t0XT~q*iChhMp1!{K3loz7yC%2@UuxifAY-)jZD{M z*TLVMr~<`ka(>rSu1SRGm!#%N;JFPjZBf-vMZL zc>V1WD011+)EGmj?BcG2`3a{>L+AieitDsLm|IQFw@heBX6?%uqB(~1g>}J;)h^&0 zwM^@^mKCYm0uOaZIw~ncRn0&I?&JI1Dezy6-UI@MtD)F2g{TNxg8CG3+&ib$K+rAq zY6zhYE67i(HZ)KE0oe4t{2v14dy2UrQM(vUj?@*Z>%u-3Zh@|IR=5KA@|%IwX4tA? z13T^*8Me+#AU!x~rtg(bAR!VO4*CZPaF7)ukxgaWz8RXC?~4Rt5k%-7&W2yQ~( z&kydUi?cusP*o~vZ`5o;2lEilBDCCwVDH|vH{hNRiVmMcHBy<4<_6fxT1}nPV2>`; z6{YethElVvHPRw&o&K=I6*9glkxwxmf|z$YLRSK6ii&p1L0d1M(dRi(?z4RwgTag8 zED^lLN<1xmpGH}>(rMBQOlK5%Y&oAGu#INli~fi?O_X~vUCR)(kguw#>U77JCcl2a zb61`+?8CAX33+<@8xN+4^e}|mJH0Pw<=a1-XhQ2L6wzSHT6xp^NtUs8+z3H#qSrki zT%_21Nw}r-M+6l?;i4*%{ZVr+=r#{_2lHUObUxI}P$(bjs5R~NQ`TGo(=`CrpdgHcai8h6QqdntCEjgZ0E_LvwOrL)T*;4#z z&?ZajtikiJ;j=(BwI zVGVQ^gp_*39nDV3zWbqgxxm$mCpw1w#s#+h8-ZoXLk5yk|50gjAwoqbcOOoxR1z2pD=5OW@sCiL4KFn zh8P?tchcF>)tiE-e6mJc9UAM>;))-c9+T`qRlkN&jl?%&`P$CxdRF=Iub8k{d?L@-KD@OUb*i=$` zxH1}CdMt#=*wmdw;+su}BBLxpAPL)S78g=}SniCMBP5 zlSaX%iMOsUtp@D?%JTgJdC}^^{EG=lLZ1rfmFJ5z1*|C^bw<(IbP0i)*qiE$TXmIp z$p*s+9$kEb=qB6Yht(P$s}A(v+dJ_Ct!BYzN6zK&XP*Mk(M2l!G7kehtbBkcnYcZ^;h%;{tU~(nx~J&`wH`9x9LwTxHnn zI6jbwGbaSu7-F+8b7e6hH4*-|}G!^jUTksf2rXkWyStx++Pwn1r5+F>_4l zx}IH`%@bf|w)YcVpS2_tlrvK#9#4^xSHe+4PcRD))h|K`Str{E>+RW(%!_%ga&?Ny zu)bl25p65Xg%S4?0i^U*3XQrkk>G>@h*E)mI416)Jc#V4>L`Qv_C?T&Er!xG^T4?e z3YfUd4@?gg8@JrjTM>c}-vI4mupY88qyV1mq70XR3q*K+cN~az9*y!l;*WQ1{M!Ohk z^VjJ=@0i$VczOj>8Vyb^ z{v8|5Vq&A-fzf|rBg}3)rZ;My?QfjL^hR9`(;c5Dx{(uYnChryXuP#=vUa$=YNQF1 zA64}?W2W0N$WCN}!;u^CZOpI=#*|Dis&q&BmlIwQ9jGxCm^Zcl3~PHihrZYlgfH{8>z z|CJoUsxmP%?g3TtnD7Xb93>XLPt7aGEV(CTAu!2NQhI(|dU0$)R#<)tCOL{oOaG@j za?JI&O!taOejlBf8y%Mx1WyczO?VrX5)hu?8xi|5G8|JKd4z^|2g6X0NB<1CW2z%NZ=Yu`12EN*!*gFuZ)BA8TtC5CC(iMo-UzeduKf3g`#;GMX0H9O z-stbSc1w3ma^!|djvjmI{j=MS>5Z7(Wgoan|L1NyCOI;7bpIzgGRN$;+dVU|cE{*unZic=0WxU zUSH?O=a7c!AyngtN*X%L^;o;#LnwT2X!NN^%- z3nf53(qXiDaiHP9*Vj#~rGsLP{CYRc%3UaG9QP*z7Aje%&h$)%Bh*4JMh-bf&vyAaPl%H~;|IV}9Wz8)xkxI+7aQ`w46LSs9*^WHz} z>&^tfezjhg{R%^U@kIwO2W9uy8~hv7i=<;a)#;a3-qI3wk*J{`I&SuYkXZeJQQbX*jkO0>%QjVnIu6>H+(>+8yw7w|y9 zPRC%fldgu&6HU!>y%Z8Ns9tJ{we9$mW7LO|OnA_)UZx~U(8Ycp(Nr2sfK<2P)E4Lq zS2N*5Q1I; z2>ell;umlc_X;|mSzCJ|Z@V!ml=?a(mJZXFDxhn-JACb{#B}WkJNEC_+??lk7U-{4G__i6n z?sAz_W}M@)vqW}A{*dv(zPrlbW71Ekk5wYD0iQZ#A_uj2h+brvD@ObMFW&CEsp;-- z^nDT%2qh$;HzD*QNKgb+N#gdjLwr)ehubx)Z@mrRV9jX?XND}UFAiyM z`^E@c)L>@AOtpHfkr!9G_jX{IR<28*vQMVIU)^1#&I;1#h82$<>T+5njyFKwE!nA% z&lK00?MhB&YgShjg$x7Gzd~}94YW=T+Jw6g82NW3=4d9{)3IdXg#Mqm-cGHpgWf{`iiitqNQL8zJcoY|whhv^*sdr3 zrq$HLUF3YZ-R!n`?I@Z$ceLT5f_r}lYyD_H9faLPJ&zelopLd@=)9iKG&OJGYx$v< zvE$63YGH`(9|&*@HxOhXT_(#jS>V@ARSqt-cqV1~o03zpw95lid@|~(>tM-WAVRls zSKH~aw41gQ7t)G#j;er6Z=(+!u2UTJzmwsT)%#{+9V0p?_+a-_l&6i48?))L*7a`L zNYh$Zx9#8V1W>dLV5baW(1Z7|ybL`l7C<((RP?OnmRPQ3uQGk99+I9(PG7qyZR}$ZGE}LiFUS&t2n&e`(yL~EB zl9MiKuXc4vEk{dGda_1WI0!t0Rg{I|GHiU9C{|KUTGbtDCT>)tW_VVNH&MVXw>c#u zlPD_kt80|+8$Bi)BS1eLukujwd<=+A1)V9stohM_+fYzB;1-YifOOtZ#P1g&{YiH7 zXWMesE}$;km@7(tOP#yl6Aqw&&(5WZL9Qj`=o){kNAFNPI6Y|wqSp-D2oenozh6<` z^|&5^ydfX_mfBgu8R^DS+}{wSqiyXnkG?t5qhw|Gu4{lg#n zM&)Kc?74rIcg7&!;Olj3sGdR^DitfOEOZ7NWRb~!VW>6tWx&~(tyXq#r%Lnb+0{$( zEywO#*VF^3EkAv-Q?DG7>UR2nzV8_nxqDImEYDCCf#dd3{&gyBD4U$VWAQ-CG@Xt} zp`{GOSCd&MO)hrJ{E+LL;l0|K1fZB2Yw`fJoMI&&R^-Jy_I;bF{OFazFxA`gX7qTTh<#=V^<^1hMAkI?<-?j> z;k$v~xOR~_yc2}E@?sf71(CBcb$tt34ZF;Ke9EibMeD`W<1903;8p&1-=hBh?gs+z zYbuA$l9BixgKYcyiE#gt>6yJjO3LeEMVs%Im-jwq54;B#_o%by*-e%>R`2I+j?c0}G z{VO-l?2j^1-o7riS-o|6e{5vn?c17v+@<|-#f|u5ee@V^{4_^GZHLhpI|9i4tjsYb zjIvBi{N0KMxz9SSTq<;+>YPk5r(19X$CQsr=5Ybb5jrG>l3-;cCje0*_APuvkgX=P z#9|W^xM&>NeGS|Kp=PK*_dzb1PXH+9VtdCK+YB4$HfhCkp}i*tDAocfgcCAe^jjJw z`+5XXb1|vc`*`3WL{COWvF@1d#q=lYa*{SEoo0R@-W7TmTEJ%sw6d=ImH%LG( zMzk!AI_UxMH_Vs*9WCC7!m883i43+XsX|G3s?L!Mn}{T)ZkgJpy3SDPU*x4ifPjt> z^4UzlgMf$yv+V%`F?eX&h{WQ>ZZinidP;uL!J_w%v`-$#!zPXINync%`1a`U`;WqN zJP;I6rKd3UuDdL9b-gPFOMG>vd-heI--o`i^c-NXb40nh_f03 zq4Dq!!XO0T92HSd0Xoql!x!%fmIhA`M=2HFQ?t9r9}R-gV0_ZVbIteAUBUYtQ5U77 za)bH)3=_ZkMKx&<4oXR!ZbTg&zvmo84o~1;oWK$Rcofac+e|Ru2nWf=h~nV&Sbzot zUTLOv0}ZO9BEK?xw&~h3IKV3YDx@$n2`_H$<~N7-7e=rpA>f!9crT9qC=MtJ04HH} zIHh@`0bmij=#eYiBF~L*TVU1?dcj9PdiVhb9ivkjYDAic&&`h6o7g zmrV_jp#v?~ee22oYT2CgXn&#U_<-8`lTPI6T4cvgLL(~C_yp_<1|-3Ne8q=~ZgUEF zavh}soiM!5LXcV<(7}<2*`51I3|>$n)IOf5F&vYF;f)}GM9|DP3ji zh|c>{PAPiQWRfSDTt;qWWB@r+Of-_-ge27|p-+n@p8m|QT$jGJ9eH zk?d5_M-a>-5hP5U&Mk@upJ4dtd`D14!&$7l+zeuW2VO@Dm0^I7(YXhMk-cVjE$Pt^ z1Q*&Y1X2z6zykCzjtK3m5vicLW7ptHVCBQ(YG z-+V6+A1kc5^ax_-+emrT+RdGJ3Gs)MD!CWu-5GI&lB?B|d$A`1qLTjvS=fj!6wFDf zx9Eac9btw4zu1VBG90p#WKhmAF2OmyyL#gj5vz$X;qW0rs3 z(*z5RXcq$Fx@VCF1ALU>a}%A=NCyU7fO()n!dP%2^;xQWiIy{%`xpE(9ta_DL8^Hm zbRdrwOcWChLFOgV;Lz%d?6DXKp`y2^qHG#5ht5h|cZm-zub)PAJ*%wmsd%&(5VH** zo({^U!g;HC+PS!R-FO2mIPY%4OIR%hHFka&9&V8yU|bgEUYrcHnfi;CKbE->W2SEWzmo1pfkB_yR(I!9*l`?;z;T z;GtX3zdn5l{qagp{57tZo32u+XIR;YjW!$gk+_VI8n1xNywJX-*odzBU7rx>O$+XQ z!$iGx@8$m7!#(VbxG>IdJHkIH_B@_5FrP~>oeL=x5VEQjoJix@!U}+f?}9mKd&lE6 z0QhAspxPzJryc_Qj$oD}3_4*Y)@U-_DfPjMF%tmU% z`enf1rDoItqE@>liO#)z6pc85)3RFNNVwJx_0-u^Awn?c;A6<(t4|FLOnl4PGf|@= z&;DMjf+2ZV7dSC)*|WXeygXuvKJK65O`F`-2yb6ZVYAzQamY5}&trjIE08vu-xU;^ zR@%m-G%518>qQ_jecYpuIbVHzN91mqINB04@*az%vsHE=knP8>w+3BC@Kz!S6ID!= zW<921GuE>ipoAW#LNypZkThU6wS=O=YKh93jHK~>xFJ4+Io^f00z#;qSkDSkEPNGL z#82hW?d1Nz05%c~if&h&B_J>NMShQGE&C^yXxKeDG(sE9ZJ4UL3%?o6V_^q(twGaO z`}B4YFrL0}6B@v8m}!?nX$*b)(;`{>lMN) z!w9Q5pa3G}HwDO#aqN*`aL@EL($MYJn!=H$kZM2Ct`D7kMG#~UTdqOx!F%&}=xE)S z7HOZksy~CGyEvN%RBh_iLwXme+zI%*hurRuCc?!G%h!!~*>Rm9!&EtdO@}?{>2#2e zr53B_d#nxniLbcjh-exE;$cGWmAy>L`@a>4Uldp`fzt(BX{QGh#N>)&*-NlGnNA%b z*-<7MPD+A2dp9P8h*oI`g{+SjzI)ub8!|f`7l;gM3IjG`pLS{ZiZFacsIg*(1Ay`7 znD{Z-hOx@kvD`aFFYjbB_si7Epa#gE>W~kt4pppha)KF&)GwVF>7H<6jIn<7u6}73 zz4D6BFg12DBpe{fe>izIc~G=`(3r>1nX10e@G*8lh}LqJ=8drk^mxwk!90ns`GPNc zM<*nb)}D*h+$kFI$ZqQ4zCoyEqT`m&O!vA>ztpWQcKOPh*Oiqw+NAo8dobj;gv~db zsd=?t@0lsY#y8Yop6k!)xecL>lEesw&GD~A|Fcj>te+`Y$=s}SLT z7w-M7|CE=Xl+Y-KOdfwW*`17h(uCC4{%-42WIMoJPs`d5J&rPO<=Obag&aJi+9DYI zX40nMmh)?cy-41{uaNbx014Jp@cmWNqUvQtmOh?;eX;!DBx3P9m-GiKvmYSoB>`%F z?B5Cq?JE)@cYSW z*lo29w=F~T^DfSvjmOCeIWvH$9Ub8ic936?x8ZOj1MZ_1WP7ZrUTj{^5Y8V0R15z& zM|jTV_YBn)y;LgFSIT&Gd=WZ>@EG9UW$v>m6|PSRxK`%^uN!=j2GwKugfU`@cz=aO zj6eXdi^Gw+KYwB1OK&HAveE^pQ}F%o;~zDAl~BC1^l{-Sl6Ecq++m1m>Q<^mmLBt$ z^0B$6KMIr^5rw(QPkE<~tZbg`i3*H4FAFZ#Sb z{?*3>`%Akj-0mG4m`4!f504<6XTG$>+$)ZAgLOb>Giyx=+35`+hi9 zitsJ}g`MFfmsYM+jf5S*r=&Iu&9neB<$&18MjlCH&-JfHHjqE-AL9!#Z(_Ma=f}|- zUwK@6RsPNj-fEX|eHs#^k)4nQ4TRbWjNGL;05coK^yf^T5MCs5hTof$r=YM@F5x&8 zy1d&vE=bqm<4gQrk5aK-V!6&IpBd)qhWpb71@=sB>C*$sy*&Q== z{miSNLQoN|iWfX`mi@HgTPE(_X=Qo2a*pELr0|;p>tyWQlc>IGx2M+1;wlB_HHCA$RrDnWvSk{~vGz@aHI{BUt_^9MaWZ$4X8FZ1% zq4)c(_s@4hDof@~Q9{ZnV#wSxl?;$^h^0}|3k@p4#CBydgOewly*OfJ@`=3blTkv} zPn`F$ik^#&N=3$78lDnr2lk1=;lFiu3PJ(y$ad(wvtOa_F^sn)rD^y6v#1*{b{Dup zSJI^8h3ap_fSBmPn}r_7mFO9<9nGgRBLB{mrpFFPFU!SRA4N4*bv;lXI2y$pw)8~U zC`|fkKuU671D8(B=cxSdB~hy?qd^;UPI&veCTIK^L?Kf;?4}=Ks<>bSAhD%S#Oaw! zytf3FA31Tb$N%Z{(Ob73e+tqHleRf^(mWNUf9Hy)t4x-V7jaEUWajwc@;HkA>E7qo z)F=7%%PF)k&M!od(*d!U1HfZ`1&cS1C^e&1a2}K^#|T;3q23J&FG4qRvS^)gjeDJb z1}~oYJl=mK+zFEjvn9IPA1SU6trJyunxk^Ge;^Enb_yN5#1I8g>|!4sfnUx)h^_6E z14#pWU(VJsL8O=%?s5(eky`q?Anu4$nlne{dO9b;R{9&>5U7eLN$#}kgLMZc>J-^T3bxc#yN%1Mtidor}m>aHl$2d zo%pgw+G5FR?xu#8Jjc+jVzzgJ=EScEOL}CQAD&Hw$hwz}A%$EtJs>t+(9DnNHQ(A7 zQPI$=JSphzSD8LHEA~5)LUEAKF3S&@AuiW$Y>{H;fE0 z_!}?Gb?o^i+r(~Q3?Ub(@xQMqNIrnJK#Zx7RGk&sxqUA9nU7$;D^!joB@TUp5bpsH z#4bdq!<7uR{PU}g^f=9AQubQ0BeSw!(JJ;2!dlQmxMcT6i*s+A;{}~?5RY0}Ct7_> z{4(%TNQ9#L7mb)TwYF4tuXICDcT$<{1uJWx?w=^bmimho>taE>mWiq#yL~kc zWfaO+%wk5%-JFZ79v@a*IQQT}OFre1Ymma3UfM{9{@dff&UQKVhJA5OyDhQYJ>Yvv z{Gq^us#Cqw<>#VRhCqnV?(-FW|6Chf@YJpqenZxWeVcmrhZN-~zjl%T*7?8o6fY(O zPk`v+K*Bm_*qeA_1RJNnhd9Xd#L;3-3cE?V%`{uLD#xDWnc?&uX%%0i8LCQr~H0-{t?sfjJI-MeSAEsRDyDt4ByQ^`XsgXdu z;;sNM?>-mjpLsdL9nk62!>Qk@_`(`@^t?_l@Yu#fZ`B*Zr8>Q4yeA$ROn98E8SS?& z*?c^&dlOpvXdrm%curRGP5tfB57$zD6+j|yo`H`sRKC3OfWPxJ)gBv6jSDQ6*YmP; z9Q&Bn!CF4=yljKVJ{7PBm6_<>vd>)Pw@Eo zKbU>Ho{xXl_{5@VaQ)|ZK6h)zCx6BTH_q$%h7FHTZFdAW{eI_rZ+rYJlRbpagy`dA zgeRss%tBfOoA7bk6Ekquj*`5-U!vp0H{s5Zj+0G(DZvx7QXHXOCi?#ASrc=LW}!V7 zn*1NuOw6mthxU2s2jmP-ENFLz4g@s?VNy-jeN%e=N)yoCL&$~2tMAh#7 z{1qnnNZ+97)78H&RV?mITl2u;NRp69u`v5Ck&EXz_##+`x&PBZ(hlIN1C&eya_B&D z=49q902n+zRQ?(M#BRdVb62c=o9lL)Ps)&JdC}D_82Hb7*P8^2A zn#{$z@=|25&r*xL>3{?ELw-Y{*M`D#5X6Kb5!FmYHxoS#C3MN6JcdLaI+zD-fCWN! z0E)E`pd3arx>=A1Eice48%$uG4CUl#0?CGwU<~k=5s?hh*us#UVmd|W{MO{txh*Q1XjZc1NJL8_S z*ULtN8ehyHNKeN~PZXdt3Ba>J`-o(|X$bEeL|Y(+xX$KEYi6D{aaA$_{E7uRM5Eos zL_+{XI>yeJynnu(So_}bwK2G%{o-7#Vo0*{6;sl>367^7u-|q|7wTzDK4ol5q(WSE zjGc{5oE*@1B9gu3nw@gnIdq|}*3b*?CXUu*uen&IlmQU1*Ia^rYtsW+8qJ#AdQkP+8oE0h`%;(uO2X#71p1?DH)0yHc>>z5 zd$wZ^IXDOT6v5N;`hBllC$l}Gk1-e91!hMyT9iavPHLXyzyKh+&==Owg+N;(VSpoh zpp$}Os5UPcLzj%9&}36C+14EQoZig$LaghD=>u!J)xRTbg><1`lWo@`KJ4g{e>IwH z7Y_h>Z9xI8KfujHjkbcH&RLMof!NLgGFqNxwx-QN0P;qA6CarNwk68gpA!Q=NVaBe zT_oB7bMKs2;|JiGfzBPqW&{>#0-bDR2;O;9YYj~`hKd~Na~o>yWEgB04W`VcP{12Vk0OtsPT2GFcji*6%Av$! zIOwDXGj^3O^~PTE(Xg;C**9XibBXbuG%O!6a>s$@_uCO%d>279Q$Ujr% zbI;)bNo0bwj)CBN8rvrven5EKFO{5faTT$GZ}r=_yCnVYi!*TnocPE~>UUS8t%SET z!#qB){9*`(Uc*{xu;ww3>d!VVC{^@)k_ff6p@)C!RnT5@B-a5WT2J z=0_M_fdau42gy2@&HFaQ^^eT4wjABzQ*DmdD_z@yy6;_>+|xTh_YN{6|7BH=yyh_^ z2!20qGO(d`6%NJ`5z{fx%_N&$W0EI-pTs$^#qCvGE~&%0cHxL<^G?nFvj+g=#5AwI zgUi8GmOT36m39#Sdp;ix5g}TN4OEmJEp%fB+=gT4cl$btitfY5}eW`IAw5kp3pI70uH?6;4a zP&F;6v=&)CA17zqPjb5cC}JflgvqONmrIY#Wm-c|(dhP-5VfaP zJUm8*T2Lb&8%|A7!JXcT2^ZP9SRbD2MY?lFQ)r97*X>*_&i@_2zO}IZGk3ya9uPiv zCw3f~Ys7GH2jkpl@1yNY+-Hn2QeaD~I0MLQIv?GYcW#IVv(hvsINQ#%=E1ofL2u5^ zd;YDubkELVQ{Kj`Zh zf4tE;eG5gBn~s&k5lNnGV%IsWXfa0+M295~P?5svfH)!w?26}ra<90ZS?MIOYmk5V zQE6=odbT=bP26o)bGGy4-ooJ=tUW`cX|QG)@a%|?_cWx_6zT(5A&IQCTts)VYYm%1 zzci7o$mkIvJzq2wuR~@AWd9&`tq8p$iJ7w#*W;TNR*96A&axH#%Xj=**kdDC=~dp2!iMtCx(jU5M{HPMy@oyTHw|GnD6sl2>nZ+?1v%AnS-p>MM&m8 zDm0Rv4B8H{#!(IQ#6Tz4NOL7L=U`Dsm1gI_#@y4wW?U zSz3toCvPAM{D@8)LQ#Gte%>l*@<}Y-RmWer2F#~^horMkTmloFHWi}$i8>pEUTWCXw;86aVw0ZOrk~)syDX4p%l?448?_&0-bjglU#&=;%QooU@L+* ziN1Dz8p17gn^+6Bn1+bc?|6#b{&8%jIqrvPRN#;nR3|Io^diI}-oM2b`o)!Kh5vQR zaf7>tYkmsDcn`ysZwg>w4tBxoyt5s!bb56uhy>H0p{HN=O6_am9JxlRX2jzVl{J}Qhm#OWQCc)xp& zXuqnTfFz$;eR7L!0IVv+b!WAx;Pz8EO%4_AIvrPD6C!C59<%rh9<`<#m0WW!3}O)z zxJZ)2{LWj1G-!vD%+Maf5x}BQ!1=qc4eq?X`YxdBuIYQ9l8s#wc~4T9mS`R)wjMC? zCD5@n#+4ZW6W=+BitQ2p-Iu>sCUv{h3>s%f{(KIqt$j#b4*>9QHo?)%A1{86YLmyb z$=RiMG(OysEI;Jd1Z zW7C2O!+i;8gH4$rtb)yB9dZ2$uYY1A%dF#fmba9L%Ir(+pWhNx5RBnbd*0W*{;?&; z*jM53=9iT=vFVWKcBd%wwPo{h3e}2?NA%iKUcPVhK7|+KBAHAXxg|>F$6BBJO}Zf? zN^dgCMf4x;44AS8Fo#Ny=|1$h{_xsuynk2HBsR|iwkM!d{~9xNLh$PIJNsH|6ZOHr z)?7ZvEfNLVpPHJdW_6P9ioQVpN-1nqz0KHMcASrEobBdSVY`xv|MUfaS- z;xH^#XJp@>KJZ9krU$KAwG+GeE6nG+eHhR8U~Iq#4-&hg_{{4x*y^0HUG%e6fia6y zGd29)P&+4yv%h!$NRy=#bz~CcRZLj;9ARY?&h3J%jIzqwTo*Uy5yc~e(d$r3yI9~>}v=*d;=5N@|oP=Y%m$7h6X zdipf1{-xk!Ox``QWy8F(c*Ggwx6KLn-EVavO7mmt84o5+1XgL#M_P{xKnd}yuV+Q) z?Zk4e(@7#0$5B33Uosl)$RmnrA28~2p!UUoawsKL^+nI#WWOjYD1Tc}Ldz+x{vUM?@(v{2v@j`n?yF|Eq|S?f*13F)J@7EBzMr-i^HQt671G z>G^S#JW_J@KPXDt{gA}Op!m3m*wp{xQ0^rMMkf3#qIiXe`~6Q8#XC6aKTs5cr*D{> ze}IQi1glWE<`sy$;rIU{QuxP3`6p61?RWmaT@-m=Lzz1U|CuU?dFqJX)E2p+_20F^ zmFxIR*YJ*4z3s2DbQCXp=bJXp*DRe}tR37;94?t*FB@B3(ziITYl8hZQqVTE)-kX? zp>M9KYjOOvx%z2iHSM!1Ck>R38z`c6M5O_yowb(sK|`)WZYqk0l*MiOaWmE;+~y=3@V&P4zmb@JuEMqdpF-g=wd~MWE_0JPb?b|aBCCS@j9N1*=%A|hyT@mK|D0}3VoLeyz4Usr zE+TQ8@Zp4AL^-3&la4bMuwERK`K$dwAREauv<*@ErSm4++~h&feQ|9~Dgk=D(v3@R zANkuUhTP896SZ}JJyu~^VAw{5V+P}J>fto1g=iPT_aOw`p){Lp_rQ_jPL8xgXw?V( z`fx%P3&yaeZ^>d~{}MhD9Q6~{`_hDjNVrRjx*LM$WU}pNVzGZ`Qx&a*NLX!SF=b=| zAlsA6|7rpXb|2rNyqGI8I^q%gP@tGIIP@ZkA^h86FgT()Zv zThF~KdpoK6wSr+-!>a-!$Q&Kd&82fA46o(#vc#LEPX+&e;xY2cX5L8jOm*k~pf^jn zCJyj+P_i)c!LfbN8+#p%V4KbiLS6G&Cv}`$Sqk9QB8d%Q$mcGoFvL(nMF8oyAB$|{ zc-8|u9{o^e^h2r1#MDzI$pi#%`4`qETWj}%Yb?l(h!7z^D3SymPi{S;heOHTzdWl% zn>x84RAh0t=gDu^Y*P02xqOaCd}(h#-&Tpy;*aH@Gc1p&_tMU@3`}X{h$a5)(;SW% zes&N?!U~X){s^`ibnrRPNnN*xA2?37KD%TmQB2nrdNMET1rq%tuP>`v>}fd0%T564 z+HR$4&+|2&GxSX7gqu7?WxnjkcdBhW=$zo-H8SO&Pla+InadMxpm{~aR{#TF;^9 zd8RZMV;L;VYm|=lx!9J zPy3-~NyJteYrvJAAeW3BG$E(HF6X6KsUem-P2DWC4t1Hx^B|KL#;Lu14*j9_qpyRw z1Npl-el~W}*r!pzmn?iC7jx45tQ3EFrg-iG z{BW0y0x;~BiXD)Vs*GrzzL`FhNSdIev7pCB0fcGx=A}>DvJ_RROG`IIF`C4%@2_n} zz+{Npkt_ZthOJ>L!Lnw8usgayGnj8#>+u{vTU}MM!1aqlD{Z&E_B47c^=pnGdVIa6 zX>I%x3MEzZ0|`z7GbT)!q9(>%D0BlRsu z4a1bvuCixjuP2v!e}tw)E7Nfvb)9rm1~b2BJ{hk~BWu+^eVXe23guZFoscj3k|>9y zRLjLLTv=-M!Bj>xO32F1cMqoAii=-gUobrWR!Yt2lBAY3M9ym?4Uf90Za z*pueNogx_j1}EDwG5Hc~x1Goq7q2d45N|ps`N;XjIXolfaOHEFJNQM|Fn7ia>dzP+ z6zO#SsK9xI?RgoR>n8b0G4~%5yM^7CCy47Q>h6v}ADp+h>^Ha-srx-^Ad4L3rt9S9 z@4S_MTAa8D5Xvo+Wxw;<;#XCE#8_6XCqo>w`qn0di31XwYv@blj|upjf*xv!^Zcg zb_Qyiw)=nH+u#2RfY;I&WfDOYLq^l%E_v20Ou)q_;?X*sEs=o_wXsc5$_j6cdhg#{S#@q{`Td@K$)rg8MBRYvg&nK zwVyVgE#)q%bJk;ge2@jhJPbj%-J-`zX&DBoN^rB&m$t0^lGwtQ%hGlk?Z=Q2)>Obx zCGyAc0en*Sk=3KxwbJM91NDR_<$cdJm}Cz;%l$bqcjsri#g_rTsfkDxv()afU0Y=7 zC!S@ktTV%JZvXyVn2q^cHmsE!JTPav9yY&^{M6v9J{wHrnTHy4sQ`#3 zA)nR0(m9TzfhYv~5H*75rqCB0M1c;xwhrr8l*wfk3K%YB8ql7hGl}6P1K0$xgdy7X z!K^TerD&8A@-G19K>-O+fx0wk%&hD;08|$bM4=$1ba;YYjFcxq@1;~qaA*WZ0OH8G z0D!8FM6F>2$ha`uE|`p&zp->Aa*$-}1i*Ir@76>eZbx}E6Hz-s=YVng<^o?aK)p_t z1}s2u9md3xq&PqlSa3bV2#F-HiNu*`L<@#Q+tWB4$+758|8F>U2`VtqQ|^2=fm|4H zmbnuL!I8|(ftDdU+#>{dcK8D`0rwCB`VZXDQQ(9VQ9GL$)e$d5jusn9AOqt)Q1OAD z@sotadm}nbLOj?hj_jAf3yoeDCNZbUWNBV9f=!49x`u;!6b4ev*<(Y<2|EI|oe4)q zh|)_(a2x^kY4_3F4#yQe6TjRas||!u*-$8;KAnv<>Rt~AhZJ((%=V35WzNy1!UlqA7@jzM=5a8GzgFkL9m%% zQXv$O!)Mr6IuL>bnb6ou9NBNAQ6}jW4OX#&<}8R85v&P+D3k2V^z>V-Wz)w2Ry^TM z2B-Zx#S8^uKg%_VU_bBaCn%j+;+R=%hhHG4EbnA^7^WTb3Og=p=~zy=#F^$%jTgr7 z8oTkz)o~g-0YU*Fb^urx7Zy%200C1WsMM_y7?~CivY@bcvu-)l^b~oL!6tzM8q(O{ zkJxul#0WbI>0H8x(K7UQGaja=LTIUnJE=(FNLMofr%{UYZbG3_x|~I&R{Ya>hlh7wBC7>1r zSLQNCCQ{5<21`z29a(Adk*il4&LR+}9Tfj3VVs%mH?<>hw^KdrB7PD8{)Q14#Q`CB zE>I!thZE->Mu0&DLKvKcV81P8U@1mm1q&$=hVGq+hR~pY8L&-Sv|IwTY772_MN81Q ztwR0g)~U$Tg@TC%tke1(9!BlhqLof4%;G&hfqV?}ZqI*yD`HF1X62vS8G%N)U(3FeQ@?aH6 ztOH)E8|Ltg0^Eadi6(51!glKlWTUBEJye5dk@%AQQ`929XOv<>p37!-NmkL?Xp!+o z!R9WU&6ygq2e;uW1OcC-PZnD;M`70~)LQvM)f_R8<`T6bs;D!7{Ok#e0XzOIUl~xM zqEh00D~xLo4znzn#1-hLmmFA>@ByeGjj~R!3?n7P4bcpNyIkxzfS-Jx>*-QAXFzaI zwtjj!!t$xWtwN3AN~s}%OtI%DPCZAz3H^LC|MRVoS&QcoMWFj7p=j#8)OwD6=>i2j zJU7&jSqrU{fhz(i?HbVn>(@YoqzerBdTdHaVip7ok=cRoK4UXB_?K=eu-h2oVQt#fM4-*M}UO4@=Q;_pIiBW z%PBgYq{CZc0^V_gOe~-m%@wqJiQ)tpWeAjFD8?Eu>XEM(PbWdpRa1`Pjf2m>0_0DN zv+ajvh(3O(eDqan?F;R1F96>I)y`C-8$ydLQn5}#M|4WYx8R$W(&q+Wa`Mr%_g+De zuhH0NmX{I6-14SLy3UsoS9$~Jtls0)D{MN)X#mWwER&)HJa<{h?sD0mv0(goe#ygp4T7as*GE-*+E*`os|>9Qwx;fI)Xxmh6_PwIyg z(S|7GQNk;$v+y70Vz$E#y)-HMWk7MW1a}q(NF&n(2UC&@X*-IfkHZ}JHKHF^&pFj& zk4Jl;5U-gv*NZG-t;B;TE|+hbH69CZbhs|LJT9x3 z9Tk0k8SwN;1E1T=DLcG9t?9=|{^&lrI9zAyXv6DpotlQKW$$av4Rs)moT%N#?Mu}Q zg$?N&O=c}kijUvhRKJ%=cx}iK`1|A4F>(3`x&cCQg7`HYhU&zOvq1o`W8(sJXTaHR zmCjyzvd%jnL)mFBJJ=O@j8Y-s^)NE7%wq1L_z&FdlWlU8bv==8S+LeQ`u+Z_-D*k89Zh(~^t4r5?B-KYh96;EzD0>m-w z#Z2`1GOo^WRfwl&=l*BbU&p7F$NjHi1ZIB7nwQtkT}CJ*wKMD6d6v7vtvk~tM17Ns zQhB@s|Y)rTN z?T-1eH+SMY!w$O2Dw`9|@O{B|B{X)8+*ZDwEHX6FGkgW#B8t>w!0txWC-x?|9<;u@ z(gDF#fzmoo<@SMq1wK1fw-jS3T`yd&^(BvXg*JAAqI-0Xx6gC7WSzMef5Uuahw(58 z-%``gq{AR+;D9mpwO0@;4r8b2k}Eo-0_$(!gchbrAS79^{+{xkFgRz1#^lFICI)6d zol&9){OQ~!e1~0ln#4!r!2bHE^6n$Lj(g1bWlh*iwVGs$@@~)uuZeV?Tt!%O-%!y+ z)g)#}!b_tg?ffAhJ(@o|ihMG6!3Q5fdfy*X zxG#cbO)d?tda^zkqlP5GYP&>}$E@Hb+t0;xb8>7>g|4<du(mPBPM$>Ly6PmUi+ak2MXhskG9-#JBg8}F4=ntgV4L>8(BR~q$f z!a~#hrn%I3g%}k=m{Ko`zJ%u1A?gGK3lIJ{>ZdnsJuVAToT&t{vCb}hzyI~Zcyg3l z?BMh9*hv_NkELGA2&j5$^>8ZP1(0bYz~xgXH6{B!f>7Xs5K5Who0(WbAtvMz-eqI4 zx0QFFS07Gi>`RRQJ($Uq{U(=B;F@aVdVb$l;+1`J80apn1^A{Bx9-3rOsG-8F>hId{#c=3_hLx@DkVin`XS; zYp*o@HG5VS0-9&<*0or(Q@uKHI}2AeO-6ywR|~IM19S?06!N3bW=;4wGq&dk~NI_7E!uo+`MLHw4vtn zD>U~P&;Ew4)U5r^rbepB33cG=pwQHs(1j>D$E$b&tkvN}i{Eo`9_DxNuQ0JQBnWUv zH+b7DeOqdrbe$j_W%0yNb-VH<9zzcmF8wXFX$B;H} ziY(BLDNJZVhyD{+pa3a??99mJlk_0Rg%uZyv%t0Azj8irRNON#&zPuhZj{Xz=XdbmOKucj{w#U3pUsO+ zFP44#_~+Fp97+CEH_r)meFWhM7vw_3AM7&1X_t>uI07mj3JAnLjzqJst!^|Zq6Y)I z0m2=aF6l<2>Vm>h!vZ>7sFH39Frf$?3eW(N0(u}wo2@heA_%BX7-u63kuwoR`)&e6 zE*OHafPzViE9fBf80sdBn}Tpo3T~j3@*fa2s;?U=L9nt(k`&snzkjSN(SQ@(neQev zGgK4BeW)bEEGr5KVxNBuf+0y4<*MYY|C|$$K!5*WGvhOYz6_JRr1-mlf*@j8krK0t zEa1o_m&|L=y-KRcCIt&%&_M`44AD&z;au}P${bqAMi_J4u}AbuqL92F;pEW6Ci|q| zPpfbe&Cx*v9I%@LZyL4KZXS$~AWSt?QXn@eV6g}jy0L&7f}}$!(n;mA6uVRjdNW8i zWed;M_8e7DK1Jc3m)=|Dz4zVuCL5By{JuNMGmf~~BLxah7{gnRvPx zDq4QKq3~UC0)c^o7DcINVFYj5xZ{uO`3{;ROt3(QMa;P;FmV{;qvH#9SY#bVOZK=3 zkl7`VpH6_V0E9BQv4+X~Ud=M5BQ7Xll<5Cp)iNW{6#eGusKvZB;O}@odEc|Z_BrH# zDk*>i)@~wat3XH6riu+fu)><~2sRjDYCbFW)~unH8eW4Y;l_#$HjrYP^MoeaXr!(6 zv`$bRD(T^fC$9KF5&z=2XOO#`y6JCfrr_qB+qEfI^T_@jEi&SsyY934CJ*m}6L!>c zi77snAjXS6I_XY(DtLku^7w|MP(3BwaKsf~_*~#R4?8^6t+%&fMcwW9UV7oXI$wRa zZ})rf&qqIf_19;=efQsoKYsby-+q4k?;q*@tJ6nafB*jnp#Jg~K>mpjbOc0T0u{JG z1~$-v4}>86`WHa~eoB86JRk)%xIzChK@fx7<6sCyI6@MZ(1Zl6-wE3{zzZ5MgDQlf z{8-q)6yhs}H^gBMb+|(wDsYB0tYHs@_`?x?P>4rFViJ|O#03&@fktGa3Y{22C`QqW zSHxl#wYWttcF~Jp1Y;P*I7Tv-(TrzAV;a@CMmDz5jcel(vXKlWFi&0NJci&k&lFABqcdXN>;Ygm9K})0oFZ zW-^tzOlCIIna_k~G^IIBYF7W#n%Bf;Hnq7;Zg$g~-vnnk#W_xLmeZW)L}xnHxlVSr z)1B{xXFTOOPkPqVp7+FOKJ~dze)iL!{{(121v*fI7Sx~zMQB15x=@BT)S(ZBXhbDC zQHoa7q8G(zMm4%oj&{_e9|dVhMLJTFmeiytMQKV^x>A<5)TJ+lX-s80Q<~P)rZ>fD zPIbCdp7zwIKLu(~g*sHC7S*UnMQT!&x>Tk%)u~T~YE-2mNf)va%ZYh2|zSGv~Ku6M<2UiG?HzV_9xe+6t{1v^;6 z7S^zbMQmafyI96H*0KMOg=}OcJ6XzB*0Pr+r6c|zM$KBWvzP^KXhl0(2C{%4z97gS zR6vj)tWUM9g-f{rlPxpjb#aEU9H=Z>@)3kQ@h&aa%2wOV1!s!`-}65 zw)Rw%|)IYIjQz-vSqXeo(;zGJpiJ$dvCy2v#tI#bRIdH9@!CH7|Hq%w7?rkHsCStyqS@5eL`ywgx5$ ziWkfg7jq;L=+pmjH%!dq+4?xb9TBpM!50kE_93`5?nsdda%3fDzz1{KFM$byfo^aa zeJB`nnfcod>S`ea-S7cNq^klsytf-UfDf9xL1r_<=ND*ZZ*>VWhYxf^${j&%2oMct z@L74u=accCyP<_{6#CF&mUN%HVcl*J+R*CrGMGD}XFhj?Mq&vw_(-khZa7+fk?w7p zH63d0&biJ6!L#~M@CNX4x6N;k^L+07yoB~EeHUL1VTy#hzPOL{|hj%03HxD{NhK}+0q1=5<$2s`o>vMt>9pc>py3jEUKVLk( z?A@sPi1VFwg0KDCR%bdF+rSIrFJV6G3J`C_&@$k_!`sm$0 zx4&50WHxg860hWjTi$(p=g8(4f8?vb+3|)KeCI0-J}#>O^W6}=>InjR*z1qe94S2H z;Ya`b+WTGhaPLTb7* zi2a+N`wIpH5R3R@pZhaB|5L93gbxRVkNH!9`a2)`DnIfnGX_i_1C$>M1fcv&HTcoM z_Ypx99KiJxKoN^Rj(9&0RJsi$pcv#p8eBK`Nx?e`vjy-0hC2p7s671v!PS$W05rMu z*(^QFHQt**9Fj6Ev!5lzwb|33ARNM_L!Tb}!4OKhZt%EigO4I~J1LYO7E~Zgb0Gih z!a#!H!i+;h_W8mv)Gy@g!j6c;N5Zoqn7k4+vK?c!Gdw&0`GEXGA0NoC?dt|3$g%TL zLmX1X^s*mB#MqJ%*IAcM`7f;<9i>sOGdDp zpLYbudGkF*Y@cY{w)DwD_$V}d4dR(7?l)V3aJUQh9 z$n$Z>goH;j`UQ$qt|4SMg0M0rM7s^u3sz$s8j&_gl&EI!W+pLxOO-k!-aG@=5;6uMbebc}yQoD@l&vy`(fkKP$=s zM4zXW!y&9K)RMt&V9Ki;H1O%lc8kiXB#5&V3#|;uYQ#w}5(d*^xFjSzyzDNHpb->! zFGGC1Zn%Ov07UG%OJ&Tr4CJn9<45_yE;V)nWlTa51<1%fM8i&ooW&3BX>2w#MuTeiVk)dIA4AfVtWdf;xaX z)^yEoa7)@;%mchk&iuF1Tu$p+GO~-!Sc4Dae9a>?ziy~b!6XRmL{9bLGUd$7FY1H* zo4oTmPqpg^FK8~N48X}NG*WCe^i&^Vu!G~OO#jKl72}A_!ZvOci}lnx1tQS8gAYon zIrTZv^bD^5V1=v;MbFGnw} z>RJFALCX(2t_+n>`%IsQlfaI+Ns_eD^!d<=Q!awo& z#8Al;i*5YTAR~wz%_SdTO48!eE=?mLSgj2BMlU7PGBwjPMbrN@Rns+P(>8U}H-*zU zmD4$;(>k@&JH^vH)zdxY(?0dnKLyl471Ti`)Iv4XLq*g?Rn$dg)JApGM}^c#mDEY4 z)JnC~OU2Yo)znSp)K2x(PX*Ob71dEC)lxOpQ$^KORn=8x)mC-YSB2GBmDO3L)mpXH zTgBB})zw|))n4`0Uj^1+71m)T)?zi*V@1|vRn}!?)@F6qXN6WHBT zu`q`l5QGT2iBGVBHZa+a00T)#qMq%Bn3W%>O(d%22yEzvpVc3$eJZV$pK>q+A|L`u zI0vzq2bArGC$I!|P@izH0Zq_^rR9hksD_T{Sh)S4QUHS+xYoMmh??z&bEttwh}vp} z1R}TrG`I$WAY6_Zhp6p_a5&t=#afOy+muyXw(W+-H4gZQ2TYiP8~6gRg%3f1f@^>R z9B|s+K-_}tJPUB>MQ>V>Lsr~xAA2F-1saUgh(9I>uI+{(CSBew-EOd0f)HhbAmwhD0wPcjf`Eb_?ub|JhFI>1 z#m(JrNQZ8yS6zV^1^;$tlW{y~9f;T7_n4j_?MD*5;@>hiItbV+Pmr>DYYL-ShDWHF$ymCSbWe*bgHq5~j*wXdF=itmWE+o#g+q#%A=XTr_a#C)nNIKHh*H=zo3!`~7FjW?}Wo>Kd2= z=|yST1|Mkl*tv~vm_Fsk{%Wa$f^p_!+ZGF){?~3eSU^UfH7MEjUhnCRVX=@C2;w z*c&i}jt$xcf9Ukt2Qa9COn7SbZSKPE?vAkTZusyJA92TJZ18bxrTT&z=vc8R+P3b9 z03Po1iGo@d@GtO{j(CPoAaWvCgBgf~PiTh#uGygNi1-cS0Dqq;Al;&UYULdSLC$L0 z_HW~!ZGetpj_C0x2Xg-}PiT?$<{j>c=_ZIV*XlCw1`n|WOQ?aY77I83abH1$GvMgq zMc*1wUp$ZDGH3G+Cy3={bHiS9f#ryOKy!j1f}M@=r8?b?D1|vrAHuEK_!eJ_Htt8Z zp`niFy0vq$5bgL0U?>pkeb{k=fP@_Gxb!G6*KT-VB9LfeZ}t+`>2BEZc-UQ#WpiFWMVDL!?h86@%_<~<PVvCi{I}-(x&VCA=li-3R3c#JXq}`7E@#(&BsN&t Sk(Yf&8UzM>zkT@$2mm`p3*Dsv literal 0 HcmV?d00001 diff --git a/repository-reproducibility-bundle-guard/reports/demo.mp4 b/repository-reproducibility-bundle-guard/reports/demo.mp4 new file mode 100644 index 0000000000000000000000000000000000000000..6fdfe969f4316ecd24759fad558e4a9aab505e66 GIT binary patch literal 42990 zcmX`S19T=$us{67wr$(CZEl=Av2AN(+s?+ejg7Ohv$3&p^5wn%d%tsLx~r?|SLm8K zgPs8Z0L135UXE5S4t4+lDB!>TduKIvH)XMNWM=^Y0MO>nKp+561Yu`p?E0-!3kmV{ z^=nh&wC89|x-E@e`c)lbx7>*wn!pNX+t0Io;v|X6*Q1 z8YYG&R>m&>Ik9pE{!d~aKr0JNSCeml0HhSpyZBWjh#DkhRwo_?b1(ppu0uqepdf1n zp-_grlyRjNZ_-cTzM)-3dX`?s)Wlknq*$7UF7VAdMH1`r7o>jI5){(i63hFuTq3LC4{klp%-IcZ*i6g?B@ig2Q@o<;Hqr9W&a0yo5M*kpk z)5O;w%W@J08%lD;)s0VXG{VIqVSOOr4~Dc4^NM9lkCKtB#mhG#PT8Yg%mt$Ah=|~| z0*H$AVRXlG{vnulY%oNp!c=Syn@q6wLsCg(mY5466-{N$H%OmU8w2OO9J_{zw9cV4-p7iz@pNQ1hEg*;E}Sn}c}qt% z?;XfaUD(ocIcrwp9_y}h!LrZ=hy$yT3gsZDhGz|-Z2RX;VfI(8=~*(NtX82;z}U5H zn5n>9QHGMF(S7|j#JamNdFFp9iqMStFNJ#+x1`(!ke^>d1XyvHlr4iJBlfRCP$WHC6StvC-FE^;>;z6E2n{0cg-6`Lfuy`< zm?K7-LG4HV;8q0r3s1(N~rjt9js*!csM~fs53>~1TqO=9yYE0N2_%esIzSedp zLea8@76f_)n6Kiukf9JS+aqxG9`A>S4ZKd5KXV(BIZRJom^1xb3R3u2eQVioaW_Sd z@t-sro~lcE(zxnE8LeB`882sy{AzEzKF61 zmuQ@rNsdj{E z{cj})sm{as?6E-}4k$~}mOPbg!gH`Z=p>idj2SDzXp-=(dF|pCi;h0H zXa`2U1O2c5V1m%2j3#Zpf|%+yoOOoUJC!|Cei2!Fyg?MAKmKxhn_rG*iHT;@;=mt> zK=XolCPZg=7&=v_-tc@U-tn@iuPiCz!Q5$W6qM_dOdam8MHvH)25;wW?qd!tAvgNY zYREG=x;&rQTtUnE+S`^X?G`ZJLmpZ1trW(I>jIu=bA1QWY{7$vSRB?e_YzYQZYYjn z>;-Q$!Oy~f6{`pDEWd{e#RncOaFPpTriGa&+LrkT$hj3=y!#(4fd}SI2^M{}frKuN z-a0h`&HB5t_hm-?vvvDu_!-CfGNdB>Ue`CYLu`di67ppt&-({zfx&9j@6u+6USF?k zNP8|8j&eOkJ#(zK+ybkumPi->T_m>M6w`S>Bx-)4JTJV{GvOxBIY?8#jX5gS6jgXa znEx7{N~Udx-uv(+-srC>l)yI>nDLO!8gl9b9voQ?G-S#brtIi?vI-f1l`9HzkY6(- zDn4nCZ!OBi;H4<}#o*q?vBHUm`v4y_n?Rh)`EEyjSS$22O>uO>Zz2i7oP#0 z>^<_a+QD@*RV|Sqkd|s=ts}R=C}obgzKEw<=1#;wp{eu&Vz;gFA4}(5p!_^{jP%(56~5Lm0fn+S0y{ zK>7=U^R*tPe~%sw4z17)O+|*UD^)|4Q|%aiUjJY|y%)FDk?4{IzNr@PNh(@l>u{0# zimt+GR3Da$E?+o5#+fc?)=VgvaLiOx$BFG@|C;?K-A#Y7y%Co7SgKHK6xE{ z|F-ef3=n`@QEWt!<@NQ)vkCXXx?VsEe>1m}xeER;FneV536(h0uO;OS^TwujX+sv^ zUgQryc{As0QTzyVR76^BBH_-To3Ag1(;QqU0-UtYLrvTt3D`&z6)<#-hY>C$!VP8+ zTVv|H46eWTjU^#8-INLJTL`Suxz8l9MCZ=r@p1vtFcx53KrW=qt4%E_>UFddjIb1p z4JtUvF6r2`z3E3=?{!##OutR5Ay+n`07`|enFw&Y!Wsk^%Z@Nm*}ne8FUpY%ZRKH2 zJA$U!P;YxumoOFqDV%xJ&rLQgVbxYTpG6D)J9fR8TClasVPR?g`WxxQMrh)&!PMcZ zV8^T>^y2_P@Bp?=H_rLtj=Y)%EwnFOW0{D(`5Rt;0%|&%WjqbD(;Qr;9O8NxgZQqV z5#PZ`bM&7i9W%noVfy_h4UbSRgt8O|6;4@OA_0EZt@0G{)6}lVo=C`4h!`f$#s(}7 zZ6PtF`8=2t?8ZrJ$$w}YZ{{gpMO#$W3-r`o?t;6X-zR0@dnp-;c3eo{END@(&u=x% zo`x^fifaGHHIxC+oM~2=94DM0@x7GFLQHd)roB)ONsYeW3}Z+#nSPG@Uxi=2?Q)*k z2T3NItooL9$ZzK3tQGlW9BMwO_Y;)`sH$a0SKY37ApI0EV2iP~VWqeMCmBvzBU5g( zScpi7Lw7@p&rKUdTN<_Zw~ME@haMb8wPPyJ^Jt3Qqr%7~=|%+H_2R~xqr^v@cjr

IFnyj8^3!vZGwx#KFV)vtw)?_AC@kf5IxbVgSw`_=VW4W3@b1?0W4(WsV%Z-%8dJhycRhVD%MgAL}4YV|8|~=9{l#tb2^vc9!X; z^Q#QZBHlJ_HcSZ}=zn9Ix=YjmQtZ+jV(Xfqdgmaf<}iyV>&hJ!KTZMT0Zg6()AXll z9{5$A-|mBja%>Z$Ed^{MJQuwB{6&P??qLPSD!&Y~ZqO70FNTD8XmD4&_Z5YUV12#H zWSJT1pMo+P>~+RP4jn9LAJ&6|cU5YqoTYPjLx0@2|9W@V*!B_=6FAIjNCj?`NGjdH8p~mQ!V!cSMbUbM9Db@1+L2 zr)$oyAkqKf-j5yAfJOOz?V{ zWO4wYatWR6|6$Z~pX+}OKz>)RR`PRJht`>Wfz!O+Yc+C!0}HfxgbQ&e0`#Skb0e9o5m<^4VQWG5fccO&r1o0;#@+l0@q_rTqs}AQm8ij^S6ar_+8^r zb$3`tkE(#^Q-As65T+|CY;|b}0h$Qe>^a8(yF9fldCF+0)DWqyzL<=c#n0F)SJS zVV%>Sf=S68J^!ER7n>B1CJRP$?3OZW?;!9)7X(HUV07_HVY!S%XcP7SJn`P%W-sR2 zNzw~&weLD#HyrNNr(5t;J!at0IfqGF4n-k_@Yi{cpd)tDt&#U}=H^b%WQudA}EhC*A-;bmYw8UT~VaI2mNW#v@DVjGyWq>M=w)WZiDiS>ALU_i$-r?Z;$ z3Btb0+EKWb+Lv;SR8gyFXGT%ZS@rtc&Hc0x$My6pLnF8rzT#04GPi4^34Y~T)>!A? z_2-iasRdv9#No76>=>O_w)G@1@&uy{HA@X?R0e7ow|^apt4hgNCVut?qynC?D~LME z$yF_`*!WmF{K;oGsG`Ghem#GXyM-9rJqduAb;U1=+}Su-L#Z0xR!q^4ujUAkIm5LM z6np}v8`x@!q1irnwrhXD&92UN7q&>(@m!%N-VsiE(lVLx$!~sIX%1vB=~dF{xWP;M zR?h_qx3p<3|IrX-pn}_MtWPuL`@`FSb$?dA2kEx+pgDs%`_M_vOIssGF#-qe;wYj$ z;<~5$LnMa3R(m)vnB%V%p<7fc42SB*vZhL{{dJXuJFLCzGD;B}D9g4UfMAznJ~Ap% z$%f7eoL8xDVlv>=qFLR+=FvW3>`<>>X%7A~cDxcl`tLU5^8}UPeZBmfe9>gkbK$Hx zHRYHQ zh2@aEDf*wrN}yCrJ4^>E^ul$`E;Jk4bj?HKqV4Zq zhtaTv^y#Y=Oj3ndhsWZraR{l60Ku#Z@eBjdh^xGpot9;bmp9xpOkB&(fD!F-SheN5+nO;N?#{4HEHhdgKjKy^qlHvew5a9 zOo_Q*04OGM^eTXS{M>7;JM+Z%eMw2+x`NkU(<~z zTWF!SLD)LP^0w`!2Tk6Ty9mu%=A7kx0Ha1-a>F@F6O>f5-y&wOz#J zvPa=}Eftuti#OI|tqJpwcC_&KIjk(;9O%ytog!kHSZzhEpY9$I7=hGNjn6N5KiXR8 zyaa;$qLP9@bnHu`$d`h>E`*3)YD)aEG91O3VUcOl^9Cqw4zm z5-)n$gn!Bey~CeI8~6NngcghJcjqrNlUTh_f=zrFbiNmDHjmEDIk)q6g`sI43^qCq z*Fk+$#G5Q>K?a8*P8|Y2(Yb;LyFOeFoG|l-t2|rqLii5MXT+O9Zk??LsHBhyDkuTe zM6{}><;?>l+x&-J$4n!gUphu5uib>;-XW$Mk_{V$4PLi&JNoH2ZA;X2h-<(h|C1DJ z%qKEQHtX?xBOILWEYD>}XwmY)Xtrb#D=)!o5-(9bMXMkh;}bap%|#LxH_2e|YMBCC zK%rArJ@no@!?PN+I;tL|_h=z!gJM+(7aa6)`P{gE1*LGun?B9llKzk6be%6?_I$2> z(Q9Jlj$J^TlRgR9`G{>q|KfTST91%7Y3O0IAbjLz>E_2smLL`KVxZ^8IjqBrrer_9)NAonYrnO8pz%W)xqN(f2ybLb@pH{j%Zp zxKl&SK6VdImgL~MDQdq2y7z%Z{apCcjN+ZavBxPkB0Q;q31?a|C=cLOCxirT(+Bb9mlzQY#PZ!M-JT4Sht(k2thdqOs-L|B^XGw*9mDhD#) z$(_3cvCIV!ER~b=P%fx58ikXy3el^Pv+Q@qgvX(4uXKq9$L~B&4|&x|Bb^>%9atKC zc57$Tu3dziYKwydS@gN9HS|99X?yGA53SH~fL18E^E+qMkDqK>B!3Lc54$sM04=qU zTp<*HyC%@rxgP=o%!KPnea4t^{TFPrMHvo%K1zQE$09#Q4F?jZ3B9`LR#zH04OT}w z#+9i!^^QIH0FED^+I&TxYb;`&kO=})0}Nj#ajc#j`8=w&Ep_N`eo|j-k)G%=_8@9| z4?nM5p$xn_Wp`k+x(Kn$(zvBVFCS~WhR5XUnq+I|_-xF>4&ufBEDv&ez>z|neA2>{ z)gh9T2bq*1Gbw`&2H_1n!(*0GvR|4U5f*2&s}ZCo)MwdbwfIa>L!wy&Yn=JM**uQ0 z-$AAXPyN+s`L!cFaPo+?=w$Y)TEw>Hg19$IKOJV3!qzoYTW^qT)g;CKY`vCZq~l6< zgSRKk|7!$XI|ml-OJbmAbjLcP_0e8rjb(24KJ)p*I~m)=y{LGv!BphztN2((?8%HDrCk|gZ$PGF&g!YzP4?tQSXC342#i@ z=Y!Yit;g7mfAU1b(CxDT^MsN5YOn>g=G_EA-T-lqg-1-PS17TF4cy_H3}SRA1liZ6Bg?U_kEr5 za;z}8+Oie)+!5dQO5Lho=(@K>R|lY~Uct}~5bBjFZV~5a2peq1k3HhC4gx%1>t>32 z%}wlwg1p7~HQb|DzfIAOQP1R50H`Tk9QKr7Hpv6Qd1OLoccWAx;s6s!orA26-`y~& zLJ~nc(LM?dLbEym+Va0w&DUD`*ccJ{NjotG5jCKkXw%twqG(uJ5E3K_7)k+p7!hNc zl!N(w9YxHuiU>Z`A;;zoMYQ65ZDC*bzj1o#JkuL^(mN&iH1v}uP6)$Zx_7NPaye_#xDPfCf(5!;d6-PK zOk@|}zPr7M)2USVD{QU~-5~9WH-wms(pMAlSTW2Zhih|V3wn%@d{PDLSD6YkY2#j; zJ!O+VRCF`d58PQM;#m5pQXCmiaeN75=6@d{A01^rM3$xnQHMtd{1H5ue7D4&f!X2a zn$CNTuo87ND_N-|mm|HPRLk}WtF*sd8zrt{8X>~)KD*mklOS_M@RDa*1wrD&16)I4 zvZgV!j~c$L+9XX2(DgH(bvn6~OZDZPmz-0hIQ!Zli(~~#By#ZuLGh2T!*_*21aX{E zgmwYko}~}Wukh)9bze8$K3ay}B2L+n&zxC7tlrc3H<#IXjGqKy&wkSEK8HxD%exozirH5=y^7r2(QnXK&MN zRl&vNi}@7AjOL{Zs^IND@XqP*;DQMX(9|+&z?8AT!#dx|U*mmOpdjh;?P;T!eA*8Y zM(lr*CUv>cw2^A$mx$ph*|9`6|@LD5iFy2Z|4Zrg6%tU0U7-dDa&rv~=@#Ul}Ap zBxe#8y#~1+sx*M%DZ^YqYzdN?;pDCvHbSwK5D>$fyGAZDz3CMx>2}{37V6)Omv;|F zG=eWl7*vlNJk=LnBO1PM!uG=Fuz;k8;8+jm6q$5p^Lj2z6}oG=vr+ttt%DPOZEmhD zSs3+rrE-SspM_59rv^>$VQH;7Ht`b=6)QQ$=3RnRPBD5a-i-fpoyTWpzV2(+Pw>E6 zFxhLzKzqTg!EqxorAQkcuMdAh+vxiumObG+AZ3!ZZhffNI3i35NNcYfx+_GGoA1VglwgPwLngyT4R1P2 zBZL(u&_l0Q#pG9#-wjkh(Kf4IiN?4%nqcKSV%MmgTq3$Bqo^)6OZ!xL_v2u3f`?T- zRtv~=oj&csbV@jhI2y%MhD*kG6KRK|Hf1_aa9o!PaAuPMACsCHYIjV2=+5nK%1E0u zAH8{OS<*s;R;ekw#I11~PsSsvgEp=M<%B;I`{2h<=i$nOUYRe1 zBvtn7R9OMwPqmM@E9RAcbb*iy0m5Lh?nWfP=RhF{cG(Ph@8`67uxn<&3PSR+3L92F zX=5Zeas-_GBM|aPQ@!k?SjB`SfPV(2=44!Xi&YN_*9rgta1M#>(d58i$Ov*n*Zc%n zPqN)vu`*Lly#!y*Zklc9l24WjIvJl0j~mTRCq1qYNG=O-xrjoHLVlqgaiEg~X45b2 zWj_u1lKyci%2NGN&GH8xGpPpIZ6j{|weX+4Rb};Db9xfi&CBI_jTE4yjx?u2#g^@5 z5ULj)C?CoCz8ZUn&fDxS{uw z7<0n?qzrhf2up@BPgf(t4v^}G>C1cciG4}{~K3zzEz7`n+W|{tb(4-nv4;B zY*8c3Kn|P9MQBLmqc5sN=^Tqy6uq>%riVgf9Ioh#S6!{Vf)R_B?Rwh_&tLs_H>P01 z6%kQ~vaC}gG?pWekE)G&WkT>~dNPrYu`kTi8h!hj!a?&1)#>SG9FE%A=@}A101X3w zGGc(KKLY;H;uSbv*l!Z)`rm+SymQUy*WqNQfH7I$*o}(v^~YB{8hL*DXF0pH0a+Ww zf0bO#gn9L~$8NpU5r)9MPvj@>M?hCjSLNyBc98QrRzk@>41Hm=BjB~ME}+An8{C#r z<-}tq&!bP7g)}nrX&lri=;!anxyn1N9PeYntaKQ!7D7U_d2c}VUUKcAt@Y9MDB5e7 z!w~MAs8)a3oRpjwXM9Ksj^buy-gM{Tz&o)aF`=4l06>o-=y6 zdED)6Jg)xO7KpVE+%t`_qrhgk2mS5J(>XM2>a%*{aISN#%rgSFlz41$W)VE`hk2b4 z(madK4wXlYl-*($e*rQ$tdWQHS*MJ#5X_ z5%bL>=*r`-u_oKBnQ+GInEq@@VDRsw``g`ZOAG{iQOL~3v zmav0U25WoXqe{~QgFCf=fJBzJngZ?k-ffsRFr0Zt`|~5G^>#k%bq2-D7GuYFT=#P< z`E!XiwPW~o&zg|%Z2!FvP01`cqeP)uCkgKvh^Cwn6QR?}-t(>z#UJ3tujGvnyc_3k zz{urfi&3F!{=l!Hc3<`S7ijbzXJWUG5`ToQ+!?jE; zU2U06WNo7AN$vhIctnq#7@n5HV30KxeY3=>8gs<^3J2+%kUTO@elfT{w;d7>-|!!ImbyWp$+Me!*pv-L6d>E%!s@Y8eZTQogIw22h?DUz zntbe^Y=#G%Uzx3VSqhWWnO(6_=%?Ny8|An&Gn#+(m?-7Rwqp8C-70ylI=PXFk+IB0 zOCPd>JXu+m?@KYSZZNGSrDEeG!HlI~!|1U6AtJ2h?lF(7EJV-xX_B;w(cX7pFz=tW+vc=Q z(=D6`8$#y7naehjujU?_g0|8xz47kA)ZrF$Faxk-A)3^JPh9n&I+%b2$`j;%I#Xk5 zQ8JYFrt}~t+fXtY{)uj$d*Kf^-y1sGi4_u8bP@Z>@pkPI2!ADqn83JU>Zkef_lr<8 zB+iZ_qmD;GW_!k9(L!$YFmL)MK)NFqx4*aW7@JRDJ zIdYERj-etv*=J1n%y(m=bdi7!+B>eJNYt;f9$%z_YipMU@-qt>jaUC&O$h{jO}T&Y zRJ8kJf&v!{!WA{q*T+-%ex-JA1j>}foxX{UO<^N4K~PS+`H!jfH`${q~}daM?qFN^S@5U9n5UmXzX+5Ri2(9i+7&vw7UHFNCktL zX>gbK`;B7+8T^bYKz@t~zi-7uf3@r^#ye^%fe3%e7(*|&vMX)u!%AgW-9EI=Q{*9r6c!>qzN1kUpqDAn!0jECORzD3VRBBObU%kD;$$F(MeVhVP20IKIV|!lq#p=^ z=@bO+jxAsG-7qHbMnZeu6GP=r#Wi!^}?|JIepy?WAHph zPMs+o3s#t?&BrT7{dRZn^v?HgIf3S}KwgAl%1H+8_?EVH3ErfPTNZW^JS%^_(;}_+ zl*B0Nw-=xNaAc>HB=1f}Z6a<~<{iy$)3vh*rt$`ki7;hsR9jvWEU4tUKF+0iAd3H| z>##{{l58O*f;Rc=6zXm{#?o-Zk=={^MNvIsXBsUoCPl6yFPqZjctKYD-}e`my%IC; z1~Op(_71W2WVPn5R!VkMM;PllKI*L_m6Vi%7y5q{_EF7@zbrOxGL6OD>4GXYa_dZ2 zDYH(V-rS8W=?8A{E>F{s-&HEGElmxtL&tD!giwFo4ko)o&PAf^Ik)8yHWNiE#(*Z< zx25M(5DxxDzf&FQtkI|IjUq`w=t#)Wrlhe!{2^~Rn3fqdfnM%Ov6P1frA;Hb=$j0= zE``=dhEb|pa&EY@{NNiq=it!XHf7=s9TRM}InIgHPaj=XAf*M_WTUPS#$_emSelPD*;zx6)34q~r>O|^o34EB~7 zjDWPKt$9S=ee#a z7d*j|&tpNb9PNnu>Tg-MgY;fKxcg-=om>rQosDp_b^iE$y2`)jJe55j4V~_lR{1ZU zFS=;kC5J&{mAyEbxV8*A&b{Ah~ zhpqROU$LtA9-=mDSg#({N|#~Bg@q(Yh|Ybw$-3Hje1}!9`8D%Na8IYgzf{* zgoLySVD#^aQnjyMEwZO`{toRsgQ=~svzbx)!({K8$nf)X)|BuxYPs>5W_E)!;VsDa zUFcvxv=OLM8@a5x$+VEX#1VRJk*gegC+c7?V?vK4(ZX;YwvsjZ?3!q3=|QOCGL)bS z??i>=MUT#dDJ?c0VT$?own0f9D zKVA(@Zi^!RA{!sd+xngOmnYlDj*F66Zu>)t`7jhoG@@sC*!`va0FM0MWA11Sw2N6| z{1M?8lGcR9R}m!I3BsIfP;@AeDPRFvzb@+EPS>tr4A1e|eZV|hvcr;V!$bA7+-fJ$ z%qmL6%QPwVREt^m5{IS!&5zEtIR;wvN{WcXRAi-@%bC(AqTu2vC1psSbs1#YK7(~Y zi7(vbTMM2OEf(XC-Jgula3x}*%A6oPz6+FV)*DLD!kqBU-!~pdZ^f2O+#r^{XoQxu zyiUemW=Q_PIr1CAlB4%j5ozSn=$6pgMyyxOvu%|tdfQQ1DjxaK01IEKujL~Q` zSL|Xd&G~Pn(GF?M?lIiaEd)axAAJhLpptXak`Ts226dgNb4L~ppzIw|%5}%cx^T_x zcGhv85xBPyd(|mw$`!=XCzt+!I)qxarq`C8?O=xtrZ6AX#O8PrQ-z;5BA zNXlCy?o|)^LLbor$=(cGv+6V71aUBN5PmAu#jaeV^?8lH06|DSgH}F?Ah0+@(_NaK z)J}1G@OIV6xIjpJ4rr*AnH>{B3X@iq-wx;hWX)gk(rf<;v>mE;w2?hLNdXexQ1o>% z?7GI!(IvIfs@;Q=t1b3I88b2QK|j{8fHQ2hDUnCqI`c_{^rfR-zxCYAK|dvxZW)@< zaU^^6+=!F(dhKEd_m=d z8!y`(gyJy=4)O&n3z)o!8VMfm@Om$pc;O3{qIFGOB)5TeMPF;R~cqc--Fz&IFe-tMi;>eQjB_-Lx@uLU6t(05(HC!SxzDh^kXB`z_>(r!T_+2X#OzrmawUrxoSjpF z=x-77Rz8@vnL-tLqg-l7agblU`^zyw&KI((AQw8t-Z(tR^zQ8kWo3nM<@(GFP|jhl zar>EHlva0#f7uY8K=6;(*OQ{mPvl7u*znSl<)4jrS z6@&m~)5FJ0`E4j2<%8GToWV4K=qA6govH%gCApx|bE$%o%HYOER|@X6iv7dl*DOUC zFYX#o@Jo8_*W6LhAC;z72cKW~c!jhcPVWcCPmq`ix~YHl#b7LvIsnp^+1T z6h^d1LY&_VpcTssAXWmMo?ne4F|KyHY9dH?ju)N$x5al7Cha|{HPf^~L0lxp83GRF zr3dzvb0E%nDbM}c`{}+{j%Z^x6qmURRd_TAN94T~1F+ytKlzXe7iDC%_X2As8am1) z7HvCL4_22sYG=NX*PXtc!d$s2B+booPThY~8A%GnA?;x7Nri%E8k8WUZZ% z!d1}F&su9P!_+(n^mE2iAM&95nj*zRD1on<|2~0HK64l8hykq9H<{Vg2vd9?G&;xO zz9WJ{z7zXy#L*GyC zJ;yYnp$Zra=-3WI(vVCCj+dW=@Ez$eikO{Qu)c=0JGsASnF&%|8?iIm++xNE)bfSe z(kJpRKJ4W&K&40S#DPZS4}E!H52C&F?i>H~$a9Zj5IyPvSiT6M69S(&x>Q!M>}gz2 zlwEkwJ3k#Z!8ClZ-dN(}E9^aNXC!1Mi&NH`vU5@Mo@LfU;{>F5%(ThIpLiq%eQPyyhOg@`ER(Sj;Q|) zI*Z&^`F@yNP)a?^gxSVhpa|}5PEFb&S2MPzNNvFjHq=x#?|6Kq<0Q)5#3}ziH7Wek zGP~2p;)gF>cK!1_U}EmRbh)$qyO1Qss|Cf^D~dJk2-QXtXvw8mKtdhWXe? zx=RQgXvMEYtKeu!MdQ=c(U_epSltn)Si@d$l%RcMVCtQXj`|+m2RukDABaGF{_t>8 z1S^m1HuF@6$zxscxtKi$R?RW(KyLT)YcDj!$KMv7?L3%Sm={1lSx3DBiPU77b|dq-OAS{hvU+eZ-Mgm?2wHY;#Nf=lMu zdL)PzYzO@dn%U0#kARfU5%$Dzqa$J5IBoC+#>y2_%R2TCps- zats1p7)XTb*R(bUKYYsBdbIj7qU)dCY@71^W;2K+F#m*JCyw|a?>ZiNqT8$+PNm(J zp4<)8cuV(>6!9P4j9Y7*Ux6nhjl>^D2?-xm6xntRvn^KzM-`wC`^}oe4Z>23c8Ypy z5~WM+L~-a&?}L|S-cY0qgyQJ>51dL_Jsms8JrH#(`TUAu6RD-L)4#Zi8nI<#>zx6h zOu%jn-VK6HZWQ%h7jt}2=DYQONh*jGMjGi_3X+8n_sc_9HT5icdriycIsGkMt^mGK^sv2@9(lX zW8vurTaOhc8da=vl9DXUTJR7`KT;T+WWt8BR1iNhsBaz_a({&%JN*X$^V#``s_btQ z?Sj$;EepOC>jz-YVLGBe;ojguM>Ji(L(A^`2%>ry`iy1FxBpFc*N1bL*JaAiy|Q(_nQ17)X^(eQm*^zm$E4RC5f z@=%bP?h3U(t!n?s=bwj%!(ro|O_V$Pv!3~VqKgmQGV}6b6I-M0Opd#H4Nh>F*&Uf0 zPRL)6IvnKmIPm~ALdVxGmX*3LmyF#UU9n~++Yboacrxqtmo|_J86e73P1zoqIva_m zN0WwAk9k=bSk{H-aXeanN?Njxj0_?}vTy(afDP>Jg!sMlBKw$7~5`l=?C% z9-v`T*Y~GvOeN!JzI}TSCCDhY1VuywEj^BHr#pcN%8^gvXH>`wh}cOr__L9FD{&$5 zp}nRiMYd$bJfx+kJ|*w7=vBplbfW3sqfS%M+`RQ>G3AAv0zW^yK{ zw|O-|4Ul*Qxtub*js30t?1iZh?75}=AIPUMc+~Gp`J!D0*gtpYoX9)_jwTteIJH7D zdRNr*@~L`R8&JQ{5BFT9%W9{XvVwJiI9>~{JhG}-X&j)B)kxfwcKbUQDVY1mQM@ZQ z8z}>y%88-0y0yU*7Ldf`3DBIli)<+aWZcb);x3yFqZE*lKM5a&%L!|S5?z<~p#5KO zDy=te(JpVobn(ER{gt@D_KC0|-PQ$Lbb5cD=gY-ibWh1fT$=P3u}P64G}Kmb_=z-( z=}&7^z=B8Y6NUdsH))aJn#5T%%PG&1h^CUeBp=y3?)6;q{ z)QZfP7vD%nLv~Q|P$`z@{^tKW2tAI`$94)PUD5uUYy!DLTxnoPW0`WTp^*yha^7Sg zaFm%eoQ4BfW_LW~d*pKyCb6eMF*#k$kmqx*I;8fkaYh-SI^XHzgBx@>b58|M)Awz5pW6 zLGF@Q-Du36$0D0<{bDfhj?vIcC)>uIa2`UWg{T-PZ`iuDs3WVhn6@7gla7tQNd&4S zr>4mYTvXG5w*n739*~-PSCGI}Es3^%%ZYiol6UET#n#WYjqk#7R zdd^Xhv<7$k0lmiuXTmHASfC1tF5BNud{iKH-Mo0Y+h+Ad7l?0{)fw4P@k zX{Z}<>!gC;Q|FS<4EEThxAVA0y$FNR+Wrr!ZdeEP=%0@|$1BKNv+8`f#*MhYf%g)XCCOuZbW0M! zZnNMt**k=rX&CmGiSq8;f12ZGpKw`CohpsZMB4Zg>V?->i31z-eu1wfhvb5=6B|j* zP#Dnh|HZrbQ4nr)$CP`)^s9!V<~~+Z?2(&HGTL%3Rr%(KJzFS&0!)ey=IOi6H$>-p z=4q7S)vKEu%x7-fr)*F0AH-x{6DL%s7HuXgwPIrCN%u-dgFwRcpzQ56SKpr_A3WPJ zns7d-`1tf4Fr5~C%n;U?jGiMTa|9A3<{@w*`WELt z?g_E+CZD4<6Jg#+1yP!c@x8TI<}*}>Rdq7&eg>BeuXD!;tZ4jZ2Lo_p+^Ld;bQc}qry5Q(#`#9xh9TH84DetROAhBK!asF`?L^D zR;{n+qMw#fXa=Es7Igd>MbmTw?o$>YMvN}cd%7PWe(yJNs5-x9Jz(G1fnL>MPb00t zr-%BIX|^?X`P?dL`^JbhsHHpHF26`cs2p*nvYkMG&`X&F;!j1Waw9^OPCq3l#MR6i zOcwL#`Zcq-x@(k~hCjzhj`~suxm|R)9-i3*^T#BB6;am>I7&@5zxF{xBHN^N#WKEc zsWvG>k~wm@raJShJ@T5O&MC)w4%Sp}dwvRN*wCjg!{1W|G$%@-+qmdD@q?%ZQYKC8QQKVQ zO{C#SoC4OuMx%C9{JKHFc_b9cqxZaIN_b4!ZwT1jA!FrMZJXsBZ}9V5w$74tP)kw{ z_mxkXEAihRJpxB#F~F&Jmvp5(_BYm7yXo}=6o)fbA52A8CIPA}_Q0a@4&9Ijpu|0b2VODA-^CC35@p;W`F+r^LdPzjHvf|fjNy=G7+CHG2PA> z$SSA9s>+)RdLT2ShRs!+O>BH8vzv}XCK6}4Is7DZ4pUsjK!x!TF0N=>QK|k(nR;zd9M{*UAkO z%Jn~_Yh`&UOwIZo zh22!AN6?y_$)P_?-HlKMPYB0*ufNQ*N8{A&&46ywz-3ZtG0U*ns?V9a(ERk=4t}5L zqe|u79B8#Zb)dSp2YlUaF1!4kbVDpj8v0vnkt8vXXJjjhP?g%=vCJP! zdNA$PQj*KhT#I;XIIt5LdPA08&4?jjv#&F+BHo{dOqBim z3XOu-pOO^hIz7Ema;AZ>j5I*vyE#S}TVCe7Mu;LEMk#c3I?Zq=*oc0ppc^M}EQ2Uc zDXi2M5A5r~Joapigf>pA3iiYcZNM~&j236ua!&+4;ax0b1c`^N>Fh4BV=77qi&%W_ zdI4wL$4ZXEP)+`^7g+x*qjwv}uE~pmj>5SkVeH|z39$ptLtXq&Ow-@=J;XkL-acvj zuB}XV)a;q6C7e>UlI%lzju`eu2@cjT%~VO3`P4Uad!}u3;%zI0V>DZ*kmp@XzXD(I zNOPOkBB!JCTea!WA{`}D+BnE;Obvp&i`@h7F=FsuTp`!N2*wx3RNcM90wac>U)(pl zV~51A6=Hsn5`y*op}oDBLjPH*zV2O}E_qa^TJp3-;SYcTAxH)F9pRU2NN^*Y#Q*@= z@)y;54O5m!Cc%V4Hz-IA`uKl+Q4}6082>TnC|k4kQuFdPMZVAh9@yTe?`QEOYni4L zk#s@t?sbr~fZEg8Iq#7c$%xVtm5a2CO!ajue)tdR0T5B2uIV>p(B%&xk>XQOBE28G zaFCB8xky~XcunAm>zE;dLyBb=t$cL8fm>V#bbMSsztkeGYkR*p7C;REOVVoq0E!a; zLj?c;*$I8`gGIhR%Txc^b=1IU`jf2kd5WEc^?Ez+xIF*S~;#2 z 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 JKY_37{{kQo_ + + Repository Reproducibility Bundle Guard + repo-climate-forecasting / preprint-v2.1.0 + + RELEASE + Components: 7 + High: 0 + Medium: 0 + Low: 0 + Synthetic release packets only. No private data or external services. + \ No newline at end of file diff --git a/repository-reproducibility-bundle-guard/reports/risky-candidate.json b/repository-reproducibility-bundle-guard/reports/risky-candidate.json new file mode 100644 index 00000000..066048f9 --- /dev/null +++ b/repository-reproducibility-bundle-guard/reports/risky-candidate.json @@ -0,0 +1,136 @@ +{ + "repositoryId": "repo-incomplete-export", + "releaseTag": "preprint-v2.2.0", + "commit": "9f8c7d6e5b4a3210", + "decision": "hold", + "summary": { + "componentsReviewed": 5, + "requiredTypesCovered": 4, + "bundleEntries": 2, + "findings": 16, + "high": 11, + "medium": 4, + "low": 1 + }, + "findings": [ + { + "code": "MISSING_REQUIRED_COMPONENT", + "severity": "high", + "sourceId": "notebook", + "message": "notebook component is absent from the release manifest.", + "remediation": "Add the required component or explicitly hold the release until the research packet is complete." + }, + { + "code": "MISSING_REQUIRED_COMPONENT", + "severity": "high", + "sourceId": "results", + "message": "results component is absent from the release manifest.", + "remediation": "Add the required component or explicitly hold the release until the research packet is complete." + }, + { + "code": "MISSING_REQUIRED_COMPONENT", + "severity": "high", + "sourceId": "protocol", + "message": "protocol component is absent from the release manifest.", + "remediation": "Add the required component or explicitly hold the release until the research packet is complete." + }, + { + "code": "DUPLICATE_MANIFEST_PATH", + "severity": "high", + "sourceId": "code/train.py", + "message": "code/train.py appears more than once in the release manifest.", + "remediation": "Keep one canonical manifest row per path so rollback and integrity checks are deterministic." + }, + { + "code": "INVALID_COMPONENT_DIGEST", + "severity": "high", + "sourceId": "manuscript-main", + "message": "manuscript/main.md does not carry a valid SHA-256 digest.", + "remediation": "Record the lowercase SHA-256 digest before tagging the release." + }, + { + "code": "MISSING_DATA_PROVENANCE", + "severity": "medium", + "sourceId": "observations", + "message": "data/observations.parquet lacks provenance references to inputs, instruments, or analysis commits.", + "remediation": "Link the dataset/result to source instruments, upstream datasets, notebooks, or analysis commits." + }, + { + "code": "MISSING_RUNTIME_LOCKFILE", + "severity": "high", + "sourceId": "analysis-code", + "message": "code/train.py lacks lockfile evidence for executable reproducibility.", + "remediation": "Attach package-lock, requirements lock, renv, Manifest.toml, or equivalent runtime lock evidence." + }, + { + "code": "UNPINNED_RUNTIME_IMAGE", + "severity": "medium", + "sourceId": "analysis-code", + "message": "code/train.py runtime image is not digest-pinned.", + "remediation": "Pin the container/runtime image by immutable digest instead of a mutable tag." + }, + { + "code": "MISSING_RUNTIME_LOCKFILE", + "severity": "high", + "sourceId": "duplicate-code", + "message": "code/train.py lacks lockfile evidence for executable reproducibility.", + "remediation": "Attach package-lock, requirements lock, renv, Manifest.toml, or equivalent runtime lock evidence." + }, + { + "code": "UNPINNED_RUNTIME_IMAGE", + "severity": "medium", + "sourceId": "duplicate-code", + "message": "code/train.py runtime image is not digest-pinned.", + "remediation": "Pin the container/runtime image by immutable digest instead of a mutable tag." + }, + { + "code": "UNVERSIONED_COMPONENT", + "severity": "high", + "sourceId": "metadata", + "message": "metadata.json is not marked as version-controlled.", + "remediation": "Commit, tag, or archive the component under repository version control before release." + }, + { + "code": "MISSING_METADATA_EXPORT_TARGETS", + "severity": "low", + "sourceId": "metadata", + "message": "metadata.json does not declare export targets.", + "remediation": "Declare DOI, schema.org, DataCite, or repository export targets for discovery." + }, + { + "code": "INCOMPLETE_RELEASE_METADATA", + "severity": "high", + "sourceId": "metadata", + "message": "Release metadata is missing DOI, schema.org, DataCite, or license evidence.", + "remediation": "Complete persistent identifier, discovery metadata, citation metadata, and license fields before publication." + }, + { + "code": "MISSING_AUTHOR_ATTRIBUTION", + "severity": "medium", + "sourceId": "metadata.authors", + "message": "Release metadata does not include author attribution.", + "remediation": "Attach author identifiers before the repository release is exported or assigned a DOI." + }, + { + "code": "INVALID_EXPORT_BUNDLE", + "severity": "high", + "sourceId": "bundle", + "message": "Release bundle archive path or digest is missing/invalid.", + "remediation": "Generate a release archive with a stable SHA-256 digest before tagging." + }, + { + "code": "BUNDLE_OMITS_MANIFEST_COMPONENTS", + "severity": "high", + "sourceId": "bundle.includes", + "message": "Release bundle omits manifest paths: data/observations.parquet, code/train.py.", + "remediation": "Regenerate the archive so every manifest component is present in the export bundle." + } + ], + "releaseCriteria": [ + "Every required scientific repository component is present in the manifest.", + "Every manifest entry has a stable digest and version-control status.", + "Executable code and notebooks include lockfile evidence and pinned runtimes.", + "Datasets and results link back to provenance inputs.", + "The export bundle includes every manifest path and has its own SHA-256 digest." + ] +} \ No newline at end of file diff --git a/repository-reproducibility-bundle-guard/reports/risky-candidate.md b/repository-reproducibility-bundle-guard/reports/risky-candidate.md new file mode 100644 index 00000000..60ecdd3c --- /dev/null +++ b/repository-reproducibility-bundle-guard/reports/risky-candidate.md @@ -0,0 +1,36 @@ +# Repository Reproducibility Bundle Guard + +Scenario: risky-candidate + +Repository: repo-incomplete-export +Release tag: preprint-v2.2.0 +Decision: HOLD + +Reviewed 5 manifest components and 2 bundle entries. + +## Findings + +- HIGH MISSING_REQUIRED_COMPONENT: notebook component is absent from the release manifest. +- HIGH MISSING_REQUIRED_COMPONENT: results component is absent from the release manifest. +- HIGH MISSING_REQUIRED_COMPONENT: protocol component is absent from the release manifest. +- HIGH DUPLICATE_MANIFEST_PATH: code/train.py appears more than once in the release manifest. +- HIGH INVALID_COMPONENT_DIGEST: manuscript/main.md does not carry a valid SHA-256 digest. +- MEDIUM MISSING_DATA_PROVENANCE: data/observations.parquet lacks provenance references to inputs, instruments, or analysis commits. +- HIGH MISSING_RUNTIME_LOCKFILE: code/train.py lacks lockfile evidence for executable reproducibility. +- MEDIUM UNPINNED_RUNTIME_IMAGE: code/train.py runtime image is not digest-pinned. +- HIGH MISSING_RUNTIME_LOCKFILE: code/train.py lacks lockfile evidence for executable reproducibility. +- MEDIUM UNPINNED_RUNTIME_IMAGE: code/train.py runtime image is not digest-pinned. +- HIGH UNVERSIONED_COMPONENT: metadata.json is not marked as version-controlled. +- LOW MISSING_METADATA_EXPORT_TARGETS: metadata.json does not declare export targets. +- HIGH INCOMPLETE_RELEASE_METADATA: Release metadata is missing DOI, schema.org, DataCite, or license evidence. +- MEDIUM MISSING_AUTHOR_ATTRIBUTION: Release metadata does not include author attribution. +- HIGH INVALID_EXPORT_BUNDLE: Release bundle archive path or digest is missing/invalid. +- HIGH BUNDLE_OMITS_MANIFEST_COMPONENTS: Release bundle omits manifest paths: data/observations.parquet, code/train.py. + +## Release Criteria + +- Every required scientific repository component is present in the manifest. +- Every manifest entry has a stable digest and version-control status. +- Executable code and notebooks include lockfile evidence and pinned runtimes. +- Datasets and results link back to provenance inputs. +- The export bundle includes every manifest path and has its own SHA-256 digest. diff --git a/repository-reproducibility-bundle-guard/reports/risky-candidate.svg b/repository-reproducibility-bundle-guard/reports/risky-candidate.svg new file mode 100644 index 00000000..28b96f95 --- /dev/null +++ b/repository-reproducibility-bundle-guard/reports/risky-candidate.svg @@ -0,0 +1,12 @@ + + + Repository Reproducibility Bundle Guard + repo-incomplete-export / preprint-v2.2.0 + + HOLD + Components: 5 + High: 11 + Medium: 4 + Low: 1 + Synthetic release packets only. No private data or external services. + \ No newline at end of file diff --git a/repository-reproducibility-bundle-guard/requirements-map.md b/repository-reproducibility-bundle-guard/requirements-map.md new file mode 100644 index 00000000..36552554 --- /dev/null +++ b/repository-reproducibility-bundle-guard/requirements-map.md @@ -0,0 +1,14 @@ +# Requirements Map + +Issue #10 asks for project repositories that support structured scientific components, versioning, integrity, collaboration, metadata, reproducibility, and export readiness. + +This slice covers a focused release gate: + +- Repository structure: validates that manuscript, data, code, notebooks, results, protocols, and metadata are all present in the release manifest. +- File and metadata versioning: requires each component to be versioned and carry a stable SHA-256 digest. +- Reproducibility: requires executable code and notebooks to include lockfile evidence and digest-pinned runtime images. +- Provenance: requires datasets and results to reference upstream inputs, instruments, notebooks, or commits. +- Metadata export: requires DOI, schema.org, DataCite, license, author attribution, and metadata export targets. +- Publication/export readiness: requires the release archive to have its own digest and include every manifest path. + +Out of scope by design: branch protection, merge requests, release signatures, Git LFS pointer integrity, restore rehearsals, credential rotation, and review-decision provenance, because those are already covered by separate same-issue slices. diff --git a/repository-reproducibility-bundle-guard/sample-data.js b/repository-reproducibility-bundle-guard/sample-data.js new file mode 100644 index 00000000..adfabf78 --- /dev/null +++ b/repository-reproducibility-bundle-guard/sample-data.js @@ -0,0 +1,171 @@ +const goodDigest = "a".repeat(64); +const secondDigest = "b".repeat(64); +const thirdDigest = "c".repeat(64); +const fourthDigest = "d".repeat(64); +const fifthDigest = "e".repeat(64); +const sixthDigest = "f".repeat(64); +const seventhDigest = "1".repeat(64); +const bundleDigest = "2".repeat(64); +const runtimeDigest = `ghcr.io/scibase/python-research@sha256:${"3".repeat(64)}`; + +const releaseCandidate = { + repositoryId: "repo-climate-forecasting", + releaseTag: "preprint-v2.1.0", + commit: "9f8c7d6e5b4a3210", + metadata: { + doi: "10.5555/scibase.climate.2026.002", + schemaOrg: true, + dataCite: true, + license: "CC-BY-4.0", + authors: ["orcid:0000-0002-1825-0097", "orcid:0000-0003-1415-9265"], + }, + components: [ + { + id: "manuscript-main", + type: "manuscript", + path: "manuscript/main.md", + sha256: goodDigest, + bytes: 18422, + provenanceRefs: ["protocols/forecast-protocol.md"], + exportTargets: ["pdf", "html"], + }, + { + id: "observations", + type: "data", + path: "data/observations.parquet", + sha256: secondDigest, + bytes: 90021, + provenanceRefs: ["instrument:NOAA-GHCN", "commit:9f8c7d6e5b4a3210"], + exportTargets: ["parquet", "csv-preview"], + }, + { + id: "analysis-code", + type: "code", + path: "code/train.py", + sha256: thirdDigest, + bytes: 15420, + runtimeImage: runtimeDigest, + lockfiles: ["code/requirements.lock"], + provenanceRefs: ["data/observations.parquet"], + }, + { + id: "notebook-validation", + type: "notebook", + path: "notebooks/validation.ipynb", + sha256: fourthDigest, + bytes: 74210, + runtimeImage: runtimeDigest, + lockfiles: ["code/requirements.lock"], + provenanceRefs: ["code/train.py"], + }, + { + id: "figure-pack", + type: "results", + path: "results/figures.zip", + sha256: fifthDigest, + bytes: 25001, + provenanceRefs: ["notebooks/validation.ipynb"], + exportTargets: ["png", "svg"], + }, + { + id: "forecast-protocol", + type: "protocol", + path: "protocols/forecast-protocol.md", + sha256: sixthDigest, + bytes: 9360, + provenanceRefs: ["doi:10.5555/scibase.climate.2026.001"], + }, + { + id: "metadata", + type: "metadata", + path: "metadata.json", + sha256: seventhDigest, + bytes: 4200, + exportTargets: ["doi", "schema.org", "datacite"], + }, + ], + bundle: { + archivePath: "exports/repo-climate-forecasting-preprint-v2.1.0.tar.gz", + sha256: bundleDigest, + generatedAt: "2026-06-01T18:00:00Z", + includes: [ + "manuscript/main.md", + "data/observations.parquet", + "code/train.py", + "notebooks/validation.ipynb", + "results/figures.zip", + "protocols/forecast-protocol.md", + "metadata.json", + ], + }, +}; + +const riskyCandidate = { + ...releaseCandidate, + repositoryId: "repo-incomplete-export", + releaseTag: "preprint-v2.2.0", + metadata: { + doi: "", + schemaOrg: false, + dataCite: true, + license: "", + authors: [], + }, + components: [ + { + id: "manuscript-main", + type: "manuscript", + path: "manuscript/main.md", + sha256: "not-a-digest", + bytes: 18422, + provenanceRefs: [], + }, + { + id: "observations", + type: "data", + path: "data/observations.parquet", + sha256: secondDigest, + bytes: 90021, + provenanceRefs: [], + }, + { + id: "analysis-code", + type: "code", + path: "code/train.py", + sha256: thirdDigest, + bytes: 15420, + runtimeImage: "ghcr.io/scibase/python-research:latest", + lockfiles: [], + provenanceRefs: ["data/observations.parquet"], + }, + { + id: "duplicate-code", + type: "code", + path: "code/train.py", + sha256: thirdDigest, + bytes: 15420, + runtimeImage: "ghcr.io/scibase/python-research:latest", + lockfiles: [], + }, + { + id: "metadata", + type: "metadata", + path: "metadata.json", + sha256: seventhDigest, + bytes: 4200, + exportTargets: [], + versioned: false, + }, + ], + bundle: { + archivePath: "exports/repo-incomplete-export.tar.gz", + sha256: "bad-bundle-digest", + generatedAt: "2026-06-01T18:00:00Z", + includes: ["manuscript/main.md", "metadata.json"], + }, +}; + +module.exports = { + releaseCandidate, + riskyCandidate, +}; diff --git a/repository-reproducibility-bundle-guard/test.js b/repository-reproducibility-bundle-guard/test.js new file mode 100644 index 00000000..ca1a03e6 --- /dev/null +++ b/repository-reproducibility-bundle-guard/test.js @@ -0,0 +1,46 @@ +const assert = require("assert"); + +const { assessReproducibilityBundle, normalizeCandidate } = require("./index"); +const { releaseCandidate, riskyCandidate } = require("./sample-data"); + +const clean = assessReproducibilityBundle(releaseCandidate); +assert.strictEqual(clean.decision, "release"); +assert.strictEqual(clean.summary.findings, 0); +assert.strictEqual(clean.summary.requiredTypesCovered, 7); + +const risky = assessReproducibilityBundle(riskyCandidate); +assert.strictEqual(risky.decision, "hold"); +for (const code of [ + "MISSING_REQUIRED_COMPONENT", + "DUPLICATE_MANIFEST_PATH", + "INVALID_COMPONENT_DIGEST", + "UNVERSIONED_COMPONENT", + "MISSING_RUNTIME_LOCKFILE", + "UNPINNED_RUNTIME_IMAGE", + "MISSING_DATA_PROVENANCE", + "MISSING_METADATA_EXPORT_TARGETS", + "INCOMPLETE_RELEASE_METADATA", + "MISSING_AUTHOR_ATTRIBUTION", + "INVALID_EXPORT_BUNDLE", + "BUNDLE_OMITS_MANIFEST_COMPONENTS", +]) { + assert(risky.findings.some((finding) => finding.code === code), `missing ${code}`); +} + +const reviseOnly = assessReproducibilityBundle({ + ...releaseCandidate, + components: releaseCandidate.components.map((component) => + component.id === "analysis-code" + ? { ...component, runtimeImage: "ghcr.io/scibase/python-research:latest" } + : component + ), +}); +assert.strictEqual(reviseOnly.decision, "revise"); +assert(reviseOnly.findings.some((finding) => finding.code === "UNPINNED_RUNTIME_IMAGE")); + +assert.throws( + () => normalizeCandidate({ ...releaseCandidate, repositoryId: "" }), + /repositoryId must be a non-empty string/ +); + +console.log("repository reproducibility bundle guard tests passed");